using Autodesk.Revit.DB; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using System.Collections.Generic; using System.Linq; //using COME4Revit.WinForm; using System.Diagnostics; using Autodesk.Revit.UI.Selection; using KMBIM.Revit.Tools; using KDCS.Utils; using KMBIM.Revit.Tools.Properties; namespace KMBIM { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] public class PipeConnectT : IExternalCommand { UIApplication uiapp; UIDocument uidoc; Document doc; Autodesk.Revit.Creation.Application creApp; Autodesk.Revit.Creation.Document creDoc; public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded; uiapp = commandData.Application; uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.ApplicationServices.Application app = uiapp.Application; doc = uidoc.Document; creApp = uiapp.Application.Create; creDoc = doc.Create; List MainPtLst = new List(); List BranchPtLst = new List(); Element MainElem = null; List m_BranchElemLst = new List(); List m_MainElemLst = new List(); try { //메인 파이프 선택 Reference pickref = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), Resources.CrossConnectT_MainSelect); if (pickref != null) { ElementId MainElemID = pickref.ElementId; MainElem = doc.GetElement(MainElemID) as Element; //MessageBox.Show("메인 : " + MainElem.Name); } m_MainElemLst.Add(MainElem); //가지 파이프 선택 IList pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), Resources.CrossConnectT_BranchSelect); if (pickrefs != null) { foreach (Reference refer in pickrefs) { //메인 파이프가 가지파이프에 있으면 저장X ElementId BranchElemID = refer.ElementId; Element BranchElem = doc.GetElement(BranchElemID) as Element; if (MainElem.Id.Compare(BranchElem.Id) == 0) continue; m_BranchElemLst.Add(BranchElem); //MessageBox.Show("가지 :" + BranchElem); } } ElementId divPipeID = null; int breakcnt = 0; bool b_MainCutTrue = false; using (Transaction trans = new Transaction(doc)) { trans.Start("CreateT"); while (true) { foreach (Element mainElem in m_MainElemLst) { foreach (Element BranchElem in m_BranchElemLst) { //divPipeID = CreatePipeT(BranchElem, mainElem, false); divPipeID = CreatePipeT(mainElem, BranchElem, true); if (divPipeID != null) { m_BranchElemLst.Remove(BranchElem); b_MainCutTrue = true; break; } else b_MainCutTrue = false; } if (b_MainCutTrue == true) break; } if (divPipeID != null) m_MainElemLst.Add(doc.GetElement(divPipeID)); breakcnt++; if (breakcnt > 100) break; if (m_BranchElemLst.Count <= 0) break; }//while end //MessageBox.Show("메인 개수 :" + m_MainElemLst.Count); trans.Commit(); } } catch { } return Result.Succeeded; } //파이프T 연결 메인,가지 교차점 trim 후 Tee 삽입 public ElementId CreatePipeT(Element main_element, Element branch_element, bool MainPipe_Down) { ElementId m_divideElemId = null, b_divideElemId = null; List mainElemPts = new List(); List branchElemPts = new List(); XYZ InterPt, main_InterPt, branch_InterPt; Pipe mainPipe = main_element as Pipe; Pipe branchPipe = branch_element as Pipe; mainElemPts = GetPipeConnectorPts(mainPipe); branchElemPts = GetPipeConnectorPts(branchPipe); InterPt = GetIntersectionPoint(mainElemPts[0], mainElemPts[1], branchElemPts[0], branchElemPts[1]); if (InterPt == null) return null; main_InterPt = new XYZ(InterPt.X, InterPt.Y, mainElemPts[0].Z); branch_InterPt = new XYZ(InterPt.X, InterPt.Y, branchElemPts[0].Z); try { mainPipe = main_element as Pipe; m_divideElemId = PlumbingUtils.BreakCurve(doc, mainPipe.Id, main_InterPt); branchPipe = branch_element as Pipe; b_divideElemId = PlumbingUtils.BreakCurve(doc, branchPipe.Id, branch_InterPt); } catch { } //나뉜 메인관이 없을 경우 리턴 if (m_divideElemId == null) return null; //T연결시 커넥트 3개가 필요하여 메인 가지관 교차점 사이에 파이프 작도 //잘린 메인id 파이프로 전환 Pipe mainDivide = doc.GetElement(m_divideElemId) as Pipe; Pipe branchDivide = doc.GetElement(b_divideElemId) as Pipe; Pipe HeadPipe = null; Level level = new FilteredElementCollector(doc).OfClass(typeof(Level)).First() as Level; //if (main_InterPt.IsAlmostEqualTo(branch_InterPt,0.1)) return null; Parameter mainParam = mainPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM); Parameter branchParam = branchPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM); if (mainParam.AsDouble() < branchParam.AsDouble()) { HeadPipe = Pipe.Create(doc, mainPipe.MEPSystem.GetTypeId(), mainPipe.GetTypeId(), level.Id, main_InterPt, branch_InterPt); Connector con = HeadPipe.ConnectorManager.Connectors.Cast().First(); con.Radius = mainParam.AsDouble() / 2.0; } else { HeadPipe = Pipe.Create(doc, branchPipe.MEPSystem.GetTypeId(), branchPipe.GetTypeId(), level.Id, main_InterPt, branch_InterPt); Connector con = HeadPipe.ConnectorManager.Connectors.Cast().First(); con.Radius = branchParam.AsDouble() / 2.0; } CreatePipeT(mainPipe, mainDivide, HeadPipe); CreatePipeT(branchPipe, branchDivide, HeadPipe); return m_divideElemId; } //파이프 커넥터점 2개 구하기 public List GetPipeConnectorPts(Pipe pipe) { List ptLst = new List(); ConnectorManager pipe_connectorManager1 = pipe.ConnectorManager; ConnectorSet pipe_connectorSet1 = pipe_connectorManager1.Connectors; foreach (Connector connector1 in pipe_connectorSet1) { ptLst.Add(connector1.Origin); } return ptLst; } //파이프T 커넥터3개로 작도하기 public void CreatePipeT(Pipe Main1, Pipe Main2, Pipe Head) { //나뉘어진 메인관2개 가지관 1개 커넥트 구해 T작도 ConnectorManager pipe_connectorManager2 = Main1.ConnectorManager; ConnectorSet pipe_connectorSet2 = pipe_connectorManager2.Connectors; ConnectorManager pipe_connectorManager3 = Main2.ConnectorManager; ConnectorSet pipe_connectorSet3 = pipe_connectorManager3.Connectors; Connector pipe_main1con = null; Connector pipe_main2con = null; Connector pipe_branchcon = null; double minDist = double.MaxValue; foreach (Connector maincon1 in pipe_connectorSet2) { foreach (Connector maincon2 in pipe_connectorSet3) { double d = maincon1.Origin.DistanceTo(maincon2.Origin); if (d < minDist) { pipe_main1con = maincon1; pipe_main2con = maincon2; minDist = d; } } } ConnectorManager New_connectorManager = Head.ConnectorManager; ConnectorSet New_connectorSet = New_connectorManager.Connectors; Connector New_con = null; double minDist2 = double.MaxValue; foreach (Connector maincon1 in pipe_connectorSet2) { foreach (Connector maincon3 in New_connectorSet) { double d = maincon1.Origin.DistanceTo(maincon3.Origin); if (d < minDist2) { pipe_main1con = maincon1; New_con = maincon3; minDist2 = d; } } } try { FamilyInstance family = creDoc.NewTeeFitting(pipe_main1con, pipe_main2con, New_con); } catch { } } public class PipeSelectionFilter : ISelectionFilter { public bool AllowElement(Element element) { if (element.Category == null) return false; 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) { XYZ resPt = XYZ.Zero; //p1 = Util.Polar(p1, p2, p1, 1); //p2 = Util.Polar(p2, p1, p2, 1); //p3 = Util.Polar(p3, p4, p3, 1); //p4 = Util.Polar(p4, p3, p4, 1); 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; resPt = new XYZ(x, y, 0); return resPt; } static Definition GetDefinition(Element elem, string parameter_name) { IList ps = elem.GetParameters(parameter_name); int n = ps.Count; Debug.Assert(1 >= n, "expected maximum one shared parameters" + "named " + parameter_name); Definition d = (0 == n) ? null : ps[0].Definition; return d; } } }