Client/Desktop/KMBIM3.0/23.10.18/Cmd/Assembly/AssemblyMain.cs

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;
}
}
}
}