using Autodesk.Revit.DB; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using KMBIM.Utils; using KMBIM.Revit.Tools.Cmd.PipeConnection; using KMBIM.Revit.Tools.Utils; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using KDCS.Utils; namespace KMBIM.Revit.Tools.Cmd.Piping { public partial class FormPipeConnector : System.Windows.Forms.Form { private UIApplication m_UiApp; private UIDocument m_rvtUIDoc; private Document m_rvtDoc; private Autodesk.Revit.ApplicationServices.Application m_rvtApp; public Autodesk.Revit.UI.UIDocument uidoc { get; set; } private EnumPipeConnectType m_PipeConnectType; private RequestHandlerPipeConnect m_Handler; private ResolverForPipeConnect m_Resolver; private ExternalEvent m_ExEvent; private int m_LineStyle = (int)BuiltInCategory.OST_HiddenLines; private Dictionary> dictPointList = null; private Element baseElement = null; private Element targetElement = null; private Connector baseConnector = null; private Connector targetConnector = null; public FormPipeConnector(UIApplication uiapp, ExternalEvent exEvent, RequestHandlerPipeConnect handler) { InitializeComponent(); m_UiApp = uiapp; m_rvtApp = uiapp.Application; m_rvtUIDoc = uiapp.ActiveUIDocument; m_rvtDoc = m_rvtUIDoc.Document; dictPointList = new Dictionary>(); m_Handler = handler; m_ExEvent = exEvent; } /// /// Control enabler / disabler /// /// private void EnableCommands(bool status) { foreach (System.Windows.Forms.Control ctrl in this.Controls) { ctrl.Enabled = status; } if (!status) { //this.buttonCancel.Enabled = true; } } // External Event Handler로부터 호출된다. public void WakeUp() { EnableCommands(true); } private void buttonPrev_Click(object sender, EventArgs e) { Dictionary> dictRoute = new Dictionary>(); m_Resolver.MovePrevious(); m_Resolver.GetRoute(ref dictRoute); labelRouteNum.Text = string.Format("{0}/{1}", m_Resolver.GetIndex() + 1, dictRoute.Keys.Count); m_Resolver.SetResolverMode(ResolverForPipeConnect.EnumResolverMode.Prev); Action(); } private Connector FindUnConnectedConnector(Pipe pipe) { ConnectorSet conns = pipe.ConnectorManager.Connectors; foreach (Connector conn in conns) { if(conn.IsConnected==false) return conn; } return null; } // / // / // v // ②-------① // / | /| // ③--------④ | // | ⑥-----|- ⑤ // | / | / // ⑦--------⑧ // ^ // / // / //---------------------------------------------------------------------------------------- private void GetDictRouteHHParallel(ref Connector baseConnector, ref Connector targetConnector) { Connector c1 = baseConnector; Connector c2 = targetConnector; double minDst = baseConnector.Radius * 2.5; double hgt = Math.Abs(c1.CoordinateSystem.Origin.Z - c2.CoordinateSystem.Origin.Z); // 기준 파이프의 수직 평면 생성 XYZ baseX = c1.CoordinateSystem.BasisZ.CrossProduct(XYZ.BasisZ); Plane plane1 = Plane.CreateByNormalAndOrigin(baseX, c1.CoordinateSystem.Origin); // 연결할 파이프의 무한선 생성 Line uline2 = Line.CreateUnbound(c2.CoordinateSystem.Origin, c2.CoordinateSystem.BasisZ); XYZ p1 = c2.Origin; XYZ p7 = c1.Origin; XYZ p2 = Util.Project(plane1, p1); Plane plane2 = Plane.CreateByNormalAndOrigin(c1.CoordinateSystem.BasisZ, p7); double parm; XYZ p4 = new XYZ(); if (Util.Intersect(plane2, uline2, 0.01, out p4, out parm) != Util.Plane_Line.Intersecting) { p4 = Util.Project(plane2, p1); } XYZ p3 = Util.Project(plane1, p4); Plane plane3 = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, p7); XYZ p8 = Util.Project(plane3, p4); XYZ p5 = Util.Project(plane3, p1); XYZ p6 = Util.Project(plane3, p2); XYZ mp32 = Util.Midpoint(p3, p2); XYZ mp76 = Util.Midpoint(p7, p6); XYZ mp85 = Util.Midpoint(p8, p5); XYZ mp41 = Util.Midpoint(p4, p1); Pipe basePipe = baseConnector.Owner as Pipe; Pipe targetPipe = targetConnector.Owner as Pipe; double minoffset = baseConnector.Radius * 1.2 + 0.16404199; // + 50mm(0.16404199ft) double minoffset2 = baseConnector.Radius * 4.2 + 0.16404199; // + 50mm(0.16404199ft) bool bDrawable = true; double oneinch = 0.0833333; // 1Inch=0.0833333ft if (hgt > Geo.MmToFoot(100)) { List lst0 = new List(); lst0.Add(p7); lst0.Add(mp76); lst0.Add(mp32); double dst1 = p3.DistanceTo(p4); if (dst1 > minoffset) lst0.Add(mp41); else { if (dst1 > oneinch) bDrawable = false; } lst0.Add(p1); if(bDrawable) dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst0); if (basePipe != null) { // 파이프 - 모두 // 7->3->4->1 if (p4.DistanceTo(p1) > minoffset) { List lst1 = new List(); lst1.Add(p7); lst1.Add(p3); if (lst1.Last().DistanceTo(p4) > minoffset) lst1.Add(p4); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } if (p7.DistanceTo(p8) > minoffset) { // 7-8-4-1 List lst2 = new List(); lst2.Add(p7); lst2.Add(p8); lst2.Add(p4); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } // 파이프 -> 파이프 if (targetPipe != null) { // 7-6-2-1 List lst3 = new List(); lst3.Add(p7); lst3.Add(p6); if (p2.DistanceTo(p1) > minoffset) lst3.Add(p2); lst3.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); if (p2.DistanceTo(p1) > minoffset) { // 7-6-5-1 List lst4 = new List(); lst4.Add(p7); lst4.Add(p6); lst4.Add(p5); lst4.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst4); // 7-3-2-1 List lst5 = new List(); lst5.Add(p7); lst5.Add(p3); lst5.Add(p2); lst5.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst5); // 7-8-51 List lst6 = new List(); lst6.Add(p7); lst6.Add(p8); lst6.Add(p5); lst6.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst6); } } } { if (targetPipe != null) { //패밀리-파이프 // 7->6->2->1 List lst1 = new List(); lst1.Add(p7); lst1.Add(p6); if (p1.DistanceTo(p2) > minoffset) lst1.Add(p2); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); if (p6.DistanceTo(p5) > minoffset) { // 7-6-5-1 List lst2= new List(); lst2.Add(p7); lst2.Add(p6); lst2.Add(p5); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } } else { // 패밀리-패밀리 if (p3.DistanceTo(p2) > minoffset2) { if (p3.DistanceTo(p4) > minoffset) { // 7-m76-m85-m41-1 List lst3= new List(); lst3.Add(p7); lst3.Add(mp76); lst3.Add(mp85); lst3.Add(mp41); lst3.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } } } } } else // 오르 내림 없음 { if (basePipe != null) { // 파이프 - 모두 // 7->8->1 List lst1 = new List(); lst1.Add(p7); if (p7.DistanceTo(p8) > minoffset) lst1.Add(p8); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); // 파이프 -> 파이프 if (targetPipe != null) { if (p7.DistanceTo(p8) > minoffset) { // 7-8-4-1 List lst2 = new List(); lst2.Add(p7); lst2.Add(p6); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } } } else { // 패밀리 -> 파이프 if (targetPipe != null) { // 7-6-1 List lst1 = new List(); lst1.Add(p7); if (p7.DistanceTo(p8) > minoffset) lst1.Add(p6); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } else { // 패밀리 - 패밀리 if (p3.DistanceTo(p2) > minoffset2) { // 7-m76-m85-1 List lst1 = new List(); lst1.Add(p7); lst1.Add(mp76); lst1.Add(mp85); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } } } } } // // // // ②-------① <------- // / | /| // ③--------④ | // | ⑥-----|- ⑤ // | / | / // ⑦--------⑧ // ^ // / // / //---------------------------------------------------------------------------------------- private void GetDictRouteHHOrthogonal(ref Connector baseConnector, ref Connector targetConnector) { Connector c1 = baseConnector; Connector c2 = targetConnector; double minDst = baseConnector.Radius * 2.5; double hgt = Math.Abs(c1.CoordinateSystem.Origin.Z - c2.CoordinateSystem.Origin.Z); // 기준 파이프의 수직 평면 생성 XYZ baseX = c1.CoordinateSystem.BasisZ.CrossProduct(XYZ.BasisZ); Plane plane1 = Plane.CreateByNormalAndOrigin(baseX, c1.CoordinateSystem.Origin); // 연결할 파이프의 무한선 생성 Line uline2 = Line.CreateUnbound(c2.CoordinateSystem.Origin, c2.CoordinateSystem.BasisZ); XYZ p1 = c2.Origin; XYZ p7 = c1.Origin; XYZ p2 = new XYZ(); double parm; if (Util.Intersect(plane1, uline2, 0.01, out p2, out parm) != Util.Plane_Line.Intersecting) { p2 = Util.Project(plane1, p1); } Plane plane2 = Plane.CreateByNormalAndOrigin(c1.CoordinateSystem.BasisZ, p7); XYZ p4 = Util.Project(plane2, p1); XYZ p3 = Util.Project(plane1, p4); Plane plane3 = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, p7); XYZ p8 = Util.Project(plane3, p4); XYZ p5 = Util.Project(plane3, p1); XYZ p6 = Util.Project(plane3, p2); XYZ mp32 = Util.Midpoint(p3, p2); XYZ mp76 = Util.Midpoint(p7, p6); XYZ mp85 = Util.Midpoint(p8, p5); XYZ mp14 = Util.Midpoint(p4, p1); XYZ mp21 = Util.Midpoint(p2, p1); XYZ mp34 = Util.Midpoint(p3, p4); XYZ mp78 = Util.Midpoint(p7, p8); XYZ mp65 = Util.Midpoint(p6, p5); XYZ mp2134 = Util.Midpoint(mp21, mp34); XYZ v12 = (p2 - p1).Normalize(); Pipe basePipe = baseConnector.Owner as Pipe; Pipe targetPipe = targetConnector.Owner as Pipe; double minoffset = baseConnector.Radius * 1.2 + 0.16404199; // + 50mm(0.16404199ft) double minoffset1 = baseConnector.Radius * 2.2 + 0.16404199; // + 50mm(0.16404199ft) double minoffset2 = baseConnector.Radius * 11.0 + 0.16404199; // + 50mm(0.16404199ft) double minPipeLen = targetConnector.Radius * 6.0; if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ) == false) { MessageBox.Show("연결할 수 없습니다."); return; } if (hgt > Geo.MmToFoot(100)) { // 파이프 - 모두 if (p4.DistanceTo(p1) > minoffset) { //---------------------------------------------------------------------------- // 7-6-2-1 //---------------------------------------------------------------------------- List lst1 = new List(); if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ)) { //대상 연결점이 교차점 방향인 경우: if (!(p2.DistanceTo(p1) < minoffset && targetPipe == null)) { lst1.Add(p7); lst1.Add(p6); lst1.Add(p2); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } } else { // 대상 연결점이 교차점 방향이 아닌 경우: XYZ p14e = mp14; if (targetPipe == null) // 목표 연결점이 파이프가 아니면 { p14e = mp14 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; } lst1.Add(p7); lst1.Add(mp76); lst1.Add(mp32); lst1.Add(p14e); if (targetPipe == null) // 목표 연결점이 파이프가 아닌 경우 점 추가 { XYZ p1e = p1 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst1.Add(p1e); } lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } //---------------------------------------------------------------------------- // 7-6-5-1 //---------------------------------------------------------------------------- List lst2 = new List(); if (targetPipe != null) { // 대상연결점이 파이프인 경우 if (p2.DistanceTo(p1) > minoffset) { lst2.Add(p7); lst2.Add(p6); lst2.Add(p5); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } } else { // 대상연결점이 파이프가 아닌 경우 if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ)) { //대상 연결점이 교차점 방향인 경우: lst2.Add(p7); lst2.Add(p6); lst2.Add(mp65); lst2.Add(mp21); lst2.Add(p1); } else { // 대상 연결점이 교차점 방향이 아닌 경우: XYZ p5e = p5 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; XYZ p1e = p1 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst2.Add(p7); lst2.Add(p6); lst2.Add(p5e); lst2.Add(p1e); lst2.Add(p1); } if (lst2.Count > 2) { dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } } } if (basePipe != null) { // 기준 연결점이 파이프인 경우 if (p7.DistanceTo(p8) > minoffset1) { // 7-78-34-21-1 List lst2 = new List(); if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ)) { lst2.Add(p7); lst2.Add(mp78); lst2.Add(mp34); lst2.Add(mp21); lst2.Add(p1); } else { lst2.Add(p7); lst2.Add(mp78); lst2.Add(mp34); lst2.Add(mp2134); XYZ mp14e = mp14 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst2.Add(mp14e); XYZ p1_1 = p1 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst2.Add(p1_1); lst2.Add(p1); } dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); // 7-78-65-21-1 List lst3 = new List(); if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ)) { lst3.Add(p7); lst3.Add(mp78); lst3.Add(mp65); lst3.Add(mp21); lst3.Add(p1); } else { XYZ p78 = p8 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; XYZ p65 = p5 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; XYZ p21 = p1 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst3.Add(p7); lst3.Add(p78); lst3.Add(p65); lst3.Add(p21); lst3.Add(p1); } dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } // 파이프 -> 파이프 if (targetPipe != null) { // 7-3-2-1 List lst4 = new List(); if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ)) { // 대상 커넥터가 교차점 방향 if (p2.DistanceTo(p1) > minoffset) { lst4.Add(p7); lst4.Add(p3); lst4.Add(p2); lst4.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst4); } } else { // 대상 커넥터가 교차점 반대 방향 lst4.Add(p7); lst4.Add(p3); lst4.Add(mp32); XYZ p14e = mp14 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; XYZ p1e = p1 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst4.Add(p14e); lst4.Add(p1e); lst4.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst4); } if (p2.DistanceTo(p1) > minoffset) { // 7-3-4-1 List lst5 = new List(); lst5.Add(p7); lst5.Add(p3); lst5.Add(p4); lst5.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst5); // 7-8-4-1 List lst6 = new List(); lst6.Add(p7); lst6.Add(p8); lst6.Add(p4); lst6.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst6); // 7-8-5-1 List lst7 = new List(); lst7.Add(p7); lst7.Add(p8); lst7.Add(p5); lst7.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst7); } } else { // 파이프-패밀리 // 7-3-2-1 List lst4 = new List(); if (v12.IsAlmostEqualTo(targetConnector.CoordinateSystem.BasisZ)) { lst4.Add(p7); lst4.Add(p3); if (p2.DistanceTo(p1) > minoffset) lst4.Add(p2); lst4.Add(p1); } else { lst4.Add(p7); lst4.Add(p3); lst4.Add(mp32); XYZ p14e = mp14 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; XYZ p1e = p1 + targetConnector.CoordinateSystem.BasisZ * minPipeLen; lst4.Add(p14e); lst4.Add(p1e); lst4.Add(p1); } dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst4); if (p2.DistanceTo(p1) > minoffset1) { // 7-3-mp34-mp21-1 List lst5 = new List(); lst5.Add(p7); lst5.Add(p3); lst5.Add(mp34); lst5.Add(mp21); lst5.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst5); // 7-mp78-mp34-mp21-1 List lst6 = new List(); lst6.Add(p7); lst6.Add(mp78); lst6.Add(mp34); lst6.Add(mp21); lst6.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst6); // 7-mp78-mp65-mp21-1 List lst7 = new List(); lst7.Add(p7); lst7.Add(mp78); lst7.Add(mp65); lst7.Add(mp21); lst7.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst7); // 7-6-mp65-mp21-1 List lst8 = new List(); lst8.Add(p7); lst8.Add(p6); lst8.Add(mp65); lst8.Add(mp21); lst8.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst8); } } } { if (targetPipe == null) { // 패밀리-패밀리 double dst32 = p3.DistanceTo(p2); if (dst32 > minoffset2) { // 7-m76-m32-m41-1 List lst2 = new List(); lst2.Add(p7); lst2.Add(mp76); lst2.Add(mp32); lst2.Add(p2); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } if (dst32 > minoffset1 && p2.DistanceTo(p1) > minoffset2) { // 7-6-m65-m21-1 List lst3 = new List(); lst3.Add(p7); lst3.Add(p6); lst3.Add(mp65); lst3.Add(mp21); lst3.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } } } } else // 오르 내림 없음 { // 파이프 - 모두 // 7->6->1 if (p6.DistanceTo(p5) > minoffset) { List lst1 = new List(); lst1.Add(p7); lst1.Add(p6); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } if (basePipe != null) { // 파이프 - 모두 // 7->8->1 List lst2 = new List(); lst2.Add(p7); if (p7.DistanceTo(p8) > minoffset) lst2.Add(p8); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); // 파이프 -> 파이프 if (targetPipe != null) { if (p7.DistanceTo(p8) > minoffset) { // 7-8-4-1 List lst3 = new List(); lst3.Add(p7); lst3.Add(p8); lst3.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } } } else { // 패밀리 -> 파이프 if (targetPipe != null) { if (p7.DistanceTo(p6) > minoffset2) { // 7-m76-m85-1 List lst2 = new List(); lst2.Add(p7); lst2.Add(mp76); if (mp76.DistanceTo(mp85) > minoffset) lst2.Add(mp85); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } } else { // 패밀리 - 패밀리 if (p3.DistanceTo(p2) > minoffset2) { // 7-m76-m85-1 List lst1 = new List(); lst1.Add(p7); lst1.Add(p6); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); } } } } } // 수평-수평 private void GetDictRouteHH(ref Connector baseConnector, ref XYZ pick1, ref Connector targetConnector, ref XYZ pick2) { Connector c1 = baseConnector; Connector c2 = targetConnector; double minDst = baseConnector.Radius * 2.5; double hgt = Math.Abs(c1.CoordinateSystem.Origin.Z - c2.CoordinateSystem.Origin.Z); if (c1.CoordinateSystem.Origin.Z > c2.CoordinateSystem.Origin.Z) { Util.Swap(ref baseElement, ref targetElement); Util.Swap(ref baseConnector, ref targetConnector); Util.Swap(ref pick1, ref pick2); } if (baseConnector.CoordinateSystem.BasisZ.CrossProduct(targetConnector.CoordinateSystem.BasisZ).GetLength() > 0.9) { // 수평 - 수평(직교) //---------------------------------------------------------------------------------------- GetDictRouteHHOrthogonal(ref baseConnector, ref targetConnector); } else { // 수평 - 수평(평행) GetDictRouteHHParallel(ref baseConnector, ref targetConnector); } } /// /// 기준 파이프는 항상 수평 /// /// 수평 파이프 /// 수직 파이프 private void GetDictRouteHV(ref Connector baseConnector, ref XYZ pick1, ref Connector targetConnector, ref XYZ pick2) { if (Math.Abs(baseConnector.CoordinateSystem.BasisZ.Z) > 0.6 && Math.Abs(targetConnector.CoordinateSystem.BasisZ.Z) < 0.1) { Util.Swap(ref baseElement, ref targetElement); Util.Swap(ref baseConnector, ref targetConnector); Util.Swap(ref pick1, ref pick2); } if(baseConnector.CoordinateSystem.Origin.Z > targetConnector.CoordinateSystem.Origin.Z) GetDictRouteHVUp(ref baseConnector, ref targetConnector); else GetDictRouteHVDn(ref baseConnector, ref targetConnector); } private void GetDictRouteVV(ref Connector baseConnector, ref XYZ pick1, ref Connector targetConnector, ref XYZ pick2) { if (baseConnector.CoordinateSystem.BasisZ.Z < 0 && targetConnector.CoordinateSystem.BasisZ.Z < 0.1) { if (baseConnector.CoordinateSystem.Origin.Z > targetConnector.CoordinateSystem.Origin.Z) { Util.Swap(ref baseElement, ref targetElement); Util.Swap(ref baseConnector, ref targetConnector); Util.Swap(ref pick1, ref pick2); } GetDictRouteVDnVDn(ref baseConnector, ref targetConnector); } } // // // ②-------① // / | /| // ③--------④ | // ^ | ⑥-----|- ⑤ // / | / | /^ // / ⑦--------⑧ I // I //---------------------------------------------------------------------------------------- private void GetDictRouteHVUp(ref Connector baseConnector, ref Connector targetConnector) { //if (targetConnector.CoordinateSystem.BasisZ.Z < 0) //{ // MessageBox.Show("연결할 수 없습니다."); // return; //} // 기준 파이프의 수직 평면 생성 XYZ baseX = baseConnector.CoordinateSystem.BasisZ.CrossProduct(XYZ.BasisZ); Plane plane1 = Plane.CreateByNormalAndOrigin(baseX, baseConnector.CoordinateSystem.Origin); double parm; XYZ p5 = targetConnector.Origin; XYZ p6 = Util.Project(plane1, p5); XYZ p3 = baseConnector.Origin; Plane plane2 = Plane.CreateByNormalAndOrigin(baseConnector.CoordinateSystem.BasisY, p3); XYZ p1 = Util.Project(plane2, p5); XYZ p2 = Util.Project(plane1, p1); Plane plane3 = Plane.CreateByNormalAndOrigin(baseConnector.CoordinateSystem.BasisZ, p3); XYZ p4 = Util.Project(plane3, p1); XYZ p7 = Util.Project(plane3, p6); XYZ p8 = Util.Project(plane3, p5); double minoffset = baseConnector.Radius * 1.2 + 0.16404199; // + 50mm(0.16404199ft) double minoffset2 = baseConnector.Radius * 4.2 + 0.16404199; // + 50mm(0.16404199ft) Pipe basePipe = baseElement as Pipe; Pipe targetPipe = targetElement as Pipe; double hgt = p6.DistanceTo(p2); if (hgt > Geo.MmToFoot(100)) { string listKey = string.Empty; // 3->2->1->5 List lst1 = new List(); lst1.Add(p3); lst1.Add(p2); if (p2.DistanceTo(p1) > minoffset) lst1.Add(p1); lst1.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); if (p3.DistanceTo(p2) > minoffset2 && p2.DistanceTo(p1) > minoffset) { XYZ mp32 = Util.Midpoint(p3, p2); XYZ mp41 = Util.Midpoint(p4, p1); List lst1a = new List(); lst1a.Add(p3); lst1a.Add(mp32); lst1a.Add(mp41); lst1a.Add(p1); lst1a.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1a); } if (basePipe != null) { // 파이프 - 모두 // 3->4->1->5 if (p4.DistanceTo(p1) > minoffset) { List lst2 = new List(); lst2.Add(p3); if (lst2.Last().DistanceTo(p4) > minoffset) lst2.Add(p4); lst2.Add(p1); lst2.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } // 파이프 -> 파이프 if (targetPipe != null) { // 3->4->8->5 List lst3 = new List(); lst3.Add(p3); if (lst3.Last().DistanceTo(p4) > minoffset) lst3.Add(p4); lst3.Add(p8); lst3.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); // 3->7->6->5 List lst4 = new List(); lst4.Add(p3); if (lst4.Last().DistanceTo(p4) > minoffset) lst4.Add(p4); lst4.Add(p8); lst4.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst4); // 3->7->8->5 List lst5 = new List(); lst5.Add(p3); if (lst5.Last().DistanceTo(p4) > minoffset) lst5.Add(p4); lst5.Add(p8); lst5.Add(p5); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst5); } } else { // 패밀리 - 파이프 } } } // I // v // ②-------① // /| /| // ③--------④ | // | ⑥-----|- ⑤ // |/ | / // ⑦--------⑧ // ^ // / // / //---------------------------------------------------------------------------------------- private void GetDictRouteHVDn(ref Connector baseConnector, ref Connector targetConnector) { //if (targetConnector.CoordinateSystem.BasisZ.Z > 0) //{ // MessageBox.Show("연결할 수 없습니다."); // return; //} // 기준 파이프의 수직 평면 생성 XYZ baseX = baseConnector.CoordinateSystem.BasisZ.CrossProduct(XYZ.BasisZ); Plane plane1 = Plane.CreateByNormalAndOrigin(baseX, baseConnector.CoordinateSystem.Origin); double parm; XYZ p1 = targetConnector.Origin; XYZ p2 = Util.Project(plane1, p1); XYZ p7 = baseConnector.Origin; Line uline1 = Line.CreateUnbound(p7, baseConnector.CoordinateSystem.BasisZ); Plane plane2 = Plane.CreateByNormalAndOrigin(baseConnector.CoordinateSystem.BasisZ, p7); XYZ p3 = Util.Project(plane2, p2); XYZ p4 = Util.Project(plane2, p1); Plane plane3 = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, p7); XYZ p8 = Util.Project(plane3, p4); XYZ p5 = Util.Project(plane3, p1); XYZ p6 = Util.Project(plane3, p2); double minoffset = baseConnector.Radius * 1.2 + 0.16404199; // + 50mm(0.16404199ft) double minoffset2 = baseConnector.Radius * 11.0 + 0.16404199; // + 50mm(0.16404199ft) Pipe basePipe = baseElement as Pipe; Pipe targetPipe = targetElement as Pipe; double hgt = p6.DistanceTo(p2); if (hgt > Geo.MmToFoot(100)) { string listKey = string.Empty; // 기본추가 //---------------------------------------- // 7->6->5->1 //---------------------------------------- List lst1 = new List(); // 대상연결점 커넥터가 위를 향한 경우 if (targetConnector.CoordinateSystem.BasisZ.Z > 0 ) { XYZ p5u = p1 + XYZ.BasisZ * minoffset2; XYZ p6u = p2 + XYZ.BasisZ * minoffset2; if (targetPipe != null) { p5u = p1; p6u = p2; } lst1.Add(p7); lst1.Add(p6); lst1.Add(p6u); if (targetPipe == null) lst1.Add(p5u); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); }else{ if (p7.DistanceTo(p6) > minoffset) { lst1.Add(p7); XYZ v1 = (p6 - p7).Normalize(); if (v1.Equals(baseConnector.CoordinateSystem.BasisZ) == false) { p6 = p7 + baseConnector.CoordinateSystem.BasisZ * p7.DistanceTo(p6); } lst1.Add(p6); if (p6.DistanceTo(p5) > minoffset) lst1.Add(p5); else p1 = new XYZ(p6.X, p6.Y, p1.Z); lst1.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); }//end-if } //---------------------------------------- // 7-67-23-14-1 //---------------------------------------- List lst1_1 = new List(); XYZ p14 = Util.Midpoint(p1, p4); XYZ p23 = Util.Midpoint(p2, p3); XYZ p67 = Util.Midpoint(p6, p7); XYZ p15 = Util.Midpoint(p1, p5); XYZ p58 = Util.Midpoint(p5, p8); XYZ p1458 = Util.Midpoint(p14, p58); XYZ p2367 = Util.Midpoint(p23, p67); XYZ p23u = p23 + XYZ.BasisZ * minoffset2; XYZ p14u = p14 + XYZ.BasisZ * minoffset2; XYZ p1u = p1 + XYZ.BasisZ * minoffset2; // 대상연결점 커넥터가 위를 향한 경우 if (targetConnector.CoordinateSystem.BasisZ.Z > 0) { if (targetPipe != null) { p23u = p23; p14u = p14; } lst1_1.Add(p7); lst1_1.Add(p67); lst1_1.Add(p23u); lst1_1.Add(p14u); if (targetPipe == null) lst1_1.Add(p1u); lst1_1.Add(p1); } // 대상연결점 커넥터가 아래를 향한 경우 else { lst1_1.Add(p7); lst1_1.Add(p67); if (targetPipe != null) // 목표 커넥터가 패밀리 인스턴스인경우 { p2367 = p23; p1458 = p14; } lst1_1.Add(p2367); if (p2367.DistanceTo(p1458) > minoffset) lst1_1.Add(p1458); if (targetPipe == null) lst1_1.Add(p15); lst1_1.Add(p1); } dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1_1); // 기준연결점이 파이프인 경우 if (basePipe != null) { // 7->8->5->1 List lst2 = new List(); if (p7.DistanceTo(p8) > minoffset && p8.DistanceTo(p5) > minoffset) { if (targetConnector.CoordinateSystem.BasisZ.Z > 0 ) { XYZ p8u=p4+XYZ.BasisZ * minoffset2; XYZ p5u=p1+XYZ.BasisZ * minoffset2; if (targetPipe != null) { p8u = p4; p5u = p1; } lst2.Add(p7); lst2.Add(p8); lst2.Add(p8u); if (targetPipe == null) lst2.Add(p5u); lst2.Add(p1); }else { lst2.Add(p7); if (lst2.Last().DistanceTo(p8) > minoffset) lst2.Add(p8); lst2.Add(p5); lst2.Add(p1); } dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); } // 기준연결점이 파이프이고 목표 연결점의 오너가 파이프인 경우 // 파이프 -> 파이프 if (targetPipe != null) { List lst3 = new List(); { lst3.Add(p7); lst3.Add(p3); lst3.Add(p4); lst3.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } List lst4 = new List(); { lst4.Add(p7); lst4.Add(p3); lst4.Add(p2); lst4.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst4); } List lst5 = new List(); { lst5.Add(p7); lst5.Add(p8); if (lst5.Last().DistanceTo(p2) > minoffset) lst5.Add(p4); if (lst5.Last().DistanceTo(p1) > minoffset) lst5.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst5); } if (p2.DistanceTo(p1) > minoffset) { // 7-6-2-1 (중복) // 7-6-1 (추가X) } } } // 기준연결점이 패밀리인스턴스인 경우 else { // 패밀리인스턴스 -> 파이프 if (targetPipe != null) { // 7-6-2-1 if (targetConnector.CoordinateSystem.BasisZ.Z > 0) // 파이프가 위로 향한 경우 { if (p2.DistanceTo(p1) > minoffset) { List lst2 = new List(); lst2.Add(p7); lst2.Add(p6); lst2.Add(p2); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); List lst3 = new List(); lst3.Add(p7); lst3.Add(p6); lst3.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } } else { if (p2.DistanceTo(p1) > minoffset) { List lst2 = new List(); lst2.Add(p7); lst2.Add(p6); lst2.Add(p2); lst2.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); List lst3 = new List(); lst3.Add(p7); lst3.Add(p6); lst3.Add(p1); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } } } else { // 패밀리인스턴스 - 패밀리인스턴스 // -> 추가할 경로 없음. } } } } // I I // v v // ②---------① // | ⑦-----|-⑧ // | / |/ // ③--------④ // / / // ⑤--------⑥ // //---------------------------------------------------------------------------------------- private void GetDictRouteVDnVDn(ref Connector baseConnector, ref Connector targetConnector) { //if (targetConnector.CoordinateSystem.BasisZ.Z > 0) //{ // MessageBox.Show("연결할 수 없습니다."); // return; //} Level lvl = Util.GetLevel(m_rvtDoc, baseConnector.Origin.Z); // 기준 파이프의 수직 평면 생성 XYZ p1 = baseConnector.Origin; XYZ p2 = targetConnector.Origin; XYZ vZ = XYZ.BasisZ; double dst1m = Unit.MMToFeet(1000d); // 1m; XYZ p4 = new XYZ(p1.X, p1.Y, lvl.Elevation); XYZ p14on = Line.CreateUnbound(p1, p4).Project(p2).XYZPoint; XYZ p3 = new XYZ(p2.X, p2.Y, p4.Z); double dst12 = p3.DistanceTo(p4); XYZ vY = (p3 - p4).Normalize(); XYZ vX = vZ.CrossProduct(vY).Negate(); XYZ p7 = p3 + vX * dst1m; XYZ p8 = p4 + vX * dst1m; XYZ p5 = p3 - vX * dst1m; XYZ p6 = p4 - vX * dst1m; // 기본추가 //---------------------------------------- // 1->4->3->2 //---------------------------------------- List lst1 = new List(); lst1.Add(p1); lst1.Add(p4); lst1.Add(p3); lst1.Add(p2); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst1); //---------------------------------------- // 1->4->6->5->3->2 //---------------------------------------- List lst2 = new List(); lst2.Add(p1); lst2.Add(p4); lst2.Add(p6); lst2.Add(p5); lst2.Add(p3); lst2.Add(p2); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst2); //---------------------------------------- // 1->4->8->7->3->2 //---------------------------------------- List lst3 = new List(); lst3.Add(p1); lst3.Add(p4); lst3.Add(p8); lst3.Add(p7); lst3.Add(p3); lst3.Add(p2); dictPointList.Add((dictPointList.Keys.Count() + 1).ToString(), lst3); } private void GetDictRoute(ref Element baseElm, ref XYZ pick1, ref Element targetElm, ref XYZ pick2) { baseConnector = GetClosestConnector(baseElm, pick1); m_Resolver.SetBaseElementOrigin(baseElm, baseConnector); targetConnector = GetClosestConnector(targetElm, pick2); if (m_Resolver.GetSystemType() == null && targetConnector!=null) { if (targetConnector.MEPSystem != null) { m_Resolver.SetSystemType(targetConnector.MEPSystem.GetTypeId()); } else { // 둘 다 배관 커넥터가 아닌 경우 배관 기본 시스템유형을 가져와야 한다. Document doc = m_rvtDoc; FilteredElementCollector systemCollector = new FilteredElementCollector(doc).OfClass(typeof(MEPSystem)); IEnumerable desirableSystems = systemCollector.ToElements(); foreach (Element elm in desirableSystems) { MEPSystem system = elm as MEPSystem; if (system != null) { if (system.GetType() == typeof(Autodesk.Revit.DB.Plumbing.PipingSystem)) { m_Resolver.SetSystemType(system.GetTypeId()); break; } } } } } Pipe pipe1 = baseElm as Pipe; if (pipe1 != null) { m_Resolver.SetPipeDiameter(pipe1.Diameter); } else { m_Resolver.SetPipeDiameter(baseConnector.Radius*2d); } // 수평-수평 double eTor = 0.01; if (Math.Abs(baseConnector.CoordinateSystem.BasisZ.Z) < eTor && Math.Abs(targetConnector.CoordinateSystem.BasisZ.Z) < eTor) { GetDictRouteHH(ref baseConnector, ref pick1, ref targetConnector, ref pick2); } else { // 수평-수직 if ((Math.Abs(baseConnector.CoordinateSystem.BasisZ.Z) < eTor && Math.Abs(targetConnector.CoordinateSystem.BasisZ.Z) > 0.5) || (Math.Abs(targetConnector.CoordinateSystem.BasisZ.Z) < eTor && Math.Abs(baseConnector.CoordinateSystem.BasisZ.Z) > 0.5)) { GetDictRouteHV(ref baseConnector, ref pick1, ref targetConnector, ref pick2); } // 수직(∨)-수직(∨) else if ((Math.Abs(baseConnector.CoordinateSystem.BasisZ.Z) > eTor && Math.Abs(targetConnector.CoordinateSystem.BasisZ.Z) > eTor)) { GetDictRouteVV(ref baseConnector, ref pick1, ref targetConnector, ref pick2); } } } private void GetConnectorManager(Element e, ref ConnectorManager conMan) { conMan = null; MEPCurve mc = e as MEPCurve; FamilyInstance fi = e as FamilyInstance; if (null == mc && null == fi) { return; } if (fi != null) { conMan = fi.MEPModel != null ? fi.MEPModel.ConnectorManager : null; } else if (mc != null) { conMan = mc.ConnectorManager; } } // 주어진 점과 가장 가까운 커넥터를 찾느다. private Connector GetClosestConnector(Element element, XYZ pt) { ConnectorManager conMan = null; GetConnectorManager(element, ref conMan); if (conMan == null) return null; double minDst = double.MaxValue; Connector minConnector = null; double dst = 0d; if (conMan != null) { foreach (Connector con in conMan.Connectors) { // 기준 파이프에 연결될 파이프 dst = pt.DistanceTo(con.Origin); if (dst < minDst) { minConnector = con; minDst = dst; } } } return minConnector; } public void Init(Element base_element, XYZ p1, Element target_element, XYZ p2) { try { baseElement = base_element; targetElement = target_element; m_Resolver = new ResolverForPipeConnect(m_UiApp); if (targetElement == null) return; Dictionary> dictRoute = new Dictionary>(); dictPointList.Clear(); GetDictRoute(ref baseElement, ref p1, ref targetElement, ref p2); m_Resolver.SetElement(baseElement, targetElement); m_Resolver.SetRoute(ref dictPointList); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { } } private void Action() { try { m_Resolver.SetFlexible(checkBoxFlexible.Checked); m_Handler.Request.Make(m_Resolver); m_ExEvent.Raise(); EnableCommands(false); } catch (Exception ex) { } finally { } } private void buttonConnect_Click(object sender, EventArgs e) { Reg.setReg("FormPipeConnector_checkBoxFlexible", checkBoxFlexible.Checked ? "1" : "0"); //Reg.setReg("FormPipeConnector_checkBoxRefModelLine", checkBoxRefModelLine.Checked ? "1" : "0"); m_Resolver.SetResolverMode(ResolverForPipeConnect.EnumResolverMode.Run); m_Resolver.SetConnector(baseConnector, targetConnector); Action(); } private void buttonNext_Click(object sender, EventArgs e) { Dictionary> dictRoute = new Dictionary>(); m_Resolver.MoveNext(); m_Resolver.GetRoute(ref dictRoute); labelRouteNum.Text = string.Format("{0}/{1}", m_Resolver.GetIndex() + 1, dictRoute.Keys.Count); m_Resolver.SetResolverMode(ResolverForPipeConnect.EnumResolverMode.Next); Action(); } private void FormPipeConnector_Load(object sender, EventArgs e) { string sFlexible = Reg.getReg("FormPipeConnector_checkBoxFlexible"); if (sFlexible == "1") checkBoxFlexible.Checked = true; else checkBoxFlexible.Checked = false; string sRefModelLine = Reg.getReg("FormPipeConnector_checkBoxRefModelLine"); //if (sRefModelLine == "1") checkBoxRefModelLine.Checked = true; //else checkBoxRefModelLine.Checked = false; Dictionary> dictRoute = new Dictionary>(); m_Resolver.GetRoute(ref dictRoute); if (dictRoute.Keys.Count == 0) { MessageBox.Show("연결 가능한 경로가 없습니다!"); this.Close(); } else { labelRouteNum.Text = string.Format("{0}/{1}", m_Resolver.GetIndex() + 1, dictRoute.Keys.Count); m_Resolver.SetResolverMode(ResolverForPipeConnect.EnumResolverMode.Prev); Action(); } } private void FormPipeConnector_FormClosed(object sender, FormClosedEventArgs e) { m_Resolver.SetResolverMode(ResolverForPipeConnect.EnumResolverMode.Close); Action(); } private void checkBoxFlexible_CheckedChanged(object sender, EventArgs e) { } private void FormPipeConnector_KeyDown(object sender, KeyEventArgs e) { } } }