742 lines
33 KiB
C#
742 lines
33 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 dirPipe = null;
|
|
public static List<MovePipeInfo> mpiList = new List<MovePipeInfo>();
|
|
public static List<MovePipeInfo> RightMpiLst = new List<MovePipeInfo>();
|
|
public static List<MovePipeInfo> LeftMpiLst = new List<MovePipeInfo>();
|
|
public static List<MovePipeInfo> UpMpiLst = new List<MovePipeInfo>();
|
|
public static List<MovePipeInfo> DownMpiLst = new List<MovePipeInfo>();
|
|
public static MovePipeInfo dirMpi = new MovePipeInfo();
|
|
public static double dirPipeInsul = 0;
|
|
public static double userPipeInsulCri = 0;
|
|
|
|
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
|
{
|
|
try
|
|
{
|
|
if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
|
|
// 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;
|
|
|
|
dirPipe = doc.GetElement(r.ElementId) as Pipe;
|
|
List<Connector> criPipeCon = Util.GetElementConnectors(dirPipe);//기준 파이프 커넥터들
|
|
|
|
//기준 배관 외경
|
|
Parameter criPipeODiaParam = dirPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
double criPipeODia = Unit.FeetToMM(criPipeODiaParam.AsDouble());
|
|
|
|
//기준 배관 단열재 두께
|
|
Parameter criPipeInsulThickParam = dirPipe.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
|
|
dirPipeInsul = Unit.FeetToMM(criPipeInsulThickParam.AsDouble());
|
|
|
|
LocationCurve criPipeLC = dirPipe.Location as LocationCurve;//기준 배관 직선 구하기
|
|
Line criPipeLine = criPipeLC.Curve as Line;
|
|
|
|
XYZ dirSp = null, dirEp = null;
|
|
Util.GetStartEndPoint(dirPipe, ref dirSp, ref dirEp);
|
|
XYZ midPt = Util.Midpoint(dirSp, dirEp);
|
|
//거리 구하기 위해 z값 0 (Z값 있으면 배관 간격띄우기 값이 다를 때 대각선 값 나옴)
|
|
XYZ midZ0Pt = Util.PointZ0(midPt);
|
|
|
|
//XYZ stPt = criPipeLine.GetEndPoint(0);
|
|
//XYZ endPt = criPipeLine.GetEndPoint(1);
|
|
//XYZ midPt = Util.Midpoint(stPt, endPt);
|
|
|
|
//간격 띄우기 값으로 가로로 나열되어 있는지, 세로(Z축 방향)로 나열되어 있는지 파악
|
|
double dirPipeOffset = dirPipe.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble();
|
|
double movePipeOffset = movePipeList[0].get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble();
|
|
|
|
//초기화 안하면 명령어 실행할 때마다 중복 오류
|
|
mpiList.Clear();
|
|
RightMpiLst.Clear();
|
|
LeftMpiLst.Clear();
|
|
UpMpiLst.Clear();
|
|
DownMpiLst.Clear();
|
|
|
|
foreach (Pipe p in movePipeList)
|
|
{
|
|
//if (dirPipe.Id.Equals(p.Id)) continue;
|
|
XYZ moveSp = null, moveEp = null;
|
|
Util.GetStartEndPoint(p, ref moveSp, ref moveEp);
|
|
Line pVirLine = Line.CreateUnbound(moveSp, (moveEp - moveSp).Normalize());
|
|
|
|
IntersectionResult interRes = pVirLine.Project(midZ0Pt);
|
|
XYZ closePt = interRes.XYZPoint;
|
|
//거리 구하기 위해 z값 0 (Z값 있으면 배관 간격띄우기 값이 다를 때 대각선 값 나옴)
|
|
XYZ closeZ0Pt = Util.PointZ0(closePt);
|
|
|
|
//Util.Pyosi(doc, closeZ0Pt, 1);
|
|
//MessageBox.Show("1");
|
|
|
|
MovePipeInfo mpi = new MovePipeInfo();
|
|
mpi.PipeToMove = p;
|
|
mpi.InterPt = closePt;
|
|
mpi.InterZ0Pt = closeZ0Pt;
|
|
|
|
//움직일 배관 간격 띄우기 값
|
|
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;
|
|
|
|
//배관 중심과 중심 간의 간격
|
|
double distForSort = Unit.FeetToMM(mpi.InterZ0Pt.DistanceTo(midZ0Pt));
|
|
//MessageBox.Show(distForSort.ToString());
|
|
|
|
mpi.DistanceFromCri = distForSort;//나열을 위한 클래스에 집어넣기
|
|
|
|
mpiList.Add(mpi);
|
|
}
|
|
|
|
//거리순으로 나열, 오름차순
|
|
mpiList.Sort((a, b) => a.DistanceFromCri.CompareTo(b.DistanceFromCri));
|
|
|
|
//기준 배관 기준으로 왼쪽 오른쪽 나눔
|
|
foreach (MovePipeInfo info in mpiList)
|
|
{
|
|
//기준 배관 넘어감
|
|
if (dirPipe.Id.Equals(info.PipeToMove.Id))
|
|
{
|
|
dirMpi = info;
|
|
continue;
|
|
}
|
|
|
|
//기준 배관 기준 왼쪽 오른쪽 나누기
|
|
if (Util.isRightPoint(info.InterZ0Pt, dirSp, dirEp) == true)
|
|
RightMpiLst.Add(info);
|
|
else
|
|
LeftMpiLst.Add(info);
|
|
|
|
}
|
|
|
|
//거리순으로 나열, 오름차순
|
|
RightMpiLst.Sort((a, b) => a.DistanceFromCri.CompareTo(b.DistanceFromCri));
|
|
LeftMpiLst.Sort((a, b) => a.DistanceFromCri.CompareTo(b.DistanceFromCri));
|
|
|
|
//기준 배관 기준으로 위 아래 나눔
|
|
foreach (MovePipeInfo info in mpiList)
|
|
{
|
|
//기준 배관 넘어감
|
|
if (dirPipe.Id.Equals(info.PipeToMove.Id))
|
|
{
|
|
dirMpi = info;
|
|
continue;
|
|
}
|
|
|
|
//기준 배관 기주 위 아래 나누기
|
|
if (midPt.Z < info.InterPt.Z)
|
|
UpMpiLst.Add(info);
|
|
else
|
|
DownMpiLst.Add(info);
|
|
}
|
|
|
|
//간격띄우기 값 순으로 나열
|
|
//UpMpiLst.Sort((a, b) => Math.Abs(midPt.Z - a.InterPt.Z).CompareTo(midPt.Z - b.InterPt.Z));
|
|
//DownMpiLst.Sort((a, b) => Math.Abs(midPt.Z - a.InterPt.Z).CompareTo(midPt.Z - b.InterPt.Z));
|
|
UpMpiLst.Sort((a, b) => a.Offset.CompareTo(b.Offset));
|
|
DownMpiLst.Sort((a, b) => a.Offset.CompareTo(b.Offset));
|
|
DownMpiLst.Reverse();
|
|
|
|
//대화상자 시작
|
|
SetOffset so = new SetOffset();
|
|
so.ShowDialog();
|
|
|
|
//RightMpiLst.Reverse();
|
|
|
|
so.doc = doc;
|
|
double m_Offset = so.offsetValue;//간격 띄우기
|
|
int idx_DirSort = so.m_RadIdx;//정렬 방향 (수평/수직)
|
|
|
|
if (so.isConfirmed == false) return Result.Cancelled;//취소시 명령어 종료
|
|
|
|
//Transaction 실행
|
|
using (Transaction trans = new Transaction(doc))
|
|
{
|
|
trans.Start("Start");
|
|
|
|
// 기준 배관 단열재 두께 변경
|
|
if (dirMpi.InsultionThick != dirMpi.UserInsultionThick)
|
|
{
|
|
//유저가 기준 배관 단열재 두께를 변경한 경우
|
|
Util.SetPipeInsulationThickness(doc, dirMpi.PipeToMove, Unit.MMToFeet(dirMpi.UserInsultionThick));
|
|
}
|
|
|
|
|
|
//정렬 수평일 경우
|
|
if (idx_DirSort == 0)
|
|
{
|
|
//기준배관 오른쪽 배관 단열재 두께 변경
|
|
foreach (MovePipeInfo rightInfo in RightMpiLst)
|
|
{
|
|
if (rightInfo.InsultionThick != rightInfo.UserInsultionThick)
|
|
{
|
|
//유저가 단열재 두께를 변경한 경우
|
|
Util.SetPipeInsulationThickness(doc, rightInfo.PipeToMove, Unit.MMToFeet(rightInfo.UserInsultionThick));
|
|
}
|
|
}
|
|
//기준배관 왼쪽 배관 단열재 두께 변경
|
|
foreach (MovePipeInfo leftInfo in LeftMpiLst)
|
|
{
|
|
if (leftInfo.InsultionThick != leftInfo.UserInsultionThick)
|
|
{
|
|
//유저가 단열재 두께를 변경한 경우
|
|
Util.SetPipeInsulationThickness(doc, leftInfo.PipeToMove, Unit.MMToFeet(leftInfo.UserInsultionThick));
|
|
}
|
|
}
|
|
|
|
//수평 프로세스
|
|
MoveHorizontalProcess(so, RightMpiLst, LeftMpiLst, dirMpi, midZ0Pt);
|
|
}
|
|
else if(idx_DirSort==1)//정렬 수직일 경우
|
|
{
|
|
//기준배관 위쪽 배관 단열재 두께 변경
|
|
foreach (MovePipeInfo UpInfo in UpMpiLst)
|
|
{
|
|
if (UpInfo.InsultionThick != UpInfo.UserInsultionThick)
|
|
{
|
|
//유저가 단열재 두께를 변경한 경우
|
|
Util.SetPipeInsulationThickness(doc, UpInfo.PipeToMove, Unit.MMToFeet(UpInfo.UserInsultionThick));
|
|
}
|
|
}
|
|
//기준배관 아래쪽 배관 단열재 두께 변경
|
|
foreach (MovePipeInfo DownInfo in DownMpiLst)
|
|
{
|
|
if (DownInfo.InsultionThick != DownInfo.UserInsultionThick)
|
|
{
|
|
//유저가 단열재 두께를 변경한 경우
|
|
Util.SetPipeInsulationThickness(doc, DownInfo.PipeToMove, Unit.MMToFeet(DownInfo.UserInsultionThick));
|
|
}
|
|
}
|
|
|
|
//수직 프로세스
|
|
MoveVerticalProcess(so, UpMpiLst, DownMpiLst, dirMpi, midPt);
|
|
}
|
|
|
|
|
|
trans.Commit();
|
|
}//end trans
|
|
|
|
|
|
}
|
|
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>
|
|
/// 실제 이동 거리 구해 배관 이동
|
|
/// </summary>
|
|
/// <param name="dlg"></param> 대화상자
|
|
/// <param name="RightInfoLst"></param> 기준배관 오른쪽 배관리스트
|
|
/// <param name="LeftInfoLst"></param>기준배관 왼쪽 배관리스트
|
|
/// <param name="dirMpi"></param>기준 배관
|
|
/// <param name="dirPipeMidPt"></param> 기준배관 중간점
|
|
public void MoveHorizontalProcess(SetOffset dlg, List<MovePipeInfo> RightInfoLst, List<MovePipeInfo> LeftInfoLst, MovePipeInfo dirMpi, XYZ dirPipeMidPt)
|
|
{
|
|
|
|
XYZ dirInterPt = dirPipeMidPt;
|
|
MovePipeInfo dirInfo = dirMpi;
|
|
//기준배관 오른쪽 리스트 실제
|
|
foreach (MovePipeInfo info in RightInfoLst)
|
|
{
|
|
//기준배관과 교차점 중심 간 거리
|
|
double dirDist = Unit.FeetToMM(info.InterZ0Pt.DistanceTo(dirInterPt));
|
|
|
|
//사용자가 단열재 두께를 변경했을 때
|
|
double realDist = 0;
|
|
if (dirInfo.InsultionThick != dirInfo.UserInsultionThick)
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.UserInsultionThick);
|
|
}
|
|
else//변경 안 했을 때
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.InsultionThick);
|
|
}
|
|
|
|
//이전 배관과 거리 변수 추가
|
|
info.Distance = realDist;
|
|
|
|
//갱신
|
|
dirInfo = info;
|
|
dirInterPt = info.InterZ0Pt;
|
|
|
|
}
|
|
|
|
dirInterPt = dirPipeMidPt;
|
|
dirInfo = dirMpi;
|
|
//기준배관 왼쪽 리스트
|
|
foreach (MovePipeInfo info in LeftInfoLst)
|
|
{
|
|
//기준배관과 교차점 중심 간 거리
|
|
double dirDist = Unit.FeetToMM(info.InterZ0Pt.DistanceTo(dirInterPt));
|
|
|
|
//사용자가 단열재 두께를 변경했을 때
|
|
double realDist = 0;
|
|
if (dirInfo.InsultionThick != dirInfo.UserInsultionThick)
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.UserInsultionThick);
|
|
}
|
|
else//변경 안 했을 때
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.InsultionThick);
|
|
}
|
|
|
|
//이전 배관과 거리 변수 추가
|
|
info.Distance = realDist;
|
|
|
|
//갱신
|
|
dirInfo = info;
|
|
dirInterPt = info.InterZ0Pt;
|
|
|
|
}
|
|
|
|
//정렬방향 - 수평
|
|
if (dlg.m_RadIdx == 0)
|
|
{
|
|
//기준배관 방향으로 옮긴 배관들 중 마지막으로 옮긴 거리
|
|
double lastRedDist = 0;
|
|
|
|
//기준파이프 오른쪽 파이프 리스트
|
|
foreach (MovePipeInfo rp in RightMpiLst)
|
|
{
|
|
double redDist = 0;
|
|
XYZ vec = (dirPipeMidPt - rp.InterZ0Pt).Normalize();
|
|
if (rp.UserInsultionThick != rp.InsultionThick)
|
|
{
|
|
if (rp.UserInsultionThick > rp.InsultionThick)
|
|
redDist = rp.Distance - dlg.offsetValue + lastRedDist - (rp.UserInsultionThick - rp.InsultionThick);
|
|
else
|
|
redDist = rp.Distance - dlg.offsetValue + lastRedDist + (rp.InsultionThick - rp.UserInsultionThick);
|
|
}
|
|
else
|
|
redDist = rp.Distance - dlg.offsetValue + lastRedDist;
|
|
|
|
//redDist = rp.Distance - m_Offset + lastRedDist;
|
|
XYZ movePt = Util.Polar(rp.InterZ0Pt, vec, Unit.MMToFeet(redDist));
|
|
XYZ tranVec = (movePt - rp.InterZ0Pt);
|
|
|
|
ElementTransformUtils.MoveElement(doc, rp.PipeToMove.Id, tranVec);
|
|
lastRedDist = redDist;
|
|
}
|
|
|
|
lastRedDist = 0;
|
|
//기준파이프 왼쪽 파이프 리스트
|
|
foreach (MovePipeInfo lp in LeftMpiLst)
|
|
{
|
|
double redDist = 0;
|
|
XYZ vec = (dirPipeMidPt - lp.InterZ0Pt).Normalize();
|
|
if (lp.UserInsultionThick != lp.InsultionThick)
|
|
{
|
|
if (lp.UserInsultionThick > lp.InsultionThick)
|
|
redDist = lp.Distance - dlg.offsetValue + lastRedDist - (lp.UserInsultionThick - lp.InsultionThick);
|
|
else
|
|
redDist = lp.Distance - dlg.offsetValue + lastRedDist + (lp.InsultionThick - lp.UserInsultionThick);
|
|
}
|
|
else
|
|
redDist = lp.Distance - dlg.offsetValue + lastRedDist;
|
|
|
|
//redDist = rp.Distance - m_Offset + lastRedDist;
|
|
XYZ movePt = Util.Polar(lp.InterZ0Pt, vec, Unit.MMToFeet(redDist));
|
|
XYZ tranVec = (movePt - lp.InterZ0Pt);
|
|
|
|
ElementTransformUtils.MoveElement(doc, lp.PipeToMove.Id, tranVec);
|
|
lastRedDist = redDist;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 실제 이동 거리 구해 배관 이동
|
|
/// </summary>
|
|
/// <param name="dlg"></param> 대화상자
|
|
/// <param name="RightInfoLst"></param> 기준배관 오른쪽 배관리스트
|
|
/// <param name="LeftInfoLst"></param>기준배관 왼쪽 배관리스트
|
|
/// <param name="dirMpi"></param>기준 배관
|
|
/// <param name="dirPipeMidPt"></param> 기준배관 중간점
|
|
public void MoveVerticalProcess(SetOffset dlg, List<MovePipeInfo> UpInfoLst, List<MovePipeInfo> DownInfoLst, MovePipeInfo dirMpi, XYZ dirPipeMidPt)
|
|
{
|
|
//기준 배관과 가까운 순서대로 정렬
|
|
//RightMpiLst.Sort((a, b) => Math.Abs(dirPipeMidPt.Z - a.InterPt.Z).CompareTo(Math.Abs(dirPipeMidPt.Z - b.InterPt.Z)));
|
|
|
|
|
|
XYZ dirInterPt = dirPipeMidPt;
|
|
MovePipeInfo dirInfo = dirMpi;
|
|
//기준배관 오른쪽 리스트 실제
|
|
foreach (MovePipeInfo info in UpInfoLst)
|
|
{
|
|
//기준배관과 교차점 중심 간 높이
|
|
//double dirDist = Unit.FeetToMM(info.InterZ0Pt.DistanceTo(dirInterPt));
|
|
double dirDist = Unit.FeetToMM(Math.Abs(info.InterPt.Z - dirInterPt.Z));
|
|
|
|
//사용자가 단열재 두께를 변경했을 때
|
|
double realDist = 0;
|
|
if (dirInfo.InsultionThick != dirInfo.UserInsultionThick)
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.UserInsultionThick);
|
|
}
|
|
else//변경 안 했을 때
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.InsultionThick);
|
|
}
|
|
|
|
//이전 배관과 거리 변수 추가
|
|
info.Distance = realDist;
|
|
|
|
//갱신
|
|
dirInfo = info;
|
|
dirInterPt = info.InterPt;
|
|
|
|
//string a = "distance : " + info.Distance.ToString() +
|
|
// "\n" + "DistanceFromCri : " + info.DistanceFromCri.ToString() +
|
|
// "\n" + "interPt : " + info.InterPt.ToString() +
|
|
// "\n" + "OuterDia : " + info.OuterDia.ToString();
|
|
//MessageBox.Show(a);
|
|
}
|
|
|
|
|
|
//기준 배관과 가까운 순서대로 정렬
|
|
//LeftMpiLst.Sort((a, b) => Math.Abs(dirPipeMidPt.Z - a.InterPt.Z).CompareTo(Math.Abs(dirPipeMidPt.Z - b.InterPt.Z)));
|
|
|
|
dirInterPt = dirPipeMidPt;
|
|
dirInfo = dirMpi;
|
|
//기준배관 왼쪽 리스트
|
|
foreach (MovePipeInfo info in DownInfoLst)
|
|
{
|
|
//기준배관과 교차점 중심 간 높이
|
|
//double dirDist = Unit.FeetToMM(info.InterPt.DistanceTo(dirInterPt));
|
|
double dirDist = Unit.FeetToMM(Math.Abs(info.InterPt.Z - dirInterPt.Z));
|
|
|
|
//사용자가 단열재 두께를 변경했을 때
|
|
double realDist = 0;
|
|
if (dirInfo.InsultionThick != dirInfo.UserInsultionThick)
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.UserInsultionThick);
|
|
}
|
|
else//변경 안 했을 때
|
|
{
|
|
realDist = dirDist - (info.OuterDia / 2.0 + dirInfo.OuterDia / 2.0 + info.InsultionThick + dirInfo.InsultionThick);
|
|
}
|
|
|
|
//이전 배관과 거리 변수 추가
|
|
info.Distance = realDist;
|
|
|
|
//갱신
|
|
dirInfo = info;
|
|
dirInterPt = info.InterPt;
|
|
|
|
}
|
|
|
|
|
|
|
|
//정렬방향 - 수직
|
|
if (dlg.m_RadIdx == 1)
|
|
{
|
|
//기준배관 방향으로 옮긴 배관들 중 마지막으로 옮긴 거리
|
|
double lastRedDist = 0;
|
|
|
|
//기준파이프 위쪽 파이프 리스트
|
|
foreach (MovePipeInfo up in UpMpiLst)
|
|
{
|
|
double redDist = 0;
|
|
//XYZ vec = (dirPipeMidPt - rp.InterPt).Normalize();
|
|
XYZ vec = (new XYZ(0, 0, dirPipeMidPt.Z) - new XYZ(0, 0, up.InterPt.Z)).Normalize();
|
|
if (up.UserInsultionThick != up.InsultionThick)
|
|
{
|
|
if (up.UserInsultionThick > up.InsultionThick)
|
|
redDist = up.Distance - dlg.offsetValue + lastRedDist - (up.UserInsultionThick - up.InsultionThick);
|
|
else
|
|
redDist = up.Distance - dlg.offsetValue + lastRedDist + (up.InsultionThick - up.UserInsultionThick);
|
|
}
|
|
else
|
|
redDist = up.Distance - dlg.offsetValue + lastRedDist;
|
|
|
|
//redDist = rp.Distance - m_Offset + lastRedDist;
|
|
XYZ movePt = Util.Polar(up.InterPt, vec, Unit.MMToFeet(redDist));
|
|
XYZ tranVec = (movePt - up.InterPt);
|
|
|
|
ElementTransformUtils.MoveElement(doc, up.PipeToMove.Id, tranVec);
|
|
lastRedDist = redDist;
|
|
}
|
|
|
|
lastRedDist = 0;
|
|
//기준파이프 아래쪽 파이프 리스트
|
|
foreach (MovePipeInfo dp in DownMpiLst)
|
|
{
|
|
double redDist = 0;
|
|
//XYZ vec = (dirPipeMidPt - lp.InterPt).Normalize();
|
|
XYZ vec = (new XYZ(0, 0, dirPipeMidPt.Z) - new XYZ(0, 0, dp.InterPt.Z)).Normalize();
|
|
if (dp.UserInsultionThick != dp.InsultionThick)
|
|
{
|
|
if (dp.UserInsultionThick > dp.InsultionThick)
|
|
redDist = dp.Distance - dlg.offsetValue + lastRedDist - (dp.UserInsultionThick - dp.InsultionThick);
|
|
else
|
|
redDist = dp.Distance - dlg.offsetValue + lastRedDist + (dp.InsultionThick - dp.UserInsultionThick);
|
|
}
|
|
else
|
|
redDist = dp.Distance - dlg.offsetValue + lastRedDist;
|
|
|
|
//redDist = rp.Distance - m_Offset + lastRedDist;
|
|
XYZ movePt = Util.Polar(dp.InterPt, vec, Unit.MMToFeet(redDist));
|
|
XYZ tranVec = (movePt - dp.InterPt);
|
|
|
|
ElementTransformUtils.MoveElement(doc, dp.PipeToMove.Id, tranVec);
|
|
lastRedDist = redDist;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 기준 배관으로 다른 배관들을 다른 리스트에 담아 분류하기
|
|
/// </summary>
|
|
/// <param name="infoTrue">리스트1</param>
|
|
/// <param name="infoFalse">리스트2</param>
|
|
public void DividePipesBasedOndirPipe(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 = dirPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
double Pipe1ODia = Unit.FeetToMM(Pipe1ODiaParam.AsDouble());
|
|
|
|
//pipe1 단열재 두께
|
|
Parameter pipe1InsulThickParam = dirPipe.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
|
|
double pipe1InsultionThick = Unit.FeetToMM(pipe1InsulThickParam.AsDouble());
|
|
|
|
LocationCurve Pipe1LC = dirPipe.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);
|
|
}
|
|
}
|
|
} |