975 lines
32 KiB
C#
975 lines
32 KiB
C#
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using Autodesk.Revit.UI;
|
|
using KMBIM.Utils;
|
|
using KMBIM.Revit.Tools.Utils;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using KDCS.Utils;
|
|
|
|
namespace KMBIM.Revit.Tools.Cmd.PipeConnection
|
|
{
|
|
|
|
public class ResolverForPipeConnect
|
|
{
|
|
public enum EnumResolverMode
|
|
{
|
|
Undef,
|
|
RefBaseModelLine,
|
|
Prev,
|
|
Next,
|
|
Run,
|
|
Close
|
|
}
|
|
|
|
private UIApplication m_rvtUIApp;
|
|
private UIDocument m_rvtUIDoc;
|
|
private Document m_rvtDoc;
|
|
private Autodesk.Revit.ApplicationServices.Application m_rvtApp;
|
|
public Autodesk.Revit.UI.UIDocument uidoc { get; set; }
|
|
private int m_inx;
|
|
private bool m_bFlexible;
|
|
private bool m_bRefFloorBaseLine;
|
|
|
|
|
|
Dictionary<string, List<XYZ>> m_Routes = new Dictionary<string, List<XYZ>>();
|
|
List<Pipe> lstCurve = new List<Pipe>();
|
|
|
|
EnumResolverMode m_ResolverMode;
|
|
|
|
|
|
ElementId systemTypeId = null;
|
|
Element m_baseElementOrigin = null;
|
|
Element m_baseElement = null;
|
|
Element m_targetElement = null;
|
|
Connector m_baseConnectorOrigin = null;
|
|
Connector m_baseConnector = null;
|
|
Connector m_targetConnector = null;
|
|
Pipe basePipe = null;
|
|
Pipe targetPipe = null;
|
|
PipeType pipeType = null;
|
|
FlexPipeType flexPipeType = null;
|
|
private double m_pipeDiameter;
|
|
|
|
|
|
|
|
//private int m_LineStyle = (int)BuiltInCategory.OST_HiddenLines;
|
|
private int m_LineStyle = (int)BuiltInCategory.OST_Lines;
|
|
|
|
|
|
public ResolverForPipeConnect(UIApplication uiapp)
|
|
{
|
|
m_rvtUIApp = uiapp;
|
|
m_rvtApp = uiapp.Application;
|
|
m_rvtUIDoc = uiapp.ActiveUIDocument;
|
|
m_rvtDoc = m_rvtUIDoc.Document;
|
|
m_inx = 0;
|
|
m_bFlexible = false;
|
|
m_bRefFloorBaseLine = false;
|
|
}
|
|
|
|
public void SetRefFloorBaseLine(bool bRefFloorBaseLine)
|
|
{
|
|
m_bRefFloorBaseLine = bRefFloorBaseLine;
|
|
}
|
|
|
|
|
|
public void SetResolverMode(EnumResolverMode mode)
|
|
{
|
|
m_ResolverMode = mode;
|
|
}
|
|
|
|
public void SetRoute(ref Dictionary<string, List<XYZ>> route)
|
|
{
|
|
this.m_Routes = route;
|
|
m_inx = 0;
|
|
|
|
}
|
|
|
|
public void SetPipeDiameter(double dia)
|
|
{
|
|
m_pipeDiameter = dia;
|
|
}
|
|
|
|
|
|
public void SetBaseElementOrigin(Element elm, Connector con)
|
|
{
|
|
this.m_baseElementOrigin = elm;
|
|
this.m_baseConnectorOrigin = con;
|
|
Pipe pipe1 = elm as Pipe;
|
|
if (pipe1 != null)
|
|
{
|
|
this.pipeType = pipe1.PipeType;
|
|
if (systemTypeId == null)
|
|
{
|
|
systemTypeId = pipe1.MEPSystem.GetTypeId();
|
|
}
|
|
}else if(con != null){
|
|
if (con.MEPSystem != null)
|
|
{
|
|
systemTypeId = con.MEPSystem.GetTypeId();
|
|
}
|
|
}
|
|
}
|
|
public void SetElement(Element e1, Element e2)
|
|
{
|
|
this.m_baseElement = e1;
|
|
this.m_targetElement = e2;
|
|
|
|
if (pipeType == null)
|
|
{
|
|
Pipe pipe1 = e1 as Pipe;
|
|
if (pipe1 != null)
|
|
{
|
|
this.pipeType = pipe1.PipeType;
|
|
}
|
|
else
|
|
{
|
|
Pipe pipe2 = e2 as Pipe;
|
|
if (pipe2 != null)
|
|
{
|
|
this.pipeType = pipe2.PipeType;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void SetConnector(Connector c1, Connector c2)
|
|
{
|
|
this.m_baseConnector = c1;
|
|
this.m_targetConnector = c2;
|
|
}
|
|
|
|
public void GetRoute(ref Dictionary<string, List<XYZ>> route)
|
|
{
|
|
route = this.m_Routes;
|
|
|
|
}
|
|
|
|
public int GetIndex()
|
|
{
|
|
return this.m_Routes.Keys.Count > 0 ? m_inx % this.m_Routes.Keys.Count : m_inx;
|
|
}
|
|
|
|
public void MoveNext()
|
|
{
|
|
if (m_inx >= (m_Routes.Keys.Count - 1)) m_inx = 0;
|
|
else m_inx += 1;
|
|
|
|
}
|
|
|
|
public void MovePrevious()
|
|
{
|
|
|
|
if (m_inx > 0)
|
|
{
|
|
m_inx -= 1;
|
|
}
|
|
}
|
|
|
|
public void SetSystemType(ElementId systemtypeid)
|
|
{
|
|
this.systemTypeId = systemtypeid;
|
|
}
|
|
|
|
public ElementId GetSystemType()
|
|
{
|
|
return this.systemTypeId;
|
|
}
|
|
|
|
private void DrawRoute()
|
|
{
|
|
if (this.m_Routes == null) return;
|
|
if (this.m_Routes.Count < 1) return;
|
|
|
|
var levelId = m_baseElement.LevelId;
|
|
Pipe pipeBase = m_baseElement as Pipe;
|
|
if (pipeBase != null)
|
|
{
|
|
levelId = pipeBase.ReferenceLevel.Id;
|
|
}
|
|
|
|
if (this.pipeType == null)
|
|
{
|
|
var pipeTypes = new FilteredElementCollector(m_rvtDoc).OfClass(typeof(PipeType)).ToElements();
|
|
if (pipeTypes.Count > 0)
|
|
{
|
|
pipeType = pipeTypes[pipeTypes.Count - 1] as PipeType;
|
|
}
|
|
}
|
|
|
|
var lst = this.m_Routes[(m_inx + 1).ToString()];
|
|
if (lst == null) return;
|
|
|
|
using (Transaction tr = new Transaction(m_rvtDoc, "Create3DModelLine"))
|
|
{
|
|
tr.Start();
|
|
// Line is slightly off axis and may cause inaccuracies.
|
|
// (선이 축을 약간 벗어났습니다.부정확새질 수 있습니다.)
|
|
// => This is not an error, it is a warning. You can pass warnings but can't pass errors.
|
|
FailureHandlingOptions failureHandlingOptions = tr.GetFailureHandlingOptions();
|
|
failureHandlingOptions.SetFailuresPreprocessor(new KdcsFailureHandler());
|
|
tr.SetFailureHandlingOptions(failureHandlingOptions);
|
|
for (int i = 0; i < lst.Count - 1; i++)
|
|
{
|
|
XYZ p1 = lst[i];
|
|
XYZ p2 = lst[i + 1];
|
|
var crv = Pipe.CreatePlaceholder(m_rvtDoc, systemTypeId, pipeType.Id, levelId, p1, p2);
|
|
if (crv != null) lstCurve.Add(crv);
|
|
}
|
|
|
|
|
|
if (lstCurve.Count > 2)
|
|
{
|
|
for (int i = 0; i < lstCurve.Count - 1; i++)
|
|
{
|
|
Pipe pipe1 = lstCurve.ElementAt(i);
|
|
Pipe pipe2 = lstCurve.ElementAt(i+1);
|
|
Connector sc1, ec1, sc2, ec2;
|
|
sc1=ec1=sc2=ec2=null;
|
|
Util.GetStartEndConnector(pipe1, ref sc1, ref ec1);
|
|
Util.GetStartEndConnector(pipe2, ref sc2, ref ec2);
|
|
ec1.ConnectTo(sc2);
|
|
}
|
|
}
|
|
tr.Commit();
|
|
}
|
|
}
|
|
|
|
public void DeleteCurves()
|
|
{
|
|
if (lstCurve.Count < 1) return;
|
|
using (Transaction tr = new Transaction(m_rvtDoc, "Delete Curves"))
|
|
{
|
|
tr.Start();
|
|
foreach (var crv in lstCurve)
|
|
{
|
|
m_rvtDoc.Delete(crv.Id);
|
|
}
|
|
lstCurve.Clear();
|
|
tr.Commit();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public void SetFlexible(bool bFlexible)
|
|
{
|
|
m_bFlexible = bFlexible;
|
|
}
|
|
|
|
public void Run()
|
|
{
|
|
try
|
|
{
|
|
if (this.m_ResolverMode == EnumResolverMode.Prev)
|
|
{
|
|
DeleteCurves();
|
|
m_inx = GetIndex();
|
|
DrawRoute();
|
|
|
|
}
|
|
else if (this.m_ResolverMode == EnumResolverMode.Next)
|
|
{
|
|
DeleteCurves();
|
|
m_inx = GetIndex();
|
|
DrawRoute();
|
|
|
|
}
|
|
else if(this.m_ResolverMode == EnumResolverMode.Run)
|
|
{
|
|
|
|
basePipe = m_baseElement as Pipe;
|
|
targetPipe = m_targetElement as Pipe;
|
|
|
|
|
|
|
|
if (this.pipeType == null)
|
|
{
|
|
var pipeTypes = new FilteredElementCollector(m_rvtDoc).OfClass(typeof(PipeType)).ToElements();
|
|
if (pipeTypes.Count > 0)
|
|
{
|
|
pipeType = pipeTypes[pipeTypes.Count - 1] as PipeType;
|
|
}
|
|
}
|
|
|
|
if (this.flexPipeType == null)
|
|
{
|
|
var pipeTypes = new FilteredElementCollector(m_rvtDoc).OfClass(typeof(FlexPipeType)).ToElements();
|
|
if (pipeTypes.Count > 0)
|
|
{
|
|
flexPipeType = pipeTypes[pipeTypes.Count - 1] as FlexPipeType;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (pipeType != null)
|
|
{
|
|
using (Transaction tr = new Transaction(m_rvtDoc, "CreatePipes"))
|
|
{
|
|
tr.Start();
|
|
CreatePipe(m_rvtDoc, lstCurve);
|
|
tr.Commit();
|
|
}
|
|
|
|
}
|
|
DeleteCurves();
|
|
App.thisApp.m_wfPipeConnector.Close();
|
|
|
|
}
|
|
else if (this.m_ResolverMode == EnumResolverMode.Close)
|
|
{
|
|
DeleteCurves();
|
|
}
|
|
|
|
m_rvtUIDoc.RefreshActiveView();
|
|
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
}
|
|
|
|
// Clamps value between 0 and 1 and returns value
|
|
public static float Clamp01(float value)
|
|
{
|
|
if (value < 0F)
|
|
return 0F;
|
|
else if (value > 1F)
|
|
return 1F;
|
|
else
|
|
return value;
|
|
}
|
|
|
|
public static float InverseLerp(float a, float b, float value)
|
|
{
|
|
if (a != b)
|
|
return Clamp01((value - a) / (b - a));
|
|
else
|
|
return 0.0f;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 주어진 arrayToCurve 점들을 이용하여 커브점을 만들어 넘겨준다.
|
|
/// </summary>
|
|
/// <param name="arrayToCurve">정점 배열</param>
|
|
/// <param name="smoothness">보간 수</param>
|
|
/// <returns></returns>
|
|
public static XYZ[] MakeSmoothCurve(XYZ[] arrayToCurve, float smoothness)
|
|
{
|
|
List<XYZ> points;
|
|
List<XYZ> curvedPoints;
|
|
int pointsLength = 0;
|
|
int curvedLength = 0;
|
|
|
|
if (smoothness < 1.0f) smoothness = 1.0f;
|
|
pointsLength = arrayToCurve.Length;
|
|
curvedLength = (pointsLength * Convert.ToInt16(Math.Round(smoothness))) - 1;
|
|
curvedPoints = new List<XYZ>(curvedLength);
|
|
float t = 0.0f;
|
|
for (int pointInTimeOnCurve = 0; pointInTimeOnCurve < curvedLength + 1; pointInTimeOnCurve++)
|
|
{
|
|
t = InverseLerp(0, curvedLength, pointInTimeOnCurve);
|
|
points = new List<XYZ>(arrayToCurve);
|
|
for (int j = pointsLength - 1; j > 0; j--)
|
|
{
|
|
for (int i = 0; i < j; i++)
|
|
{
|
|
points[i] = (1 - t) * points[i] + t * points[i + 1];
|
|
}
|
|
}
|
|
curvedPoints.Add(points[0]);
|
|
}
|
|
return (curvedPoints.ToArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 파이프 생성
|
|
/// </summary>
|
|
/// <param name="document"></param>
|
|
/// <param name="elementList"></param>
|
|
/// <param name="basePipe"></param>
|
|
public void CreatePipe(Document document, List<Pipe> curveList)
|
|
{
|
|
|
|
//var paramLevel = m_baseElement.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
|
|
var levelId = m_baseElement.LevelId; //.IntegerValue != -1 ? m_baseElement.LevelId : m_targetElement.LevelId;
|
|
Pipe pipeBase = m_baseElement as Pipe;
|
|
if (pipeBase != null)
|
|
{
|
|
levelId = pipeBase.ReferenceLevel.Id;
|
|
}
|
|
|
|
|
|
if (pipeType == null) return;
|
|
|
|
|
|
List<XYZ> lst = new List<XYZ>();
|
|
bool isFirst = true;
|
|
foreach (var pip in curveList)
|
|
{
|
|
LocationCurve locCrv = pip.Location as LocationCurve;
|
|
XYZ sp = locCrv.Curve.GetEndPoint(0);
|
|
XYZ ep = locCrv.Curve.GetEndPoint(1);
|
|
if (isFirst)
|
|
{
|
|
if (m_baseConnector.Origin.DistanceTo(sp) > m_baseConnector.Origin.DistanceTo(ep))
|
|
{
|
|
Util.Swap(ref sp, ref ep);
|
|
}
|
|
lst.Add(sp);
|
|
lst.Add(ep);
|
|
|
|
}
|
|
else
|
|
{
|
|
XYZ pLast = lst.Last();
|
|
if(pLast.DistanceTo(sp) > pLast.DistanceTo(ep)) lst.Add(sp);
|
|
else lst.Add(ep);
|
|
}
|
|
isFirst = false;
|
|
}
|
|
|
|
Pipe newPipe = null;
|
|
XYZ start = null;
|
|
XYZ end = null;
|
|
XYZ splitpoint = null;
|
|
List<XYZ> lstTmp = new List<XYZ>();
|
|
List<XYZ> lstCrv = new List<XYZ>();
|
|
if (m_bFlexible && flexPipeType!=null)
|
|
{
|
|
|
|
//var lst = this.m_Routes[(m_inx + 1).ToString()];
|
|
if (lst.Count > 2)
|
|
{
|
|
lstTmp.Add(lst.First());
|
|
int dur = lst.Count - 1;
|
|
for (int i = 1; i < dur; i++)
|
|
{
|
|
|
|
|
|
XYZ fp0 = lst.ElementAt(i-1);
|
|
XYZ fp1 = lst.ElementAt(i);
|
|
XYZ fp2 = lst.ElementAt(i + 1);
|
|
|
|
XYZ fpInsm = fp1 + (fp0 - fp1).Normalize() * fp0.DistanceTo(fp1) * 0.5;
|
|
XYZ fpIns0 = fp1 + (fp0 - fp1).Normalize() * m_pipeDiameter * 5;
|
|
XYZ fpIns1 = fp1 + (fp0 - fp1).Normalize() * m_pipeDiameter * 4;
|
|
XYZ fpIns2 = fp1 + (fp0 - fp1).Normalize() * m_pipeDiameter * 3.0;
|
|
XYZ fpIns3 = fp1 + (fp2 - fp1).Normalize() * m_pipeDiameter * 3.0;
|
|
XYZ fpIns4 = fp1 + (fp2 - fp1).Normalize() * m_pipeDiameter * 4;
|
|
XYZ fpIns5 = fp1 + (fp2 - fp1).Normalize() * m_pipeDiameter * 5;
|
|
|
|
lstCrv.Clear();
|
|
lstCrv.Add(fpIns0);
|
|
lstCrv.Add(fpIns1);
|
|
lstCrv.Add(fpIns2);
|
|
lstCrv.Add(fpIns3);
|
|
lstCrv.Add(fpIns4);
|
|
lstCrv.Add(fpIns5);
|
|
var inArr = lstCrv.ToArray();
|
|
var arrcrv = MakeSmoothCurve(inArr, 1.5f);
|
|
lstTmp.Add(fpInsm);
|
|
lstTmp.AddRange(arrcrv);
|
|
|
|
}
|
|
XYZ plp = lst.ElementAt(lst.Count - 2);
|
|
XYZ pll = lst.Last();
|
|
lstTmp.Add(Util.Midpoint(plp, pll));
|
|
lstTmp.Add(lst.Last());
|
|
|
|
lst = lstTmp.ToList();
|
|
}
|
|
FlexPipe newFlexPipe = FlexPipe.Create(m_rvtDoc, systemTypeId, flexPipeType.Id, levelId, lst.ToArray());
|
|
|
|
if (newFlexPipe != null)
|
|
{
|
|
LocationCurve locCrv = newFlexPipe.Location as LocationCurve;
|
|
if (locCrv != null)
|
|
{
|
|
newFlexPipe.StartTangent = m_baseConnector.CoordinateSystem.BasisZ;
|
|
newFlexPipe.EndTangent = m_targetConnector.CoordinateSystem.BasisZ;
|
|
}
|
|
|
|
newFlexPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(m_pipeDiameter);
|
|
Connector pipeConnectorFirst = FindConnector(newFlexPipe, m_baseConnector.CoordinateSystem.Origin);
|
|
if (pipeConnectorFirst != null)
|
|
{
|
|
if (Util.IsEqual(m_baseConnector.Radius, pipeConnectorFirst.Radius))
|
|
{
|
|
pipeConnectorFirst.ConnectTo(m_baseConnector);
|
|
}
|
|
else
|
|
{
|
|
try{
|
|
m_rvtDoc.Create.NewTransitionFitting(pipeConnectorFirst, m_baseConnector);
|
|
}
|
|
catch (Autodesk.Revit.Exceptions.InvalidOperationException ex)
|
|
{
|
|
MessageBox.Show("기준 커넥터 위치에 변환 피팅을 삽입할 수 없습니다.");
|
|
|
|
}
|
|
catch (Exception ex) { }
|
|
}
|
|
|
|
}
|
|
|
|
Connector pipeConnectorLast = FindConnector(newFlexPipe, m_targetConnector.CoordinateSystem.Origin);
|
|
if (Util.IsEqual(m_targetConnector.Radius, pipeConnectorLast.Radius))
|
|
{
|
|
pipeConnectorLast.ConnectTo(m_targetConnector);
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
m_rvtDoc.Create.NewTransitionFitting(pipeConnectorLast, m_targetConnector);
|
|
}
|
|
catch (Autodesk.Revit.Exceptions.InvalidOperationException ex)
|
|
{
|
|
MessageBox.Show("대상 커넥터 위치에 변환 피팅을 삽입할 수 없습니다.");
|
|
|
|
}
|
|
catch (Exception ex) { }
|
|
}
|
|
|
|
m_rvtDoc.Regenerate();
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 경로선
|
|
List<Line> lines = new List<Line>();
|
|
foreach (Pipe pipe in curveList)
|
|
{
|
|
Line line = (pipe.Location as LocationCurve).Curve as Line;
|
|
lines.Add(line);
|
|
}
|
|
|
|
//PlumbingUtils.ConvertPipePlaceholders(document, lines);
|
|
|
|
if (basePipe != null)
|
|
{
|
|
Line crv2 = lines.First();
|
|
Line crv1 = (basePipe.Location as LocationCurve).Curve as Line;
|
|
if (Util.IsParallel(crv1.Direction, crv2.Direction))
|
|
{
|
|
XYZ ptBase = m_baseConnector.CoordinateSystem.Origin;
|
|
|
|
if (crv2.GetEndPoint(0).DistanceTo(ptBase) > crv2.GetEndPoint(1).DistanceTo(ptBase))
|
|
Util.SetPipeEnd(basePipe, crv2.GetEndPoint(0));
|
|
else
|
|
Util.SetPipeEnd(basePipe, crv2.GetEndPoint(1));
|
|
|
|
|
|
lines.RemoveAt(0);
|
|
}
|
|
}
|
|
|
|
|
|
List<Pipe> pipes = new List<Pipe>();
|
|
foreach (Line line in lines)
|
|
{
|
|
start = line.GetEndPoint(0);
|
|
end = line.GetEndPoint(1);
|
|
|
|
newPipe = Pipe.Create(document, systemTypeId, pipeType.Id, levelId, start, end);
|
|
|
|
pipes.Add(newPipe);
|
|
|
|
newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(m_pipeDiameter);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 파이프 연결
|
|
for (int i = 1; i < pipes.Count(); i++)
|
|
{
|
|
Bend(pipes[i - 1], pipes[i]);
|
|
}
|
|
document.Regenerate();
|
|
|
|
if (basePipe != null)
|
|
{
|
|
var pipeFirst = pipes.First();
|
|
Bend(basePipe, pipeFirst);
|
|
|
|
}
|
|
else
|
|
{
|
|
// 베이스 커넥터와 첫번째 파이프 연결
|
|
var pipeFirst = pipes.First();
|
|
Connector pipeConnectorFirst = FindConnector(pipeFirst, m_baseConnector.CoordinateSystem.Origin);
|
|
if (pipeConnectorFirst != null)
|
|
{
|
|
if (Util.IsEqual(m_baseConnector.Radius, pipeConnectorFirst.Radius))
|
|
{
|
|
pipeConnectorFirst.ConnectTo(m_baseConnector);
|
|
}
|
|
else m_rvtDoc.Create.NewTransitionFitting(pipeConnectorFirst, m_baseConnector);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
var pipeLast = pipes.Last();
|
|
if (targetPipe != null)
|
|
{
|
|
|
|
Bend(targetPipe, pipeLast);
|
|
|
|
}
|
|
else
|
|
{
|
|
Connector pipeConnectorLast = FindConnector(pipeLast, m_targetConnector.CoordinateSystem.Origin);
|
|
if (Util.IsEqual(m_targetConnector.Radius, pipeConnectorLast.Radius))
|
|
{
|
|
pipeConnectorLast.ConnectTo(m_targetConnector);
|
|
}
|
|
else m_rvtDoc.Create.NewTransitionFitting(pipeConnectorLast, m_targetConnector);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
private XYZ ParallelInters(Line crv1, Line crv2)
|
|
{
|
|
|
|
XYZ itr = null;
|
|
double tol = 0.0328084; // ft = 1cm
|
|
double min_len = double.MaxValue;
|
|
|
|
if (crv1.GetEndPoint(0).DistanceTo(crv2.GetEndPoint(0)) < tol)
|
|
{
|
|
itr = crv1.GetEndPoint(0);
|
|
}
|
|
|
|
if (crv1.GetEndPoint(0).DistanceTo(crv2.GetEndPoint(1)) < tol)
|
|
{
|
|
itr = crv1.GetEndPoint(0);
|
|
}
|
|
else if (crv1.GetEndPoint(1).DistanceTo(crv2.GetEndPoint(0)) < tol)
|
|
{
|
|
itr = crv1.GetEndPoint(1);
|
|
}
|
|
else if (crv1.GetEndPoint(1).DistanceTo(crv2.GetEndPoint(1)) < tol)
|
|
{
|
|
itr = crv1.GetEndPoint(1);
|
|
}
|
|
return itr;
|
|
}
|
|
/// <summary>
|
|
/// 주어진 두개으 파이프를 엘보로 연결한다.
|
|
/// </summary>
|
|
/// <param name="pipe1"></param>
|
|
/// <param name="pipe2"></param>
|
|
public void Bend(Pipe pipe1, Pipe pipe2)
|
|
{
|
|
|
|
Autodesk.Revit.DB.Parameter paramLevel = pipe1.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
|
|
ElementId levelId = paramLevel.AsElementId();
|
|
|
|
|
|
|
|
|
|
Line crv1 = (pipe1.Location as LocationCurve).Curve as Line;
|
|
Line crv2 = (pipe2.Location as LocationCurve).Curve as Line;
|
|
|
|
XYZ itr = null;
|
|
if(Util.IsParallel(crv1.Direction, crv2.Direction)){
|
|
itr = ParallelInters(crv1, crv2);
|
|
}
|
|
else
|
|
{
|
|
itr = Util.GetCurvesIntersectionPoint(crv1, crv2);
|
|
}
|
|
// 2개의 파이프가 서로 만나는 쪽의 커텍터 찾기
|
|
Connector connector1 = FindConnector(pipe1, itr);
|
|
Connector connector2 = FindConnector(pipe2, itr);
|
|
|
|
FamilyInstance fii = null;
|
|
if (connector1 != null && connector2 != null)
|
|
{
|
|
|
|
double tol = 0.001;
|
|
if (Util.IsZero(connector1.CoordinateSystem.BasisZ.CrossProduct(connector2.CoordinateSystem.BasisZ).GetLength(), tol)) // 0.001ft = 0.3048 mm 어느 정도 2개 객체가 수평하면
|
|
{
|
|
|
|
try
|
|
{
|
|
List<Element> lstElement2BeDeleted = new List<Element>();
|
|
Resolver resolver = new Resolver(m_rvtDoc);
|
|
resolver.JoinPipeSegment(connector1, ref connector2, ref lstElement2BeDeleted);
|
|
if (lstElement2BeDeleted.Count > 0)
|
|
{
|
|
foreach (var el in lstElement2BeDeleted)
|
|
{
|
|
m_rvtDoc.Delete(el.Id);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
catch (Exception ex) {
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
try
|
|
{
|
|
fii = m_rvtDoc.Create.NewElbowFitting(connector1, connector2);
|
|
}
|
|
catch (ArgumentNullException ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
catch(Exception ex){
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Copy parameters from source pipe to target pipe.
|
|
/// </summary>
|
|
/// <param name="source">Coping source</param>
|
|
/// <param name="target">Coping target</param>
|
|
private void CopyParameters(Pipe source, Pipe target)
|
|
{
|
|
double diameter = source.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble();
|
|
target.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(diameter);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Filter the inputting References, just allow Pipe, Duct and Beam References.
|
|
/// </summary>
|
|
/// <param name="pipe">Pipe</param>
|
|
/// <param name="refs">References to filter</param>
|
|
private void Filter(Pipe pipe, List<ReferenceWithContext> refs)
|
|
{
|
|
for (int i = refs.Count - 1; i >= 0; i--)
|
|
{
|
|
Reference cur = refs[i].GetReference();
|
|
Element curElem = m_rvtDoc.GetElement(cur);
|
|
if (curElem.Id == pipe.Id ||
|
|
(!(curElem is Pipe) &&
|
|
curElem.Category.Id.IntegerValue != (int)BuiltInCategory.OST_StructuralFraming))
|
|
{
|
|
refs.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Line FindParallelLine(Section section, Autodesk.Revit.DB.XYZ dir, double height)
|
|
{
|
|
Autodesk.Revit.DB.XYZ detal = dir * height;
|
|
Line line = Line.CreateBound(section.Start + detal, section.End + detal);
|
|
return line;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find out two References, whose ProximityParameter is negative or positive,
|
|
/// And Get the minimal value from all positive reference, and get the maximal value
|
|
/// from the negative reference. if there are no such reference, using null instead.
|
|
/// </summary>
|
|
/// <param name="refs">References</param>
|
|
/// <returns>Reference array</returns>
|
|
private ReferenceWithContext[] GetClosestSectionsToOrigin(List<ReferenceWithContext> refs)
|
|
{
|
|
ReferenceWithContext[] mins = new ReferenceWithContext[2];
|
|
if (refs.Count == 0)
|
|
{
|
|
return mins;
|
|
}
|
|
|
|
if (refs[0].Proximity > 0)
|
|
{
|
|
mins[1] = refs[0];
|
|
return mins;
|
|
}
|
|
|
|
for (int i = 0; i < refs.Count - 1; i++)
|
|
{
|
|
if (refs[i].Proximity < 0 && refs[i + 1].Proximity > 0)
|
|
{
|
|
mins[0] = refs[i];
|
|
mins[1] = refs[i + 1];
|
|
return mins;
|
|
}
|
|
}
|
|
|
|
mins[0] = refs[refs.Count - 1];
|
|
|
|
return mins;
|
|
}
|
|
|
|
public void MepSystem()
|
|
{
|
|
Document doc = m_rvtDoc;
|
|
FilteredElementCollector systemCollector = new FilteredElementCollector(doc).OfClass(typeof(MEPSystem));
|
|
|
|
IEnumerable<Element> desirableSystems = systemCollector.ToElements();
|
|
foreach (Element elm in desirableSystems)
|
|
{
|
|
MEPSystem system = elm as MEPSystem;
|
|
if (system != null)
|
|
{
|
|
if (system.GetType() == typeof(Autodesk.Revit.DB.Plumbing.PipingSystem))
|
|
{
|
|
Autodesk.Revit.DB.Plumbing.PipeSystemType type = (system as Autodesk.Revit.DB.Plumbing.PipingSystem).SystemType;
|
|
}
|
|
string name = system.Name;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public Pipe CreateNewPipe(Document document, ElementId systemTypeId, ElementId levelId)
|
|
{
|
|
Pipe pipe = null;
|
|
PipeType pipeType = null;
|
|
// find a pipe type
|
|
var pipeTypes = new FilteredElementCollector(document).OfClass(typeof(PipeType)).ToElements();
|
|
if (pipeTypes.Count > 0)
|
|
{
|
|
pipeType = pipeTypes[pipeTypes.Count - 1] as PipeType;
|
|
}
|
|
|
|
if (pipeType == null) return null;
|
|
|
|
|
|
// create pipe between 2 points
|
|
XYZ p1 = new XYZ(0, 0, 0);
|
|
XYZ p2 = new XYZ(10, 0, 0);
|
|
|
|
pipe = Pipe.Create(document, systemTypeId, pipeType.Id, levelId, p1, p2);
|
|
|
|
return pipe;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 주어진 점에서 가장 가까운 연결점을 찾는다.
|
|
/// </summary>
|
|
/// <param name="pipe"></param>
|
|
/// <param name="conXYZ"></param>
|
|
/// <returns></returns>
|
|
private Connector FindConnector(Pipe pipe, Autodesk.Revit.DB.XYZ conXYZ)
|
|
{
|
|
ConnectorSet conns = pipe.ConnectorManager.Connectors;
|
|
double minDst = double.MaxValue;
|
|
Connector closestConnector = null;
|
|
foreach (Connector conn in conns)
|
|
{
|
|
if (conn.Origin.DistanceTo(conXYZ) < minDst)
|
|
{
|
|
minDst = conn.Origin.DistanceTo(conXYZ);
|
|
closestConnector = conn;
|
|
}
|
|
}
|
|
return closestConnector;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 주어진 점에서 가장 가까운 연결점을 찾는다.
|
|
/// </summary>
|
|
/// <param name="pipe"></param>
|
|
/// <param name="conXYZ"></param>
|
|
/// <returns></returns>
|
|
private Connector FindConnector(FlexPipe pipe, Autodesk.Revit.DB.XYZ conXYZ)
|
|
{
|
|
ConnectorSet conns = pipe.ConnectorManager.Connectors;
|
|
double minDst = double.MaxValue;
|
|
Connector closestConnector = null;
|
|
foreach (Connector conn in conns)
|
|
{
|
|
if (conn.Origin.DistanceTo(conXYZ) < minDst)
|
|
{
|
|
minDst = conn.Origin.DistanceTo(conXYZ);
|
|
closestConnector = conn;
|
|
}
|
|
}
|
|
return closestConnector;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Find out the connector which the pipe's specified connector connected to.
|
|
/// The pipe's specified connector is given by point conxyz.
|
|
/// </summary>
|
|
/// <param name="pipe">Pipe to find the connector</param>
|
|
/// <param name="conXYZ">Specified point</param>
|
|
/// <returns>Connector whose origin is conXYZ</returns>
|
|
private Connector FindConnectedTo(Pipe pipe, Autodesk.Revit.DB.XYZ conXYZ)
|
|
{
|
|
Connector connItself = FindConnector(pipe, conXYZ);
|
|
ConnectorSet connSet = connItself.AllRefs;
|
|
foreach (Connector conn in connSet)
|
|
{
|
|
if (conn.Owner.Id.IntegerValue != pipe.Id.IntegerValue &&
|
|
conn.ConnectorType == ConnectorType.End)
|
|
{
|
|
return conn;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
}
|
|
}
|