using Autodesk.Revit.DB; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using System.Collections.Generic; using System.Linq; //using COME4Revit.WinForm; using System.Diagnostics; using Autodesk.Revit.UI.Selection; using System; using System.Windows.Forms; using KDCS.Utils; using View = Autodesk.Revit.DB.View; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.Creation; namespace KMBIM { class SpkrInfor { public ElementId m_SpID; //헤드 ID public Connector HeadCon = null; public XYZ m_Headpt = null; //헤드 커넥터 점. public XYZ m_InterPt = null; //헤드와 메인관 수직점 public double m_Ep2InterDst = 0; // 메인 끝점과 수직점 사이 거리 public bool EqVector = true;//현재 백터와 이전 벡터가 같은지(다르면 90도 꺾인 작도 위해) public XYZ SeparateionPt = null; // 하향식 - 이격거리 점 } class SpkrComparer : IComparer { public int Compare(SpkrInfor a, SpkrInfor b) { double diff = a.m_Ep2InterDst - b.m_Ep2InterDst; if (Math.Abs(diff) < 0.0001) return 0; else if (diff > 0.0001) return 1; else if (diff < 0.0001) return -1; else return 0; } } class SpkrOrthoComparer : IComparer { public int Compare(SpkrInfor a, SpkrInfor b) { double diff = a.m_Headpt.DistanceTo(b.m_InterPt) - b.m_Headpt.DistanceTo(a.m_InterPt); if (Math.Abs(diff) < 0.0001) return 0; else if (diff > 0.0001) return 1; else if (diff < 0.0001) return -1; else return 0; } } [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] public class SprinKlerSort : IExternalCommand { UIApplication uiapp; UIDocument uidoc; Autodesk.Revit.DB.Document doc; public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { uiapp = commandData.Application; uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.ApplicationServices.Application app = uiapp.Application; doc = uidoc.Document; try { //기준 파이프 선택 Reference pipeRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new PipeSelectionFilter(), "기준 배관 선택 : "); //기준 스프링클러 선택 IList spkrRefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(ObjectType.Element, new SpkrSelectionFilter(), "정렬할 스프링클러 범위 지정 : "); Element pipeElem = doc.GetElement(pipeRef); List spkrElemLst = new List(); foreach (Reference refer in spkrRefs) { spkrElemLst.Add(doc.GetElement(refer)); } //기준 파이프 라인 Line pipeLine = ((pipeElem as Pipe).Location as LocationCurve).Curve as Line; if (pipeLine == null) return Result.Cancelled; SpkrInfor Infor = new SpkrInfor(); List inforLst = new List(); XYZ ep2interVec = null; foreach (Element elem in spkrElemLst) { FamilyInstance family = elem as FamilyInstance; List conLst = Util.GetElementConnectors(family); foreach (Connector con in conLst) { IntersectionResult interRes = pipeLine.Project(con.Origin); XYZ interpt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, con.Origin.Z); SpkrInfor infor = new SpkrInfor(); infor.HeadCon = con; infor.m_Headpt = con.Origin; infor.m_InterPt = interpt; infor.m_SpID = con.Owner.Id; //Util.Pyosi(doc, interRes.XYZPoint, 1); infor.m_Ep2InterDst = interRes.XYZPoint.DistanceTo(pipeLine.GetEndPoint(1)); ep2interVec = (interRes.XYZPoint - pipeLine.GetEndPoint(1)).Normalize(); inforLst.Add(infor); } }//foreach end SpkrComparer SC = new SpkrComparer(); SpkrOrthoComparer SOC = new SpkrOrthoComparer(); inforLst.Sort(SC); List> m_TotalLst = new List>(); while (true) { if (inforLst.Count <= 0) break; List Group = DivideObjSprinKlerData(pipeElem as Pipe, inforLst); foreach (SpkrInfor infor in Group) { inforLst.Remove(infor); } //나눈 그룹 리스트에 담기. if (Group.Count > 0) m_TotalLst.Add(Group); }//while end foreach (List spkrLst in m_TotalLst) { if (spkrLst.Count <= 0) continue; double total_InterDst = 0; double avgDst = 0; foreach (SpkrInfor spkr in spkrLst) { total_InterDst += spkr.m_Ep2InterDst; } //그룹 스프링클러들의 평균거리 구함 if (total_InterDst != 0) { avgDst = total_InterDst / spkrLst.Count; XYZ AvgPt = Util.Polar(pipeLine.GetEndPoint(1), (spkrLst.First().m_InterPt - pipeLine.GetEndPoint(1)).Normalize(), avgDst); } //ElementTransformUtils.MoveElement 함수 사용 시 스프링클러가 사라짐. using (Transaction trans = new Transaction(doc)) { trans.Start("moveSpkr"); foreach (SpkrInfor spkr in spkrLst) { XYZ movePt = Util.Polar(spkr.m_Headpt, ep2interVec, avgDst - spkr.m_Ep2InterDst); FamilyInstance family = doc.GetElement(spkr.m_SpID) as FamilyInstance; LocationPoint locpt = family.Location as LocationPoint; locpt.Point = movePt; } trans.Commit(); } } } catch(Exception) { //MessageBox.Show("" + e); } return Result.Succeeded; } List DivideObjSprinKlerData(Pipe mainPipe, List MainObjLst) { List resLst = new List(); resLst.AddRange(MainObjLst); SpkrInfor obj1st = MainObjLst.First(); foreach (SpkrInfor obj in MainObjLst) { double aa = Math.Round(Unit.FeetToMM(obj1st.m_InterPt.DistanceTo(obj.m_InterPt)), 3); if (Math.Round(Unit.FeetToMM(obj1st.m_InterPt.DistanceTo(obj.m_InterPt)), 3) >= 1000) { int ctIdx = resLst.IndexOf(obj); resLst.RemoveAt(ctIdx); } } XYZ sp = null, ep = null; Util.GetStartEndPoint(mainPipe, ref sp, ref ep); for (int i = 0; i < resLst.Count(); i++) { for (int k = 0; k < resLst.Count(); k++) { if (i == k) continue; SpkrInfor obj_i = resLst[i]; SpkrInfor obj_k = resLst[k]; bool i_right = Util.isRightPoint(obj_i.m_Headpt, sp, ep); bool k_right = Util.isRightPoint(obj_k.m_Headpt, sp, ep); //메인관 기준 같은 쪽 헤더가 아니면 넘어감 if (i_right != k_right) continue; double i_inter2HeadDst = obj_i.m_InterPt.DistanceTo(obj_i.m_Headpt); double k_inter2HeadDst = obj_k.m_InterPt.DistanceTo(obj_k.m_Headpt); //헤드점-메인관교차점 길이가 같은게 그룹에 있을 경우 (● ●) if (Math.Abs(i_inter2HeadDst - k_inter2HeadDst) < Unit.MMToFeet(0.01)) { resLst.Remove(obj_k); break; } } } return resLst; } public class SpkrSelectionFilter : ISelectionFilter { public bool AllowElement(Element element) { if (element.Category == null) return false; if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers) { return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return false; } } public class PipeSelectionFilter : ISelectionFilter { public bool AllowElement(Element element) { if (element.Category == null) return false; if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves) { return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return false; } } } }