Client/Desktop/KMBIM3.0/KMBIM3.0_소스/Utils/KDCSCurveElement.cs

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);
}
}
}
}