608 lines
29 KiB
C#
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);
|
|
}
|
|
}
|
|
} |