Client/Desktop/KMBIM3.0/23.10.16/Cmd/Dimension/DuctC2CDim.cs

1156 lines
48 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 System.Windows.Forms;
using KDCS.Utils;
using KMBIM.Revit.Tools;
namespace KMBIM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class DuctC2CDim : 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(), "치수 기입할 덕트 선택 : ");
//Reference DuctRef = uidoc.Selection.PickObject(ObjectType.Element, "치수 기입할 배관 선택 : ");
//IList<Reference> refs = uidoc.Selection.PickObjects(ObjectType.Element, "치수 기입 : ");
//방향 지정
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;
//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);
//참조 평면 방향
XYZ ReferVec = null;
if (isRight)
ReferVec = Util.RotateVector(FlowVec, Util.DTR(-90.0));
else
ReferVec = Util.RotateVector(FlowVec, Util.DTR(90.0));
for(int i=0; i<m_ElemIDLst.Count(); i++)
{
Element elem = doc.GetElement(m_ElemIDLst.ElementAt(i));
if(elem is Duct)
{
List<Connector> DuctConLst = Util.GetElementConnectors(elem);
List<Reference> m_ReferLst = new List<Reference>();
List<XYZ> m_RefptLst = new List<XYZ>();
foreach(Connector con in DuctConLst)
{
//덕트 패밀리 커넥터
Connector DuctNextCon = Util.GetNextElementConnector(con);
if(DuctNextCon != null)
{
if(DuctNextCon.Owner is FamilyInstance)
{
FamilyInstance family = DuctNextCon.Owner as FamilyInstance;
XYZ referPt = null;
Reference DrawRefer = GetFamilyMidPtReference(family, duct, ReferVec, ref referPt);
if (DrawRefer == null) continue;
referPt = new XYZ(referPt.X, referPt.Y, DuctNextCon.Origin.Z);
m_ReferLst.Add(DrawRefer);
m_RefptLst.Add(referPt);
}
}
else//덕트에 붙은 객체가 없을 경우 덕트 레퍼런스 저장
{
foreach (var geoobj in (elem as Duct).get_Geometry(NewOptions()))
{
Curve cv = geoobj as Curve;
if (cv != null)
{
if (cv.GetEndPoint(0).IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01)))
{
m_ReferLst.Add(cv.GetEndPointReference(0));
XYZ ConZ = new XYZ(cv.GetEndPoint(0).X, cv.GetEndPoint(0).Y, con.Origin.Z);
m_RefptLst.Add(ConZ);
}
else if (cv.GetEndPoint(1).IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01)))
{
m_ReferLst.Add(cv.GetEndPointReference(1));
XYZ ConZ = new XYZ(cv.GetEndPoint(1).X, cv.GetEndPoint(1).Y, con.Origin.Z);
m_RefptLst.Add(ConZ);
}
}
}
}
if (m_RefptLst.Count() == 2 && m_ReferLst.Count() == 2)
{
directPt = new XYZ(directPt.X, directPt.Y, m_RefptLst[0].Z);
CreateDim(isRight, directPt, m_RefptLst, m_ReferLst);
}
}
}
}
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
return Result.Succeeded;
}
public Reference GetFamilyMidPtReference(FamilyInstance family, Duct DirDuct, XYZ referVec, ref XYZ referPt)
{
XYZ MidPt = null, sp = null, ep = null;
Reference DrawRefer = null;
Util.GetStartEndPoint(DirDuct, ref sp, ref ep);
//파이프 시작-끝 벡터, 끝-시작 벡터
XYZ DirVec = (ep - sp).Normalize();
XYZ ReverseVec = (sp - ep).Normalize();
XYZ locPt = ((family.Location) as LocationPoint).Point;
if (locPt == null) return null;
//레듀셔 또는 캡은 원점이 가운데 점이 아니라 커넥터로 구해야 함.
if (Util.GetFamilyPartType(family, PartType.Transition) == true)
{
List<Connector> familyConLst = Util.GetElementConnectors(family);
Connector con1 = familyConLst.First();
Connector con2 = familyConLst.ElementAt(1);
XYZ RedMidPt = Util.Midpoint(con1.Origin, con2.Origin);
MidPt = new XYZ(RedMidPt.X, RedMidPt.Y, sp.Z);
XYZ plrpt = Util.Polar(MidPt, referVec, Unit.MMToFeet(5));
XYZ thirdPt = new XYZ(plrpt.X, plrpt.Y, sp.Z+1);
using (Transaction trans = new Transaction(doc))
{
trans.Start("refer");
ReferencePlane refPlane = doc.Create.NewReferencePlane2(MidPt, plrpt, thirdPt, doc.ActiveView);
DrawRefer = refPlane.GetReference();
referPt = MidPt;
trans.Commit();
}
}
else if (Util.GetFamilyPartType(family, PartType.Cap) == true)
{
List<Connector> CapConLst = Util.GetElementConnectors(family);
DrawRefer = GetCapReference(family);
if(DrawRefer !=null)
referPt = CapConLst.First().Origin;
else//못 찾으면 덕트 끝점으로
{
Connector DuctCon = Util.GetNextElementConnector(CapConLst.First());
if(DuctCon != null)
{
foreach (var geoobj in (DuctCon.Owner as Duct).get_Geometry(NewOptions()))
{
Curve cv = geoobj as Curve;
if (cv != null)
{
if (cv.GetEndPoint(0).IsAlmostEqualTo(DuctCon.Origin, Unit.MMToFeet(0.01)))
{
DrawRefer = cv.GetEndPointReference(0);
XYZ ConZ = new XYZ(cv.GetEndPoint(0).X, cv.GetEndPoint(0).Y, DuctCon.Origin.Z);
referPt = ConZ;
break;
}
else if (cv.GetEndPoint(1).IsAlmostEqualTo(DuctCon.Origin, Unit.MMToFeet(0.01)))
{
DrawRefer = cv.GetEndPointReference(1);
XYZ ConZ = new XYZ(cv.GetEndPoint(1).X, cv.GetEndPoint(1).Y, DuctCon.Origin.Z);
referPt = ConZ;
break;
}
}
}
}
}
}
else
{
MidPt = new XYZ(locPt.X, locPt.Y, sp.Z);
XYZ plrpt = Util.Polar(MidPt, referVec, Unit.MMToFeet(5));
XYZ thirdPt = new XYZ(plrpt.X, plrpt.Y, sp.Z+1);
using (Transaction trans = new Transaction(doc))
{
trans.Start("refer");
ReferencePlane refPlane = doc.Create.NewReferencePlane2(MidPt, plrpt, thirdPt, doc.ActiveView);
DrawRefer = refPlane.GetReference();
referPt = MidPt;
trans.Commit();
}
}
return DrawRefer;
}
//캡 reference 구하기.
public Reference GetCapReference(Element elem)
{
Reference resRef = null;
if (elem is FamilyInstance)
{
FamilyInstance family = elem as FamilyInstance;
Parameter param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
//캡
if ((PartType)param.AsInteger() == PartType.Cap)
{
GeometryElement gElem = family.get_Geometry(NewOptions());
GeometryInstance gInst = gElem.First() as GeometryInstance;
foreach (var Geo in family.get_Geometry(NewOptions()))
{
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 (planarFace.FaceNormal.X > 0)
{
resRef = planarFace.Reference;
return resRef;
}
}
}
}
}
}
return resRef;
}
//레듀셔의 좁은쪽 reference 구하기.
public Reference GetReducerReference(Element elem)
{
Reference resRef = null;
if (elem is FamilyInstance)
{
FamilyInstance family = elem as FamilyInstance;
Parameter param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
//레듀셔일 때
if ((PartType)param.AsInteger() == PartType.Transition)
{
ConnectorSet FamilyConSet = family.MEPModel.ConnectorManager.Connectors;
List<Connector> m_ConLst = new List<Connector>();
foreach (Connector familyCon in FamilyConSet)
m_ConLst.Add(familyCon);
Connector resCon = null;
if (m_ConLst[0].Width > m_ConLst[1].Width)
resCon = m_ConLst[1];
else
resCon = m_ConLst[0];
//레듀셔의 작은쪽에 붙은 객체 찾기.
Connector NextCon = GetNextElementConnector(resCon);
//레듀셔 다음 객체가 덕트면 작도 아니면 작도X
if (!(NextCon.Owner is Duct))
return resRef;
foreach (var geoobj in (NextCon.Owner).get_Geometry(NewOptions()))
{
Curve cv = geoobj as Curve;
if (cv == null) continue;
if (cv.GetEndPoint(0).IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.01)))
{
resRef = cv.GetEndPointReference(0);//ra.Append(cv.GetEndPointReference(0));
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("Reducer");
}
else if (cv.GetEndPoint(1).IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.01)))
{
resRef = cv.GetEndPointReference(1);
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("Reducer");
}
}
}
}
return resRef;
}
public Reference GetBranchElement2(Connector CurCon, XYZ FlowVec, XYZ ReverseVec, ref XYZ referPt)
{
Reference resRef = null;
if (CurCon.IsConnected == true)
{
Connector NextCon = GetNextElementConnector(CurCon);
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("NextCon");
bool b_reducer = GetFamilyPartType(NextCon, PartType.Transition);
bool b_Cap = GetFamilyPartType(NextCon, PartType.Cap);
bool b_Tee = GetFamilyPartType(NextCon, PartType.Tee);
bool b_Elbow = GetFamilyPartType(NextCon, PartType.Elbow);
if (b_reducer)
{
resRef = GetReducerReference(NextCon.Owner);
referPt = NextCon.Origin;
//Pyosi(referPt, 1);
//MessageBox.Show("reducer");
}
else if (b_Cap)
{
resRef = GetCapReference(NextCon.Owner);
referPt = NextCon.Origin;
//Pyosi(referPt, 1);
//MessageBox.Show("캡");
}
else if(b_Tee || b_Elbow)//Tee or Elbow
{
Connector ClosestCon = GetClosestConnector(NextCon, FlowVec, ReverseVec);
Connector ClosestNextCon = null;
if (ClosestCon != null)
ClosestNextCon = GetNextElementConnector(ClosestCon);
if (ClosestNextCon.Owner is Duct)
{
resRef = GetElementPointReference(ClosestNextCon.Owner, ClosestNextCon);
referPt = ClosestNextCon.Origin;
//Pyosi(referPt, 1);
//MessageBox.Show("엘보 티");
}
else
{
Connector ClosestCon2 = GetClosestConnector(ClosestNextCon, FlowVec, ReverseVec);
Connector ClosestNextCon2 = GetNextElementConnector(ClosestCon2);
resRef = GetElementPointReference(ClosestNextCon2.Owner, ClosestNextCon2);
referPt = ClosestNextCon2.Origin;
//Pyosi(referPt, 1);
//MessageBox.Show("다음 엘보 티");
}
}
else
return resRef;
}
else
{
//덕트 커넥터에 객체가 부착되지 않은 경우 덕트를 저장.
resRef = GetElementPointReference(CurCon.Owner, CurCon);
referPt = CurCon.Origin;
//Pyosi(CurCon.Origin, 1);
//MessageBox.Show("부착 없는 덕트");
}
return resRef;
}
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);
bool b_valve = GetFamilyPartType(NextCon, PartType.ValveNormal);
bool b_BRKvalve = GetFamilyPartType(NextCon, PartType.ValveBreaksInto);
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 void CreateDim(bool isRight, XYZ DirectPt, List<XYZ> m_PtLst, List<Reference> m_ReferLst)
{
if (m_PtLst.Count == 2)
{
XYZ p1 = null, p2 = null, plrpt1 = null, plrpt2 = null, p1DstPlr = null, p2DstPlr = null;
XYZ vec = null;
bool LoopIsRight = Util.isRightPoint(DirectPt, m_PtLst[0], m_PtLst[1]);
if (LoopIsRight == isRight)
{
p1 = m_PtLst[0];
p2 = m_PtLst[1];
}
else
{
p1 = m_PtLst[1];
p2 = m_PtLst[0];
}
//p1Z0 = new XYZ(p1.X, p1.Y, 0);
//p2Z0 = new XYZ(p2.X, p2.Y, 0);
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);
}
else
{
vec = Util.RotateVector(p1, p2, Util.kPi / 2);
}
//선에서 가까운점 구하기.(덕트에서 치수작도할 만큼 거리 구하기)
Line lin = Line.CreateBound(p1DstPlr, p2DstPlr);
XYZ onPt = Util.GetPointOnLine(lin, DirectPt);
double dist = DirectPt.DistanceTo(onPt);
plrpt1 = Util.Polar(p1, vec, dist);
plrpt2 = Util.Polar(p2, vec, dist);
using (Transaction trans = new Transaction(doc))
{
trans.Start("dim");
ReferenceArray ra = new ReferenceArray();
ra.Append(m_ReferLst[0]);
ra.Append(m_ReferLst[1]);
Line newLine = Line.CreateBound(plrpt1, plrpt2);
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();
}
}
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 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 (planarFace.FaceNormal.X > 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;
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;
//패밀리 커넥터가 1개일 때
resCon = connected;
}
}
}
}
}
}
return resCon;
}
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 bool Pyosi(XYZ pt, int TranMode)
{
if (TranMode == 0)
{
XYZ pt1 = new XYZ(pt.X - 0.328084, pt.Y + 0.328084, pt.Z);
XYZ pt2 = new XYZ(pt.X + Unit.MMToFeet(100), pt.Y + Unit.MMToFeet(100), pt.Z);
XYZ pt3 = new XYZ(pt.X + 0.328084, pt.Y - 0.328084, pt.Z);
XYZ pt4 = new XYZ(pt.X - 0.328084, pt.Y - 0.328084, pt.Z);
Autodesk.Revit.DB.View view = doc.ActiveView;
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt1, pt3);
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt2, pt4);
}
else
{
using (Transaction transaction = new Transaction(doc))
{
transaction.Start("Start");
XYZ pt1 = new XYZ(pt.X - 0.328084, pt.Y + 0.328084, pt.Z);
XYZ pt2 = new XYZ(pt.X + Unit.MMToFeet(100), pt.Y + Unit.MMToFeet(100), pt.Z);
XYZ pt3 = new XYZ(pt.X + 0.328084, pt.Y - 0.328084, pt.Z);
XYZ pt4 = new XYZ(pt.X - 0.328084, pt.Y - 0.328084, pt.Z);
Autodesk.Revit.DB.View view = doc.ActiveView;
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt1, pt3);
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt2, pt4);
transaction.Commit();
}
}
return true;
}
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;
}
}
public Options NewOptions()
{
Options opt = new Options();
opt.ComputeReferences = true;
opt.IncludeNonVisibleObjects = true;
opt.View = doc.ActiveView;
//if (opt.DetailLevel != ViewDetailLevel.Fine)
// opt.DetailLevel = ViewDetailLevel.Fine;
return opt;
}
public Reference GetElementPointReference(Element elem, Connector con)
{
Reference resRef = null;
foreach (var geoobj in (elem as Duct).get_Geometry(NewOptions()))
{
Curve cv = geoobj as Curve;
if (cv == null) continue;
if (cv.GetEndPoint(0).IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01)))
resRef = cv.GetEndPointReference(0);
else if (cv.GetEndPoint(1).IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01)))
resRef = cv.GetEndPointReference(1);
}
return resRef;
}
}
}