Client/Desktop/KMBIM3.0/KMBIM3.0_23.08.16_수정최종/Cmd/PipeMatchInterval/PipeMatchInterval-수정전.cs

608 lines
29 KiB
C#

using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Threading.Tasks;
using KDCS.Utils;
using System.Collections;
using System.Windows.Forms;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.DB.Mechanical;
using System.Xml.Linq;
using Autodesk.Revit.UI.Events;
using System.IO;
using KMBIM.Revit.Tools;
using KMBIM.Revit.Tools.Cmd.ColorSort;
using System.Resources;
using KMBIM.Revit.Tools.Cmd.PipeMatchInterval;
namespace KMBIM
{
/// <summary>
/// Made By Lee Juho, DCS
/// 2021.08
///
/// 1. 위치 조정할 배관 선택
/// 2. 기준 배관 선택
/// 3. 기준 배관의 LocationCurve의 벡터를 구해서 90도 눕힌 다음 가상의 선을 만들고 그 선에 위치 조정할 배관들 커넥터의 좌표를 투영
/// 4. 투영된 점들간의 간격 구하기 = 배관 중심과 중심 간의 간격
/// 5. LocationCurve의 시작점과 각 배관들의 거리에 따라 리스트 정렬,
/// 6. 3에서 구한 LocationCurve의 시작점 -> 기준 배관 벡터 & 움직일 배관 -> 기준 배관이 동일한지 구분해서 배관을 두 개의 그룹으로 쪼개기
/// 7. WinForm 띄워서 단열재 두께 입력받기
/// 8. 6에서 쪼갠 리스트를 백터로 향하는 방향으로 따로 for문 루프 돌리기
/// 9. 원래 위치에 비해 배관이 더 멀어져야 하는지, 가까워져야 하는지에 따라 위치 조정
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class PipeMatchInterval : IExternalCommand
{
UIApplication uiapp;
UIDocument uidoc;
static public Autodesk.Revit.DB.Document doc = null;
Autodesk.Revit.ApplicationServices.Application app = null;
public static List<Pipe> movePipeList = new List<Pipe>();
public static Pipe criteriaPipe = null;
public static List<MovePipeInfo> mpiList = new List<MovePipeInfo>();
public static double criPipeInsul = 0;
public static double userPipeInsulCri = 0;
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
try
{
// Verify active document
if (null == commandData.Application.ActiveUIDocument.Document)
{
message = "현재 활성화된 뷰가 없습니다.";
return Result.Failed;
}
uiapp = commandData.Application;
uidoc = uiapp.ActiveUIDocument;
app = uiapp.Application;
doc = uidoc.Document;
IList<Reference> rList = uidoc.Selection.PickObjects(ObjectType.Element, new PipeSelectionFilter(), "위치 바꿀 배관 선택: ");
movePipeList.Clear();
//바꿀 배관
foreach (Reference refer in rList)
{
if (refer == null) return Result.Cancelled;
Pipe movePipe = doc.GetElement(refer.ElementId) as Pipe;
movePipeList.Add(movePipe);
}
//기준 배관
Reference r = uidoc.Selection.PickObject(ObjectType.Element, new PipeSelectionFilter(), "기준 배관 선택: ");
if (r == null) return Result.Failed;
criteriaPipe = doc.GetElement(r.ElementId) as Pipe;
List<Connector> criPipeCon = Util.GetElementConnectors(criteriaPipe);//기준 파이프 커넥터들
//기준 배관 외경
Parameter criPipeODiaParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
double criPipeODia = Unit.FeetToMM(criPipeODiaParam.AsDouble());
//기준 배관 단열재 두께
Parameter criPipeInsulThickParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
criPipeInsul = Unit.FeetToMM(criPipeInsulThickParam.AsDouble());
LocationCurve criPipeLC = criteriaPipe.Location as LocationCurve;//기준 배관 직선 구하기
Line criPipeLine = criPipeLC.Curve as Line;
XYZ stPt = criPipeLine.GetEndPoint(0);
XYZ endPt = criPipeLine.GetEndPoint(1);
XYZ midPt = Util.Midpoint(stPt, endPt);
//간격 띄우기 값으로 가로로 나열되어 있는지, 세로(Z축 방향)로 나열되어 있는지 파악
double criPipeOffset = criteriaPipe.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble();
double movePipeOffset = movePipeList[0].get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble();
Line guideLine = null;
XYZ guideLinePt1 = null;
if (Math.Abs(criPipeOffset - movePipeOffset) >= Unit.MMToFeet(10))//Z값이 다른 경우. 세로로 가이드라인 작성
{
//Z방향으로 벡터 생성
XYZ criPipeZRot1 = new XYZ(midPt.X, midPt.Y, midPt.Z + 50);
XYZ criPipeZRot2 = new XYZ(midPt.X, midPt.Y, midPt.Z - 50);
XYZ criPipeZRotVec1 = (criPipeZRot2 - criPipeZRot1).Normalize();
XYZ criPipeZRotVec2 = (criPipeZRot1 - criPipeZRot2).Normalize();
guideLinePt1 = Util.Polar(midPt, criPipeZRotVec1, 100);
XYZ guideLinePt2 = Util.Polar(midPt, criPipeZRotVec2, 100);
guideLine = Line.CreateBound(guideLinePt1, guideLinePt2);
}
else//Z값이 같은 경우. 가로로 가이드 라인 작성
{
//기준 배관 백터의 양쪽 횡방향 백터 구하기
XYZ criPipeRot1 = Util.RotateVector(criPipeLine.Direction, Util.DTR(90));
XYZ criPipeRot2 = Util.RotateVector(criPipeLine.Direction, Util.DTR(270));
guideLinePt1 = Util.Polar(midPt, criPipeRot1, 100);
XYZ guideLinePt2 = Util.Polar(midPt, criPipeRot2, 100);
guideLine = Line.CreateBound(guideLinePt1, guideLinePt2);//가상의 가이드 라인 생성
}
mpiList.Clear();
//거리를 구하기 위해 가상의 선을 만들어서 투영시키기
foreach (Pipe p in movePipeList)
{
//커넥터의 좌표를 가상의 가이드 라인에 투영
List<Connector> cList = Util.GetElementConnectors(p);
IntersectionResult interRes = guideLine.Project(cList.First().Origin);
MovePipeInfo mpi = new MovePipeInfo();
mpi.PipeToMove = p;
mpi.InterPt = interRes.XYZPoint;//투영된 점
//mpi.InterPt = Util.PointZ0(interRes.XYZPoint);//투영된 점
//움직일 배관 간격 띄우기 값
Parameter mvPipeOffsetParam = p.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM);
double mvPipeOffset = Unit.FeetToMM(mvPipeOffsetParam.AsDouble());
mpi.Offset = mvPipeOffset;
//움직일 배관 호칭경
Parameter mvPipeNorDiaParam = p.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
double mvPipeNorDia = Unit.FeetToMM(mvPipeNorDiaParam.AsDouble());
mpi.NormalDiameter = mvPipeNorDia;
//움직일 배관 외경
Parameter mvPipeODiaParam = p.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
double mvPipeODia = Unit.FeetToMM(mvPipeODiaParam.AsDouble());
mpi.OuterDia = mvPipeODia;
mpi.OuterDiaRound = Math.Round(mpi.OuterDia, 1);
//움직일 배관 단열재 두께
Parameter mvPipeInsulThickParam = p.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
double mvPipeInsulThick = Unit.FeetToMM(mvPipeInsulThickParam.AsDouble());
mpi.InsultionThick = mvPipeInsulThick;
Util.Pyosi(doc, mpi.InterPt, 1);
//배관 중심과 중심 간의 간격
double distForSort = Unit.FeetToMM(mpi.InterPt.DistanceTo(guideLinePt1));
mpi.DistanceFromCri = distForSort;//나열을 위한 클래스에 집어넣기
mpiList.Add(mpi);
}
//if(Math.Abs(criPipeOffset - movePipeOffset) >= Unit.MMToFeet(10))
//{
// //위에서 아래로 나열
// //mpiList.Sort((a, b) => b.Offset.CompareTo(a.Offset));
// mpiList.OrderByDescending(num => num.Offset);
//}
//else
///{
//거리순으로 나열. 오름차순
mpiList.Sort((a, b) => a.DistanceFromCri.CompareTo(b.DistanceFromCri));//클래스 자체를 Sort
//}
//실제 배관 사이의 거리 구하기
GetPipesDistanceAndDivide(midPt, guideLinePt1, criPipeODia);
SetOffset so = new SetOffset();
so.ShowDialog();
so.doc = doc;
double offsetValFromUser = so.offsetValue;//간격 띄우기 값
if (so.isConfirmed == false) return Result.Cancelled;//폼에서 취소 누름
using (Transaction tr = new Transaction(doc))
{
tr.Start("Start");
List<MovePipeInfo> infoTrue = new List<MovePipeInfo>();
List<MovePipeInfo> infoFalse = new List<MovePipeInfo>();
//기준 배관을 중심으로 나누기
DividePipesBasedOnCriteriaPipe(infoTrue, infoFalse);
//기준 배관과 멀어져 가며 하나씩 옮기기
for (int i = infoTrue.Count() - 1; i >= 0; i--)
{
double offsetVal = 0;
double offsetValForNextPipe = 0;
if(userPipeInsulCri != criPipeInsul)
{
infoTrue[infoTrue.Count() - 1].Distance = infoTrue[infoTrue.Count() - 1].Distance - userPipeInsulCri;
}
if (offsetValFromUser <= infoTrue[i].Distance)//거리를 줄여야 할 경우
{
//유저가 단열재 두께 값을 따로 지정한 경우
//따로 지정한 값이 원래의 단열재 두께보다 두꺼운 경우
if (infoTrue[i].UserInsultionThick > infoTrue[i].InsultionThick)
{
offsetVal = (infoTrue[i].Distance - offsetValFromUser) + infoTrue[i].UserInsultionThick;
offsetValForNextPipe = offsetVal + infoTrue[i].UserInsultionThick;//단열재 두께가 추가되면 옆 배관까지 영향을 주기 때문에 따로 처리
}
//따로 지정한 값이 원래의 단열재 두꼐보다 얇은 경우
else if (infoTrue[i].UserInsultionThick < infoTrue[i].InsultionThick)
{
offsetVal = (infoTrue[i].Distance - offsetValFromUser) - infoTrue[i].UserInsultionThick;
offsetValForNextPipe = offsetVal - infoTrue[i].UserInsultionThick;
}
//값 수정 안된 경우
else if (infoTrue[i].UserInsultionThick == infoTrue[i].InsultionThick)
{
offsetVal = infoTrue[i].Distance - offsetValFromUser;
offsetValForNextPipe = offsetVal;
}
XYZ toCriVec = (midPt - infoTrue[i].InterPt).Normalize() * Unit.MMToFeet(offsetVal);
ElementTransformUtils.MoveElement(doc, infoTrue[i].PipeToMove.Id, toCriVec);
if (i > 0 && infoTrue.Count() > 1)//하나의 배관을 바꾸면 다른 배관들도 다 영향을 받기 때문에 인덱스가 넘어가기 전에 값 조정
{
infoTrue[i - 1].Distance = infoTrue[i - 1].Distance + offsetValForNextPipe;
}
}
else if (offsetValFromUser > infoTrue[i].Distance)//거리를 늘려야 하는 경우
{
//유저가 단열재 두께 값을 따로 지정한 경우
if (infoTrue[i].UserInsultionThick > infoTrue[i].InsultionThick)
{
offsetVal = (offsetValFromUser - infoTrue[i].Distance) + infoTrue[i].UserInsultionThick;
offsetValForNextPipe = offsetVal + infoTrue[i].UserInsultionThick;
}
else if (infoTrue[i].UserInsultionThick < infoTrue[i].InsultionThick)
{
offsetVal = (offsetValFromUser - infoTrue[i].Distance) - infoTrue[i].UserInsultionThick;
offsetValForNextPipe = offsetVal - infoTrue[i].UserInsultionThick;
}
else if (infoTrue[i].UserInsultionThick == infoTrue[i].InsultionThick)
{
offsetVal = offsetValFromUser - infoTrue[i].Distance;
offsetValForNextPipe = offsetVal;
}
XYZ toCriVec = (infoTrue[i].InterPt - midPt).Normalize() * Unit.MMToFeet(offsetVal);
ElementTransformUtils.MoveElement(doc, infoTrue[i].PipeToMove.Id, toCriVec);
if (i > 0 && infoTrue.Count() > 1)
{
infoTrue[i - 1].Distance = infoTrue[i - 1].Distance - offsetValForNextPipe;
}
}
}
for (int i = 0; i < infoFalse.Count(); i++)
{
double offsetVal = 0;
double offsetValForNextPipe = 0;
if (userPipeInsulCri != criPipeInsul)
{
infoFalse[0].Distance = infoFalse[0].Distance - userPipeInsulCri;
}
if (offsetValFromUser <= infoFalse[i].Distance)//거리를 줄여야 할 경우
{
//유저가 단열재 두께 값을 따로 지정한 경우
//따로 지정한 값이 원래의 단열재 두께보다 두꺼운 경우
if (infoFalse[i].UserInsultionThick > infoFalse[i].InsultionThick)
{
offsetVal = (infoFalse[i].Distance - offsetValFromUser) + infoFalse[i].UserInsultionThick;
offsetValForNextPipe = offsetVal + infoFalse[i].UserInsultionThick;
}
//따로 지정한 값이 원래의 단열재 두께보다 얇은 경우
else if (infoFalse[i].UserInsultionThick < infoFalse[i].InsultionThick)
{
offsetVal = (infoFalse[i].Distance - offsetValFromUser) - infoFalse[i].UserInsultionThick;
offsetValForNextPipe = offsetVal - infoFalse[i].UserInsultionThick;
}
//값 수정 안된 경우
else if (infoFalse[i].UserInsultionThick == infoFalse[i].InsultionThick)
{
offsetVal = infoFalse[i].Distance - offsetValFromUser;
offsetValForNextPipe = offsetVal;
}
XYZ toCriVec = (midPt - infoFalse[i].InterPt).Normalize() * Unit.MMToFeet(offsetVal);
ElementTransformUtils.MoveElement(doc, infoFalse[i].PipeToMove.Id, toCriVec);
if (i < infoFalse.Count() - 1 && infoFalse.Count() > 1)
{
infoFalse[i + 1].Distance = infoFalse[i + 1].Distance + offsetValForNextPipe;
}
}
else if (offsetValFromUser > infoFalse[i].Distance)//거리를 늘려야 하는 경우
{
//유저가 단열재 두께 값을 따로 지정한 경우
if (infoFalse[i].UserInsultionThick > infoFalse[i].InsultionThick)
{
offsetVal = (offsetValFromUser - infoFalse[i].Distance) + infoFalse[i].UserInsultionThick;
offsetValForNextPipe = offsetVal + infoFalse[i].UserInsultionThick;
}
else if (infoFalse[i].UserInsultionThick < infoFalse[i].InsultionThick)
{
offsetVal = (offsetValFromUser - infoFalse[i].Distance) - infoFalse[i].UserInsultionThick;
offsetValForNextPipe = offsetVal - infoFalse[i].UserInsultionThick;
}
else if (infoFalse[i].UserInsultionThick == infoFalse[i].InsultionThick)
{
offsetVal = offsetValFromUser - infoFalse[i].Distance;
offsetValForNextPipe = offsetVal;
}
XYZ toCriVec = (infoFalse[i].InterPt - midPt).Normalize() * Unit.MMToFeet(offsetVal);
ElementTransformUtils.MoveElement(doc, infoFalse[i].PipeToMove.Id, toCriVec);
if (i < infoFalse.Count() - 1 && infoFalse.Count() > 1)
{
infoFalse[i + 1].Distance = infoFalse[i + 1].Distance - offsetValForNextPipe;
}
}
}
tr.Commit();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return Result.Succeeded;
}
//Method--------------------------------------------------------------------------------------------------------------
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;
}
}
public double GetMinValue(List<double> doubleList)
{
double minLength = doubleList[0];
for (int i = 0; i < doubleList.Count(); i++)
{
//최솟값 구하기
if (minLength > doubleList[i])
{
minLength = doubleList[i];
}
}
return minLength;
}
public double RTD(double radian)
{
return radian * (180.0 / Math.PI);
}
/// <summary>
/// 배관과 다른 배관 간의 간격을 구한다.
/// 기준 배관으로 향하는 벡터를 기준으로 방향이 같은 것 / 다른 것을 나누어서 따로 거리를 구한다.(후에 나눈 배관들을 따로 처리 하기 위함)
/// 거리를 구할 배관들의 외경, 단열재 두께, 기준 배관의 LocationCurve가 필요
/// </summary>
/// <param name="criteriaPipeMidPt"></param>
/// <param name="guideLinePt1"></param>
/// <param name="criPipeODia"></param>
public void GetPipesDistanceAndDivide(XYZ criteriaPipeMidPt, XYZ guideLinePt1, double criPipeODia)
{
for (int i = 0; i < mpiList.Count(); i++)
{
XYZ SortVec = (mpiList[i].InterPt - guideLinePt1).Normalize();
XYZ toMidPtVec = (criteriaPipeMidPt - mpiList[i].InterPt).Normalize();
if (toMidPtVec.IsAlmostEqualTo(SortVec))//정렬 방향 & 움직일 배관에서 기준 배관으로의 백터가 동일한 경우
{
if (i != mpiList.Count() - 1)
{
double dist = Unit.FeetToMM(mpiList[i].InterPt.DistanceTo(mpiList[i + 1].InterPt));//배관 중심과 중심 사이의 간격
if (mpiList[i + 1].PipeToMove == criteriaPipe)//다음 배관이 기준 배관인 경우
{
double realDist = dist - (criPipeODia / 2 + mpiList[i].OuterDia / 2 + mpiList[i + 1].InsultionThick
+ mpiList[i].InsultionThick);
mpiList[i].Distance = realDist;
}
else//다음 배관이 기준 배관이 아닌 경우
{
double realDist = dist - (mpiList[i + 1].OuterDia / 2 + mpiList[i].OuterDia / 2 + mpiList[i + 1].InsultionThick
+ mpiList[i].InsultionThick);
mpiList[i].Distance = realDist;
}
//구별 시 기준 배관 배제
if (mpiList[i].PipeToMove.Id != criteriaPipe.Id)
{
mpiList[i].JudgePipe = 1;
}
else if (mpiList[i].PipeToMove.Id == criteriaPipe.Id)
{
mpiList[i].JudgePipe = 2;
}
}
}
else//반대 방향인 경우
{
double dist = 0;
if (i > 0)
{
dist = Unit.FeetToMM(mpiList[i].InterPt.DistanceTo(mpiList[i - 1].InterPt));//배관 중심과 중심 사이의 간격
}
if (i != 0)
{
if (mpiList[i - 1].PipeToMove == criteriaPipe)//다음 배관이 기준 배관인 경우
{
double realDist = dist - (criPipeODia / 2 + mpiList[i].OuterDia / 2 + mpiList[i - 1].InsultionThick + mpiList[i].InsultionThick);
mpiList[i].Distance = realDist;
}
else//다음 배관이 기준 배관이 아닌 경우
{
double realDist = dist - (mpiList[i - 1].OuterDia / 2 + mpiList[i].OuterDia / 2 + mpiList[i - 1].InsultionThick + mpiList[i].InsultionThick);
mpiList[i].Distance = realDist;
}
}
//구별 시 기준 배관 배제
if (mpiList[i].PipeToMove.Id != criteriaPipe.Id)
{
mpiList[i].JudgePipe = 0;
}
else if (mpiList[i].PipeToMove.Id == criteriaPipe.Id)
{
mpiList[i].JudgePipe = 2;
}
}
}
}
/// <summary>
/// 기준 배관으로 다른 배관들을 다른 리스트에 담아 분류하기
/// </summary>
/// <param name="infoTrue">리스트1</param>
/// <param name="infoFalse">리스트2</param>
public void DividePipesBasedOnCriteriaPipe(List<MovePipeInfo> infoTrue, List<MovePipeInfo> infoFalse)
{
for (int i = 0; i < mpiList.Count(); i++)
{
if (mpiList[i].JudgePipe == 1)//정렬 방향 & 움직일 배관에서 기준 배관으로의 백터가 동일한 경우
{
infoTrue.Add(mpiList[i]);
}
else if (mpiList[i].JudgePipe == 0)
{
infoFalse.Add(mpiList[i]);
}
else if (mpiList[i].JudgePipe == 2) continue;//기준 배관 패스
}
}
/// <summary>
/// 배관 두 개 사이의 간격 구하기(중점에서 중점간 거리가 아닌 실제 겉 표면에서 부터의 겉 표면 까지의 거리)
/// </summary>
/// <param name="pipe1">첫번째 배관</param>
/// <param name="pipe2">두번째 배관</param>
/// <returns>배관 사이의 거리</returns>
public double GetPipesDistanceMM(Pipe pipe1, Pipe pipe2)
{
//pipe1 배관 외경
Parameter Pipe1ODiaParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
double Pipe1ODia = Unit.FeetToMM(Pipe1ODiaParam.AsDouble());
//pipe1 단열재 두께
Parameter pipe1InsulThickParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
double pipe1InsultionThick = Unit.FeetToMM(pipe1InsulThickParam.AsDouble());
LocationCurve Pipe1LC = criteriaPipe.Location as LocationCurve;//pipe1 직선 구하기
Line Pipe1Line = Pipe1LC.Curve as Line;
XYZ stPt = Pipe1Line.GetEndPoint(0);
XYZ endPt = Pipe1Line.GetEndPoint(1);
XYZ midPt = Util.Midpoint(stPt, endPt);
//pipe1 백터의 양쪽 횡방향 백터 구하기
XYZ Pipe1Rot1 = Util.RotateVector(Pipe1Line.Direction, Util.DTR(90));
XYZ Pipe1Rot2 = Util.RotateVector(Pipe1Line.Direction, Util.DTR(270));
XYZ guideLinePt1 = Util.Polar(midPt, Pipe1Rot1, 100);
XYZ guideLinePt2 = Util.Polar(midPt, Pipe1Rot2, 100);
Line guideLine = Line.CreateBound(guideLinePt1, guideLinePt2);//가상의 가이드 라인 생성
//----------------------------------------------------------------------------------------
//커넥터의 좌표를 가상의 가이드 라인에 투영
List<Connector> cList = Util.GetElementConnectors(pipe2);
IntersectionResult interRes = guideLine.Project(cList.First().Origin);
XYZ interPt = interRes.XYZPoint;
//pipe2 배관 외경
Parameter pipe2ODiaParam = pipe2.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
double pipe2ODia = Unit.FeetToMM(pipe2ODiaParam.AsDouble());
//pipe2 단열재 두께
Parameter pipe2InsulThickParam = pipe2.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
double pipe2InsulThick = Unit.FeetToMM(pipe2InsulThickParam.AsDouble());
//배관 중심과 중심 간의 간격
double distBetweenPipesCenter = Unit.FeetToMM(interPt.DistanceTo(guideLinePt1));
double dist = distBetweenPipesCenter - (Pipe1ODia / 2 + pipe2ODia / 2 + pipe1InsultionThick + pipe2InsulThick);
return dist;
}
/// <summary>
/// 요소에 색상 지정. 가시성/그래픽에 투영/표면 재지정 없음으로 설정하면 안 보임
/// </summary>
/// <param name="eId">색상 넣을 요소 Id</param>
/// <param name="SelectedColor">바꿀 색상</param>
public void SetColor(Document doc, Element e, System.Drawing.Color SelectedColor)
{
FilteredElementCollector fec = new FilteredElementCollector(doc).OfClass(typeof(FillPatternElement));
ElementId fillEId = null;
foreach (FillPatternElement fpe in fec)
{
if (fpe.GetFillPattern().IsSolidFill)//솔리드 채움으로 되어 있는 요소에만 색상 지정 가능
{
fillEId = fpe.Id;
break;
}
else
MessageBox.Show("솔리드 채움으로 바꾸십시오.", "오류");
}
System.Drawing.Color col = SelectedColor;
Autodesk.Revit.DB.Color adeskColor = new Autodesk.Revit.DB.Color(col.R, col.G, col.B);
OverrideGraphicSettings ogs = new OverrideGraphicSettings();
ogs.SetProjectionLineColor(adeskColor);
ogs.SetSurfaceForegroundPatternColor(adeskColor);
ogs.SetCutForegroundPatternColor(adeskColor);
if (e.Id != null)
{
ogs.SetSurfaceForegroundPatternId(fillEId);
ogs.SetCutForegroundPatternId(fillEId);
ogs.SetProjectionLinePatternId(fillEId);
}
doc.ActiveView.SetElementOverrides(e.Id, ogs);
}
}
}