1018 lines
44 KiB
C#
1018 lines
44 KiB
C#
using Autodesk.Revit.ApplicationServices;
|
|
using Autodesk.Revit.Creation;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using Autodesk.Revit.DB.Structure;
|
|
using Autodesk.Revit.UI;
|
|
using Autodesk.Revit.UI.Selection;
|
|
using KDCS.Utils;
|
|
using KMBIM.Revit.Tools;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
|
|
using View = Autodesk.Revit.DB.View;
|
|
|
|
namespace KMBIM
|
|
{
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|
public class AssemblyMain : 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;
|
|
LanguageType lang;
|
|
|
|
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;
|
|
lang = commandData.Application.Application.Language;
|
|
|
|
try
|
|
{
|
|
var filterFam = new FilteredElementCollector(doc)
|
|
.OfClass(typeof(FamilySymbol));
|
|
|
|
string temp = "";
|
|
List<Info_ValveSymbol> info_ValSymLst = new List<Info_ValveSymbol>();
|
|
List<Info_AttachSymbol> info_AttachSymLst = new List<Info_AttachSymbol>();
|
|
List<string> NonParamSymbolLst = new List<string>();
|
|
|
|
foreach (FamilySymbol FamSym in filterFam)
|
|
{
|
|
//배관 밸브류만 추출
|
|
if ((int)BuiltInCategory.OST_PipeAccessory == FamSym.Category.Id.IntegerValue)
|
|
{
|
|
Info_ValveSymbol info = new Info_ValveSymbol();
|
|
info.m_FamSym = FamSym;
|
|
info.m_SymFamilyName = FamSym.FamilyName;
|
|
|
|
//중복된 FamilyName 존재 시 추가 X
|
|
bool b_Overlap = false;
|
|
foreach (Info_ValveSymbol infor in info_ValSymLst)
|
|
{
|
|
if (infor.m_SymFamilyName == FamSym.FamilyName)
|
|
{
|
|
b_Overlap = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (b_Overlap == false)
|
|
info_ValSymLst.Add(info);
|
|
}
|
|
|
|
//배관 부속류만 추출
|
|
if ((int)BuiltInCategory.OST_PipeFitting == FamSym.Category.Id.IntegerValue)
|
|
{
|
|
//aaa += "\n" + FamSym.FamilyName;
|
|
Info_AttachSymbol info = new Info_AttachSymbol();
|
|
info.m_AttFamSym = FamSym;
|
|
info.m_AttSymFamilyName = FamSym.FamilyName;
|
|
|
|
//중복된 FamilyName 존재 시 추가 X
|
|
bool b_Overlap = false;
|
|
foreach (Info_AttachSymbol infor in info_AttachSymLst)
|
|
{
|
|
if (infor.m_AttSymFamilyName == FamSym.FamilyName)
|
|
{
|
|
b_Overlap = true;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (b_Overlap == false)
|
|
{
|
|
//유니온만 추출
|
|
//if (Util.GetFamilyPartType(info.m_AttFamSym, PartType.Transition) == true
|
|
if (Util.GetFamilyPartType(info.m_AttFamSym, PartType.Union) == true)
|
|
{
|
|
info_AttachSymLst.Add(info);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
//MessageBox.Show(aaa);
|
|
|
|
using(Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("FilterNomRad");
|
|
|
|
foreach(Info_ValveSymbol info in info_ValSymLst)
|
|
{
|
|
FamilySymbol symbol = info.m_FamSym;
|
|
if (symbol.IsActive == false)
|
|
symbol.Activate();
|
|
|
|
FamilyInstance Family = doc.Create.NewFamilyInstance(XYZ.Zero, symbol, StructuralType.NonStructural);
|
|
doc.Regenerate();
|
|
|
|
Definition df = GetDefinition(Family, "NomRad");
|
|
if (df == null)
|
|
NonParamSymbolLst.Add(symbol.FamilyName);
|
|
|
|
Util.Delete(doc, Family);
|
|
doc.Regenerate();
|
|
}
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
//배관 관경 세그먼트 가져와야 함으로 파이프 선택 먼저하도록 변경
|
|
|
|
//어셈블리 부착할 파이프 선택
|
|
Reference pickRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new PipeSelectionFilter(), "어셈블리 연결할 배관 선택 : ");
|
|
|
|
Element elem = doc.GetElement(pickRef);
|
|
|
|
Form_Assembly dlg = new Form_Assembly();
|
|
dlg.info_ValSymLst = info_ValSymLst;
|
|
dlg.info_AttSymLst = info_AttachSymLst;
|
|
dlg.NonNomRadLst = NonParamSymbolLst;
|
|
dlg.m_uidoc = uidoc;
|
|
dlg.m_doc = doc;
|
|
//dlg.PipeTypeName = (elem as Pipe).PipeType.Name;
|
|
dlg.mainPipe = elem as Pipe;
|
|
if (dlg.ShowDialog() == DialogResult.Cancel) return Result.Cancelled;
|
|
|
|
List<AssemblyData> MainAssemLst = new List<AssemblyData>();
|
|
List<AssemblyData> SubAssemLst = new List<AssemblyData>();
|
|
|
|
MainAssemLst = dlg.m_MainDataLst;
|
|
SubAssemLst = dlg.m_SubDataLst;
|
|
double m_M2Sdist = dlg.Main2SubDist;
|
|
|
|
string tmp_nonSymLst = "";
|
|
foreach (AssemblyData data in MainAssemLst)
|
|
{
|
|
if (data.AssemFamSymFamName != "")
|
|
{
|
|
FamilySymbol famSym = Util.getNameByFamily(doc, data.AssemFamSymFamName);
|
|
if (famSym == null)
|
|
{
|
|
if (tmp_nonSymLst.Contains(data.AssemFamSymFamName) == false)
|
|
tmp_nonSymLst += ("- " + data.AssemFamSymFamName + "\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (AssemblyData data in SubAssemLst)
|
|
{
|
|
if (data.AssemFamSymFamName != "")
|
|
{
|
|
FamilySymbol famSym = Util.getNameByFamily(doc, data.AssemFamSymFamName);
|
|
if (famSym == null)
|
|
{
|
|
if (tmp_nonSymLst.Contains(data.AssemFamSymFamName) == false)
|
|
tmp_nonSymLst += ("- " + data.AssemFamSymFamName + "\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
//심볼 없으면 중지
|
|
if (tmp_nonSymLst != "")
|
|
{
|
|
MessageBox.Show("다음 심볼이 존재하지 않습니다.\n\n" + tmp_nonSymLst, "심볼 오류");
|
|
return Result.Failed;
|
|
}
|
|
|
|
|
|
|
|
View view = doc.ActiveView;
|
|
|
|
if (elem is Pipe)
|
|
{
|
|
Pipe DirPipe = elem as Pipe;
|
|
Connector spCon = null, epCon = null;
|
|
Util.GetStartEndConnector(DirPipe, ref spCon, ref epCon);
|
|
Line PipeLine = (DirPipe.Location as LocationCurve).Curve as Line;
|
|
|
|
IntersectionResult interRes = PipeLine.Project(pickRef.GlobalPoint);
|
|
XYZ PipeVec = (epCon.Origin - spCon.Origin).Normalize();
|
|
XYZ ClosePt = interRes.XYZPoint;
|
|
|
|
//밸브 배치할 커넥터
|
|
Connector setCon = null, SetOtherCon = null;
|
|
if (ClosePt.DistanceTo(spCon.Origin) > ClosePt.DistanceTo(epCon.Origin))
|
|
{
|
|
setCon = epCon;
|
|
SetOtherCon = spCon;
|
|
}
|
|
else
|
|
{
|
|
setCon = spCon;
|
|
SetOtherCon = epCon;
|
|
}
|
|
//Util.Pyosi(doc, setCon.Origin, 1);
|
|
//return Result.Succeeded;
|
|
XYZ SetVec = (setCon.Origin - SetOtherCon.Origin).Normalize();
|
|
XYZ SetOtherVec = (SetOtherCon.Origin - setCon.Origin).Normalize();
|
|
|
|
//첫번째 줄 생성된 객체 리스트에 저장
|
|
List<Element> FirstLineElemLst = new List<Element>();
|
|
|
|
|
|
//메인어셈블리 작도
|
|
MainAssemblyDraw(dlg, DirPipe, SetVec, setCon, ref FirstLineElemLst);
|
|
//서브어셈블리 작도
|
|
SubAssemblyDraw(dlg, FirstLineElemLst, DirPipe, SetVec, dlg.subDia);
|
|
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//MessageBox.Show("" + e);
|
|
MessageBox.Show("내부 오류가 발생하였습니다.\n관경이 없는 부속류 사용 시 작도가 되지 않습니다.\n확인하여 다시 작도하시기 바랍니다.", "오류");
|
|
}
|
|
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
//바이패스가 존재하는데 연속하는 파이프가 없을 경우 시작,끝에 추가
|
|
List<AssemblyData> ByPass_AddTeePipe(List<AssemblyData> AssemLst)
|
|
{
|
|
List<AssemblyData> AddAssemLst = new List<AssemblyData>();
|
|
AddAssemLst.AddRange(AssemLst);
|
|
|
|
//바이패스인데 첫번째 배관 데이터 다음에 심볼이 들어갈 경우 맨 앞에 300의 배관 데이터 추가
|
|
AssemblyData FirstData = AssemLst.First();
|
|
//첫번째 리스트 값이 배관일 때
|
|
if(FirstData.IsSymbol == false)
|
|
{
|
|
//두번쨰 리스트 값이 심볼일 때 배관 맨 앞에 추가
|
|
AssemblyData SecondData = AssemLst[1];
|
|
if (SecondData.IsSymbol == true)
|
|
{
|
|
AssemblyData newPipeData = new AssemblyData();
|
|
newPipeData.AssemFamSymFamName = null;
|
|
newPipeData.AssemPipeDist = "300";
|
|
newPipeData.IsSymbol = false;
|
|
AddAssemLst.Insert(0, newPipeData);
|
|
}
|
|
}
|
|
|
|
AssemblyData LastData = AssemLst.Last();
|
|
//마지막 리스트 값이 배관일 때
|
|
if (LastData.IsSymbol == false)
|
|
{
|
|
//끝에서 두번째 리스트 값이 심볼일 때 배관 맨 뒤 추가
|
|
AssemblyData Last2ndData = AssemLst[AssemLst.Count-2];
|
|
if (Last2ndData.IsSymbol == true)
|
|
{
|
|
AssemblyData newPipeData = new AssemblyData();
|
|
newPipeData.AssemFamSymFamName = null;
|
|
newPipeData.AssemPipeDist = "300";
|
|
newPipeData.IsSymbol = false;
|
|
AddAssemLst.Insert(AddAssemLst.Count, newPipeData);
|
|
}
|
|
}
|
|
|
|
|
|
return AddAssemLst;
|
|
}
|
|
|
|
//메인 어셈블리 작도
|
|
void MainAssemblyDraw(Form_Assembly dlg, Pipe DirPipe, XYZ DirVec, Connector SetCon, ref List<Element> FirstLineElemLst)
|
|
{
|
|
//첫번째 줄
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("1");
|
|
doc.Regenerate();
|
|
|
|
if(dlg.m_TypeIdx==0)
|
|
dlg.m_MainDataLst = ByPass_AddTeePipe(dlg.m_MainDataLst);
|
|
|
|
Connector LastCon = SetCon;
|
|
foreach (AssemblyData data in dlg.m_MainDataLst)
|
|
{
|
|
List<FamilySymbol> fam = new List<FamilySymbol>();
|
|
|
|
if (lang == LanguageType.English_USA || lang == LanguageType.English_GB)
|
|
fam = Util.getFamily(doc, "Pipe Accessories");
|
|
else if (lang == LanguageType.Korean)
|
|
fam = Util.getFamily(doc, "파이프 액세서리");
|
|
|
|
FamilySymbol valve = null;
|
|
|
|
|
|
|
|
if (data.IsSymbol == true)//심볼일 경우
|
|
{
|
|
|
|
//밸브 로드
|
|
valve = Util.getNameByFamily(doc, data.AssemFamSymFamName);
|
|
|
|
//심볼이 활성화 안되어 있으면 활성화 시킴
|
|
if (valve.IsActive == false)
|
|
valve.Activate();
|
|
|
|
FamilyInstance Fam = InsertSymbolToDirectionPipe(doc, DirPipe, LastCon, valve);
|
|
doc.Regenerate();
|
|
|
|
List<Connector> FamConLst = Util.GetElementConnectors(Fam);
|
|
XYZ FamInsertPt = (Fam.Location as LocationPoint).Point;
|
|
|
|
Connector valSpCon = null, valEpCon = null;
|
|
foreach (Connector con in FamConLst)
|
|
{
|
|
XYZ vec = (con.Origin - FamInsertPt).Normalize();
|
|
if (vec.IsAlmostEqualTo(DirVec))
|
|
valEpCon = con;
|
|
else
|
|
valSpCon = con;
|
|
}
|
|
|
|
XYZ FamVec = (valEpCon.Origin - valSpCon.Origin).Normalize();
|
|
XYZ FamReVec = (valSpCon.Origin - valEpCon.Origin).Normalize();
|
|
|
|
//유니온 일 때
|
|
if (Util.GetFamilyPartType(valve, PartType.Union))
|
|
{
|
|
valSpCon.Radius = LastCon.Radius;
|
|
doc.Regenerate();
|
|
|
|
Connector UniSpCon = null, UniEpCon = null;
|
|
foreach (Connector con in FamConLst)
|
|
{
|
|
XYZ vec = (con.Origin - FamInsertPt).Normalize();
|
|
if (vec.IsAlmostEqualTo(DirVec))
|
|
UniEpCon = con;
|
|
else
|
|
UniSpCon = con;
|
|
}
|
|
|
|
if (LastCon.Owner is FamilyInstance)
|
|
{
|
|
XYZ plrpt = Util.Polar(LastCon.Origin, FamVec, UniSpCon.Origin.DistanceTo(LastCon.Origin));
|
|
ElementTransformUtils.MoveElement(doc, Fam.Id, plrpt - LastCon.Origin);
|
|
}
|
|
else
|
|
{
|
|
XYZ plrpt = Util.Polar(LastCon.Origin, FamReVec, UniSpCon.Origin.DistanceTo(LastCon.Origin));
|
|
LastCon.Origin = plrpt;
|
|
}
|
|
|
|
doc.Regenerate();
|
|
LastCon.ConnectTo(UniSpCon);
|
|
LastCon = UniEpCon;
|
|
}
|
|
else//밸브일 때
|
|
{
|
|
|
|
Definition df = GetDefinition(Fam, "NomRad");
|
|
if (df != null)
|
|
{
|
|
Parameter paramRad = Fam.get_Parameter(df);
|
|
paramRad.Set(DirPipe.Diameter / 2.0);
|
|
}
|
|
else
|
|
{
|
|
trans.RollBack();
|
|
MessageBox.Show("패밀리에 파라미터 'NomRad'가 없습니다.");
|
|
return;
|
|
}
|
|
|
|
doc.Regenerate();
|
|
|
|
//커넥터 위치 옮김
|
|
if (LastCon.Owner is FamilyInstance)
|
|
{
|
|
XYZ plrpt = Util.Polar(LastCon.Origin, FamVec, valSpCon.Origin.DistanceTo(LastCon.Origin));
|
|
ElementTransformUtils.MoveElement(doc, Fam.Id, plrpt-LastCon.Origin);
|
|
}
|
|
else
|
|
{
|
|
XYZ plrpt = Util.Polar(LastCon.Origin, FamReVec, valSpCon.Origin.DistanceTo(LastCon.Origin));
|
|
LastCon.Origin = plrpt;
|
|
}
|
|
|
|
doc.Regenerate();
|
|
LastCon.ConnectTo(valSpCon);
|
|
LastCon = valEpCon;
|
|
//ElementTransformUtils.MoveElement(doc, valveFam.Id, plrpt - LastCon.Origin);
|
|
}
|
|
}
|
|
else//배관일 경우
|
|
{
|
|
//거리 double로 변경
|
|
double PipeDist = 0;
|
|
double.TryParse(data.AssemPipeDist, out PipeDist);
|
|
|
|
double dist = 0;
|
|
if (LastCon.Owner is FamilyInstance)
|
|
{
|
|
FamilyInstance lastFam = LastCon.Owner as FamilyInstance;
|
|
//밸브 삽입점-커넥터 거리 구하기
|
|
XYZ Insertpt = (lastFam.Location as LocationPoint).Point;
|
|
XYZ InsertZ0pt = Util.PointZ0(Insertpt);
|
|
XYZ LastConZ0pt = Util.PointZ0(LastCon.Origin);
|
|
dist = InsertZ0pt.DistanceTo(LastConZ0pt);
|
|
}
|
|
|
|
|
|
//선택 파이프 끝에서 데이터 거리만큼 떨어진 점 구하기.
|
|
if (Unit.MMToFeet(PipeDist) <= dist)
|
|
{
|
|
continue;
|
|
}
|
|
XYZ plrPt = Util.Polar(LastCon.Origin, DirVec, Math.Abs(Unit.MMToFeet(PipeDist) - dist));
|
|
double dd = Unit.FeetToMM(dist);
|
|
|
|
//배관 그릴 pt 리스트
|
|
List<XYZ> pipePts = new List<XYZ>();
|
|
pipePts.Add(LastCon.Origin);
|
|
pipePts.Add(plrPt);
|
|
|
|
List<Pipe> pipeLst = Util.CreatePipe(uiapp, doc, pipePts, DirPipe.MEPSystem.GetTypeId(), DirPipe.PipeType.Id, DirPipe.ReferenceLevel.Id);
|
|
|
|
Pipe newPipe = pipeLst.First();
|
|
Parameter paramDia = newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
|
|
if (paramDia != null)
|
|
paramDia.Set(DirPipe.Diameter);
|
|
|
|
//새로 생긴 파이프 커넥터 리스트
|
|
List<Connector> ConLst = Util.GetElementConnectors(newPipe);
|
|
Connector newPipeCon = null, newPipeOtherCon = null;
|
|
|
|
foreach (Connector con in ConLst)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(LastCon.Origin))
|
|
newPipeCon = con;
|
|
else
|
|
newPipeOtherCon = con;
|
|
}
|
|
|
|
LastCon.ConnectTo(newPipeCon);
|
|
|
|
//파이프 끝 점 (파이프 생성 후 연결 안 된 점)
|
|
LastCon = newPipeOtherCon;
|
|
//Util.Pyosi(doc, LastCon.Origin, 0);
|
|
doc.Regenerate();
|
|
|
|
FirstLineElemLst.Add(newPipeCon.Owner);
|
|
|
|
}
|
|
|
|
}//foreach end
|
|
|
|
|
|
trans.Commit();
|
|
}
|
|
}
|
|
|
|
//서브 어셈블리 작도
|
|
void SubAssemblyDraw(Form_Assembly dlg, List<Element> FirstLineElemLst, Pipe DirPipe, XYZ DirVec, double SubPipeDia)
|
|
{
|
|
List<info_SubBranchPt> info_branchPtLst = new List<info_SubBranchPt>();
|
|
|
|
//두번째 줄
|
|
if (dlg.m_TypeIdx == 0)
|
|
{
|
|
//서브 어셈블리 리스트박스 개수가 1개 이상일 때
|
|
if (dlg.m_SubDataLst.Count > 0)
|
|
{
|
|
//메인 어셈블리에 배관길이가 2개 연속으로 적용된 곳 사이에 T분기 빼는 작업
|
|
if (FirstLineElemLst.Count >= 3)//4개 이상인 경우만 작동 파이프 4개일 때 분기로 작업하기 위해.
|
|
{
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("1");
|
|
|
|
foreach (Element el in FirstLineElemLst)
|
|
{
|
|
if (el is Pipe)
|
|
{
|
|
Connector spConnector = null, epConnector = null;
|
|
Util.GetStartEndConnector(el as Pipe, ref spConnector, ref epConnector);
|
|
if (epConnector.IsConnected == true)
|
|
{
|
|
//파이프 커넥터 다음 커넥터가 파이프면 T연결
|
|
Connector NextCon = GetNextElementConnector(epConnector);
|
|
|
|
XYZ RotVec = null;
|
|
|
|
if (NextCon.Owner is Pipe)
|
|
{
|
|
Line pipeLine = ((NextCon.Owner as Pipe).Location as LocationCurve).Curve as Line;
|
|
if (Math.Abs(DirVec.Z) > Unit.MMToFeet(1))
|
|
RotVec = Util.RotateVectorX(DirVec, Util.DTR(-90));
|
|
else
|
|
RotVec = Util.RotateVector(DirVec, Util.DTR(90));
|
|
//T연결할 분기 배관 작도
|
|
|
|
XYZ plrpt = Util.Polar(NextCon.Origin, RotVec, Unit.MMToFeet(dlg.Main2SubDist));
|
|
|
|
//분기 포인트 구하기.
|
|
info_SubBranchPt info_subBranchPt = new info_SubBranchPt();
|
|
info_subBranchPt.branchSpCon = NextCon;
|
|
info_subBranchPt.branchEpt = plrpt;
|
|
info_subBranchPt.FirstPipeEpCon = epConnector;
|
|
info_subBranchPt.LastPipeSpCon = NextCon;
|
|
|
|
info_branchPtLst.Add(info_subBranchPt);
|
|
//Util.Pyosi(doc, NextCon.Origin, 1);
|
|
//Util.Pyosi(doc, plrpt, 1);
|
|
}
|
|
}
|
|
}
|
|
}//foreach end
|
|
|
|
//T분기 끝점 리스트
|
|
List<Connector> BranchEndConLst = new List<Connector>();
|
|
|
|
|
|
|
|
foreach (info_SubBranchPt info in info_branchPtLst)
|
|
{
|
|
List<XYZ> pipePtLst = new List<XYZ>();
|
|
pipePtLst.Add(info.branchSpCon.Origin);
|
|
pipePtLst.Add(info.branchEpt);
|
|
//분기 파이프 그리기
|
|
List<Pipe> branchPipeLst = Util.CreatePipe(uiapp, doc, pipePtLst, DirPipe.MEPSystem.GetTypeId(), DirPipe.PipeType.Id, DirPipe.ReferenceLevel.Id);
|
|
|
|
//분기 파이프 관경 변경
|
|
Pipe branchPipe = branchPipeLst.First();
|
|
Parameter paramDia = branchPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
|
|
if (paramDia != null)
|
|
paramDia.Set(Unit.MMToFeet(SubPipeDia));
|
|
|
|
doc.Regenerate();
|
|
|
|
List<Connector> bPipeConLst = Util.GetElementConnectors(branchPipe);
|
|
//T분기 시작 커넥터 교체.
|
|
foreach (Connector con in bPipeConLst)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(info.branchSpCon.Origin))
|
|
{
|
|
info.branchSpCon = con;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//T분기 작도
|
|
FamilyInstance teeFam = doc.Create.NewTeeFitting(info.FirstPipeEpCon, info.LastPipeSpCon, info.branchSpCon);
|
|
|
|
//T분기 파이프 끝 커넥터
|
|
Connector branchEpCon = Util.GetOtherConnector(info.branchSpCon);
|
|
|
|
//리스트에 T분기 파이프 끝 커넥터 저장
|
|
BranchEndConLst.Add(branchEpCon);
|
|
}
|
|
|
|
|
|
List<FamilySymbol> fam = new List<FamilySymbol>();
|
|
|
|
if (lang == LanguageType.English_USA || lang == LanguageType.English_GB)
|
|
fam = Util.getFamily(doc, "Pipe Accessories");
|
|
else if (lang == LanguageType.Korean)
|
|
fam = Util.getFamily(doc, "파이프 액세서리");
|
|
|
|
//SubAssemblyProcess(dlg, DirPipe, DirVec, FirstLineElemLst, BranchEndConLst);
|
|
//서브 어셈블리 1개 또는 여러개 일 때
|
|
if (dlg.m_SubDataLst.Count == 1)
|
|
SubAssemblyOneProcess(dlg, DirPipe, DirVec, SubPipeDia, FirstLineElemLst, BranchEndConLst);
|
|
else
|
|
SubAssemblyMultiProcess(dlg, DirPipe, DirVec, SubPipeDia, FirstLineElemLst, BranchEndConLst);
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void SubAssemblyOneProcess(Form_Assembly dlg, Pipe DirPipe, XYZ DirVec, double PipeDia, List<Element> SubLineElemLst, List<Connector> BranchEpConLst)
|
|
{
|
|
FamilySymbol valve = null;
|
|
|
|
//서브 어셈블리 개수가 1개에 밸브류일 경우
|
|
if (dlg.m_SubDataLst.Count == 1)
|
|
{
|
|
List<XYZ> ptLst = new List<XYZ>();
|
|
foreach (Connector con in BranchEpConLst)
|
|
{
|
|
ptLst.Add(con.Origin);
|
|
}
|
|
|
|
//파이프 생성 및 관경 변경
|
|
List<Pipe> newPipeLst = Util.CreatePipe2(uiapp, doc, ptLst, DirPipe.Diameter, DirPipe.MEPSystem.GetTypeId(), DirPipe.PipeType.Id, DirPipe.ReferenceLevel.Id);
|
|
Pipe newPipe = newPipeLst.First();
|
|
Parameter paramDia = newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
|
|
if (paramDia != null)
|
|
paramDia.Set(Unit.MMToFeet(PipeDia));
|
|
|
|
//파이프 커넥터 리스트
|
|
List<Connector> newPipeConLst = Util.GetElementConnectors(newPipeLst.First());
|
|
|
|
foreach (Connector PipeCon in newPipeConLst)
|
|
{
|
|
foreach (Connector branchCon in BranchEpConLst)
|
|
{
|
|
if (PipeCon.Origin.IsAlmostEqualTo(branchCon.Origin))
|
|
{
|
|
FamilyInstance ElbowFam = doc.Create.NewElbowFitting(PipeCon, branchCon);
|
|
}
|
|
}
|
|
}
|
|
|
|
doc.Regenerate();
|
|
|
|
AssemblyData data = dlg.m_SubDataLst.First();
|
|
//심볼일 때 중심에 설치
|
|
if (data.IsSymbol == true)
|
|
{
|
|
List<Connector> ElbowPipeConLst = Util.GetElementConnectors(newPipe);
|
|
|
|
XYZ MidPt = Util.Midpoint(ElbowPipeConLst.First().Origin, ElbowPipeConLst.Last().Origin);
|
|
|
|
//파이프 중심점 자르기
|
|
List<ElementId> divElemIdLst = Util.DivideElement(doc, newPipe, MidPt);
|
|
|
|
//밸브 로드
|
|
valve = Util.getNameByFamily(doc, data.AssemFamSymFamName);
|
|
|
|
//심볼이 활성화 안되어 있으면 활성화 시킴
|
|
if (valve.IsActive == false)
|
|
valve.Activate();
|
|
|
|
Pipe FirstdivPipe = doc.GetElement(divElemIdLst.First()) as Pipe;
|
|
List<Connector> conlst = Util.GetElementConnectors(FirstdivPipe);
|
|
Connector LastCon = null;
|
|
|
|
foreach (Connector con in conlst)
|
|
{
|
|
if (MidPt.IsAlmostEqualTo(con.Origin))
|
|
LastCon = con;
|
|
}
|
|
|
|
//밸브 설치 후 배관과 연결
|
|
//FamilyInstance valveFam = creDoc.NewFamilyInstance(MidPt, valve, DirVec, doc.GetElement(divElemIdLst.First()), StructuralType.NonStructural);
|
|
//FamilyInstance valveFam = creDoc.NewFamilyInstance(MidPt, valve, StructuralType.NonStructural);
|
|
FamilyInstance valveFam = InsertSymbolToDirectionPipe(doc, DirPipe, LastCon, valve);
|
|
Definition df = GetDefinition(valveFam, "NomRad");
|
|
if (df != null)
|
|
{
|
|
Parameter paramRad = valveFam.get_Parameter(df);
|
|
paramRad.Set(Unit.MMToFeet(PipeDia) / 2.0);
|
|
};
|
|
|
|
doc.Regenerate();
|
|
//밸브 커넥터 리스트
|
|
List<Connector> FamConLst = Util.GetElementConnectors(valveFam);
|
|
|
|
foreach (ElementId id in divElemIdLst)
|
|
{
|
|
Connector PipeConnector = null;
|
|
Connector ValveConnector = null;
|
|
|
|
Pipe divPipe = doc.GetElement(id) as Pipe;
|
|
List<Connector> divPipeConLst = Util.GetElementConnectors(divPipe);
|
|
|
|
List<Connector> closeConLst = new List<Connector>();
|
|
|
|
//현재 잘린 파이프 커넥터 중 밸브와 가까운 커넥터 구하기
|
|
foreach (Connector PipeCon in divPipeConLst)
|
|
{
|
|
if (PipeCon.Origin.IsAlmostEqualTo(MidPt))
|
|
{
|
|
PipeConnector = PipeCon;
|
|
}
|
|
}
|
|
|
|
Connector OtherCon = Util.GetOtherConnector(PipeConnector);
|
|
double minDist = double.MaxValue;
|
|
XYZ MoveVec = (OtherCon.Origin - PipeConnector.Origin).Normalize();
|
|
//현재 잘린 파이프와 가까운 밸브 커넥터 구하기
|
|
foreach (Connector FamCon in FamConLst)
|
|
{
|
|
double dist = OtherCon.Origin.DistanceTo(FamCon.Origin);
|
|
if (dist < minDist)
|
|
{
|
|
minDist = dist;
|
|
ValveConnector = FamCon;
|
|
}
|
|
}
|
|
|
|
//파이프 커넥터 점 밸브와 겹치는 길이만큼 옮기기
|
|
XYZ plrPt = Util.Polar(PipeConnector.Origin, MoveVec, PipeConnector.Origin.DistanceTo(ValveConnector.Origin));
|
|
PipeConnector.Origin = plrPt;
|
|
|
|
|
|
//파이프 밸브 커넥터 연결
|
|
PipeConnector.ConnectTo(ValveConnector);
|
|
|
|
//break;
|
|
}
|
|
|
|
}
|
|
|
|
//한개 작도 후 리턴하여 나감.
|
|
return;
|
|
}
|
|
}
|
|
|
|
void SubAssemblyMultiProcess(Form_Assembly dlg, Pipe DirPipe, XYZ DirVec, double PipeDia, List<Element> SubLineElemLst, List<Connector> BranchEpConLst)
|
|
{
|
|
FamilySymbol valve = null;
|
|
List<Connector> SubLineConLst = new List<Connector>();
|
|
//2개 이상일 떄 실행
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//서브 어셈블리 가지관 최대 길이
|
|
double m_SubBranchMaxDist = BranchEpConLst.First().Origin.DistanceTo(BranchEpConLst.Last().Origin);
|
|
//서브 어셈블리 시작 끝 커넥터
|
|
Connector SubAssemSpCon = null, SubAssemEpCon = null;
|
|
|
|
AssemblyData FirstData = dlg.m_SubDataLst.First();
|
|
AssemblyData LastData = dlg.m_SubDataLst.Last();
|
|
|
|
|
|
|
|
doc.Regenerate();
|
|
Connector LastCon = BranchEpConLst.First();
|
|
foreach (AssemblyData data in dlg.m_SubDataLst)
|
|
{
|
|
|
|
if (data.IsSymbol == true)//심볼일 경우
|
|
{
|
|
|
|
//밸브 로드
|
|
valve = Util.getNameByFamily(doc, data.AssemFamSymFamName);
|
|
|
|
//심볼이 활성화 안되어 있으면 활성화 시킴
|
|
if (valve.IsActive == false)
|
|
valve.Activate();
|
|
|
|
//밸브 설치 후 배관과 연결
|
|
//FamilyInstance valveFam = creDoc.NewFamilyInstance(LastCon.Origin, valve, DirVec, LastCon.Owner, StructuralType.NonStructural);
|
|
//FamilyInstance valveFam = creDoc.NewFamilyInstance(LastCon.Origin, valve, StructuralType.NonStructural);
|
|
FamilyInstance valveFam = InsertSymbolToDirectionPipe(doc, DirPipe, LastCon, valve);
|
|
doc.Regenerate();
|
|
//Util.Pyosi(doc, LastCon.Origin, 0);
|
|
|
|
List<Connector> FamConLst = Util.GetElementConnectors(valveFam);
|
|
XYZ FamInsertPt = (valveFam.Location as LocationPoint).Point;
|
|
|
|
Connector valSpCon = null, valEpCon = null;
|
|
foreach (Connector con in FamConLst)
|
|
{
|
|
XYZ vec = (con.Origin - FamInsertPt).Normalize();
|
|
if (vec.IsAlmostEqualTo(DirVec))
|
|
valEpCon = con;
|
|
else
|
|
valSpCon = con;
|
|
}
|
|
|
|
XYZ valVec = (valEpCon.Origin - valSpCon.Origin).Normalize();
|
|
XYZ valReVec = (valSpCon.Origin - valEpCon.Origin).Normalize();
|
|
|
|
Definition df = GetDefinition(valveFam, "NomRad");
|
|
if (df != null)
|
|
{
|
|
Parameter paramRad = valveFam.get_Parameter(df);
|
|
paramRad.Set(Unit.MMToFeet(PipeDia / 2.0));
|
|
};
|
|
|
|
doc.Regenerate();
|
|
|
|
//커넥터 위치 옮김
|
|
//XYZ plrpt = Util.Polar(LastCon.Origin, valVec, valSpCon.Origin.DistanceTo(LastCon.Origin));
|
|
XYZ plrpt = Util.Polar(LastCon.Origin, valReVec, valSpCon.Origin.DistanceTo(LastCon.Origin));
|
|
LastCon.Origin = plrpt;
|
|
doc.Regenerate();
|
|
LastCon.ConnectTo(valSpCon);
|
|
LastCon = valEpCon;
|
|
|
|
//ElementTransformUtils.MoveElement(doc, valveFam.Id, plrpt - LastCon.Origin);
|
|
//
|
|
////선택 파이프 끝 커넥터와 밸브 연결
|
|
//LastCon.ConnectTo(valSpCon);
|
|
//LastCon = valEpCon;
|
|
//
|
|
//doc.Regenerate();
|
|
//
|
|
//SubLineElemLst.Add(valEpCon.Owner);
|
|
//SubLineConLst.Add(valSpCon);
|
|
//SubLineConLst.Add(valEpCon);
|
|
//Util.Pyosi(doc, LastCon.Origin, 0);
|
|
}
|
|
else//배관일 경우
|
|
{
|
|
//거리 double로 변경
|
|
double PipeDist = 0;
|
|
double.TryParse(data.AssemPipeDist, out PipeDist);
|
|
//선택 파이프 끝에서 데이터 거리만큼 떨어진 점 구하기.
|
|
XYZ plrPt = Util.Polar(LastCon.Origin, DirVec, Unit.MMToFeet(PipeDist));
|
|
//배관 그릴 pt 리스트
|
|
List<XYZ> pipePts = new List<XYZ>();
|
|
pipePts.Add(LastCon.Origin);
|
|
pipePts.Add(plrPt);
|
|
|
|
List<Pipe> pipeLst = Util.CreatePipe(uiapp, doc, pipePts, DirPipe.MEPSystem.GetTypeId(), DirPipe.PipeType.Id, DirPipe.ReferenceLevel.Id);
|
|
|
|
Pipe newPipe = pipeLst.First();
|
|
Parameter paramDia = newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
|
|
if (paramDia != null)
|
|
paramDia.Set(Unit.MMToFeet(PipeDia));
|
|
|
|
//새로 생긴 파이프 커넥터 리스트
|
|
List<Connector> ConLst = Util.GetElementConnectors(newPipe);
|
|
Connector newPipeCon = null, newPipeOtherCon = null;
|
|
|
|
foreach (Connector con in ConLst)
|
|
{
|
|
if (con.Origin.IsAlmostEqualTo(LastCon.Origin))
|
|
newPipeCon = con;
|
|
else
|
|
newPipeOtherCon = con;
|
|
}
|
|
|
|
LastCon.ConnectTo(newPipeCon);
|
|
|
|
//파이프 끝 점 (파이프 생성 후 연결 안 된 점)
|
|
LastCon = newPipeOtherCon;
|
|
//Util.Pyosi(doc, LastCon.Origin, 0);
|
|
doc.Regenerate();
|
|
|
|
SubLineElemLst.Add(newPipeCon.Owner);
|
|
SubLineConLst.Add(newPipeCon);
|
|
SubLineConLst.Add(newPipeOtherCon);
|
|
}
|
|
}
|
|
|
|
//서브 어셈블리 엘보피팅
|
|
doc.Create.NewElbowFitting(BranchEpConLst.First(), SubLineConLst.First());
|
|
doc.Create.NewElbowFitting(BranchEpConLst.Last(), SubLineConLst.Last());
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 객체 방향으로 심볼 돌려서 삽입
|
|
/// </summary>
|
|
/// <param name="PatchCon"></param>부착할 커넥터
|
|
/// <param name="symbol"></param> 심볼(커넥터)
|
|
FamilyInstance InsertSymbolToDirectionPipe(Autodesk.Revit.DB.Document doc, Pipe DirPipe, Connector PatchCon, FamilySymbol symbol)
|
|
{
|
|
|
|
FamilyInstance fi = null;
|
|
//Line PipeLine = (DirPipe.Location as LocationCurve).Curve as Line;
|
|
Connector OtherCon = Util.GetOtherConnector(PatchCon);
|
|
XYZ vec = (PatchCon.Origin - OtherCon.Origin).Normalize();
|
|
|
|
if (Math.Abs(vec.Z) > Unit.MMToFeet(1))
|
|
{
|
|
fi = doc.Create.NewFamilyInstance(PatchCon.Origin, symbol, StructuralType.NonStructural);
|
|
//회전
|
|
Line axisRot = Line.CreateBound(PatchCon.Origin, PatchCon.Origin + XYZ.BasisY);
|
|
double ang = vec.AngleTo(XYZ.BasisY);
|
|
|
|
ElementTransformUtils.RotateElement(doc, fi.Id, axisRot, ang);
|
|
|
|
}
|
|
else
|
|
fi = doc.Create.NewFamilyInstance(PatchCon.Origin, symbol, vec, DirPipe, StructuralType.NonStructural);
|
|
|
|
|
|
return fi;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 매개 변수 정의를 반환합니다.
|
|
/// 주어진 요소와 매개 변수 이름.
|
|
/// </summary>
|
|
static Definition GetDefinition(Element elem, string parameter_name)
|
|
{
|
|
IList<Parameter> ps = elem.GetParameters(parameter_name);
|
|
|
|
int n = ps.Count;
|
|
|
|
Debug.Assert(1 >= n, "expected maximum one shared parameters" + "named " + parameter_name);
|
|
|
|
Definition d = (0 == n) ? null
|
|
: ps[0].Definition;
|
|
|
|
return d;
|
|
}
|
|
|
|
//커넥터에 연결된 다음 객체의 커넥터 구하기.
|
|
public static Connector GetNextElementConnector(Connector baseCon)
|
|
{
|
|
Connector resCon = null;
|
|
if (baseCon.IsConnected == true)
|
|
{
|
|
ConnectorSet ConSet = baseCon.AllRefs;
|
|
ConnectorSetIterator csi = ConSet.ForwardIterator();
|
|
while (csi.MoveNext())
|
|
{
|
|
Connector connected = csi.Current as Connector;
|
|
|
|
if (connected != null && connected.ConnectorType == ConnectorType.End)
|
|
{
|
|
if (baseCon.Origin.IsAlmostEqualTo(connected.Origin))
|
|
{
|
|
if (connected.IsConnected == true)
|
|
{
|
|
ConnectorSet ConnectedSet = null;
|
|
FamilyInstance family = null;
|
|
Pipe pipe = null;
|
|
FlexPipe flexpipe = null;
|
|
|
|
if (connected.Owner is FamilyInstance)
|
|
{
|
|
family = connected.Owner as FamilyInstance;
|
|
ConnectedSet = family.MEPModel.ConnectorManager.Connectors;
|
|
}
|
|
else if (connected.Owner is Pipe)
|
|
{
|
|
pipe = connected.Owner as Pipe;
|
|
ConnectedSet = pipe.ConnectorManager.Connectors;
|
|
}
|
|
else if (connected.Owner is FlexPipe)
|
|
{
|
|
flexpipe = connected.Owner as FlexPipe;
|
|
ConnectedSet = flexpipe.ConnectorManager.Connectors;
|
|
}
|
|
|
|
foreach (Connector NextCon in ConnectedSet)
|
|
{
|
|
if (connected.Origin.IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.001)))
|
|
{
|
|
resCon = NextCon;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}//while end
|
|
}
|
|
}
|
|
return resCon;
|
|
}
|
|
|
|
public class Info_ValveSymbol
|
|
{
|
|
public FamilySymbol m_FamSym;
|
|
public string m_SymFamilyName;
|
|
}
|
|
|
|
public class Info_AttachSymbol
|
|
{
|
|
public FamilySymbol m_AttFamSym;
|
|
public string m_AttSymFamilyName;
|
|
}
|
|
|
|
public class info_SubBranchPt
|
|
{
|
|
public Connector branchSpCon;//T분기 중간 커넥터(가지관 시작 커넥터)
|
|
public XYZ branchEpt;//T분기 가지관 끝 점
|
|
public Connector FirstPipeEpCon;//T분기 처음 커넥터
|
|
public Connector LastPipeSpCon;//T분기 마지막 커넥터
|
|
}
|
|
|
|
public class PipeSelectionFilter : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category == null) return false;
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|