486 lines
20 KiB
C#
486 lines
20 KiB
C#
using System;
|
|
using Autodesk.Revit.UI;
|
|
using Autodesk.Revit.DB;
|
|
using System.Collections.Generic;
|
|
using System.Windows.Forms;
|
|
using System.Linq;
|
|
using Autodesk.Revit.UI.Selection;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using KDCS.Utils;
|
|
using Autodesk.Revit.DB.Structure;
|
|
using KMBIM.Revit.Tools.Cmd.SprinklerConnect;
|
|
|
|
|
|
namespace KMBIM
|
|
{
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|
class Sprinkler_Downward_Auto : IExternalCommand
|
|
{
|
|
UIApplication uiapp;
|
|
UIDocument uidoc;
|
|
Autodesk.Revit.DB.Document doc;
|
|
Autodesk.Revit.Creation.Application creApp;
|
|
Autodesk.Revit.Creation.Document creDoc;
|
|
Autodesk.Revit.UI.ExternalCommandData m_commandData;
|
|
double m_MainHgt = 0, m_BranchHgt = 0, m_HeadOffset = 0, m_ConnectDist = 0, m_CapDist = 0;
|
|
List<ObjSprinKler> lst_objSprinkler = new List<ObjSprinKler>();
|
|
ObjComparer OC = new ObjComparer();
|
|
ObjOrthoComparer OrthoC = new ObjOrthoComparer();
|
|
XYZ mainSp = null, mainEp = null;
|
|
SprinKler_Function Spkr_Func = new SprinKler_Function();
|
|
//이격 방향
|
|
XYZ SeparationVec = null;
|
|
|
|
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
|
{
|
|
m_commandData = commandData;
|
|
uiapp = commandData.Application;
|
|
uidoc = uiapp.ActiveUIDocument;
|
|
doc = uidoc.Document;
|
|
creApp = uiapp.Application.Create;
|
|
creDoc = doc.Create;
|
|
|
|
|
|
List<ElementId> m_SpklrList = new List<ElementId>();
|
|
List<List<ObjSprinKler>> m_TotalObjLst = new List<List<ObjSprinKler>>();
|
|
List<List<ObjSprinKler>> Left_TotalObjLst = new List<List<ObjSprinKler>>();
|
|
List<List<ObjSprinKler>> Right_TotalObjLst = new List<List<ObjSprinKler>>();
|
|
List<double> m_SpklrHgtLst = new List<double>();
|
|
|
|
try
|
|
{
|
|
Reference pickref = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionMainPipe(), "교차배관 선택 : ");
|
|
if (pickref == null) return Result.Cancelled;
|
|
|
|
IList<Reference> pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new HeaderFilter(), "배관에 연결할 스프링클러 범위 지정 : ");
|
|
if (pickrefs == null) return Result.Cancelled;
|
|
|
|
ElementId id = pickref.ElementId;
|
|
Element elem1 = doc.GetElement(id) as Element;
|
|
|
|
foreach (Reference refer in pickrefs)
|
|
{
|
|
ElementId id2 = refer.ElementId;
|
|
Element elem2 = doc.GetElement(id2);
|
|
m_SpklrList.Add(id2);
|
|
}
|
|
|
|
Line pipeline = null;//메인 배관 선형
|
|
//메인 파이프 간격띄우기 구하기
|
|
if (elem1 is Pipe)
|
|
{
|
|
Pipe MainPipe = elem1 as Pipe;
|
|
pipeline = (MainPipe.Location as LocationCurve).Curve as Line;
|
|
m_MainHgt = pipeline.GetEndPoint(0).Z;
|
|
mainSp = pipeline.GetEndPoint(0);
|
|
mainEp = pipeline.GetEndPoint(1);
|
|
//SprinKler_Function 변수값 넘겨주기
|
|
Spkr_Func.doc = uidoc.Document;
|
|
Spkr_Func.creDoc = doc.Create;
|
|
Spkr_Func.uiapp = commandData.Application;
|
|
Spkr_Func.MainPipeTypeId = MainPipe.PipeType.Id;
|
|
Spkr_Func.MainSystemTypeId = MainPipe.MEPSystem.GetTypeId();
|
|
Spkr_Func.MainLevelId = MainPipe.ReferenceLevel.Id;
|
|
|
|
}
|
|
|
|
//기준 헤드 지정
|
|
Reference pickDirRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new HeaderFilter(), "기준 스프링클러 헤드 선택 : ");
|
|
if (pickDirRef == null) return Result.Cancelled;
|
|
|
|
Element pickDirElem = doc.GetElement(pickDirRef.ElementId);
|
|
|
|
//이격 거리 방향 지정
|
|
XYZ SeparatePt = commandData.Application.ActiveUIDocument.Selection.PickPoint("가지배관 방향 지정 : ");
|
|
if (SeparatePt == null) return Result.Cancelled;
|
|
|
|
List<Connector> DirHeadCons = Util.GetElementConnectors(pickDirElem);
|
|
IntersectionResult interRes = pipeline.Project(DirHeadCons.First().Origin);
|
|
XYZ interZ0 = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, 0);
|
|
XYZ HeadZ0 = new XYZ(DirHeadCons.First().Origin.X, DirHeadCons.First().Origin.Y, 0);
|
|
XYZ SeparatePtZ0 = new XYZ(SeparatePt.X, SeparatePt.Y, 0);
|
|
|
|
SeparationVec = (interZ0 - HeadZ0).Normalize();
|
|
bool isRight = Util.isRightPoint(SeparatePtZ0, HeadZ0, interZ0);
|
|
if (isRight == true)
|
|
SeparationVec = Util.RotateVector(SeparationVec, Util.DTR(-90.0));
|
|
else
|
|
SeparationVec = Util.RotateVector(SeparationVec, Util.DTR(90.0));
|
|
|
|
|
|
//대화상자 기본값 설정
|
|
Form_Downward dlg = new Form_Downward();
|
|
dlg.MainHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3);
|
|
dlg.BranchHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3) + 300;
|
|
dlg.HeaderOffset = 150;
|
|
dlg.ConnectDist = 150;
|
|
dlg.CapDist = 100;
|
|
dlg.ShowDialog();
|
|
if (dlg.DialogResult == DialogResult.Cancel) return Result.Succeeded;
|
|
//대화상자 값 가져오기
|
|
m_MainHgt = dlg.MainHeight;
|
|
m_BranchHgt = dlg.BranchHeight;
|
|
m_HeadOffset = dlg.HeaderOffset;
|
|
m_ConnectDist = dlg.ConnectDist;
|
|
m_CapDist = dlg.CapDist;
|
|
|
|
|
|
//헤드 값 지정
|
|
foreach (ElementId elemid in m_SpklrList)
|
|
{
|
|
FamilyInstance family = (doc.GetElement(elemid)) as FamilyInstance;
|
|
ConnectorSet conSet = family.MEPModel.ConnectorManager.Connectors;
|
|
foreach (Connector con in conSet)
|
|
{
|
|
interRes = pipeline.Project(con.Origin);
|
|
XYZ interpt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, con.Origin.Z);
|
|
ObjSprinKler objSprinKler = new ObjSprinKler();
|
|
objSprinKler.HeadCon = con;
|
|
objSprinKler.m_Headpt = con.Origin;
|
|
objSprinKler.m_InterPt = interpt;
|
|
objSprinKler.m_SpID = con.Owner.Id;
|
|
objSprinKler.m_Ep2InterDst = interRes.XYZPoint.DistanceTo(pipeline.GetEndPoint(1));
|
|
|
|
|
|
|
|
XYZ SepaPt = Util.Polar(con.Origin, SeparationVec, Unit.MMToFeet(m_ConnectDist));
|
|
|
|
//이격점에서 메인 교차wja
|
|
interRes = pipeline.Project(SepaPt);
|
|
interpt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, SepaPt.Z);
|
|
//이격점, 이격점에 따른 교차점 저장
|
|
objSprinKler.m_InterPt = interpt;
|
|
objSprinKler.SeparateionPt = SepaPt;
|
|
|
|
|
|
//헤드 정보 리스트에 담기
|
|
lst_objSprinkler.Add(objSprinKler);
|
|
m_SpklrHgtLst.Add(con.Origin.Z);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//헤드 수직점에 따른 헤드 값 정렬
|
|
lst_objSprinkler.Sort(OC);
|
|
|
|
bool loop = true;
|
|
//헤드를 거리별로 그룹 나눠서 리스트에 저장하기.
|
|
while (loop)
|
|
{
|
|
if (lst_objSprinkler.Count <= 0) break;
|
|
|
|
List<ObjSprinKler> Group = Spkr_Func.DivideObjSprinKlerData(lst_objSprinkler);
|
|
|
|
//추출 그룹 정렬
|
|
Group.Sort(OrthoC);
|
|
List<int> ContainLst = new List<int>();
|
|
|
|
foreach (ObjSprinKler obj in Group)
|
|
{
|
|
int idx = lst_objSprinkler.IndexOf(obj);
|
|
lst_objSprinkler.RemoveAt(idx);
|
|
}
|
|
//나눈 그룹 리스트에 담기.
|
|
if (Group.Count > 0)
|
|
m_TotalObjLst.Add(Group);
|
|
}//while end
|
|
|
|
//총 리스트에서 헤드가 1개일 때 그 헤드 리스트 앞 뒤 중 가까운쪽에 넣고 삭제
|
|
m_TotalObjLst = Spkr_Func.RemoveSingleObjLst(m_TotalObjLst);
|
|
|
|
//처음 관경25는 헤드쪽때문에 기입
|
|
List<double> headLst = new List<double>();
|
|
headLst.Add(25); headLst.Add(25); headLst.Add(25); headLst.Add(32); headLst.Add(40); headLst.Add(40);
|
|
headLst.Add(50); headLst.Add(50); headLst.Add(50); headLst.Add(50); headLst.Add(50); headLst.Add(65);
|
|
headLst.Add(65); headLst.Add(65); headLst.Add(65); headLst.Add(65); headLst.Add(65); headLst.Add(65);
|
|
|
|
List<Pipe> TeeBranchPipeLst = new List<Pipe>();
|
|
using (Transaction trans1 = new Transaction(doc))
|
|
{
|
|
trans1.Start("cre");
|
|
|
|
//총 리스트를 메인관 기준 왼쪽 오른쪽 분류
|
|
foreach (List<ObjSprinKler> lst_obj in m_TotalObjLst)
|
|
{
|
|
List<ObjSprinKler> lst_LeftObj = new List<ObjSprinKler>();
|
|
List<ObjSprinKler> lst_RightObj = new List<ObjSprinKler>();
|
|
|
|
foreach (ObjSprinKler obj in lst_obj)
|
|
{
|
|
if (Util.isRightPoint(obj.m_Headpt, mainEp, mainSp))
|
|
lst_RightObj.Add(obj);
|
|
else
|
|
lst_LeftObj.Add(obj);
|
|
}
|
|
|
|
List<Pipe> pipeLst = ProcessingSpkr(lst_LeftObj, lst_RightObj, elem1, headLst);
|
|
|
|
TeeBranchPipeLst.AddRange(pipeLst);
|
|
}
|
|
|
|
ElementId MainPipeID = elem1.Id;
|
|
|
|
//메인관에 T연결
|
|
foreach (Pipe pp in TeeBranchPipeLst)
|
|
{
|
|
Connector pipeSpCon = null, pipeEpCon = null;
|
|
bool b_Cons = Util.GetStartEndConnector(pp, ref pipeSpCon, ref pipeEpCon);
|
|
|
|
if (b_Cons == false) continue;
|
|
|
|
|
|
|
|
Line MainLine = ((doc.GetElement(MainPipeID) as Pipe).Location as LocationCurve).Curve as Line;
|
|
XYZ DivPt = Util.GetPointOnLine(MainLine, pipeEpCon.Origin);
|
|
|
|
ElementId divID = PlumbingUtils.BreakCurve(doc, MainPipeID, DivPt);
|
|
|
|
if (divID == null) continue;
|
|
|
|
Connector MainCon1 = null, MainCon2 = null;
|
|
List<Connector> MainCon1Lst = Util.GetElementConnectors(doc.GetElement(divID));
|
|
List<Connector> MainCon2Lst = Util.GetElementConnectors(doc.GetElement(MainPipeID));
|
|
|
|
foreach (Connector con1 in MainCon1Lst)
|
|
{
|
|
foreach (Connector con2 in MainCon2Lst)
|
|
{
|
|
if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
|
|
{
|
|
MainCon1 = con1;
|
|
MainCon2 = con2;
|
|
}
|
|
}
|
|
}
|
|
Util.CreateTee(creDoc, MainCon1, MainCon2, pipeEpCon);
|
|
MainPipeID = divID;
|
|
|
|
}
|
|
trans1.Commit();
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//MessageBox.Show("" + e);
|
|
}
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
|
|
public List<Pipe> ProcessingSpkr(List<ObjSprinKler> RangeLeftLst, List<ObjSprinKler> RangeRightLst, Element MainElem, List<double> HeadDiaLst)
|
|
{
|
|
ObjSprinKler obj1 = null, obj2 = null;
|
|
List<XYZ> m_LeftPtLst = new List<XYZ>();
|
|
List<XYZ> m_RightPtLst = new List<XYZ>();
|
|
List<ModelCurve> m_LCurveLst = new List<ModelCurve>();
|
|
List<ModelCurve> m_RCurveLst = new List<ModelCurve>();
|
|
List<Pipe> newPipes = new List<Pipe>();
|
|
List<Pipe> TeeBranchPipeLst = new List<Pipe>();
|
|
List<ObjSprinKler> ExceptSpkrLst = new List<ObjSprinKler>();
|
|
|
|
Element LeftLastElem = null;
|
|
Element RightLastElem = null;
|
|
|
|
bool b_leftLst_Connect = false;
|
|
bool b_rightLst_Connect = false;
|
|
foreach (ObjSprinKler obj in RangeLeftLst)
|
|
{
|
|
if (obj.HeadCon.IsConnected == true)
|
|
{
|
|
b_leftLst_Connect = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
foreach (ObjSprinKler obj in RangeRightLst)
|
|
{
|
|
if (obj.HeadCon.IsConnected == true)
|
|
{
|
|
b_rightLst_Connect = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (b_leftLst_Connect == true || b_rightLst_Connect == true) return TeeBranchPipeLst;
|
|
|
|
//메인관 기준 왼쪽
|
|
int sp_hd = 0, sp_In = 0;
|
|
bool b_LeftDraw = true;
|
|
if (RangeLeftLst.Count() > 0)
|
|
{
|
|
//가지파이프
|
|
for (int i = 0; i < RangeLeftLst.Count(); i++)
|
|
{
|
|
if (i < (RangeLeftLst.Count() - 1))
|
|
{
|
|
obj1 = RangeLeftLst[i];
|
|
obj2 = RangeLeftLst[i + 1];
|
|
List<XYZ> mainPts = Spkr_Func.DownSPJOIN(obj1, obj2, m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
|
|
//틀어진 점에서 작도할 거리가 나오지 않으면 작도 X
|
|
if (mainPts == null)
|
|
{
|
|
if (RangeLeftLst.Count() - 1 >= i + 2)
|
|
{
|
|
mainPts = Spkr_Func.DownSPJOIN(obj1, RangeLeftLst[i + 2], m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
|
|
if (mainPts.Count() > 0)
|
|
{
|
|
m_LeftPtLst.AddRange(mainPts);
|
|
}
|
|
i++;
|
|
}
|
|
ExceptSpkrLst.Add(obj2);
|
|
}
|
|
else if (mainPts.Count() > 0)
|
|
{
|
|
m_LeftPtLst.AddRange(mainPts);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (b_LeftDraw == true)
|
|
{
|
|
//작도할 수 없는 스프링클러 제거
|
|
foreach (ObjSprinKler obj in ExceptSpkrLst)
|
|
{
|
|
RangeLeftLst.Remove(obj);
|
|
}
|
|
|
|
//메인 연결될 가지파이프
|
|
XYZ lastPt = Spkr_Func.DownGetMain2LastpipePoint(RangeLeftLst.Last(), m_BranchHgt);
|
|
m_LeftPtLst.Add(lastPt);
|
|
|
|
m_LeftPtLst.Reverse();
|
|
|
|
//캡 파이프
|
|
XYZ capPt = Spkr_Func.DownGetCAPpoint(RangeLeftLst.First(), m_BranchHgt, m_CapDist);
|
|
m_LeftPtLst.Add(capPt);
|
|
|
|
m_LeftPtLst.Reverse();
|
|
|
|
//파이프 및 엘보 생성
|
|
newPipes = Util.CreatePipe(uiapp, doc, m_LeftPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
|
|
|
|
//헤드와 가지관 연결
|
|
List<ElementId> LeftElemIdLst = Spkr_Func.DownConnectHead2pipe(RangeLeftLst, newPipes, HeadDiaLst, m_HeadOffset, m_ConnectDist, m_BranchHgt);
|
|
doc.Regenerate();
|
|
LeftLastElem = doc.GetElement(LeftElemIdLst.Last());
|
|
}
|
|
}
|
|
|
|
//메인관 기준 오른쪽
|
|
sp_hd = 0; sp_In = 0;
|
|
bool b_RightDraw = true;
|
|
ExceptSpkrLst.Clear();
|
|
if (RangeRightLst.Count() > 0)
|
|
{
|
|
////캡 파이프
|
|
//List<XYZ> capPt = GetCAPpipe(RangeRightLst.First(), m_HeadOffset, m_CapDist);
|
|
//m_RightPtLst.AddRange(capPt);
|
|
//가지 파이프
|
|
for (int i = 0; i < RangeRightLst.Count(); i++)
|
|
{
|
|
if (i < (RangeRightLst.Count() - 1))
|
|
{
|
|
obj1 = RangeRightLst[i];
|
|
obj2 = RangeRightLst[i + 1];
|
|
List<XYZ> mainPts = Spkr_Func.DownSPJOIN(obj1, obj2, m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
|
|
//틀어진 점에서 작도할 거리가 나오지 않으면 작도 X
|
|
if (mainPts == null)
|
|
{
|
|
if (RangeRightLst.Count() - 1 >= i + 2)
|
|
{
|
|
mainPts = Spkr_Func.DownSPJOIN(obj1, RangeRightLst[i + 2], m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
|
|
if (mainPts.Count() > 0)
|
|
{
|
|
m_RightPtLst.AddRange(mainPts);
|
|
}
|
|
i++;
|
|
}
|
|
ExceptSpkrLst.Add(obj2);
|
|
}
|
|
else if (mainPts.Count() > 0)
|
|
{
|
|
m_RightPtLst.AddRange(mainPts);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (b_RightDraw == true)
|
|
{
|
|
//작도할 수 없는 스프링클러 제거
|
|
foreach (ObjSprinKler obj in ExceptSpkrLst)
|
|
{
|
|
RangeRightLst.Remove(obj);
|
|
}
|
|
|
|
//메인 연결될 가지파이프
|
|
XYZ lastPt = Spkr_Func.DownGetMain2LastpipePoint(RangeRightLst.Last(), m_BranchHgt);
|
|
m_RightPtLst.Add(lastPt);
|
|
|
|
m_RightPtLst.Reverse();
|
|
|
|
//캡 파이프
|
|
XYZ capPt = Spkr_Func.DownGetCAPpoint(RangeRightLst.First(), m_BranchHgt, m_CapDist);
|
|
m_RightPtLst.Add(capPt);
|
|
|
|
m_RightPtLst.Reverse();
|
|
|
|
//파이프 및 엘보 생성
|
|
newPipes = Util.CreatePipe(uiapp, doc, m_RightPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
|
|
|
|
//헤드와 가지관 연결
|
|
List<ElementId> RightElemIdLst = Spkr_Func.DownConnectHead2pipe(RangeRightLst, newPipes, HeadDiaLst, m_HeadOffset, m_ConnectDist, m_BranchHgt);
|
|
doc.Regenerate();
|
|
RightLastElem = doc.GetElement(RightElemIdLst.Last());
|
|
}
|
|
}
|
|
|
|
|
|
//메인관 가지관 연결
|
|
TeeBranchPipeLst = Spkr_Func.MainConnectBranch(MainElem, LeftLastElem, RightLastElem);
|
|
//trans1.Commit();
|
|
|
|
|
|
return TeeBranchPipeLst;
|
|
}
|
|
|
|
|
|
public class SelectionMainPipe : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public class HeaderFilter : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|