329 lines
11 KiB
C#
329 lines
11 KiB
C#
//
|
|
// (C) Copyright 2003-2017 by Autodesk, Inc.
|
|
//
|
|
// Permission to use, copy, modify, and distribute this software in
|
|
// object code form for any purpose and without fee is hereby granted,
|
|
// provided that the above copyright notice appears in all copies and
|
|
// that both that copyright notice and the limited warranty and
|
|
// restricted rights notice below appear in all supporting
|
|
// documentation.
|
|
//
|
|
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
|
|
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
|
|
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
|
|
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
|
|
// UNINTERRUPTED OR ERROR FREE.
|
|
//
|
|
// Use, duplication, or disclosure by the U.S. Government is subject to
|
|
// restrictions set forth in FAR 52.227-19 (Commercial Computer
|
|
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
|
|
// (Rights in Technical Data and Computer Software), as applicable.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.DB.Electrical;
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using KDCS.Utils;
|
|
using KMBIM.Revit.Tools.Utils;
|
|
|
|
namespace KMBIM
|
|
{
|
|
/// <summary>
|
|
/// 이 클래스는 덕트 또는 파이프의 장애물을 나타내는 클래스
|
|
/// </summary>
|
|
|
|
|
|
public class SimpleSection
|
|
{
|
|
Document m_rvtDoc;
|
|
public Line Line { get; set; }
|
|
public Element ReferenceElement { get; set; }
|
|
public XYZ MidPoint { get; set; }
|
|
|
|
public SimpleSection(Document doc, Section section)
|
|
{
|
|
m_rvtDoc = doc;
|
|
XYZ sp = section.Start;
|
|
XYZ ep = section.End;
|
|
|
|
if (section.Refs[0].GetReference().LinkedElementId.IntegerValue != -1)
|
|
{
|
|
RevitLinkInstance rli = m_rvtDoc.GetElement(section.Refs[0].GetReference().ElementId) as RevitLinkInstance;
|
|
if (rli != null)
|
|
{
|
|
ReferenceElement = rli.GetLinkDocument().GetElement(section.Refs[0].GetReference().LinkedElementId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ReferenceElement = m_rvtDoc.GetElement(section.Refs[0].GetReference().ElementId);
|
|
}
|
|
|
|
|
|
this.Line = Line.CreateBound(sp, ep);
|
|
this.MidPoint = Util.Midpoint(sp, ep);
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<XYZ> GetIntersectUpperLower(XYZ vRay, View3D view3d)
|
|
{
|
|
List<XYZ> lstResut = new List<XYZ>();
|
|
|
|
ReferenceIntersector referenceIntersector= null;
|
|
if (ReferenceElement.Document.IsLinked)
|
|
{
|
|
List<BuiltInCategory> builtInCats = new List<BuiltInCategory>();
|
|
builtInCats.Add(BuiltInCategory.OST_StructuralFraming);
|
|
ElementMulticategoryFilter intersectFilter = new ElementMulticategoryFilter(builtInCats);
|
|
|
|
referenceIntersector = new ReferenceIntersector(intersectFilter, FindReferenceTarget.Face, view3d);
|
|
referenceIntersector.FindReferencesInRevitLinks = true;
|
|
|
|
|
|
}
|
|
else referenceIntersector = new ReferenceIntersector(ReferenceElement.Id, FindReferenceTarget.Face, view3d);
|
|
|
|
// 주어진 요소(eId)이 점과 방향으로 만들어진 광선과 교차하는 지 확인
|
|
IList<ReferenceWithContext> obstructionsOnUnboundLine = referenceIntersector.Find(MidPoint - vRay * 328.0, vRay);
|
|
foreach (ReferenceWithContext gRefWithContext in obstructionsOnUnboundLine)
|
|
{
|
|
Reference gRef = gRefWithContext.GetReference();
|
|
//var eId = gRef.GetReference().ElementId; // 링크된 모델인 경우 RevitLinkInstance ID
|
|
//var lId = gRef.GetReference().LinkedElementId; // 링코된 모델에 포함된 요소의 ID
|
|
|
|
|
|
XYZ itr = null;
|
|
if (gRef.LinkedElementId.IntegerValue != -1)
|
|
{
|
|
if (gRef.LinkedElementId != ReferenceElement.Id) continue;
|
|
RevitLinkInstance rli = m_rvtDoc.GetElement(gRef.ElementId) as RevitLinkInstance;
|
|
if (rli != null)
|
|
{
|
|
itr = rli.GetTransform().OfPoint(gRef.GlobalPoint);
|
|
}
|
|
else itr = gRef.GlobalPoint;
|
|
}
|
|
else itr = gRef.GlobalPoint;
|
|
bool bFound = false;
|
|
|
|
if(lstResut.Find(x => x.DistanceTo(itr) < 0.00328084) == null) lstResut.Add(itr);
|
|
|
|
}
|
|
return lstResut;
|
|
}
|
|
}
|
|
|
|
public class Section
|
|
{
|
|
private Document m_rvtDoc;
|
|
|
|
/// <summary>
|
|
/// Pipe centerline's direction.
|
|
/// </summary>
|
|
private Autodesk.Revit.DB.XYZ m_dir;
|
|
|
|
/// <summary>
|
|
/// Extend factor in negative direction.
|
|
/// </summary>
|
|
private double m_startFactor;
|
|
|
|
/// <summary>
|
|
/// Extend factor in positive direction.
|
|
/// </summary>
|
|
private double m_endFactor;
|
|
|
|
/// <summary>
|
|
/// References contained in this obstruction.
|
|
/// </summary>
|
|
private List<ReferenceWithContext> m_refs;
|
|
|
|
/// <summary>
|
|
/// Pipes to avoid this obstruction, it is assigned when resolving this obstruction.
|
|
/// Its count will be three if resolved, the three pipe constructs a "U" shape to round the obstruction.
|
|
/// </summary>
|
|
private List<Pipe> m_pipes;
|
|
private List<Duct> m_ducts;
|
|
private List<CableTray> m_cabletrays;
|
|
private List<Conduit> m_conduits;
|
|
public List<SimpleSection> m_mergedSections;
|
|
|
|
|
|
public KDCSIntersectorElement InterSectorElement { get; set; }
|
|
|
|
public XYZ Start1 { get; set; }
|
|
public XYZ End1 { get; set; }
|
|
|
|
public bool IsMerged { get; set; }
|
|
public Plane BasePlane { get; set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Private constructor, just be called in static factory method BuildSections.
|
|
/// </summary>
|
|
/// <param name="dir">Pipe's direction</param>
|
|
private Section(Document doc, Autodesk.Revit.DB.XYZ dir)
|
|
{
|
|
m_rvtDoc = doc;
|
|
m_dir = dir;
|
|
m_startFactor = 0;
|
|
m_endFactor = 0;
|
|
m_refs = new List<ReferenceWithContext>();
|
|
m_ducts = new List<Duct>();
|
|
m_pipes = new List<Pipe>();
|
|
m_cabletrays = new List<CableTray>();
|
|
m_conduits = new List<Conduit>();
|
|
m_mergedSections = new List<SimpleSection>();
|
|
IsMerged = false;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Pipe centerline's direction.
|
|
/// </summary>
|
|
public Autodesk.Revit.DB.XYZ CenterLineDirection
|
|
{
|
|
get { return m_dir; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pipes to avoid this obstruction, it is assigned when resolving this obstruction.
|
|
/// Its count will be three if resolved, the three pipe constructs a "U" shape to round the obstruction.
|
|
/// </summary>
|
|
public List<Pipe> Pipes
|
|
{
|
|
get { return m_pipes; }
|
|
}
|
|
|
|
|
|
public List<Duct> Ducts
|
|
{
|
|
get { return m_ducts; }
|
|
}
|
|
|
|
public List<CableTray> CableTrays
|
|
{
|
|
get { return m_cabletrays; }
|
|
}
|
|
|
|
public List<Conduit> Conduits
|
|
{
|
|
get { return m_conduits; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Start point of this obstruction.
|
|
/// </summary>
|
|
public Autodesk.Revit.DB.XYZ Start
|
|
{
|
|
get
|
|
{
|
|
return m_refs[0].GetReference().GlobalPoint + m_dir * m_startFactor;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// End point of this obstruction.
|
|
/// </summary>
|
|
public Autodesk.Revit.DB.XYZ End
|
|
{
|
|
get
|
|
{
|
|
return m_refs[m_refs.Count - 1].GetReference().GlobalPoint + m_dir * m_endFactor;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// References contained in this obstruction.
|
|
/// </summary>
|
|
public List<ReferenceWithContext> Refs
|
|
{
|
|
get { return m_refs; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extend this obstruction's interval in one direction.
|
|
/// </summary>
|
|
/// <param name="index">index of direction, 0 => start, 1 => end</param>
|
|
public void Inflate(int index, double value)
|
|
{
|
|
if (index == 0)
|
|
{
|
|
m_startFactor -= value;
|
|
}
|
|
else if(index == 1)
|
|
{
|
|
m_endFactor += value;
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentOutOfRangeException("Index should be 0 or 1.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 참조 섹션을 만듭니다. 섹션에는 광선이 장애물을 통과하는 여러 지점이 포함됩니다.
|
|
/// 장애물이 한개인 경우 2개의 점이, 두개인 경우 4개의 점이 포함됩니다.
|
|
/// </summary>
|
|
/// <param name="allrefs">참조</param>
|
|
/// <param name="dir">회피 요소의 방향</param>
|
|
/// <returns>섹션 목록</returns>
|
|
public static List<Section> BuildSections(Document doc, List<ReferenceWithContext> allrefs, Autodesk.Revit.DB.XYZ dir)
|
|
{
|
|
List<ReferenceWithContext> buildStack = new List<ReferenceWithContext>();
|
|
List<Section> sections = new List<Section>();
|
|
Section current = null;
|
|
foreach (ReferenceWithContext geoRef in allrefs)
|
|
{
|
|
if (buildStack.Count == 0)
|
|
{
|
|
current = new Section(doc, dir);
|
|
sections.Add(current);
|
|
}
|
|
|
|
current.Refs.Add(geoRef);
|
|
|
|
|
|
|
|
ReferenceWithContext tmp = Find(buildStack, geoRef);
|
|
if (tmp != null)
|
|
{
|
|
buildStack.Remove(tmp);
|
|
}
|
|
else
|
|
buildStack.Add(geoRef);
|
|
}
|
|
|
|
return sections;
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Judge whether a Reference is already in the list of Reference, return the founded value.
|
|
/// </summary>
|
|
/// <param name="arr">List of Reference</param>
|
|
/// <param name="entry">Reference to test</param>
|
|
/// <returns>One Reference has the same element's Id with entry</returns>
|
|
private static ReferenceWithContext Find(List<ReferenceWithContext> arr, ReferenceWithContext entry)
|
|
{
|
|
foreach (ReferenceWithContext tmp in arr)
|
|
{
|
|
if (tmp.GetReference().ElementId == entry.GetReference().ElementId)
|
|
{
|
|
return tmp;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|