Client/Desktop/KMBIM3.0/23.11.03/Cmd/SprinklerConnect/Sprinkler_Upword_Auto.cs

519 lines
22 KiB
C#

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using Autodesk.Revit.UI.Selection;
//using SpinKler;
using Autodesk.Revit.DB.Plumbing;
using KDCS.Utils;
using Autodesk.Revit.DB.Structure;
using KMBIM.Revit.Tools.Cmd.SprinklerConnect;
using KMBIM.Revit.Tools;
namespace KMBIM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class Sprinkler_Upword_Auto : IExternalCommand
{
UIApplication uiapp;
UIDocument uidoc;
Autodesk.Revit.DB.Document doc;
Autodesk.Revit.Creation.Application creApp;
Autodesk.Revit.Creation.Document creDoc;
Autodesk.Revit.UI.ExternalCommandData m_commandData;
double m_MainHgt = 0, m_BranchHgt = 0, m_CapDist = 0, m_GenLevElevation = 0, m_Tolerance = 0, m_TReducerDist = 0;
List<ObjSprinKler> lst_objSprinkler = new List<ObjSprinKler>();
ObjComparer OC = new ObjComparer();
ObjOrthoComparer OrthoC = new ObjOrthoComparer();
XYZ mainSp = null, mainEp = null;
SprinKler_Function Spkr_Func = new SprinKler_Function();
Pipe MainPipe = null;
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
m_commandData = commandData;
uiapp = commandData.Application;
uidoc = uiapp.ActiveUIDocument;
doc = uidoc.Document;
creApp = uiapp.Application.Create;
creDoc = doc.Create;
List<ElementId> m_SpklrList = new List<ElementId>();
List<List<ObjSprinKler>> m_TotalObjLst = new List<List<ObjSprinKler>>();
List<List<ObjSprinKler>> Left_TotalObjLst = new List<List<ObjSprinKler>>();
List<List<ObjSprinKler>> Right_TotalObjLst = new List<List<ObjSprinKler>>();
List<double> m_SpklrHgtLst = new List<double>();
double m_MainAng = 0;
try
{
Reference pickref = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "교차배관 선택 : ");
if (pickref == null) return Result.Succeeded;
IList<Reference> pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new HeaderFilter(), "배관에 연결할 스프링클러 범위 지정 : ");
if (pickrefs == null) return Result.Succeeded;
ElementId id = pickref.ElementId;
Element elem1 = doc.GetElement(id) as Element;
foreach (Reference refer in pickrefs)
{
ElementId id2 = refer.ElementId;
Element elem2 = doc.GetElement(id2);
m_SpklrList.Add(id2);
}
Line pipeline = null;//메인 배관 선형
//메인 파이프 간격띄우기 구하기
if (elem1 is Pipe)
{
MainPipe = elem1 as Pipe;
pipeline = (MainPipe.Location as LocationCurve).Curve as Line;
mainSp = pipeline.GetEndPoint(0);
mainEp = pipeline.GetEndPoint(1);
//m_MainHgt = pipeline.GetEndPoint(0).Z;
m_MainHgt = MainPipe.LevelOffset;
//현재 레벨의 높이 구하기.(active Level을 구하면 3D에서 작도가 안됌.)
m_GenLevElevation = Unit.FeetToMM(pipeline.GetEndPoint(0).Z - MainPipe.LevelOffset);
//SprinKler_Function 변수값 넘겨주기
Spkr_Func.doc = uidoc.Document;
Spkr_Func.creDoc = doc.Create;
Spkr_Func.uiapp = commandData.Application;
Spkr_Func.MainPipeTypeId = MainPipe.PipeType.Id;
Spkr_Func.MainSystemTypeId = MainPipe.MEPSystem.GetTypeId();
Spkr_Func.MainLevelId = MainPipe.ReferenceLevel.Id;
}
//헤드 값 지정
foreach (ElementId elemid in m_SpklrList)
{
FamilyInstance family = (doc.GetElement(elemid)) as FamilyInstance;
ConnectorSet conSet = family.MEPModel.ConnectorManager.Connectors;
foreach (Connector con in conSet)
{
IntersectionResult interRes = pipeline.Project(con.Origin);
XYZ interpt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, con.Origin.Z);
ObjSprinKler objSprinKler = new ObjSprinKler();
objSprinKler.HeadCon = con;
objSprinKler.m_Headpt = con.Origin;
objSprinKler.m_InterPt = interpt;
objSprinKler.m_SpID = con.Owner.Id;
objSprinKler.m_Ep2InterDst = interRes.XYZPoint.DistanceTo(pipeline.GetEndPoint(1));
lst_objSprinkler.Add(objSprinKler);
m_SpklrHgtLst.Add(con.Origin.Z);
break;
}
}
//헤드 수직점에 따른 헤드 값 정렬
lst_objSprinkler.Sort(OC);
bool loop = true;
//헤드를 거리별로 그룹 나눠서 리스트에 저장하기.
while (loop)
{
if (lst_objSprinkler.Count <= 0) break;
List<ObjSprinKler> Group = Spkr_Func.DivideObjSprinKlerData(MainPipe, lst_objSprinkler);
//추출 그룹 정렬
Group.Sort(OrthoC);
List<int> ContainLst = new List<int>();
foreach (ObjSprinKler obj in Group)
{
int idx = lst_objSprinkler.IndexOf(obj);
lst_objSprinkler.RemoveAt(idx);
}
//나눈 그룹 리스트에 담기.
if (Group.Count > 0)
m_TotalObjLst.Add(Group);
}//while end
//총 리스트에서 헤드가 1개일 때 그 헤드 리스트 앞 뒤 중 가까운쪽에 넣고 삭제
m_TotalObjLst = Spkr_Func.RemoveSingleObjLst(m_TotalObjLst);
//대화상자 기본값 설정
Form_Upward dlg = new Form_Upward();
dlg.MainHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3);
dlg.BranchHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3) + 300;
dlg.CapDist = 100;
dlg.m_HgtLst = m_SpklrHgtLst;
dlg.SpkrTol = 5;
dlg.TeeReducerDist = 100;
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.Cancel) return Result.Succeeded;
//대화상자 값 가져오기
m_MainHgt = dlg.MainHeight;
m_BranchHgt = dlg.BranchHeight;
m_CapDist = dlg.CapDist;
m_Tolerance = dlg.SpkrTol;
m_TReducerDist = dlg.TeeReducerDist;
//교차배관, 가지배관 높이 재지정
m_MainHgt = m_MainHgt + m_GenLevElevation;
m_BranchHgt = m_BranchHgt + m_GenLevElevation;
//처음 관경25는 헤드쪽때문에 기입
List<double> headLst = new List<double>();
headLst.Add(25); headLst.Add(25); headLst.Add(25); headLst.Add(32); headLst.Add(40); headLst.Add(40);
headLst.Add(50); headLst.Add(50); headLst.Add(50); headLst.Add(50); headLst.Add(50); headLst.Add(65);
headLst.Add(65); headLst.Add(65); headLst.Add(65); headLst.Add(65); headLst.Add(65); headLst.Add(65);
List<Pipe> TeeBranchPipeLst = new List<Pipe>();
using (Transaction trans1 = new Transaction(doc))
{
trans1.Start("cre");
//총 리스트를 메인관 기준 왼쪽 오른쪽 분류
foreach (List<ObjSprinKler> lst_obj in m_TotalObjLst)
{
//허용오차 범위 안 스프링클러 정렬
List<ObjSprinKler> sortLst_obj = SprinklerTolSort(lst_obj, pipeline, m_Tolerance);
List<ObjSprinKler> lst_LeftObj = new List<ObjSprinKler>();
List<ObjSprinKler> lst_RightObj = new List<ObjSprinKler>();
foreach (ObjSprinKler obj in sortLst_obj)
{
if (Util.isRightPoint(obj.m_Headpt, mainEp, mainSp))
lst_RightObj.Add(obj);
else
lst_LeftObj.Add(obj);
}
List<Pipe> pipeLst = ProcessingSpkr(lst_LeftObj, lst_RightObj, elem1, headLst);
TeeBranchPipeLst.AddRange(pipeLst);
}
ElementId MainPipeID = elem1.Id;
//메인관에 T연결
foreach (Pipe pp in TeeBranchPipeLst)
{
Connector pipeSpCon = null, pipeEpCon = null;
bool b_Cons = Util.GetStartEndConnector(pp, ref pipeSpCon, ref pipeEpCon);
if (b_Cons == false) continue;
Line MainLine = ((doc.GetElement(MainPipeID) as Pipe).Location as LocationCurve).Curve as Line;
XYZ DivPt = Util.GetPointOnLine(MainLine, pipeEpCon.Origin);
ElementId divID = PlumbingUtils.BreakCurve(doc, MainPipeID, DivPt);
if (divID == null) continue;
Connector MainCon1 = null, MainCon2 = null;
List<Connector> MainCon1Lst = Util.GetElementConnectors(doc.GetElement(divID));
List<Connector> MainCon2Lst = Util.GetElementConnectors(doc.GetElement(MainPipeID));
foreach (Connector con1 in MainCon1Lst)
{
foreach (Connector con2 in MainCon2Lst)
{
if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
{
MainCon1 = con1;
MainCon2 = con2;
}
}
}
Util.CreateTee(creDoc, MainCon1, MainCon2, pipeEpCon);
MainPipeID = divID;
}
trans1.Commit();
}
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
return Result.Succeeded;
}
public List<Pipe> ProcessingSpkr(List<ObjSprinKler> RangeLeftLst, List<ObjSprinKler> RangeRightLst, Element MainElem, List<double> HeadDiaLst)
{
ObjSprinKler obj1 = null, obj2 = null;
List<XYZ> m_LeftPtLst = new List<XYZ>();
List<XYZ> m_RightPtLst = new List<XYZ>();
List<ModelCurve> m_LCurveLst = new List<ModelCurve>();
List<ModelCurve> m_RCurveLst = new List<ModelCurve>();
List<Pipe> newPipes = new List<Pipe>();
List<Pipe> TeeBranchPipeLst = new List<Pipe>();
List<ObjSprinKler> ExceptSpkrLst = new List<ObjSprinKler>();
Element LeftLastElem = null;
Element RightLastElem = null;
bool b_leftLst_Connect = false;
bool b_rightLst_Connect = false;
foreach (ObjSprinKler obj in RangeLeftLst)
{
if (obj.HeadCon.IsConnected == true)
{
b_leftLst_Connect = true;
break;
}
}
foreach (ObjSprinKler obj in RangeRightLst)
{
if (obj.HeadCon.IsConnected == true)
{
b_rightLst_Connect = true;
break;
}
}
if (b_leftLst_Connect == true || b_rightLst_Connect == true) return TeeBranchPipeLst;
//메인관 기준 왼쪽
int sp_hd = 0, sp_In = 0;
bool b_LeftDraw = true;
if (RangeLeftLst.Count() > 0)
{
//가지파이프
for (int i = 0; i < RangeLeftLst.Count(); i++)
{
if (i < (RangeLeftLst.Count() - 1))
{
obj1 = RangeLeftLst[i];
obj2 = RangeLeftLst[i + 1];
List<XYZ> mainPts = Spkr_Func.UpSPJOIN(obj1, obj2, m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
//틀어진 점에서 작도할 거리가 나오지 않으면 작도 X
if (mainPts == null)
{
if (RangeLeftLst.Count() - 1 >= i + 2)
{
mainPts = Spkr_Func.UpSPJOIN(obj1, RangeLeftLst[i + 2], m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
if (mainPts.Count() > 0)
{
m_LeftPtLst.AddRange(mainPts);
}
i++;
}
ExceptSpkrLst.Add(obj2);
}
else if (mainPts.Count() > 0)
{
m_LeftPtLst.AddRange(mainPts);
}
}
}
if (b_LeftDraw == true)
{
//작도할 수 없는 스프링클러 제거
foreach (ObjSprinKler obj in ExceptSpkrLst)
{
RangeLeftLst.Remove(obj);
}
//메인 연결될 가지파이프
XYZ lastPt = Spkr_Func.GetMain2LastpipePoint(RangeLeftLst.Last(), m_BranchHgt);
m_LeftPtLst.Add(lastPt);
m_LeftPtLst.Reverse();
//캡 파이프
XYZ capPt = Spkr_Func.GetCAPpoint(RangeLeftLst.First(), m_BranchHgt, m_CapDist);
m_LeftPtLst.Add(capPt);
m_LeftPtLst.Reverse();
//파이프 및 엘보 생성
newPipes = Util.CreatePipe(uiapp, doc, m_LeftPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
//헤드와 가지관 연결
List<ElementId> LeftElemIdLst = Spkr_Func.ConnectHead2pipe(RangeLeftLst, newPipes, HeadDiaLst,m_TReducerDist);
doc.Regenerate();
LeftLastElem = doc.GetElement(LeftElemIdLst.Last());
}
}
//메인관 기준 오른쪽
sp_hd = 0; sp_In = 0;
bool b_RightDraw = true;
ExceptSpkrLst.Clear();
if (RangeRightLst.Count() > 0)
{
////캡 파이프
//List<XYZ> capPt = GetCAPpipe(RangeRightLst.First(), m_HeadOffset, m_CapDist);
//m_RightPtLst.AddRange(capPt);
//가지 파이프
for (int i = 0; i < RangeRightLst.Count(); i++)
{
if (i < (RangeRightLst.Count() - 1))
{
obj1 = RangeRightLst[i];
obj2 = RangeRightLst[i + 1];
List<XYZ> mainPts = Spkr_Func.UpSPJOIN(obj1, obj2, m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
//틀어진 점에서 작도할 거리가 나오지 않으면 작도 X
if (mainPts == null)
{
if (RangeRightLst.Count() - 1 >= i + 2)
{
mainPts = Spkr_Func.UpSPJOIN(obj1, RangeRightLst[i + 2], m_BranchHgt, ref sp_In, i + 1, HeadDiaLst);
if (mainPts.Count() > 0)
{
m_RightPtLst.AddRange(mainPts);
}
i++;
}
ExceptSpkrLst.Add(obj2);
}
else if (mainPts.Count() > 0)
{
m_RightPtLst.AddRange(mainPts);
}
}
}
if (b_RightDraw == true)
{
//작도할 수 없는 스프링클러 제거
foreach (ObjSprinKler obj in ExceptSpkrLst)
{
RangeRightLst.Remove(obj);
}
//메인 연결될 가지파이프
XYZ lastPt = Spkr_Func.GetMain2LastpipePoint(RangeRightLst.Last(), m_BranchHgt);
m_RightPtLst.Add(lastPt);
m_RightPtLst.Reverse();
//캡 파이프
XYZ capPt = Spkr_Func.GetCAPpoint(RangeRightLst.First(), m_BranchHgt, m_CapDist);
m_RightPtLst.Add(capPt);
m_RightPtLst.Reverse();
//파이프 및 엘보 생성
newPipes = Util.CreatePipe(uiapp, doc, m_RightPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
//헤드와 가지관 연결
List<ElementId> RightElemIdLst = Spkr_Func.ConnectHead2pipe(RangeRightLst, newPipes, HeadDiaLst, m_TReducerDist);
doc.Regenerate();
RightLastElem = doc.GetElement(RightElemIdLst.Last());
}
}
//메인관 가지관 연결
TeeBranchPipeLst = Spkr_Func.MainConnectBranch(MainElem, LeftLastElem, RightLastElem);
//trans1.Commit();
return TeeBranchPipeLst;
}
public List<ObjSprinKler> SprinklerTolSort(List<ObjSprinKler> GroupSpkr, Line MainLine, double m_Tol)
{
List<ObjSprinKler> resLst = new List<ObjSprinKler>();
ObjSprinKler FirstSpkr = GroupSpkr.First();
XYZ newEpt = new XYZ(MainLine.GetEndPoint(1).X, MainLine.GetEndPoint(1).Y, FirstSpkr.m_InterPt.Z);
double firstDist = FirstSpkr.m_InterPt.DistanceTo(newEpt);
foreach(ObjSprinKler spkr in GroupSpkr)
{
if (spkr.m_SpID.Equals(FirstSpkr.m_SpID))
{
resLst.Add(spkr);
continue;
}
double nextDist = spkr.m_InterPt.DistanceTo(newEpt);
if (Math.Abs(firstDist - nextDist) > Unit.MMToFeet(m_Tol) || Math.Abs(firstDist - nextDist) < Unit.MMToFeet(0.01))
{
resLst.Add(spkr);
continue;
}
XYZ moveVec = (FirstSpkr.m_InterPt - spkr.m_InterPt).Normalize();
XYZ movePt = Util.Polar(spkr.m_Headpt, moveVec, Math.Abs(firstDist - nextDist));
FamilyInstance family = doc.GetElement(spkr.m_SpID) as FamilyInstance;
LocationPoint locpt = family.Location as LocationPoint;
locpt.Point = movePt;
doc.Regenerate();
List<Connector> spkrCon = Util.GetElementConnectors(family);
//메인관-커넥터 가까운 점
IntersectionResult interRes = MainLine.Project(spkrCon.First().Origin);
XYZ interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, spkrCon.First().Origin.Z);
//스프링클러 헤드 정보
spkr.HeadCon = spkrCon.First();
spkr.m_Headpt = spkrCon.First().Origin;
spkr.m_InterPt = interPt;
spkr.m_SpID = family.Id;
resLst.Add(spkr);
}
return resLst;
}
public class HeaderFilter : 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 SelectionFilter : 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;
}
}
}
}