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 KDCS.Utils; using Autodesk.Revit.DB.Structure; namespace KMBIM.Revit.Tools.Cmd.SprinklerConnect { 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 XYZ SeparateionPt = null; // 하향식 - 이격거리 점 } 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) { //XYZ aHeadPtZ0 = new XYZ(a.m_Headpt.X, a.m_Headpt.Y, 0); //XYZ aInterPtZ0 = new XYZ(a.m_InterPt.X, a.m_InterPt.Y, 0); //XYZ bHeadPtZ0 = new XYZ(b.m_Headpt.X, b.m_Headpt.Y, 0); //XYZ bInterPtZ0 = new XYZ(b.m_InterPt.X, b.m_InterPt.Y, 0); //double diff = bHeadPtZ0.DistanceTo(aInterPtZ0) - aHeadPtZ0.DistanceTo(bInterPtZ0); 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; } } class SprinKler_Function { //변수는 실행쪽에서 받아옴 public Document doc; public Autodesk.Revit.Creation.Document creDoc; public UIApplication uiapp; public ElementId MainPipeTypeId = null; public ElementId MainSystemTypeId = null; public ElementId MainLevelId = null; ObjComparer OC = new ObjComparer(); ObjOrthoComparer OrthoC = new ObjOrthoComparer(); /////////////////////////헤드 리스트 분할 함수//////////////////////////// // 1000mm범위의 헤드를 리스트에 담아 리턴 public List DivideObjSprinKlerData(Pipe mainPipe,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); } } XYZ sp = null, ep = null; Util.GetStartEndPoint(mainPipe, ref sp, ref ep); for(int i=0; i < resLst.Count(); i++) { for (int k = 0; k < resLst.Count(); k++) { if (i == k) continue; ObjSprinKler obj_i = resLst[i]; ObjSprinKler obj_k = resLst[k]; bool i_right = Util.isRightPoint(obj_i.m_Headpt, sp, ep); bool k_right = Util.isRightPoint(obj_k.m_Headpt, sp, ep); //메인관 기준 같은 쪽 헤더가 아니면 넘어감 if (i_right != k_right) continue; double i_inter2HeadDst = obj_i.m_InterPt.DistanceTo(obj_i.m_Headpt); double k_inter2HeadDst = obj_k.m_InterPt.DistanceTo(obj_k.m_Headpt); //헤드점-메인관교차점 길이가 같은게 그룹에 있을 경우 (● ●) if(Math.Abs(i_inter2HeadDst-k_inter2HeadDst) < Unit.MMToFeet(0.01)) { resLst.Remove(obj_k); break; } } } 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 == m_Lst.Count() - 1)//마지막 그룹이 1개일 때 이전만 비교 { List BeforeObj = m_Lst[i - 1]; BeforeObj.Add(m_Lst[i].First()); m_Lst[i].Remove(m_Lst[i].First()); BeforeObj.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); } } } } 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; } /////////////////////////헤드 포인트//////////////////////////// /// /// 상향식 틀어진 가지관 등 점 구하기. /// /// 첫번째 헤드 /// 두번째 헤드 /// 대화상자 헤드 간격띄우기 /// 틀어진 헤드 작도점 1,2로 나뉘는 변수 /// 헤드가 몇번째 관경을 적용하는지 나타내는 변수 /// 헤드 관경 리스트 /// //z값 0으로 벡터 구해야 함 스프링클러 높이가 다르면 벡터가 대각선이 됨. public List UpSPJOIN(ObjSprinKler objSpkr1, ObjSprinKler objSpkr2, double BranchHgt, ref int sp_in, int DiaCnt, List headDiaLst) { 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 = null, jpt2 = null; siz15 = Unit.MMToFeet(300); XYZ Z0Headpt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, 0); XYZ Z0Headpt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, 0); vec = (Z0Headpt1 - Z0Headpt2).Normalize(); double ang = Util.Angle2D(Z0Headpt1, Z0Headpt2); //vec = (objSpkr1.m_Headpt - objSpkr2.m_Headpt).Normalize(); double vecAng = Util.RTD(vec.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ)); //헤드메인교차점-헤드 벡터 XYZ HMvec = null; XYZ Z0InterPt = new XYZ(objSpkr1.m_InterPt.X, objSpkr1.m_InterPt.Y, 0); HMvec = (Z0InterPt - Z0Headpt1).Normalize(); //HMvec = (objSpkr1.m_InterPt - objSpkr1.m_Headpt).Normalize(); //jpt1 = objSpkr1.m_Headpt; //jpt2 = objSpkr2.m_Headpt; jpt1 = Z0Headpt1; jpt2 = Z0Headpt2; ang1 = vecAng; List linePtlst = new List(); //두개의 헤드가 틀어진 경우 if (!((Math.Abs(ang1 - 0.0) < 0.01) || (Math.Abs(ang1 - 360.0) < 0.01)) && !(Math.Abs(ang1 - 90.0) < 0.01) && !(Math.Abs(ang1 - 180.0) < 0.01) && !(Math.Abs(ang1 - 270.0) < 0.01)) { 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 = Util.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 = Util.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; XYZ newpt110 = new XYZ(pt110.X, pt110.Y, Unit.MMToFeet(BranchHgt)); XYZ newpt2 = new XYZ(pt2.X, pt2.Y, Unit.MMToFeet(BranchHgt)); //틀어진 점 구할 때 거리가 헤드에 적용될 관경의 3배 거리보다 작을 경우 리턴 if (newpt110.DistanceTo(newpt2) < Unit.MMToFeet(headDiaLst.ElementAt(DiaCnt) * 2.0)) { MessageBox.Show("배관 연결할 거리가 나오지 않습니다."); linePtlst = null; return linePtlst; } if (sp_in == 1) { linePtlst.Add(newpt110); linePtlst.Add(newpt2); } else { linePtlst.Add(newpt2); linePtlst.Add(newpt110); } } //sp_hd++; return linePtlst; } /// /// 캡포인트 구하기. /// /// 메인관에서 가장 먼 헤드 /// 대화상자 헤드 간격띄우기 /// 대화상자 캡까지의 간격 /// public XYZ GetCAPpoint(ObjSprinKler FirstObjSpkr, double BranchHgt, 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, Unit.MMToFeet(BranchHgt)); return newCapPt; } /// /// 메인 연결될 가지파이프 /// /// 메인관에 가장 가까운 헤드 /// 대화상자 헤드 간격띄우기 /// public XYZ GetMain2LastpipePoint(ObjSprinKler LastObjSpkr, double BranchHgt) { //헤드간격 띄우기 값 적용 XYZ newInterPt = new XYZ(LastObjSpkr.m_InterPt.X, LastObjSpkr.m_InterPt.Y, Unit.MMToFeet(BranchHgt)); //XYZ newHeadPt = new XYZ(LastObjSpkr.m_Headpt.X, LastObjSpkr.m_Headpt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset)); return newInterPt; } /// /// 하향식 틀어진 가지관 등 점 구하기. /// /// 첫번째 헤드 /// 두번째 헤드 /// 대화상자 헤드 간격띄우기 /// 틀어진 헤드 작도점 1,2로 나뉘는 변수 /// 헤드가 몇번째 관경을 적용하는지 나타내는 변수 /// 헤드 관경 리스트 /// public List DownSPJOIN(ObjSprinKler objSpkr1, ObjSprinKler objSpkr2, double BranchHeight, ref int sp_in, int DiaCnt, List headDiaLst) { doc.Regenerate(); 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 = null, jpt2 = null; siz15 = Unit.MMToFeet(300); XYZ Z0Headpt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, 0); XYZ Z0Headpt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, 0); vec = (Z0Headpt1 - Z0Headpt2).Normalize(); //vec = (objSpkr1.m_Headpt - objSpkr2.m_Headpt).Normalize(); double vecAng = Util.RTD(vec.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ)); //헤드메인교차점-헤드 벡터 XYZ HMvec = null; XYZ Z0InterPt = new XYZ(objSpkr1.m_InterPt.X, objSpkr1.m_InterPt.Y, 0); XYZ Z0SepaPt1 = new XYZ(objSpkr1.SeparateionPt.X, objSpkr1.SeparateionPt.Y, 0); XYZ Z0SepaPt2 = new XYZ(objSpkr2.SeparateionPt.X, objSpkr2.SeparateionPt.Y, 0); HMvec = (Z0InterPt - Z0SepaPt1).Normalize(); jpt1 = Z0SepaPt1; jpt2 = Z0SepaPt2; ang1 = vecAng; List linePtlst = new List(); //두개의 헤드가 틀어진 경우 if (!((Math.Abs(ang1 - 0.0) < 0.001) || (Math.Abs(ang1 - 360.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 = Util.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 = Util.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; //Util.Pyosi(doc, pt110); //Util.Pyosi(doc, pt2); XYZ newHeadPt1 = null, newHeadPt2 = null; //헤드간격 띄우기 값 적용 newHeadPt1 = new XYZ(objSpkr1.SeparateionPt.X, objSpkr1.SeparateionPt.Y, Unit.MMToFeet(BranchHeight)); newHeadPt2 = new XYZ(objSpkr2.SeparateionPt.X, objSpkr2.SeparateionPt.Y, Unit.MMToFeet(BranchHeight)); XYZ newpt110 = new XYZ(pt110.X, pt110.Y, Unit.MMToFeet(BranchHeight)); XYZ newpt2 = new XYZ(pt2.X, pt2.Y, Unit.MMToFeet(BranchHeight)); //틀어진 점 구할 때 거리가 헤드에 적용될 관경의 3배 거리보다 작을 경우 리턴 if (newpt110.DistanceTo(newpt2) < Unit.MMToFeet(headDiaLst.ElementAt(DiaCnt) * 2.0)) { MessageBox.Show("배관 연결할 거리가 나오지 않습니다."); linePtlst = null; return linePtlst; } if (sp_in == 1) { linePtlst.Add(newpt110); linePtlst.Add(newpt2); } else { linePtlst.Add(newpt2); linePtlst.Add(newpt110); } } //sp_hd++; return linePtlst; } /// /// 하향식 캡포인트 구하기. /// /// 메인관에서 가장 먼 헤드 /// 대화상자 헤드 간격띄우기 /// 대화상자 캡까지의 간격 /// public XYZ DownGetCAPpoint(ObjSprinKler FirstObjSpkr, double BranchHeight, double CapDist) { //메인-헤드 방향 벡터 XYZ MHvec = (FirstObjSpkr.SeparateionPt - FirstObjSpkr.m_InterPt).Normalize(); //헤드-캡까지의 간격(사용자입력값)만큼 떨어진 점 구하기. XYZ CapPt = Util.Polar(FirstObjSpkr.SeparateionPt, MHvec, Unit.MMToFeet(CapDist)); //헤드간격 띄우기 값 적용 XYZ newCapPt = new XYZ(CapPt.X, CapPt.Y, Unit.MMToFeet(BranchHeight)); return newCapPt; } /// /// 하향식 메인 연결될 가지파이프 /// /// 메인관에 가장 가까운 헤드 /// 대화상자 헤드 간격띄우기 /// public XYZ DownGetMain2LastpipePoint(ObjSprinKler LastObjSpkr, double BranchHeight) { //헤드간격 띄우기 값 적용 XYZ newInterPt = new XYZ(LastObjSpkr.m_InterPt.X, LastObjSpkr.m_InterPt.Y, Unit.MMToFeet(BranchHeight)); //XYZ newHeadPt = new XYZ(LastObjSpkr.m_Headpt.X, LastObjSpkr.m_Headpt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset)); return newInterPt; } /////////////////////////생성 함수//////////////////////////// /// /// 가지관과 상향식 헤드 T연결 /// /// 헤드 /// 가지관 /// public List 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; XYZ HeadPtZ0 = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, 0); XYZ interPtZ0 = new XYZ(interPt.X, interPt.Y, 0); double H2InterDist = interPtZ0.DistanceTo(HeadPtZ0); //헤드와 배관의 가까운점이 이격 거리보다 클 때 실행X if (H2InterDist > Unit.MMToFeet(0.1)) return null; List pipeIdLst = new List(); //헤드와 배관의 가까운점이 배관의 시작 또는 끝점일 경우 실행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; //가지관 자르기 m_divideElemId = PlumbingUtils.BreakCurve(doc, BranchPipe.Id, interPt); Pipe divideBranchPipe = doc.GetElement(m_divideElemId) as Pipe; Pipe Headpipe = CreateHeadPipe(objSprinKler, interPt, BranchPipe); pipeIdLst.Add(m_divideElemId); pipeIdLst.Add(BranchPipe.Id); 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); } return pipeIdLst; } /// /// 가지관과 하향식 헤드 T연결 /// /// 헤드 /// 가지관 /// 헤드 간격띄우기 /// 이격거리 /// 헤드와 연결될 배관 종류// 0 = 배관 / 1 = 플렉시블 배관 /// public List CreatePipeT(ObjSprinKler objSprinKler, Pipe BranchPipe, double HeadOffsetDist, double ConnectDist, double BranchHeight, int Mode) { Line pipeline = (BranchPipe.Location as LocationCurve).Curve as Line; IntersectionResult intersection = pipeline.Project(objSprinKler.m_Headpt); XYZ interPt = intersection.XYZPoint; XYZ ZHeadPt = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, interPt.Z); XYZ HeadPtZ0 = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, 0); XYZ interPtZ0 = new XYZ(interPt.X, interPt.Y, 0); double H2InterDist = interPtZ0.DistanceTo(HeadPtZ0); double dd = Unit.FeetToMM(interPtZ0.DistanceTo(HeadPtZ0)); //MessageBox.Show("" + Unit.FeetToMM(interPt.DistanceTo(ZHeadPt))); //헤드와 배관의 가까운점이 이격 거리보다 클 때 실행X if (Math.Abs(Unit.MMToFeet(ConnectDist) - H2InterDist) > Unit.MMToFeet(10)) return null; //헤드와 배관의 가까운점이 배관의 시작 또는 끝점일 경우 실행X //if (interPt.IsAlmostEqualTo(pipeline.GetEndPoint(0), Unit.MMToFeet(0.01)) // || interPt.IsAlmostEqualTo(pipeline.GetEndPoint(1), Unit.MMToFeet(0.01))) return null; List pipeIdLst = new List(); ElementId m_divideElemId = null; //가지관 자르기 m_divideElemId = PlumbingUtils.BreakCurve(doc, BranchPipe.Id, interPt); Pipe divideBranchPipe = doc.GetElement(m_divideElemId) as Pipe; //헤드의 z값을 이격거리된 점으로 변경 XYZ NewHeadPt = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, Unit.MMToFeet(BranchHeight + HeadOffsetDist)); XYZ NewInterPt = new XYZ(interPt.X, interPt.Y, Unit.MMToFeet(BranchHeight + HeadOffsetDist)); //분기 배관에 T작도할 파이프 생성 및 헤드에 파이프 연결 루틴 Pipe Headpipe = CreateHeadConnectPipe(objSprinKler, interPt, NewHeadPt, NewInterPt, Mode); //Pipe Headpipe = CreateHeadPipe(objSprinKler, interPt, BranchPipe); pipeIdLst.Add(m_divideElemId); pipeIdLst.Add(BranchPipe.Id); 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); } return pipeIdLst; } /// /// T연결에 필요한 분기배관 생성 /// /// 헤드 /// T연결할 포인트와 헤드점으로 파이프생성 /// 가지배관의 타입을 가져오기위해 /// //메인관 시스템타입 /// //메인관 레벨 /// public Pipe CreateHeadPipe(ObjSprinKler objSpkr, XYZ breakPt, Pipe BranchPipe) { //Level level = doc.ActiveView.GenLevel; Pipe headPipe = Pipe.Create(doc, MainSystemTypeId, BranchPipe.GetTypeId(), MainLevelId, 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; } /// /// 하향식 T연결에 필요한 분기배관 생성 및 헤드에 연결 /// /// 헤드 /// T연결할 포인트와 헤드점으로 파이프생성 /// //이격 거리 파이프 시작점 /// //이격 거리 파이프 끝점 /// 헤드와 연결될 배관 종류// 0 = 배관 / 1 = 플렉시블 배관 /// public Pipe CreateHeadConnectPipe(ObjSprinKler objSpkr, XYZ breakPt, XYZ NewHeadPt, XYZ NewInterPt, int Mode) { //D1 파이프 생성 List D2Lst = new List(); D2Lst.Add(breakPt); D2Lst.Add(NewInterPt); List D1Pipe = Util.CreatePipe(uiapp, doc, D2Lst, MainSystemTypeId, MainPipeTypeId, MainLevelId); //D2 파이프 생성 D2Lst.Clear(); D2Lst.Add(NewInterPt); D2Lst.Add(NewHeadPt); List D2Pipe = Util.CreatePipe(uiapp, doc, D2Lst, MainSystemTypeId, MainPipeTypeId, MainLevelId); //헤드 커넥터 파이프 생성 D2Lst.Clear(); D2Lst.Add(NewHeadPt); D2Lst.Add(objSpkr.m_Headpt); List FPLst = new List(); FPLst.Add(objSpkr.m_Headpt); List HPipe = Util.CreatePipe(uiapp, doc, D2Lst, MainSystemTypeId, MainPipeTypeId, MainLevelId); //엘보 피팅 Connector Con1Sp = null, Con1Ep = null, Con2Sp = null, Con2Ep = null; Util.GetStartEndConnector(D1Pipe.First(), ref Con1Sp, ref Con1Ep); Util.GetStartEndConnector(D2Pipe.First(), ref Con2Sp, ref Con2Ep); Util.ElbowFitting(doc, Con1Ep, Con2Sp); Util.GetStartEndConnector(D2Pipe.First(), ref Con1Sp, ref Con1Ep); Util.GetStartEndConnector(HPipe.First(), ref Con2Sp, ref Con2Ep); FamilyInstance ElbowFam = Util.ElbowFitting(doc, Con1Ep, Con2Sp); //Util.Pyosi(doc, Con2Sp.Origin, 0); //헤드와 파이프 연결 if (Con2Ep.IsConnected == false) { Con2Ep.Radius = Unit.MMToFeet(25 / 2.0); //reducerFam = doc.Create.NewTransitionFitting(Con2Ep, objSpkr.HeadCon); Con2Ep.ConnectTo(objSpkr.HeadCon); } //플렉시블 배관이 선택된 경우 배관을 지우고 새로 만듬. if (Mode == 1) { doc.Delete(HPipe.First().Id); doc.Regenerate(); List elbowConLst = Util.GetElementConnectors(ElbowFam); foreach (Connector con in elbowConLst) { //플렉시블과 연결할 커넥터 찾기. if (con.IsConnected == false) { FPLst.Add(con.Origin); } } //플렉시블 작도 List FlexPipe = Util.CreateFlexPipe(uiapp, doc, FPLst, MainSystemTypeId, MainPipeTypeId, MainLevelId); Util.GetStartEndConnector(FlexPipe.First(), ref Con2Sp, ref Con2Ep); FlexPipe.First().StartTangent = objSpkr.HeadCon.CoordinateSystem.BasisZ; objSpkr.HeadCon.ConnectTo(Con2Sp); foreach (Connector con in elbowConLst) { //플렉시블과 연결할 커넥터 찾기. if (con.Origin.IsAlmostEqualTo(Con2Ep.Origin, Unit.MMToFeet(0.01))) { FlexPipe.First().EndTangent = con.CoordinateSystem.BasisZ.Negate(); con.ConnectTo(Con2Ep); } } } return D1Pipe.First(); } /// /// 캡 생성 /// /// 캡 배치할 커넥터 public void CreateCap(Connector baseCon, ElementId mainPipeTypeId) { PipeType pipeType = doc.GetElement(mainPipeTypeId) as PipeType; if (pipeType != null) { //파이프의 라우팅된 패밀리 심볼 구하기 FamilySymbol capSymbol = Util.GetSymbol_RoutingPreference(doc, pipeType, RoutingPreferenceRuleGroupType.Caps); if (capSymbol != null) { //캡 생성 FamilyInstance fi = doc.Create.NewFamilyInstance(baseCon.Origin, capSymbol, StructuralType.NonStructural); doc.Regenerate(); //가지관에 맞게 캡 돌려서 커넥터 연결하기 Util.MatchingRotateElement(doc, baseCon.Owner, fi); List CapconLst = Util.GetElementConnectors(fi); CapconLst.First().Radius = baseCon.Radius; } } } /// /// 가지관 끝에서 메인관으로 수직인 파이프 작도 /// /// 메인 배관 /// 가지관 끝에서 메인관으로 수직인 커넥터 /// public Pipe CreatePipeFromNearPt(Element MainElement, Connector EpConnector) { Line pipeline = (MainElement.Location as LocationCurve).Curve as Line; XYZ interPt = Util.GetPointOnLine(pipeline, EpConnector.Origin); //파이프 작도할 점 List DrawPtLst = new List(); DrawPtLst.Add(EpConnector.Origin); DrawPtLst.Add(interPt); //파이프 생성 List NewPipe = Util.CreatePipe(uiapp, doc, DrawPtLst, MainSystemTypeId, MainPipeTypeId, MainLevelId); List newConnectors = Util.GetElementConnectors(NewPipe.First()); return NewPipe.First(); } /// /// T와 레듀셔 사이에 파이프 생성 /// /// Tee 패밀리 인스턴스 /// T와 레듀셔 사이에 생성할 파이프 길이 public void CreatePipeBetweenTeeAndReducer(FamilyInstance familyTee, double Interval) { List TeeConLst = Util.GetElementConnectors(familyTee); foreach (Connector TeeCon in TeeConLst) { //Tee 커넥터에 붙어있는 객체 Connector NextCon = Util.GetNextElementConnector(TeeCon); if (NextCon == null) continue; bool b_Reducer = Util.GetFamilyPartType(NextCon, PartType.Transition); //Tee 커넥터에 붙어있는 객체가 레듀셔 일 때만 작업 if (b_Reducer) { Connector NextOtherCon = Util.GetOtherConnector(NextCon); Connector PipeCon = Util.GetNextElementConnector(NextOtherCon); //레듀셔 연결 끊고 레듀셔 삭제 TeeCon.DisconnectFrom(NextCon); doc.Delete(NextCon.Owner.Id); //파이프 생성하기 위해 위치 조정 PipeCon.Origin = Util.Polar(PipeCon.Origin, TeeCon.Origin, PipeCon.Origin, Unit.MMToFeet(Interval)); //Tee에 새로운 파이프 생성 XYZ ReducerPt = Util.Polar(TeeCon.Origin, TeeCon.Origin, PipeCon.Origin, Unit.MMToFeet(Interval)); List ReducerPtLst = new List(); ReducerPtLst.Add(TeeCon.Origin); ReducerPtLst.Add(ReducerPt); List NewPipeLst = Util.CreatePipe(uiapp, doc, ReducerPtLst, MainSystemTypeId, MainPipeTypeId, MainLevelId); List newPipeCons = Util.GetElementConnectors(NewPipeLst.First()); //Tee 관경으로 변경 newPipeCons.First().Radius = TeeCon.Radius; //새 파이프와 이동한 파이프 레듀셔로 연결 foreach (Connector NewCon in newPipeCons) { if (NewCon.Origin.IsAlmostEqualTo(ReducerPt, Unit.MMToFeet(0.01))) creDoc.NewTransitionFitting(NewCon, PipeCon); else if (NewCon.Origin.IsAlmostEqualTo(TeeCon.Origin, Unit.MMToFeet(0.01))) TeeCon.ConnectTo(NewCon); //Tee와 새 파이프 커넥터가 연결되어 있지 않아 수정.//20200208 } } } } /////////////////////////연결 루틴//////////////////////////// /// /// 상향식 헤드와 파이프 연결 /// /// 헤드 리스트 /// 헤드와 연결될 파이프리스트 /// 헤드 관경리스트 /// public List ConnectHead2pipe(List sprinKlers, List pipes, List HeadDiaLst) { Pipe pipe = pipes.First(); List PipeIdLst = new List(); for (int i = 0; i < sprinKlers.Count(); i++) { List DividePipeIDLst = new List(); ObjSprinKler obj = sprinKlers.ElementAt(i); DividePipeIDLst = CreatePipeT(obj, pipe); if (DividePipeIDLst != null) { foreach (ElementId id in DividePipeIDLst) { if (PipeIdLst.Contains(id) == false) PipeIdLst.Add(id); } pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프 } else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행 { foreach (Pipe pp in pipes) { DividePipeIDLst = CreatePipeT(obj, pp); if (DividePipeIDLst != null) { foreach (ElementId id in DividePipeIDLst) { if (PipeIdLst.Contains(id) == false) PipeIdLst.Add(id); } pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프 break; } else { if (PipeIdLst.Contains(pp.Id) == false) PipeIdLst.Add(pp.Id); } } } } Pipe DivideFirstPipe = doc.GetElement(PipeIdLst.First()) as Pipe; //객체 따로 리스트 저장 List ElemLst = getFamilyAndPipe(DivideFirstPipe); ApplyDiameter(ElemLst, HeadDiaLst); doc.Regenerate(); ApplyReducer(ElemLst, 100); //ApplyTeeDiameter(ElemLst, HeadDiaLst); //첫번째 파이프 시작점에 캡부착 if (doc.GetElement(ElemLst.First()) is Pipe) { Connector SpCon = null, epCon = null; Util.GetStartEndConnector((doc.GetElement(ElemLst.First()) as Pipe), ref SpCon, ref epCon); //캡 생성 CreateCap(SpCon, MainPipeTypeId); } return ElemLst;//객체 리스트 넘겨주기(메인관 기준 왼쪽 오른쪽 끝을 이어주기 위해) } /// /// 하향식 헤드와 파이프 연결 /// /// 헤드 리스트 /// 헤드와 연결될 파이프리스트 /// 헤드 관경리스트 /// 헤드와 연결될 배관 종류// 0 = 배관 / 1 = 플렉시블 배관 /// public List DownConnectHead2pipe(List sprinKlers, List pipes, List HeadDiaLst, double HeadOffsetDist, double ConnectDist, double BranchHeight, int Mode) { Pipe pipe = pipes.First(); List PipeIdLst = new List(); for (int i = 0; i < sprinKlers.Count(); i++) { List DividePipeIDLst = new List(); ObjSprinKler obj = sprinKlers.ElementAt(i); DividePipeIDLst = CreatePipeT(obj, pipe, HeadOffsetDist, ConnectDist, BranchHeight, Mode); if (DividePipeIDLst != null) { foreach (ElementId id in DividePipeIDLst) { if (PipeIdLst.Contains(id) == false) PipeIdLst.Add(id); } pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프 } else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행 { foreach (Pipe pp in pipes) { DividePipeIDLst = CreatePipeT(obj, pp, HeadOffsetDist, ConnectDist, BranchHeight, Mode); if (DividePipeIDLst != null) { foreach (ElementId id in DividePipeIDLst) { if (PipeIdLst.Contains(id) == false) PipeIdLst.Add(id); } pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프 break; } else { if (PipeIdLst.Contains(pp.Id) == false) PipeIdLst.Add(pp.Id); } } } } Pipe DivideFirstPipe = doc.GetElement(PipeIdLst.First()) as Pipe; //객체 따로 리스트 저장 List ElemLst = getFamilyAndPipe(DivideFirstPipe); ApplyDiameter(ElemLst, HeadDiaLst); doc.Regenerate(); //ApplyReducer(ElemLst, 100); //첫번째 파이프 시작점에 캡부착 if (doc.GetElement(ElemLst.First()) is Pipe) { Connector SpCon = null, epCon = null; Util.GetStartEndConnector((doc.GetElement(ElemLst.First()) as Pipe), ref SpCon, ref epCon); //캡 생성 CreateCap(SpCon, MainPipeTypeId); } return ElemLst;//객체 리스트 넘겨주기(메인관 기준 왼쪽 오른쪽 끝을 이어주기 위해) } //메인관 가지관 연결 public List MainConnectBranch(Element MainElem, Element LeftElem, Element RightElem) { Line MainLine = ((MainElem as Pipe).Location as LocationCurve).Curve as Line; List TeeBranchPipeLst = new List(); try { //한쪽만 존재할 때 if (LeftElem == null || RightElem == null) { Connector SpCon = null, EpCon = null; Pipe BranchPipe = null; if (LeftElem != null) { Util.GetStartEndConnector(LeftElem as Pipe, ref SpCon, ref EpCon); BranchPipe = LeftElem as Pipe; } else if (RightElem != null) { Util.GetStartEndConnector(RightElem as Pipe, ref SpCon, ref EpCon); BranchPipe = RightElem as Pipe; } Pipe NewPipe = CreatePipeFromNearPt(MainElem, EpCon); //파이프 엘보 관경 맞추고 연결 Connector NewSpCon = null, NewEpCon = null; Util.GetStartEndConnector(NewPipe, ref NewSpCon, ref NewEpCon); NewSpCon.Radius = EpCon.Radius; Util.ElbowFitting(doc, EpCon, NewSpCon); TeeBranchPipeLst.Add(NewPipe); } //양쪽 존재할 때 else if (LeftElem != null && RightElem != null) { Connector LeftSpCon = null, LeftEpCon = null; Connector RightSpCon = null, RightEpCon = null; Util.GetStartEndConnector(LeftElem as Pipe, ref LeftSpCon, ref LeftEpCon); Util.GetStartEndConnector(RightElem as Pipe, ref RightSpCon, ref RightEpCon); //가지관 끝에서 메인관까지 가까운점 구하기 Line pipeline = (MainElem.Location as LocationCurve).Curve as Line; XYZ interPt = Util.GetPointOnLine(pipeline, LeftEpCon.Origin); //양쪽 가지관의 끝 커넥터가 메인관과 수직점이 같을 경우 XYZ LeftInterPt = Util.GetPointOnLine(pipeline, LeftEpCon.Origin); XYZ RightInterPt = Util.GetPointOnLine(pipeline, RightEpCon.Origin); if (LeftInterPt.IsAlmostEqualTo(RightInterPt, Unit.MMToFeet(0.01))) { Connector NewSpCon = null, NewEpCon = null; Pipe leftNewPipe = CreatePipeFromNearPt(MainElem, LeftEpCon); Util.GetStartEndConnector(leftNewPipe, ref NewSpCon, ref NewEpCon); //생성된 파이프 관경 = 양쪽 중 큰 관경으로 if (LeftEpCon.Radius > RightEpCon.Radius) NewEpCon.Radius = LeftEpCon.Radius; else NewEpCon.Radius = RightEpCon.Radius; FamilyInstance familyTee = null; familyTee = Util.CreateTee(creDoc, LeftEpCon, RightEpCon, NewSpCon); //왼쪽 오른쪽 관경이 다르면 레듀셔와 Tee 사이 간격 띄우기 if (!(Math.Abs(LeftEpCon.Radius - RightEpCon.Radius) < Unit.MMToFeet(0.01))) { CreatePipeBetweenTeeAndReducer(familyTee, 100); } TeeBranchPipeLst.Add(leftNewPipe); } else//Tee가 생성되지 않았을 때(끝 점이 틀어져 있을 때 따로 엘보 작도) { //틀어진 거리가 관경보다 작을 때 작도 X if (LeftEpCon.Radius > RightEpCon.Radius) { if (LeftInterPt.DistanceTo(RightInterPt) < LeftEpCon.Radius * 4) { MessageBox.Show("메인관에 Tee를 연결할 거리가 나오지 않습니다.", "오류"); return TeeBranchPipeLst; } } else { if (LeftInterPt.DistanceTo(RightInterPt) < RightEpCon.Radius * 4) { MessageBox.Show("메인관에 Tee를 연결할 거리가 나오지 않습니다.", "오류"); return TeeBranchPipeLst; } } Connector leftNewspCon = null, leftNewepCon = null, rightNewspCon = null, rightNewepCon = null; ElementId MainElemID = MainElem.Id; //왼쪽 파이프 엘보 관경 맞추고 연결 Pipe leftNewPipe = CreatePipeFromNearPt(MainElem, LeftEpCon); Util.GetStartEndConnector(leftNewPipe, ref leftNewspCon, ref leftNewepCon); leftNewspCon.Radius = LeftEpCon.Radius; Util.ElbowFitting(doc, LeftEpCon, leftNewspCon); //오른쪽 파이프 엘보 관경 맞추고 연결 Pipe rightNewPipe = CreatePipeFromNearPt(MainElem, RightEpCon); Util.GetStartEndConnector(rightNewPipe, ref rightNewspCon, ref rightNewepCon); rightNewspCon.Radius = RightEpCon.Radius; Util.ElbowFitting(doc, RightEpCon, rightNewspCon); if (leftNewepCon.Origin.DistanceTo(MainLine.GetEndPoint(1)) < rightNewepCon.Origin.DistanceTo(MainLine.GetEndPoint(1))) { TeeBranchPipeLst.Add(leftNewPipe); TeeBranchPipeLst.Add(rightNewPipe); } else { TeeBranchPipeLst.Add(rightNewPipe); TeeBranchPipeLst.Add(leftNewPipe); } } } } catch (Exception e) { //MessageBox.Show("" + e); } ////나뉜 메인관 리턴해줘야 함. return TeeBranchPipeLst; } //시작객체부터 객체 없을 때까지 리스트에 담기. public List getFamilyAndPipe(Pipe FirstPipe) { Connector pipeSpCon = null, pipeEpCon = null; //시작 끝 커넥터 구하기 Util.GetStartEndConnector(FirstPipe, ref pipeSpCon, ref pipeEpCon); List elemIdLst = new List(); XYZ flowVec = (pipeEpCon.Origin - pipeSpCon.Origin).Normalize(); XYZ ReVec = (pipeSpCon.Origin - pipeEpCon.Origin).Normalize(); Connector CurCon = pipeEpCon; elemIdLst.Add(CurCon.Owner.Id); while (true) { Connector NextCon = Util.GetNextElementConnector(CurCon); if (NextCon == null) break; //Pyosi(NextCon.Origin, 1); Connector NextOtherCon = null; if (Util.GetFamilyPartType(NextCon, PartType.Tee)) NextOtherCon = Util.GetClosestConnector(NextCon, flowVec, ReVec);//커넥터 3개이상일 때 반대쪽 커넥터 찾기 else NextOtherCon = Util.GetOtherConnector(NextCon);//커넥터 2개일 때 반대쪽 커넥터찾기 CurCon = NextOtherCon; elemIdLst.Add(CurCon.Owner.Id); }//while end return elemIdLst; } //관경 적용 public void ApplyDiameter(List ElementIdLst, List HeadDiaLst) { List DiaLst = HeadDiaLst; int DiaCnt = 0; for (int i = 0; i < ElementIdLst.Count(); i++) { double CurDia = DiaLst.ElementAt(DiaCnt); double NextDia = DiaLst.ElementAt(DiaCnt + 1); List Connectors = Util.GetElementConnectors(doc.GetElement(ElementIdLst[i])); Connectors.First().Radius = Unit.MMToFeet(CurDia / 2.0); if (Util.GetFamilyPartType(Connectors.First(), PartType.Tee)) { DiaCnt++; Connectors.First().Radius = Unit.MMToFeet(NextDia / 2.0); doc.Regenerate(); } } } //레듀셔 적용 public void ApplyReducer(List ElementIdLst, double T2ReducerDist) { Pipe firstPipe = doc.GetElement(ElementIdLst.First()) as Pipe; XYZ sp = null, ep = null; Util.GetStartEndPoint(firstPipe, ref sp, ref ep); List TeeLst = new List(); //Tee만 추출 for (int i = 0; i < ElementIdLst.Count(); i++) { Element elem = doc.GetElement(ElementIdLst.ElementAt(i)); List Connectors = Util.GetElementConnectors(elem); if (elem is FamilyInstance && Util.GetFamilyPartType(Connectors.First(), PartType.Tee)) TeeLst.Add(ElementIdLst.ElementAt(i)); } //레듀셔가 붙은 커넥터만 찾아 작업 foreach (ElementId id in TeeLst) { Element elem = doc.GetElement(id); List TeeConLst = Util.GetElementConnectors(elem); Connector ReducerCon = null; foreach(Connector con in TeeConLst) { Connector nextcon = Util.GetNextElementConnector(con); if (nextcon != null) { Connector otherCon = Util.GetOtherConnector(nextcon); Util.Pyosi(doc, otherCon.Origin, 0); } } // foreach (Connector TeeCon in TeeConLst) // { // Connector NextCon = Util.GetNextElementConnector(TeeCon); // double ddd = Unit.FeetToMM(TeeCon.Radius); // //레듀셔가 붙은 커넥터 찾기 // if (NextCon != null && Util.GetFamilyPartType(NextCon, PartType.Transition)) // { // //레듀셔 커넥터의 관경이 작은쪽만 찾기(큰쪽은 Tee 가지커넥터를 찾을 수도 있어서) // List ReducerConLst = Util.GetElementConnectors(NextCon.Owner); // if (NextCon.Origin.IsAlmostEqualTo(ReducerConLst[0].Origin, Unit.MMToFeet(0.01))) // { // if (NextCon.Radius > ReducerConLst[1].Radius) // continue; // else // ReducerCon = NextCon; // } // else if (NextCon.Origin.IsAlmostEqualTo(ReducerConLst[1].Origin, Unit.MMToFeet(0.01))) // { // if (NextCon.Radius > ReducerConLst[0].Radius) // continue; // else // ReducerCon = NextCon; // } // // if (ReducerCon != null) // { // Connector RedOtherCon = Util.GetOtherConnector(ReducerCon); // //레듀셔에 붙은 파이프 커넥터 구하기. // Connector PipeCon = Util.GetNextElementConnector(RedOtherCon); // // //레듀셔 다시 연결하기때문에 지움 // doc.Delete(ReducerCon.Owner.Id); // doc.Regenerate(); // //파이프 위치 이동 // PipeCon.Origin = Util.Polar(PipeCon.Origin, sp, ep, Unit.MMToFeet(T2ReducerDist)); // // //Tee에 파이프 새로 생성 // XYZ ReducerPt = Util.Polar(TeeCon.Origin, sp, ep, Unit.MMToFeet(T2ReducerDist)); // List ReducerPtLst = new List(); // ReducerPtLst.Add(TeeCon.Origin); ReducerPtLst.Add(ReducerPt); // List newPipeLst = Util.CreatePipe(uiapp, doc, ReducerPtLst, MainSystemTypeId, MainSystemTypeId, MainLevelId); // List newPipeCons = Util.GetElementConnectors(newPipeLst[0]); // newPipeCons.First().Radius = TeeCon.Radius; // //새 파이프와 이동한 파이프 레듀셔로 연결 // foreach (Connector con in newPipeCons) // { // if (con.Origin.IsAlmostEqualTo(ReducerPt, Unit.MMToFeet(0.01))) // { // creDoc.NewTransitionFitting(con, PipeCon); // } // } // } // } // }//Tee에 붙은 레듀셔 커넥터 구하기 end } } //T 관경적용 public void ApplyTeeDiameter(ListElementIdLst, List HeadDiaLst) { foreach (ElementId id in ElementIdLst) { Element elem = doc.GetElement(id); List conLst = Util.GetElementConnectors(elem); Util.Pyosi(doc, conLst.First().Origin, 0); } } } }