using System; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Plumbing; using KDCS.UtilsGe; using System.Collections.Generic; using KDCS.Utils; namespace KMBIM.Revit.Tools.Utils { public enum Orientation { Undefined = 0, Vertical=1, Horizontal=2 } public class KDCSIntersectorElement { public XYZ HitPoint { get; set; } private Element _Element; private Document _LinkDocument; private RevitLinkInstance _RevitLinkInstance; public Element Element { get { return _Element; } set{ _Element = value; Id = _Element.Id; _RevitLinkInstance = null; ElementType = _Element.GetType(); Orientation = Utils.Orientation.Vertical; Line = GetLine(); StartPoint = new XYZ(Line.GetEndPoint(0).X, Line.GetEndPoint(0).Y, Line.GetEndPoint(0).Z); EndPoint = new XYZ(Line.GetEndPoint(1).X, Line.GetEndPoint(1).Y, Line.GetEndPoint(1).Z); StartConnector = GetClosestConnector(StartPoint); EndConnector = GetClosestConnector(EndPoint); Direction = new Vector(StartPoint, EndPoint); GetSize(); GetIntersectorLine(); } } public ElementId Id { get; set; } public Type ElementType { get; set; } public Orientation Orientation { get; set; } public Vector Direction { get; set; } public double Width { get; set; } public double Height { get; set; } public XYZ StartPoint { get; set; } public XYZ EndPoint { get; set; } public Line Line { get; set; } public Line LineTop { get; set; } public Line LineBottom { get; set; } public Line LineLeft { get; set; } public Line LineRight { get; set; } public Connector StartConnector { get; set; } public Connector EndConnector { get; set; } public KDCSIntersectorElement(Element element, XYZ hitPoint = null, Document doc = null) { _LinkDocument = doc; Element = element; HitPoint = hitPoint; } public Document GetLinkDocument() { return _LinkDocument; } public void SetRevitLinkInstance(RevitLinkInstance rli) { _RevitLinkInstance = rli; } public RevitLinkInstance GetRevitLinkInstance() { return _RevitLinkInstance; } public Line GetLine() { if (this.ElementType == typeof(Duct)) { Duct duct = _Element as Duct; var line = (duct.Location as LocationCurve).Curve as Line; return line; } else if (this.ElementType == typeof(Pipe)) { Pipe pipe = _Element as Pipe; var line = (pipe.Location as LocationCurve).Curve as Line; return line; } else if (this.ElementType == typeof(Conduit)) { Conduit conduit = _Element as Conduit; var line = (conduit.Location as LocationCurve).Curve as Line; return line; } else if (this.ElementType == typeof(CableTray)) { CableTray cableTray = _Element as CableTray; var line = (cableTray.Location as LocationCurve).Curve as Line; return line; } else if (this.ElementType == typeof(FamilyInstance)) { FamilyInstance fi = _Element as FamilyInstance; var line = (fi.Location as LocationCurve).Curve as Line; return line; } return null; } 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; } public 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; } } // 주어진 점과 가장 가까운 커넥터를 찾는다. public Connector GetClosestConnector(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 connector2 in conMan.Connectors) { // 기준 파이프에 연결될 파이프 dst = pt.DistanceTo(connector2.Origin); if (dst < minDst) { minConnector = connector2; minDst = dst; } } } return minConnector; } private void GetSize() { if (ElementType == typeof(Pipe)) { Pipe pipe = _Element as Pipe; Width = pipe.Diameter; Height = pipe.Diameter; } else if (ElementType == typeof(Duct)) { Duct duct = _Element as Duct; Width = GetDuctWidth(duct); Height = GetDuctHeight(duct); } else if (ElementType == typeof(CableTray)) { CableTray cableTray = _Element as CableTray; Width = cableTray.Width; Height = cableTray.Height; } else if (ElementType == typeof(Conduit)) { Conduit conduit = _Element as Conduit; Width = conduit.Diameter; Height = conduit.Diameter; } else if (ElementType == typeof(FamilyInstance)) { FamilyInstance fi = _Element as FamilyInstance; var line = (fi.Location as LocationCurve).Curve as Line; XYZ mp = Util.Midpoint(line.GetEndPoint(0), line.GetEndPoint(1)); // 구조 프레임의 전체 면을 구한다. List faTB = new List(); List faLR = new List(); var tr = fi.GetTransform(); Options opt = App.uiApplication.Application.Create.NewGeometryOptions(); opt.ComputeReferences = true; opt.IncludeNonVisibleObjects = false; opt.View = App.uiApplication.ActiveUIDocument.Document.ActiveView; GeometryElement geo = fi.Symbol.get_Geometry(opt); GeometryElement trgeo = geo.GetTransformed(tr); foreach (GeometryObject obj in trgeo) { Solid solid = obj as Solid; if (solid != null) { FaceArray fai = solid.Faces; foreach (Face f in fai) { PlanarFace pf = f as PlanarFace; if (null != pf) { if(Util.IsParallel(pf.FaceNormal, XYZ.BasisZ)) faTB.Add(pf); else faLR.Add(pf); }//end-if }//end-foreach }//end-if }//end-foreach if (faTB.Count > 0) { PlanarFace maxPf = null; double maxArea = 0; foreach (PlanarFace pf in faTB) { if (maxArea < pf.Area) { maxArea = pf.Area; maxPf = pf; } } var itr = maxPf.Project(mp); double l1 = itr != null ? itr.XYZPoint.DistanceTo(mp) : 0.9; Width = l1 * 2.0; } if (faLR.Count > 0) { PlanarFace maxPf = null; double maxArea = 0; foreach (PlanarFace pf in faLR) { if (maxArea < pf.Area) { maxArea = pf.Area; maxPf = pf; } } var itr = maxPf.Project(mp); double l1 = itr != null ? itr.XYZPoint.DistanceTo(mp) : 0.65; Height = l1 * 2.0; } } } // 교차 확인 선 작성 private void GetIntersectorLine() { XYZ org = Line.GetEndPoint(0); double halfWidth = Width * 0.5; double halfHeight = Height * 0.5; if (this.ElementType == typeof(FamilyInstance)) { Category cat = this.Element.Category; if (cat != null) { // 구조 보 if (cat.Id.IntegerValue.Equals((int)BuiltInCategory.OST_StructuralFraming)) { XYZ vz = Line.Direction.Normalize(); XYZ vy = XYZ.BasisZ; XYZ vx = vz.CrossProduct(vy); XYZ orgR = org + vx * halfWidth; XYZ orgL = org - vx * halfWidth; XYZ orgT = org + vy * halfHeight; XYZ orgB = org - vy * halfHeight; LineLeft = Line.CreateBound(orgL, orgL + vz * Line.Length); LineRight = Line.CreateBound(orgR, orgR + vz * Line.Length); LineTop = Line.CreateBound(orgT, orgT + vz * Line.Length); LineBottom = Line.CreateBound(orgB, orgB + vz * Line.Length); } } }else{ XYZ orgR = org + EndConnector.CoordinateSystem.BasisX * halfWidth; XYZ orgL = org - EndConnector.CoordinateSystem.BasisX * halfWidth; XYZ orgT = org + EndConnector.CoordinateSystem.BasisY * halfHeight; XYZ orgB = org - EndConnector.CoordinateSystem.BasisY * halfHeight; XYZ v1 = Direction.Instance.Normalize(); LineLeft = Line.CreateBound(orgL, orgL + v1 * Line.Length); LineRight = Line.CreateBound(orgR, orgR + v1 * Line.Length); LineTop = Line.CreateBound(orgT, orgT + v1 * Line.Length); LineBottom = Line.CreateBound(orgB, orgB + v1 * Line.Length); } } } }