778 lines
38 KiB
C#
778 lines
38 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_Downward_Manual : 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_HeadOffset = 0, m_ConnectDist, m_CapDist = 0, m_Tol = 0, m_TReducerDist = 0;
|
|
int m_Mode = 0;
|
|
Connector mainSpCon = null, mainEpCon = null;
|
|
XYZ MainVec = null;
|
|
//이격 방향
|
|
XYZ SeparationVec = null;
|
|
List<ObjSprinKler> lst_objSprinkler = new List<ObjSprinKler>();
|
|
ObjSprinKler FirstObj = new ObjSprinKler();
|
|
SprinKler_Function Spkr_Func = new SprinKler_Function();
|
|
List<ElementId> RemoveElemIdLst = new List<ElementId>();
|
|
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;
|
|
|
|
try
|
|
{
|
|
//메인 파이프
|
|
Reference pickMainRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new SelectionMainPipe(), "기준 교차배관 선택 : ");
|
|
if (pickMainRef == null) return Result.Succeeded;
|
|
|
|
Element MainElem = doc.GetElement(pickMainRef.ElementId) as Element;
|
|
Pipe mainPipe = MainElem as Pipe;
|
|
Line mainLine = (mainPipe.Location as LocationCurve).Curve as Line;
|
|
|
|
XYZ DirectVec = null, ReverseVec = null;
|
|
DirectVec = (mainLine.GetEndPoint(1) - mainLine.GetEndPoint(0)).Normalize();
|
|
ReverseVec = (mainLine.GetEndPoint(0) - mainLine.GetEndPoint(1)).Normalize();
|
|
|
|
XYZ SpExtension = Util.Polar(mainLine.GetEndPoint(0), ReverseVec, 1000);
|
|
XYZ EpExtension = Util.Polar(mainLine.GetEndPoint(1), DirectVec, 1000);
|
|
Line NewMainLine = Line.CreateBound(SpExtension, EpExtension);
|
|
|
|
Util.GetStartEndConnector(mainPipe, ref mainSpCon, ref mainEpCon);//메인 시작 끝 커넥터
|
|
//m_MainHgt = NewMainLine.GetEndPoint(0).Z;//메인 높이
|
|
m_MainHgt = mainPipe.LevelOffset;//메인 파이프 오프셋 값
|
|
|
|
//현재 레벨의 높이 구하기.(active Level을 구하면 3D에서 작도가 안됌.)
|
|
double GenLevElevation = Unit.FeetToMM(NewMainLine.GetEndPoint(0).Z - mainPipe.LevelOffset);
|
|
MainVec = (mainEpCon.Origin - mainSpCon.Origin).Normalize();//메인 시작-끝 벡터
|
|
|
|
//처음 관경25는 헤드쪽때문에 기입
|
|
List<double> headDiaLst = new List<double>();
|
|
headDiaLst.Add(25); headDiaLst.Add(25); headDiaLst.Add(25); headDiaLst.Add(32); headDiaLst.Add(40); headDiaLst.Add(40);
|
|
headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(65);
|
|
headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65);
|
|
|
|
//대화상자
|
|
Form_Downward dlg = new Form_Downward();
|
|
dlg.MainHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3);
|
|
dlg.BranchHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3) + 300;
|
|
dlg.HeaderOffset = 150;
|
|
dlg.ConnectDist = 150;
|
|
dlg.CapDist = 100;
|
|
dlg.SpkrTol = 5;
|
|
dlg.TeeReducerDist = 100;
|
|
//플렉시블 파이프 유형 로드 유무
|
|
ICollection<Element> FlexPipeTypeLst = new FilteredElementCollector(doc).OfClass(typeof(FlexPipeType)).ToElements();
|
|
if (FlexPipeTypeLst.Count() > 0) dlg.m_FlexPipeLoad = true;
|
|
|
|
dlg.ShowDialog();
|
|
if (dlg.DialogResult == DialogResult.Cancel) return Result.Cancelled;
|
|
//대화상자 값 가져오기
|
|
m_MainHgt = dlg.MainHeight;
|
|
m_BranchHgt = dlg.BranchHeight;
|
|
m_HeadOffset = dlg.HeaderOffset;
|
|
m_ConnectDist = dlg.ConnectDist;
|
|
m_CapDist = dlg.CapDist;
|
|
m_Mode = dlg.m_RadIdx;
|
|
m_Tol = dlg.SpkrTol;
|
|
m_TReducerDist = dlg.TeeReducerDist;
|
|
|
|
//교차배관,가지배관 높이 재지정
|
|
m_MainHgt = m_MainHgt + GenLevElevation;
|
|
m_BranchHgt = m_BranchHgt + GenLevElevation;
|
|
|
|
//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;
|
|
|
|
Element pickFirstElem = null;
|
|
while (true)
|
|
{
|
|
//첫번째 헤드
|
|
Reference pickFirstRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "스프링클러 헤드 선택 : ");
|
|
if (pickFirstRef == null) return Result.Succeeded;
|
|
|
|
pickFirstElem = doc.GetElement(pickFirstRef.ElementId);
|
|
List<Connector> firstHeadCon = Util.GetElementConnectors(pickFirstElem);
|
|
if (firstHeadCon == null)
|
|
{
|
|
MessageBox.Show("스프링클러에 커넥터가 존재하지 않습니다.", "오류");
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
Connector HeadCon = firstHeadCon.First();
|
|
if (HeadCon.Origin.Z > Unit.MMToFeet(m_BranchHgt + m_HeadOffset))
|
|
{
|
|
MessageBox.Show("스프링클러에 커넥터의 높이가 (가지배관 높이 + 헤드 간격 띄우기) 값보다 높습니다.", "오류");
|
|
continue;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
}//while end
|
|
|
|
|
|
//이격 거리 방향 지정
|
|
XYZ SeparatePt = commandData.Application.ActiveUIDocument.Selection.PickPoint("가지배관 방향 지정 : ");
|
|
if (SeparatePt == null) return Result.Succeeded;
|
|
|
|
|
|
if (pickFirstElem is FamilyInstance)
|
|
{
|
|
FamilyInstance firstHeadfam = pickFirstElem as FamilyInstance;
|
|
List<Connector> ConLst = Util.GetElementConnectors(firstHeadfam);
|
|
//헤드 커넥터
|
|
Connector HeadCon = ConLst.First();
|
|
//메인관-커넥터 가까운 점
|
|
IntersectionResult interRes = NewMainLine.Project(HeadCon.Origin);
|
|
XYZ interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, HeadCon.Origin.Z);
|
|
//첫번째 헤드 정보
|
|
FirstObj.HeadCon = HeadCon;
|
|
FirstObj.m_Headpt = HeadCon.Origin;
|
|
FirstObj.m_SpID = firstHeadfam.Id;
|
|
|
|
|
|
XYZ InterZ0 = new XYZ(interPt.X, interPt.Y, 0);
|
|
XYZ HeadZ0 = new XYZ(FirstObj.m_Headpt.X, FirstObj.m_Headpt.Y, 0);
|
|
XYZ SeparatePtZ0 = new XYZ(SeparatePt.X, SeparatePt.Y, 0);
|
|
SeparationVec = (InterZ0 - HeadZ0).Normalize();
|
|
bool isRight = Util.isRightPoint(SeparatePtZ0, HeadZ0, InterZ0);
|
|
|
|
if (isRight == true)
|
|
SeparationVec = Util.RotateVector(SeparationVec, Util.DTR(-90.0));
|
|
else
|
|
SeparationVec = Util.RotateVector(SeparationVec, Util.DTR(90.0));
|
|
|
|
XYZ SepaPt = Util.Polar(FirstObj.m_Headpt, SeparationVec, Unit.MMToFeet(m_ConnectDist));
|
|
|
|
//이격점에서 메인 교차점
|
|
interRes = NewMainLine.Project(SepaPt);
|
|
interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, SepaPt.Z);
|
|
|
|
FirstObj.m_InterPt = interPt;
|
|
FirstObj.SeparateionPt = SepaPt;
|
|
|
|
lst_objSprinkler.Add(FirstObj);
|
|
}
|
|
//Util.Pyosi(doc, FirstObj.SeparateionPt, 1);
|
|
//MessageBox.Show("1");
|
|
//Util.Pyosi(doc, FirstObj.m_InterPt, 1);
|
|
//MessageBox.Show("2");
|
|
|
|
|
|
ObjSprinKler objspkr = new ObjSprinKler();
|
|
objspkr = FirstObj;
|
|
|
|
//두번째 헤드부터 반복문
|
|
List<XYZ> BranchPtLst = new List<XYZ>();
|
|
|
|
int sp_in = 0;
|
|
int HeadCnt = 1;
|
|
|
|
while (true)
|
|
{
|
|
Reference pickRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "스프링클러 헤드 선택 : ");
|
|
|
|
Element pickElem = doc.GetElement(pickRef.ElementId);
|
|
List<Connector> spkrCon = Util.GetElementConnectors(pickElem);
|
|
if (spkrCon == null)
|
|
{
|
|
MessageBox.Show("스프링클러 헤드에 커넥터가 존재하지 않습니다.", "오류");
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
Connector firstCon = spkrCon.First();
|
|
if (firstCon.Origin.Z > Unit.MMToFeet(m_BranchHgt + m_HeadOffset))
|
|
{
|
|
MessageBox.Show("스프링클러에 커넥터의 높이가 (가지배관 높이 + 헤드 간격 띄우기) 값보다 높습니다.", "오류");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//헤드 선택했을 때
|
|
if (pickElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers)
|
|
{
|
|
FamilyInstance Headfamily = pickElem as FamilyInstance;
|
|
List<Connector> ConLst = Util.GetElementConnectors(Headfamily);
|
|
//헤드 커넥터
|
|
Connector HeadCon = ConLst.First();
|
|
//메인관-커넥터 가까운 점
|
|
IntersectionResult interRes = NewMainLine.Project(HeadCon.Origin);
|
|
XYZ interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, HeadCon.Origin.Z);
|
|
|
|
ObjSprinKler NextObjSpkr = new ObjSprinKler();
|
|
//헤드 정보
|
|
NextObjSpkr.HeadCon = HeadCon;
|
|
NextObjSpkr.m_Headpt = HeadCon.Origin;
|
|
NextObjSpkr.m_SpID = Headfamily.Id;
|
|
//이격거리 적용된 점
|
|
XYZ SepaPt = Util.Polar(NextObjSpkr.m_Headpt, SeparationVec, Unit.MMToFeet(m_ConnectDist));
|
|
|
|
//이격점에서 메인 교차점
|
|
interRes = NewMainLine.Project(SepaPt);
|
|
interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, SepaPt.Z);
|
|
|
|
//이격거리 적용하여 헤드정보 추가
|
|
NextObjSpkr.m_InterPt = interPt;
|
|
NextObjSpkr.SeparateionPt = SepaPt;
|
|
|
|
List<Pipe> pipeLst = new List<Pipe>();
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("Pipe");
|
|
{
|
|
double firstDist = objspkr.m_InterPt.DistanceTo(mainLine.GetEndPoint(1));
|
|
double nextDist = NextObjSpkr.m_InterPt.DistanceTo(mainLine.GetEndPoint(1));
|
|
|
|
//첫번째 두번째 스프링클러의 거리가 허용오차 보다 작으면 옮김.
|
|
if (Math.Abs(firstDist - nextDist) <= Unit.MMToFeet(m_Tol))
|
|
{
|
|
//using(Transaction trans = new Transaction(doc))
|
|
//{
|
|
// trans.Start("SortSpkr");
|
|
|
|
XYZ moveVec = (objspkr.m_InterPt - NextObjSpkr.m_InterPt).Normalize();
|
|
XYZ movePt = Util.Polar(NextObjSpkr.m_Headpt, moveVec, Math.Abs(firstDist - nextDist));
|
|
|
|
FamilyInstance family = doc.GetElement(NextObjSpkr.m_SpID) as FamilyInstance;
|
|
LocationPoint locpt = family.Location as LocationPoint;
|
|
|
|
locpt.Point = movePt;
|
|
|
|
doc.Regenerate();
|
|
|
|
List<Connector> conLst = Util.GetElementConnectors(family);
|
|
Connector MoveHeadCon = conLst.First();
|
|
|
|
//메인관-커넥터 가까운 점
|
|
interRes = NewMainLine.Project(MoveHeadCon.Origin);
|
|
interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, MoveHeadCon.Origin.Z);
|
|
|
|
//헤드 정보
|
|
NextObjSpkr.HeadCon = MoveHeadCon;
|
|
NextObjSpkr.m_Headpt = MoveHeadCon.Origin;
|
|
NextObjSpkr.m_SpID = Headfamily.Id;
|
|
//이격거리 적용된 점
|
|
SepaPt = Util.Polar(NextObjSpkr.m_Headpt, SeparationVec, Unit.MMToFeet(m_ConnectDist));
|
|
|
|
//이격점에서 메인 교차점
|
|
interRes = NewMainLine.Project(SepaPt);
|
|
interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, SepaPt.Z);
|
|
|
|
//이격거리 적용하여 헤드정보 추가
|
|
NextObjSpkr.m_InterPt = interPt;
|
|
NextObjSpkr.SeparateionPt = SepaPt;
|
|
|
|
// trans.Commit();
|
|
//}
|
|
}
|
|
}
|
|
|
|
|
|
//헤드 리스트에 추가
|
|
lst_objSprinkler.Add(NextObjSpkr);
|
|
|
|
//틀어진 경우 점 2개 일직선일 경우 0개
|
|
List<XYZ> pts = Spkr_Func.DownSPJOIN(objspkr, NextObjSpkr, m_BranchHgt, ref sp_in, HeadCnt, headDiaLst);
|
|
if (pts == null) continue;
|
|
|
|
XYZ objSpkr_offsetpt = new XYZ(objspkr.SeparateionPt.X, objspkr.SeparateionPt.Y, Unit.MMToFeet(m_BranchHgt));
|
|
XYZ NextobjSpkr_offsetpt = new XYZ(NextObjSpkr.SeparateionPt.X, NextObjSpkr.SeparateionPt.Y, Unit.MMToFeet(m_BranchHgt));
|
|
|
|
|
|
if (pts.Count() == 2)
|
|
{
|
|
BranchPtLst.AddRange(pts);
|
|
}
|
|
|
|
//예시 작도점
|
|
List<XYZ> DrawPts = new List<XYZ>();
|
|
DrawPts.Add(objSpkr_offsetpt);
|
|
DrawPts.AddRange(pts);
|
|
DrawPts.Add(NextobjSpkr_offsetpt);
|
|
|
|
|
|
pipeLst = Util.CreatePipe(uiapp, doc, DrawPts, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
|
|
trans.Commit();
|
|
}
|
|
//지울 객체 찾아서 마무리에서 삭제할 리스트에 담기
|
|
List<ElementId> RemoveIDLst = Spkr_Func.getFamilyAndPipe(pipeLst.First());
|
|
RemoveElemIdLst.AddRange(RemoveIDLst);
|
|
|
|
|
|
HeadCnt++;
|
|
objspkr = NextObjSpkr;
|
|
}
|
|
//파이프(메인) 선택했을 때
|
|
else if (pickElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
|
|
{
|
|
Pipe PickMainPipe = pickElem as Pipe;
|
|
//이전에 작도된 파이프와 엘보는 삭제하고 작업
|
|
Util.DeleteElement(doc, RemoveElemIdLst);
|
|
//삭제된 리스트 초기화;
|
|
RemoveElemIdLst.Clear();
|
|
|
|
|
|
XYZ CapPt = Spkr_Func.DownGetCAPpoint(FirstObj, m_BranchHgt, m_CapDist);
|
|
//캡 포인트 리스트 담기
|
|
if (BranchPtLst.Count() > 0)
|
|
{
|
|
//리스트에 값이 있으면 처음에 pt넣음
|
|
BranchPtLst.Reverse();
|
|
BranchPtLst.Add(CapPt);
|
|
BranchPtLst.Reverse();
|
|
}
|
|
else
|
|
BranchPtLst.Add(CapPt);
|
|
|
|
//메인 연결될 가지파이프
|
|
XYZ LastPt = Spkr_Func.DownGetMain2LastpipePoint(objspkr, m_BranchHgt);
|
|
|
|
BranchPtLst.Add(LastPt);
|
|
|
|
//가지배관 헤드 연결
|
|
List<ElementId> ElemIdLst = new List<ElementId>();
|
|
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("Connect");
|
|
List<ObjSprinKler> sort_objspkrLst = SprinklerTolSort(lst_objSprinkler, mainLine, m_Tol);
|
|
List<Pipe> DrawPipeLst = Util.CreatePipe(uiapp, doc, BranchPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
|
|
|
|
ElemIdLst = Spkr_Func.DownConnectHead2pipe(lst_objSprinkler, DrawPipeLst, headDiaLst, m_HeadOffset, m_ConnectDist, m_BranchHgt,m_TReducerDist, m_Mode);
|
|
|
|
Connector lastspCon = null, lastepCon = null;
|
|
Util.GetStartEndConnector(doc.GetElement(ElemIdLst.Last()) as Pipe, ref lastspCon, ref lastepCon);
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
//가지배관 교차배관 연결
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("1");
|
|
Connector lastspCon = null, lastepCon = null;
|
|
Util.GetStartEndConnector(doc.GetElement(ElemIdLst.Last()) as Pipe, ref lastspCon, ref lastepCon);
|
|
|
|
//MainConnectElbow(MainElem, doc.GetElement(ElemIdLst.Last()));
|
|
Line MainElemLine = ((MainElem as Pipe).Location as LocationCurve).Curve as Line;
|
|
IntersectionResult interRes = MainElemLine.Project(lastepCon.Origin);
|
|
XYZ closePt1 = interRes.XYZPoint;
|
|
Line PickElemLine = ((pickElem as Pipe).Location as LocationCurve).Curve as Line;
|
|
interRes = PickElemLine.Project(lastepCon.Origin);
|
|
XYZ closePt2 = interRes.XYZPoint;
|
|
|
|
double main2EpConDist = lastepCon.Origin.DistanceTo(closePt1);
|
|
double pick2EpConDist = lastepCon.Origin.DistanceTo(closePt2);
|
|
|
|
if (main2EpConDist > pick2EpConDist)
|
|
MainConnectElbow(pickElem, doc.GetElement(ElemIdLst.Last()));
|
|
else
|
|
MainConnectElbow(MainElem, doc.GetElement(ElemIdLst.Last()));
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
break;
|
|
}
|
|
//엘보를 선택했을 때
|
|
else if (pickElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting)
|
|
{
|
|
|
|
FamilyInstance ElbowFamily = doc.GetElement(pickRef) as FamilyInstance;
|
|
string elbowFamStr = ElbowFamily.Category.Name;
|
|
|
|
Line ExtensionLine = NewMainLine;
|
|
//이전에 작도된 파이프와 엘보는 삭제하고 작업
|
|
Util.DeleteElement(doc, RemoveElemIdLst);
|
|
//삭제된 리스트 초기화;
|
|
RemoveElemIdLst.Clear();
|
|
|
|
//캡 생성
|
|
XYZ CapPt = Spkr_Func.DownGetCAPpoint(FirstObj, m_BranchHgt, m_CapDist);
|
|
//캡 포인트 리스트 담기
|
|
if (BranchPtLst.Count() > 0)
|
|
{
|
|
//리스트에 값이 있으면 처음에 pt넣음
|
|
BranchPtLst.Reverse();
|
|
BranchPtLst.Add(CapPt);
|
|
BranchPtLst.Reverse();
|
|
}
|
|
else
|
|
BranchPtLst.Add(CapPt);
|
|
|
|
//메인 연결될 가지파이프
|
|
XYZ LastPt = Spkr_Func.DownGetMain2LastpipePoint(objspkr, m_BranchHgt);
|
|
|
|
BranchPtLst.Add(LastPt);
|
|
|
|
List<ElementId> ElemIdLst = new List<ElementId>();
|
|
//가지배관 헤드 연결
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("HeadConnectBranch");
|
|
List<Pipe> DrawPipeLst = Util.CreatePipe(uiapp, doc, BranchPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
|
|
//헤드 가지배관 연결
|
|
ElemIdLst = Spkr_Func.DownConnectHead2pipe(lst_objSprinkler, DrawPipeLst, headDiaLst, m_HeadOffset, m_ConnectDist, m_BranchHgt, m_TReducerDist, m_Mode);
|
|
//교차배관 가지배관 연결
|
|
//MainConnectElbow(MainElem, doc.GetElement(ElemIdLst.Last()));
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
//XYZ InterPt = Util.GetPointOnLine(ExtensionLine, LastPt);
|
|
////Util.Pyosi(doc, InterPt, 1);
|
|
//
|
|
////생성되어있는 T 찾기
|
|
//FamilyInstance CrossTee = null;
|
|
//
|
|
//IList<Element> instances = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_PipeFitting).ToElements();
|
|
//foreach (Element elem in instances)
|
|
//{
|
|
// bool b_Type = Util.GetFamilyPartType(elem, PartType.Tee);
|
|
// if (b_Type == false) continue;
|
|
//
|
|
// FamilyInstance Teefam = elem as FamilyInstance;
|
|
// LocationPoint locpt = Teefam.Location as LocationPoint;
|
|
//
|
|
// if (locpt.Point.IsAlmostEqualTo(InterPt, Unit.MMToFeet(0.01)))
|
|
// {
|
|
// CrossTee = elem as FamilyInstance;
|
|
// break;
|
|
// }
|
|
//}
|
|
//
|
|
//if (CrossTee != null)
|
|
//{
|
|
// Connector ColumnCon = null;
|
|
//
|
|
// Connector PipeCon = null;
|
|
// Connector BranchTeeCon = GetTeeBranchConnector(CrossTee, MainVec, ReverseVec);
|
|
// Connector NextOtherCon = null;
|
|
// //Util.Pyosi(doc, BranchTeeCon.Origin, 1);
|
|
// int cnt = 0;
|
|
// while (true)
|
|
// {
|
|
// Connector NextCon = Util.GetNextElementConnector(BranchTeeCon);
|
|
//
|
|
// //선택한 엘보 패밀리가 나올 때 까지 반복
|
|
// if (!(NextCon.Owner is FamilyInstance))
|
|
// {
|
|
// NextOtherCon = Util.GetOtherConnector(NextCon);
|
|
// BranchTeeCon = NextOtherCon;
|
|
// continue;
|
|
// }
|
|
// if (Util.GetFamilyPartType(NextCon, PartType.Elbow) == true)
|
|
// {
|
|
// FamilyInstance family = NextCon.Owner as FamilyInstance;
|
|
//
|
|
// if (family.Id == ElbowFamily.Id)
|
|
// {
|
|
// //엘보에 붙어있는 파이프 커넥터 구하기
|
|
// ColumnCon = BranchTeeCon;
|
|
// Connector ElbowCon = NextCon;
|
|
// Connector ElbowOtherCon = Util.GetOtherConnector(ElbowCon);
|
|
// PipeCon = Util.GetNextElementConnector(ElbowOtherCon);
|
|
//
|
|
// //Util.Pyosi(doc, NextCon.Origin,1);
|
|
// //Util.Pyosi(doc, ElbowOtherCon.Origin,1);
|
|
// break;
|
|
// }
|
|
// }
|
|
//
|
|
// NextOtherCon = Util.GetOtherConnector(NextCon);
|
|
// BranchTeeCon = NextOtherCon;
|
|
//
|
|
// cnt++;
|
|
// if (cnt > 3000) break;
|
|
// }//while end
|
|
//
|
|
// Connector lastSpCon = null, lastEpCon = null;
|
|
// using (Transaction trans = new Transaction(doc))
|
|
// {
|
|
// trans.Start("1");
|
|
// //doc.Regenerate();
|
|
// List<Pipe> DrawPipeLst = Util.CreatePipe(uiapp, doc, BranchPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId);
|
|
//
|
|
// List<ElementId> ElemIdLst = Spkr_Func.DownConnectHead2pipe(lst_objSprinkler, DrawPipeLst, headDiaLst, m_HeadOffset, m_ConnectDist, m_BranchHgt);
|
|
//
|
|
// //Util.Pyosi(doc, ElbowPipeCon.Origin, 0);
|
|
// doc.Delete(ElbowFamily.Id);
|
|
//
|
|
// Pipe LastPipe = doc.GetElement(ElemIdLst.Last()) as Pipe;
|
|
// //작도된 파이프 중 메인에 가까운 파이프 끝점
|
|
// Util.GetStartEndConnector(LastPipe, ref lastSpCon, ref lastEpCon);
|
|
//
|
|
// //파이프 관경이 다를경우 레듀셔일 수 있어 다음객체 찾고 레듀셔 지움
|
|
// if (!(PipeCon.Owner is Pipe))
|
|
// {
|
|
// Connector OtherCon = Util.GetOtherConnector(PipeCon);
|
|
// PipeCon = Util.GetNextElementConnector(OtherCon);
|
|
// doc.Delete(OtherCon.Owner.Id);
|
|
// }
|
|
//
|
|
// if (!(ColumnCon.Owner is Pipe))
|
|
// {
|
|
// Connector OtherCon = Util.GetOtherConnector(ColumnCon);
|
|
// ColumnCon = Util.GetNextElementConnector(OtherCon);
|
|
// doc.Delete(OtherCon.Owner.Id);
|
|
// }
|
|
//
|
|
//
|
|
// XYZ MoveElbowPt = Util.Polar(PipeCon.Origin,
|
|
// lastEpCon.Origin, lastSpCon.Origin, PipeCon.Origin.DistanceTo(lastEpCon.Origin));
|
|
// //엘보에 붙어있던 파이프 위치 조정
|
|
// PipeCon.Origin = MoveElbowPt;
|
|
//
|
|
// Connector ColumnOtherCon = Util.GetOtherConnector(ColumnCon);
|
|
// XYZ MoveColumnPt = Util.Polar(ColumnCon.Origin,
|
|
// ColumnOtherCon.Origin, ColumnCon.Origin, ColumnCon.Origin.DistanceTo(lastEpCon.Origin));
|
|
// //Tee 기둥 위치 조정
|
|
// ColumnCon.Origin = MoveColumnPt;
|
|
// //Tee 기둥 관경 큰 관경 변경
|
|
// if (lastEpCon.Radius > PipeCon.Radius)
|
|
// ColumnCon.Radius = lastEpCon.Radius;
|
|
// else
|
|
// ColumnCon.Radius = PipeCon.Radius;
|
|
// //Tee 작도
|
|
// FamilyInstance familyTee = creDoc.NewTeeFitting(lastEpCon, PipeCon, ColumnCon);
|
|
//
|
|
// if (Math.Abs(lastEpCon.Origin.Z - PipeCon.Origin.Z) > Unit.MMToFeet(0.1))
|
|
// {
|
|
// MessageBox.Show("양쪽의 가지관 높이가 다릅니다.");
|
|
// return Result.Failed;
|
|
// }
|
|
//
|
|
// //왼쪽 오른쪽 관경이 다를 경우 레듀셔와 Tee 사이 간격 띄우기
|
|
// if (!(Math.Abs(lastEpCon.Radius - PipeCon.Radius) < Unit.MMToFeet(0.01)))
|
|
// {
|
|
// Spkr_Func.CreatePipeBetweenTeeAndReducer(familyTee, 100);
|
|
// //Util.Pyosi(doc, lastEpCon.Origin);
|
|
// }
|
|
//
|
|
// trans.Commit();
|
|
// }
|
|
//}
|
|
break;
|
|
}
|
|
}//while end
|
|
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("delete");
|
|
if (RemoveElemIdLst.Count() > 0)
|
|
doc.Delete(RemoveElemIdLst);
|
|
trans.Commit();
|
|
}
|
|
//MessageBox.Show("" + e);
|
|
}
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
//기준 커넥터에서 FlowVec 방향 커넥터 구하기(Tee 또는 Cross에서 사용)
|
|
public Connector GetTeeBranchConnector(FamilyInstance familyTee, XYZ FlowVec, XYZ ReverseVec)
|
|
{
|
|
Connector resCon = null;
|
|
ConnectorSet ConSet = null;
|
|
FamilyInstance family = null;
|
|
Pipe pipe = null;
|
|
|
|
List<Connector> TeeConLst = Util.GetElementConnectors(familyTee);
|
|
|
|
foreach (Connector TeeCon in TeeConLst)
|
|
{
|
|
if (TeeCon.IsConnected == true)
|
|
{
|
|
family = TeeCon.Owner as FamilyInstance;
|
|
ConSet = family.MEPModel.ConnectorManager.Connectors;
|
|
|
|
foreach (Connector con in ConSet)
|
|
{
|
|
if (TeeCon.Origin.IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01))) continue;
|
|
XYZ CurVec = (con.Origin - TeeCon.Origin).Normalize();
|
|
if (!(CurVec.IsAlmostEqualTo(FlowVec, Unit.MMToFeet(0.01)) || CurVec.IsAlmostEqualTo(ReverseVec, Unit.MMToFeet(0.01))))
|
|
resCon = con;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return resCon;
|
|
}
|
|
|
|
|
|
//메인과 가지관 엘보 작도
|
|
public void MainConnectElbow(Element MainPipeElem, Element BranchElem)
|
|
{
|
|
Connector SpCon = null, EpCon = null;
|
|
Pipe NewPipe = null;
|
|
|
|
Util.GetStartEndConnector(BranchElem as Pipe, ref SpCon, ref EpCon);
|
|
|
|
NewPipe = Spkr_Func.CreatePipeFromNearPt(MainPipeElem, EpCon);
|
|
//파이프 엘보 관경 맞추고 연결
|
|
Connector NewSpCon = null, NewEpCon = null;
|
|
Util.GetStartEndConnector(NewPipe, ref NewSpCon, ref NewEpCon);
|
|
NewSpCon.Radius = EpCon.Radius;
|
|
Util.ElbowFitting(doc, EpCon, NewSpCon);
|
|
|
|
//메인관에 T연결
|
|
Connector pipeSpCon = null, pipeEpCon = null;
|
|
bool b_Cons = Util.GetStartEndConnector(NewPipe, ref pipeSpCon, ref pipeEpCon);
|
|
|
|
Line DirectLine = ((MainPipeElem as Pipe).Location as LocationCurve).Curve as Line;
|
|
XYZ DivPt = Util.GetPointOnLine(DirectLine, pipeEpCon.Origin);
|
|
ElementId divID = PlumbingUtils.BreakCurve(doc, MainPipeElem.Id, DivPt);
|
|
|
|
Connector MainCon1 = null, MainCon2 = null;
|
|
List<Connector> MainCon1Lst = Util.GetElementConnectors(doc.GetElement(divID));
|
|
List<Connector> MainCon2Lst = Util.GetElementConnectors(MainPipeElem);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
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 SelectionMainPipe : 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;
|
|
}
|
|
}
|
|
|
|
public class SelectionFilter : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category == null) return false;
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers
|
|
|| element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves
|
|
|| element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|