// // (C) Copyright 2003-2017 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using System.Text; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.DB.Mechanical; using System.Diagnostics; using Element = Autodesk.Revit.DB.Element; using System.Collections; using System.Windows.Forms; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.UI.Selection; using KDCS.Utils; namespace KMBIM { enum EnumAvoidObstructionType { None = 0, AvoidUpDn, Avoid_Up, Avoid_Dn, AvoidDnUp, AvoidUp_, AvoidDn_ } /// /// Custom filter for selection. /// public class AvoidObstructionSelectionFilter : ISelectionFilter { private List m_listsElementType=null; // 특정 유형만 선택할 수 있도록 한다. public AvoidObstructionSelectionFilter(List lstElementType) { m_listsElementType = new List(); foreach (Type t1 in lstElementType) { m_listsElementType.Add(t1); } } public bool AllowElement(Element elem) { foreach (Type t1 in m_listsElementType) { if (elem.GetType() == t1) return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return true; } } /// /// This class implement the algorithm to detect the obstruction and resolve it. /// class Resolver { /// /// Revit Document. /// private UIDocument m_rvtUIDoc; private Document m_rvtDoc; /// /// Revit Application. /// private Autodesk.Revit.ApplicationServices.Application m_rvtApp; EnumAvoidObstructionType m_AvoidObstructionType; /// /// Detector to detect the obstructions. /// private Detector m_detector; PipingSystemType m_pipingSystemType; MechanicalSystemType m_ductSystemType; /// /// Constructor, initialize all the fields of this class. /// /// Revit ExternalCommandData from external command entrance public Resolver(ExternalCommandData data) { m_rvtUIDoc = data.Application.ActiveUIDocument; m_rvtDoc = data.Application.ActiveUIDocument.Document; m_rvtApp = data.Application.Application; m_detector = new Detector(m_rvtDoc); FilteredElementCollector collector = new FilteredElementCollector(m_rvtDoc); var pipingSystemTypes = collector.OfClass(typeof(PipingSystemType)).ToElements(); foreach (PipingSystemType pipingSystemType in pipingSystemTypes) { if (pipingSystemType.SystemClassification == MEPSystemClassification.SupplyHydronic || pipingSystemType.SystemClassification == MEPSystemClassification.ReturnHydronic) { m_pipingSystemType = pipingSystemType; break; } } FilteredElementCollector collectorDuct = new FilteredElementCollector(m_rvtDoc); var ductSystemTypes = collectorDuct.OfClass(typeof(MechanicalSystemType)).ToElements(); foreach (MechanicalSystemType ductSystemType in ductSystemTypes) { if (ductSystemType.SystemClassification == MEPSystemClassification.SupplyAir || ductSystemType.SystemClassification == MEPSystemClassification.ReturnAir) { m_ductSystemType = ductSystemType; break; } } } /// /// Detect and resolve the obstructions of all Pipes. /// /// 충돌요소 /// 회피요소 public void Resolve(ref List lstObstruction, ref List lstAvoidance) { foreach (Element e1 in lstAvoidance) { foreach (Element e2 in lstObstruction) { Type et1 = e1.GetType(); // 회피요소 유형 using (Transaction tr = new Transaction(m_rvtDoc, "External Tool - Resolver")) { tr.Start(); try { if (et1 == typeof(Duct)) { Run(e1 as Duct, e2); } else if (et1 == typeof(Pipe)) { Run(e1 as Pipe, e2); } else if (et1 == typeof(CableTray)) { } else if (et1 == typeof(Conduit)) { } tr.Commit(); } catch (System.Exception ex) { string str_msg = ex.Message; tr.RollBack(); } } }//for-each }//for-each } public void SetAvoidObstructionType(EnumAvoidObstructionType obstructionType) { m_AvoidObstructionType = obstructionType; } /// /// Calculate the uniform perpendicular directions with inputting direction "dir". /// /// Direction to calculate /// How many perpendicular directions will be calculated /// The calculated perpendicular directions with dir private List PerpendicularDirs(Autodesk.Revit.DB.XYZ dir, int count) { List dirs = new List(); Plane plane = Plane.CreateByNormalAndOrigin(dir, Autodesk.Revit.DB.XYZ.Zero); Arc arc = Arc.Create(plane, 1.0, 0, 6.2831); double delta = 1.0 / (double)count; for (int i = 1; i <= count; i++) { Autodesk.Revit.DB.XYZ pt = arc.Evaluate(delta * i, true); dirs.Add(pt); } return dirs; } private void Bend(Pipe pipe, Pipe obstruction) { var parameter = pipe.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM); var levelId = parameter.AsElementId(); var systemTypeId = m_pipingSystemType.Id; // Get the centerline of pipe. Line pipeLine = (pipe.Location as LocationCurve).Curve as Line; double pipRad = pipe.Diameter * 0.5; // Calculate the intersection references with pipe's centerline. Autodesk.Revit.DB.XYZ startPt = pipeLine.GetEndPoint(0); Autodesk.Revit.DB.XYZ endPt = pipeLine.GetEndPoint(1); Autodesk.Revit.DB.XYZ axisZ = (endPt - startPt).Normalize(); double pipeLength = startPt.DistanceTo(endPt); XYZ axisX = new XYZ(); XYZ axisY = new XYZ(); Util.AxesXY(axisZ, ref axisX, ref axisY); XYZ orgR = startPt + axisX * pipRad; XYZ orgL = startPt - axisX * pipRad; XYZ orgT = startPt + axisY * pipRad; XYZ orgB = startPt - axisY * pipRad; // �浹 Ȯ�μ� Line checkLeftLine = Line.CreateBound(orgL, orgL + axisZ * pipeLength); Line checkRightLine = Line.CreateBound(orgR, orgR + axisZ * pipeLength); Line checkTopLine = Line.CreateBound(orgT, orgT + axisZ * pipeLength); Line checkBottomLine = Line.CreateBound(orgB, orgB + axisZ * pipeLength); // ��Ʈ�� �߽ɼ����� ��������(�浹��)�� ����Ѵ�. List obstructionTopRefArr = m_detector.Obstructions(checkTopLine); List obstructionBottomRefArr = m_detector.Obstructions(checkBottomLine); List obstructionLeftRefArr = m_detector.Obstructions(checkLeftLine); List obstructionRightRefArr = m_detector.Obstructions(checkRightLine); // ��������(�浹��) �� ��Ʈ,������, �� ������ ����Ѵ�. // duct: �� �ڽ��� ���ܽ�Ű������ Filter(pipe, obstructionTopRefArr); Filter(pipe, obstructionBottomRefArr); Filter(pipe, obstructionLeftRefArr); Filter(pipe, obstructionRightRefArr); List obstructionRefArr = null; // ��->��->��->�� ������ if (obstructionTopRefArr.Count > 0) obstructionRefArr = obstructionTopRefArr; // �� if (obstructionBottomRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionBottomRefArr; // �� else obstructionRefArr.AddRange(obstructionBottomRefArr); // ��,�� ��� ���� �߻� } if (obstructionRefArr == null) { if (obstructionLeftRefArr.Count > 0) obstructionRefArr = obstructionLeftRefArr; // �� if (obstructionRightRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionRightRefArr; // �� else obstructionRefArr.AddRange(obstructionRightRefArr); // ��,�� ��� ���� �߻� } } // ������ �������� �ʴ´�. if (obstructionRefArr == null) return; if (obstructionRefArr.Count == 0) return; // ���� �����κ��� ������ �ۼ��Ѵ�. obstructionRefArr.Sort(m_detector.CompareReferencesWithContext); List
sections = Section.BuildSections(obstructionRefArr, pipeLine.Direction); List
lstSectionTmp = new List
(); lstSectionTmp.AddRange(sections); // �ߺ� ���� ����->���� ��ġ�� �������� Section�� �߻��� ��� �ߺ� ���� if (sections.Count > 1) { while (lstSectionTmp.Count > 0) { Section section1 = lstSectionTmp[0]; lstSectionTmp.RemoveAt(0); var intResult1 = pipeLine.Project(KDCS.Utils.Util.Midpoint(section1.Start, section1.End)); foreach (Section section2 in lstSectionTmp) { var intResult2 = pipeLine.Project(KDCS.Utils.Util.Midpoint(section2.Start, section2.End)); if (intResult2 != null) { if (intResult1.XYZPoint.DistanceTo(intResult2.XYZPoint) < pipRad) { sections.Remove(section2); break; } } } } } // Merge the neighbor sections if the distance of them is too close. for (int i = sections.Count - 2; i >= 0; i--) { Autodesk.Revit.DB.XYZ detal = sections[i].End - sections[i + 1].Start; if (detal.GetLength() < pipe.Diameter * 3) { sections[i].Refs.AddRange(sections[i + 1].Refs); sections.RemoveAt(i + 1); } } // Resolve the obstructions one by one. foreach (Section sec in sections) { Resolve(pipe, sec); } // Connect the neighbor sections with pipe and elbow fittings. // for (int i = 1; i < sections.Count; i++) { // Get the end point from the previous section. Autodesk.Revit.DB.XYZ start = sections[i - 1].End1; // Get the start point from the current section. Autodesk.Revit.DB.XYZ end = sections[i].Start1; // Create a pipe between two neighbor section. Pipe tmpPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, start, end); // Copy pipe's parameters values to tmpPipe. CopyParameters(pipe, tmpPipe); // Create elbow fitting to connect previous section with tmpPipe. Connector conn1 = FindConnector(sections[i - 1].Pipes[2], start); Connector conn2 = FindConnector(tmpPipe, start); FamilyInstance f1 = null; try{ f1 = m_rvtDoc.Create.NewElbowFitting(conn1, conn2); } catch (Exception ex) { string strmsg = ex.Message; } // Create elbow fitting to connect current section with tmpPipe. Connector conn3 = FindConnector(sections[i].Pipes[0], end); Connector conn4 = FindConnector(tmpPipe, end); FamilyInstance f2 = m_rvtDoc.Create.NewElbowFitting(conn3, conn4); } // Find two connectors which pipe's two ends connector connected to. Connector startConn = FindConnectedTo(pipe, pipeLine.GetEndPoint(0)); Connector endConn = FindConnectedTo(pipe, pipeLine.GetEndPoint(1)); Pipe startPipe = null; if (null != startConn) { // Create a pipe between pipe's start connector and pipe's start section. startPipe = Pipe.Create(m_rvtDoc, pipe.PipeType.Id, levelId, startConn, sections[0].Start1); } else { // Create a pipe between pipe's start point and pipe's start section. startPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, sections[0].Start1, pipeLine.GetEndPoint(0)); } // Copy parameters from pipe to startPipe. CopyParameters(pipe, startPipe); // Connect the startPipe and first section with elbow fitting. Connector connStart1 = FindConnector(startPipe, sections[0].Start1); Connector connStart2 = FindConnector(sections[0].Pipes[0], sections[0].Start1); FamilyInstance f3 = null; try{ f3 = m_rvtDoc.Create.NewElbowFitting(connStart1, connStart2); } catch (Exception ex) { string strmsg = ex.Message; } Pipe endPipe = null; int count = sections.Count; if (null != endConn) { // Create a pipe between pipe's end connector and pipe's end section. endPipe = Pipe.Create(m_rvtDoc, pipe.PipeType.Id, levelId, endConn, sections[count - 1].End1); } else { // Create a pipe between pipe's end point and pipe's end section. endPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, sections[count - 1].End1, pipeLine.GetEndPoint(1)); } // Copy parameters from pipe to endPipe. CopyParameters(pipe, endPipe); // Connect the endPipe and last section with elbow fitting. Connector connEnd1 = FindConnector(endPipe, sections[count - 1].End1); Connector connEnd2 = FindConnector(sections[count - 1].Pipes[2], sections[count - 1].End1); FamilyInstance f4 = null; try{ f4 = m_rvtDoc.Create.NewElbowFitting(connEnd1, connEnd2); } catch (Exception ex) { string strmsg = ex.Message; } // Delete the pipe after resolved. m_rvtDoc.Delete(pipe.Id); } private void Bend(Pipe pipe, Duct obstruction) { var parameter = pipe.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM); var levelId = parameter.AsElementId(); var systemTypeId = m_pipingSystemType.Id; // Get the centerline of pipe. Line pipeLine = (pipe.Location as LocationCurve).Curve as Line; double pipRad = pipe.Diameter * 0.5; // Calculate the intersection references with pipe's centerline. Autodesk.Revit.DB.XYZ startPt = pipeLine.GetEndPoint(0); Autodesk.Revit.DB.XYZ endPt = pipeLine.GetEndPoint(1); Autodesk.Revit.DB.XYZ axisZ = (endPt - startPt).Normalize(); double pipeLength = startPt.DistanceTo(endPt); XYZ axisX = new XYZ(); XYZ axisY = new XYZ(); KDCS.Utils.Util.AxesXY(axisZ, ref axisX, ref axisY); XYZ orgR = startPt + axisX * pipRad; XYZ orgL = startPt - axisX * pipRad; XYZ orgT = startPt + axisY * pipRad; XYZ orgB = startPt - axisY * pipRad; // �浹 Ȯ�μ� Line checkLeftLine = Line.CreateBound(orgL, orgL + axisZ * pipeLength); Line checkRightLine = Line.CreateBound(orgR, orgR + axisZ * pipeLength); Line checkTopLine = Line.CreateBound(orgT, orgT + axisZ * pipeLength); Line checkBottomLine = Line.CreateBound(orgB, orgB + axisZ * pipeLength); // ��Ʈ�� �߽ɼ����� ��������(�浹��)�� ����Ѵ�. List obstructionTopRefArr = m_detector.Obstructions(checkTopLine); List obstructionBottomRefArr = m_detector.Obstructions(checkBottomLine); List obstructionLeftRefArr = m_detector.Obstructions(checkLeftLine); List obstructionRightRefArr = m_detector.Obstructions(checkRightLine); // ��������(�浹��) �� ��Ʈ,������, �� ������ ����Ѵ�. // duct: �� �ڽ��� ���ܽ�Ű������ Filter(pipe, obstructionTopRefArr); Filter(pipe, obstructionBottomRefArr); Filter(pipe, obstructionLeftRefArr); Filter(pipe, obstructionRightRefArr); List obstructionRefArr = null; // ��->��->��->�� ������ if (obstructionTopRefArr.Count > 0) obstructionRefArr = obstructionTopRefArr; // �� if (obstructionBottomRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionBottomRefArr; // �� else obstructionRefArr.AddRange(obstructionBottomRefArr); // ��,�� ��� ���� �߻� } if (obstructionRefArr == null) { if (obstructionLeftRefArr.Count > 0) obstructionRefArr = obstructionLeftRefArr; // �� if (obstructionRightRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionRightRefArr; // �� else obstructionRefArr.AddRange(obstructionRightRefArr); // ��,�� ��� ���� �߻� } } // ������ �������� �ʴ´�. if (obstructionRefArr == null) return; if (obstructionRefArr.Count == 0) return; // ���� �����κ��� ������ �ۼ��Ѵ�. obstructionRefArr.Sort(m_detector.CompareReferencesWithContext); List
sections = Section.BuildSections(obstructionRefArr, pipeLine.Direction); List
lstSectionTmp = new List
(); lstSectionTmp.AddRange(sections); // �ߺ� ���� ����->���� ��ġ�� �������� Section�� �߻��� ��� �ߺ� ���� if (sections.Count > 1) { while (lstSectionTmp.Count > 0) { Section section1 = lstSectionTmp[0]; lstSectionTmp.RemoveAt(0); var intResult1 = pipeLine.Project(KDCS.Utils.Util.Midpoint(section1.Start, section1.End)); foreach (Section section2 in lstSectionTmp) { var intResult2 = pipeLine.Project(KDCS.Utils.Util.Midpoint(section2.Start, section2.End)); if (intResult2 != null) { if (intResult1.XYZPoint.DistanceTo(intResult2.XYZPoint) < pipRad) { sections.Remove(section2); break; } } } } } // Merge the neighbor sections if the distance of them is too close. for (int i = sections.Count - 2; i >= 0; i--) { Autodesk.Revit.DB.XYZ detal = sections[i].End - sections[i + 1].Start; if (detal.GetLength() < pipe.Diameter * 3) { sections[i].Refs.AddRange(sections[i + 1].Refs); sections.RemoveAt(i + 1); } } // Resolve the obstructions one by one. foreach (Section sec in sections) { Resolve(pipe, sec); } // Connect the neighbor sections with pipe and elbow fittings. // for (int i = 1; i < sections.Count; i++) { // Get the end point from the previous section. Autodesk.Revit.DB.XYZ start = sections[i - 1].End1; // Get the start point from the current section. Autodesk.Revit.DB.XYZ end = sections[i].Start1; // Create a pipe between two neighbor section. Pipe tmpPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, start, end); // Copy pipe's parameters values to tmpPipe. CopyParameters(pipe, tmpPipe); // Create elbow fitting to connect previous section with tmpPipe. Connector conn1 = FindConnector(sections[i - 1].Pipes[2], start); Connector conn2 = FindConnector(tmpPipe, start); FamilyInstance f1 = null; try { f1 = m_rvtDoc.Create.NewElbowFitting(conn1, conn2); } catch (Exception ex) { string strmsg = ex.Message; } // Create elbow fitting to connect current section with tmpPipe. Connector conn3 = FindConnector(sections[i].Pipes[0], end); Connector conn4 = FindConnector(tmpPipe, end); FamilyInstance f2 = m_rvtDoc.Create.NewElbowFitting(conn3, conn4); } // Find two connectors which pipe's two ends connector connected to. Connector startConn = FindConnectedTo(pipe, pipeLine.GetEndPoint(0)); Connector endConn = FindConnectedTo(pipe, pipeLine.GetEndPoint(1)); Pipe startPipe = null; if (null != startConn) { // Create a pipe between pipe's start connector and pipe's start section. startPipe = Pipe.Create(m_rvtDoc, pipe.PipeType.Id, levelId, startConn, sections[0].Start1); } else { // Create a pipe between pipe's start point and pipe's start section. startPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, sections[0].Start1, pipeLine.GetEndPoint(0)); } // Copy parameters from pipe to startPipe. CopyParameters(pipe, startPipe); // Connect the startPipe and first section with elbow fitting. Connector connStart1 = FindConnector(startPipe, sections[0].Start1); Connector connStart2 = FindConnector(sections[0].Pipes[0], sections[0].Start1); FamilyInstance f3 = null; try { f3 = m_rvtDoc.Create.NewElbowFitting(connStart1, connStart2); } catch (Exception ex) { string strmsg = ex.Message; } Pipe endPipe = null; int count = sections.Count; if (null != endConn) { // Create a pipe between pipe's end connector and pipe's end section. endPipe = Pipe.Create(m_rvtDoc, pipe.PipeType.Id, levelId, endConn, sections[count - 1].End1); } else { // Create a pipe between pipe's end point and pipe's end section. endPipe = Pipe.Create(m_rvtDoc, systemTypeId, pipe.PipeType.Id, levelId, sections[count - 1].End1, pipeLine.GetEndPoint(1)); } // Copy parameters from pipe to endPipe. CopyParameters(pipe, endPipe); // Connect the endPipe and last section with elbow fitting. Connector connEnd1 = FindConnector(endPipe, sections[count - 1].End1); Connector connEnd2 = FindConnector(sections[count - 1].Pipes[2], sections[count - 1].End1); FamilyInstance f4 = null; try { f4 = m_rvtDoc.Create.NewElbowFitting(connEnd1, connEnd2); } catch (Exception ex) { string strmsg = ex.Message; } // Delete the pipe after resolved. m_rvtDoc.Delete(pipe.Id); } /// /// Detect the obstructions of pipe and resolve them. /// /// Pipe to resolve private void Run(Pipe pipe, Element obstruction) { if(obstruction.GetType() == typeof(Pipe)){ Bend(pipe, obstruction as Pipe); }else if(obstruction.GetType() == typeof(Duct)){ Bend(pipe, obstruction as Duct); } } private double GetDuctWidth(Duct duct) { double width = 0d; ConnectorProfileType shape = KDCS.Utils.Util.GetShape(duct); if (shape == ConnectorProfileType.Round) { width = duct.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).AsDouble(); } else { width = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).AsDouble(); } return width; } private double GetDuctHeight(Duct duct) { double height = 0d; ConnectorProfileType shape = KDCS.Utils.Util.GetShape(duct); if (shape == ConnectorProfileType.Round) { height = duct.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).AsDouble(); } else { height = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).AsDouble(); } return height; } /// /// Use Autodesk.Revit.DB.ElementId to get the corresponding element /// /// the element id value /// the corresponding element Autodesk.Revit.DB.Element GetElementById(int id) { // Create a Autodesk.Revit.DB.ElementId data Autodesk.Revit.DB.ElementId elementId = new Autodesk.Revit.DB.ElementId(id); // Get the corresponding element return m_rvtDoc.GetElement(elementId); } SketchPlane GetSketchPlaneById(int id) { // First get the sketch plane by the giving element id. SketchPlane workPlane = GetElementById(id) as SketchPlane; if (null == workPlane) { throw new Exception("Don't have the work plane you select."); } return workPlane; } private void Bend(Duct duct, Duct obstruction) { // duct.LookupParameter(string name) var paramLevel = duct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM); var levelId = paramLevel.AsElementId(); var systemTypeId = m_ductSystemType.Id; // ��Ʈ ������ var halfWidth = GetDuctWidth(duct) * 0.5; var halfHeight = GetDuctHeight(duct) * 0.5; // ��Ʈ �߽ɼ��� ���Ѵ�. Line ductLine = (duct.Location as LocationCurve).Curve as Line; Autodesk.Revit.DB.XYZ startPt = ductLine.GetEndPoint(0); Autodesk.Revit.DB.XYZ endPt = ductLine.GetEndPoint(1); Autodesk.Revit.DB.XYZ axisZ = (endPt - startPt).Normalize(); double ductLength = startPt.DistanceTo(endPt); XYZ axisX = new XYZ(); XYZ axisY = new XYZ(); KDCS.Utils.Util.AxesXY(axisZ, ref axisX, ref axisY); XYZ orgR = startPt + axisX * halfWidth; XYZ orgL = startPt - axisX * halfWidth; XYZ orgT = startPt + axisY * halfHeight; XYZ orgB = startPt - axisY * halfHeight; // �浹 Ȯ�μ� Line checkLeftLine = Line.CreateBound(orgL, orgL + axisZ * ductLength); Line checkRightLine = Line.CreateBound(orgR, orgR + axisZ * ductLength); Line checkTopLine = Line.CreateBound(orgT, orgT + axisZ * ductLength); Line checkBottomLine = Line.CreateBound(orgB, orgB + axisZ * ductLength); // ��Ʈ�� �߽ɼ����� ��������(�浹��)�� ����Ѵ�. List obstructionTopRefArr = m_detector.Obstructions(checkTopLine); List obstructionBottomRefArr = m_detector.Obstructions(checkBottomLine); List obstructionLeftRefArr = m_detector.Obstructions(checkLeftLine); List obstructionRightRefArr = m_detector.Obstructions(checkRightLine); // ��������(�浹��) �� ��Ʈ,������, �� ������ ����Ѵ�. // duct: �� �ڽ��� ���ܽ�Ű������ Filter(duct, obstructionTopRefArr); Filter(duct, obstructionBottomRefArr); Filter(duct, obstructionLeftRefArr); Filter(duct, obstructionRightRefArr); List obstructionRefArr = null; // ��->��->��->�� ������ if (obstructionTopRefArr.Count > 0) obstructionRefArr = obstructionTopRefArr; // �� if (obstructionBottomRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionBottomRefArr; // �� else obstructionRefArr.AddRange(obstructionBottomRefArr); // ��,�� ��� ���� �߻� } if (obstructionRefArr == null) { if (obstructionLeftRefArr.Count > 0) obstructionRefArr = obstructionLeftRefArr; // �� if (obstructionRightRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionRightRefArr; // �� else obstructionRefArr.AddRange(obstructionRightRefArr); // ��,�� ��� ���� �߻� } } // ������ �������� �ʴ´�. if (obstructionRefArr == null) return; if (obstructionRefArr.Count == 0) return; // ���� �����κ��� ������ �ۼ��Ѵ�. obstructionRefArr.Sort(m_detector.CompareReferencesWithContext); List
sections = Section.BuildSections(obstructionRefArr, ductLine.Direction); List
lstSectionTmp = new List
(); lstSectionTmp.AddRange(sections); // �ߺ� ���� ����->���� ��ġ�� �������� Section�� �߻��� ��� �ߺ� ���� if (sections.Count > 1) { while (lstSectionTmp.Count > 0) { Section section1 = lstSectionTmp[0]; lstSectionTmp.RemoveAt(0); var intResult1 = ductLine.Project(KDCS.Utils.Util.Midpoint(section1.Start, section1.End)); foreach (Section section2 in lstSectionTmp) { var intResult2 = ductLine.Project(KDCS.Utils.Util.Midpoint(section2.Start, section2.End)); if (intResult2 != null) { if (intResult1.XYZPoint.DistanceTo(intResult2.XYZPoint) < halfHeight) { sections.Remove(section2); break; } } } } } // ���� ������ �Ÿ��� �ʹ� ª�� ��� ������ �����Ѵ�. double width = GetDuctWidth(duct); for (int i = sections.Count - 2; i >= 0; i--) { Autodesk.Revit.DB.XYZ detal = sections[i].End - sections[i + 1].Start; if (detal.GetLength() < width * 3) { sections[i].Refs.AddRange(sections[i + 1].Refs); sections.RemoveAt(i + 1); } } // ��ֹ��� �ϳ��� �ذ�. foreach (Section sec in sections) { Resolve(duct, sec); } // ��Ʈ �� ���� �������� ���� ���� �����Ѵ�. for (int i = 1; i < sections.Count; i++) { // Get the end point from the previous section. Autodesk.Revit.DB.XYZ start = sections[i - 1].End1; // Get the start point from the current section. Autodesk.Revit.DB.XYZ end = sections[i].Start1; // Create a duct between two neighbor section. Duct tmpDuct = Duct.Create(m_rvtDoc, systemTypeId, duct.DuctType.Id, levelId, start, end); // Copy pipe's parameters values to tmpPipe. CopyParameters(duct, tmpDuct); // Create elbow fitting to connect previous section with tmpPipe. Connector conn1 = FindConnector(sections[i - 1].Ducts[2], start); Connector conn2 = FindConnector(tmpDuct, start); if (conn1 != null && conn2 != null) { FamilyInstance fi = null; try { fi = m_rvtDoc.Create.NewElbowFitting(conn1, conn2); } catch (Exception ex) { string strmsg = ex.Message; } } // Create elbow fitting to connect current section with tmpPipe. Connector conn3 = FindConnector(sections[i].Ducts[0], end); Connector conn4 = FindConnector(tmpDuct, end); if (conn3 != null && conn4 != null) { FamilyInstance f2 = null; try { f2 = m_rvtDoc.Create.NewElbowFitting(conn3, conn4); } catch (Exception ex) { string strmsg = ex.Message; } } } // Find two connectors which pipe's two ends connector connected to. Connector startConn = FindConnectedTo(duct, ductLine.GetEndPoint(0)); Connector endConn = FindConnectedTo(duct, ductLine.GetEndPoint(1)); Duct startDuct = null; if (null != startConn) { // Create a pipe between pipe's start connector and pipe's start section. startDuct = Duct.Create(m_rvtDoc, duct.DuctType.Id, levelId, startConn, sections[0].Start1); } else { // Create a pipe between pipe's start point and pipe's start section. startDuct = Duct.Create(m_rvtDoc, systemTypeId, duct.DuctType.Id, levelId, sections[0].Start1, ductLine.GetEndPoint(0)); } // Copy parameters from pipe to startPipe. CopyParameters(duct, startDuct); // starDuct�� ù ��° ������ ���� �������� ���� Connector connStart1 = FindConnector(startDuct, sections[0].Start1); Connector connStart2 = FindConnector(sections[0].Ducts[0], sections[0].Start1); FamilyInstance fii = null; if (connStart1 != null && connStart2 != null) { try { fii = m_rvtDoc.Create.NewElbowFitting(connStart1, connStart2); } catch (Exception ex) { string strmsg = ex.Message; } } Duct endDuct = null; int count = sections.Count; if (null != endConn) { // Create a pipe between pipe's end connector and pipe's end section. endDuct = Duct.Create(m_rvtDoc, duct.DuctType.Id, levelId, endConn, sections[count - 1].End1); } else { // Create a pipe between pipe's end point and pipe's end section. endDuct = Duct.Create(m_rvtDoc, systemTypeId, duct.DuctType.Id, levelId, sections[count - 1].End1, ductLine.GetEndPoint(1)); } // Copy parameters from pipe to endPipe. CopyParameters(duct, endDuct); // endDuct�� ������ ������ ���� �������� ���� Connector connEnd1 = FindConnector(endDuct, sections[count - 1].End1); Connector connEnd2 = FindConnector(sections[count - 1].Ducts[2], sections[count - 1].End1); FamilyInstance fiii = null; if (connEnd1 != null && connEnd2 != null) { try { fiii = m_rvtDoc.Create.NewElbowFitting(connEnd1, connEnd2); } catch (Exception ex) { string strmsg = ex.Message; } } // �浹 ȸ�� �� ��Ʈ ���� m_rvtDoc.Delete(duct.Id); } private void Bend(Duct duct, Pipe obstruction) { // duct.LookupParameter(string name) var paramLevel = duct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM); var levelId = paramLevel.AsElementId(); var systemTypeId = m_ductSystemType.Id; // ��Ʈ ������ var halfWidth = GetDuctWidth(duct) * 0.5; var halfHeight = GetDuctHeight(duct) * 0.5; // ��Ʈ �߽ɼ��� ���Ѵ�. Line ductLine = (duct.Location as LocationCurve).Curve as Line; Autodesk.Revit.DB.XYZ startPt = ductLine.GetEndPoint(0); Autodesk.Revit.DB.XYZ endPt = ductLine.GetEndPoint(1); Autodesk.Revit.DB.XYZ axisZ = (endPt - startPt).Normalize(); double ductLength = startPt.DistanceTo(endPt); XYZ axisX = new XYZ(); XYZ axisY = new XYZ(); KDCS.Utils.Util.AxesXY(axisZ, ref axisX, ref axisY); XYZ orgR = startPt + axisX * halfWidth; XYZ orgL = startPt - axisX * halfWidth; XYZ orgT = startPt + axisY * halfHeight; XYZ orgB = startPt - axisY * halfHeight; // �浹 Ȯ�μ� Line checkLeftLine = Line.CreateBound(orgL, orgL + axisZ * ductLength); Line checkRightLine = Line.CreateBound(orgR, orgR + axisZ * ductLength); Line checkTopLine = Line.CreateBound(orgT, orgT + axisZ * ductLength); Line checkBottomLine = Line.CreateBound(orgB, orgB + axisZ * ductLength); // ��Ʈ�� �߽ɼ����� ��������(�浹��)�� ����Ѵ�. List obstructionTopRefArr = m_detector.Obstructions(checkTopLine); List obstructionBottomRefArr = m_detector.Obstructions(checkBottomLine); List obstructionLeftRefArr = m_detector.Obstructions(checkLeftLine); List obstructionRightRefArr = m_detector.Obstructions(checkRightLine); // ��������(�浹��) �� ��Ʈ,������, �� ������ ����Ѵ�. // duct: �� �ڽ��� ���ܽ�Ű������ Filter(duct, obstructionTopRefArr); Filter(duct, obstructionBottomRefArr); Filter(duct, obstructionLeftRefArr); Filter(duct, obstructionRightRefArr); List obstructionRefArr = null; // ��->��->��->�� ������ if (obstructionTopRefArr.Count > 0) obstructionRefArr = obstructionTopRefArr; // �� if (obstructionBottomRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionBottomRefArr; // �� else obstructionRefArr.AddRange(obstructionBottomRefArr); // ��,�� ��� ���� �߻� } if (obstructionRefArr == null) { if (obstructionLeftRefArr.Count > 0) obstructionRefArr = obstructionLeftRefArr; // �� if (obstructionRightRefArr.Count > 0) { if (obstructionRefArr == null) obstructionRefArr = obstructionRightRefArr; // �� else obstructionRefArr.AddRange(obstructionRightRefArr); // ��,�� ��� ���� �߻� } } // ������ �������� �ʴ´�. if (obstructionRefArr == null) return; if (obstructionRefArr.Count == 0) return; // ���� �����κ��� ������ �ۼ��Ѵ�. obstructionRefArr.Sort(m_detector.CompareReferencesWithContext); List
sections = Section.BuildSections(obstructionRefArr, ductLine.Direction); List
lstSectionTmp = new List
(); lstSectionTmp.AddRange(sections); // �ߺ� ���� ����->���� ��ġ�� �������� Section�� �߻��� ��� �ߺ� ���� if (sections.Count > 1) { while (lstSectionTmp.Count > 0) { Section section1 = lstSectionTmp[0]; lstSectionTmp.RemoveAt(0); var intResult1 = ductLine.Project(KDCS.Utils.Util.Midpoint(section1.Start, section1.End)); foreach (Section section2 in lstSectionTmp) { var intResult2 = ductLine.Project(KDCS.Utils.Util.Midpoint(section2.Start, section2.End)); if (intResult2 != null) { if (intResult1.XYZPoint.DistanceTo(intResult2.XYZPoint) < halfHeight) { sections.Remove(section2); break; } } } } } // ���� ������ �Ÿ��� �ʹ� ª�� ��� ������ �����Ѵ�. double width = GetDuctWidth(duct); for (int i = sections.Count - 2; i >= 0; i--) { Autodesk.Revit.DB.XYZ detal = sections[i].End - sections[i + 1].Start; if (detal.GetLength() < width * 3) { sections[i].Refs.AddRange(sections[i + 1].Refs); sections.RemoveAt(i + 1); } } // ��ֹ��� �ϳ��� �ذ�. foreach (Section sec in sections) { Resolve(duct, sec); } // ��Ʈ �� ���� �������� ���� ���� �����Ѵ�. for (int i = 1; i < sections.Count; i++) { // Get the end point from the previous section. Autodesk.Revit.DB.XYZ start = sections[i - 1].End1; // Get the start point from the current section. Autodesk.Revit.DB.XYZ end = sections[i].Start1; // Create a duct between two neighbor section. Duct tmpDuct = Duct.Create(m_rvtDoc, systemTypeId, duct.DuctType.Id, levelId, start, end); // Copy pipe's parameters values to tmpPipe. CopyParameters(duct, tmpDuct); // Create elbow fitting to connect previous section with tmpPipe. Connector conn1 = FindConnector(sections[i - 1].Ducts[2], start); Connector conn2 = FindConnector(tmpDuct, start); if (conn1 != null && conn2 != null) { FamilyInstance fi = null; try { fi = m_rvtDoc.Create.NewElbowFitting(conn1, conn2); } catch (Exception ex) { string strmsg = ex.Message; } } // Create elbow fitting to connect current section with tmpPipe. Connector conn3 = FindConnector(sections[i].Ducts[0], end); Connector conn4 = FindConnector(tmpDuct, end); if (conn3 != null && conn4 != null) { FamilyInstance f2 = null; try { f2 = m_rvtDoc.Create.NewElbowFitting(conn3, conn4); } catch (Exception ex) { string strmsg = ex.Message; } } } // Find two connectors which pipe's two ends connector connected to. Connector startConn = FindConnectedTo(duct, ductLine.GetEndPoint(0)); Connector endConn = FindConnectedTo(duct, ductLine.GetEndPoint(1)); Duct startDuct = null; if (null != startConn) { // Create a pipe between pipe's start connector and pipe's start section. startDuct = Duct.Create(m_rvtDoc, duct.DuctType.Id, levelId, startConn, sections[0].Start1); } else { // Create a pipe between pipe's start point and pipe's start section. startDuct = Duct.Create(m_rvtDoc, systemTypeId, duct.DuctType.Id, levelId, sections[0].Start1, ductLine.GetEndPoint(0)); } // Copy parameters from pipe to startPipe. CopyParameters(duct, startDuct); // starDuct�� ù ��° ������ ���� �������� ���� Connector connStart1 = FindConnector(startDuct, sections[0].Start1); Connector connStart2 = FindConnector(sections[0].Ducts[0], sections[0].Start1); FamilyInstance fii = null; if (connStart1 != null && connStart2 != null) { try { fii = m_rvtDoc.Create.NewElbowFitting(connStart1, connStart2); } catch (Exception ex) { string strmsg = ex.Message; } } Duct endDuct = null; int count = sections.Count; if (null != endConn) { // Create a pipe between pipe's end connector and pipe's end section. endDuct = Duct.Create(m_rvtDoc, duct.DuctType.Id, levelId, endConn, sections[count - 1].End1); } else { // Create a pipe between pipe's end point and pipe's end section. endDuct = Duct.Create(m_rvtDoc, systemTypeId, duct.DuctType.Id, levelId, sections[count - 1].End1, ductLine.GetEndPoint(1)); } // Copy parameters from pipe to endPipe. CopyParameters(duct, endDuct); // endDuct�� ������ ������ ���� �������� ���� Connector connEnd1 = FindConnector(endDuct, sections[count - 1].End1); Connector connEnd2 = FindConnector(sections[count - 1].Ducts[2], sections[count - 1].End1); FamilyInstance fiii = null; if (connEnd1 != null && connEnd2 != null) { try { fiii = m_rvtDoc.Create.NewElbowFitting(connEnd1, connEnd2); } catch (Exception ex) { string strmsg = ex.Message; } } // �浹 ȸ�� �� ��Ʈ ���� m_rvtDoc.Delete(duct.Id); } /// /// 주어진 덕트가 충돌요소를 회피유형과 여유공간 높이에 따라 회피하도록 한다. /// /// 회피요소 /// 충돌요소 private void Run(Duct duct, Element eObstruction) { if (eObstruction.GetType() == typeof(Duct)) { Bend(duct, eObstruction as Duct); }else if (eObstruction.GetType() == typeof(Pipe)) { Bend(duct, eObstruction as Pipe); } } /// /// Filter the inputting References, just allow Pipe, Duct and Beam References. /// /// Pipe /// References to filter private void Filter(Pipe pipe, List refs) { for (int i = refs.Count - 1; i >= 0; i--) { Reference cur = refs[i].GetReference(); Element curElem = m_rvtDoc.GetElement(cur); if (curElem.Id == pipe.Id || (!(curElem is Pipe) && !(curElem is Duct) && curElem.Category.Id.IntegerValue != (int)BuiltInCategory.OST_StructuralFraming)) { refs.RemoveAt(i); } } } private void Filter(Duct duct, List refs) { for (int i = refs.Count - 1; i >= 0; i--) { Reference cur = refs[i].GetReference(); Element curElem = m_rvtDoc.GetElement(cur); // �־��� ��Ʈ �ڽ��� �ƴ� ��Ʈ,�� �� �ϳ����� �Ѵ�. if (curElem.Id == duct.Id || (!(curElem is Duct) && curElem.Category.Id.IntegerValue != (int)BuiltInCategory.OST_StructuralFraming)) { refs.RemoveAt(i); } } } /// /// This method will find out a route to avoid the obstruction. /// /// Pipe to resolve /// Pipe's one obstruction /// A route which can avoid the obstruction private Line FindRoute(Pipe pipe, Section section) { // Perpendicular direction minimal length. double minLength = pipe.Diameter * 2; // Parallel direction jump step. double jumpStep = pipe.Diameter; // Calculate the directions in which to find the solution. List dirs = new List(); Autodesk.Revit.DB.XYZ crossDir = null; foreach (ReferenceWithContext gref in section.Refs) { Element elem = m_rvtDoc.GetElement(gref.GetReference()); Line locationLine = (elem.Location as LocationCurve).Curve as Line; Autodesk.Revit.DB.XYZ refDir = locationLine.GetEndPoint(1) - locationLine.GetEndPoint(0); refDir = refDir.Normalize(); if (refDir.IsAlmostEqualTo(section.CenterLineDirection) || refDir.IsAlmostEqualTo(-section.CenterLineDirection)) { continue; } crossDir = refDir.CrossProduct(section.CenterLineDirection); dirs.Add(crossDir.Normalize()); break; } // When all the obstruction are parallel with the centerline of the pipe, // We can't calculate the direction from the vector.Cross method. if (dirs.Count == 0) { // Calculate perpendicular directions with dir in four directions. List perDirs = PerpendicularDirs(section.CenterLineDirection, 4); dirs.Add(perDirs[0]); dirs.Add(perDirs[1]); } Line foundLine = null; while (null == foundLine) { // Extend the section interval by jumpStep. section.Inflate(0, jumpStep); section.Inflate(1, jumpStep); // Find solution in the given directions. for (int i = 0; null == foundLine && i < dirs.Count; i++) { // Calculate the intersections. List obs1 = m_detector.Obstructions(section.Start, dirs[i]); List obs2 = m_detector.Obstructions(section.End, dirs[i]); // Filter out the intersection result. Filter(pipe, obs1); Filter(pipe, obs2); // Find out the minimal intersections in two opposite direction. ReferenceWithContext[] mins1 = GetClosestSectionsToOrigin(obs1); ReferenceWithContext[] mins2 = GetClosestSectionsToOrigin(obs2); // Find solution in the given direction and its opposite direction. for (int j = 0; null == foundLine && j < 2; j++) { if (mins1[j] != null && Math.Abs(mins1[j].Proximity) < minLength || mins2[j] != null && Math.Abs(mins2[j].Proximity) < minLength) { continue; } // Calculate the maximal height that the parallel line can be reached. double maxHeight = 0; if (mins1[j] != null && mins2[j] != null) { maxHeight = Math.Min(Math.Abs(mins1[j].Proximity), Math.Abs(mins2[j].Proximity)); } else if (mins1[j] != null) { maxHeight = Math.Abs(mins1[j].Proximity); } else if (mins2[j] != null) { maxHeight = Math.Abs(mins2[j].Proximity); } if (maxHeight < jumpStep * 3) maxHeight = jumpStep * 3; Autodesk.Revit.DB.XYZ dir = (j == 1) ? dirs[i] : -dirs[i]; // Calculate the parallel line which can avoid obstructions. foundLine = FindParallelLine(pipe, section, dir, maxHeight); } } } return foundLine; } /// /// This method will find out a route to avoid the obstruction. /// /// Pipe to resolve /// Pipe's one obstruction /// ��ֹ��� ���Ҽ� �ִ� ��Ʈ �߽ɼ��� ������ ��θ� ã�´�. private Line FindRoute(Duct duct, Section section) { // �������� �ּ� ���� double minLength = GetDuctWidth(duct); // Parallel direction jump step. double jumpStep = GetDuctHeight(duct); // ���ع��� ���� �� �ִ� ������ ����Ѵ�. List dirs = new List(); XYZ ptMidSection = KDCS.Utils.Util.Midpoint(section.Start, section.End); // ���� �߽��� Line locationLineSelf = (duct.Location as LocationCurve).Curve as Line; Autodesk.Revit.DB.XYZ selfDir = locationLineSelf.GetEndPoint(1) - locationLineSelf.GetEndPoint(0); Line ublineSelf = Line.CreateUnbound(locationLineSelf.GetEndPoint(0), selfDir); //Autodesk.Revit.DB.XYZ crossDir = null; foreach (ReferenceWithContext gref in section.Refs) { Element elem = m_rvtDoc.GetElement(gref.GetReference()); Line locationObstructionLine = (elem.Location as LocationCurve).Curve as Line; Autodesk.Revit.DB.XYZ refObstructionDir = locationObstructionLine.GetEndPoint(1) - locationObstructionLine.GetEndPoint(0); refObstructionDir.Normalize(); if (refObstructionDir.IsAlmostEqualTo(section.CenterLineDirection) || refObstructionDir.IsAlmostEqualTo(-section.CenterLineDirection)) { continue; } //crossDir = refDir.CrossProduct(section.CenterLineDirection); Line ubObstructionLineOther = Line.CreateUnbound(locationObstructionLine.GetEndPoint(0), refObstructionDir); var ptOnDuct = ubObstructionLineOther.Project(ptMidSection); if (ptOnDuct != null) { // ��ֹ� �߽ɿ��� ���� �߽��� ���� XYZ v1 = (ptOnDuct.XYZPoint - ptMidSection).Normalize(); if (v1.GetLength() > 0) { dirs.Add(v1); break; } } } // ��� ��ֹ��� ��Ʈ�� �߽ɼ��� �����ϸ� vector.Cross �Լ��� �̿��Ͽ� ������ ����� �� ����. if (dirs.Count == 0) { // Calculate perpendicular directions with dir in four directions. List perDirs = PerpendicularDirs(section.CenterLineDirection, 4); dirs.Add(perDirs[0]); dirs.Add(perDirs[1]); } Line foundLine = null; while (null == foundLine) { // jumpStep ��ŭ ������ Ȯ���Ѵ�. section.Inflate(0, jumpStep); section.Inflate(1, jumpStep); // �־��� ���⿡�� �ذ�å�� ã�´�. for (int i = 0; null == foundLine && i < dirs.Count; i++) { // ������ ��� List obs1 = m_detector.Obstructions(section.Start, dirs[i]); List obs2 = m_detector.Obstructions(section.End, dirs[i]); // ���� ������� �ڱ� �ڽ��� ��� �Ǵ� ��Ʈ, ������, ���� �ƴ� ��� ���͸� Filter(duct, obs1); Filter(duct, obs2); // �ΰ��� �ݴ� ���⿡�� �ּ� �������� ã�´�. ReferenceWithContext[] mins1 = GetClosestSectionsToOrigin(obs1); ReferenceWithContext[] mins2 = GetClosestSectionsToOrigin(obs2); // �־��� ����� �ݴ� ���⿡�� �ַ���� ã�´�. for (int j = 0; null == foundLine && j < 2; j++) { if (mins1[j] != null && Math.Abs(mins1[j].Proximity) < minLength || mins2[j] != null && Math.Abs(mins2[j].Proximity) < minLength) { continue; } // ���༱�� ���� �� �� �ִ� �ִ� ���̸� ����Ѵ�. double maxHeight = 0d; if (mins1[j] != null && mins2[j] != null) { maxHeight = Math.Max(Math.Abs(mins1[j].Proximity), Math.Abs(mins2[j].Proximity)); } else if (mins1[j] != null) { maxHeight = Math.Abs(mins1[j].Proximity); } else if (mins2[j] != null) { maxHeight = Math.Abs(mins2[j].Proximity); } if (maxHeight < jumpStep*3) maxHeight = jumpStep*3; Autodesk.Revit.DB.XYZ dir = (j == 1) ? dirs[i] : -dirs[i]; // ��ֹ��� ���� �� �ִ� ���༱ ��� foundLine = FindParallelLine(duct, section, dir, maxHeight); } } } return foundLine; } /// /// Find a line Parallel to pipe's centerline to avoid the obstruction. /// /// Pipe who has obstructions /// Pipe's one obstruction /// Offset Direction of the parallel line /// Maximum offset distance /// Parallel line which can avoid the obstruction private Line FindParallelLine(Pipe pipe, Section section, Autodesk.Revit.DB.XYZ dir, double maxLength) { double step = pipe.Diameter; double height = 2 * pipe.Diameter; while (height <= maxLength) { Autodesk.Revit.DB.XYZ detal = dir * height; Line line = Line.CreateBound(section.Start + detal, section.End + detal); List refs = m_detector.Obstructions(line); Filter(pipe, refs); if (refs.Count == 0) { return line; } height += step; } return null; } private Line FindParallelLine(Duct duct, Section section, Autodesk.Revit.DB.XYZ dir, double maxLength) { double step = duct.Width; double height = 2 * duct.Height; while (height <= maxLength) { Autodesk.Revit.DB.XYZ detal = dir * height; Line line = Line.CreateBound(section.Start + detal, section.End + detal); List refs = m_detector.Obstructions(line); Filter(duct, refs); if (refs.Count == 0) { return line; } height += step; } return null; } /// /// Find out two References, whose ProximityParameter is negative or positive, /// And Get the minimal value from all positive reference, and get the maximal value /// from the negative reference. if there are no such reference, using null instead. /// /// References /// Reference array private ReferenceWithContext[] GetClosestSectionsToOrigin(List refs) { ReferenceWithContext[] mins = new ReferenceWithContext[2]; if (refs.Count == 0) { return mins; } if (refs[0].Proximity > 0) { mins[1] = refs[0]; return mins; } for (int i = 0; i < refs.Count - 1; i++) { if (refs[i].Proximity < 0 && refs[i + 1].Proximity > 0) { mins[0] = refs[i]; mins[1] = refs[i + 1]; return mins; } } mins[0] = refs[refs.Count - 1]; return mins; } public void MepSystem() { 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)) { Autodesk.Revit.DB.Plumbing.PipeSystemType type = (system as Autodesk.Revit.DB.Plumbing.PipingSystem).SystemType; } string name = system.Name; } } } public Pipe CreateNewPipe(Document document, ElementId systemTypeId, ElementId levelId) { Pipe pipe = null; PipeType pipeType = null; // find a pipe type var pipeTypes = new FilteredElementCollector(document).OfClass(typeof(PipeType)).ToElements(); if(pipeTypes.Count>0){ pipeType = pipeTypes[pipeTypes.Count - 1] as PipeType; } if (pipeType == null) return null; // create pipe between 2 points XYZ p1 = new XYZ(0, 0, 0); XYZ p2 = new XYZ(10, 0, 0); pipe = Pipe.Create(document, systemTypeId, pipeType.Id, levelId, p1, p2); return pipe; } /// /// Resolve one obstruction of Pipe. /// /// Pipe to resolve /// One pipe's obstruction private void Resolve(Pipe pipe, Section section) { // Find out a parallel line of pipe centerline, which can avoid the obstruction. Line offset = FindRoute(pipe, section); XYZ dir = offset.Direction; // �־��� ���ǿ� ���� ���� ���� �����. Line pipeLine = (pipe.Location as LocationCurve).Curve as Line; XYZ sectionStart = pipeLine.Project(section.Start).XYZPoint; XYZ sectionEnd = pipeLine.Project(section.End).XYZPoint; Line sectionLine = Line.CreateBound(sectionStart, sectionEnd); double x_offset = 0; XYZ ptStart = sectionLine.GetEndPoint(0); XYZ ptEnd = sectionLine.GetEndPoint(1); if (x_offset > 0) { ptStart = ptStart - dir * x_offset; ptEnd = ptEnd + dir * x_offset; } section.Start1 = ptStart; section.End1 = ptEnd; // Construct two side lines, which can avoid the obstruction too. Line side1 = Line.CreateBound(sectionLine.GetEndPoint(0), offset.GetEndPoint(0)); Line side2 = Line.CreateBound(offset.GetEndPoint(1), sectionLine.GetEndPoint(1)); // // Create an "U" shape, which connected with three pipes and two elbows, to round the obstruction. // PipeType pipeType = pipe.PipeType; Autodesk.Revit.DB.XYZ start = side1.GetEndPoint(0); Autodesk.Revit.DB.XYZ startOffset = offset.GetEndPoint(0); Autodesk.Revit.DB.XYZ endOffset = offset.GetEndPoint(1); Autodesk.Revit.DB.XYZ end = side2.GetEndPoint(1); var parameter = pipe.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM); var levelId = parameter.AsElementId(); // Create three side pipes of "U" shape. var systemTypeId = m_pipingSystemType.Id; Pipe pipe1 = Pipe.Create(m_rvtDoc, systemTypeId, pipeType.Id, levelId, start, startOffset); Pipe pipe2 = Pipe.Create(m_rvtDoc, systemTypeId, pipeType.Id, levelId, startOffset, endOffset); Pipe pipe3 = Pipe.Create(m_rvtDoc, systemTypeId, pipeType.Id, levelId, endOffset, end); // Copy parameters from pipe to other three created pipes. CopyParameters(pipe, pipe1); CopyParameters(pipe, pipe2); CopyParameters(pipe, pipe3); // Add the created three pipes to current section. section.Pipes.Add(pipe1); section.Pipes.Add(pipe2); section.Pipes.Add(pipe3); // Create the first elbow to connect two neighbor pipes of "U" shape. Connector conn1 = FindConnector(pipe1, startOffset); Connector conn2 = FindConnector(pipe2, startOffset); m_rvtDoc.Create.NewElbowFitting(conn1, conn2); // Create the second elbow to connect another two neighbor pipes of "U" shape. Connector conn3 = FindConnector(pipe2, endOffset); Connector conn4 = FindConnector(pipe3, endOffset); m_rvtDoc.Create.NewElbowFitting(conn3, conn4); } /// /// ��Ʈ�� ��ֹ��κ��� ȸ���Ѵ�. /// /// ȸ���� ��Ʈ /// ��Ʈ �ϳ��� ��ֹ� private void Resolve(Duct duct, Section section) { // ��ֹ��� ���� �� �ִ� ��Ʈ �߽ɼ����� ���༱�� ���Ѵ�. Line offset = FindRoute(duct, section); var ductHeight = GetDuctHeight(duct); var section_len = section.Start.DistanceTo(section.End); if (section_len < ductHeight*2.5) { section.Inflate(0, ductHeight * 1.5); section.Inflate(1, ductHeight * 1.5); } // �־��� ���ǿ� ���� ���� ���� �����. Line ductLine = (duct.Location as LocationCurve).Curve as Line; XYZ sectionStart = ductLine.Project(section.Start).XYZPoint; XYZ sectionEnd = ductLine.Project(section.End).XYZPoint; Line sectionLine = Line.CreateBound(sectionStart, sectionEnd); XYZ dir = (offset.GetEndPoint(1) - offset.GetEndPoint(0)).Normalize(); XYZ xa = new XYZ(); XYZ ya = new XYZ(); KDCS.Utils.Util.AxesXY(dir, ref xa, ref ya); Plane geometryPlane = Plane.CreateByNormalAndOrigin(ya, offset.GetEndPoint(0)); SketchPlane plane = SketchPlane.Create(m_rvtDoc, geometryPlane); if (plane != null) { m_rvtDoc.Create.NewModelCurve(Line.CreateBound(offset.Origin, offset.Origin + offset.Direction * 20), plane); } double x_offset = sectionLine.GetEndPoint(0).DistanceTo(offset.GetEndPoint(0)); XYZ ptStart = sectionLine.GetEndPoint(0) - dir * x_offset; XYZ ptEnd = sectionLine.GetEndPoint(1) + dir * x_offset; section.Start1 = ptStart; section.End1 = ptEnd; // Construct two side lines, which can avoid the obstruction too. Line side1 = Line.CreateBound(ptStart, offset.GetEndPoint(0)); Line side2 = Line.CreateBound(offset.GetEndPoint(1), ptEnd); // // Create an "U" shape, which connected with three pipes and two elbows, to round the obstruction. // DuctType ductType = duct.DuctType; Autodesk.Revit.DB.XYZ start = side1.GetEndPoint(0); Autodesk.Revit.DB.XYZ startOffset = offset.GetEndPoint(0); Autodesk.Revit.DB.XYZ endOffset = offset.GetEndPoint(1); Autodesk.Revit.DB.XYZ end = side2.GetEndPoint(1); var parameter = duct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM); var levelId = parameter.AsElementId(); // Create three side pipes of "U" shape. var systemTypeId = m_ductSystemType.Id; Duct duct1 = Duct.Create(m_rvtDoc, systemTypeId, ductType.Id, levelId, start, startOffset); Duct duct2 = Duct.Create(m_rvtDoc, systemTypeId, ductType.Id, levelId, startOffset, endOffset); Duct duct3 = Duct.Create(m_rvtDoc, systemTypeId, ductType.Id, levelId, endOffset, end); // Copy parameters from pipe to other three created pipes. CopyParameters(duct, duct1); CopyParameters(duct, duct2); CopyParameters(duct, duct3); // Add the created three pipes to current section. section.Ducts.Add(duct1); section.Ducts.Add(duct2); section.Ducts.Add(duct3); // Create the first elbow to connect two neighbor pipes of "U" shape. Connector conn1 = FindConnector(duct1, startOffset); Connector conn2 = FindConnector(duct2, startOffset); m_rvtDoc.Create.NewElbowFitting(conn1, conn2); // Create the second elbow to connect another two neighbor pipes of "U" shape. Connector conn3 = FindConnector(duct2, endOffset); Connector conn4 = FindConnector(duct3, endOffset); m_rvtDoc.Create.NewElbowFitting(conn3, conn4); } /// /// Copy parameters from source pipe to target pipe. /// /// Coping source /// Coping target private void CopyParameters(Pipe source, Pipe target) { double diameter = source.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble(); target.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(diameter); } private void CopyParameters(Duct source, Duct target) { ConnectorProfileType shape = KDCS.Utils.Util.GetShape(source); if (shape == ConnectorProfileType.Round) { double diameter = source.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).AsDouble(); target.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).Set(diameter); } else if (shape == ConnectorProfileType.Rectangular) { double width = source.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).AsDouble(); target.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(width); double height = source.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).AsDouble(); target.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(height); } else if (shape == ConnectorProfileType.Oval) { double width = source.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).AsDouble(); target.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(width); double height = source.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).AsDouble(); target.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(height); } } /// /// Find out a connector from pipe with a specified point. /// /// Pipe to find the connector /// Specified point /// Connector whose origin is conXYZ private Connector FindConnector(Pipe pipe, Autodesk.Revit.DB.XYZ conXYZ) { ConnectorSet conns = pipe.ConnectorManager.Connectors; foreach (Connector conn in conns) { if (conn.Origin.IsAlmostEqualTo(conXYZ)) { return conn; } } return null; } private Connector FindConnector(Duct duct, Autodesk.Revit.DB.XYZ conXYZ) { ConnectorSet conns = duct.ConnectorManager.Connectors; foreach (Connector conn in conns) { if (conn.Origin.IsAlmostEqualTo(conXYZ)) { return conn; } } return null; } /// /// Find out the connector which the pipe's specified connector connected to. /// The pipe's specified connector is given by point conxyz. /// /// Pipe to find the connector /// Specified point /// Connector whose origin is conXYZ private Connector FindConnectedTo(Pipe pipe, Autodesk.Revit.DB.XYZ conXYZ) { Connector connItself = FindConnector(pipe, conXYZ); ConnectorSet connSet = connItself.AllRefs; foreach (Connector conn in connSet) { if (conn.Owner.Id.IntegerValue != pipe.Id.IntegerValue && conn.ConnectorType == ConnectorType.End) { return conn; } } return null; } private Connector FindConnectedTo(Duct duct, Autodesk.Revit.DB.XYZ conXYZ) { Connector connItself = FindConnector(duct, conXYZ); ConnectorSet connSet = connItself.AllRefs; foreach (Connector conn in connSet) { if (conn.Owner.Id.IntegerValue != duct.Id.IntegerValue && conn.ConnectorType == ConnectorType.End) { return conn; } } return null; } } }