976 lines
39 KiB
C#
976 lines
39 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Autodesk.Revit.UI;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.UI.Selection;
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
using KDCS.Utils;
|
|
using KMBIM.Revit.Tools;
|
|
|
|
namespace KMBIM
|
|
{
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|
class DuctDimension : 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;
|
|
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;
|
|
|
|
try
|
|
{
|
|
//파이프 선택
|
|
Reference DuctRef = uidoc.Selection.PickObject(ObjectType.Element, new DuctSelectionFilter(), "치수 기입할 배관 선택 : ");
|
|
//방향 지정
|
|
XYZ directPt = null;
|
|
Util.PickPoint(uidoc, "치수 방향을 지정하세요.", ref directPt);
|
|
|
|
|
|
if (DuctRef == null || directPt == null) return Result.Succeeded;
|
|
|
|
Duct duct = doc.GetElement(DuctRef) as Duct;
|
|
|
|
XYZ sp1 = null, ep1 = null;
|
|
Util.GetStartEndPoint(duct, ref sp1, ref ep1);
|
|
XYZ FlowVec = (ep1 - sp1).Normalize();//시작-끝 방향 Vector
|
|
XYZ ReverseVec = (sp1 - ep1).Normalize(); // 시작-끝 역방향 Vector
|
|
|
|
bool isRight = Util.isRightPoint(directPt, sp1, ep1);
|
|
|
|
//선택한 파이프의 시작점 방향 커넥터 모음에 선택파이프 추가
|
|
m_MainElemIDLst1.Add(duct.Id);
|
|
|
|
ConnectorSet connectorSet = duct.ConnectorManager.Connectors;
|
|
Connector NextCon = null;
|
|
int LoopMax = 0;
|
|
int ConNum = 1;//파이프 2개의 커넥터 방향 나누기 위해
|
|
|
|
foreach (Connector con in connectorSet)
|
|
{
|
|
Connector LoopCon = null;
|
|
LoopCon = con;
|
|
bool b_Elbow = false;
|
|
//ElemCon = GetConnected(LoopCon, sp1, ConNum, ref m_MainElemIDLst1, ref m_MainElemIDLst2);
|
|
while (true)
|
|
{
|
|
NextCon = GetConnected(LoopCon, ConNum, FlowVec, ReverseVec,ref b_Elbow, ref m_MainElemIDLst1, ref m_MainElemIDLst2);
|
|
|
|
if (NextCon == null)
|
|
break;
|
|
else
|
|
LoopCon = 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);
|
|
|
|
//MessageBox.Show("main1:" + m_MainElemIDLst1.Count() + "\n main2:" + m_MainElemIDLst2.Count());
|
|
|
|
//파이프 길이 치수 생성
|
|
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 Duct)
|
|
{
|
|
CreateDim(elem as Duct, isRight, directPt);
|
|
}
|
|
}
|
|
trans.Commit();
|
|
}
|
|
//싱과 싱 길이 치수 생성
|
|
for (int i = 0; i < m_ElemIDLst.Count; i++)
|
|
{
|
|
Element elem = doc.GetElement(m_ElemIDLst[i]);
|
|
List<Element> m_BranchLst = new List<Element>();
|
|
if (elem is Duct)
|
|
{
|
|
//메인 파이프의 양끝 커넥터에 90도인 파이프 찾기.
|
|
GetBranchElement(elem as Duct, FlowVec, ReverseVec, ref m_BranchLst);
|
|
|
|
//양 끝 90도인 파이프 2개 못찾으면 작도 X
|
|
if (m_BranchLst.Count == 2)
|
|
CreateDim(elem as Duct, m_BranchLst[0], m_BranchLst[1], isRight, directPt, m_ElemIDLst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//MessageBox.Show("" + e);
|
|
|
|
}
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
//처음 선택한 파이프 양 커넥터에 연결된 객체들 리스트 2개에 각각 담기.
|
|
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 = GetNextElementConnector(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;
|
|
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 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 GetNextElementConnector(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;
|
|
Duct duct = null;
|
|
|
|
if (connected.Owner is FamilyInstance)
|
|
{
|
|
family = connected.Owner as FamilyInstance;
|
|
ConnectedSet = family.MEPModel.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 void GetBranchElement(Duct duct, XYZ FlowVec, XYZ ReverseVec, ref List<Element> m_BranchList)
|
|
{
|
|
ConnectorSet conSet = duct.ConnectorManager.Connectors;
|
|
|
|
foreach (Connector con in conSet)//파이프 커넥터 2개
|
|
{
|
|
if (con.IsConnected == true)
|
|
{
|
|
|
|
Connector NextCon = GetNextElementConnector(con);
|
|
//Pyosi(NextCon.Origin, 1);
|
|
//MessageBox.Show("NextCon");
|
|
|
|
bool b_reducer = GetFamilyPartType(NextCon, PartType.Transition);
|
|
bool b_Cap = GetFamilyPartType(NextCon, PartType.Cap);
|
|
|
|
if (b_reducer)
|
|
m_BranchList.Add(NextCon.Owner);
|
|
else if (b_Cap)
|
|
{
|
|
m_BranchList.Add(duct);
|
|
}
|
|
else
|
|
{
|
|
Connector ClosestCon = GetClosestConnector(NextCon, FlowVec, ReverseVec);
|
|
|
|
Connector ClosestNextCon = null;
|
|
|
|
if (ClosestCon != null)
|
|
ClosestNextCon = GetNextElementConnector(ClosestCon);
|
|
|
|
if (ClosestNextCon.Owner is Duct)
|
|
m_BranchList.Add(ClosestNextCon.Owner);
|
|
else
|
|
{
|
|
Connector ClosestCon2 = GetClosestConnector(ClosestNextCon, FlowVec, ReverseVec);
|
|
|
|
Connector ClosestNextCon2 = GetNextElementConnector(ClosestCon2);
|
|
m_BranchList.Add(ClosestNextCon2.Owner);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//파이프 커넥터에 객체가 부착되지 않은 경우 파이프를 저장.
|
|
m_BranchList.Add(duct);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public Connector GetClosestConnector(Connector baseCon, XYZ FlowVec, XYZ ReverseVec)
|
|
{
|
|
Connector resCon = null;
|
|
ConnectorSet ConSet = null;
|
|
MEPSystem mEPSystem = baseCon.MEPSystem;
|
|
FamilyInstance family = 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 Duct)
|
|
{
|
|
duct = baseCon.Owner as Duct;
|
|
ConSet = duct.ConnectorManager.Connectors;
|
|
}
|
|
|
|
bool b_reducer = GetFamilyPartType(baseCon, PartType.Transition);
|
|
//객체가 레듀셔일 경우
|
|
|
|
foreach (Connector con in ConSet)
|
|
{
|
|
if (baseCon.Origin.IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01))) continue;
|
|
XYZ CurVec = (con.Origin - baseCon.Origin).Normalize();
|
|
if (!(CurVec.IsAlmostEqualTo(FlowVec, Unit.MMToFeet(0.01)) || CurVec.IsAlmostEqualTo(ReverseVec, Unit.MMToFeet(0.01))))
|
|
resCon = con;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return resCon;
|
|
}
|
|
|
|
|
|
//현재 커넥터를 가진 객체의 현재 커넥터로부터 가장 먼 커넥터 찾기.
|
|
public Connector GetFlowConnector(Connector baseCon, XYZ flowVec, XYZ ReverseVec)
|
|
{
|
|
Connector resCon = null;
|
|
MEPSystem mepSystem = baseCon.MEPSystem;
|
|
FamilyInstance family = null;
|
|
Duct duct = null;
|
|
ConnectorSet ConSet = null;
|
|
|
|
if (null != mepSystem)
|
|
{
|
|
if (baseCon.IsConnected == true)
|
|
{
|
|
if (baseCon.Owner is FamilyInstance)
|
|
{
|
|
family = baseCon.Owner as FamilyInstance;
|
|
ConSet = family.MEPModel.ConnectorManager.Connectors;
|
|
}
|
|
|
|
else if (baseCon.Owner is Duct)
|
|
{
|
|
duct = baseCon.Owner as Duct;
|
|
ConSet = duct.ConnectorManager.Connectors;
|
|
}
|
|
|
|
//마감 등 커넥터가 1개일 때 다음 객체구할 수 없음.
|
|
if (ConSet.Size == 1) return null;
|
|
|
|
//덕트 실제길이
|
|
foreach (Connector con in ConSet)
|
|
{
|
|
//메인관의 흐름과 역흐름 방향인 경우의 커넥터만 찾기.
|
|
if (baseCon.Origin.IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01))) continue;
|
|
|
|
XYZ CurVec = (con.Origin - baseCon.Origin).Normalize();
|
|
if (CurVec.IsAlmostEqualTo(flowVec, Unit.MMToFeet(0.01)) || CurVec.IsAlmostEqualTo(ReverseVec, Unit.MMToFeet(0.01)))
|
|
resCon = con;
|
|
}
|
|
}
|
|
}
|
|
|
|
return resCon;
|
|
}
|
|
|
|
//현재 커넥터를 가진 객체의 현재 커넥터로부터 가장 가까운 커넥터에 연결된 객체 찾기.
|
|
public Element GetClosestElement(Connector baseCon, XYZ FlowVec, XYZ ReverseVec)
|
|
{
|
|
Connector resCon = null;
|
|
MEPSystem mepSystem = baseCon.MEPSystem;
|
|
FamilyInstance family = null;
|
|
Duct duct = null;
|
|
ConnectorSet ConSet = null;
|
|
Element element = null;
|
|
|
|
if (null != mepSystem)
|
|
{
|
|
if (baseCon.IsConnected == true)
|
|
{
|
|
if (baseCon.Owner is FamilyInstance)
|
|
{
|
|
family = baseCon.Owner as FamilyInstance;
|
|
ConSet = family.MEPModel.ConnectorManager.Connectors;
|
|
}
|
|
|
|
else if (baseCon.Owner is Duct)
|
|
{
|
|
duct = baseCon.Owner as Duct;
|
|
ConSet = duct.ConnectorManager.Connectors;
|
|
}
|
|
|
|
//덕트 실제길이
|
|
foreach (Connector con in ConSet)
|
|
{
|
|
|
|
//메인관의 흐름과 역흐름 방향이 아닌 경우의 커넥터만 찾기.
|
|
if (baseCon.Origin.IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01))) continue;
|
|
|
|
XYZ CurVec = (con.Origin - baseCon.Origin).Normalize();
|
|
if (!(CurVec.IsAlmostEqualTo(FlowVec, Unit.MMToFeet(0.01)) || CurVec.IsAlmostEqualTo(ReverseVec, Unit.MMToFeet(0.01))))
|
|
{
|
|
resCon = con;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//기준 커넥터에서 가까운 커넥터에 연결된 덕트 구하기
|
|
|
|
if (resCon != null)
|
|
{
|
|
if (resCon.MEPSystem != null)
|
|
{
|
|
if (resCon.IsConnected == true)
|
|
{
|
|
ConnectorSet connectorSet = resCon.AllRefs;
|
|
ConnectorSetIterator csi = connectorSet.ForwardIterator();
|
|
while (csi.MoveNext())
|
|
{
|
|
Connector connected = csi.Current as Connector;
|
|
if (null != connected)
|
|
{
|
|
if (connected.Owner is Duct)
|
|
{
|
|
if (resCon.Origin.IsAlmostEqualTo(connected.Origin, Unit.MMToFeet(0.01)))
|
|
{
|
|
if (connected.IsConnected == true)
|
|
{
|
|
element = connected.Owner;
|
|
//XYZ aa = null, bb = null;
|
|
//Util.GetStartEndPoint(connected.Owner as Duct, ref aa, ref bb);
|
|
}
|
|
}
|
|
}
|
|
else // familyinstance
|
|
{//덕트가 아니면 그 다음에서 덕트를 찾는다.
|
|
element = GetNextElement(connected);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return element;
|
|
}
|
|
|
|
//커넥터가 덕트가 아닐 경우 다음 객체를 구하는 루틴,
|
|
public Element GetNextElement(Connector CurConnector)
|
|
{
|
|
Connector resCon = null;
|
|
ConnectorSet NextConSet = null;
|
|
Duct duct = null;
|
|
FamilyInstance family = null;
|
|
Element resElem = null;
|
|
if (CurConnector.Owner is Duct)
|
|
{
|
|
duct = CurConnector.Owner as Duct;
|
|
NextConSet = duct.ConnectorManager.Connectors;
|
|
}
|
|
else if (CurConnector.Owner is FamilyInstance)
|
|
{
|
|
family = CurConnector.Owner as FamilyInstance;
|
|
NextConSet = family.MEPModel.ConnectorManager.Connectors;
|
|
}
|
|
|
|
foreach (Connector con in NextConSet)
|
|
{
|
|
if (!(con.Origin.IsAlmostEqualTo(CurConnector.Origin, Unit.MMToFeet(0.01))))
|
|
{
|
|
resCon = con;
|
|
|
|
if (con.IsConnected == true)
|
|
{
|
|
ConnectorSet Next2ConSet = con.AllRefs;
|
|
ConnectorSetIterator csi = Next2ConSet.ForwardIterator();
|
|
while (csi.MoveNext())
|
|
{
|
|
Connector connected = csi.Current as Connector;
|
|
|
|
if (connected.Owner is Duct)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(connected.Origin, Unit.MMToFeet(0.01)))
|
|
{
|
|
if (connected.IsConnected == true)
|
|
{
|
|
resElem = connected.Owner;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return resElem;
|
|
}
|
|
|
|
public void CreateDim(Duct duct, bool isRight, XYZ DirectPt)
|
|
{
|
|
|
|
//using (Transaction trans = new Transaction(doc))
|
|
//{
|
|
// trans.Start("Dimension");
|
|
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);
|
|
|
|
// trans.Commit();
|
|
//}
|
|
|
|
}
|
|
|
|
public void CreateDim(Duct duct, Element Elem1, Element Elem2, bool isRight, XYZ DirectPt, List<ElementId> m_ElemIDLst)
|
|
{
|
|
SketchPlane geometryPlane = view.SketchPlane;
|
|
|
|
XYZ sp1 = null, sp2 = null, ep1 = null, ep2 = null, p1 = null, p2 = null;
|
|
Util.GetStartEndPoint(duct, ref p1, ref p2);
|
|
Util.GetStartEndPoint(Elem1 as Duct, ref sp1, ref ep1);
|
|
Util.GetStartEndPoint(Elem2 as Duct, ref sp2, ref ep2);
|
|
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) + Unit.MMToFeet(1000));
|
|
plrpt2 = Util.Polar(p2, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt) + Unit.MMToFeet(1000));
|
|
}
|
|
else
|
|
{
|
|
vec = Util.RotateVector(p1, p2, Util.kPi / 2);
|
|
plrpt1 = Util.Polar(p1, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt) + Unit.MMToFeet(1000));
|
|
plrpt2 = Util.Polar(p2, vec, GetShortestDistance(DirectPt, p1DstPlr, p2DstPlr, out closePt) + Unit.MMToFeet(1000));
|
|
}
|
|
|
|
Line newLine = Line.CreateBound(plrpt1, plrpt2);
|
|
Options opt = new Options();
|
|
opt.ComputeReferences = true;
|
|
opt.IncludeNonVisibleObjects = true;
|
|
opt.View = doc.ActiveView;
|
|
ReferenceArray ra = new ReferenceArray();
|
|
//메인관의 파이프인 경우
|
|
if (m_ElemIDLst.Contains(Elem1.Id) && Elem1 is Duct)
|
|
{
|
|
Connector NotCon = GetIsNotConnected(Elem1 as Duct);
|
|
//Pyosi(NotCon.Origin, 1);
|
|
//MessageBox.Show("NotCon in Elem1");
|
|
//Connector NextCon = GetNextElementConnector(NotCon);
|
|
|
|
if (GetFamilyPartType(NotCon, PartType.Cap))
|
|
{
|
|
//Pyosi(NotCon.Origin, 1);
|
|
//MessageBox.Show("NextCon in Elem1");
|
|
Reference refer = GetCapReference(NotCon);
|
|
ra.Append(refer);
|
|
}
|
|
else
|
|
{
|
|
foreach (var geoobj in (Elem1 as Duct).get_Geometry(opt))
|
|
{
|
|
Curve cv = geoobj as Curve;
|
|
if (cv == null) continue;
|
|
if (cv.GetEndPoint(0).IsAlmostEqualTo(NotCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(0));
|
|
else if (cv.GetEndPoint(1).IsAlmostEqualTo(NotCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(1));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
if (Elem1 is Duct)
|
|
{
|
|
foreach (var geoobj in (Elem1 as Duct).get_Geometry(opt))
|
|
{
|
|
Curve cv = geoobj as Curve;
|
|
if (cv == null) continue;
|
|
ra.Append(cv.Reference);
|
|
}
|
|
}
|
|
else
|
|
{//패밀리인 경우
|
|
if (Elem1 is FamilyInstance)
|
|
{
|
|
ConnectorSet FamilyConSet = (Elem1 as FamilyInstance).MEPModel.ConnectorManager.Connectors;
|
|
List<Connector> m_ConLst = new List<Connector>();
|
|
foreach (Connector familyCon in FamilyConSet)
|
|
m_ConLst.Add(familyCon);
|
|
|
|
//첫번째 객체가 패밀리이면서 레듀셔일 떄
|
|
if (GetFamilyPartType(m_ConLst.First(), PartType.Transition))
|
|
{
|
|
Connector resCon = null;
|
|
if (m_ConLst[0].Width > m_ConLst[1].Width)
|
|
resCon = m_ConLst[1];
|
|
else
|
|
resCon = m_ConLst[0];
|
|
//////
|
|
//Pyosi(resCon.Origin, 1);
|
|
//MessageBox.Show("1");
|
|
//레듀셔의 작은쪽에 붙은 객체 찾기.
|
|
Connector NextCon = GetNextElementConnector(resCon);
|
|
//레듀셔 다음 객체가 파이프면 작도 아니면 작도X
|
|
if (!(NextCon.Owner is Duct))
|
|
return;
|
|
foreach (var geoobj in (NextCon.Owner).get_Geometry(opt))
|
|
{
|
|
Curve cv = geoobj as Curve;
|
|
if (cv == null) continue;
|
|
|
|
if (cv.GetEndPoint(0).IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(0));
|
|
else if (cv.GetEndPoint(1).IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(1));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
//메인관의 파이프인 경우
|
|
if (m_ElemIDLst.Contains(Elem2.Id) && Elem2 is Duct)
|
|
{
|
|
Connector NotCon = GetIsNotConnected(Elem2 as Duct);
|
|
|
|
if (GetFamilyPartType(NotCon, PartType.Cap))
|
|
{
|
|
Reference refer = GetCapReference(NotCon);
|
|
ra.Append(refer);
|
|
}
|
|
else
|
|
{
|
|
foreach (var geoobj in (Elem2 as Duct).get_Geometry(opt))
|
|
{
|
|
Curve cv = geoobj as Curve;
|
|
if (cv == null) continue;
|
|
if (cv.GetEndPoint(0).IsAlmostEqualTo(NotCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(0));
|
|
else if (cv.GetEndPoint(1).IsAlmostEqualTo(NotCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(1));
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (Elem2 is Duct)
|
|
{
|
|
foreach (var geoobj in (Elem2 as Duct).get_Geometry(opt))
|
|
{
|
|
Curve cv = geoobj as Curve;
|
|
if (cv == null) continue;
|
|
ra.Append(cv.Reference);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Elem2 is FamilyInstance)
|
|
{
|
|
ConnectorSet FamilyConSet = (Elem2 as FamilyInstance).MEPModel.ConnectorManager.Connectors;
|
|
List<Connector> m_ConLst = new List<Connector>();
|
|
foreach (Connector familyCon in FamilyConSet)
|
|
m_ConLst.Add(familyCon);
|
|
|
|
//첫번째 객체가 패밀리이면서 레듀셔일 떄
|
|
if (GetFamilyPartType(m_ConLst.First(), PartType.Transition))
|
|
{
|
|
Connector resCon = null;
|
|
if (m_ConLst[0].Width > m_ConLst[1].Width)
|
|
resCon = m_ConLst[1];
|
|
else
|
|
resCon = m_ConLst[0];
|
|
//////
|
|
//Pyosi(resCon.Origin, 1);
|
|
//MessageBox.Show("2");
|
|
//레듀셔의 작은쪽에 붙은 객체 찾기.
|
|
Connector NextCon = GetNextElementConnector(resCon);
|
|
//레듀셔 다음 객체가 파이프면 작도 아니면 작도X
|
|
if (!(NextCon.Owner is Duct))
|
|
return;
|
|
foreach (var geoobj in (NextCon.Owner).get_Geometry(opt))
|
|
{
|
|
Curve cv = geoobj as Curve;
|
|
if (cv == null) continue;
|
|
|
|
if (cv.GetEndPoint(0).IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(0));
|
|
else if (cv.GetEndPoint(1).IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.01)))
|
|
ra.Append(cv.GetEndPointReference(1));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("CreateDimension");
|
|
//MessageBox.Show("count : " + ra.Size);
|
|
Dimension newDim = doc.Create.NewDimension(view, newLine, ra);
|
|
trans.Commit();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public Reference GetCapReference(Connector BaseCon)
|
|
{
|
|
Reference refer = null;
|
|
|
|
FamilyInstance family = BaseCon.Owner as FamilyInstance;
|
|
Options opt = new Options();
|
|
opt.ComputeReferences = true;
|
|
opt.IncludeNonVisibleObjects = true;
|
|
opt.View = doc.ActiveView;
|
|
|
|
GeometryElement gElem = family.get_Geometry(opt);
|
|
GeometryInstance gInst = gElem.First() as GeometryInstance;
|
|
|
|
foreach (var Geo in family.get_Geometry(opt))
|
|
{
|
|
if (!(Geo is GeometryInstance)) continue;
|
|
|
|
GeometryElement gSymbol = (Geo as GeometryInstance).GetSymbolGeometry();
|
|
if (gSymbol != null && gSymbol.Count() > 0)
|
|
{
|
|
Solid solid = gSymbol.First() as Solid;
|
|
ReferenceArray referLst = new ReferenceArray();
|
|
|
|
|
|
foreach (Face face in solid.Faces)
|
|
{
|
|
PlanarFace planarFace = face as PlanarFace;
|
|
if (planarFace == null) continue;
|
|
//referLst.Append(planarFace.Reference);
|
|
if (Math.Round(planarFace.FaceNormal.X,8) > 0)
|
|
refer = planarFace.Reference;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
return refer;
|
|
}
|
|
|
|
//연결되지 않은 커넥터 또는 커넥터에 연결되어있지만 다음 객체가 커넥터가 1개일 경우
|
|
public Connector GetIsNotConnected(Duct duct)
|
|
{
|
|
Connector resCon = null;
|
|
ConnectorSet conSet = duct.ConnectorManager.Connectors;
|
|
|
|
foreach (Connector con in conSet)
|
|
{
|
|
if (con.MEPSystem != null)
|
|
{
|
|
if (con.IsConnected == false)//연결되지 않은 커넥터
|
|
resCon = con;
|
|
else
|
|
{
|
|
ConnectorSet NewConSet = con.AllRefs;
|
|
ConnectorSetIterator csi = NewConSet.ForwardIterator();
|
|
while (csi.MoveNext())
|
|
{
|
|
Connector connected = csi.Current as Connector;
|
|
if (connected != null)
|
|
{
|
|
if (connected.Owner is FamilyInstance)
|
|
{
|
|
FamilyInstance family = connected.Owner as FamilyInstance;
|
|
//패밀리가 엘보일 경우 저장 X
|
|
var param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
|
|
PartType part = (PartType)param.AsInteger();
|
|
if (part == PartType.Elbow) continue;
|
|
else if (part == PartType.Tee) continue;
|
|
else if (part == PartType.Cross) continue;
|
|
else if (part == PartType.Transition) continue;
|
|
|
|
resCon = connected;
|
|
|
|
ConnectorSet tt = connected.AllRefs;
|
|
int aaa = tt.Size;
|
|
}
|
|
|
|
}
|
|
}
|
|
//if (NewConSet.Size == 1) resCon = con;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return resCon;
|
|
}
|
|
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 class DuctSelectionFilter : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category == null) return false;
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|