338 lines
12 KiB
C#
338 lines
12 KiB
C#
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<PlanarFace> faTB = new List<PlanarFace>();
|
|
List<PlanarFace> faLR = new List<PlanarFace>();
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|