Client/Desktop/KMBIM3.0/23.10.16/Cmd/SprinklerConnect/SprinKler_Function.cs

1363 lines
63 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;
namespace KMBIM.Revit.Tools.Cmd.SprinklerConnect
{
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 XYZ SeparateionPt = null; // 하향식 - 이격거리 점
}
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)
{
//XYZ aHeadPtZ0 = new XYZ(a.m_Headpt.X, a.m_Headpt.Y, 0);
//XYZ aInterPtZ0 = new XYZ(a.m_InterPt.X, a.m_InterPt.Y, 0);
//XYZ bHeadPtZ0 = new XYZ(b.m_Headpt.X, b.m_Headpt.Y, 0);
//XYZ bInterPtZ0 = new XYZ(b.m_InterPt.X, b.m_InterPt.Y, 0);
//double diff = bHeadPtZ0.DistanceTo(aInterPtZ0) - aHeadPtZ0.DistanceTo(bInterPtZ0);
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;
}
}
class SprinKler_Function
{
//변수는 실행쪽에서 받아옴
public Document doc;
public Autodesk.Revit.Creation.Document creDoc;
public UIApplication uiapp;
public ElementId MainPipeTypeId = null;
public ElementId MainSystemTypeId = null;
public ElementId MainLevelId = null;
ObjComparer OC = new ObjComparer();
ObjOrthoComparer OrthoC = new ObjOrthoComparer();
/////////////////////////헤드 리스트 분할 함수////////////////////////////
// 1000mm범위의 헤드를 리스트에 담아 리턴
public List<ObjSprinKler> DivideObjSprinKlerData(Pipe mainPipe,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);
}
}
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;
ObjSprinKler obj_i = resLst[i];
ObjSprinKler 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;
}
//총 리스트에서 헤드가 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 == m_Lst.Count() - 1)//마지막 그룹이 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);
}
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);
}
}
}
}
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;
}
/////////////////////////헤드 포인트////////////////////////////
/// <summary>
/// 상향식 틀어진 가지관 등 점 구하기.
/// </summary>
/// <param name="objSpkr1"></param>첫번째 헤드
/// <param name="objSpkr2"></param>두번째 헤드
/// <param name="HeadOffset"></param>대화상자 헤드 간격띄우기
/// <param name="sp_in"></param>틀어진 헤드 작도점 1,2로 나뉘는 변수
/// <param name="DiaCnt"></param>헤드가 몇번째 관경을 적용하는지 나타내는 변수
/// <param name="headDiaLst"></param>헤드 관경 리스트
/// <returns></returns>
//z값 0으로 벡터 구해야 함 스프링클러 높이가 다르면 벡터가 대각선이 됨.
public List<XYZ> UpSPJOIN(ObjSprinKler objSpkr1, ObjSprinKler objSpkr2, double BranchHgt, ref int sp_in, int DiaCnt, List<double> headDiaLst)
{
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 = null, jpt2 = null;
siz15 = Unit.MMToFeet(300);
XYZ Z0Headpt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, 0);
XYZ Z0Headpt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, 0);
vec = (Z0Headpt1 - Z0Headpt2).Normalize();
double ang = Util.Angle2D(Z0Headpt1, Z0Headpt2);
//vec = (objSpkr1.m_Headpt - objSpkr2.m_Headpt).Normalize();
double vecAng = Util.RTD(vec.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ));
//헤드메인교차점-헤드 벡터
XYZ HMvec = null;
XYZ Z0InterPt = new XYZ(objSpkr1.m_InterPt.X, objSpkr1.m_InterPt.Y, 0);
HMvec = (Z0InterPt - Z0Headpt1).Normalize();
//HMvec = (objSpkr1.m_InterPt - objSpkr1.m_Headpt).Normalize();
//jpt1 = objSpkr1.m_Headpt;
//jpt2 = objSpkr2.m_Headpt;
jpt1 = Z0Headpt1;
jpt2 = Z0Headpt2;
ang1 = vecAng;
List<XYZ> linePtlst = new List<XYZ>();
//두개의 헤드가 틀어진 경우
if (!((Math.Abs(ang1 - 0.0) < 0.01) || (Math.Abs(ang1 - 360.0) < 0.01)) && !(Math.Abs(ang1 - 90.0) < 0.01) &&
!(Math.Abs(ang1 - 180.0) < 0.01) && !(Math.Abs(ang1 - 270.0) < 0.01))
{
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 = Util.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 = Util.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;
XYZ newpt110 = new XYZ(pt110.X, pt110.Y, Unit.MMToFeet(BranchHgt));
XYZ newpt2 = new XYZ(pt2.X, pt2.Y, Unit.MMToFeet(BranchHgt));
//틀어진 점 구할 때 거리가 헤드에 적용될 관경의 3배 거리보다 작을 경우 리턴
if (newpt110.DistanceTo(newpt2) < Unit.MMToFeet(headDiaLst.ElementAt(DiaCnt) * 2.0))
{
MessageBox.Show("배관 연결할 거리가 나오지 않습니다.");
linePtlst = null;
return linePtlst;
}
if (sp_in == 1)
{
linePtlst.Add(newpt110);
linePtlst.Add(newpt2);
}
else
{
linePtlst.Add(newpt2);
linePtlst.Add(newpt110);
}
}
//sp_hd++;
return linePtlst;
}
/// <summary>
/// 캡포인트 구하기.
/// </summary>
/// <param name="FirstObjSpkr"></param>메인관에서 가장 먼 헤드
/// <param name="HeadOffset"></param>대화상자 헤드 간격띄우기
/// <param name="CapDist"></param>대화상자 캡까지의 간격
/// <returns></returns>
public XYZ GetCAPpoint(ObjSprinKler FirstObjSpkr, double BranchHgt, 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, Unit.MMToFeet(BranchHgt));
return newCapPt;
}
/// <summary>
/// 메인 연결될 가지파이프
/// </summary>
/// <param name="LastObjSpkr"></param>메인관에 가장 가까운 헤드
/// <param name="HeadOffset"></param>대화상자 헤드 간격띄우기
/// <returns></returns>
public XYZ GetMain2LastpipePoint(ObjSprinKler LastObjSpkr, double BranchHgt)
{
//헤드간격 띄우기 값 적용
XYZ newInterPt = new XYZ(LastObjSpkr.m_InterPt.X, LastObjSpkr.m_InterPt.Y, Unit.MMToFeet(BranchHgt));
//XYZ newHeadPt = new XYZ(LastObjSpkr.m_Headpt.X, LastObjSpkr.m_Headpt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
return newInterPt;
}
/// <summary>
/// 하향식 틀어진 가지관 등 점 구하기.
/// </summary>
/// <param name="objSpkr1"></param>첫번째 헤드
/// <param name="objSpkr2"></param>두번째 헤드
/// <param name="HeadOffset"></param>대화상자 헤드 간격띄우기
/// <param name="sp_in"></param>틀어진 헤드 작도점 1,2로 나뉘는 변수
/// <param name="DiaCnt"></param>헤드가 몇번째 관경을 적용하는지 나타내는 변수
/// <param name="headDiaLst"></param>헤드 관경 리스트
/// <returns></returns>
public List<XYZ> DownSPJOIN(ObjSprinKler objSpkr1, ObjSprinKler objSpkr2, double BranchHeight, ref int sp_in, int DiaCnt, List<double> headDiaLst)
{
doc.Regenerate();
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 = null, jpt2 = null;
siz15 = Unit.MMToFeet(300);
XYZ Z0Headpt1 = new XYZ(objSpkr1.m_Headpt.X, objSpkr1.m_Headpt.Y, 0);
XYZ Z0Headpt2 = new XYZ(objSpkr2.m_Headpt.X, objSpkr2.m_Headpt.Y, 0);
vec = (Z0Headpt1 - Z0Headpt2).Normalize();
//vec = (objSpkr1.m_Headpt - objSpkr2.m_Headpt).Normalize();
double vecAng = Util.RTD(vec.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ));
//헤드메인교차점-헤드 벡터
XYZ HMvec = null;
XYZ Z0InterPt = new XYZ(objSpkr1.m_InterPt.X, objSpkr1.m_InterPt.Y, 0);
XYZ Z0SepaPt1 = new XYZ(objSpkr1.SeparateionPt.X, objSpkr1.SeparateionPt.Y, 0);
XYZ Z0SepaPt2 = new XYZ(objSpkr2.SeparateionPt.X, objSpkr2.SeparateionPt.Y, 0);
HMvec = (Z0InterPt - Z0SepaPt1).Normalize();
jpt1 = Z0SepaPt1;
jpt2 = Z0SepaPt2;
ang1 = vecAng;
List<XYZ> linePtlst = new List<XYZ>();
//두개의 헤드가 틀어진 경우
if (!((Math.Abs(ang1 - 0.0) < 0.001) || (Math.Abs(ang1 - 360.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 = Util.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 = Util.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;
//Util.Pyosi(doc, pt110);
//Util.Pyosi(doc, pt2);
XYZ newHeadPt1 = null, newHeadPt2 = null;
//헤드간격 띄우기 값 적용
newHeadPt1 = new XYZ(objSpkr1.SeparateionPt.X, objSpkr1.SeparateionPt.Y, Unit.MMToFeet(BranchHeight));
newHeadPt2 = new XYZ(objSpkr2.SeparateionPt.X, objSpkr2.SeparateionPt.Y, Unit.MMToFeet(BranchHeight));
XYZ newpt110 = new XYZ(pt110.X, pt110.Y, Unit.MMToFeet(BranchHeight));
XYZ newpt2 = new XYZ(pt2.X, pt2.Y, Unit.MMToFeet(BranchHeight));
//틀어진 점 구할 때 거리가 헤드에 적용될 관경의 3배 거리보다 작을 경우 리턴
if (newpt110.DistanceTo(newpt2) < Unit.MMToFeet(headDiaLst.ElementAt(DiaCnt) * 2.0))
{
MessageBox.Show("배관 연결할 거리가 나오지 않습니다.");
linePtlst = null;
return linePtlst;
}
if (sp_in == 1)
{
linePtlst.Add(newpt110);
linePtlst.Add(newpt2);
}
else
{
linePtlst.Add(newpt2);
linePtlst.Add(newpt110);
}
}
//sp_hd++;
return linePtlst;
}
/// <summary>
/// 하향식 캡포인트 구하기.
/// </summary>
/// <param name="FirstObjSpkr"></param>메인관에서 가장 먼 헤드
/// <param name="HeadOffset"></param>대화상자 헤드 간격띄우기
/// <param name="CapDist"></param>대화상자 캡까지의 간격
/// <returns></returns>
public XYZ DownGetCAPpoint(ObjSprinKler FirstObjSpkr, double BranchHeight, double CapDist)
{
//메인-헤드 방향 벡터
XYZ MHvec = (FirstObjSpkr.SeparateionPt - FirstObjSpkr.m_InterPt).Normalize();
//헤드-캡까지의 간격(사용자입력값)만큼 떨어진 점 구하기.
XYZ CapPt = Util.Polar(FirstObjSpkr.SeparateionPt, MHvec, Unit.MMToFeet(CapDist));
//헤드간격 띄우기 값 적용
XYZ newCapPt = new XYZ(CapPt.X, CapPt.Y, Unit.MMToFeet(BranchHeight));
return newCapPt;
}
/// <summary>
/// 하향식 메인 연결될 가지파이프
/// </summary>
/// <param name="LastObjSpkr"></param>메인관에 가장 가까운 헤드
/// <param name="HeadOffset"></param>대화상자 헤드 간격띄우기
/// <returns></returns>
public XYZ DownGetMain2LastpipePoint(ObjSprinKler LastObjSpkr, double BranchHeight)
{
//헤드간격 띄우기 값 적용
XYZ newInterPt = new XYZ(LastObjSpkr.m_InterPt.X, LastObjSpkr.m_InterPt.Y, Unit.MMToFeet(BranchHeight));
//XYZ newHeadPt = new XYZ(LastObjSpkr.m_Headpt.X, LastObjSpkr.m_Headpt.Y, LastObjSpkr.m_Headpt.Z - Unit.MMToFeet(HeadOffset));
return newInterPt;
}
/////////////////////////생성 함수////////////////////////////
/// <summary>
/// 가지관과 상향식 헤드 T연결
/// </summary>
/// <param name="objSprinKler"></param>헤드
/// <param name="BranchPipe"></param>가지관
/// <returns></returns>
public List<ElementId> 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;
XYZ HeadPtZ0 = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, 0);
XYZ interPtZ0 = new XYZ(interPt.X, interPt.Y, 0);
double H2InterDist = interPtZ0.DistanceTo(HeadPtZ0);
//헤드와 배관의 가까운점이 이격 거리보다 클 때 실행X
if (H2InterDist > Unit.MMToFeet(0.1)) return null;
List<ElementId> pipeIdLst = new List<ElementId>();
//헤드와 배관의 가까운점이 배관의 시작 또는 끝점일 경우 실행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;
//가지관 자르기
m_divideElemId = PlumbingUtils.BreakCurve(doc, BranchPipe.Id, interPt);
Pipe divideBranchPipe = doc.GetElement(m_divideElemId) as Pipe;
Pipe Headpipe = CreateHeadPipe(objSprinKler, interPt, BranchPipe);
pipeIdLst.Add(m_divideElemId);
pipeIdLst.Add(BranchPipe.Id);
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);
}
return pipeIdLst;
}
/// <summary>
/// 가지관과 하향식 헤드 T연결
/// </summary>
/// <param name="objSprinKler"></param>헤드
/// <param name="BranchPipe"></param>가지관
/// <param name="HeadOffsetDist"></param>헤드 간격띄우기
/// <param name="ConnectDist"></param>이격거리
/// <param name="Mode"></param>헤드와 연결될 배관 종류// 0 = 배관 / 1 = 플렉시블 배관
/// <returns></returns>
public List<ElementId> CreatePipeT(ObjSprinKler objSprinKler, Pipe BranchPipe, double HeadOffsetDist, double ConnectDist, double BranchHeight, int Mode)
{
Line pipeline = (BranchPipe.Location as LocationCurve).Curve as Line;
IntersectionResult intersection = pipeline.Project(objSprinKler.m_Headpt);
XYZ interPt = intersection.XYZPoint;
XYZ ZHeadPt = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, interPt.Z);
XYZ HeadPtZ0 = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, 0);
XYZ interPtZ0 = new XYZ(interPt.X, interPt.Y, 0);
double H2InterDist = interPtZ0.DistanceTo(HeadPtZ0);
double dd = Unit.FeetToMM(interPtZ0.DistanceTo(HeadPtZ0));
//MessageBox.Show("" + Unit.FeetToMM(interPt.DistanceTo(ZHeadPt)));
//헤드와 배관의 가까운점이 이격 거리보다 클 때 실행X
if (Math.Abs(Unit.MMToFeet(ConnectDist) - H2InterDist) > Unit.MMToFeet(10)) return null;
//헤드와 배관의 가까운점이 배관의 시작 또는 끝점일 경우 실행X
//if (interPt.IsAlmostEqualTo(pipeline.GetEndPoint(0), Unit.MMToFeet(0.01))
// || interPt.IsAlmostEqualTo(pipeline.GetEndPoint(1), Unit.MMToFeet(0.01))) return null;
List<ElementId> pipeIdLst = new List<ElementId>();
ElementId m_divideElemId = null;
//가지관 자르기
m_divideElemId = PlumbingUtils.BreakCurve(doc, BranchPipe.Id, interPt);
Pipe divideBranchPipe = doc.GetElement(m_divideElemId) as Pipe;
//헤드의 z값을 이격거리된 점으로 변경
XYZ NewHeadPt = new XYZ(objSprinKler.m_Headpt.X, objSprinKler.m_Headpt.Y, Unit.MMToFeet(BranchHeight + HeadOffsetDist));
XYZ NewInterPt = new XYZ(interPt.X, interPt.Y, Unit.MMToFeet(BranchHeight + HeadOffsetDist));
//분기 배관에 T작도할 파이프 생성 및 헤드에 파이프 연결 루틴
Pipe Headpipe = CreateHeadConnectPipe(objSprinKler, interPt, NewHeadPt, NewInterPt, Mode);
//Pipe Headpipe = CreateHeadPipe(objSprinKler, interPt, BranchPipe);
pipeIdLst.Add(m_divideElemId);
pipeIdLst.Add(BranchPipe.Id);
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);
}
return pipeIdLst;
}
/// <summary>
/// T연결에 필요한 분기배관 생성
/// </summary>
/// <param name="objSpkr"></param>헤드
/// <param name="breakPt"></param>T연결할 포인트와 헤드점으로 파이프생성
/// <param name="BranchPipe"></param>가지배관의 타입을 가져오기위해
/// <param name="MainSystemTypeId"></param>//메인관 시스템타입
/// <param name="MainLevelId"></param>//메인관 레벨
/// <returns></returns>
public Pipe CreateHeadPipe(ObjSprinKler objSpkr, XYZ breakPt, Pipe BranchPipe)
{
//Level level = doc.ActiveView.GenLevel;
Pipe headPipe = Pipe.Create(doc, MainSystemTypeId, BranchPipe.GetTypeId(), MainLevelId, 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;
}
/// <summary>
/// 하향식 T연결에 필요한 분기배관 생성 및 헤드에 연결
/// </summary>
/// <param name="objSpkr"></param>헤드
/// <param name="breakPt"></param>T연결할 포인트와 헤드점으로 파이프생성
/// <param name="NewInterPt"></param>//이격 거리 파이프 시작점
/// <param name="NewHeadpt"></param>//이격 거리 파이프 끝점
/// <param name="Mode"></param>헤드와 연결될 배관 종류// 0 = 배관 / 1 = 플렉시블 배관
/// <returns></returns>
public Pipe CreateHeadConnectPipe(ObjSprinKler objSpkr, XYZ breakPt, XYZ NewHeadPt, XYZ NewInterPt, int Mode)
{
//D1 파이프 생성
List<XYZ> D2Lst = new List<XYZ>();
D2Lst.Add(breakPt); D2Lst.Add(NewInterPt);
List<Pipe> D1Pipe = Util.CreatePipe(uiapp, doc, D2Lst, MainSystemTypeId, MainPipeTypeId, MainLevelId);
//D2 파이프 생성
D2Lst.Clear();
D2Lst.Add(NewInterPt); D2Lst.Add(NewHeadPt);
List<Pipe> D2Pipe = Util.CreatePipe(uiapp, doc, D2Lst, MainSystemTypeId, MainPipeTypeId, MainLevelId);
//헤드 커넥터 파이프 생성
D2Lst.Clear();
D2Lst.Add(NewHeadPt); D2Lst.Add(objSpkr.m_Headpt);
List<XYZ> FPLst = new List<XYZ>();
FPLst.Add(objSpkr.m_Headpt);
List<Pipe> HPipe = Util.CreatePipe(uiapp, doc, D2Lst, MainSystemTypeId, MainPipeTypeId, MainLevelId);
//엘보 피팅
Connector Con1Sp = null, Con1Ep = null, Con2Sp = null, Con2Ep = null;
Util.GetStartEndConnector(D1Pipe.First(), ref Con1Sp, ref Con1Ep);
Util.GetStartEndConnector(D2Pipe.First(), ref Con2Sp, ref Con2Ep);
Util.ElbowFitting(doc, Con1Ep, Con2Sp);
Util.GetStartEndConnector(D2Pipe.First(), ref Con1Sp, ref Con1Ep);
Util.GetStartEndConnector(HPipe.First(), ref Con2Sp, ref Con2Ep);
FamilyInstance ElbowFam = Util.ElbowFitting(doc, Con1Ep, Con2Sp);
//Util.Pyosi(doc, Con2Sp.Origin, 0);
//헤드와 파이프 연결
if (Con2Ep.IsConnected == false)
{
Con2Ep.Radius = Unit.MMToFeet(25 / 2.0);
//reducerFam = doc.Create.NewTransitionFitting(Con2Ep, objSpkr.HeadCon);
Con2Ep.ConnectTo(objSpkr.HeadCon);
}
//플렉시블 배관이 선택된 경우 배관을 지우고 새로 만듬.
if (Mode == 1)
{
doc.Delete(HPipe.First().Id);
doc.Regenerate();
List<Connector> elbowConLst = Util.GetElementConnectors(ElbowFam);
foreach (Connector con in elbowConLst)
{
//플렉시블과 연결할 커넥터 찾기.
if (con.IsConnected == false)
{
FPLst.Add(con.Origin);
}
}
//플렉시블 작도
List<FlexPipe> FlexPipe = Util.CreateFlexPipe(uiapp, doc, FPLst, MainSystemTypeId, MainPipeTypeId, MainLevelId);
Util.GetStartEndConnector(FlexPipe.First(), ref Con2Sp, ref Con2Ep);
FlexPipe.First().StartTangent = objSpkr.HeadCon.CoordinateSystem.BasisZ;
objSpkr.HeadCon.ConnectTo(Con2Sp);
foreach (Connector con in elbowConLst)
{
//플렉시블과 연결할 커넥터 찾기.
if (con.Origin.IsAlmostEqualTo(Con2Ep.Origin, Unit.MMToFeet(0.01)))
{
FlexPipe.First().EndTangent = con.CoordinateSystem.BasisZ.Negate();
con.ConnectTo(Con2Ep);
}
}
}
return D1Pipe.First();
}
/// <summary>
/// 캡 생성
/// </summary>
/// <param name="baseCon"></param>캡 배치할 커넥터
public void CreateCap(Connector baseCon, ElementId mainPipeTypeId)
{
PipeType pipeType = doc.GetElement(mainPipeTypeId) as PipeType;
if (pipeType != null)
{
//파이프의 라우팅된 패밀리 심볼 구하기
FamilySymbol capSymbol = Util.GetSymbol_RoutingPreference(doc, pipeType, RoutingPreferenceRuleGroupType.Caps);
if (capSymbol != null)
{
//캡 생성
FamilyInstance fi = doc.Create.NewFamilyInstance(baseCon.Origin, capSymbol, StructuralType.NonStructural);
doc.Regenerate();
//가지관에 맞게 캡 돌려서 커넥터 연결하기
Util.MatchingRotateElement(doc, baseCon.Owner, fi);
List<Connector> CapconLst = Util.GetElementConnectors(fi);
CapconLst.First().Radius = baseCon.Radius;
}
}
}
/// <summary>
/// 가지관 끝에서 메인관으로 수직인 파이프 작도
/// </summary>
/// <param name="MainElement"></param>메인 배관
/// <param name="EpConnector"></param>가지관 끝에서 메인관으로 수직인 커넥터
/// <returns></returns>
public Pipe CreatePipeFromNearPt(Element MainElement, Connector EpConnector)
{
Line pipeline = (MainElement.Location as LocationCurve).Curve as Line;
XYZ interPt = Util.GetPointOnLine(pipeline, EpConnector.Origin);
//파이프 작도할 점
List<XYZ> DrawPtLst = new List<XYZ>();
DrawPtLst.Add(EpConnector.Origin); DrawPtLst.Add(interPt);
//파이프 생성
List<Pipe> NewPipe = Util.CreatePipe(uiapp, doc, DrawPtLst, MainSystemTypeId, MainPipeTypeId, MainLevelId);
List<Connector> newConnectors = Util.GetElementConnectors(NewPipe.First());
return NewPipe.First();
}
/// <summary>
/// T와 레듀셔 사이에 파이프 생성
/// </summary>
/// <param name="familyTee"></param> Tee 패밀리 인스턴스
/// <param name="Interval"></param> T와 레듀셔 사이에 생성할 파이프 길이
public void CreatePipeBetweenTeeAndReducer(FamilyInstance familyTee, double Interval)
{
List<Connector> TeeConLst = Util.GetElementConnectors(familyTee);
foreach (Connector TeeCon in TeeConLst)
{
//Tee 커넥터에 붙어있는 객체
Connector NextCon = Util.GetNextElementConnector(TeeCon);
if (NextCon == null) continue;
bool b_Reducer = Util.GetFamilyPartType(NextCon, PartType.Transition);
//Tee 커넥터에 붙어있는 객체가 레듀셔 일 때만 작업
if (b_Reducer)
{
Connector NextOtherCon = Util.GetOtherConnector(NextCon);
Connector PipeCon = Util.GetNextElementConnector(NextOtherCon);
//레듀셔 연결 끊고 레듀셔 삭제
TeeCon.DisconnectFrom(NextCon);
doc.Delete(NextCon.Owner.Id);
//파이프 생성하기 위해 위치 조정
PipeCon.Origin = Util.Polar(PipeCon.Origin, TeeCon.Origin, PipeCon.Origin, Unit.MMToFeet(Interval));
//Tee에 새로운 파이프 생성
XYZ ReducerPt = Util.Polar(TeeCon.Origin, TeeCon.Origin, PipeCon.Origin, Unit.MMToFeet(Interval));
List<XYZ> ReducerPtLst = new List<XYZ>();
ReducerPtLst.Add(TeeCon.Origin); ReducerPtLst.Add(ReducerPt);
List<Pipe> NewPipeLst = Util.CreatePipe(uiapp, doc, ReducerPtLst, MainSystemTypeId, MainPipeTypeId, MainLevelId);
List<Connector> newPipeCons = Util.GetElementConnectors(NewPipeLst.First());
//Tee 관경으로 변경
newPipeCons.First().Radius = TeeCon.Radius;
//새 파이프와 이동한 파이프 레듀셔로 연결
foreach (Connector NewCon in newPipeCons)
{
if (NewCon.Origin.IsAlmostEqualTo(ReducerPt, Unit.MMToFeet(0.01)))
creDoc.NewTransitionFitting(NewCon, PipeCon);
else if (NewCon.Origin.IsAlmostEqualTo(TeeCon.Origin, Unit.MMToFeet(0.01)))
TeeCon.ConnectTo(NewCon);
//Tee와 새 파이프 커넥터가 연결되어 있지 않아 수정.//20200208
}
}
}
}
/////////////////////////연결 루틴////////////////////////////
/// <summary>
/// 상향식 헤드와 파이프 연결
/// </summary>
/// <param name="sprinKlers"></param>헤드 리스트
/// <param name="pipes"></param>헤드와 연결될 파이프리스트
/// <param name="HeadDiaLst"></param>헤드 관경리스트
/// <returns></returns>
public List<ElementId> ConnectHead2pipe(List<ObjSprinKler> sprinKlers, List<Pipe> pipes, List<double> HeadDiaLst, double ReducerDist)
{
Pipe pipe = pipes.First();
List<ElementId> PipeIdLst = new List<ElementId>();
for (int i = 0; i < sprinKlers.Count(); i++)
{
List<ElementId> DividePipeIDLst = new List<ElementId>();
ObjSprinKler obj = sprinKlers.ElementAt(i);
DividePipeIDLst = CreatePipeT(obj, pipe);
if (DividePipeIDLst != null)
{
foreach (ElementId id in DividePipeIDLst)
{
if (PipeIdLst.Contains(id) == false)
PipeIdLst.Add(id);
}
pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프
}
else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행
{
foreach (Pipe pp in pipes)
{
DividePipeIDLst = CreatePipeT(obj, pp);
if (DividePipeIDLst != null)
{
foreach (ElementId id in DividePipeIDLst)
{
if (PipeIdLst.Contains(id) == false)
PipeIdLst.Add(id);
}
pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프
break;
}
else
{
if (PipeIdLst.Contains(pp.Id) == false)
PipeIdLst.Add(pp.Id);
}
}
}
}
Pipe DivideFirstPipe = doc.GetElement(PipeIdLst.First()) as Pipe;
Connector FirstSpCon = null, FirstEpCon = null;
Util.GetStartEndConnector(DivideFirstPipe, ref FirstSpCon, ref FirstEpCon);
//객체 따로 리스트 저장
List<ElementId> ElemLst = getFamilyAndPipe(DivideFirstPipe);
//ApplyDiameter(ElemLst, HeadDiaLst);
ApplyDiameterAndReducer(FirstEpCon, HeadDiaLst, ReducerDist);
doc.Regenerate();
ApplyReducer(ElemLst, 100);
//ApplyTeeDiameter(ElemLst, HeadDiaLst);
//첫번째 파이프 시작점에 캡부착
if (doc.GetElement(ElemLst.First()) is Pipe)
{
Connector SpCon = null, epCon = null;
Util.GetStartEndConnector((doc.GetElement(ElemLst.First()) as Pipe), ref SpCon, ref epCon);
//캡 생성
CreateCap(SpCon, MainPipeTypeId);
}
return ElemLst;//객체 리스트 넘겨주기(메인관 기준 왼쪽 오른쪽 끝을 이어주기 위해)
}
/// <summary>
/// 하향식 헤드와 파이프 연결
/// </summary>
/// <param name="sprinKlers"></param>헤드 리스트
/// <param name="pipes"></param>헤드와 연결될 파이프리스트
/// <param name="HeadDiaLst"></param>헤드 관경리스트
/// <param name="Mode"></param>헤드와 연결될 배관 종류// 0 = 배관 / 1 = 플렉시블 배관
/// <returns></returns>
public List<ElementId> DownConnectHead2pipe(List<ObjSprinKler> sprinKlers, List<Pipe> pipes, List<double> HeadDiaLst, double HeadOffsetDist, double ConnectDist, double BranchHeight, double ReducerDist, int Mode)
{
Pipe pipe = pipes.First();
List<ElementId> PipeIdLst = new List<ElementId>();
for (int i = 0; i < sprinKlers.Count(); i++)
{
List<ElementId> DividePipeIDLst = new List<ElementId>();
ObjSprinKler obj = sprinKlers.ElementAt(i);
DividePipeIDLst = CreatePipeT(obj, pipe, HeadOffsetDist, ConnectDist, BranchHeight, Mode);
if (DividePipeIDLst != null)
{
foreach (ElementId id in DividePipeIDLst)
{
if (PipeIdLst.Contains(id) == false)
PipeIdLst.Add(id);
}
pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프
}
else//다음 파이프가 넘어오지 않으면 다음 파이프에서 실행
{
foreach (Pipe pp in pipes)
{
DividePipeIDLst = CreatePipeT(obj, pp, HeadOffsetDist, ConnectDist, BranchHeight, Mode);
if (DividePipeIDLst != null)
{
foreach (ElementId id in DividePipeIDLst)
{
if (PipeIdLst.Contains(id) == false)
PipeIdLst.Add(id);
}
pipe = doc.GetElement(DividePipeIDLst[1]) as Pipe;//리스트 두번째가 나뉜 파이프
break;
}
else
{
if (PipeIdLst.Contains(pp.Id) == false)
PipeIdLst.Add(pp.Id);
}
}
}
}
Pipe DivideFirstPipe = doc.GetElement(PipeIdLst.First()) as Pipe;
Connector FirstSpCon = null, FirstEpCon = null;
Util.GetStartEndConnector(DivideFirstPipe, ref FirstSpCon, ref FirstEpCon);
//객체 따로 리스트 저장
List<ElementId> ElemLst = getFamilyAndPipe(DivideFirstPipe);
//ApplyDiameter(ElemLst, HeadDiaLst);
ApplyDiameterAndReducer(FirstEpCon, HeadDiaLst,ReducerDist);
doc.Regenerate();
//ApplyReducer(ElemLst, 100);
//첫번째 파이프 시작점에 캡부착
if (doc.GetElement(ElemLst.First()) is Pipe)
{
Connector SpCon = null, epCon = null;
Util.GetStartEndConnector((doc.GetElement(ElemLst.First()) as Pipe), ref SpCon, ref epCon);
//캡 생성
CreateCap(SpCon, MainPipeTypeId);
}
return ElemLst;//객체 리스트 넘겨주기(메인관 기준 왼쪽 오른쪽 끝을 이어주기 위해)
}
//메인관 가지관 연결
public List<Pipe> MainConnectBranch(Element MainElem, Element LeftElem, Element RightElem)
{
Line MainLine = ((MainElem as Pipe).Location as LocationCurve).Curve as Line;
List<Pipe> TeeBranchPipeLst = new List<Pipe>();
try
{
//한쪽만 존재할 때
if (LeftElem == null || RightElem == null)
{
Connector SpCon = null, EpCon = null;
Pipe BranchPipe = null;
if (LeftElem != null)
{
Util.GetStartEndConnector(LeftElem as Pipe, ref SpCon, ref EpCon);
BranchPipe = LeftElem as Pipe;
}
else if (RightElem != null)
{
Util.GetStartEndConnector(RightElem as Pipe, ref SpCon, ref EpCon);
BranchPipe = RightElem as Pipe;
}
Pipe NewPipe = CreatePipeFromNearPt(MainElem, EpCon);
//파이프 엘보 관경 맞추고 연결
Connector NewSpCon = null, NewEpCon = null;
Util.GetStartEndConnector(NewPipe, ref NewSpCon, ref NewEpCon);
NewSpCon.Radius = EpCon.Radius;
Util.ElbowFitting(doc, EpCon, NewSpCon);
TeeBranchPipeLst.Add(NewPipe);
}
//양쪽 존재할 때
else if (LeftElem != null && RightElem != null)
{
Connector LeftSpCon = null, LeftEpCon = null;
Connector RightSpCon = null, RightEpCon = null;
Util.GetStartEndConnector(LeftElem as Pipe, ref LeftSpCon, ref LeftEpCon);
Util.GetStartEndConnector(RightElem as Pipe, ref RightSpCon, ref RightEpCon);
//가지관 끝에서 메인관까지 가까운점 구하기
Line pipeline = (MainElem.Location as LocationCurve).Curve as Line;
XYZ interPt = Util.GetPointOnLine(pipeline, LeftEpCon.Origin);
//양쪽 가지관의 끝 커넥터가 메인관과 수직점이 같을 경우
XYZ LeftInterPt = Util.GetPointOnLine(pipeline, LeftEpCon.Origin);
XYZ RightInterPt = Util.GetPointOnLine(pipeline, RightEpCon.Origin);
if (LeftInterPt.IsAlmostEqualTo(RightInterPt, Unit.MMToFeet(0.01)))
{
Connector NewSpCon = null, NewEpCon = null;
Pipe leftNewPipe = CreatePipeFromNearPt(MainElem, LeftEpCon);
Util.GetStartEndConnector(leftNewPipe, ref NewSpCon, ref NewEpCon);
//생성된 파이프 관경 = 양쪽 중 큰 관경으로
if (LeftEpCon.Radius > RightEpCon.Radius)
NewEpCon.Radius = LeftEpCon.Radius;
else
NewEpCon.Radius = RightEpCon.Radius;
FamilyInstance familyTee = null;
familyTee = Util.CreateTee(creDoc, LeftEpCon, RightEpCon, NewSpCon);
//왼쪽 오른쪽 관경이 다르면 레듀셔와 Tee 사이 간격 띄우기
if (!(Math.Abs(LeftEpCon.Radius - RightEpCon.Radius) < Unit.MMToFeet(0.01)))
{
CreatePipeBetweenTeeAndReducer(familyTee, 100);
}
TeeBranchPipeLst.Add(leftNewPipe);
}
else//Tee가 생성되지 않았을 때(끝 점이 틀어져 있을 때 따로 엘보 작도)
{
//틀어진 거리가 관경보다 작을 때 작도 X
if (LeftEpCon.Radius > RightEpCon.Radius)
{
if (LeftInterPt.DistanceTo(RightInterPt) < LeftEpCon.Radius * 4)
{
MessageBox.Show("메인관에 Tee를 연결할 거리가 나오지 않습니다.", "오류");
return TeeBranchPipeLst;
}
}
else
{
if (LeftInterPt.DistanceTo(RightInterPt) < RightEpCon.Radius * 4)
{
MessageBox.Show("메인관에 Tee를 연결할 거리가 나오지 않습니다.", "오류");
return TeeBranchPipeLst;
}
}
Connector leftNewspCon = null, leftNewepCon = null, rightNewspCon = null, rightNewepCon = null;
ElementId MainElemID = MainElem.Id;
//왼쪽 파이프 엘보 관경 맞추고 연결
Pipe leftNewPipe = CreatePipeFromNearPt(MainElem, LeftEpCon);
Util.GetStartEndConnector(leftNewPipe, ref leftNewspCon, ref leftNewepCon);
leftNewspCon.Radius = LeftEpCon.Radius;
Util.ElbowFitting(doc, LeftEpCon, leftNewspCon);
//오른쪽 파이프 엘보 관경 맞추고 연결
Pipe rightNewPipe = CreatePipeFromNearPt(MainElem, RightEpCon);
Util.GetStartEndConnector(rightNewPipe, ref rightNewspCon, ref rightNewepCon);
rightNewspCon.Radius = RightEpCon.Radius;
Util.ElbowFitting(doc, RightEpCon, rightNewspCon);
if (leftNewepCon.Origin.DistanceTo(MainLine.GetEndPoint(1)) < rightNewepCon.Origin.DistanceTo(MainLine.GetEndPoint(1)))
{
TeeBranchPipeLst.Add(leftNewPipe);
TeeBranchPipeLst.Add(rightNewPipe);
}
else
{
TeeBranchPipeLst.Add(rightNewPipe);
TeeBranchPipeLst.Add(leftNewPipe);
}
}
}
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
////나뉜 메인관 리턴해줘야 함.
return TeeBranchPipeLst;
}
//시작객체부터 객체 없을 때까지 리스트에 담기.
public List<ElementId> getFamilyAndPipe(Pipe FirstPipe)
{
Connector pipeSpCon = null, pipeEpCon = null;
//시작 끝 커넥터 구하기
Util.GetStartEndConnector(FirstPipe, ref pipeSpCon, ref pipeEpCon);
List<ElementId> elemIdLst = new List<ElementId>();
XYZ flowVec = (pipeEpCon.Origin - pipeSpCon.Origin).Normalize();
XYZ ReVec = (pipeSpCon.Origin - pipeEpCon.Origin).Normalize();
Connector CurCon = pipeEpCon;
elemIdLst.Add(CurCon.Owner.Id);
while (true)
{
Connector NextCon = Util.GetNextElementConnector(CurCon);
if (NextCon == null) break;
//Pyosi(NextCon.Origin, 1);
Connector NextOtherCon = null;
if (Util.GetFamilyPartType(NextCon, PartType.Tee))
NextOtherCon = Util.GetClosestConnector(NextCon, flowVec, ReVec);//커넥터 3개이상일 때 반대쪽 커넥터 찾기
else
NextOtherCon = Util.GetOtherConnector(NextCon);//커넥터 2개일 때 반대쪽 커넥터찾기
CurCon = NextOtherCon;
elemIdLst.Add(CurCon.Owner.Id);
}//while end
return elemIdLst;
}
/// <summary>
/// 첫번째 파이프 끝 커넥터부터 관경 및 레듀셔 적용하기
/// </summary>
/// <param name="FirstEpCon"></param>첫번쨰 파이프 끝 커넥터
/// <param name="HeadDiaLst"></param>
public void ApplyDiameterAndReducer(Connector FirstEpCon,List<double> HeadDiaLst, double m_TReducerDist)
{
if (FirstEpCon == null) return;
Connector stdCon = FirstEpCon, stdSpCon = null, stdEpCon = null;
Util.GetStartEndConnector(stdCon.Owner as Pipe, ref stdSpCon, ref stdEpCon);
List<double> DiaLst = HeadDiaLst;
int DiaCnt = 0;
while (true)
{
double CurDia = DiaLst.ElementAt(DiaCnt);
double NextDia = DiaLst.ElementAt(DiaCnt + 1);
//다음 커넥터
Connector NextCon = Util.GetNextElementConnector(stdCon);
if (NextCon == null) break;
Connector OtherCon = null;
//붙어있는 커넥터가 파이프일 떄
if(NextCon.Owner is Pipe)
{
//파이프 관경 관경리스트 값으로 변경
NextCon.Radius = Unit.MMToFeet(CurDia / 2.0);
//파이프 반대쪽 커넥터
OtherCon = Util.GetOtherConnector(NextCon);
}
else if(NextCon.Owner is FamilyInstance)
{
if(Util.GetFamilyPartType(NextCon, PartType.Elbow))//Elbow일 때
{
//파이프 관경 관경리스트 값으로 변경
NextCon.Radius = Unit.MMToFeet(CurDia / 2.0);
//파이프 반대쪽 커넥터
OtherCon = Util.GetOtherConnector(NextCon);
}
else if(Util.GetFamilyPartType(NextCon,PartType.Tee))//Tee일 때
{
//Tee일 때 관경리스트 값 +1
DiaCnt++;
CurDia = DiaLst.ElementAt(DiaCnt);
NextDia = DiaLst.ElementAt(DiaCnt + 1);
//기준 커넥터의 방향인 반대쪽 커넥터 구하기
OtherCon = Util.GetDirectionConnector(NextCon.Owner as FamilyInstance, NextCon);
//if(DiaCnt == 1)continue;
//Tee 관경 관경리스트 값으로 변경
NextCon.Radius = Unit.MMToFeet(CurDia / 2.0);
//Tee 파이프 커넥터 연결 끊기
stdCon.DisconnectFrom(NextCon);
doc.Regenerate();
if (stdCon.Radius == NextCon.Radius)
{
stdCon.ConnectTo(NextCon);
}
else
{
//파이프 커넥터에서 레듀셔 길이+50mm 만큼 이동
XYZ vec = (NextCon.Origin - OtherCon.Origin).Normalize();
XYZ ReVec = (OtherCon.Origin - NextCon.Origin).Normalize();
XYZ newPipePt = Util.Polar(NextCon.Origin, vec, Unit.MMToFeet(m_TReducerDist));
XYZ ReducerPt = Util.Polar(newPipePt, vec, Unit.MMToFeet(20));
//연결 끊은 파이프 커넥터 점 이동
stdCon.Origin = ReducerPt;
doc.Regenerate();
//Tee 옆 파이프 생성
Pipe newPipe = Util.CreatePipe2(uiapp, doc, newPipePt, NextCon.Origin, Unit.MMToFeet(CurDia), MainSystemTypeId, MainPipeTypeId, MainLevelId);
Connector newSpCon = null, newEpCon = null;
//새로 생성한 파이프 시작 끝 커넥터
Util.GetStartEndConnector(newPipe, ref newSpCon, ref newEpCon);
//Tee 새 파이프 연결
NextCon.ConnectTo(newEpCon);
doc.Regenerate();
double dist = Unit.FeetToMM(newSpCon.Origin.DistanceTo(newEpCon.Origin));
//새 파이프 T와 끊은 이전 파이프 연결
doc.Create.NewTransitionFitting(stdCon, newSpCon);
doc.Regenerate();
}
}
}
//기준 커넥터 변경
stdCon = OtherCon;
}//while end
}
//관경 적용
public void ApplyDiameter(List<ElementId> ElementIdLst, List<double> HeadDiaLst)
{
List<double> DiaLst = HeadDiaLst;
int DiaCnt = 0;
for (int i = 0; i < ElementIdLst.Count(); i++)
{
double CurDia = DiaLst.ElementAt(DiaCnt);
double NextDia = DiaLst.ElementAt(DiaCnt + 1);
List<Connector> Connectors = Util.GetElementConnectors(doc.GetElement(ElementIdLst[i]));
Connectors.First().Radius = Unit.MMToFeet(CurDia / 2.0);
if (Util.GetFamilyPartType(Connectors.First(), PartType.Tee))
{
DiaCnt++;
Connectors.First().Radius = Unit.MMToFeet(NextDia / 2.0);
}
}
}
//레듀셔 적용
public void ApplyReducer(List<ElementId> ElementIdLst, double T2ReducerDist)
{
Pipe firstPipe = doc.GetElement(ElementIdLst.First()) as Pipe;
XYZ sp = null, ep = null;
Util.GetStartEndPoint(firstPipe, ref sp, ref ep);
List<ElementId> TeeLst = new List<ElementId>();
//Tee만 추출
for (int i = 0; i < ElementIdLst.Count(); i++)
{
Element elem = doc.GetElement(ElementIdLst.ElementAt(i));
List<Connector> Connectors = Util.GetElementConnectors(elem);
if (elem is FamilyInstance && Util.GetFamilyPartType(Connectors.First(), PartType.Tee))
TeeLst.Add(ElementIdLst.ElementAt(i));
}
//레듀셔가 붙은 커넥터만 찾아 작업
foreach (ElementId id in TeeLst)
{
Element elem = doc.GetElement(id);
List<Connector> TeeConLst = Util.GetElementConnectors(elem);
Connector ReducerCon = null;
foreach(Connector con in TeeConLst)
{
Connector nextcon = Util.GetNextElementConnector(con);
if (nextcon != null)
{
Connector otherCon = Util.GetOtherConnector(nextcon);
//Util.Pyosi(doc, otherCon.Origin, 0);
}
}
// foreach (Connector TeeCon in TeeConLst)
// {
// Connector NextCon = Util.GetNextElementConnector(TeeCon);
// double ddd = Unit.FeetToMM(TeeCon.Radius);
// //레듀셔가 붙은 커넥터 찾기
// if (NextCon != null && Util.GetFamilyPartType(NextCon, PartType.Transition))
// {
// //레듀셔 커넥터의 관경이 작은쪽만 찾기(큰쪽은 Tee 가지커넥터를 찾을 수도 있어서)
// List<Connector> ReducerConLst = Util.GetElementConnectors(NextCon.Owner);
// if (NextCon.Origin.IsAlmostEqualTo(ReducerConLst[0].Origin, Unit.MMToFeet(0.01)))
// {
// if (NextCon.Radius > ReducerConLst[1].Radius)
// continue;
// else
// ReducerCon = NextCon;
// }
// else if (NextCon.Origin.IsAlmostEqualTo(ReducerConLst[1].Origin, Unit.MMToFeet(0.01)))
// {
// if (NextCon.Radius > ReducerConLst[0].Radius)
// continue;
// else
// ReducerCon = NextCon;
// }
//
// if (ReducerCon != null)
// {
// Connector RedOtherCon = Util.GetOtherConnector(ReducerCon);
// //레듀셔에 붙은 파이프 커넥터 구하기.
// Connector PipeCon = Util.GetNextElementConnector(RedOtherCon);
//
// //레듀셔 다시 연결하기때문에 지움
// doc.Delete(ReducerCon.Owner.Id);
// doc.Regenerate();
// //파이프 위치 이동
// PipeCon.Origin = Util.Polar(PipeCon.Origin, sp, ep, Unit.MMToFeet(T2ReducerDist));
//
// //Tee에 파이프 새로 생성
// XYZ ReducerPt = Util.Polar(TeeCon.Origin, sp, ep, Unit.MMToFeet(T2ReducerDist));
// List<XYZ> ReducerPtLst = new List<XYZ>();
// ReducerPtLst.Add(TeeCon.Origin); ReducerPtLst.Add(ReducerPt);
// List<Pipe> newPipeLst = Util.CreatePipe(uiapp, doc, ReducerPtLst, MainSystemTypeId, MainSystemTypeId, MainLevelId);
// List<Connector> newPipeCons = Util.GetElementConnectors(newPipeLst[0]);
// newPipeCons.First().Radius = TeeCon.Radius;
// //새 파이프와 이동한 파이프 레듀셔로 연결
// foreach (Connector con in newPipeCons)
// {
// if (con.Origin.IsAlmostEqualTo(ReducerPt, Unit.MMToFeet(0.01)))
// {
// creDoc.NewTransitionFitting(con, PipeCon);
// }
// }
// }
// }
// }//Tee에 붙은 레듀셔 커넥터 구하기 end
}
}
}
}