Client/Desktop/KMBIM3.0/KMBIM3.0_소스/Cmd/Header/HeaderSteam.cs

1217 lines
53 KiB
C#

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.Creation;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Structure;
using System.IO;
using System.Windows.Forms;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.ApplicationServices;
using KDCS.Utils;
using KMBIM;
using KMBIM.Revit.Tools;
namespace KMBIM
{
// 커넥터의 좌표를 소트 하라.
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
class HeaderSteam : IExternalCommand
{
UIApplication uiapp;
UIDocument uidoc;
ExternalCommandData m_revit;
Autodesk.Revit.DB.Document doc;
Autodesk.Revit.Creation.Application creApp;
Autodesk.Revit.Creation.Document creDoc;
Autodesk.Revit.DB.View view;
LanguageType lang;
public List<KMBIM.HeValue> m_ArrValue = new List<KMBIM.HeValue>();
public List<KMBIM.HdValue> m_ArrHdValue = new List<KMBIM.HdValue>();
public List<string> m_ArrDia = new List<string>();
double hd1; // 사용자가 선택한 메인ㅌ 헤더의 관경
Connector outvalveconn = null, trapvalveconn = null;
double maxdist = 0.0; // 헤더 다리의 최대거리
double footdia = 0.0; //헤더 다리의 지름
double flangedia = 0.0; //플랜지의 지름
double flangelen = 0.0; //플랜지의 길이
int totalfooter = 0; // 전체 기둥의개수
double[] hd_loc_dst; // 가지관의 거리를 기억하는 배열
double hd2; // 해더의 총 길이
double[] gd_List = new double[10]; // 헤더 지지관의 거리?
double[] flst = new double[7];
double m_headHight = 0.0; //헤더 높이
int gi_ListEA; //헤더 지지다리의 갯수
int Cntnum = -1;
Autodesk.Revit.Creation.ItemFactoryBase m_CreationBase;
XYZ p1 = new XYZ(); // 삽입점
XYZ p2 = new XYZ(); //방향
double[] borlst; // 관경리스트
int ListBoxCnt = -1; // 다이얼로그에서 설정한 관경의 목록의 개수
int ListBoxCnt2 = -1; // 다이얼로그에서 설정한 관경의 목록의 개수
public const double PI = 3.14159265358;
public double ksv = 7.545932; //2300을 pit로 변환해놓은값
//패밀리 경로
public string str_Globepath = null, str_Safepath = null;
public PipingSystemType pSysType = null;
public double m_ControlValHgt = 0;
public List<PipingSystemType> SysTypeNameLst = new List<PipingSystemType>();
public Autodesk.Revit.UI.Result Execute(ExternalCommandData revit,
ref string message, ElementSet elements)
{
if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
uiapp = revit.Application;
uidoc = uiapp.ActiveUIDocument;
doc = uidoc.Document;
m_revit = revit;
creApp = uiapp.Application.Create;
creDoc = doc.Create;
view = doc.ActiveView;
lang = revit.Application.Application.Language;
try
{
//파이프 시스템 유형 리스트에 넣기
List<string> m_pipeSysTypeList = new List<string>();
ICollection<Element> SysTypeCollection = new FilteredElementCollector(doc).OfClass(typeof(PipingSystemType)).ToElements();
foreach (Element elem in SysTypeCollection)
{
if (elem is PipingSystemType)
{
PipingSystemType pipingSystemType = elem as PipingSystemType;
m_pipeSysTypeList.Add(pipingSystemType.Name);
}
}
Form_Steam dlg = new Form_Steam();
dlg.m_nMode = 4;
dlg.m_HeadHgt = 800;
dlg.m_ValHgt = 1300;
dlg.HeaderSysTypeLst = m_pipeSysTypeList;
dlg.doc = doc;
if (dlg.ShowDialog() == DialogResult.OK)
{
//MessageBox.Show("" + dlg.m_BFpath + "\n\n" + dlg.m_Drainpath + "\n\n" + dlg.m_Safepath + "\n\n" + dlg.m_PGpath + "\n\n" + dlg.m_TGpath);
//패밀리 경로
str_Globepath = dlg.m_Globepath;
str_Safepath = dlg.m_Safepath;
m_ControlValHgt = dlg.m_ValHgt;
//pSysType = dlg.HeaderSysType;
m_ArrValue = dlg.m_ArrValue;
m_ArrHdValue = dlg.m_ArrHdValue;
m_ArrDia = dlg.m_ArrDia;
SysTypeNameLst = dlg.SelectedSysTypeNameLst;
// 다이얼로그에서 설정한 데이터를 읽어 들인다.
ListBoxCnt2 = dlg.listboxcnt - 1;
hd1 = dlg.mainHeaderDia; //헤더의몸통의 관경
ListBoxCnt = dlg.listboxcnt; // 가지관의 갯수
m_headHight = dlg.m_HeadHgt;
if (ListBoxCnt > 0)
{
borlst = new double[ListBoxCnt + 2];
for (int m = 0; m < ListBoxCnt; m++)
{
borlst[m] = dlg.dlst[m];
}
}
// 1. 삽입점을 묻는다.
// 2. 방향을 묻는다.
// 3. 헤더의를 삽입한다.
// 4. 해더의 가지관을 삽입한다.
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// 삽입점과 방향을 얻어온다.
ObjectSnapTypes snapType = ObjectSnapTypes.Centers | ObjectSnapTypes.Endpoints | ObjectSnapTypes.Intersections
| ObjectSnapTypes.Midpoints | ObjectSnapTypes.Nearest | ObjectSnapTypes.WorkPlaneGrid | ObjectSnapTypes.Points | ObjectSnapTypes.Quadrants | ObjectSnapTypes.Tangents;
p1 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapType, "삽입점");
//p2 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapType, "방향 지정");
//선택한 점이 파이프 위의 점이면 파이프 높이 가져와야
//메인헤더와 플랜지의 값들을 계산
HDR_MDRAW(p1, 900);
// 다리간의 거리및 두께를 계산
HDR_HHH();
// 헤더를 로드및 삽입
// 4 -> 입면 증기
LoadFamily(4);
// 가지관을 삽입한다.
//총거리 = hd2
//메인헤더의 관경은 = hd1
//지지다리간의 최대 거리 = maxdist
//다리간의 거리 = gd_list
//헤더 지금 = hd1
//플랜지 관경 = flangedia
//플랜지 길이 = flangelen
}
}
catch
{
}
return Autodesk.Revit.UI.Result.Succeeded;
}
private void HDR_MDRAW(XYZ inp, double hg1)
{
int m, flg, hd_Cnt;
double hp1, ds1;
XYZ pnt1;
flangelen = hd1 * 0.14;
borlst[ListBoxCnt2 + 1] = 32.0; // 안전밸브
// 주관 길이
hd_loc_dst = new double[ListBoxCnt2 + 4];
flg = 0;
hd_Cnt = 0;
pnt1 = inp;
hd_loc_dst[hd_Cnt] = 250;
hd_Cnt++;
for (m = 0; m < ListBoxCnt2 + 1; m++)
{
flg = flg + 1;
ds1 = SL(borlst[m], borlst[flg]); //파이프간 간격
hd_loc_dst[hd_Cnt] = ds1; hd_Cnt++;
// pntlst.append(pnt`1); //파이프작도 좌표 리스트
}
hd_loc_dst[hd_Cnt] = 250; hd_Cnt++; // 안전밸브
// pnt1 = m_Math.Polar(pnt1, 250, ang);
// pntlst.append(pnt1);
FL(hd1);
hp1 = flst[6] * 0.5; // 플랜지외경지름
flangedia = hp1;
hd2 = 0;
for (m = 0; m < hd_Cnt; m++)
{
hd2 = hd2 + hd_loc_dst[m];
}
} //defun end HDR-MDRAW
///헤더 다리 부분
private void HDR_HHH()
{
double chg1, chg2, dst0, dst1, dst2;
chg1 = chg2 = dst0 = dst1 = dst2 = 0.0;
bool chk = false;
int flg = 0;
// chg1 = 지지관 지름 chg2 = 최대 지지 간격
if (hd1 == 200)
{
//chg1 = 65;
chg1 = 100;
chg2 = 1250;
}
else if (hd1 == 250)
{
//chg1 = 80;
chg1 = 120;
chg2 = 1500;
}
else if (hd1 >= 300)
{
//chg1 = 100;
chg1 = 150;
chg2 = 1750;
} // cond-end
footdia = chg1; //다리 기둥의 지름
chk = true;
flg = 0;
while (chk)
{
switch (flg)
{
case 0:
gi_ListEA = HDR_2D(hd2, chg2);
flg = 1 + flg;
break;
case 1:
gi_ListEA = HDR_3D(hd2, chg2);
flg = 1 + flg;
break;
case 2:
gi_ListEA = HDR_4D(hd2, chg2);
flg = 1 + flg;
break;
case 3:
gi_ListEA = HDR_5D(hd2, chg2);
flg = 1 + flg;
break;
default:
break;
} // cond-end
if (gi_ListEA != 0) chk = false;
} // while-end
//다리의 총 개수
totalfooter = flg;
// ***************************
// ekfl
} // defun hdr-2d
private void LoadFamily(int ai_type)
{
string versionNumber = doc.Application.VersionNumber.ToString();
List<Connector> tttt = new List<Connector>();
// load a family symbol from file
FamilySymbol gotSymbol = null;
List<FamilySymbol> fam1 = new List<FamilySymbol>();
if (lang == LanguageType.English_USA || lang == LanguageType.English_GB)
fam1 = getFamily("Mechanical Equipment");
else if (lang == LanguageType.Korean)
fam1 = getFamily("기계 장비");
FamilySymbol valve = null;
bool sw = false;
//패밀리의 갯수가 하나이상이면 사용자가 선택 할수 있도록 해줘야한다.
//string Tmp = System.Reflection.Assembly.GetExecutingAssembly().Location;
//Tmp = Tmp.Replace("\\KMBIM2019.dll", "");
string Tmp = Util.GetKMBIMLibraryFolder("Libraries\\Header");
// get the active view's level for beam creation
ViewPlan view = doc.ActiveView as ViewPlan;
Level level = view.GenLevel;
//Level level = uidoc.Document.GetElement(uidoc.ActiveView.LevelId) as Level;
String fileName = Tmp + "\\family\\" + versionNumber + "\\new Steam Header.rfa";
// 아래의 이름은 패밀리 고유의 이름이다. 패밀리 작업할때 입력하게 되어있다.
String name = "Hot Water Header (Supply)";
using (Transaction trans = new Transaction(doc))
{
trans.Start("FamilyLoad");
sw = uidoc.Document.LoadFamilySymbol(fileName, name, out gotSymbol);
trans.Commit();
}
Definition df = null;
// 패밀리를 로드한다.
if (sw)
{
// 로드가 성공 하였다면 패밀리를 삽입한다.
Level level2 = uidoc.Document.ActiveView.GenLevel;
//FamilyInstance familyInstance = uidoc.Document.Create.NewFamilyInstance(new XYZ(p1.X, p1.Y, (p1.Z + Unit.CovertToAPI(800, DisplayUnitType.DUT_MILLIMETERS))), gotSymbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
FamilyInstance familyInstance = null;
Parameter familyParam = null;
using (Transaction trans = new Transaction(doc))
{
trans.Start("symbolActive");
if (gotSymbol.IsActive == false)
gotSymbol.Activate();
//familyInstance = uidoc.Document.Create.NewFamilyInstance(new XYZ(p1.X, p1.Y, (p1.Z + Unit.CovertToAPI(800, DisplayUnitType.DUT_MILLIMETERS))), gotSymbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
p1 = new XYZ(p1.X, p1.Y, 0);
familyInstance = uidoc.Document.Create.NewFamilyInstance(p1, gotSymbol, StructuralType.NonStructural);
uidoc.Document.Regenerate();
//헤더 높이 지정
df = GetDefinition(familyInstance, "foot1dist");
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter("Fdia");
sw = familyParam.Set(Unit.MMToFeet(m_headHight));
//sw = familyParam.Set(Unit.CovertToAPI(m_headHight, DisplayUnitType.DUT_MILLIMETERS));
uidoc.Document.Regenerate();
Parameter param = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
double dd = Unit.FeetToMM(param.AsDouble());
param.Set(0);
uidoc.Document.Regenerate();
// Family asdf = familyInstance.Symbol.Family as Family;
// 플랜지의 길이 얻고 입력
// API 내부에서는 사용자가 입력하는 밀리의 단위가 아닌 피트가 쓰인다 그래서 변환해서 입력해 주어야 한다.
df = GetDefinition(familyInstance, "FSize");
familyParam = familyInstance.get_Parameter(df);
//Parameter familyParam = familyInstance.get_Parameter("FSize");
sw = familyParam.Set(Unit.MMToFeet(flangelen));
//sw = familyParam.Set(Unit.CovertToAPI(flangelen, DisplayUnitType.DUT_MILLIMETERS));
//플랜지의 반경 얻고 입력
df = GetDefinition(familyInstance, "Fdia");
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter("Fdia");
sw = familyParam.Set(Unit.MMToFeet(flangedia));
//sw = familyParam.Set(Unit.CovertToAPI(flangedia, DisplayUnitType.DUT_MILLIMETERS));
//다리의 지름
// API 내부에서는 사용자가 입력하는 밀리의 단위가 아닌 피트가 쓰인다 그래서 변환해서 입력해 주어야 한다.
df = GetDefinition(familyInstance, "footerdia");
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter("footerdia");
sw = familyParam.Set(Unit.MMToFeet(footdia));
//sw = familyParam.Set(Unit.CovertToAPI(footdia, DisplayUnitType.DUT_MILLIMETERS));
//헤더의 반경
// API 내부에서는 사용자가 입력하는 밀리의 단위가 아닌 피트가 쓰인다 그래서 변환해서 입력해 주어야 한다.
df = GetDefinition(familyInstance, "HeaderDia");
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter("HeaderDia");
sw = familyParam.Set(Unit.MMToFeet(hd1));
//sw = familyParam.Set(Unit.CovertToAPI(hd1, DisplayUnitType.DUT_MILLIMETERS));
// 헤더의 총거리
// API 내부에서는 사용자가 입력하는 밀리의 단위가 아닌 피트가 쓰인다 그래서 변환해서 입력해 주어야 한다.
df = GetDefinition(familyInstance, "Totaldistance");
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter("Totaldistance");
sw = familyParam.Set(Unit.MMToFeet(hd2));
//sw = familyParam.Set(Unit.CovertToAPI(hd2, DisplayUnitType.DUT_MILLIMETERS));
for (int i = 0; i <= totalfooter; i++)
{
string Tm2p = string.Format("footer_{0}", i + 1);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter(Tm2p);
sw = familyParam.Set(Unit.MMToFeet(gd_List[i]));
//sw = familyParam.Set(Unit.CovertToAPI(gd_List[i], DisplayUnitType.DUT_MILLIMETERS));
}
//안보이는 다리들을 한곳으로 모으자
if (totalfooter >= 1)
{
for (int i = 3; i <= 5; i++)
{
string Tm2p = string.Format("footer_{0}", i);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter(Tm2p);
if (i - 1 > totalfooter)
{
familyParam.Set(Unit.MMToFeet(0));
//familyParam.Set(Unit.CovertToAPI(0, DisplayUnitType.DUT_MILLIMETERS));
}
}
}
//보이는 다리의 거리를 준다.
for (int i = 0; i <= totalfooter; i++)
{
string Tm2p = string.Format("footer_{0}", i + 1);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
//familyParam = familyInstance.get_Parameter(Tm2p);
sw = familyParam.Set(Unit.MMToFeet(gd_List[i]));
//sw = familyParam.Set(Unit.CovertToAPI(gd_List[i], DisplayUnitType.DUT_MILLIMETERS));
}
// 헤더 지지 다리를 상황에 따라서 보여주고 안보여주고 하는 기능
if (totalfooter >= 1)
{
for (int i = 3; i <= 5; i++)
{
string Tm2p = string.Format("FootVisible_{0}", i);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
if (i - 1 <= totalfooter)
sw = familyParam.Set(1);
else
sw = familyParam.Set(0);
}
}
// 가지관들의 거리르 삽입해준다.
// 상황에 따라서 압력계나 온도계는 빠질수도 있다. 압력계는 가장 처음 온도계는 두번째 안전밸브는 마지막이다.
for (int i = 0; i <= hd_loc_dst.Length - 1; i++)
{
string Tm2p = string.Format("part_{0}", i + 1);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
sw = familyParam.Set(Unit.MMToFeet(hd_loc_dst[i]));
//sw = familyParam.Set(Unit.CovertToAPI(hd_loc_dst[i], DisplayUnitType.DUT_MILLIMETERS));
}
//헤더의 커넥터를 전부 모아라.
FilteredElementCollector collector = new FilteredElementCollector(uidoc.Document);
collector.OfClass(typeof(PipeType));
PipeType pipeType = collector.FirstElement() as PipeType;
//PipeType pipeType = null;
//패밀리 위치변경 조정
doc.Regenerate();
Family family = familyInstance.Symbol.Family;
ConnectorSetIterator csi = null;
if (null != familyInstance.MEPModel)
{
int cnt = 0;
// 커넥터를 거리별로 정렬 한다.
DinoComparer cc = new DinoComparer();
List<Connector> OtherZConLst = new List<Connector>();
List<Connector> bodyConLst = Util.GetElementConnectors(familyInstance);
bodyConLst.Sort(cc);
double LastZ = (bodyConLst.Last().Origin.Z);
foreach (Connector con in bodyConLst)
{
tttt.Add(con);
if (Math.Abs(LastZ - con.Origin.Z) > Unit.MMToFeet(1))
{
OtherZConLst.Add(con);
//Util.Pyosi(doc, con.Origin, 0);
}
}
//tttt.Sort(cc);
OtherZConLst.Sort(cc);
foreach (Connector con in OtherZConLst)
{
tttt.Remove(con);
}
doc.Regenerate();
//outvalveconn = tttt[8];
trapvalveconn = OtherZConLst[0];
outvalveconn = OtherZConLst[1];
//tttt.RemoveAt(8);
// 일단 밸브 패밀리가 로드 되어져 있는지를 보라
List<FamilySymbol> fam = new List<FamilySymbol>();
if (lang == LanguageType.English_USA || lang == LanguageType.English_GB)
fam = getFamily("Pipe Accessories");
else if (lang == LanguageType.Korean)
fam = getFamily("파이프 액세서리");
//패밀리의 갯수가 하나이상이면 사용자가 선택 할수 있도록 해줘야한다.
if (fam.Count >= 1)
{
if (ai_type == 4)
{
//valve = LoadFamilys("\\data\\PV_Butterfly Valve - 20-500mm-Handle.rfa", "PV_Butterfly Valve - 20-500mm-Handle");
valve = LoadFamilys(str_Globepath);
}
if (valve == null)
{
if (ai_type == 4)
{
//valve = getNameByFamily("PV_Butterfly Valve - 20-500mm-Handle");
valve = getNameByFamily(Path.GetFileNameWithoutExtension(str_Globepath));
}
}
}
if (fam.Count == 0)// 밸브 패밀리가 없다면 로드하라
{
if (ai_type == 4)
{
//valve = LoadFamilys("\\data\\PV_Butterfly Valve - 20-500mm-Handle.rfa", "PV_Butterfly Valve - 20-500mm-Handle");
valve = LoadFamilys(str_Globepath);
}
if (valve == null)
{
if (ai_type == 4)
{
//valve = getNameByFamily("PV_Butterfly Valve - 20-500mm-Handle");
valve = getNameByFamily(Path.GetFileNameWithoutExtension(str_Globepath));
}
}
}
List<Pipe> pipelist = new List<Pipe>();
List<XYZ> intps = new List<XYZ>();
// 상황에 따른 대처를 위해서 변수 생셩
if (ai_type == 4)
Cntnum = 0;
double m_elevation = view.GenLevel.Elevation;
// 커넥터수만큼 roof를 돌면서 파이프를 그린다.
for (int i = Cntnum; i < tttt.Count; i++)
{
if (cnt < borlst.Length - 2)
{
double con2valDst = Unit.MMToFeet(m_ControlValHgt) - (tttt[i].Origin.Z - m_elevation);
XYZ inpt = new XYZ(tttt[i].Origin.X, tttt[i].Origin.Y, (tttt[i].Origin.Z + con2valDst*2.0));
//XYZ inpt = new XYZ(tttt[i].Origin.X, tttt[i].Origin.Y, (tttt[i].Origin.Z + Unit.CovertToAPI(1000, DisplayUnitType.DUT_MILLIMETERS)));
Pipe pipe = null;
pSysType = SysTypeNameLst[cnt];
pipe = Pipe.Create(doc, pSysType.Id, pipeType.Id, level.Id, tttt[i].Origin, inpt);
//파이프와 헤더 몸통 커넥터 연결
List<Connector> pipeConLst = Util.GetElementConnectors(pipe);
foreach (Connector con in pipeConLst)
{
if (con.Origin.IsAlmostEqualTo(tttt[i].Origin, Unit.MMToFeet(0.01)))
con.ConnectTo(tttt[i]);
}
if (ai_type == 4)
ChangePipeSize(pipe, borlst[cnt + Cntnum]); // 냉온수일때
pipelist.Add(pipe);
intps.Add(inpt);
}
else
break;
cnt++;
}
cnt = 0;
for (int i = 0; i < pipelist.Count; i++)
{
// 밸브를 삽입히가.
FamilyInstance fi = null;
//using(Transaction trans = new Transaction(doc))
//{
// trans.Start("valve");
if (valve.IsActive == false)
valve.Activate();
var vel = valve.IsActive;
fi = uidoc.Document.Create.NewFamilyInstance(XYZ.Zero, valve, StructuralType.NonStructural);
uidoc.Document.Regenerate();
// trans.Commit();
//}
XYZ base1 = XYZ.Zero;
XYZ base2 = -XYZ.BasisY;
// 회전축을 정의하고
Line nline = Line.CreateUnbound(base1, base2);
// 돌린다.
fi.Location.Rotate(nline, Math.PI / 2);
base1 = XYZ.Zero;
base2 = -XYZ.BasisZ;
// 다시 회전축을 정의하고
nline = Line.CreateUnbound(base1, base2);
//돌린다.
fi.Location.Rotate(nline, -Math.PI / 2);
XYZ vec = (intps[i] - tttt[i + Cntnum].Origin).Normalize();
XYZ PipeMidPt = Util.Polar(tttt[i + Cntnum].Origin, vec, intps[i].DistanceTo(tttt[i + Cntnum].Origin) / 2.0);
ElementTransformUtils.MoveElement(uidoc.Document, fi.Id, PipeMidPt);
//자르기 전 파이프 시작 끝 커넥터 구하기
Connector spCon = null, epCon = null;
Util.GetStartEndConnector(pipelist[i], ref spCon, ref epCon);
//파이프 중간점 기준으로 자르기
List<ElementId> m_DivLst = Util.DivideElement(doc, pipelist[i], PipeMidPt);
Connector divspCon1 = null, divepCon1 = null, divspCon2 = null, divepCon2 = null;
Util.GetStartEndConnector(doc.GetElement(m_DivLst.First()) as Pipe, ref divspCon1, ref divepCon1);
Util.GetStartEndConnector(doc.GetElement(m_DivLst[1]) as Pipe, ref divspCon2, ref divepCon2);
//밸브 커넥터 구하기
List<Connector> ValConLst = Util.GetElementConnectors(fi);
//밸브 관경 파이프 관경으로 변경
ValConLst.First().Radius = pipelist[i].Diameter / 2.0;
doc.Regenerate();
//밸브커넥터와 가까운 파이프커넥터끼리 연결
foreach (Connector valCon in ValConLst)
{
//자르기 전 파이프 시작 끝점 거리 비교
double dist1 = valCon.Origin.DistanceTo(divspCon1.Origin);
double dist2 = valCon.Origin.DistanceTo(divepCon2.Origin);
if (dist1 < dist2)
{
divepCon1.Origin = valCon.Origin;
divepCon1.ConnectTo(valCon);
}
else
{
divspCon2.Origin = valCon.Origin;
divspCon2.ConnectTo(valCon);
}
}
cnt++;
}
}
//가지관들의 관경을 삽입해준다.
int intype = -1;
if (ai_type == 2)
intype = 2;
else
intype = 1;
if (ai_type == 4)
{
for (int i = 0; i < borlst.Length - 1; i++)
{
string Tm2p = string.Format("part{0}_dia", i + intype);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
sw = familyParam.Set(Unit.MMToFeet(borlst[i]));
//sw = familyParam.Set(Unit.CovertToAPI(borlst[i], DisplayUnitType.DUT_MILLIMETERS));
}
}
// 가지관이 많은데 사용자에게 보이는 문제점이 있어서 거리가 없는경우는 전부 한곳으로 겹치도록 처리
for (int i = hd_loc_dst.Length - 1; i <= 40; i++)
{
string Tm2p = string.Format("part_{0}", i);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
sw = familyParam.Set(Unit.MMToFeet(0));
//sw = familyParam.Set(Unit.CovertToAPI(0, DisplayUnitType.DUT_MILLIMETERS));
}
// 가지관이 총 40개가 있는데 상황에 따라서 보여주고 안보여 주고 하는 기능
for (int i = 1; i <= 40; i++)
{
string Tm2p = string.Format("PartVisible_{0}", i);
df = GetDefinition(familyInstance, Tm2p);
familyParam = familyInstance.get_Parameter(df);
if (i < hd_loc_dst.Length - 1) //2를 빼는 이유는 마지막 치수는 마지막 파이프 부터 끝쩜까지의 길이이기 때문에 뺀것이다. 그리고 또 하나는 꼬메소스에서 볼때 하나가 남기 때문에사용하지 않는 공간이기때문데 뺏다.
sw = familyParam.Set(1);
else
sw = familyParam.Set(0);
}
//트랩 커넥터 헤더증기에서만 보여줌
df = GetDefinition(familyInstance, "PartVisible_trap");
familyParam = familyInstance.get_Parameter(df);
familyParam.Set(1);
// 안전밸브 파이프 그리기
XYZ safeinpt = new XYZ(tttt[borlst.Length - 2 + Cntnum].Origin.X, tttt[borlst.Length - 2 + Cntnum].Origin.Y, (tttt[borlst.Length - 2 + Cntnum].Origin.Z + Unit.MMToFeet(150)));
//XYZ safeinpt = new XYZ(tttt[borlst.Length - 2 + Cntnum].Origin.X, tttt[borlst.Length - 2 + Cntnum].Origin.Y, (tttt[borlst.Length - 2 + Cntnum].Origin.Z + Unit.CovertToAPI(150, DisplayUnitType.DUT_MILLIMETERS)));
//Pipe pipes = uidoc.Document.Create.NewPipe(safeinpt, tttt[borlst.Length - 2 + Cntnum], pipeType);
Pipe pipes = Pipe.Create(doc, pSysType.Id, pipeType.Id, level.Id, tttt[borlst.Length - 2 + Cntnum].Origin, safeinpt);
//파이프와 헤더 몸통 커넥터 연결
List<Connector> pipesConLst = Util.GetElementConnectors(pipes);
foreach (Connector con in pipesConLst)
{
if (con.Origin.IsAlmostEqualTo(tttt[borlst.Length - 2 + Cntnum].Origin, Unit.MMToFeet(0.01)))
con.ConnectTo(tttt[borlst.Length - 2 + Cntnum]);
}
ChangePipeSize(pipes, 32);
//상황에 따라서 안전밸브의 삽입여부가 결정된다.
//if (ai_type == 2 || ai_type == 3 || ai_type == 4)
//{
//
// // 일단 밸브 패밀리가 로드 되어져 있는지를 보라
// List<FamilySymbol> fam = new List<FamilySymbol>();
// if (lang == LanguageType.English_USA || lang == LanguageType.English_GB)
// fam = getFamily("Mechanical Equipment");
// else if (lang == LanguageType.Korean)
// fam = getFamily("기계 장비");
//
// FamilySymbol valves = null;
//
// //패밀리의 갯수가 하나이상이면 사용자가 선택 할수 있도록 해줘야한다.
// if (fam.Count >= 1)
// {
// valve = LoadFamilys(str_Safepath);
// if (valve == null)
// {
// valve = getNameByFamily(Path.GetFileNameWithoutExtension(str_Safepath));
// }
//
//
// }
//
// if (fam.Count == 0)// 밸브 패밀리가 없다면 로드하라
// {
// valve = LoadFamilys(str_Safepath);
// }
//
// if (valve.IsActive == false)
// valve.Activate();
// FamilyInstance fi = uidoc.Document.Create.NewFamilyInstance(XYZ.Zero, valve, StructuralType.NonStructural);
//
// XYZ base1 = XYZ.Zero;
// XYZ base2 = -XYZ.BasisY;
//
// //uidoc.Document.Move(fi, new XYZ(safeinpt.X, safeinpt.Y, (safeinpt.Z + Unit.CovertToAPI(100, DisplayUnitType.DUT_MILLIMETERS))));
// ElementTransformUtils.MoveElement(uidoc.Document, fi.Id, new XYZ(safeinpt.X, safeinpt.Y, (safeinpt.Z + Unit.CovertToAPI(100, DisplayUnitType.DUT_MILLIMETERS))));
//
// ConnectorSet connectors = pipes.ConnectorManager.Connectors;
// Connector pipe_end = null;
//
// // 파이파의 커넥터중에 파이프의 끝나는검과 가장 가까운 커넥터를 얻어와라.
// double dist = double.MaxValue;
//
// foreach (Connector c in connectors)
// {
// XYZ p = c.Origin;
// XYZ valvept = new XYZ(tttt[borlst.Length - 2 + Cntnum].Origin.X, tttt[borlst.Length - 2 + Cntnum].Origin.Y, (tttt[borlst.Length - 2 + Cntnum].Origin.Z + Unit.CovertToAPI(150, DisplayUnitType.DUT_MILLIMETERS)));
// double d = p.DistanceTo(safeinpt);
//
// if (d < dist)
// {
// dist = d;
// pipe_end = c;
// }
// // break;
// }
//
//
//
// Connector first = null;
// Connector second = null;
//
//
// //밸브의 커넥터를 가져와라.
// ConnectorSet conns = fi.MEPModel.ConnectorManager.Connectors;
//
// // 밸브의 커넥터중에 파이프의 끝점과 가장 가까운 커넥터를 얻어와라.
// dist = double.MaxValue;
// foreach (Connector c in conns)
// {
// XYZ p = c.Origin;
// XYZ valvept = pipe_end.Origin;
// double d = p.DistanceTo(valvept);
//
// if (d < dist)
// {
// dist = d;
// first = c;
// }
// }
//
// // 밸브의 커넥터중 파이프의 끝점과 가장 먼 커넥터를 찾아라.
// foreach (Connector c in conns)
// {
// XYZ p = c.Origin;
// XYZ valvept = pipe_end.Origin;
// double d = p.DistanceTo(valvept);
//
// if (c != first)
// {
// second = c;
// break;
// }
//
// }
//
// // 커넥터를 연결해준다.
// df = GetDefinition(fi, "DI");
// familyParam = fi.get_Parameter(df);
// df = GetDefinition(fi.Symbol, "DI");
// familyParam = fi.Symbol.get_Parameter(df);
// sw = familyParam.Set(pipe_end.Radius * 2);
// pipe_end.ConnectTo(first);
//}
// 배수 밸브 파이프 그리기
XYZ outinpt = new XYZ(outvalveconn.Origin.X, outvalveconn.Origin.Y, (outvalveconn.Origin.Z - Unit.MMToFeet(150)));
//XYZ outinpt = new XYZ(outvalveconn.Origin.X, outvalveconn.Origin.Y, (outvalveconn.Origin.Z - Unit.CovertToAPI(150, DisplayUnitType.DUT_MILLIMETERS)));
//pipes = uidoc.Document.Create.NewPipe(outinpt, outvalveconn, pipeType);
pipes = Pipe.Create(doc, pSysType.Id, pipeType.Id, level.Id, outvalveconn.Origin, outinpt);
//파이프와 헤더 몸통 커넥터 연결
List<Connector> ConLst = Util.GetElementConnectors(pipes);
foreach (Connector con in ConLst)
{
if (con.Origin.IsAlmostEqualTo(outvalveconn.Origin, Unit.MMToFeet(0.01)))
con.ConnectTo(outvalveconn);
}
ChangePipeSize(pipes, 32);
//20210309 트랩 파이프 그리기 추가
// 트랩 파이프 그리기
XYZ trapInpt = new XYZ(trapvalveconn.Origin.X, trapvalveconn.Origin.Y, (trapvalveconn.Origin.Z - Unit.MMToFeet(150)));
pipes = Pipe.Create(doc, pSysType.Id, pipeType.Id, level.Id, trapvalveconn.Origin, trapInpt);
//파이프와 헤더 몸통 커넥터 연결
ConLst = Util.GetElementConnectors(pipes);
foreach (Connector con in ConLst)
{
if (con.Origin.IsAlmostEqualTo(trapvalveconn.Origin, Unit.MMToFeet(0.01)))
con.ConnectTo(trapvalveconn);
}
ChangePipeSize(pipes, 32);
uidoc.Document.Regenerate();
trans.Commit();
}
}
else
{
throw new Exception("Couldn't load ");
}
}
private double SL(double index1, double index2)
{
int i;
int n;
double dGet, val1, val2;
HeValue heval;
string s;
//수정 해야 할 부분 //yong 02.12 return값에 맞춰서 excel data핸들링하게 .....
n = (int)m_ArrValue.Count();
for (i = 0; i < n; i++)
{
heval = m_ArrValue[i];
val1 = Convert.ToDouble(heval.he);
val2 = Convert.ToDouble(heval.we);
if (((Math.Abs(val1 - index1) < 0.001 && Math.Abs(val2 - index2) < 0.001) ||
(Math.Abs(val1 - index2) < 0.001 && Math.Abs(val2 - index1) < 0.001)) && (val1 != 0.0f && val2 != 0.0f))
{
dGet = Convert.ToDouble(heval.val);
return dGet;
break;//
}
}
////////////////////////////
return 0.0f;
} // defun-end
private void FL(double index)
{
HdValue val;
double dHDDIA;
//HDDIA,BLTSIZE,BLTBORE,BLTNO,FLGID,BLTCENDST,FLGOD
//헤더지름,볼트 사이즈,구멍크기,구멍개수,플랜지 내경,볼트 중심간 거리 ,플랜지 외경
for (int i = 0; i < m_ArrHdValue.Count; i++)
{
val = m_ArrHdValue[i];
dHDDIA = Convert.ToDouble(val.HDDIA);
if (dHDDIA == index)
{
flst[0] = dHDDIA;
flst[1] = Convert.ToDouble(val.BLTSIZE);
flst[2] = Convert.ToDouble(val.BLTBORE);
flst[3] = Convert.ToDouble(val.BLTNO);
flst[4] = Convert.ToDouble(val.FLGID);
flst[5] = Convert.ToDouble(val.BLTCENDST);
flst[6] = Convert.ToDouble(val.FLGOD);
return;
}
}
} //defun-end
private int HDR_2D(double hd2, double chg2)
{
double dd1, dd2, dd3;
dd1 = 0.28 * hd2;
dd2 = 0.44 * hd2;
dd3 = 0.28 * hd2;
if (dd2 > chg2) return 0;
else
{
gd_List[0] = dd1;
gd_List[1] = dd2;
gd_List[2] = dd3;
return 2;
}
} // defun hdr-2d
private int HDR_3D(double hd2, double chg2)
{
double dd1, dd2, dd3, dd4;
dd1 = 0.13 * hd2;
dd2 = 0.37 * hd2;
dd3 = 0.37 * hd2;
dd4 = 0.13 * hd2;
if (dd2 > chg2) return 0;
else
{
gd_List[0] = dd1;
gd_List[1] = dd2;
gd_List[2] = dd3;
gd_List[3] = dd4;
return 3;
}
} // defun hdr-3d
private int HDR_4D(double hd2, double chg2)
{
double dd1, dd2, dd3, dd4, dd5;
dd1 = 0.095 * hd2;
dd2 = 0.27 * hd2;
dd3 = 0.27 * hd2;
dd4 = 0.27 * hd2;
dd5 = 0.095 * hd2;
if (dd2 > chg2) return 0;
else
{
gd_List[0] = dd1;
gd_List[1] = dd2;
gd_List[2] = dd3;
gd_List[3] = dd4;
gd_List[4] = dd5;
return 4;
}
} // defun hdr-4d
private int HDR_5D(double hd2, double chg2)
{
double dd1, dd2, dd3, dd4, dd5, dd6;
dd1 = 0.08 * hd2;
dd2 = 0.21 * hd2;
dd3 = 0.21 * hd2;
dd4 = 0.21 * hd2;
dd5 = 0.21 * hd2;
dd6 = 0.08 * hd2;
if (dd2 > chg2) return 0;
else
{
gd_List[0] = dd1;
gd_List[1] = dd2;
gd_List[2] = dd3;
gd_List[3] = dd4;
gd_List[4] = dd5;
gd_List[5] = dd6;
return 5;
}
} // defun hdr-2d
// 패밀리 존재 여부 검토
private List<FamilySymbol> getFamily(string categori)
{
List<FamilySymbol> familySymbol = new List<FamilySymbol>();
List<FamilyInstanceCreationData> fiCreationDatas =
new List<FamilyInstanceCreationData>();
ElementSet elementSet = null;
//Try to get a FamilySymbol
FilteredElementCollector collector = new FilteredElementCollector(m_revit.Application.ActiveUIDocument.Document);
ICollection<Element> collection = collector.OfClass(typeof(FamilySymbol)).ToElements();
FamilySymbol Symbol;
foreach (Element e in collection)
{
Symbol = e as FamilySymbol;
if (null != Symbol.Category)
{
if (categori == Symbol.Category.Name)
{
familySymbol.Add(Symbol);
}
}
}
return familySymbol;
}
// 패밀리 존재 여부 검토
private FamilySymbol getNameByFamily(string name)
{
List<FamilyInstanceCreationData> fiCreationDatas = new List<FamilyInstanceCreationData>();
ElementSet elementSet = null;
//Try to get a FamilySymbol
FilteredElementCollector collector = new FilteredElementCollector(m_revit.Application.ActiveUIDocument.Document);
ICollection<Element> collection = collector.OfClass(typeof(FamilySymbol)).ToElements();
FamilySymbol Symbol;
FamilySymbol target = null;
foreach (Element e in collection)
{
Symbol = e as FamilySymbol;
if (null != Symbol.Category)
{
if (name == Symbol.Family.Name)
{
// MessageBox.Show(Symbol.Family.Name);
target = Symbol;
break;
}
}
}
return target;
}
private FamilySymbol LoadFamilys(string famroot, string famname)
{
//string Tmp = System.Reflection.Assembly.GetExecutingAssembly().Location;
//Tmp = Tmp.Replace("\\KMBIM2019.dll", "");
string Tmp = Util.GetKMBIMLibraryFolder("Libraries\\Header");
// get the active view's level for beam creation
Level level = uidoc.Document.GetElement(uidoc.ActiveView.LevelId) as Level;
// load a family symbol from file
FamilySymbol gotSymbol = null;
String fileName = Tmp + famroot;// "\\data\\2010-0240312-글로브_밸브_(플랜지형).rfa";
// 아래의 이름은 패밀리 고유의 이름이다. 패밀리 작업할때 입력하게 되어있다.
String name = famname;//"2010-0240312-글로브_밸브_(플랜지형)";
FamilyInstance instance = null;
// 패밀리를 로드한다.
Family fam = null;
ElementType elemType = null;
//uidoc.Document.LoadFamilySymbol(fileName, "", out gotSymbol);
bool sw = uidoc.Document.LoadFamily(fileName, out fam);
if (sw == true)
{
/*foreach (FamilySymbol c in fam.Symbols)
{
gotSymbol = c;
}*/
ISet<ElementId> fam_ids = fam.GetFamilySymbolIds();
List<string> fam_sym_names = new List<string>();
if (fam_ids.Count() == 0) return null;
gotSymbol = (FamilySymbol)doc.GetElement(fam_ids.ElementAt(0));
}
return gotSymbol;
}
private FamilySymbol LoadFamilys(string FamilyPath)
{
// get the active view's level for beam creation
Level level = uidoc.Document.GetElement(uidoc.ActiveView.LevelId) as Level;
// load a family symbol from file
FamilySymbol gotSymbol = null;
String fileName = FamilyPath;// "\\data\\2010-0240312-글로브_밸브_(플랜지형).rfa";
// 아래의 이름은 패밀리 고유의 이름이다. 패밀리 작업할때 입력하게 되어있다.
String name = Path.GetFileNameWithoutExtension(FamilyPath);//"2010-0240312-글로브_밸브_(플랜지형)";
// 패밀리를 로드한다.
Family fam = null;
bool sw = uidoc.Document.LoadFamily(fileName, out fam);
if (sw == true)
{
ISet<ElementId> fam_ids = fam.GetFamilySymbolIds();
List<string> fam_sym_names = new List<string>();
if (fam_ids.Count() == 0) return null;
gotSymbol = (FamilySymbol)doc.GetElement(fam_ids.ElementAt(0));
}
return gotSymbol;
}
/// <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 void ChangePipeSize(Pipe pipe, double bore)
{
Parameter parameter = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
// string message = "Pipe diameter: " + parameter.AsValueString();
parameter.Set(Unit.MMToFeet(bore)); // set to 6"
//parameter.Set(Unit.CovertToAPI(bore, DisplayUnitType.DUT_MILLIMETERS)); // set to 6"
// message += "\nPipe diameter after set: " + parameter.AsValueString();
//MessageBox.Show(message, "Revit");
}
}
}