978 lines
42 KiB
C#
978 lines
42 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 SpinKler;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
using KDCS.Utils;
|
|
using KMBIM.Revit.Tools.Properties;
|
|
|
|
namespace KMBIM
|
|
{
|
|
public class ObjSprinKler
|
|
{
|
|
public ElementId m_SpID; //헤드 ID
|
|
public Connector HeadCon = null;
|
|
public XYZ m_Headpt = null; //헤드 커넥터 점.
|
|
public XYZ m_InterPt = null; //헤드와 메인관 수직점
|
|
public double m_Ep2InterDst = 0; // 메인 끝점과 수직점 사이 거리
|
|
public bool EqVector = true;//현재 백터와 이전 벡터가 같은지(다르면 90도 꺾인 작도 위해)
|
|
|
|
}
|
|
|
|
public class ObjComparer : IComparer<ObjSprinKler>
|
|
{
|
|
public int Compare(ObjSprinKler a, ObjSprinKler b)
|
|
{
|
|
double diff = a.m_Ep2InterDst - b.m_Ep2InterDst;
|
|
if (Math.Abs(diff) < 0.0001) return 0;
|
|
else if (diff > 0.0001) return 1;
|
|
else if (diff < 0.0001) return -1;
|
|
else return 0;
|
|
|
|
}
|
|
}
|
|
|
|
public class ObjOrthoComparer : IComparer<ObjSprinKler>
|
|
{
|
|
public int Compare(ObjSprinKler a, ObjSprinKler b)
|
|
{
|
|
double diff = b.m_Headpt.DistanceTo(a.m_InterPt) - a.m_Headpt.DistanceTo(b.m_InterPt);
|
|
if (Math.Abs(diff) < 0.0001) return 0;
|
|
else if (diff > 0.0001) return 1;
|
|
else if (diff < 0.0001) return -1;
|
|
else return 0;
|
|
|
|
}
|
|
}
|
|
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|
class Sprinkler_Upword : 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_HeadOffset = 0, m_CapDist = 0;
|
|
List<ObjSprinKler> lst_objSprinkler = new List<ObjSprinKler>();
|
|
ObjComparer OC = new ObjComparer();
|
|
ObjOrthoComparer OrthoC = new ObjOrthoComparer();
|
|
PipeType mainPipeType = null;
|
|
double MainPipeOffset = 0;
|
|
XYZ MainVec = 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>();
|
|
double m_MainAng = 0;
|
|
XYZ mainSp = null, mainEp = null;
|
|
|
|
MessageBox.Show("123");
|
|
try
|
|
{
|
|
Reference pickref = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "메인 파이프 선택 : ");
|
|
if (pickref == null) return Result.Succeeded;
|
|
|
|
IList<Reference> pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new HeaderFilter(), "배관에 연결할 스프링클러 범위 지정 : ");
|
|
if (pickrefs == null) return Result.Succeeded;
|
|
|
|
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;
|
|
mainPipeType = MainPipe.PipeType;
|
|
MainPipeOffset = MainPipe.LevelOffset;
|
|
pipeline = (MainPipe.Location as LocationCurve).Curve as Line;
|
|
mainSp = pipeline.GetEndPoint(0);
|
|
mainEp = pipeline.GetEndPoint(1);
|
|
MainVec = (mainEp - mainSp).Normalize();
|
|
m_MainHgt = pipeline.GetEndPoint(0).Z;
|
|
m_MainAng = Util.Angle2D(pipeline.GetEndPoint(0), pipeline.GetEndPoint(1));
|
|
}
|
|
foreach (ElementId elemid in m_SpklrList)
|
|
{
|
|
FamilyInstance family = (doc.GetElement(elemid)) as FamilyInstance;
|
|
ConnectorSet conSet = family.MEPModel.ConnectorManager.Connectors;
|
|
foreach (Connector con in conSet)
|
|
{
|
|
IntersectionResult interRes = pipeline.Project(con.Origin);
|
|
//m_HeadInterPtLst.Add(interRes.XYZPoint);//헤드 교차점 리스트.
|
|
//m_HeadDictionary.Add(con, interRes.XYZPoint);
|
|
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));
|
|
lst_objSprinkler.Add(objSprinKler);
|
|
///////////////////////////////////////////배열 추가해야 함.
|
|
//Pyosi(interRes.XYZPoint,1);
|
|
//MessageBox.Show("1");
|
|
m_SpklrHgtLst.Add(con.Origin.Z);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//헤드 수직점에 따른 헤드 값 정렬
|
|
lst_objSprinkler.Sort(OC);
|
|
|
|
|
|
foreach (ObjSprinKler obj in lst_objSprinkler)
|
|
{
|
|
XYZ aa = obj.m_Headpt;
|
|
XYZ bb = obj.m_InterPt;
|
|
ElementId eid = obj.m_SpID;
|
|
//Pyosi(aa, 1);
|
|
//MessageBox.Show("head");
|
|
//Pyosi(bb, 1);
|
|
//MessageBox.Show("inter");
|
|
}
|
|
|
|
bool loop = true;
|
|
//헤드를 거리별로 그룹 나눠서 리스트에 저장하기.
|
|
while (loop)
|
|
{
|
|
if (lst_objSprinkler.Count <= 0) break;
|
|
|
|
List<ObjSprinKler> Group = DivideObjSprinKlerData(lst_objSprinkler);
|
|
|
|
//추출 그룹 정렬
|
|
Group.Sort(OrthoC);
|
|
List<int> ContainLst = new List<int>();
|
|
|
|
foreach (ObjSprinKler obj in Group)
|
|
{
|
|
//Pyosi(obj.m_InterPt, 1);
|
|
//MessageBox.Show("1");
|
|
int idx = lst_objSprinkler.IndexOf(obj);
|
|
lst_objSprinkler.RemoveAt(idx);
|
|
}
|
|
//나눈 그룹 리스트에 담기.
|
|
if (Group.Count > 0)
|
|
m_TotalObjLst.Add(Group);
|
|
}//while end
|
|
|
|
//총 리스트에서 헤드가 1개일 때 그 헤드 리스트 앞 뒤 중 가까운쪽에 넣고 삭제
|
|
m_TotalObjLst = RemoveSingleObjLst(m_TotalObjLst);
|
|
//m_TotalObjLst.Reverse();//메인관 끝점부터 시작하기 위해
|
|
|
|
|
|
//MessageBox.Show("m_TotalObjLst :" + m_TotalObjLst.Count());
|
|
|
|
Form_Upword dlg = new Form_Upword();
|
|
dlg.MainHeight = Unit.FeetToMM(m_MainHgt);
|
|
dlg.HeaderOffset = 150;
|
|
dlg.CapDist = 100;
|
|
dlg.m_HgtLst = m_SpklrHgtLst;//헤드 높이를 메인파이프 높이와 비교하기 위해
|
|
dlg.ShowDialog();
|
|
if (dlg.DialogResult == DialogResult.Cancel) return Result.Succeeded;
|
|
//대화상자 값 가져오기
|
|
m_MainHgt = dlg.MainHeight;
|
|
m_HeadOffset = dlg.HeaderOffset;
|
|
m_CapDist = dlg.CapDist;
|
|
|
|
//처음 관경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);
|
|
|
|
//총 리스트를 메인관 기준 왼쪽 오른쪽 분류
|
|
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);
|
|
}
|
|
|
|
ProcessingSpkr(lst_LeftObj, lst_RightObj, mainSp, mainEp, MainVec, headLst);
|
|
}
|
|
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
public void ProcessingSpkr(List<ObjSprinKler> RangeLeftLst, List<ObjSprinKler> RangeRightLst, XYZ MainSp, XYZ MainEp, XYZ mainVec, List<double> HeadDiaLst)
|
|
{
|
|
double Ldraw_ang = Util.Angle2D(MainSp, MainEp) - (0.5 * Util.kPi);
|
|
double Rdraw_ang = Util.Angle2D(MainSp, MainEp) + (0.5 * Util.kPi);
|
|
XYZ v = (MainEp - MainSp).Normalize();
|
|
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>();
|
|
//메인관 기준 왼쪽
|
|
int sp_hd = 0, sp_In = 0;
|
|
if (RangeLeftLst.Count() > 0)
|
|
{
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("Left");
|
|
//캡 파이프
|
|
List<XYZ> capPt = GetCAPpipe(RangeLeftLst.First(), m_HeadOffset, m_CapDist);
|
|
m_LeftPtLst.AddRange(capPt);
|
|
//가지파이프
|
|
for (int i = 0; i < RangeLeftLst.Count(); i++)
|
|
{
|
|
if (i < (RangeLeftLst.Count() - 1))
|
|
{
|
|
obj1 = RangeLeftLst[i];
|
|
obj2 = RangeLeftLst[i + 1];
|
|
List<XYZ> mainPts = SPJOIN(obj1, obj2, m_HeadOffset, ref sp_hd, ref sp_In);
|
|
m_LeftPtLst.AddRange(mainPts);
|
|
|
|
}
|
|
}
|
|
|
|
//메인 연결될 가지파이프
|
|
List<XYZ> lastPt = GetMain2Lastpipe(RangeLeftLst.Last(), m_HeadOffset, ref sp_hd);
|
|
m_LeftPtLst.AddRange(lastPt);
|
|
//파이프 및 엘보 생성
|
|
newPipes = CreatePipe(uidoc, doc, m_LeftPtLst, mainPipeType);
|
|
|
|
trans.Commit();
|
|
}
|
|
//헤드와 가지관 연결
|
|
ConnectHead2pipe(RangeLeftLst, newPipes, HeadDiaLst);
|
|
}
|
|
|
|
//메인관 기준 오른쪽
|
|
sp_hd = 0; sp_In = 0;
|
|
if (RangeRightLst.Count() > 0)
|
|
{
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("Right");
|
|
//캡 파이프
|
|
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 = SPJOIN(obj1, obj2, m_HeadOffset, ref sp_hd, ref sp_In);
|
|
m_RightPtLst.AddRange(mainPts);
|
|
}
|
|
}
|
|
|
|
//메인 연결될 가지파이프
|
|
List<XYZ> lastPt = GetMain2Lastpipe(RangeRightLst.Last(), m_HeadOffset, ref sp_hd);
|
|
m_RightPtLst.AddRange(lastPt);
|
|
//파이프 및 엘보 생성
|
|
newPipes = CreatePipe(uidoc, doc, m_RightPtLst, mainPipeType);
|
|
|
|
trans.Commit();
|
|
}
|
|
//헤드와 가지관 연결
|
|
ConnectHead2pipe(RangeRightLst, newPipes, HeadDiaLst);
|
|
}
|
|
}
|
|
|
|
//캡포인트 구하기.
|
|
public List<XYZ> GetCAPpipe(ObjSprinKler FirstObjSpkr, double HeadOffset, double CapDist)
|
|
{
|
|
//메인-헤드 방향 벡터
|
|
XYZ MHvec = (FirstObjSpkr.m_Headpt - FirstObjSpkr.m_InterPt).Normalize();
|
|
//헤드-캡까지의 간격(사용자입력값)만큼 떨어진 점 구하기.
|
|
XYZ CapPt = Util.Polar(FirstObjSpkr.m_Headpt, MHvec, Unit.MMToFeet(CapDist));
|
|
//헤드간격 띄우기 값 적용
|
|
XYZ newCapPt = new XYZ(CapPt.X, CapPt.Y, CapPt.Z - Unit.MMToFeet(HeadOffset));
|
|
XYZ newHeadPt = new XYZ(FirstObjSpkr.m_Headpt.X, FirstObjSpkr.m_Headpt.Y, FirstObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
|
|
|
|
List<XYZ> pts = new List<XYZ>();
|
|
pts.Add(newCapPt);
|
|
//pts.Add(newHeadPt);
|
|
|
|
return pts;
|
|
}
|
|
|
|
//틀어진 가지관 등 점 구하기.
|
|
public List<XYZ> SPJOIN(ObjSprinKler objSpkr1, ObjSprinKler objSpkr2, double HeadOffset, ref int sp_hd, ref int sp_in)
|
|
{
|
|
double siz15 = 0, ang1 = 0; ;
|
|
XYZ pt110 = null, pt210 = null, tmppt1 = null, tmppt2 = null,
|
|
pt2 = null, pt21 = null, pt22 = null, inter1 = null, vec = null;
|
|
XYZ jpt1 = objSpkr1.m_Headpt;
|
|
XYZ jpt2 = objSpkr2.m_Headpt;
|
|
siz15 = Unit.MMToFeet(300);
|
|
vec = (objSpkr1.m_Headpt - objSpkr2.m_Headpt).Normalize();
|
|
double vecAng = Util.RTD(vec.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ));
|
|
|
|
//헤드메인교차점-헤드 벡터
|
|
XYZ HMvec = (objSpkr1.m_InterPt - objSpkr1.m_Headpt).Normalize();
|
|
|
|
ang1 = vecAng;
|
|
List<XYZ> linePtlst = new List<XYZ>();
|
|
|
|
|
|
//두개의 헤드가 틀어진 경우
|
|
if (!(Math.Abs(ang1 - 0.0) < 0.001) && !(Math.Abs(ang1 - 90.0) < 0.001) &&
|
|
!(Math.Abs(ang1 - 180.0) < 0.001) && !(Math.Abs(ang1 - 270.0) < 0.001))
|
|
{
|
|
sp_in++;
|
|
|
|
if (sp_in == 1)
|
|
{
|
|
pt110 = Util.Polar(jpt1, HMvec, siz15);
|
|
pt210 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(180)), siz15);
|
|
tmppt1 = Util.Polar(jpt1, HMvec, 1000);
|
|
tmppt2 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(90)), 1000);
|
|
inter1 = GetIntersectionPoint(jpt1, tmppt1, jpt2, tmppt2);
|
|
pt21 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(90)), inter1.DistanceTo(jpt2));
|
|
pt22 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(270)), inter1.DistanceTo(jpt2));
|
|
}
|
|
else
|
|
{
|
|
pt210 = Util.Polar(jpt1, HMvec, siz15);
|
|
pt110 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(180)), siz15);
|
|
tmppt1 = Util.Polar(jpt1, HMvec, 1000);
|
|
tmppt2 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(90)), 1000);
|
|
inter1 = GetIntersectionPoint(jpt1, tmppt1, jpt2, tmppt2);
|
|
pt21 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(90)), inter1.DistanceTo(jpt2));
|
|
pt22 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(270)), inter1.DistanceTo(jpt2));
|
|
}
|
|
|
|
if (sp_in >= 2)
|
|
sp_in = 0;
|
|
|
|
if (pt210.DistanceTo(pt21) >= pt210.DistanceTo(pt22))
|
|
pt2 = pt22;
|
|
else
|
|
pt2 = pt21;
|
|
//Pyosi(pt2, 1);
|
|
//MessageBox.Show("pt2");
|
|
|
|
//헤드간격 띄우기 값 적용
|
|
XYZ newHeadPt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, objSpkr1.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
XYZ newHeadPt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, objSpkr2.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
XYZ newpt110 = new XYZ(pt110.X, pt110.Y, pt110.Z - Unit.MMToFeet(HeadOffset));
|
|
XYZ newpt2 = new XYZ(pt2.X, pt2.Y, pt2.Z - Unit.MMToFeet(HeadOffset));
|
|
|
|
if (sp_in == 1)
|
|
{
|
|
//linePtlst.Add(newHeadPt1);
|
|
linePtlst.Add(newpt110);
|
|
linePtlst.Add(newpt2);
|
|
//linePtlst.Add(newHeadPt2);
|
|
}
|
|
else
|
|
{
|
|
//linePtlst.Add(newHeadPt1);
|
|
linePtlst.Add(newpt2);
|
|
linePtlst.Add(newpt110);
|
|
//linePtlst.Add(newHeadPt2);
|
|
}
|
|
}
|
|
else//두개의 헤드가 일직선인 경우
|
|
{
|
|
//헤드간격 띄우기 값 적용
|
|
XYZ newHeadPt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, objSpkr1.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
XYZ newHeadPt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, objSpkr2.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
//linePtlst.Add(newHeadPt1);
|
|
//linePtlst.Add(newHeadPt2);
|
|
}
|
|
|
|
sp_hd++;
|
|
|
|
return linePtlst;
|
|
|
|
}
|
|
|
|
//메인 연결될 가지파이프
|
|
public List<XYZ> GetMain2Lastpipe(ObjSprinKler LastObjSpkr, double HeadOffset, ref int sp_hd)
|
|
{
|
|
List<XYZ> pts = new List<XYZ>();
|
|
//헤드간격 띄우기 값 적용
|
|
XYZ newInterPt = new XYZ(LastObjSpkr.m_InterPt.X, LastObjSpkr.m_InterPt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
XYZ newHeadPt = new XYZ(LastObjSpkr.m_Headpt.X, LastObjSpkr.m_Headpt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
|
|
|
|
//pts.Add(newHeadPt);
|
|
pts.Add(newInterPt);
|
|
|
|
return pts;
|
|
}
|
|
|
|
public void ConnectHead2pipe(List<ObjSprinKler> sprinKlers, List<Pipe> pipes, List<double> HeadDiaLst)
|
|
{
|
|
//double DirectAng = FromBranchToHeadAngle(sprinKlers.First(), pipes.First());
|
|
|
|
Pipe pipe = pipes.First();
|
|
Pipe DividePipe = null;
|
|
for (int i = 0; i < sprinKlers.Count(); i++)
|
|
{
|
|
ObjSprinKler obj = sprinKlers.ElementAt(i);
|
|
DividePipe = CreatePipeT(obj, pipe);
|
|
if (DividePipe != null)
|
|
{
|
|
ApplyReducerAndDiameter(DividePipe, HeadDiaLst[i], HeadDiaLst[i + 1], 100);
|
|
pipe = DividePipe;
|
|
}
|
|
else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행
|
|
{
|
|
pipes.RemoveAt(0);
|
|
foreach (Pipe pp in pipes)
|
|
{
|
|
//XYZ aa = null, bb = null;
|
|
//Util.GetStartEndPoint(pp, ref aa, ref bb);
|
|
//Pyosi(aa, 1);
|
|
//MessageBox.Show("1");
|
|
//Connector con = pp.ConnectorManager.Connectors.Cast<Connector>().First();
|
|
//con.Radius = Unit.MMToFeet(HeadDiaLst[i] / 2.0);
|
|
DividePipe = CreatePipeT(obj, pp);
|
|
if (DividePipe != null)
|
|
{
|
|
ApplyReducerAndDiameter(DividePipe, HeadDiaLst[i], HeadDiaLst[i + 1], 100);
|
|
pipe = DividePipe;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Pipe CreatePipeT(ObjSprinKler objSprinKler, Pipe BranchPipe)
|
|
{
|
|
|
|
Line pipeline = (BranchPipe.Location as LocationCurve).Curve as Line;
|
|
IntersectionResult intersection = pipeline.Project(objSprinKler.m_Headpt);
|
|
XYZ interPt = intersection.XYZPoint;
|
|
|
|
//헤드와 배관의 가까운점이 배관의 시작 또는 끝점일 경우 실행X
|
|
if (interPt.IsAlmostEqualTo(pipeline.GetEndPoint(0), Unit.MMToFeet(0.01))
|
|
|| interPt.IsAlmostEqualTo(pipeline.GetEndPoint(1), Unit.MMToFeet(0.01))) return null;
|
|
|
|
ElementId m_divideElemId = null;
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("1");
|
|
//가지관 자르기
|
|
m_divideElemId = PlumbingUtils.BreakCurve(doc, BranchPipe.Id, interPt);
|
|
Pipe divideBranchPipe = doc.GetElement(m_divideElemId) as Pipe;
|
|
Pipe Headpipe = CreateHeadPipe(objSprinKler, interPt, BranchPipe);
|
|
|
|
Connector HeadCon = null, mainCon1 = null, mainCon2 = null;
|
|
|
|
//나뉜 파이프의 겹치는 커넥터 구하기(T커넥터)
|
|
List<Connector> MainCon1Lst = Util.GetElementConnectors(divideBranchPipe);
|
|
List<Connector> MainCon2Lst = Util.GetElementConnectors(BranchPipe);
|
|
foreach (Connector con1 in MainCon1Lst)
|
|
{
|
|
foreach (Connector con2 in MainCon2Lst)
|
|
{
|
|
if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
|
|
{
|
|
mainCon1 = con1; mainCon2 = con2;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//헤드 파이프 T커넥터
|
|
List<Connector> HeadConsLst = Util.GetElementConnectors(Headpipe as Element);
|
|
foreach (Connector con in HeadConsLst)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(interPt, Unit.MMToFeet(0.01)))
|
|
HeadCon = con;
|
|
}
|
|
|
|
if (mainCon1 != null && mainCon2 != null && HeadCon != null)
|
|
{
|
|
FamilyInstance family = creDoc.NewTeeFitting(mainCon1, mainCon2, HeadCon);
|
|
}
|
|
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
return BranchPipe;
|
|
|
|
}
|
|
|
|
//파이프에 관경 넣고 T와 레듀셔 사이 100mm 떨어트려 작도
|
|
public void ApplyReducerAndDiameter(Pipe BranchPipe, double CurDia, double NextDia, double T2ReducerDist)
|
|
{
|
|
if (Math.Abs(CurDia - NextDia) < 0.01) return;
|
|
XYZ sp = null, ep = null;
|
|
Connector PipeStartCon = null, TeeCon = null;
|
|
|
|
Util.GetStartEndPoint(BranchPipe, ref sp, ref ep);
|
|
List<Connector> pipeConLst = Util.GetElementConnectors(BranchPipe);
|
|
|
|
if (sp.DistanceTo(ep) < Unit.MMToFeet(200))
|
|
{
|
|
MessageBox.Show("길이가 짧습니다.");
|
|
return;
|
|
}
|
|
|
|
//시작점 커넥터 구하기.
|
|
foreach (Connector con in pipeConLst)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(sp, Unit.MMToFeet(0.01)))
|
|
PipeStartCon = con;
|
|
}
|
|
|
|
TeeCon = Util.GetNextElementConnector(PipeStartCon);
|
|
|
|
List<XYZ> reducerPtLst = new List<XYZ>();
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("1");
|
|
// T 와 파이프 연결 끊기
|
|
PipeStartCon.DisconnectFrom(TeeCon);
|
|
|
|
// T 에서 100mm만큼 파이프생성
|
|
XYZ ReducerPt = Util.Polar(TeeCon.Origin, sp, ep, Unit.MMToFeet(100));
|
|
reducerPtLst.Add(TeeCon.Origin); reducerPtLst.Add(ReducerPt);
|
|
List<Pipe> newPipeLst = CreatePipe(uidoc, doc, reducerPtLst, mainPipeType);
|
|
List<Connector> newPipeCons = Util.GetElementConnectors(newPipeLst[0]);
|
|
newPipeCons.First().Radius = TeeCon.Radius;
|
|
|
|
PipeStartCon.Radius = Unit.MMToFeet(NextDia) / 2.0;
|
|
PipeStartCon.Origin = Util.Polar(PipeStartCon.Origin, sp, ep, Unit.MMToFeet(109));
|
|
//Pyosi(PipeStartCon.Origin, 0);
|
|
//새로 만든 파이프와 연결
|
|
foreach (Connector con in newPipeCons)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(ReducerPt, Unit.MMToFeet(0.01)))
|
|
{
|
|
creDoc.NewTransitionFitting(con, PipeStartCon);
|
|
}
|
|
|
|
}
|
|
//틀어진 경우 레듀셔 커넥터에서부터 다음 T나오기전까지 관경 동일하게 만들기.
|
|
|
|
//Connector OtherCon = Util.GetOtherConnector(PipeStartCon);
|
|
//Connector OtherNextCon = Util.GetNextElementConnector(OtherCon);
|
|
//bool loop = false;
|
|
//
|
|
//if (OtherNextCon != null) loop = true;
|
|
//
|
|
//while (loop)
|
|
//{
|
|
//
|
|
// if (Util.GetFamilyPartType(OtherNextCon, PartType.Transition))
|
|
// {
|
|
// OtherNextCon = Util.GetNextElementConnector(OtherCon);
|
|
// OtherCon = Util.GetOtherConnector(OtherNextCon);
|
|
// Pyosi(OtherCon.Origin, 0);
|
|
// }
|
|
// else if(Util.GetFamilyPartType(OtherNextCon, PartType.Elbow))
|
|
// {
|
|
// OtherNextCon = Util.GetNextElementConnector(OtherCon);
|
|
// OtherCon = Util.GetOtherConnector(OtherNextCon);
|
|
// Pyosi(OtherCon.Origin, 0);
|
|
// }
|
|
// else if (Util.GetFamilyPartType(OtherNextCon, PartType.Tee))
|
|
// {
|
|
// break;
|
|
// }
|
|
// else if(OtherNextCon.Owner is Pipe)
|
|
// {
|
|
// OtherNextCon = Util.GetNextElementConnector(OtherCon);
|
|
// OtherCon = Util.GetOtherConnector(OtherNextCon);
|
|
// Pyosi(OtherCon.Origin, 0);
|
|
// }
|
|
//
|
|
//}//while end
|
|
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
//Pyosi(sp, 1);
|
|
//MessageBox.Show("1");
|
|
|
|
}
|
|
|
|
//T연결에 필요한 분기배관 생성
|
|
public Pipe CreateHeadPipe(ObjSprinKler objSpkr, XYZ breakPt, Pipe BranchPipe)
|
|
{
|
|
Level level = doc.ActiveView.GenLevel;
|
|
|
|
Pipe headPipe = Pipe.Create(doc, BranchPipe.MEPSystem.GetTypeId(), BranchPipe.GetTypeId(), level.Id, breakPt, objSpkr.m_Headpt);
|
|
|
|
List<Connector> HeadCons = Util.GetElementConnectors(headPipe);
|
|
foreach (Connector con in HeadCons)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(objSpkr.HeadCon.Origin, Unit.MMToFeet(0.01)))
|
|
{
|
|
con.Radius = Unit.MMToFeet(25 / 2.0);
|
|
//헤드와 헤드파이프 커넥터 연결
|
|
con.ConnectTo(objSpkr.HeadCon);
|
|
}
|
|
}
|
|
return headPipe;
|
|
}
|
|
|
|
// 1000mm범위의 헤드를 리스트에 담아 리턴
|
|
public List<ObjSprinKler> DivideObjSprinKlerData(List<ObjSprinKler> MainObjLst)
|
|
{
|
|
List<ObjSprinKler> resLst = new List<ObjSprinKler>();
|
|
resLst.AddRange(MainObjLst);
|
|
ObjSprinKler obj1st = MainObjLst.First();
|
|
|
|
foreach (ObjSprinKler obj in MainObjLst)
|
|
{
|
|
double aa = Math.Round(Unit.FeetToMM(obj1st.m_InterPt.DistanceTo(obj.m_InterPt)), 3);
|
|
if (Math.Round(Unit.FeetToMM(obj1st.m_InterPt.DistanceTo(obj.m_InterPt)), 3) > 1000)
|
|
{
|
|
int ctIdx = resLst.IndexOf(obj);
|
|
resLst.RemoveAt(ctIdx);
|
|
}
|
|
}
|
|
|
|
|
|
return resLst;
|
|
}
|
|
|
|
//총 리스트에서 헤드가 1개일 때 그 헤드 리스트 앞 뒤 중 가까운쪽에 넣고 삭제
|
|
public List<List<ObjSprinKler>> RemoveSingleObjLst(List<List<ObjSprinKler>> m_Lst)
|
|
{
|
|
|
|
for (int i = 0; i < m_Lst.Count(); i++)
|
|
{
|
|
List<ObjSprinKler> m_objLst = m_Lst.ElementAt(i);
|
|
if (m_objLst.Count() == 1)
|
|
{
|
|
if (i == 0)//첫번째 그룹에 1개일 때 이전을 비교할 필요없음.
|
|
{
|
|
List<ObjSprinKler> AfterObj = m_Lst[i + 1];
|
|
AfterObj.Add(m_Lst[i].First());
|
|
m_Lst[i].Remove(m_Lst[i].First());
|
|
AfterObj.Sort(OrthoC);
|
|
}
|
|
else if (i > 0)//두번째 이후
|
|
{
|
|
List<ObjSprinKler> BeforeObj = m_Lst[i - 1];
|
|
List<ObjSprinKler> CurObj = m_Lst[i];
|
|
List<ObjSprinKler> AfterObj = m_Lst[i + 1];
|
|
|
|
double beforeDist = BeforeObj.First().m_Headpt.DistanceTo(CurObj.First().m_Headpt);
|
|
double afterDist = AfterObj.First().m_Headpt.DistanceTo(CurObj.First().m_Headpt);
|
|
//가까운쪽에 넣기
|
|
if (Math.Round(Unit.FeetToMM(beforeDist), 3) < Math.Round(Unit.FeetToMM(afterDist), 3))
|
|
{
|
|
BeforeObj.Add(CurObj.First());
|
|
CurObj.Remove(CurObj.First());
|
|
BeforeObj.Sort(OrthoC);
|
|
}
|
|
else
|
|
{
|
|
AfterObj.Add(CurObj.First());
|
|
CurObj.Remove(CurObj.First());
|
|
AfterObj.Sort(OrthoC);
|
|
}
|
|
}
|
|
else if (i == m_Lst.Count() - 1)
|
|
{
|
|
List<ObjSprinKler> BeforeObj = m_Lst[i - 1];
|
|
BeforeObj.Add(m_Lst[i].First());
|
|
m_Lst[i].Remove(m_Lst[i].First());
|
|
BeforeObj.Sort(OrthoC);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
List<List<ObjSprinKler>> RemoveIdxLst = new List<List<ObjSprinKler>>();
|
|
foreach (List<ObjSprinKler> objsp in m_Lst)
|
|
{
|
|
if (objsp.Count == 0)
|
|
{
|
|
RemoveIdxLst.Add(objsp);
|
|
//m_TotalObjLst.RemoveAt(idx);
|
|
}
|
|
}
|
|
|
|
foreach (List<ObjSprinKler> objsp in RemoveIdxLst)
|
|
{
|
|
m_Lst.Remove(objsp);
|
|
}
|
|
|
|
return m_Lst;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
public class SelectionFilter : 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 XYZ GetIntersectionPoint(XYZ p1, XYZ p2, XYZ p3, XYZ p4)
|
|
{
|
|
double d = (p1.X - p2.X) * (p3.Y - p4.Y) - (p1.Y - p2.Y) * (p3.X - p4.X);
|
|
if (d == 0) return null;
|
|
|
|
double pre = (p1.X * p2.Y - p1.Y * p2.X), post = (p3.X * p4.Y - p3.Y * p4.X);
|
|
double x = (pre * (p3.X - p4.X) - (p1.X - p2.X) * post) / d;
|
|
double y = (pre * (p3.Y - p4.Y) - (p1.Y - p2.Y) * post) / d;
|
|
|
|
XYZ resPt = new XYZ(x, y, p1.Z);
|
|
|
|
return resPt;
|
|
}
|
|
|
|
public bool Pyosi(XYZ pt, int TranMode)
|
|
{
|
|
Level level = doc.ActiveView.GenLevel;
|
|
if (TranMode == 0)
|
|
{
|
|
XYZ pt1 = new XYZ(pt.X - 1.64042, pt.Y + 1.64042, level.Elevation);
|
|
XYZ pt2 = new XYZ(pt.X + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), pt.Y + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), level.Elevation);
|
|
XYZ pt3 = new XYZ(pt.X + 1.64042, pt.Y - 1.64042, level.Elevation);
|
|
XYZ pt4 = new XYZ(pt.X - 1.64042, pt.Y - 1.64042, level.Elevation);
|
|
|
|
Autodesk.Revit.DB.View view = doc.ActiveView;
|
|
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt1, pt3);
|
|
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt2, pt4);
|
|
}
|
|
else
|
|
{
|
|
using (Transaction transaction = new Transaction(doc))
|
|
{
|
|
transaction.Start("Start");
|
|
|
|
XYZ pt1 = new XYZ(pt.X - 1.64042, pt.Y + 1.64042, level.Elevation);
|
|
XYZ pt2 = new XYZ(pt.X + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), pt.Y + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), level.Elevation);
|
|
XYZ pt3 = new XYZ(pt.X + 1.64042, pt.Y - 1.64042, level.Elevation);
|
|
XYZ pt4 = new XYZ(pt.X - 1.64042, pt.Y - 1.64042, level.Elevation);
|
|
|
|
Autodesk.Revit.DB.View view = doc.ActiveView;
|
|
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt1, pt3);
|
|
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt2, pt4);
|
|
transaction.Commit();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public List<Pipe> CreatePipe(UIDocument uidoc, Document document, List<XYZ> pts, PipeType pipeType)
|
|
{
|
|
Autodesk.Revit.DB.View view = document.ActiveView;
|
|
Level level = document.ActiveView.GenLevel;
|
|
FilteredElementCollector sysCollector = new FilteredElementCollector(document);
|
|
//sysCollector.OfClass(typeof(PipingSystemType));
|
|
sysCollector.OfCategory(BuiltInCategory.OST_PipingSystem);
|
|
ElementId pipeSysTypeId = sysCollector.FirstElementId();
|
|
|
|
Pipe newpipe = null;
|
|
List<Pipe> pipes = new List<Pipe>();
|
|
|
|
List<Curve> newLineLst = new List<Curve>();
|
|
List<Element> ElemLst = new List<Element>();
|
|
for (int i = 0; i < pts.Count() - 1; i++)
|
|
{
|
|
ModelLine newLine = Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pts[i], pts[i + 1]) as ModelLine;
|
|
Curve cur = newLine.GeometryCurve;
|
|
newLineLst.Add(cur);
|
|
ElemLst.Add(newLine);
|
|
}
|
|
|
|
try
|
|
{
|
|
|
|
List<Element> elePipe = new List<Element>();
|
|
int cnt = 0;
|
|
foreach (Curve cur in newLineLst)
|
|
{
|
|
XYZ start = cur.GetEndPoint(0);
|
|
XYZ end = cur.GetEndPoint(1);
|
|
if (pipeType != null)
|
|
{
|
|
|
|
newpipe = Pipe.Create(document, pipeSysTypeId, pipeType.Id, level.Id, start, end);
|
|
|
|
//MessageBox.Show("1");
|
|
|
|
Element element = document.GetElement(newpipe.Id as ElementId);
|
|
elePipe.Add(element);
|
|
|
|
// 1-6) fitting 할 elbow 굵기에 맞게 pipe 굵기 설정하기
|
|
ElementId elementId = newpipe.Id as ElementId;
|
|
//Parameter parameter = element.LookupParameter("지름");
|
|
newpipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(Unit.MMToFeet(25));
|
|
pipes.Add(newpipe);
|
|
}
|
|
}
|
|
document.Regenerate();
|
|
|
|
for (int i = 0; i < pipes.Count() - 1; i++)
|
|
{
|
|
|
|
ConnectorManager pipe_connectorManager1 = pipes.ElementAt(i).ConnectorManager;
|
|
ConnectorSet pipe_connectorSet1 = pipe_connectorManager1.Connectors;
|
|
ConnectorManager pipe_connectorManager2 = pipes.ElementAt(i + 1).ConnectorManager;
|
|
ConnectorSet pipe_connectorSet2 = pipe_connectorManager2.Connectors;
|
|
|
|
|
|
// 2-3) 파이프가 가지고 있는 connectors 에서 연결시킬 connector 뽑아내기
|
|
|
|
Connector pipe_connector1 = null;
|
|
Connector pipe_connector2 = null;
|
|
double minDist = double.MaxValue;
|
|
foreach (Connector connector1 in pipe_connectorSet1)
|
|
{
|
|
foreach (Connector connector2 in pipe_connectorSet2)
|
|
{
|
|
double d = connector1.Origin.DistanceTo(connector2.Origin);
|
|
if (d < minDist)
|
|
{
|
|
pipe_connector1 = connector1;
|
|
pipe_connector2 = connector2;
|
|
minDist = d;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2-4) 2개의 파이프 연결시키기
|
|
try
|
|
{
|
|
FamilyInstance fitting = document.Create.NewElbowFitting(pipe_connector1, pipe_connector2);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//MessageBox.Show("" + e);
|
|
}
|
|
|
|
}
|
|
// pipe와 겹치는 line 삭제하기
|
|
foreach (Element element in ElemLst)
|
|
{
|
|
if (element == null) continue;
|
|
ElementId elementId = element.Id;
|
|
document.Delete(elementId);
|
|
}
|
|
|
|
return pipes;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
|
|
}
|
|
|
|
return pipes;
|
|
}
|
|
|
|
//DividePipe가 null일 경우 다음 커넥터로 넘기는 코드
|
|
//public void ConnectHead2pipe2(List<ObjSprinKler> sprinKlers, List<Pipe> pipes)
|
|
//{
|
|
// //double DirectAng = FromBranchToHeadAngle(sprinKlers.First(), pipes.First());
|
|
// Pipe pipe = pipes.First();
|
|
// Pipe DividePipe = null;
|
|
// foreach (ObjSprinKler obj in sprinKlers)
|
|
// {
|
|
// DividePipe = CreatePipeT(obj, pipe);
|
|
// if (DividePipe != null)
|
|
// pipe = DividePipe;
|
|
// else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행
|
|
// {
|
|
// Line pipeline = (pipe.Location as LocationCurve).Curve as Line;
|
|
// //Pyosi(pipeline.GetEndPoint(1), 1);
|
|
// //MessageBox.Show("1");
|
|
// foreach (Connector con in Util.GetElementConnectors(pipe))
|
|
// {
|
|
// //끝점에서 다음 객체의 반대쪽 커넥터 구하기.
|
|
// if (con.Origin.IsAlmostEqualTo(pipeline.GetEndPoint(1), Unit.MMToFeet(0.01)))
|
|
// {
|
|
// Connector baseCon = con;
|
|
// while (true)
|
|
// {
|
|
// Connector NextCon = Util.GetNextElementConnector(baseCon);
|
|
// Connector NextOtherCon = Util.GetOtherConnector(NextCon);
|
|
// Connector Next2Con = Util.GetNextElementConnector(NextOtherCon);
|
|
//
|
|
// if (Next2Con.Owner is Pipe)
|
|
// {
|
|
// pipe = Next2Con.Owner as Pipe;
|
|
// DividePipe = CreatePipeT(obj, pipe);
|
|
// if (DividePipe != null)
|
|
// {
|
|
// pipe = DividePipe;
|
|
// break;
|
|
// }
|
|
// else
|
|
// baseCon = Next2Con;
|
|
// }
|
|
// else
|
|
// continue;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//}
|
|
}
|
|
}
|