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 { 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 { 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 lst_objSprinkler = new List(); 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 m_SpklrList = new List(); List> m_TotalObjLst = new List>(); List> Left_TotalObjLst = new List>(); List> Right_TotalObjLst = new List>(); List m_SpklrHgtLst = new List(); 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 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 Group = DivideObjSprinKlerData(lst_objSprinkler); //추출 그룹 정렬 Group.Sort(OrthoC); List ContainLst = new List(); 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 headLst = new List(); 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 lst_obj in m_TotalObjLst) { List lst_LeftObj = new List(); List lst_RightObj = new List(); 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 RangeLeftLst, List RangeRightLst, XYZ MainSp, XYZ MainEp, XYZ mainVec, List 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 m_LeftPtLst = new List(); List m_RightPtLst = new List(); List m_LCurveLst = new List(); List m_RCurveLst = new List(); List newPipes = new List(); //메인관 기준 왼쪽 int sp_hd = 0, sp_In = 0; if (RangeLeftLst.Count() > 0) { using (Transaction trans = new Transaction(doc)) { trans.Start("Left"); //캡 파이프 List 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 mainPts = SPJOIN(obj1, obj2, m_HeadOffset, ref sp_hd, ref sp_In); m_LeftPtLst.AddRange(mainPts); } } //메인 연결될 가지파이프 List 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 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 mainPts = SPJOIN(obj1, obj2, m_HeadOffset, ref sp_hd, ref sp_In); m_RightPtLst.AddRange(mainPts); } } //메인 연결될 가지파이프 List 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 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 pts = new List(); pts.Add(newCapPt); //pts.Add(newHeadPt); return pts; } //틀어진 가지관 등 점 구하기. public List 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 linePtlst = new List(); //두개의 헤드가 틀어진 경우 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 GetMain2Lastpipe(ObjSprinKler LastObjSpkr, double HeadOffset, ref int sp_hd) { List pts = new List(); //헤드간격 띄우기 값 적용 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 sprinKlers, List pipes, List 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().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 MainCon1Lst = Util.GetElementConnectors(divideBranchPipe); List 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 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 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 reducerPtLst = new List(); 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 newPipeLst = CreatePipe(uidoc, doc, reducerPtLst, mainPipeType); List 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 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 DivideObjSprinKlerData(List MainObjLst) { List resLst = new List(); 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> RemoveSingleObjLst(List> m_Lst) { for (int i = 0; i < m_Lst.Count(); i++) { List m_objLst = m_Lst.ElementAt(i); if (m_objLst.Count() == 1) { if (i == 0)//첫번째 그룹에 1개일 때 이전을 비교할 필요없음. { List 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 BeforeObj = m_Lst[i - 1]; List CurObj = m_Lst[i]; List 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 BeforeObj = m_Lst[i - 1]; BeforeObj.Add(m_Lst[i].First()); m_Lst[i].Remove(m_Lst[i].First()); BeforeObj.Sort(OrthoC); } } } List> RemoveIdxLst = new List>(); foreach (List objsp in m_Lst) { if (objsp.Count == 0) { RemoveIdxLst.Add(objsp); //m_TotalObjLst.RemoveAt(idx); } } foreach (List 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 CreatePipe(UIDocument uidoc, Document document, List 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 pipes = new List(); List newLineLst = new List(); List ElemLst = new List(); 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 elePipe = new List(); 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 sprinKlers, List 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; // } // } // } // } // } //} } }