using System; using System.Collections.Generic; using System.Linq; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI.Selection; using System.Windows.Forms; using KDCS.Utils; using KMBIM.Revit.Tools; namespace KMBIM { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] class PipeC2CDim : 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 m_ElemIDLst = new List(); List m_MainElemIDLst1 = new List();//선택한 파이프의 시작점 방향 커넥터 모음 List m_MainElemIDLst2 = new List();//선택한 파이프의 끝점 방향 커넥터 모음 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 pipeRef = uidoc.Selection.PickObject(ObjectType.Element, new PipeSelectionFilter(), "치수 기입할 메인 배관 선택 : "); Reference pickRef = uidoc.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "치수 기입할 메인 배관 선택 : "); //Reference pipeRef = uidoc.Selection.PickObject(ObjexxxxxxxxxxxxxxxxxxxxxxxxxxctType.Element, "치수 기입할 배관 선택 : "); //IList refs = uidoc.Selection.PickObjects(ObjectType.Element, "치수 기입 : "); //방향 지정 XYZ directPt = null; Util.PickPoint(uidoc, "치수 방향을 지정하세요.", ref directPt); Pipe pipe = null; Duct duct = null; 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 = 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 = 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); //List m_ReferLst = new List(); //List m_RefptLst = new List(); //싱과 싱 길이 치수 생성 //참조 평면 방향 XYZ ReferVec = null; if (isRight) ReferVec = Util.RotateVector(FlowVec, Util.DTR(-90.0)); else ReferVec = Util.RotateVector(FlowVec, Util.DTR(90.0)); using(Transaction trans = new Transaction(doc)) { trans.Start("1"); for (int i = 0; i < m_ElemIDLst.Count(); i++) { Element elem = doc.GetElement(m_ElemIDLst.ElementAt(i)); if (elem is Pipe) { List pipeConLst = Util.GetElementConnectors(elem); List m_ReferLst = new List(); List m_RefptLst = new List(); foreach (Connector con in pipeConLst) { //파이프 패밀리 커넥터 Connector pipeNextCon = Util.GetNextElementConnector(con); if (pipeNextCon != null) { if (pipeNextCon.Owner is FamilyInstance) { FamilyInstance family = pipeNextCon.Owner as FamilyInstance; XYZ referPt = null; Reference DrawRefer = GetFamilyMidPtReference(family, pipe, ReferVec, ref referPt); doc.Regenerate(); if (DrawRefer == null) continue; referPt = new XYZ(referPt.X, referPt.Y, pipeNextCon.Origin.Z); m_ReferLst.Add(DrawRefer); m_RefptLst.Add(referPt); } } else//파이프에 붙은 객체가 없을 경우 파이프 레퍼런스 저장 { foreach (var geoobj in elem.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); } } } else if (elem is Duct) { List ductConLst = Util.GetElementConnectors(elem); List m_ReferLst = new List(); List m_RefptLst = new List(); 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); doc.Regenerate(); 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.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); } } } }//for end trans.Commit(); } //MessageBox.Show("개수: " + m_ReferLst.Count()); } catch (Exception e) { //MessageBox.Show("" + e); } return Result.Succeeded; } public Reference GetFamilyMidPtReference(FamilyInstance family, Pipe DirPipe, XYZ referVec,ref XYZ referPt) { XYZ MidPt=null, sp = null, ep = null; Reference DrawRefer = null; Util.GetStartEndPoint(DirPipe, 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 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); ReferencePlane refPlane = doc.Create.NewReferencePlane2(MidPt, plrpt, thirdPt, doc.ActiveView); DrawRefer = refPlane.GetReference(); referPt = MidPt; //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 CapConLst = Util.GetElementConnectors(family); DrawRefer = GetCapReference(CapConLst.First()); if(DrawRefer != null) referPt = CapConLst.First().Origin; else//못 찾으면 파이프 끝점으로 { Connector PipeCon = Util.GetNextElementConnector(CapConLst.First()); if (PipeCon != null) { foreach (var geoobj in (PipeCon.Owner as Pipe).get_Geometry(NewOptions())) { Curve cv = geoobj as Curve; if (cv != null) { if (cv.GetEndPoint(0).IsAlmostEqualTo(PipeCon.Origin, Unit.MMToFeet(0.01))) { DrawRefer = cv.GetEndPointReference(0); XYZ ConZ = new XYZ(cv.GetEndPoint(0).X, cv.GetEndPoint(0).Y, PipeCon.Origin.Z); referPt = ConZ; break; } else if (cv.GetEndPoint(1).IsAlmostEqualTo(PipeCon.Origin, Unit.MMToFeet(0.01))) { DrawRefer = cv.GetEndPointReference(1); XYZ ConZ = new XYZ(cv.GetEndPoint(1).X, cv.GetEndPoint(1).Y, PipeCon.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); ReferencePlane refPlane = doc.Create.NewReferencePlane2(MidPt, plrpt, thirdPt, doc.ActiveView); DrawRefer = refPlane.GetReference(); referPt = MidPt; //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; } 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 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); ReferencePlane refPlane = doc.Create.NewReferencePlane2(MidPt, plrpt, thirdPt, doc.ActiveView); DrawRefer = refPlane.GetReference(); referPt = MidPt; //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 CapConLst = Util.GetElementConnectors(family); DrawRefer = GetCapReference(CapConLst.First()); if (DrawRefer != null) referPt = CapConLst.First().Origin; else//못 찾으면 파이프 끝점으로 { Connector PipeCon = Util.GetNextElementConnector(CapConLst.First()); if (PipeCon != null) { foreach (var geoobj in (PipeCon.Owner as Pipe).get_Geometry(NewOptions())) { Curve cv = geoobj as Curve; if (cv != null) { if (cv.GetEndPoint(0).IsAlmostEqualTo(PipeCon.Origin, Unit.MMToFeet(0.01))) { DrawRefer = cv.GetEndPointReference(0); XYZ ConZ = new XYZ(cv.GetEndPoint(0).X, cv.GetEndPoint(0).Y, PipeCon.Origin.Z); referPt = ConZ; break; } else if (cv.GetEndPoint(1).IsAlmostEqualTo(PipeCon.Origin, Unit.MMToFeet(0.01))) { DrawRefer = cv.GetEndPointReference(1); XYZ ConZ = new XYZ(cv.GetEndPoint(1).X, cv.GetEndPoint(1).Y, PipeCon.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); ReferencePlane refPlane = doc.Create.NewReferencePlane2(MidPt, plrpt, thirdPt, doc.ActiveView); DrawRefer = refPlane.GetReference(); referPt = MidPt; //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 m_ConLst = new List(); foreach (Connector familyCon in FamilyConSet) m_ConLst.Add(familyCon); Connector resCon = null; if (m_ConLst[0].Radius > m_ConLst[1].Radius) resCon = m_ConLst[1]; else resCon = m_ConLst[0]; //레듀셔의 작은쪽에 붙은 객체 찾기. Connector NextCon = GetNextElementConnector(resCon); //레듀셔 다음 객체가 파이프면 작도 아니면 작도X if (!(NextCon.Owner is Pipe)) return resRef; else 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 = Util.GetNextElementConnector(CurCon); //Pyosi(NextCon.Origin, 1); //MessageBox.Show("NextCon"); bool b_reducer = Util.GetFamilyPartType(NextCon, PartType.Transition); bool b_Cap = Util.GetFamilyPartType(NextCon, PartType.Cap); bool b_valve = Util.GetFamilyPartType(NextCon, PartType.ValveNormal); bool b_BRKvalve = Util.GetFamilyPartType(NextCon, PartType.ValveBreaksInto); if (b_reducer) { Connector NextOtherCon = Util.GetOtherConnector(NextCon); Connector Next2Con = Util.GetNextElementConnector(NextOtherCon); if (Next2Con.Owner is FamilyInstance) { //레듀셔 옆 객체가 Tee 또는 Elbow 일 경우 if (Util.GetFamilyPartType(Next2Con, PartType.Tee) || Util.GetFamilyPartType(Next2Con, PartType.Elbow)) { Connector ClosestCon = Util.GetClosestConnector(NextCon, FlowVec, ReverseVec); Connector ClosestNextCon = null; if (ClosestCon != null) ClosestNextCon = Util.GetNextElementConnector(ClosestCon); if (ClosestNextCon.Owner is Pipe) { resRef = GetElementPointReference(ClosestNextCon.Owner, ClosestNextCon); referPt = ClosestNextCon.Origin; //Pyosi(ClosestNextCon.Origin, 1); //MessageBox.Show("엘보 티"); } else if (ClosestNextCon.Owner is Duct) { resRef = GetElementPointReference(ClosestNextCon.Owner, ClosestNextCon); referPt = ClosestNextCon.Origin; //Pyosi(ClosestNextCon.Origin, 1); //MessageBox.Show("엘보 티"); } else { Connector ClosestCon2 = Util.GetClosestConnector(ClosestNextCon, FlowVec, ReverseVec); Connector ClosestNextCon2 = Util.GetNextElementConnector(ClosestCon2); resRef = GetElementPointReference(ClosestNextCon2.Owner, ClosestNextCon2); referPt = ClosestNextCon2.Origin; //Pyosi(ClosestNextCon2.Origin, 1); //MessageBox.Show("엘보 티 다음 파이프"); } } else { resRef = GetReducerReference(NextCon.Owner); referPt = NextCon.Origin; } } } else if (b_Cap) { resRef = GetCapReference(NextCon.Owner); referPt = NextCon.Origin; } else if (b_valve || b_BRKvalve) return resRef; else//Tee or Elbow { Connector ClosestCon = Util.GetClosestConnector(NextCon, FlowVec, ReverseVec); Connector ClosestNextCon = null; if (ClosestCon != null) ClosestNextCon = Util.GetNextElementConnector(ClosestCon); if (ClosestNextCon.Owner is Pipe) { resRef = GetElementPointReference(ClosestNextCon.Owner, ClosestNextCon); referPt = ClosestNextCon.Origin; //Pyosi(ClosestNextCon.Origin, 1); //MessageBox.Show("엘보 티"); } else { Connector ClosestCon2 = Util.GetClosestConnector(ClosestNextCon, FlowVec, ReverseVec); Connector ClosestNextCon2 = Util.GetNextElementConnector(ClosestCon2); resRef = GetElementPointReference(ClosestNextCon2.Owner, ClosestNextCon2); referPt = ClosestNextCon2.Origin; //Pyosi(ClosestNextCon2.Origin, 1); //MessageBox.Show("엘보 티 다음 파이프"); } } } else { //파이프 커넥터에 객체가 부착되지 않은 경우 파이프를 저장. resRef = GetElementPointReference(CurCon.Owner, CurCon); referPt = CurCon.Origin; //Pyosi(CurCon.Origin, 1); //MessageBox.Show("부착 없는 파이프"); } return resRef; } public void GetBranchElement(Pipe pipe, XYZ FlowVec, XYZ ReverseVec, ref List m_BranchList) { ConnectorSet conSet = pipe.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(pipe); } else { Connector ClosestCon = GetClosestConnector(NextCon, FlowVec, ReverseVec); Connector ClosestNextCon = null; if (ClosestCon != null) ClosestNextCon = GetNextElementConnector(ClosestCon); if (ClosestNextCon.Owner is Pipe) 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(pipe); } } } public Connector GetClosestConnector(Connector baseCon, XYZ FlowVec, XYZ ReverseVec) { Connector resCon = null; ConnectorSet ConSet = null; MEPSystem mEPSystem = baseCon.MEPSystem; FamilyInstance family = null; Pipe pipe = 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; } 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 m_PtLst, List 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); 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); //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(Pipe pipe, Element Elem1, Element Elem2, bool isRight, XYZ DirectPt, List m_ElemIDLst) { SketchPlane geometryPlane = view.SketchPlane; XYZ sp1 = null, sp2 = null, ep1 = null, ep2 = null, p1 = null, p2 = null; Util.GetStartEndPoint(pipe, ref p1, ref p2); Util.GetStartEndPoint(Elem1 as Pipe, ref sp1, ref ep1); Util.GetStartEndPoint(Elem2 as Pipe, 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 Pipe) { Connector NotCon = GetIsNotConnected(Elem1 as Pipe); //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 Pipe).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 Pipe) { foreach (var geoobj in (Elem1 as Pipe).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 m_ConLst = new List(); foreach (Connector familyCon in FamilyConSet) m_ConLst.Add(familyCon); //첫번째 객체가 패밀리이면서 레듀셔일 떄 if (GetFamilyPartType(m_ConLst.First(), PartType.Transition)) { Connector resCon = null; if (m_ConLst[0].Radius > m_ConLst[1].Radius) 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 Pipe)) 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 Pipe) { Connector NotCon = GetIsNotConnected(Elem2 as Pipe); if (GetFamilyPartType(NotCon, PartType.Cap)) { Reference refer = GetCapReference(NotCon); ra.Append(refer); } else { foreach (var geoobj in (Elem2 as Pipe).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 Pipe) { foreach (var geoobj in (Elem2 as Pipe).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 m_ConLst = new List(); foreach (Connector familyCon in FamilyConSet) m_ConLst.Add(familyCon); //첫번째 객체가 패밀리이면서 레듀셔일 떄 if (GetFamilyPartType(m_ConLst.First(), PartType.Transition)) { Connector resCon = null; if (m_ConLst[0].Radius > m_ConLst[1].Radius) 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 Pipe)) 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)); } } } } } Dimension newDim = doc.Create.NewDimension(view, newLine, ra); //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(Pipe pipe) { Connector resCon = null; ConnectorSet conSet = pipe.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 m_ElemIDLst1, ref List 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; Pipe pipe = 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; } 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; 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 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 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; } } 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 Pipe).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; } } }