Client/Desktop/KMBIM3.0/23.10.18/Cmd/PipeMatchInterval/PipeMatchInterval.cs

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);
}
}
}