Client/Desktop/KMBIM3.0/KMBIM3.0_소스/Cmd/PipeRack/FixingBolt.cs

1279 lines
52 KiB
C#

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Autodesk.Revit.UI.Selection;
using System;
using System.Windows.Forms;
using KDCS.Utils;
using View = Autodesk.Revit.DB.View;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.Creation;
using KMBIM.Revit.Tools;
namespace KMBIM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class FixingBolt : IExternalCommand
{
internal class LevelComparer : IComparer<Autodesk.Revit.DB.Level>
{
public int Compare(Autodesk.Revit.DB.Level x, Autodesk.Revit.DB.Level y)
{
if (x == null && y == null)
{
return 0;
}
if (x == null)
{
return -1;
}
if (y == null)
{
return 1;
}
if (Util.fuzzyEqual(x.ProjectElevation, y.ProjectElevation))
{
return 0;
}
if (x.ProjectElevation < y.ProjectElevation)
{
return -1;
}
return 1;
}
}
UIApplication uiapp;
UIDocument uidoc;
Autodesk.Revit.DB.Document doc;
Autodesk.Revit.Creation.Application creApp;
Autodesk.Revit.Creation.Document creDoc;
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
uiapp = commandData.Application;
uidoc = uiapp.ActiveUIDocument;
Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
doc = uidoc.Document;
creApp = uiapp.Application.Create;
creDoc = doc.Create;
View view = doc.ActiveView;
int BoltType = 0, AttachDir = 0;
bool b_InsideAttach = true;
string m_SetLvlName = "";
LinkedFunction linkedFunction = new LinkedFunction();
try
{
if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
Form_FixingBolt dlg = new Form_FixingBolt();
dlg.revit = commandData;
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.Cancel) return Result.Cancelled;
BoltType = dlg.m_RadType;
AttachDir = dlg.m_RadAttach;
b_InsideAttach = dlg.b_Inside;
m_SetLvlName = dlg.m_LvlSet;
//U볼트 패밀리 로드
FamilySymbol bolt = LoadFamilys("U_bolt.rfa", null);
if (bolt == null)
bolt = getNameByFamily("U_bolt");
//가이드 슈 패밀리 로드
FamilySymbol shoe = LoadFamilys("Guide_Shoe.rfa", null);
if (shoe == null)
shoe = getNameByFamily("Guide_Shoe");
//기준면 부착
if (AttachDir == 0)
{
//설치 할 면 선택
//Reference FaceRef = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Face, new PlanarFaceSelectionFilter(doc), "볼트 설치할 배관 선택 : ");
Reference FaceRef = null;
PlanarFace pface = null;
linkedFunction.SelectFaceInLinkedFile(uiapp, out pface,out FaceRef);
//패밀리 인스턴스
FamilyInstance Rack = doc.GetElement(FaceRef) as FamilyInstance;
//XYZ locpt = (Rack.Location as LocationPoint).Point;
////선택한 면 Face로 변경
//GeometryObject geoObject = doc.GetElement(FaceRef).GetGeometryObjectFromReference(FaceRef);
////Face rface = geoObject as Face;
//PlanarFace pface = geoObject as PlanarFace;
while (true)
{
//설치할 파이프 선택
Reference PipeRef = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), "볼트 설치할 배관 선택 : ");
Pipe pickPipe = doc.GetElement(PipeRef) as Pipe;
Curve PipeCur = ((pickPipe.Location) as LocationCurve).Curve;
IntersectionResult interRes = PipeCur.Project(PipeRef.GlobalPoint);
XYZ insertPt = interRes.XYZPoint;
XYZ PipePt = insertPt;
XYZ PipeSp = null, PipeEp = null;
Util.GetStartEndPoint(pickPipe, ref PipeSp, ref PipeEp);
//파이프 방향
XYZ DirVec = (PipeEp - PipeSp).Normalize();
XYZ rDirVec = (PipeSp - PipeEp).Normalize();
//기준면과 파이프 방향이 맞지 않을 경우 작도 X
if (Rack != null)
{
Transform tr = Rack.GetTransform().Inverse;
if (pface.FaceNormal.IsAlmostEqualTo(tr.OfVector(DirVec))
|| pface.FaceNormal.IsAlmostEqualTo(tr.OfVector(rDirVec)))
{
MessageBox.Show("기준면과 파이프의 방향이 다릅니다.", "오류");
break;
}
}
else
{
if (pface.FaceNormal.IsAlmostEqualTo(DirVec)
|| pface.FaceNormal.IsAlmostEqualTo(rDirVec))
{
MessageBox.Show("기준면과 파이프의 방향이 다릅니다.", "오류");
break;
}
}
using (Transaction trans = new Transaction(doc))
{
trans.Start("process");
bolt.Activate();
shoe.Activate();
//기준면 배치 프로세스
bool b_tf = PickFaceProcess(FaceRef, PipeRef,pface, BoltType, b_InsideAttach, shoe, bolt);
if (b_tf == false) continue;
trans.Commit();
}
}//while end
}
else if (AttachDir == 1)//구조체 부착
{
while (true)
{
// 설치할 파이프 선택
Reference PipeRef = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), "볼트 설치할 배관 선택 : ");
Pipe pickPipe = doc.GetElement(PipeRef) as Pipe;
Curve PipeCur = ((pickPipe.Location) as LocationCurve).Curve;
IntersectionResult interRes = PipeCur.Project(PipeRef.GlobalPoint);
XYZ insertPt = interRes.XYZPoint;
XYZ PipePt = insertPt;
XYZ PipeSp = null, PipeEp = null;
Util.GetStartEndPoint(pickPipe, ref PipeSp, ref PipeEp);
//파이프 방향
XYZ DirVec = (PipeEp - PipeSp).Normalize();
XYZ rDirVec = (PipeSp - PipeEp).Normalize();
//Z값 기준
XYZ VecZ = XYZ.BasisZ;
using (Transaction trans = new Transaction(doc))
{
trans.Start("process");
bolt.Activate();
shoe.Activate();
//레벨 배치 프로세스
bool b_tf = StructualProcess(PipeRef, BoltType, shoe, bolt);
if (b_tf == false) continue;
trans.Commit();
}
}//while end
}
else if (AttachDir == 2)//레벨 부착
{
while (true)
{
// 설치할 파이프 선택
Reference PipeRef = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new PipeSelectionFilter(), "볼트 설치할 배관 선택 : ");
Pipe pickPipe = doc.GetElement(PipeRef) as Pipe;
Curve PipeCur = ((pickPipe.Location) as LocationCurve).Curve;
IntersectionResult interRes = PipeCur.Project(PipeRef.GlobalPoint);
XYZ insertPt = interRes.XYZPoint;
XYZ PipePt = insertPt;
XYZ PipeSp = null, PipeEp = null;
Util.GetStartEndPoint(pickPipe, ref PipeSp, ref PipeEp);
//파이프 방향
XYZ DirVec = (PipeEp - PipeSp).Normalize();
XYZ rDirVec = (PipeSp - PipeEp).Normalize();
//Z값 기준
XYZ VecZ = XYZ.BasisZ;
using (Transaction trans = new Transaction(doc))
{
trans.Start("process");
bolt.Activate();
shoe.Activate();
//레벨 배치 프로세스
bool b_tf = LevelProcess(PipeRef, m_SetLvlName, BoltType, shoe, bolt);
if (b_tf == false) continue;
trans.Commit();
}
}//while end
}
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
return Result.Succeeded;
}
//배치기준 부착면 선택
public bool PickFaceProcess(Reference FaceRef, Reference PipeRef,PlanarFace pFace, int BoltType, bool b_InsideAttach, FamilySymbol shoe, FamilySymbol bolt)
{
bool b_TF = true;
FamilyInstance family = null;
IntersectionResult interRes = new IntersectionResult();
//선택한 면 Face로 변경
//GeometryObject geoObject = doc.GetElement(FaceRef).GetGeometryObjectFromReference(FaceRef);
//Face rface = geoObject as Face;
//PlanarFace pface = geoObject as PlanarFace;
Pipe PickPipe = doc.GetElement(PipeRef) as Pipe;
Curve PipeCur = (PickPipe.Location as LocationCurve).Curve;
interRes = PipeCur.Project(PipeRef.GlobalPoint);
XYZ insertPt = interRes.XYZPoint;
XYZ PipePt = insertPt;
XYZ PipeSp = null, PipeEp = null;
Util.GetStartEndPoint(PickPipe, ref PipeSp, ref PipeEp);
Element elem = doc.GetElement(FaceRef);
if(elem is FamilyInstance)//패밀리 인스터스일 때
{
//Face Curve와 파이프 Curve의 교차점 리스트 구하기
List<XYZ> interPtLst = getFamilyInterPoint(FaceRef, PickPipe);
//경계구역 내 설치 체크박스
if (b_InsideAttach == true)
{
//선택한 점이 면 위에 있는지 확인
if (GetPointOnLine(interPtLst, PipeRef) == false)
{
MessageBox.Show("기준 면 바깥 점을 선택하였습니다.", "오류");
b_TF = false;
return b_TF;
}
////교차점 리스트 중간점 구하기
//insertPt = Util.Polar(interPtLst[0], interPtLst[0], interPtLst[1], interPtLst[0].DistanceTo(interPtLst[1]) / 2.0);
Curve PickFaceCur = Line.CreateBound(interPtLst[0], interPtLst[1]);
interRes = PickFaceCur.Project(insertPt);
insertPt = interRes.XYZPoint;
}
else
{
Curve PickFaceCur = Line.CreateBound(interPtLst[0], interPtLst[1]);
XYZ FaceInterPt = Util.GetPointOnLine(PickFaceCur, insertPt);
interRes = PipeCur.Project(FaceInterPt);
XYZ PipeOnPt = interRes.XYZPoint;
insertPt = Util.Polar(FaceInterPt, PipeOnPt, PipePt, PipeOnPt.DistanceTo(PipePt));
//Util.Pyosi(doc, PipeOnPt, 0);
}
}
//호스트 객체 or 링크객체일 때
else
{
//경계구역 내 설치 체크박스
if (b_InsideAttach == true)
{
interRes = pFace.Project(insertPt);
if (interRes == null)
{
MessageBox.Show("기준 면 바깥 점을 선택하였습니다.", "오류");
b_TF = false;
return b_TF;
}
insertPt = interRes.XYZPoint;
}
else
{
//경계구역 외 설치
XYZ FGlobalPt = FaceRef.GlobalPoint;
//기준면 선택시 GlobalPoint와 파이프 Line의 가까운 점
interRes = PipeCur.Project(FGlobalPt);
XYZ PipeDirPt = interRes.XYZPoint;
interRes = pFace.Project(PipeDirPt);
XYZ FaceDirPt = interRes.XYZPoint;
double Pipe2FaceDst = PipeDirPt.DistanceTo(FaceDirPt);
insertPt = Util.Polar(insertPt, PipeDirPt, FaceDirPt, PipeDirPt.DistanceTo(FaceDirPt));
//Util.Pyosi(doc, aa, 0);
}
}
//패밀리 생성
if (BoltType == 0)
{
//파이프 단열제 두께
double insulThk = Util.GetPipeInsulationThickness(doc, PickPipe);
//가이드 슈일 경우 중간점과 파이프
interRes = PipeCur.Project(insertPt);
XYZ ShoeInsertPt = interRes.XYZPoint;
if (ShoeInsertPt.DistanceTo(insertPt) - PickPipe.Diameter / 2.0 - insulThk / 2.0 < Unit.MMToFeet(6))
{
MessageBox.Show("기준면과 파이프 사이의 거리가 좁습니다.", "오류");
b_TF = false;
}
family = doc.Create.NewFamilyInstance(FaceRef, ShoeInsertPt, (PipeSp - PipeEp).Normalize(), shoe);
}
else
family = doc.Create.NewFamilyInstance(FaceRef, insertPt, (PipeSp - PipeEp).Normalize(), bolt);
//패밀리 업데이트
doc.Regenerate();
//Util.Pyosi(doc, PipePt, 0);
//Util.Pyosi(doc, insertPt, 0);
//파이프와 볼트 삽입점의 교차점
interRes = PipeCur.Project(insertPt);
XYZ PipeInterPt = interRes.XYZPoint;
//볼트 옵션 변경/
SetFaceBoltOpt(FaceRef, family, BoltType, PickPipe, PipeInterPt.DistanceTo(insertPt));
//XYZ zVec = (PipeSp - PipeEp).Normalize().DotProduct()
XYZ zVec = new XYZ(0, 0, 1);
return b_TF;
}
//배치기준 구조체
public bool StructualProcess(Reference PipeRef, int BoltType, FamilySymbol shoe, FamilySymbol bolt)
{
bool b_TF = true;
FamilyInstance family = null;
IntersectionResult interRes = new IntersectionResult();
//파이프-구조체 거리
double Pipe2StructualDist = 0;
Reference structRef = null;
Level structLevel = null;
GetClosestStructrualElevation(PipeRef, out Pipe2StructualDist, out structRef, out structLevel);
Pipe PickPipe = doc.GetElement(PipeRef) as Pipe;
Curve PipeCur = (PickPipe.Location as LocationCurve).Curve;
interRes = PipeCur.Project(PipeRef.GlobalPoint);
//선택 파이프 점으로 파이프 중심점 구하기
XYZ insertPt = interRes.XYZPoint;
XYZ PipePt = insertPt;
XYZ PipeSp = null, PipeEp = null;
Util.GetStartEndPoint(PickPipe, ref PipeSp, ref PipeEp);
//참조평면 생성
XYZ p2 = new XYZ(insertPt.X + Unit.MMToFeet(10), insertPt.Y, insertPt.Z);
XYZ p1 = new XYZ(insertPt.X, insertPt.Y, insertPt.Z);
XYZ p3 = new XYZ(insertPt.X, insertPt.Y + Unit.MMToFeet(10), insertPt.Z);
ReferencePlane referPlane = doc.Create.NewReferencePlane2(p3, p1, p2, doc.ActiveView);
//doc.Create.NewReferencePlane()
//구조체가 없는 경우 참조평면으로
if(structRef == null)
{
if (BoltType == 0)
family = doc.Create.NewFamilyInstance(referPlane.GetReference(), insertPt, (PipeEp - PipeSp).Normalize(), shoe);
else
family = doc.Create.NewFamilyInstance(referPlane.GetReference(), insertPt, (PipeEp - PipeSp).Normalize(), bolt);
family.IsWorkPlaneFlipped = true;
}
else
{//구조체 존재할 경우
if (BoltType == 0)
family = doc.Create.NewFamilyInstance(structRef, insertPt, (PipeEp - PipeSp).Normalize(), shoe);
else
family = doc.Create.NewFamilyInstance(structRef, insertPt, (PipeEp - PipeSp).Normalize(), bolt);
}
//family.IsWorkPlaneFlipped = true;
doc.Regenerate();
SetStructBoltOpt(family, BoltType, PickPipe, structLevel, Pipe2StructualDist);
return b_TF;
}
//배치기준 레벨
public bool LevelProcess(Reference PipeRef, string setLevelName, int BoltType, FamilySymbol shoe, FamilySymbol bolt)
{
bool b_TF = true;
FamilyInstance family = null;
IntersectionResult interRes = new IntersectionResult();
Pipe PickPipe = doc.GetElement(PipeRef) as Pipe;
Curve PipeCur = (PickPipe.Location as LocationCurve).Curve;
interRes = PipeCur.Project(PipeRef.GlobalPoint);
//선택 파이프 점으로 파이프 중심점 구하기
XYZ insertPt = interRes.XYZPoint;
XYZ PipePt = insertPt;
XYZ PipeSp = null, PipeEp = null;
Util.GetStartEndPoint(PickPipe, ref PipeSp, ref PipeEp);
//레벨 찾기
Level m_SetLevel = Util.GetLevel(doc, setLevelName);
if (m_SetLevel.Elevation - PickPipe.ReferenceLevel.Elevation - PickPipe.LevelOffset < 0)
{
MessageBox.Show("배치기준 레벨보다 파이프가 더 높이 있습니다.", "오류");
return b_TF = false;
}
//참조평면 생성
XYZ p2 = new XYZ(insertPt.X + Unit.MMToFeet(10), insertPt.Y, insertPt.Z);
XYZ p1 = new XYZ(insertPt.X, insertPt.Y, insertPt.Z);
XYZ p3 = new XYZ(insertPt.X, insertPt.Y + Unit.MMToFeet(10), insertPt.Z);
ReferencePlane referPlane = doc.Create.NewReferencePlane2(p3, p1, p2, doc.ActiveView);
//doc.Create.NewReferencePlane()
if (BoltType == 0)
family = doc.Create.NewFamilyInstance(referPlane.GetReference(), insertPt, (PipeEp - PipeSp).Normalize(), shoe);
else
family = doc.Create.NewFamilyInstance(referPlane.GetReference(), insertPt, (PipeEp - PipeSp).Normalize(), bolt);
family.IsWorkPlaneFlipped = true;
doc.Regenerate();
SetLevelBoltOpt(family, BoltType, PickPipe, m_SetLevel);
return b_TF;
}
public bool GetPointOnLine(List<XYZ> ptLst, Reference PickPipeRef)
{
//if (ptLst.Count != 2) return;
bool b_tf = true;
Pipe pipe = doc.GetElement(PickPipeRef) as Pipe;
Curve PipeCur = (pipe.Location as LocationCurve).Curve;
IntersectionResult interRes = new IntersectionResult();
interRes = PipeCur.Project(PickPipeRef.GlobalPoint);
XYZ PickPt = interRes.XYZPoint;
interRes = PipeCur.Project(ptLst[0]);
XYZ CurSp = interRes.XYZPoint;
interRes = PipeCur.Project(ptLst[1]);
XYZ CurEp = interRes.XYZPoint;
//Util.Pyosi(doc, PickPt, 0);
//Util.Pyosi(doc, CurSp, 0);
//Util.Pyosi(doc, CurEp, 0);
double totalDist = CurSp.DistanceTo(CurEp);
double ADist = PickPt.DistanceTo(CurSp);
double BDist = PickPt.DistanceTo(CurEp);
if ((ADist + BDist) - totalDist < Unit.MMToFeet(0.00001))
b_tf = true;
else
b_tf = false;
return b_tf;
}
public List<XYZ> getFamilyInterPoint(Reference FaceRef, Pipe PickPipe)
{
Element elem = doc.GetElement(FaceRef);
FamilyInstance family = elem as FamilyInstance;
GeometryObject geoObj = elem.GetGeometryObjectFromReference(FaceRef);
PlanarFace pface = geoObj as PlanarFace;
if (family == null || pface == null) return null;
Curve PipeCur = (PickPipe.Location as LocationCurve).Curve;
Transform tr = family.GetTransform();
Transform InverseTr = tr.Inverse;
IList<CurveLoop> curveloops = pface.GetEdgesAsCurveLoops();
//curve 교차점 리스트
List<XYZ> interPtLst = new List<XYZ>();
foreach (var curveloop in curveloops)
{
//if (trRack == null) break;
foreach (Curve curve in curveloop)
{
//커브 시작 끝점 z=0으로 해서 intersection 구하기
Curve TrCur = curve.CreateTransformed(tr);
Curve PipeCurZ0 = LinePointZ0(PipeCur);
Curve TrCurZ0 = LinePointZ0(TrCur);
//Util.Pyosi(doc, PipeCurZ0.GetEndPoint(0), 0);
//Util.Pyosi(doc, TrCurZ0.GetEndPoint(0), 0);
IntersectionResultArray InterResArr = new IntersectionResultArray();
PipeCurZ0.Intersect(TrCurZ0, out InterResArr);
//PipeCur.Intersect(TrCur, out InterResArr);
if (InterResArr == null) continue;
foreach (IntersectionResult interRes in InterResArr)
{
IntersectionResult TrInter = TrCur.Project(interRes.XYZPoint);
if (TrInter == null) continue;
interPtLst.Add(TrInter.XYZPoint);
//Util.Pyosi(doc, TrInter.XYZPoint, 0);
}
}
}
return interPtLst;
}
public Curve LinePointZ0(Curve curve)
{
XYZ spt = new XYZ(curve.GetEndPoint(0).X, curve.GetEndPoint(0).Y, 0);
XYZ ept = new XYZ(curve.GetEndPoint(1).X, curve.GetEndPoint(1).Y, 0);
Curve newCur = Line.CreateBound(spt, ept) as Curve;
return newCur;
}
public void SetFaceBoltOpt(Reference FaceRef, FamilyInstance bolt, int BoltType, Pipe pickPipe, double dst_Face2Pipe)
{
GeometryObject geoObject = doc.GetElement(FaceRef).GetGeometryObjectFromReference(FaceRef);
PlanarFace pface = geoObject as PlanarFace;
Definition df = null;
//파이프 단열제 두께
double insulThk = Util.GetPipeInsulationThickness(doc, pickPipe);
//가이드 슈 옵션 설정
if (BoltType == 0)
{
// 가이드 슈 간격 띄우기
double m_ShoeOffset = 0;
Parameter paramOffset = bolt.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
if (paramOffset != null)
{
//paramOffset.Set(pickPipe.LevelOffset + pickPipe.ReferenceLevel.Elevation);
//m_ShoeOffset = pickPipe.LevelOffset + pickPipe.ReferenceLevel.Elevation;
paramOffset.Set(dst_Face2Pipe);
m_ShoeOffset = dst_Face2Pipe;
}
//관경 변경
df = GetDefinition(bolt, "GuideShoeCoverInRad");
if (df != null)
{
Parameter paramCoverRad = bolt.get_Parameter(df);
if (paramCoverRad != null)
paramCoverRad.Set(pickPipe.Diameter / 2.0 + insulThk);
}
//커넥터 관경 변경
df = GetDefinition(bolt, "ConRad");
if (df != null)
{
Parameter paramConRad = bolt.get_Parameter(df);
if (paramConRad != null)
paramConRad.Set(pickPipe.Diameter / 2.0 + insulThk);
}
//슈 두께 3mm 고정
double m_ShoeThk = 0;
df = GetDefinition(bolt, "GuideShoeCoverThk");
if (df != null)
{
Parameter paramCoverThk = bolt.get_Parameter(df);
if (paramCoverThk != null)
{
paramCoverThk.Set(Unit.MMToFeet(3));
m_ShoeThk = Unit.MMToFeet(3);
}
}
//판 두께
df = GetDefinition(bolt, "SupportThk");
if (df != null)
{
Parameter paramPlateThk = bolt.get_Parameter(df);
if (paramPlateThk != null)
paramPlateThk.Set(Unit.MMToFeet(3));
}
////가대 간격띄우기 값
//double m_RackOffset = 0;
//Parameter paramRackOffset = Rack.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
//m_RackOffset = paramRackOffset.AsDouble();
//슈 지지대 높이
df = GetDefinition(bolt, "SupportHeight");
if (df != null)
{
Parameter paramSupportHgt = bolt.get_Parameter(df);
if (paramSupportHgt != null)
paramSupportHgt.Set(m_ShoeOffset - m_ShoeThk * 2 - (pickPipe.Diameter / 2.0 + insulThk));
}
//슈 지지대 높이가 음수면 실행 X
//if (m_ShoeOffset - m_ShoeThk * 2 - (pickPipe.Diameter / 2.0 + insulThk) < 0) b_tf = false;
}
else//U-볼트 옵션 설정
{
//관경
df = GetDefinition(bolt, "Diameter");
if (df != null)
{
Parameter paramDia = bolt.get_Parameter(df);
if (paramDia != null)
paramDia.Set(pickPipe.Diameter + insulThk * 2);
}
double boltDia = 0;
double m_PipeDia = Unit.FeetToMM(pickPipe.Diameter + insulThk * 2);
if (m_PipeDia >= 15 && m_PipeDia <= 50)
boltDia = Unit.MMToFeet(10);
else if (m_PipeDia >= 65 && m_PipeDia <= 90)
boltDia = Unit.MMToFeet(12);
else if (m_PipeDia > 90 && m_PipeDia <= 175)
boltDia = Unit.MMToFeet(16);
else if (m_PipeDia > 175 && m_PipeDia <= 250)
boltDia = Unit.MMToFeet(20);
else if (m_PipeDia > 250 && m_PipeDia <= 400)
boltDia = Unit.MMToFeet(24);
else if (m_PipeDia > 400 && m_PipeDia <= 500)
boltDia = Unit.MMToFeet(30);
else if (m_PipeDia > 500)
boltDia = Unit.MMToFeet(32);
else
boltDia = Unit.MMToFeet(8);
//U볼트 두께
df = GetDefinition(bolt, "Bolt_Diameter");
if(df != null)
{
Parameter paramBoltDia = bolt.get_Parameter(df);
if (paramBoltDia != null)
paramBoltDia.Set(boltDia);
}
//// U볼트 간격 띄우기
//double m_BoltOffset = 0;
//Parameter paramOffset = bolt.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
//if (paramOffset != null)
// m_BoltOffset = paramOffset.AsDouble() - pickPipe.ReferenceLevel.Elevati
//
// n;
//support 높이
df = GetDefinition(bolt, "Support_Height");
if(df != null)
{
Parameter paramSupportHgt = bolt.get_Parameter(df);
if (paramSupportHgt != null)
{
paramSupportHgt.Set(dst_Face2Pipe);
}
}
}
}
public void SetLevelBoltOpt(FamilyInstance bolt, int BoltType, Pipe pickPipe, Level setLevel)
{
Definition df = null;
//파이프 단열제 두께
double insulThk = Util.GetPipeInsulationThickness(doc, pickPipe);
//가이드 슈 옵션 설정
if (BoltType == 0)
{
//관경 변경
df = GetDefinition(bolt, "GuideShoeCoverInRad");
if (df != null)
{
Parameter paramCoverRad = bolt.get_Parameter(df);
if (paramCoverRad != null)
paramCoverRad.Set(pickPipe.Diameter / 2.0 + insulThk);
}
//커넥터 관경 변경
df = GetDefinition(bolt, "ConRad");
if (df != null)
{
Parameter paramConRad = bolt.get_Parameter(df);
if (paramConRad != null)
paramConRad.Set(pickPipe.Diameter / 2.0 + insulThk);
}
//슈 두께 3mm 고정
double m_ShoeThk = 0;
df = GetDefinition(bolt, "GuideShoeCoverThk");
if (df != null)
{
Parameter paramCoverThk = bolt.get_Parameter(df);
if (paramCoverThk != null)
{
paramCoverThk.Set(Unit.MMToFeet(3));
m_ShoeThk = Unit.MMToFeet(3);
}
}
////가대 간격띄우기 값
//double m_RackOffset = 0;
//Parameter paramRackOffset = Rack.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
//m_RackOffset = paramRackOffset.AsDouble();
//판 두께
df = GetDefinition(bolt, "SupportThk");
if (df != null)
{
Parameter paramPlateThk = bolt.get_Parameter(df);
if (paramPlateThk != null)
paramPlateThk.Set(Unit.MMToFeet(3));
}
//슈 지지대 높이
df = GetDefinition(bolt, "SupportHeight");
if (df != null)
{
Parameter paramSupportHgt = bolt.get_Parameter(df);
if (paramSupportHgt != null)
{
//배치 레벨 높이 - 파이프 참조레벨 높이 - 파이프 간격띄우기 - 파이프 반지름 - 단열재 반지름 - 가이드 슈 두께 X 2
double m_SupportHgt = setLevel.Elevation - pickPipe.ReferenceLevel.Elevation - pickPipe.LevelOffset
- pickPipe.Diameter / 2.0 - insulThk - m_ShoeThk * 2;
paramSupportHgt.Set(m_SupportHgt);
}
}
//슈 지지대 높이가 음수면 실행 X
//if (m_ShoeOffset - m_ShoeThk * 2 - (pickPipe.Diameter / 2.0 + insulThk) < 0) b_tf = false;
}
else//U-볼트 옵션 설정
{
//관경
df = GetDefinition(bolt, "Diameter");
if (df != null)
{
Parameter paramDia = bolt.get_Parameter(df);
if (paramDia != null)
paramDia.Set(pickPipe.Diameter + insulThk * 2);
}
double boltDia = 0;
double m_PipeDia = Unit.FeetToMM(pickPipe.Diameter + insulThk * 2);
if (m_PipeDia >= 15 && m_PipeDia <= 50)
boltDia = Unit.MMToFeet(10);
else if (m_PipeDia >= 65 && m_PipeDia <= 90)
boltDia = Unit.MMToFeet(12);
else if (m_PipeDia > 90 && m_PipeDia <= 175)
boltDia = Unit.MMToFeet(16);
else if (m_PipeDia > 175 && m_PipeDia <= 250)
boltDia = Unit.MMToFeet(20);
else if (m_PipeDia > 250 && m_PipeDia <= 400)
boltDia = Unit.MMToFeet(24);
else if (m_PipeDia > 400 && m_PipeDia <= 500)
boltDia = Unit.MMToFeet(30);
else if (m_PipeDia > 500)
boltDia = Unit.MMToFeet(32);
else
boltDia = Unit.MMToFeet(8);
//U볼트 두께
df = GetDefinition(bolt, "Bolt_Diameter");
if (df != null)
{
Parameter paramBoltDia = bolt.get_Parameter(df);
if (paramBoltDia != null)
paramBoltDia.Set(boltDia);
}
// U볼트 간격 띄우기
Parameter paramOffset = bolt.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
if (paramOffset != null)
{
double m_boltOffset = -(setLevel.Elevation - pickPipe.ReferenceLevel.Elevation - pickPipe.LevelOffset);
paramOffset.Set(m_boltOffset);
}
//support 높이
df = GetDefinition(bolt, "Support_Height");
if (df != null)
{
Parameter paramSupportHgt = bolt.get_Parameter(df);
if (paramSupportHgt != null)
{
double m_SupportHgt = setLevel.Elevation - pickPipe.ReferenceLevel.Elevation - pickPipe.LevelOffset;
paramSupportHgt.Set(m_SupportHgt);
}
}
}
}
public void SetStructBoltOpt(FamilyInstance bolt, int BoltType, Pipe pickPipe, Level setLevel, double SupportDst)
{
Definition df = null;
//파이프 단열제 두께
double insulThk = Util.GetPipeInsulationThickness(doc, pickPipe);
//가이드 슈 옵션 설정
if (BoltType == 0)
{
//관경 변경
df = GetDefinition(bolt, "GuideShoeCoverInRad");
if (df != null)
{
Parameter paramCoverRad = bolt.get_Parameter(df);
if (paramCoverRad != null)
paramCoverRad.Set(pickPipe.Diameter / 2.0 + insulThk);
}
//커넥터 관경 변경
df = GetDefinition(bolt, "ConRad");
if (df != null)
{
Parameter paramConRad = bolt.get_Parameter(df);
if (paramConRad != null)
paramConRad.Set(pickPipe.Diameter / 2.0 + insulThk);
}
//슈 두께 3mm 고정
double m_ShoeThk = 0;
df = GetDefinition(bolt, "GuideShoeCoverThk");
if (df != null)
{
Parameter paramCoverThk = bolt.get_Parameter(df);
if (paramCoverThk != null)
{
paramCoverThk.Set(Unit.MMToFeet(3));
m_ShoeThk = Unit.MMToFeet(3);
}
}
////가대 간격띄우기 값
//double m_RackOffset = 0;
//Parameter paramRackOffset = Rack.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
//m_RackOffset = paramRackOffset.AsDouble();
//판 두께
df = GetDefinition(bolt, "SupportThk");
if (df != null)
{
Parameter paramPlateThk = bolt.get_Parameter(df);
if (paramPlateThk != null)
paramPlateThk.Set(Unit.MMToFeet(3));
}
//슈 지지대 높이
df = GetDefinition(bolt, "SupportHeight");
if (df != null)
{
Parameter paramSupportHgt = bolt.get_Parameter(df);
if (paramSupportHgt != null && setLevel != null)
{
double SupportHgt = 0;
if (SupportDst == 0)
{
//배치 레벨 높이 - 파이프 참조레벨 높이 - 파이프 간격띄우기 - 파이프 반지름 - 단열재 반지름 - 가이드 슈 두께 X 2
SupportHgt = setLevel.Elevation - pickPipe.ReferenceLevel.Elevation - pickPipe.LevelOffset
- pickPipe.Diameter / 2.0 - insulThk - m_ShoeThk * 2;
}
else
{
SupportHgt = SupportDst - pickPipe.Diameter / 2.0 - insulThk - m_ShoeThk * 2;
}
paramSupportHgt.Set(SupportHgt);
}
}
//슈 지지대 높이가 음수면 실행 X
//if (m_ShoeOffset - m_ShoeThk * 2 - (pickPipe.Diameter / 2.0 + insulThk) < 0) b_tf = false;
}
else//U-볼트 옵션 설정
{
//관경
df = GetDefinition(bolt, "Diameter");
if (df != null)
{
Parameter paramDia = bolt.get_Parameter(df);
if (paramDia != null)
paramDia.Set(pickPipe.Diameter + insulThk * 2);
}
double boltDia = 0;
double m_PipeDia = Unit.FeetToMM(pickPipe.Diameter + insulThk * 2);
if (m_PipeDia >= 15 && m_PipeDia <= 50)
boltDia = Unit.MMToFeet(10);
else if (m_PipeDia >= 65 && m_PipeDia <= 90)
boltDia = Unit.MMToFeet(12);
else if (m_PipeDia > 90 && m_PipeDia <= 175)
boltDia = Unit.MMToFeet(16);
else if (m_PipeDia > 175 && m_PipeDia <= 250)
boltDia = Unit.MMToFeet(20);
else if (m_PipeDia > 250 && m_PipeDia <= 400)
boltDia = Unit.MMToFeet(24);
else if (m_PipeDia > 400 && m_PipeDia <= 500)
boltDia = Unit.MMToFeet(30);
else if (m_PipeDia > 500)
boltDia = Unit.MMToFeet(32);
else
boltDia = Unit.MMToFeet(8);
//U볼트 두께
df = GetDefinition(bolt, "Bolt_Diameter");
if (df != null)
{
Parameter paramBoltDia = bolt.get_Parameter(df);
if (paramBoltDia != null)
paramBoltDia.Set(boltDia);
}
//support 높이
df = GetDefinition(bolt, "Support_Height");
if (df != null)
{
Parameter paramSupportHgt = bolt.get_Parameter(df);
if (paramSupportHgt != null)
{
if (setLevel == null)
{
double Radius = pickPipe.Diameter / 2.0;
paramSupportHgt.Set(Radius);
}
else
paramSupportHgt.Set(SupportDst);
}
}
// U볼트 간격 띄우기
Parameter paramOffset = bolt.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
if (paramOffset != null)
{
if (SupportDst == 0)//SupportDst가 0 이면 구조체가 없어 레벨 값으로 간격띄우기 값 조정해야 함.
{
if (setLevel != null)
{
double m_boltOffset = -(setLevel.Elevation - pickPipe.ReferenceLevel.Elevation - pickPipe.LevelOffset);
paramOffset.Set(m_boltOffset);
}else
paramOffset.Set(-pickPipe.Diameter/2.0);
}
else
paramOffset.Set(0);
}
}
}
//파이프에서 가까운 구조체 높이 구하기
public void GetClosestStructrualElevation(Reference pickPipeRef, out double elevation, out Reference structRefer, out Level level)
{
elevation = 0;
structRefer = null;
level = null;
Level NextLevel = null;
Line line = (((doc.GetElement(pickPipeRef)) as Pipe).Location as LocationCurve).Curve as Line;
//레벨 가져오기
List<Level> levels = getLevel();
XYZ location = pickPipeRef.GlobalPoint;
if (line == null || levels.Count == 0) return;
IntersectionResult intersectionResult = line.Project(pickPipeRef.GlobalPoint);
if (intersectionResult == null) return;
int num = 0;
for (num = 0; num < levels.Count && !(location.Z < levels[num].ProjectElevation); num++)
{
}
if (num == 0)
{
level = levels[0];
}
else
{
level = levels[num - 1];
}
double locElevation = location.Z - level.ProjectElevation;
double CloseElevation = double.NaN;
//using(Transaction trans = new Transaction(doc))
//{
// trans.Start("1");
ReferenceIntersector referInterSector = GetReferenceIntersector();
if (referInterSector == null) return;
//Z값 위쪽으로
XYZ direction = new XYZ(0.0, 0.0, 1);
ReferenceWithContext referenceWithContext = referInterSector.FindNearest(location, direction);
if (referenceWithContext == null)
{
level = NextLevel;
return;
}
Reference refer = referenceWithContext.GetReference();
if (refer == null) return;
CloseElevation = refer.GlobalPoint.Z - intersectionResult.XYZPoint.Z;
elevation = CloseElevation;
structRefer = refer;
// trans.Commit();
//}
}
private ReferenceIntersector GetReferenceIntersector()
{
Autodesk.Revit.DB.ReferenceIntersector referenceIntersect = null;
if (referenceIntersect != null)
{
return null;
}
List<BuiltInCategory> list = new List<BuiltInCategory>();
list.Add(BuiltInCategory.OST_Floors);
list.Add(BuiltInCategory.OST_Roofs);
list.Add(BuiltInCategory.OST_StructuralFraming);
list.Add(BuiltInCategory.OST_StructuralTruss);
list.Add(BuiltInCategory.OST_StructuralFoundation);
list.Add(BuiltInCategory.OST_Stairs);
string viewName = "View3DBolt";
View3D view3D = null;
FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
FilteredElementIterator iter = filteredElementCollector.OfClass(typeof(View3D)).GetElementIterator();
iter.Reset();
while (iter.MoveNext())
{
View3D tmp_view3d = iter.Current as View3D;
if (null != tmp_view3d && !tmp_view3d.IsTemplate)
{
if (tmp_view3d.Name == viewName)
{
view3D = tmp_view3d;
break;
}
}
}
if (view3D == null)
{
IEnumerable<ViewFamilyType> viewFamilyTypes = from elem in new
FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType))
let type = elem as ViewFamilyType
where type.ViewFamily == ViewFamily.ThreeDimensional
select type;
view3D = View3D.CreateIsometric(doc, viewFamilyTypes.First().Id);
if (view3D == null)
{
return null;
}
view3D.Name = viewName;
foreach (BuiltInCategory item in list)
{
Util.SetCategoryHidden(doc, view3D, item);
}
if (view3D.CanModifyViewDiscipline())
{
view3D.Discipline = ViewDiscipline.Coordination;
}
if (view3D.CanModifyDetailLevel())
{
view3D.DetailLevel = Autodesk.Revit.DB.ViewDetailLevel.Fine;
}
if (view3D.CanModifyDisplayStyle())
{
view3D.DisplayStyle = DisplayStyle.Realistic;
}
view3D.CropBoxActive = false;
view3D.CropBoxVisible = false;
view3D.IsSectionBoxActive = false;
}
List<Autodesk.Revit.DB.ElementFilter> list2 = new List<Autodesk.Revit.DB.ElementFilter>();
foreach (BuiltInCategory item2 in list)
{
list2.Add(new Autodesk.Revit.DB.ElementCategoryFilter(item2));
}
referenceIntersect = new Autodesk.Revit.DB.ReferenceIntersector(new LogicalOrFilter(list2), FindReferenceTarget.Face, view3D);
referenceIntersect.FindReferencesInRevitLinks = true;
return referenceIntersect;
}
private List<Level> getLevel()
{
List<Level> LvlList = new List<Level>();
foreach(Level item in new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).OfType<Level>())
{
if (item != null)
LvlList.Add(item);
}
//레벨 높이별로 정렬
LvlList.Sort(new LevelComparer());
return LvlList;
}
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;
}
// 패밀리 존재 여부 검토
private FamilySymbol getNameByFamily(string name)
{
List<FamilyInstanceCreationData> fiCreationDatas = new List<FamilyInstanceCreationData>();
//Try to get a FamilySymbol
FilteredElementCollector collector = new FilteredElementCollector(doc);
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 versionNumber = doc.Application.VersionNumber.ToString();
//string Tmp = System.Reflection.Assembly.GetExecutingAssembly().Location;
//Tmp = Tmp.Replace("\\KMBIM2019.dll", "");
string Tmp = Util.GetKMBIMLibraryFolder("Libraries\\PipeRack");
// get the active view's level for beam creation
Level level = doc.GetElement(doc.ActiveView.LevelId) as Level;
// load a family symbol from file
FamilySymbol gotSymbol = null;
String fileName = Tmp + "\\" + versionNumber + "\\" + famroot;
// 아래의 이름은 패밀리 고유의 이름이다. 패밀리 작업할때 입력하게 되어있다.
String name = famname;
// 패밀리를 로드한다.
Family fam = null;
//m_document.Document.LoadFamilySymbol(fileName, "", out gotSymbol);
bool sw = false;
using (Transaction trans = new Transaction(doc))
{
trans.Start("LoadFamily");
sw = doc.LoadFamily(fileName, out fam);
trans.Commit();
}
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;
}
//페이스 필터
public class PlanarFaceSelectionFilter : ISelectionFilter
{
Autodesk.Revit.DB.Document m_document = null;
public PlanarFaceSelectionFilter(Autodesk.Revit.DB.Document doc)
{
m_document = doc;
}
public bool AllowElement(Element element)
{
return true;
}
public bool AllowReference(Reference refer, XYZ point)
{
if (m_document.GetElement(refer).GetGeometryObjectFromReference(refer) is PlanarFace)
{
return true;
}
return false;
}
}
//파이프 필터
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;
}
}
}
}