Client/Desktop/KMBIM3.0/23.11.03/Cmd/Dimension/PipeRealDim.cs

487 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.Creation;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Structure;
using System.Windows.Forms;
using Autodesk.Revit.ApplicationServices;
using KDCS.Utils;
using KMBIM.Revit.Tools;
namespace KMBIM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class PipeRealDim : IExternalCommand
{
UIApplication uiapp;
UIDocument uidoc;
Autodesk.Revit.DB.Document doc;
Autodesk.Revit.Creation.Application creApp;
Autodesk.Revit.Creation.Document creDoc;
Autodesk.Revit.DB.View view;
ExternalCommandData m_commandData;
LanguageType lang;
List<ElementId> m_ElemIDLst = new List<ElementId>();
List<ElementId> m_MainElemIDLst1 = new List<ElementId>();//선택한 파이프의 시작점 방향 커넥터 모음
List<ElementId> m_MainElemIDLst2 = new List<ElementId>();//선택한 파이프의 끝점 방향 커넥터 모음
public Autodesk.Revit.UI.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;
doc = uidoc.Document;
m_commandData = commandData;
creApp = uiapp.Application.Create;
creDoc = doc.Create;
view = doc.ActiveView;
lang = commandData.Application.Application.Language;
try
{
//파이프 선택
Reference pickRef = uidoc.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "치수 기입할 배관 선택 : ");
//Reference pipeRef = uidoc.Selection.PickObject(ObjectType.Element, "치수 기입할 배관 선택 : ");
//IList<Reference> refs = uidoc.Selection.PickObjects(ObjectType.Element, "치수 기입 : ");
//방향 지정
XYZ directPt = null;
Util.PickPoint(uidoc, "치수 방향을 지정하세요.", ref directPt);
XYZ sp1 = null, ep1 = null;
ConnectorSet connectorSet = new ConnectorSet();
if (pickRef == null || directPt == null)
return Result.Succeeded;
else
{
Element e = doc.GetElement(pickRef);
if (e is Pipe)
{
Pipe pipe = doc.GetElement(pickRef) as Pipe;
Util.GetStartEndPoint(pipe, ref sp1, ref ep1);
//선택한 파이프의 시작점 방향 커넥터 모음에 선택파이프 추가
m_MainElemIDLst1.Add(pipe.Id);
connectorSet = pipe.ConnectorManager.Connectors;
}
else if (e is Duct)
{
Duct duct = doc.GetElement(pickRef) as Duct;
Util.GetStartEndPoint(duct, ref sp1, ref ep1);
//선택한 파이프의 시작점 방향 커넥터 모음에 선택덕트 추가
m_MainElemIDLst1.Add(duct.Id);
connectorSet = duct.ConnectorManager.Connectors;
}
}
XYZ FlowVec = (ep1 - sp1).Normalize();//시작-끝 방향 Vector
XYZ ReverseVec = (sp1 - ep1).Normalize(); // 시작-끝 역방향 Vector
bool isRight = Util.isRightPoint(directPt, sp1, ep1);
Connector NextCon = null;
int LoopMax = 0;
int ConNum = 1;//파이프 2개의 커넥터 방향 나누기 위해
foreach (Connector con in connectorSet)
{
Connector LoopCon = null;
LoopCon = con;
bool b_Elbow = false;
//Pyosi(LoopCon.Origin, 1);
//MessageBox.Show("loopcon");
//메인 객체의 양 끝 방향의 객체 리스트에 저장.
while (true)
{
NextCon = GetConnected(LoopCon, ConNum, FlowVec, ReverseVec, ref b_Elbow, ref m_MainElemIDLst1, ref m_MainElemIDLst2);
//다음 객체의 정,역방향 커넥터가 없거나 엘보일 경우
if (NextCon == null || b_Elbow == true)
break;
else
LoopCon = NextCon;
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("nextcon");
LoopMax++;
if (LoopMax > 1000) break;
}//while end
ConNum++;
}//foreach end
//선택 파이프 중심 양쪽 모인 메인관들 리스트 1개로 합침.
m_MainElemIDLst2.Reverse();
m_ElemIDLst.AddRange(m_MainElemIDLst2);
m_ElemIDLst.AddRange(m_MainElemIDLst1);
//파이프 길이 치수 생성
using (Transaction trans = new Transaction(doc))
{
trans.Start("CreateDim");
for (int i = 0; i < m_ElemIDLst.Count; i++)
{
Element elem = doc.GetElement(m_ElemIDLst[i]);
if (elem is Pipe)
{
CreateDim(elem as Pipe, isRight, directPt);
}
else if (elem is Duct)
{
CreateDim(elem as Duct, isRight, directPt);
}
}
trans.Commit();
}
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
return Result.Succeeded;
}
public void CreateDim(Pipe pipe, bool isRight, XYZ DirectPt)
{
SketchPlane geometryPlane = view.SketchPlane;
XYZ p1 = null, p2 = null;
Util.GetStartEndPoint(pipe, ref p1, ref p2);
XYZ vec = null;
XYZ plrpt1 = null, plrpt2 = null, p1DstPlr = null, p2DstPlr = null;
bool LoopIsRight = Util.isRightPoint(DirectPt, p1, p2);
XYZ chgPt = null, closePt = null;
//기준 파이프의 점방향과 현재 파이프의 점방향이 다르면 sp,ep 바꾸기
if (isRight != LoopIsRight)
{
chgPt = p1;
p1 = p2;
p2 = chgPt;
}
p1DstPlr = Util.Polar(p1, (p1 - p2).Normalize(), 100000);
p2DstPlr = Util.Polar(p2, (p2 - p1).Normalize(), 100000);
if (isRight == true)
{
vec = Util.RotateVector(p2, p1, Util.kPi / 2);
plrpt1 = Util.Polar(p1, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
plrpt2 = Util.Polar(p2, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
}
else
{
vec = Util.RotateVector(p1, p2, Util.kPi / 2);
plrpt1 = Util.Polar(p1, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
plrpt2 = Util.Polar(p2, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
}
Line newLine = Line.CreateBound(plrpt1, plrpt2);
Options opt = new Options();
opt.ComputeReferences = true;
opt.IncludeNonVisibleObjects = true;
opt.View = doc.ActiveView;
ReferenceArray ra = new ReferenceArray();
GeometryElement geomElem = pipe.get_Geometry(opt);
foreach (GeometryObject geoobj in geomElem)
{
Curve cv = geoobj as Curve;
if (cv == null) continue;
ra.Append(cv.GetEndPointReference(0));
ra.Append(cv.GetEndPointReference(1));
}
Dimension newDim = doc.Create.NewDimension(view, newLine, ra);
}
public void CreateDim(Duct duct, bool isRight, XYZ DirectPt)
{
SketchPlane geometryPlane = view.SketchPlane;
XYZ p1 = null, p2 = null;
Util.GetStartEndPoint(duct, ref p1, ref p2);
XYZ vec = null;
XYZ plrpt1 = null, plrpt2 = null, p1DstPlr = null, p2DstPlr = null;
bool LoopIsRight = Util.isRightPoint(DirectPt, p1, p2);
XYZ chgPt = null, closePt = null;
//기준 파이프의 점방향과 현재 파이프의 점방향이 다르면 sp,ep 바꾸기
if (isRight != LoopIsRight)
{
chgPt = p1;
p1 = p2;
p2 = chgPt;
}
p1DstPlr = Util.Polar(p1, (p1 - p2).Normalize(), 100000);
p2DstPlr = Util.Polar(p2, (p2 - p1).Normalize(), 100000);
if (isRight == true)
{
vec = Util.RotateVector(p2, p1, Util.kPi / 2);
plrpt1 = Util.Polar(p1, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
plrpt2 = Util.Polar(p2, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
}
else
{
vec = Util.RotateVector(p1, p2, Util.kPi / 2);
plrpt1 = Util.Polar(p1, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
plrpt2 = Util.Polar(p2, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt));
}
Line newLine = Line.CreateBound(plrpt1, plrpt2);
Options opt = new Options();
opt.ComputeReferences = true;
opt.IncludeNonVisibleObjects = true;
opt.View = doc.ActiveView;
ReferenceArray ra = new ReferenceArray();
foreach (var geoobj in duct.get_Geometry(opt))
{
Curve cv = geoobj as Curve;
if (cv == null) continue;
ra.Append(cv.GetEndPointReference(0));
ra.Append(cv.GetEndPointReference(1));
}
Dimension newDim = doc.Create.NewDimension(view, newLine, ra);
}
private double GetShortestDistance(XYZ point, XYZ listStartPoint, XYZ lineEndPoint, out XYZ closestPoint)
{
double dx = lineEndPoint.X - listStartPoint.X;
double dy = lineEndPoint.Y - listStartPoint.Y;
if ((dx == 0) && (dy == 0))
{
closestPoint = listStartPoint;
dx = point.X - listStartPoint.X;
dy = point.Y - listStartPoint.Y;
return Math.Sqrt(dx * dx + dy * dy);
}
double t = ((point.X - listStartPoint.X) * dx + (point.Y - listStartPoint.Y) * dy) / (dx * dx + dy * dy);
if (t < 0)
{
closestPoint = new XYZ(listStartPoint.X, listStartPoint.Y, listStartPoint.Z);
dx = point.X - listStartPoint.X;
dy = point.Y - listStartPoint.Y;
}
else if (t > 1)
{
closestPoint = new XYZ(lineEndPoint.X, lineEndPoint.Y, listStartPoint.Z);
dx = point.X - lineEndPoint.X;
dy = point.Y - lineEndPoint.Y;
}
else
{
closestPoint = new XYZ(listStartPoint.X + t * dx, listStartPoint.Y + t * dy, listStartPoint.Z);
dx = point.X - closestPoint.X;
dy = point.Y - closestPoint.Y;
}
return Math.Sqrt(dx * dx + dy * dy);
}
public Connector GetConnected(Connector BaseCon, int ConNum, XYZ FlowVec, XYZ ReverseVec, ref bool b_Elbow, ref List<ElementId> m_ElemIDLst1, ref List<ElementId> m_ElemIDLst2)
{
//기본 커넥터 옆에 객체 구하기.
Connector NextCon = GetNextConnector(BaseCon);
if (NextCon == null) return null;
//기본 커넥터 옆에 객체가 엘보일 경우 b_Elbow = true
b_Elbow = GetFamilyPartType(NextCon, PartType.Elbow);
//NextCon 객체의 정방향 또는 역방향에 위치한 커넥터 구하기.
Connector resCon = GetOtherConnector(NextCon, FlowVec, ReverseVec);
if (resCon != null || b_Elbow == true)
{
if (ConNum == 1)
m_ElemIDLst1.Add(NextCon.Owner.Id);
else
m_ElemIDLst2.Add(NextCon.Owner.Id);
}
return resCon;
}
//패밀리의 타입구분
public bool GetFamilyPartType(Connector baseCon, PartType partType)
{
if (baseCon.Owner is FamilyInstance)
{
FamilyInstance family = baseCon.Owner as FamilyInstance;
Parameter param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
if (partType == (PartType)param.AsInteger())
return true;
else
return false;
}
return false;
}
//NextCon 객체의 정방향 또는 역방향에 위치한 커넥터 구하기.
public Connector GetOtherConnector(Connector baseCon, XYZ FlowVec, XYZ ReverseVec)
{
Connector resCon = null;
ConnectorSet ConSet = null;
MEPSystem mepSystem = baseCon.MEPSystem;
FamilyInstance family = null;
Pipe pipe = null;
Duct duct = null;
if (mepSystem != null)
{
if (baseCon.IsConnected == true)
{
if (baseCon.Owner is FamilyInstance)
{
family = baseCon.Owner as FamilyInstance;
ConSet = family.MEPModel.ConnectorManager.Connectors;
}
else if (baseCon.Owner is Pipe)
{
pipe = baseCon.Owner as Pipe;
ConSet = pipe.ConnectorManager.Connectors;
}
else if (baseCon.Owner is Duct)
{
duct = baseCon.Owner as Duct;
ConSet = duct.ConnectorManager.Connectors;
}
foreach (Connector con in ConSet)
{
//입력 커넥터와 같은 커넥터는 넘긴다,
if (con.Origin.IsAlmostEqualTo(baseCon.Origin, Unit.MMToFeet(0.001)))
continue;
else
{
XYZ CurVec = (con.Origin - baseCon.Origin).Normalize();
//정방향 또는 역방향 커넥터를 찾아 리턴
if (CurVec.IsAlmostEqualTo(FlowVec, Unit.MMToFeet(0.01)) || CurVec.IsAlmostEqualTo(ReverseVec, Unit.MMToFeet(0.01)))
resCon = con;
}
}
}
}
//Pyosi(resCon.Origin, 1);
//MessageBox.Show("2");
return resCon;
}
//커넥터에 연결된 다음 객체의 커넥터 구하기.
public Connector GetNextConnector(Connector baseCon)
{
Connector resCon = null;
MEPSystem mepSystem = baseCon.MEPSystem;
if (mepSystem != null)
{
if (baseCon.IsConnected == true)
{
ConnectorSet ConSet = baseCon.AllRefs;
ConnectorSetIterator csi = ConSet.ForwardIterator();
while (csi.MoveNext())
{
Connector connected = csi.Current as Connector;
if (connected != null && connected.ConnectorType == ConnectorType.End)
{
if (baseCon.Origin.IsAlmostEqualTo(connected.Origin, Unit.MMToFeet(0.001)))
{
if (connected.IsConnected == true)
{
ConnectorSet ConnectedSet = null;
FamilyInstance family = null;
Pipe pipe = null;
Duct duct = null;
if (connected.Owner is FamilyInstance)
{
family = connected.Owner as FamilyInstance;
ConnectedSet = family.MEPModel.ConnectorManager.Connectors;
}
else if (connected.Owner is Pipe)
{
pipe = connected.Owner as Pipe;
ConnectedSet = pipe.ConnectorManager.Connectors;
}
else if (connected.Owner is Duct)
{
duct = connected.Owner as Duct;
ConnectedSet = duct.ConnectorManager.Connectors;
}
foreach (Connector NextCon in ConnectedSet)
{
if (connected.Origin.IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.001)))
{
resCon = NextCon;
}
}
}
}
}
}//while end
}
}
return resCon;
}
public class SelectionFilter : ISelectionFilter
{
public bool AllowElement(Element element)
{
if (element.Category == null) return false;
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves || element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
{
return true;
}
return false;
}
public bool AllowReference(Reference refer, XYZ point)
{
return false;
}
}
}
}