262 lines
10 KiB
C#
262 lines
10 KiB
C#
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<SpkrInfor>
|
|
{
|
|
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<SpkrInfor>
|
|
{
|
|
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<Reference> spkrRefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(ObjectType.Element, new SpkrSelectionFilter(), "정렬할 스프링클러 범위 지정 : ");
|
|
|
|
Element pipeElem = doc.GetElement(pipeRef);
|
|
|
|
List<Element> spkrElemLst = new List<Element>();
|
|
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<SpkrInfor> inforLst = new List<SpkrInfor>();
|
|
XYZ ep2interVec = null;
|
|
|
|
foreach (Element elem in spkrElemLst)
|
|
{
|
|
FamilyInstance family = elem as FamilyInstance;
|
|
List<Connector> 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<List<SpkrInfor>> m_TotalLst = new List<List<SpkrInfor>>();
|
|
|
|
while (true)
|
|
{
|
|
if (inforLst.Count <= 0) break;
|
|
|
|
List<SpkrInfor> 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<SpkrInfor> 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<SpkrInfor> DivideObjSprinKlerData(Pipe mainPipe, List<SpkrInfor> MainObjLst)
|
|
{
|
|
List<SpkrInfor> resLst = new List<SpkrInfor>();
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|