Client/Desktop/KMBIM3.0/23.10.18/Cmd/SprinklerConnect/Sprinkler_Upword.cs

978 lines
42 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 Autodesk.Revit.DB.Mechanical;
using KDCS.Utils;
using KMBIM.Revit.Tools.Properties;
namespace KMBIM
{
public class ObjSprinKler
{
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 class ObjComparer : IComparer<ObjSprinKler>
{
public int Compare(ObjSprinKler a, ObjSprinKler 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;
}
}
public class ObjOrthoComparer : IComparer<ObjSprinKler>
{
public int Compare(ObjSprinKler a, ObjSprinKler b)
{
double diff = b.m_Headpt.DistanceTo(a.m_InterPt) - a.m_Headpt.DistanceTo(b.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)]
class Sprinkler_Upword : 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_HeadOffset = 0, m_CapDist = 0;
List<ObjSprinKler> lst_objSprinkler = new List<ObjSprinKler>();
ObjComparer OC = new ObjComparer();
ObjOrthoComparer OrthoC = new ObjOrthoComparer();
PipeType mainPipeType = null;
double MainPipeOffset = 0;
XYZ MainVec = null;
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
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;
XYZ mainSp = null, mainEp = null;
MessageBox.Show("123");
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)
{
Pipe MainPipe = elem1 as Pipe;
mainPipeType = MainPipe.PipeType;
MainPipeOffset = MainPipe.LevelOffset;
pipeline = (MainPipe.Location as LocationCurve).Curve as Line;
mainSp = pipeline.GetEndPoint(0);
mainEp = pipeline.GetEndPoint(1);
MainVec = (mainEp - mainSp).Normalize();
m_MainHgt = pipeline.GetEndPoint(0).Z;
m_MainAng = Util.Angle2D(pipeline.GetEndPoint(0), pipeline.GetEndPoint(1));
}
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);
//m_HeadInterPtLst.Add(interRes.XYZPoint);//헤드 교차점 리스트.
//m_HeadDictionary.Add(con, interRes.XYZPoint);
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);
///////////////////////////////////////////배열 추가해야 함.
//Pyosi(interRes.XYZPoint,1);
//MessageBox.Show("1");
m_SpklrHgtLst.Add(con.Origin.Z);
break;
}
}
//헤드 수직점에 따른 헤드 값 정렬
lst_objSprinkler.Sort(OC);
foreach (ObjSprinKler obj in lst_objSprinkler)
{
XYZ aa = obj.m_Headpt;
XYZ bb = obj.m_InterPt;
ElementId eid = obj.m_SpID;
//Pyosi(aa, 1);
//MessageBox.Show("head");
//Pyosi(bb, 1);
//MessageBox.Show("inter");
}
bool loop = true;
//헤드를 거리별로 그룹 나눠서 리스트에 저장하기.
while (loop)
{
if (lst_objSprinkler.Count <= 0) break;
List<ObjSprinKler> Group = DivideObjSprinKlerData(lst_objSprinkler);
//추출 그룹 정렬
Group.Sort(OrthoC);
List<int> ContainLst = new List<int>();
foreach (ObjSprinKler obj in Group)
{
//Pyosi(obj.m_InterPt, 1);
//MessageBox.Show("1");
int idx = lst_objSprinkler.IndexOf(obj);
lst_objSprinkler.RemoveAt(idx);
}
//나눈 그룹 리스트에 담기.
if (Group.Count > 0)
m_TotalObjLst.Add(Group);
}//while end
//총 리스트에서 헤드가 1개일 때 그 헤드 리스트 앞 뒤 중 가까운쪽에 넣고 삭제
m_TotalObjLst = RemoveSingleObjLst(m_TotalObjLst);
//m_TotalObjLst.Reverse();//메인관 끝점부터 시작하기 위해
//MessageBox.Show("m_TotalObjLst :" + m_TotalObjLst.Count());
Form_Upword dlg = new Form_Upword();
dlg.MainHeight = Unit.FeetToMM(m_MainHgt);
dlg.HeaderOffset = 150;
dlg.CapDist = 100;
dlg.m_HgtLst = m_SpklrHgtLst;//헤드 높이를 메인파이프 높이와 비교하기 위해
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.Cancel) return Result.Succeeded;
//대화상자 값 가져오기
m_MainHgt = dlg.MainHeight;
m_HeadOffset = dlg.HeaderOffset;
m_CapDist = dlg.CapDist;
//처음 관경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);
//총 리스트를 메인관 기준 왼쪽 오른쪽 분류
foreach (List<ObjSprinKler> lst_obj in m_TotalObjLst)
{
List<ObjSprinKler> lst_LeftObj = new List<ObjSprinKler>();
List<ObjSprinKler> lst_RightObj = new List<ObjSprinKler>();
foreach (ObjSprinKler obj in lst_obj)
{
if (Util.isRightPoint(obj.m_Headpt, mainEp, mainSp))
lst_RightObj.Add(obj);
else
lst_LeftObj.Add(obj);
}
ProcessingSpkr(lst_LeftObj, lst_RightObj, mainSp, mainEp, MainVec, headLst);
}
}
catch
{
}
return Result.Succeeded;
}
public void ProcessingSpkr(List<ObjSprinKler> RangeLeftLst, List<ObjSprinKler> RangeRightLst, XYZ MainSp, XYZ MainEp, XYZ mainVec, List<double> HeadDiaLst)
{
double Ldraw_ang = Util.Angle2D(MainSp, MainEp) - (0.5 * Util.kPi);
double Rdraw_ang = Util.Angle2D(MainSp, MainEp) + (0.5 * Util.kPi);
XYZ v = (MainEp - MainSp).Normalize();
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>();
//메인관 기준 왼쪽
int sp_hd = 0, sp_In = 0;
if (RangeLeftLst.Count() > 0)
{
using (Transaction trans = new Transaction(doc))
{
trans.Start("Left");
//캡 파이프
List<XYZ> capPt = GetCAPpipe(RangeLeftLst.First(), m_HeadOffset, m_CapDist);
m_LeftPtLst.AddRange(capPt);
//가지파이프
for (int i = 0; i < RangeLeftLst.Count(); i++)
{
if (i < (RangeLeftLst.Count() - 1))
{
obj1 = RangeLeftLst[i];
obj2 = RangeLeftLst[i + 1];
List<XYZ> mainPts = SPJOIN(obj1, obj2, m_HeadOffset, ref sp_hd, ref sp_In);
m_LeftPtLst.AddRange(mainPts);
}
}
//메인 연결될 가지파이프
List<XYZ> lastPt = GetMain2Lastpipe(RangeLeftLst.Last(), m_HeadOffset, ref sp_hd);
m_LeftPtLst.AddRange(lastPt);
//파이프 및 엘보 생성
newPipes = CreatePipe(uidoc, doc, m_LeftPtLst, mainPipeType);
trans.Commit();
}
//헤드와 가지관 연결
ConnectHead2pipe(RangeLeftLst, newPipes, HeadDiaLst);
}
//메인관 기준 오른쪽
sp_hd = 0; sp_In = 0;
if (RangeRightLst.Count() > 0)
{
using (Transaction trans = new Transaction(doc))
{
trans.Start("Right");
//캡 파이프
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 = SPJOIN(obj1, obj2, m_HeadOffset, ref sp_hd, ref sp_In);
m_RightPtLst.AddRange(mainPts);
}
}
//메인 연결될 가지파이프
List<XYZ> lastPt = GetMain2Lastpipe(RangeRightLst.Last(), m_HeadOffset, ref sp_hd);
m_RightPtLst.AddRange(lastPt);
//파이프 및 엘보 생성
newPipes = CreatePipe(uidoc, doc, m_RightPtLst, mainPipeType);
trans.Commit();
}
//헤드와 가지관 연결
ConnectHead2pipe(RangeRightLst, newPipes, HeadDiaLst);
}
}
//캡포인트 구하기.
public List<XYZ> GetCAPpipe(ObjSprinKler FirstObjSpkr, double HeadOffset, double CapDist)
{
//메인-헤드 방향 벡터
XYZ MHvec = (FirstObjSpkr.m_Headpt - FirstObjSpkr.m_InterPt).Normalize();
//헤드-캡까지의 간격(사용자입력값)만큼 떨어진 점 구하기.
XYZ CapPt = Util.Polar(FirstObjSpkr.m_Headpt, MHvec, Unit.MMToFeet(CapDist));
//헤드간격 띄우기 값 적용
XYZ newCapPt = new XYZ(CapPt.X, CapPt.Y, CapPt.Z - Unit.MMToFeet(HeadOffset));
XYZ newHeadPt = new XYZ(FirstObjSpkr.m_Headpt.X, FirstObjSpkr.m_Headpt.Y, FirstObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
List<XYZ> pts = new List<XYZ>();
pts.Add(newCapPt);
//pts.Add(newHeadPt);
return pts;
}
//틀어진 가지관 등 점 구하기.
public List<XYZ> SPJOIN(ObjSprinKler objSpkr1, ObjSprinKler objSpkr2, double HeadOffset, ref int sp_hd, ref int sp_in)
{
double siz15 = 0, ang1 = 0; ;
XYZ pt110 = null, pt210 = null, tmppt1 = null, tmppt2 = null,
pt2 = null, pt21 = null, pt22 = null, inter1 = null, vec = null;
XYZ jpt1 = objSpkr1.m_Headpt;
XYZ jpt2 = objSpkr2.m_Headpt;
siz15 = Unit.MMToFeet(300);
vec = (objSpkr1.m_Headpt - objSpkr2.m_Headpt).Normalize();
double vecAng = Util.RTD(vec.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ));
//헤드메인교차점-헤드 벡터
XYZ HMvec = (objSpkr1.m_InterPt - objSpkr1.m_Headpt).Normalize();
ang1 = vecAng;
List<XYZ> linePtlst = new List<XYZ>();
//두개의 헤드가 틀어진 경우
if (!(Math.Abs(ang1 - 0.0) < 0.001) && !(Math.Abs(ang1 - 90.0) < 0.001) &&
!(Math.Abs(ang1 - 180.0) < 0.001) && !(Math.Abs(ang1 - 270.0) < 0.001))
{
sp_in++;
if (sp_in == 1)
{
pt110 = Util.Polar(jpt1, HMvec, siz15);
pt210 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(180)), siz15);
tmppt1 = Util.Polar(jpt1, HMvec, 1000);
tmppt2 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(90)), 1000);
inter1 = GetIntersectionPoint(jpt1, tmppt1, jpt2, tmppt2);
pt21 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(90)), inter1.DistanceTo(jpt2));
pt22 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(270)), inter1.DistanceTo(jpt2));
}
else
{
pt210 = Util.Polar(jpt1, HMvec, siz15);
pt110 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(180)), siz15);
tmppt1 = Util.Polar(jpt1, HMvec, 1000);
tmppt2 = Util.Polar(jpt2, Util.RotateVector(HMvec, Util.DTR(90)), 1000);
inter1 = GetIntersectionPoint(jpt1, tmppt1, jpt2, tmppt2);
pt21 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(90)), inter1.DistanceTo(jpt2));
pt22 = Util.Polar(pt110, Util.RotateVector(HMvec, Util.DTR(270)), inter1.DistanceTo(jpt2));
}
if (sp_in >= 2)
sp_in = 0;
if (pt210.DistanceTo(pt21) >= pt210.DistanceTo(pt22))
pt2 = pt22;
else
pt2 = pt21;
//Pyosi(pt2, 1);
//MessageBox.Show("pt2");
//헤드간격 띄우기 값 적용
XYZ newHeadPt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, objSpkr1.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
XYZ newHeadPt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, objSpkr2.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
XYZ newpt110 = new XYZ(pt110.X, pt110.Y, pt110.Z - Unit.MMToFeet(HeadOffset));
XYZ newpt2 = new XYZ(pt2.X, pt2.Y, pt2.Z - Unit.MMToFeet(HeadOffset));
if (sp_in == 1)
{
//linePtlst.Add(newHeadPt1);
linePtlst.Add(newpt110);
linePtlst.Add(newpt2);
//linePtlst.Add(newHeadPt2);
}
else
{
//linePtlst.Add(newHeadPt1);
linePtlst.Add(newpt2);
linePtlst.Add(newpt110);
//linePtlst.Add(newHeadPt2);
}
}
else//두개의 헤드가 일직선인 경우
{
//헤드간격 띄우기 값 적용
XYZ newHeadPt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, objSpkr1.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
XYZ newHeadPt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, objSpkr2.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
//linePtlst.Add(newHeadPt1);
//linePtlst.Add(newHeadPt2);
}
sp_hd++;
return linePtlst;
}
//메인 연결될 가지파이프
public List<XYZ> GetMain2Lastpipe(ObjSprinKler LastObjSpkr, double HeadOffset, ref int sp_hd)
{
List<XYZ> pts = new List<XYZ>();
//헤드간격 띄우기 값 적용
XYZ newInterPt = new XYZ(LastObjSpkr.m_InterPt.X, LastObjSpkr.m_InterPt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
XYZ newHeadPt = new XYZ(LastObjSpkr.m_Headpt.X, LastObjSpkr.m_Headpt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
//pts.Add(newHeadPt);
pts.Add(newInterPt);
return pts;
}
public void ConnectHead2pipe(List<ObjSprinKler> sprinKlers, List<Pipe> pipes, List<double> HeadDiaLst)
{
//double DirectAng = FromBranchToHeadAngle(sprinKlers.First(), pipes.First());
Pipe pipe = pipes.First();
Pipe DividePipe = null;
for (int i = 0; i < sprinKlers.Count(); i++)
{
ObjSprinKler obj = sprinKlers.ElementAt(i);
DividePipe = CreatePipeT(obj, pipe);
if (DividePipe != null)
{
ApplyReducerAndDiameter(DividePipe, HeadDiaLst[i], HeadDiaLst[i + 1], 100);
pipe = DividePipe;
}
else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행
{
pipes.RemoveAt(0);
foreach (Pipe pp in pipes)
{
//XYZ aa = null, bb = null;
//Util.GetStartEndPoint(pp, ref aa, ref bb);
//Pyosi(aa, 1);
//MessageBox.Show("1");
//Connector con = pp.ConnectorManager.Connectors.Cast<Connector>().First();
//con.Radius = Unit.MMToFeet(HeadDiaLst[i] / 2.0);
DividePipe = CreatePipeT(obj, pp);
if (DividePipe != null)
{
ApplyReducerAndDiameter(DividePipe, HeadDiaLst[i], HeadDiaLst[i + 1], 100);
pipe = DividePipe;
break;
}
}
}
}
}
public Pipe CreatePipeT(ObjSprinKler objSprinKler, Pipe BranchPipe)
{
Line pipeline = (BranchPipe.Location as LocationCurve).Curve as Line;
IntersectionResult intersection = pipeline.Project(objSprinKler.m_Headpt);
XYZ interPt = intersection.XYZPoint;
//헤드와 배관의 가까운점이 배관의 시작 또는 끝점일 경우 실행X
if (interPt.IsAlmostEqualTo(pipeline.GetEndPoint(0), Unit.MMToFeet(0.01))
|| interPt.IsAlmostEqualTo(pipeline.GetEndPoint(1), Unit.MMToFeet(0.01))) return null;
ElementId m_divideElemId = null;
using (Transaction trans = new Transaction(doc))
{
trans.Start("1");
//가지관 자르기
m_divideElemId = PlumbingUtils.BreakCurve(doc, BranchPipe.Id, interPt);
Pipe divideBranchPipe = doc.GetElement(m_divideElemId) as Pipe;
Pipe Headpipe = CreateHeadPipe(objSprinKler, interPt, BranchPipe);
Connector HeadCon = null, mainCon1 = null, mainCon2 = null;
//나뉜 파이프의 겹치는 커넥터 구하기(T커넥터)
List<Connector> MainCon1Lst = Util.GetElementConnectors(divideBranchPipe);
List<Connector> MainCon2Lst = Util.GetElementConnectors(BranchPipe);
foreach (Connector con1 in MainCon1Lst)
{
foreach (Connector con2 in MainCon2Lst)
{
if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
{
mainCon1 = con1; mainCon2 = con2;
}
}
}
//헤드 파이프 T커넥터
List<Connector> HeadConsLst = Util.GetElementConnectors(Headpipe as Element);
foreach (Connector con in HeadConsLst)
{
if (con.Origin.IsAlmostEqualTo(interPt, Unit.MMToFeet(0.01)))
HeadCon = con;
}
if (mainCon1 != null && mainCon2 != null && HeadCon != null)
{
FamilyInstance family = creDoc.NewTeeFitting(mainCon1, mainCon2, HeadCon);
}
trans.Commit();
}
return BranchPipe;
}
//파이프에 관경 넣고 T와 레듀셔 사이 100mm 떨어트려 작도
public void ApplyReducerAndDiameter(Pipe BranchPipe, double CurDia, double NextDia, double T2ReducerDist)
{
if (Math.Abs(CurDia - NextDia) < 0.01) return;
XYZ sp = null, ep = null;
Connector PipeStartCon = null, TeeCon = null;
Util.GetStartEndPoint(BranchPipe, ref sp, ref ep);
List<Connector> pipeConLst = Util.GetElementConnectors(BranchPipe);
if (sp.DistanceTo(ep) < Unit.MMToFeet(200))
{
MessageBox.Show("길이가 짧습니다.");
return;
}
//시작점 커넥터 구하기.
foreach (Connector con in pipeConLst)
{
if (con.Origin.IsAlmostEqualTo(sp, Unit.MMToFeet(0.01)))
PipeStartCon = con;
}
TeeCon = Util.GetNextElementConnector(PipeStartCon);
List<XYZ> reducerPtLst = new List<XYZ>();
using (Transaction trans = new Transaction(doc))
{
trans.Start("1");
// T 와 파이프 연결 끊기
PipeStartCon.DisconnectFrom(TeeCon);
// T 에서 100mm만큼 파이프생성
XYZ ReducerPt = Util.Polar(TeeCon.Origin, sp, ep, Unit.MMToFeet(100));
reducerPtLst.Add(TeeCon.Origin); reducerPtLst.Add(ReducerPt);
List<Pipe> newPipeLst = CreatePipe(uidoc, doc, reducerPtLst, mainPipeType);
List<Connector> newPipeCons = Util.GetElementConnectors(newPipeLst[0]);
newPipeCons.First().Radius = TeeCon.Radius;
PipeStartCon.Radius = Unit.MMToFeet(NextDia) / 2.0;
PipeStartCon.Origin = Util.Polar(PipeStartCon.Origin, sp, ep, Unit.MMToFeet(109));
//Pyosi(PipeStartCon.Origin, 0);
//새로 만든 파이프와 연결
foreach (Connector con in newPipeCons)
{
if (con.Origin.IsAlmostEqualTo(ReducerPt, Unit.MMToFeet(0.01)))
{
creDoc.NewTransitionFitting(con, PipeStartCon);
}
}
//틀어진 경우 레듀셔 커넥터에서부터 다음 T나오기전까지 관경 동일하게 만들기.
//Connector OtherCon = Util.GetOtherConnector(PipeStartCon);
//Connector OtherNextCon = Util.GetNextElementConnector(OtherCon);
//bool loop = false;
//
//if (OtherNextCon != null) loop = true;
//
//while (loop)
//{
//
// if (Util.GetFamilyPartType(OtherNextCon, PartType.Transition))
// {
// OtherNextCon = Util.GetNextElementConnector(OtherCon);
// OtherCon = Util.GetOtherConnector(OtherNextCon);
// Pyosi(OtherCon.Origin, 0);
// }
// else if(Util.GetFamilyPartType(OtherNextCon, PartType.Elbow))
// {
// OtherNextCon = Util.GetNextElementConnector(OtherCon);
// OtherCon = Util.GetOtherConnector(OtherNextCon);
// Pyosi(OtherCon.Origin, 0);
// }
// else if (Util.GetFamilyPartType(OtherNextCon, PartType.Tee))
// {
// break;
// }
// else if(OtherNextCon.Owner is Pipe)
// {
// OtherNextCon = Util.GetNextElementConnector(OtherCon);
// OtherCon = Util.GetOtherConnector(OtherNextCon);
// Pyosi(OtherCon.Origin, 0);
// }
//
//}//while end
trans.Commit();
}
//Pyosi(sp, 1);
//MessageBox.Show("1");
}
//T연결에 필요한 분기배관 생성
public Pipe CreateHeadPipe(ObjSprinKler objSpkr, XYZ breakPt, Pipe BranchPipe)
{
Level level = doc.ActiveView.GenLevel;
Pipe headPipe = Pipe.Create(doc, BranchPipe.MEPSystem.GetTypeId(), BranchPipe.GetTypeId(), level.Id, breakPt, objSpkr.m_Headpt);
List<Connector> HeadCons = Util.GetElementConnectors(headPipe);
foreach (Connector con in HeadCons)
{
if (con.Origin.IsAlmostEqualTo(objSpkr.HeadCon.Origin, Unit.MMToFeet(0.01)))
{
con.Radius = Unit.MMToFeet(25 / 2.0);
//헤드와 헤드파이프 커넥터 연결
con.ConnectTo(objSpkr.HeadCon);
}
}
return headPipe;
}
// 1000mm범위의 헤드를 리스트에 담아 리턴
public List<ObjSprinKler> DivideObjSprinKlerData(List<ObjSprinKler> MainObjLst)
{
List<ObjSprinKler> resLst = new List<ObjSprinKler>();
resLst.AddRange(MainObjLst);
ObjSprinKler obj1st = MainObjLst.First();
foreach (ObjSprinKler 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);
}
}
return resLst;
}
//총 리스트에서 헤드가 1개일 때 그 헤드 리스트 앞 뒤 중 가까운쪽에 넣고 삭제
public List<List<ObjSprinKler>> RemoveSingleObjLst(List<List<ObjSprinKler>> m_Lst)
{
for (int i = 0; i < m_Lst.Count(); i++)
{
List<ObjSprinKler> m_objLst = m_Lst.ElementAt(i);
if (m_objLst.Count() == 1)
{
if (i == 0)//첫번째 그룹에 1개일 때 이전을 비교할 필요없음.
{
List<ObjSprinKler> AfterObj = m_Lst[i + 1];
AfterObj.Add(m_Lst[i].First());
m_Lst[i].Remove(m_Lst[i].First());
AfterObj.Sort(OrthoC);
}
else if (i > 0)//두번째 이후
{
List<ObjSprinKler> BeforeObj = m_Lst[i - 1];
List<ObjSprinKler> CurObj = m_Lst[i];
List<ObjSprinKler> AfterObj = m_Lst[i + 1];
double beforeDist = BeforeObj.First().m_Headpt.DistanceTo(CurObj.First().m_Headpt);
double afterDist = AfterObj.First().m_Headpt.DistanceTo(CurObj.First().m_Headpt);
//가까운쪽에 넣기
if (Math.Round(Unit.FeetToMM(beforeDist), 3) < Math.Round(Unit.FeetToMM(afterDist), 3))
{
BeforeObj.Add(CurObj.First());
CurObj.Remove(CurObj.First());
BeforeObj.Sort(OrthoC);
}
else
{
AfterObj.Add(CurObj.First());
CurObj.Remove(CurObj.First());
AfterObj.Sort(OrthoC);
}
}
else if (i == m_Lst.Count() - 1)
{
List<ObjSprinKler> BeforeObj = m_Lst[i - 1];
BeforeObj.Add(m_Lst[i].First());
m_Lst[i].Remove(m_Lst[i].First());
BeforeObj.Sort(OrthoC);
}
}
}
List<List<ObjSprinKler>> RemoveIdxLst = new List<List<ObjSprinKler>>();
foreach (List<ObjSprinKler> objsp in m_Lst)
{
if (objsp.Count == 0)
{
RemoveIdxLst.Add(objsp);
//m_TotalObjLst.RemoveAt(idx);
}
}
foreach (List<ObjSprinKler> objsp in RemoveIdxLst)
{
m_Lst.Remove(objsp);
}
return m_Lst;
}
public class HeaderFilter : ISelectionFilter
{
public bool AllowElement(Element element)
{
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.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
{
return true;
}
return false;
}
public bool AllowReference(Reference refer, XYZ point)
{
return false;
}
}
public XYZ GetIntersectionPoint(XYZ p1, XYZ p2, XYZ p3, XYZ p4)
{
double d = (p1.X - p2.X) * (p3.Y - p4.Y) - (p1.Y - p2.Y) * (p3.X - p4.X);
if (d == 0) return null;
double pre = (p1.X * p2.Y - p1.Y * p2.X), post = (p3.X * p4.Y - p3.Y * p4.X);
double x = (pre * (p3.X - p4.X) - (p1.X - p2.X) * post) / d;
double y = (pre * (p3.Y - p4.Y) - (p1.Y - p2.Y) * post) / d;
XYZ resPt = new XYZ(x, y, p1.Z);
return resPt;
}
public bool Pyosi(XYZ pt, int TranMode)
{
Level level = doc.ActiveView.GenLevel;
if (TranMode == 0)
{
XYZ pt1 = new XYZ(pt.X - 1.64042, pt.Y + 1.64042, level.Elevation);
XYZ pt2 = new XYZ(pt.X + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), pt.Y + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), level.Elevation);
XYZ pt3 = new XYZ(pt.X + 1.64042, pt.Y - 1.64042, level.Elevation);
XYZ pt4 = new XYZ(pt.X - 1.64042, pt.Y - 1.64042, level.Elevation);
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 - 1.64042, pt.Y + 1.64042, level.Elevation);
XYZ pt2 = new XYZ(pt.X + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), pt.Y + Unit.CovertToAPI(500, DisplayUnitType.DUT_MILLIMETERS), level.Elevation);
XYZ pt3 = new XYZ(pt.X + 1.64042, pt.Y - 1.64042, level.Elevation);
XYZ pt4 = new XYZ(pt.X - 1.64042, pt.Y - 1.64042, level.Elevation);
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 List<Pipe> CreatePipe(UIDocument uidoc, Document document, List<XYZ> pts, PipeType pipeType)
{
Autodesk.Revit.DB.View view = document.ActiveView;
Level level = document.ActiveView.GenLevel;
FilteredElementCollector sysCollector = new FilteredElementCollector(document);
//sysCollector.OfClass(typeof(PipingSystemType));
sysCollector.OfCategory(BuiltInCategory.OST_PipingSystem);
ElementId pipeSysTypeId = sysCollector.FirstElementId();
Pipe newpipe = null;
List<Pipe> pipes = new List<Pipe>();
List<Curve> newLineLst = new List<Curve>();
List<Element> ElemLst = new List<Element>();
for (int i = 0; i < pts.Count() - 1; i++)
{
ModelLine newLine = Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pts[i], pts[i + 1]) as ModelLine;
Curve cur = newLine.GeometryCurve;
newLineLst.Add(cur);
ElemLst.Add(newLine);
}
try
{
List<Element> elePipe = new List<Element>();
int cnt = 0;
foreach (Curve cur in newLineLst)
{
XYZ start = cur.GetEndPoint(0);
XYZ end = cur.GetEndPoint(1);
if (pipeType != null)
{
newpipe = Pipe.Create(document, pipeSysTypeId, pipeType.Id, level.Id, start, end);
//MessageBox.Show("1");
Element element = document.GetElement(newpipe.Id as ElementId);
elePipe.Add(element);
// 1-6) fitting 할 elbow 굵기에 맞게 pipe 굵기 설정하기
ElementId elementId = newpipe.Id as ElementId;
//Parameter parameter = element.LookupParameter("지름");
newpipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(Unit.MMToFeet(25));
pipes.Add(newpipe);
}
}
document.Regenerate();
for (int i = 0; i < pipes.Count() - 1; i++)
{
ConnectorManager pipe_connectorManager1 = pipes.ElementAt(i).ConnectorManager;
ConnectorSet pipe_connectorSet1 = pipe_connectorManager1.Connectors;
ConnectorManager pipe_connectorManager2 = pipes.ElementAt(i + 1).ConnectorManager;
ConnectorSet pipe_connectorSet2 = pipe_connectorManager2.Connectors;
// 2-3) 파이프가 가지고 있는 connectors 에서 연결시킬 connector 뽑아내기
Connector pipe_connector1 = null;
Connector pipe_connector2 = null;
double minDist = double.MaxValue;
foreach (Connector connector1 in pipe_connectorSet1)
{
foreach (Connector connector2 in pipe_connectorSet2)
{
double d = connector1.Origin.DistanceTo(connector2.Origin);
if (d < minDist)
{
pipe_connector1 = connector1;
pipe_connector2 = connector2;
minDist = d;
}
}
}
// 2-4) 2개의 파이프 연결시키기
try
{
FamilyInstance fitting = document.Create.NewElbowFitting(pipe_connector1, pipe_connector2);
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
}
// pipe와 겹치는 line 삭제하기
foreach (Element element in ElemLst)
{
if (element == null) continue;
ElementId elementId = element.Id;
document.Delete(elementId);
}
return pipes;
}
catch (Exception e)
{
}
return pipes;
}
//DividePipe가 null일 경우 다음 커넥터로 넘기는 코드
//public void ConnectHead2pipe2(List<ObjSprinKler> sprinKlers, List<Pipe> pipes)
//{
// //double DirectAng = FromBranchToHeadAngle(sprinKlers.First(), pipes.First());
// Pipe pipe = pipes.First();
// Pipe DividePipe = null;
// foreach (ObjSprinKler obj in sprinKlers)
// {
// DividePipe = CreatePipeT(obj, pipe);
// if (DividePipe != null)
// pipe = DividePipe;
// else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행
// {
// Line pipeline = (pipe.Location as LocationCurve).Curve as Line;
// //Pyosi(pipeline.GetEndPoint(1), 1);
// //MessageBox.Show("1");
// foreach (Connector con in Util.GetElementConnectors(pipe))
// {
// //끝점에서 다음 객체의 반대쪽 커넥터 구하기.
// if (con.Origin.IsAlmostEqualTo(pipeline.GetEndPoint(1), Unit.MMToFeet(0.01)))
// {
// Connector baseCon = con;
// while (true)
// {
// Connector NextCon = Util.GetNextElementConnector(baseCon);
// Connector NextOtherCon = Util.GetOtherConnector(NextCon);
// Connector Next2Con = Util.GetNextElementConnector(NextOtherCon);
//
// if (Next2Con.Owner is Pipe)
// {
// pipe = Next2Con.Owner as Pipe;
// DividePipe = CreatePipeT(obj, pipe);
// if (DividePipe != null)
// {
// pipe = DividePipe;
// break;
// }
// else
// baseCon = Next2Con;
// }
// else
// continue;
// }
// }
// }
// }
// }
//}
}
}