939 lines
42 KiB
C#
939 lines
42 KiB
C#
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using Autodesk.Revit.UI;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
//using COME4Revit.WinForm;
|
|
using System.Diagnostics;
|
|
using Autodesk.Revit.UI.Selection;
|
|
using System;
|
|
using System.Windows.Forms;
|
|
using KDCS.Utils;
|
|
using View = Autodesk.Revit.DB.View;
|
|
using Autodesk.Revit.DB.Structure;
|
|
using Autodesk.Revit.Creation;
|
|
using KMBIM.Revit.Tools;
|
|
|
|
namespace KMBIM
|
|
{
|
|
public enum EnumPipeRackInstallBase
|
|
{
|
|
Structure, //구조체
|
|
Level //레벨
|
|
}
|
|
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|
public class DrawPipeRack : IExternalCommand
|
|
{
|
|
UIApplication uiapp;
|
|
UIDocument uidoc;
|
|
Autodesk.Revit.DB.Document doc;
|
|
Autodesk.Revit.Creation.Application creApp;
|
|
Autodesk.Revit.Creation.Document creDoc;
|
|
public double m_MarginWidth = 0;
|
|
|
|
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
|
{
|
|
uiapp = commandData.Application;
|
|
uidoc = uiapp.ActiveUIDocument;
|
|
Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
|
|
doc = uidoc.Document;
|
|
creApp = uiapp.Application.Create;
|
|
creDoc = doc.Create;
|
|
View view = doc.ActiveView;
|
|
Level m_setLvlElem = null;
|
|
int RadType = 0;
|
|
PipeInfo pipeInfo1 = new PipeInfo();
|
|
PipeInfo pipeInfo2 = new PipeInfo();
|
|
|
|
try
|
|
{
|
|
//if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
|
|
//파이프 선택
|
|
IList<Reference> pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), "가대 설치할 배관 선택 : ");
|
|
|
|
if (pickrefs.Count == 0)
|
|
{
|
|
MessageBox.Show("선택한 파이프가 없습니다.", "오류");
|
|
return Result.Cancelled;
|
|
}
|
|
|
|
//파이프로 변환
|
|
List<Pipe> PipeLst = new List<Pipe>();
|
|
foreach (Reference refer in pickrefs)
|
|
{
|
|
PipeLst.Add(doc.GetElement(refer) as Pipe);
|
|
}
|
|
|
|
//가장 큰 관경 구하기
|
|
Pipe MaxDiaPipe = getMaxPipe(PipeLst);
|
|
//최소 관경 구하기
|
|
Pipe MinOffsetPipe = getMinOffsetPipe(PipeLst);
|
|
//if(MinOffsetPipe!=null)
|
|
|
|
|
|
//대화상자
|
|
Form_PipeRack dlg = new Form_PipeRack();
|
|
dlg.revit = commandData;
|
|
dlg.MaxDiaPipe = MaxDiaPipe;
|
|
dlg.MinOffPipe = MinOffsetPipe;
|
|
dlg.ShowDialog();
|
|
if (dlg.DialogResult == DialogResult.Cancel) return Result.Cancelled;
|
|
m_MarginWidth = dlg.m_MarginDist;
|
|
|
|
double flr_Height = 0.0;
|
|
double selLvl_Height = 0.0;
|
|
|
|
//가대 설치 기준 (레벨 : T / 구조체 : F)
|
|
string PipeRackInstallBase = Reg.getReg("PipeRackInstallBase");
|
|
bool InstallBase = PipeRackInstallBase.CompareTo(EnumPipeRackInstallBase.Level.ToString()) == 0 ? true : false;
|
|
if (InstallBase)
|
|
{
|
|
//대화상자 선택한 레벨 가져오기
|
|
FilteredElementCollector lvlCollector = new FilteredElementCollector(doc);
|
|
ICollection<Element> lvlCollection = lvlCollector.OfClass(typeof(Level)).ToElements();
|
|
|
|
foreach (Element elem in lvlCollection)
|
|
{
|
|
Level lvl = elem as Level;
|
|
if (lvl.Name == dlg.m_LvlSet)
|
|
m_setLvlElem = lvl;
|
|
}
|
|
|
|
|
|
// 23.06.07(JYH) 바닥 슬라브가 존재 할 경우
|
|
FilteredElementCollector floorcollector = new FilteredElementCollector(doc);
|
|
ICollection<ElementId> flrIds = floorcollector.OfClass(typeof(Floor)).ToElementIds();
|
|
foreach (ElementId flrId in flrIds)
|
|
{
|
|
Floor floor = doc.GetElement(flrId) as Floor;
|
|
|
|
if (floor.LevelId == m_setLvlElem.Id)
|
|
{
|
|
Parameter offsetParam = floor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM);
|
|
double flr_offset = offsetParam.AsDouble();
|
|
flr_Height = flr_offset;
|
|
selLvl_Height = m_setLvlElem.Elevation;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
Element nearestFloor = null;
|
|
double nearestDist = double.MaxValue;
|
|
|
|
foreach (Pipe pp in PipeLst)
|
|
{
|
|
BoundingBoxXYZ pipeBoundingBox = pp.get_BoundingBox(null);
|
|
|
|
FilteredElementCollector collector = new FilteredElementCollector(doc);
|
|
IList<Element> floors = collector.OfCategory(BuiltInCategory.OST_Floors).WhereElementIsNotElementType().ToList();
|
|
|
|
if (floors.Count <= 0)
|
|
{
|
|
MessageBox.Show("가대를 설치 할 구조체 (바닥)이 존재하지 않습니다.", "오류");
|
|
return Result.Cancelled;
|
|
}
|
|
|
|
foreach (Element floor in floors)
|
|
{
|
|
BoundingBoxXYZ floorBoundingBox = floor.get_BoundingBox(null);
|
|
double dist = pipeBoundingBox.Min.Z - floorBoundingBox.Max.Z;
|
|
|
|
if (dist > 0 && dist < nearestDist)
|
|
{
|
|
nearestDist = dist;
|
|
nearestFloor = floor;
|
|
}
|
|
}
|
|
|
|
Parameter offsetParam = nearestFloor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM);
|
|
flr_Height = offsetParam.AsDouble();
|
|
ElementId levelId = nearestFloor.LevelId;
|
|
Level level = doc.GetElement(levelId) as Level;
|
|
m_setLvlElem = level;
|
|
selLvl_Height = level.Elevation;
|
|
|
|
}
|
|
}
|
|
|
|
//볼트 타입
|
|
RadType = dlg.m_Radidx;
|
|
|
|
if (InstallBase)
|
|
{
|
|
foreach (Pipe pp in PipeLst)
|
|
{
|
|
if (m_setLvlElem.Elevation > pp.ReferenceLevel.Elevation + pp.LevelOffset)
|
|
{
|
|
MessageBox.Show("배치 레벨과 파이프 간격이 좁습니다.", "오류");
|
|
return Result.Cancelled;
|
|
}
|
|
//파이프 리스트 중 높이가 좁을 경우 명령어 취소
|
|
if ((dlg.m_LvlCurrent != "Unknown" && dlg.m_LvlCurrent == dlg.m_LvlSet) || dlg.m_LvlCurrent == "Unknown")
|
|
{
|
|
if (pp.LevelOffset < Unit.MMToFeet(200))
|
|
{
|
|
MessageBox.Show("배치 레벨과 파이프 간격이 좁습니다.", "오류");
|
|
return Result.Cancelled;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//가대 심볼 로드되어 있지 않으면 로드
|
|
FamilySymbol fs = LoadFamilys("Chanel_Support_lower.rfa", null);
|
|
|
|
if (fs == null)
|
|
fs = getNameByFamily("Chanel_Support_lower");
|
|
//U볼트 패밀리 로드
|
|
FamilySymbol bolt = LoadFamilys("U_bolt.rfa", null);
|
|
if (bolt == null)
|
|
bolt = getNameByFamily("U_bolt");
|
|
//가이드 슈 패밀리 로드
|
|
FamilySymbol shoe = LoadFamilys("Guide_Shoe.rfa", null);
|
|
if (shoe == null)
|
|
shoe = getNameByFamily("Guide_Shoe");
|
|
|
|
|
|
while (true)
|
|
{
|
|
//가대 위치 지정
|
|
Reference pickref = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), "가대 위치 지정 : ");
|
|
//위치 포인트
|
|
XYZ insertPt = pickref.GlobalPoint;
|
|
|
|
//위치포인트에서 양 쪽 가장 먼 파이프 두개를 찾아 교차점 구하기
|
|
//XYZ SideInterPt1 = null, SideInterPt2 = null;
|
|
List<PipeInfo> pipeInfoLst = new List<PipeInfo>();
|
|
if (PipeLst.Count == 1)
|
|
{
|
|
pipeInfo1.pipe = doc.GetElement(pickref) as Pipe;
|
|
Line line = (pipeInfo1.pipe.Location as LocationCurve).Curve as Line;
|
|
IntersectionResult interRes = line.Project(insertPt);
|
|
pipeInfo1.InterPt = interRes.XYZPoint;
|
|
pipeInfoLst.Add(pipeInfo1);
|
|
}
|
|
else
|
|
{
|
|
pipeInfoLst = getSidePipe(PipeLst, insertPt, ref pipeInfo1, ref pipeInfo2);
|
|
}
|
|
|
|
//Util.Pyosi(doc,SideInterPt1,1);
|
|
//MessageBox.Show("1");
|
|
|
|
//심볼이 로드되지 않으면 실행 X
|
|
if (fs != null)
|
|
{
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("symbol");
|
|
|
|
if (fs.IsActive == false)
|
|
fs.Activate();
|
|
if (bolt.IsActive == false)
|
|
bolt.Activate();
|
|
if (shoe.IsActive == false)
|
|
shoe.Activate();
|
|
|
|
Pipe firstPipe = doc.GetElement(pickrefs.First()) as Pipe;
|
|
XYZ sp = null, ep = null;
|
|
Util.GetStartEndPoint(firstPipe, ref sp, ref ep);
|
|
XYZ PipeVec = (ep - sp).Normalize();
|
|
XYZ RotVec = Util.RotateVector(PipeVec, Util.DTR(90));
|
|
|
|
FamilyInstance family = null;
|
|
FamilyInstance TypeFamily = null;
|
|
List<FamilyInstance> boltFamLst = new List<FamilyInstance>();
|
|
|
|
//파이프 1개 선택 시
|
|
if (pipeInfo2.pipe == null)
|
|
{
|
|
XYZ tmp = new XYZ(0, 0, 0);
|
|
//가대 설치
|
|
//family = doc.Create.NewFamilyInstance(pipeInfo1.InterPt, fs, RotVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
family = doc.Create.NewFamilyInstance(pipeInfo1.InterPt, fs, RotVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
|
|
if (RadType == 0)
|
|
{
|
|
//파이프가 1개일 때 가이드 슈
|
|
TypeFamily = doc.Create.NewFamilyInstance(pipeInfo1.InterPt, shoe, PipeVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
pipeInfoLst.First().family = TypeFamily;
|
|
}
|
|
else if (RadType == 1)
|
|
{
|
|
//파이프가 1개일 때 U볼트
|
|
TypeFamily = doc.Create.NewFamilyInstance(pipeInfo1.InterPt, bolt, PipeVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
pipeInfoLst.First().family = TypeFamily;
|
|
}
|
|
|
|
//Util.Pyosi(doc, pipeInfo1.InterPt, 0);
|
|
}
|
|
else
|
|
{
|
|
//파이프 여러개 선택 시 양 끝 파이프 센터점에 가대 설치
|
|
XYZ centerPt = Util.Polar(pipeInfo1.InterPt, pipeInfo1.InterPt, pipeInfo2.InterPt, pipeInfo1.InterPt.DistanceTo(pipeInfo2.InterPt) / 2.0);
|
|
family = doc.Create.NewFamilyInstance(centerPt, fs, RotVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
//Util.Pyosi(doc, centerPt, 0);
|
|
|
|
//U볼트 가이드 슈 삽입
|
|
foreach (PipeInfo info in pipeInfoLst)
|
|
{
|
|
XYZ locPt = new XYZ(info.InterPt.X, info.InterPt.Y, info.pipe.ReferenceLevel.Elevation + info.pipe.LevelOffset);
|
|
|
|
if (RadType == 0)
|
|
{
|
|
TypeFamily = doc.Create.NewFamilyInstance(locPt, shoe, PipeVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
info.family = TypeFamily;
|
|
doc.Regenerate();
|
|
List<Connector> conLst = Util.GetElementConnectors(TypeFamily);
|
|
Connector shoeCon = conLst.First();
|
|
//Util.Pyosi(doc, pipeInfo1.InterPt, 0);
|
|
doc.Regenerate();
|
|
//가이드 슈 커넥터 위치를 기준으로 파이프 중심으로 이동
|
|
XYZ translation = locPt - shoeCon.Origin;
|
|
ElementTransformUtils.MoveElement(doc, TypeFamily.Id, translation);
|
|
}
|
|
else if (RadType == 1)
|
|
{
|
|
TypeFamily = doc.Create.NewFamilyInstance(locPt, bolt, PipeVec, doc.GetElement(pickref), StructuralType.NonStructural);
|
|
info.family = TypeFamily;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
doc.Regenerate();
|
|
|
|
//패밀리 옵션 설정
|
|
FamilyOption(family, pipeInfoLst, pipeInfo1, pipeInfo2, PipeLst, m_setLvlElem, RadType, flr_Height, selLvl_Height);
|
|
|
|
trans.Commit();
|
|
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}//while end
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//MessageBox.Show("" + e);
|
|
}
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
//패밀리 옵션 설정
|
|
private void FamilyOption(FamilyInstance Rack, List<PipeInfo> pipeInfoLst, PipeInfo pipeInfo1, PipeInfo pipeInfo2, List<Pipe> pipeLst, Level SelectLevel, int BoltType, double flr_Height, double selLvl_Height)
|
|
{
|
|
//////////////////////////////가대 설정////////////////////////////////////
|
|
Definition df = null;
|
|
double MaxPipeOutDia = 0;
|
|
double MinOffPipeOutDia = 0;
|
|
//가장 큰 관경 구하기
|
|
Pipe MaxDiaPipe = getMaxPipe(pipeLst);
|
|
//가장 큰 관경 외경
|
|
Parameter maxOutDiaParam = MaxDiaPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
if (maxOutDiaParam != null)
|
|
MaxPipeOutDia = maxOutDiaParam.AsDouble();
|
|
|
|
//오프셋 값이 가장 높은 값.
|
|
Pipe MinOffsetPipe = getMinOffsetPipe(pipeLst);
|
|
//파이프 단열제 두께
|
|
double MaxinsulThk = 0, MininsulThk = 0;
|
|
if (MinOffsetPipe != null)
|
|
{
|
|
MininsulThk = Util.GetPipeInsulationThickness(doc, MinOffsetPipe);
|
|
Parameter minOutDiaParam = MinOffsetPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
if (minOutDiaParam != null)
|
|
MinOffPipeOutDia = minOutDiaParam.AsDouble();
|
|
}
|
|
else
|
|
MaxinsulThk = Util.GetPipeInsulationThickness(doc, MaxDiaPipe);
|
|
|
|
|
|
//가대 설정
|
|
if (Rack != null)
|
|
{
|
|
//가대 채널 on
|
|
df = GetDefinition(Rack, "First_Chanel");
|
|
if (df != null)
|
|
{
|
|
Parameter paramChanel = Rack.get_Parameter(df);
|
|
if (paramChanel != null)
|
|
paramChanel.Set(1);
|
|
}
|
|
|
|
//가대 폭
|
|
df = GetDefinition(Rack, "Support_Width");
|
|
if (df != null)
|
|
{
|
|
Parameter paramWidth = Rack.get_Parameter(df);
|
|
if (paramWidth != null)
|
|
{
|
|
if (pipeInfo2.pipe == null)
|
|
{
|
|
double sidePipeDia = pipeInfo1.pipe.Diameter;
|
|
//파이프 관경 + 여유분(100)
|
|
paramWidth.Set(sidePipeDia + Unit.MMToFeet(m_MarginWidth));
|
|
}
|
|
else
|
|
{
|
|
double sidePipeDia = pipeInfo1.pipe.Diameter;
|
|
double side2PipeDia = pipeInfo2.pipe.Diameter;
|
|
//양 쪽 사이드 파이프 관경 + 양 사이드 파이프 거리 + 여유분(100)
|
|
paramWidth.Set(sidePipeDia + side2PipeDia + pipeInfo1.InterPt.DistanceTo(pipeInfo2.InterPt) + Unit.MMToFeet(m_MarginWidth));
|
|
}
|
|
}
|
|
}
|
|
|
|
//간격 띄우기 값 구하기
|
|
double m_Offset = 0;
|
|
Parameter paramOffset = Rack.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
|
|
if (paramOffset != null)
|
|
{
|
|
m_Offset = paramOffset.AsDouble();
|
|
|
|
if (MinOffsetPipe == null)
|
|
m_Offset = MaxDiaPipe.LevelOffset;//모든 파이프 offset 같다 = 관경 가장 큰 파이프 offset
|
|
else
|
|
m_Offset = MinOffsetPipe.LevelOffset;//모든 파이프 offset 같지 X = offset 가장 낮은 파이프의 offset
|
|
|
|
//가장 큰 관경만큼 간격띄우기 조정
|
|
if (MinOffsetPipe != null)
|
|
{
|
|
//paramOffset.Set(MinOffsetPipe.LevelOffset - MinOffsetPipe.Diameter / 2.0 - MininsulThk + MinOffsetPipe.ReferenceLevel.Elevation);
|
|
paramOffset.Set(MinOffsetPipe.LevelOffset - MinOffPipeOutDia / 2.0 - MininsulThk + MinOffsetPipe.ReferenceLevel.Elevation);
|
|
}
|
|
else
|
|
{
|
|
//paramOffset.Set(MaxDiaPipe.LevelOffset - MaxDiaPipe.Diameter / 2.0 - MaxinsulThk + MaxDiaPipe.ReferenceLevel.Elevation);
|
|
paramOffset.Set(MaxDiaPipe.LevelOffset - MaxDiaPipe.Diameter / 2.0 - MaxinsulThk + MaxDiaPipe.ReferenceLevel.Elevation);
|
|
}
|
|
}
|
|
|
|
doc.Regenerate();
|
|
|
|
//다리 길이1
|
|
df = GetDefinition(Rack, "Support_Height1");
|
|
if (df != null)
|
|
{
|
|
Parameter paramLeg1 = Rack.get_Parameter(df);
|
|
if (paramLeg1 != null)
|
|
{
|
|
//가대 변경된 offset 값과 같음.
|
|
paramOffset = Rack.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
|
|
//현재 뷰의 레벨만큼 빼서 다리길이 조정(대화상자 만든다면 제거할것)
|
|
//MinOffsetPipe의 offset - MinOffsetPipe 반지름 - 배치레벨높이
|
|
if (MinOffsetPipe != null)
|
|
{
|
|
paramLeg1.Set(m_Offset - MinOffPipeOutDia / 2.0 - MininsulThk + (MinOffsetPipe.ReferenceLevel.Elevation - SelectLevel.Elevation) - flr_Height);
|
|
//paramLeg1.Set(m_Offset - MinOffsetPipe.Diameter / 2.0 - MininsulThk + (MinOffsetPipe.ReferenceLevel.Elevation - SelectLevel.Elevation));
|
|
}
|
|
else
|
|
{
|
|
paramLeg1.Set(m_Offset - MaxPipeOutDia / 2.0 - MaxinsulThk + (MaxDiaPipe.ReferenceLevel.Elevation - SelectLevel.Elevation) - flr_Height);
|
|
//paramLeg1.Set(m_Offset - MaxDiaPipe.Diameter / 2.0 - MaxinsulThk + (MaxDiaPipe.ReferenceLevel.Elevation - SelectLevel.Elevation));
|
|
}
|
|
}
|
|
}
|
|
|
|
//doc.Regenerate();
|
|
|
|
//다리 길이2
|
|
df = GetDefinition(Rack, "Support_Height2");
|
|
if (df != null)
|
|
{
|
|
Parameter paramLeg2 = Rack.get_Parameter(df);
|
|
if (paramLeg2 != null)
|
|
{
|
|
//현재 뷰의 레벨만큼 빼서 다리길이 조정(대화상자 만든다면 제거할것)
|
|
//MinOffsetPipe의 offset - MinOffsetPipe 반지름 - 배치레벨높이
|
|
if (MinOffsetPipe != null)
|
|
{
|
|
paramLeg2.Set(m_Offset - MinOffPipeOutDia / 2.0 - MininsulThk + (MinOffsetPipe.ReferenceLevel.Elevation - SelectLevel.Elevation) - flr_Height);
|
|
//paramLeg2.Set(m_Offset - MinOffsetPipe.Diameter / 2.0 - MininsulThk + (MinOffsetPipe.ReferenceLevel.Elevation - SelectLevel.Elevation));
|
|
}
|
|
else
|
|
{
|
|
paramLeg2.Set(m_Offset - MaxPipeOutDia / 2.0 - MaxinsulThk + (MaxDiaPipe.ReferenceLevel.Elevation - SelectLevel.Elevation) - flr_Height);
|
|
//paramLeg2.Set(m_Offset - MaxDiaPipe.Diameter / 2.0 - MaxinsulThk + (MaxDiaPipe.ReferenceLevel.Elevation - SelectLevel.Elevation));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
double m_CoverThk = 0, m_plateHgt = 0, m_plateThk = 0;
|
|
|
|
//////////////////////////////U볼트 가이드슈 설정////////////////////////////////////
|
|
foreach (PipeInfo info in pipeInfoLst)
|
|
{
|
|
//파이프 단열제 두께
|
|
double insulThk = Util.GetPipeInsulationThickness(doc, info.pipe);
|
|
//파이프 외경
|
|
Parameter param = info.pipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
double m_CurPipeOutDia = 0;
|
|
if (param != null)
|
|
m_CurPipeOutDia = param.AsDouble();
|
|
|
|
//가이드 슈
|
|
if (BoltType == 0)//가이드 슈
|
|
{
|
|
if (info.family != null)
|
|
{
|
|
//관경(외경) 변경
|
|
df = GetDefinition(info.family, "GuideShoeCoverInRad");
|
|
if (df != null)
|
|
{
|
|
Parameter paramSteelDia = info.family.get_Parameter(df);
|
|
|
|
if (paramSteelDia != null)
|
|
paramSteelDia.Set(m_CurPipeOutDia / 2.0 + insulThk);
|
|
//paramSteelDia.Set(info.pipe.Diameter / 2.0 + insulThk);
|
|
}
|
|
|
|
//커넥터 관경 변경
|
|
df = GetDefinition(info.family, "ConRad");
|
|
if (df != null)
|
|
{
|
|
Parameter paramConRad = info.family.get_Parameter(df);
|
|
if (paramConRad != null)
|
|
paramConRad.Set(m_CurPipeOutDia / 2.0 + insulThk);
|
|
//paramConRad.Set(info.pipe.Diameter / 2.0 + insulThk);
|
|
}
|
|
|
|
|
|
//슈 폭 변경
|
|
df = GetDefinition(info.family, "HalfGuideShoeCoverWidth");
|
|
if (df != null)
|
|
{
|
|
Parameter paramSteelHalfWidth = info.family.get_Parameter(df);
|
|
if (paramSteelHalfWidth != null)
|
|
paramSteelHalfWidth.Set(Unit.MMToFeet(25));
|
|
}
|
|
|
|
df = GetDefinition(info.family, "GuideShoeCoverGap");
|
|
if (df != null)
|
|
{
|
|
Parameter paramCoverGap = info.family.get_Parameter(df);
|
|
if (paramCoverGap != null)
|
|
paramCoverGap.Set(Unit.MMToFeet(3));
|
|
}
|
|
|
|
//가대 높이 재설정
|
|
//가이드 슈 두께
|
|
df = GetDefinition(info.family, "GuideShoeCoverThk");
|
|
if (df != null)
|
|
{
|
|
Parameter paramCoverThk = info.family.get_Parameter(df);
|
|
if (paramCoverThk != null)
|
|
{
|
|
paramCoverThk.Set(Unit.MMToFeet(5));//default value = 5
|
|
}
|
|
}
|
|
|
|
doc.Regenerate();
|
|
df = GetDefinition(info.family, "GuideShoeCoverThk");
|
|
if (df != null)
|
|
{
|
|
Parameter paramCoverThk = info.family.get_Parameter(df);
|
|
if (paramCoverThk != null)
|
|
m_CoverThk = paramCoverThk.AsDouble();
|
|
}
|
|
|
|
//판 두께
|
|
df = GetDefinition(info.family, "SupportThk");
|
|
if (df != null)
|
|
{
|
|
Parameter paramPlateThk = info.family.get_Parameter(df);
|
|
if (paramPlateThk != null)
|
|
m_plateThk = paramPlateThk.AsDouble();
|
|
}
|
|
|
|
//판 높이
|
|
df = GetDefinition(info.family, "SupportHeight");
|
|
if (df != null)
|
|
{
|
|
Parameter paramPlateHgt = info.family.get_Parameter(df);
|
|
if (paramPlateHgt != null)
|
|
{
|
|
m_plateHgt = paramPlateHgt.AsDouble();
|
|
if (MinOffsetPipe != null)
|
|
{
|
|
//판높이 + (MinOffsetPipe 반지름 - 현재 파이프 반지름) + (현재 파이프offset - MinOffsetPipe의offset)
|
|
paramPlateHgt.Set(m_plateHgt + ((MinOffPipeOutDia / 2.0 + MininsulThk) - (m_CurPipeOutDia / 2.0 + insulThk))
|
|
+ (info.pipe.LevelOffset - MinOffsetPipe.LevelOffset));
|
|
//paramPlateHgt.Set(m_plateHgt + ((MinOffsetPipe.Diameter / 2.0 + MininsulThk) - (info.pipe.Diameter / 2.0 + insulThk))
|
|
//+ (info.pipe.LevelOffset - MinOffsetPipe.LevelOffset));
|
|
}
|
|
else
|
|
{
|
|
//판높이 +(MaxDiaPipe반지름 - 현재파이프 반지름)
|
|
paramPlateHgt.Set(m_plateHgt + ((MaxPipeOutDia / 2.0 + MaxinsulThk) - (m_CurPipeOutDia / 2.0 + insulThk)));
|
|
//paramPlateHgt.Set(m_plateHgt + ((MaxDiaPipe.Diameter / 2.0 + MaxinsulThk) - (info.pipe.Diameter / 2.0 + insulThk)));
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (BoltType == 1)//U볼트
|
|
{
|
|
|
|
//U볼트 패밀리 설정
|
|
if (info.family != null)
|
|
{
|
|
//간격 띄우기 값 구하기
|
|
double m_Offset = 0;
|
|
Parameter paramOffset = info.family.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
|
|
if (paramOffset != null)
|
|
{
|
|
m_Offset = paramOffset.AsDouble();
|
|
//가장 큰 관경만큼 간격띄우기 조정
|
|
if (MinOffsetPipe != null)
|
|
paramOffset.Set(m_Offset - MinOffPipeOutDia / 2.0 - MininsulThk - (info.pipe.LevelOffset - MinOffsetPipe.LevelOffset));
|
|
else
|
|
paramOffset.Set(m_Offset - MaxPipeOutDia / 2.0 - MaxinsulThk);
|
|
}
|
|
|
|
//관경 변경
|
|
df = GetDefinition(info.family, "Diameter");
|
|
if (df != null)
|
|
{
|
|
Parameter paramDia = info.family.get_Parameter(df);
|
|
if (paramDia != null)
|
|
{
|
|
paramDia.Set(info.pipe.Diameter + insulThk * 2);
|
|
}
|
|
|
|
}
|
|
|
|
//외경 변경
|
|
df = GetDefinition(info.family, "OutDiameter");
|
|
if (df != null)
|
|
{
|
|
Parameter paramOutDia = info.family.get_Parameter(df);
|
|
if (paramOutDia != null)
|
|
{
|
|
Parameter p_outDia = info.pipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
if (MinOffsetPipe != null)
|
|
paramOutDia.Set(p_outDia.AsDouble() + MininsulThk * 2);
|
|
else
|
|
paramOutDia.Set(p_outDia.AsDouble() + MaxinsulThk * 2);
|
|
}
|
|
}
|
|
|
|
double boltDia = 0;
|
|
double mm_PipeDia = Unit.FeetToMM(info.pipe.Diameter + insulThk * 2);
|
|
if (mm_PipeDia >= 15 && mm_PipeDia <= 50)
|
|
boltDia = Unit.MMToFeet(10);
|
|
else if (mm_PipeDia >= 65 && mm_PipeDia <= 90)
|
|
boltDia = Unit.MMToFeet(12);
|
|
else if (mm_PipeDia > 90 && mm_PipeDia <= 175)
|
|
boltDia = Unit.MMToFeet(16);
|
|
else if (mm_PipeDia > 175 && mm_PipeDia <= 250)
|
|
boltDia = Unit.MMToFeet(20);
|
|
else if (mm_PipeDia > 250 && mm_PipeDia <= 400)
|
|
boltDia = Unit.MMToFeet(24);
|
|
else if (mm_PipeDia > 400 && mm_PipeDia <= 500)
|
|
boltDia = Unit.MMToFeet(30);
|
|
else if (mm_PipeDia > 500)
|
|
boltDia = Unit.MMToFeet(32);
|
|
else
|
|
boltDia = Unit.MMToFeet(8);
|
|
|
|
|
|
df = GetDefinition(info.family, "Bolt_Diameter");
|
|
if (df != null)
|
|
{
|
|
Parameter paramBoltDia = info.family.get_Parameter(df);
|
|
if (paramBoltDia != null)
|
|
paramBoltDia.Set(boltDia);
|
|
}
|
|
|
|
//높이 지정
|
|
df = GetDefinition(info.family, "Support_Height");
|
|
if (df != null)
|
|
{
|
|
Parameter paramSupportHgt = info.family.get_Parameter(df);
|
|
if (paramSupportHgt != null)
|
|
{
|
|
if (MinOffsetPipe != null)
|
|
{
|
|
paramSupportHgt.Set(MinOffPipeOutDia / 2.0 + MininsulThk + (info.pipe.LevelOffset - MinOffsetPipe.LevelOffset));
|
|
}
|
|
else
|
|
paramSupportHgt.Set(MaxPipeOutDia / 2.0 + MaxinsulThk);
|
|
}
|
|
}
|
|
|
|
doc.Regenerate();
|
|
}
|
|
}
|
|
}
|
|
//
|
|
//가이드 슈 일 경우 가대 높이, 다리길이 재조정
|
|
if (BoltType == 0)
|
|
{
|
|
doc.Regenerate();
|
|
//가대간격 띄우기 값 구하기
|
|
Parameter paramOffset = Rack.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
|
|
double m_Offset = 0;
|
|
if (paramOffset != null)
|
|
{
|
|
m_Offset = paramOffset.AsDouble();
|
|
//가장 큰 관경만큼 간격띄우기 조정
|
|
paramOffset.Set(m_Offset - (m_CoverThk + m_plateThk + m_plateHgt));
|
|
}
|
|
|
|
df = GetDefinition(Rack, "Support_Height1");
|
|
if (df != null)
|
|
{
|
|
Parameter paramLeg1 = Rack.get_Parameter(df);
|
|
if (paramLeg1 != null)
|
|
{
|
|
double supLength = paramLeg1.AsDouble();
|
|
paramLeg1.Set(supLength - (m_CoverThk + m_plateThk + m_plateHgt));
|
|
}
|
|
}
|
|
|
|
df = GetDefinition(Rack, "Support_Height2");
|
|
if (df != null)
|
|
{
|
|
Parameter paramLeg2 = Rack.get_Parameter(df);
|
|
if (paramLeg2 != null)
|
|
{
|
|
double supLength = paramLeg2.AsDouble();
|
|
paramLeg2.Set(supLength - (m_CoverThk + m_plateThk + m_plateHgt));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 관경이 가장 큰 파이프 구하기
|
|
/// </summary>
|
|
/// <param name="pipeLst"></param> 파이프 리스트
|
|
/// <returns></returns>
|
|
private Pipe getMaxPipe(List<Pipe> pipeLst)
|
|
{
|
|
double MaxDia = 0;
|
|
Pipe MaxPipe = null;
|
|
|
|
foreach (Pipe pp in pipeLst)
|
|
{
|
|
double m_PipeDia = pp.Diameter;
|
|
//단열재 두께
|
|
double insulThk = Util.GetPipeInsulationThickness(doc, pp);
|
|
|
|
if (MaxDia < m_PipeDia + insulThk)
|
|
{
|
|
MaxDia = m_PipeDia + (insulThk * 2);
|
|
MaxPipe = pp;
|
|
}
|
|
}
|
|
|
|
|
|
return MaxPipe;
|
|
}
|
|
|
|
private Pipe getMinOffsetPipe(List<Pipe> pipeLst)
|
|
{
|
|
double MinOffset = double.MaxValue;
|
|
Pipe MinOffsetPipe = null;
|
|
|
|
bool b_other = false;
|
|
//파이프 간격띄우기 값이 다 같으면 null 리턴
|
|
foreach (Pipe pp in pipeLst)
|
|
{
|
|
if (pipeLst.First().LevelOffset != pp.LevelOffset)
|
|
{
|
|
b_other = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//파이프 간격띄우기 값이 다른게 있다면 실행
|
|
if (b_other)
|
|
{
|
|
foreach (Pipe pp in pipeLst)
|
|
{
|
|
double pipeOffset = pp.LevelOffset;
|
|
|
|
|
|
if (MinOffset > pipeOffset)
|
|
{
|
|
MinOffset = pipeOffset;
|
|
MinOffsetPipe = pp;
|
|
}
|
|
}
|
|
}
|
|
|
|
return MinOffsetPipe;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 기준점에서 가장 먼 파이프 구하기
|
|
/// </summary>
|
|
/// <param name="pipeList"></param> 파이프 리스트
|
|
/// <param name="DirPt"></param> 기준점
|
|
/// <param name="SideInterPt"></param> 기준점과 파이프 교차점
|
|
/// <returns></returns>
|
|
private List<PipeInfo> getSidePipe(List<Pipe> pipeList, XYZ DirPt, ref PipeInfo sideInfo1, ref PipeInfo sideInfo2)
|
|
{
|
|
|
|
double minDist = double.MaxValue;
|
|
double maxDist = 0;
|
|
|
|
List<PipeInfo> PipeInfoLst = new List<PipeInfo>();
|
|
foreach (Pipe pipe in pipeList)
|
|
{
|
|
Line line = (pipe.Location as LocationCurve).Curve as Line;
|
|
IntersectionResult interRes = line.Project(DirPt);
|
|
XYZ interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, 0);
|
|
|
|
PipeInfo info = new PipeInfo();
|
|
info.pipe = pipe;
|
|
info.InterPt = interPt;
|
|
PipeInfoLst.Add(info);
|
|
}
|
|
|
|
XYZ vec = (PipeInfoLst.First().InterPt - PipeInfoLst.Last().InterPt).Normalize();
|
|
XYZ virtualPt = Util.Polar(PipeInfoLst.First().InterPt, vec, Unit.MMToFeet(10000));
|
|
|
|
foreach (PipeInfo pipeInfo in PipeInfoLst)
|
|
{
|
|
if (maxDist < virtualPt.DistanceTo(pipeInfo.InterPt))
|
|
{
|
|
sideInfo1 = pipeInfo;
|
|
maxDist = virtualPt.DistanceTo(pipeInfo.InterPt);
|
|
}
|
|
|
|
if (minDist > virtualPt.DistanceTo(pipeInfo.InterPt))
|
|
{
|
|
sideInfo2 = pipeInfo;
|
|
minDist = virtualPt.DistanceTo(pipeInfo.InterPt);
|
|
}
|
|
}
|
|
//Util.Pyosi(doc, sideInfo1.InterPt, 1);
|
|
//MessageBox.Show("1");
|
|
//Util.Pyosi(doc, sideInfo2.InterPt, 1);
|
|
//MessageBox.Show("2");
|
|
return PipeInfoLst;
|
|
}
|
|
|
|
// 패밀리 존재 여부 검토
|
|
private FamilySymbol getNameByFamily(string name)
|
|
{
|
|
|
|
List<FamilyInstanceCreationData> fiCreationDatas = new List<FamilyInstanceCreationData>();
|
|
//Try to get a FamilySymbol
|
|
FilteredElementCollector collector = new FilteredElementCollector(doc);
|
|
ICollection<Element> collection = collector.OfClass(typeof(FamilySymbol)).ToElements();
|
|
FamilySymbol Symbol;
|
|
FamilySymbol target = null;
|
|
|
|
foreach (Element e in collection)
|
|
{
|
|
|
|
Symbol = e as FamilySymbol;
|
|
|
|
|
|
|
|
if (null != Symbol.Category)
|
|
{
|
|
if (name == Symbol.Family.Name)
|
|
{
|
|
// MessageBox.Show(Symbol.Family.Name);
|
|
target = Symbol;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
private FamilySymbol LoadFamilys(string famroot, string famname)
|
|
{
|
|
string versionNumber = doc.Application.VersionNumber.ToString();
|
|
//string Tmp = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
|
//Tmp = Tmp.Replace("\\KMBIM2019.dll", "");
|
|
string Tmp = Util.GetKMBIMLibraryFolder("Libraries\\PipeRack");
|
|
// get the active view's level for beam creation
|
|
Level level = doc.GetElement(doc.ActiveView.LevelId) as Level;
|
|
// load a family symbol from file
|
|
FamilySymbol gotSymbol = null;
|
|
String fileName = Tmp + "\\" + versionNumber + "\\" + famroot;
|
|
// 아래의 이름은 패밀리 고유의 이름이다. 패밀리 작업할때 입력하게 되어있다.
|
|
String name = famname;
|
|
|
|
// 패밀리를 로드한다.
|
|
Family fam = null;
|
|
|
|
//m_document.Document.LoadFamilySymbol(fileName, "", out gotSymbol);
|
|
|
|
bool sw = false;
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("LoadFamily");
|
|
sw = doc.LoadFamily(fileName, out fam);
|
|
trans.Commit();
|
|
}
|
|
|
|
if (sw == true)
|
|
{
|
|
|
|
ISet<ElementId> fam_ids = fam.GetFamilySymbolIds();
|
|
List<string> fam_sym_names = new List<string>();
|
|
|
|
if (fam_ids.Count() == 0) return null;
|
|
gotSymbol = (FamilySymbol)doc.GetElement(fam_ids.ElementAt(0));
|
|
|
|
}
|
|
return gotSymbol;
|
|
}
|
|
|
|
static Definition GetDefinition(Element elem, string parameter_name)
|
|
{
|
|
IList<Parameter> ps = elem.GetParameters(parameter_name);
|
|
|
|
int n = ps.Count;
|
|
|
|
Debug.Assert(1 >= n, "expected maximum one shared parameters" + "named " + parameter_name);
|
|
|
|
Definition d = (0 == n) ? null
|
|
: ps[0].Definition;
|
|
|
|
return d;
|
|
}
|
|
|
|
public class PipeSelectionFilter : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category == null) return false;
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|