//
// (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.Mechanical;
using Autodesk.Revit.DB.Plumbing;
namespace KMBIM
{
///
/// 이 클래스는 덕트 또는 파이프의 장애물을 나타내는 클래스
///
class Section
{
///
/// Pipe centerline's direction.
///
private Autodesk.Revit.DB.XYZ m_dir;
///
/// Extend factor in negative direction.
///
private double m_startFactor;
///
/// Extend factor in positive direction.
///
private double m_endFactor;
///
/// References contained in this obstruction.
///
private List m_refs;
///
/// 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.
///
private List m_pipes;
private List m_ducts;
public XYZ Start1 { get; set; }
public XYZ End1 { get; set; }
///
/// Private constructor, just be called in static factory method BuildSections.
///
/// Pipe's direction
private Section(Autodesk.Revit.DB.XYZ dir)
{
m_dir = dir;
m_startFactor = 0;
m_endFactor = 0;
m_refs = new List();
m_pipes = new List();
m_ducts = new List();
}
///
/// Pipe centerline's direction.
///
public Autodesk.Revit.DB.XYZ CenterLineDirection
{
get { return m_dir; }
}
///
/// 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.
///
public List Pipes
{
get { return m_pipes; }
}
public List Ducts
{
get { return m_ducts; }
}
///
/// Start point of this obstruction.
///
public Autodesk.Revit.DB.XYZ Start
{
get
{
return m_refs[0].GetReference().GlobalPoint + m_dir * m_startFactor;
}
}
///
/// End point of this obstruction.
///
public Autodesk.Revit.DB.XYZ End
{
get
{
return m_refs[m_refs.Count - 1].GetReference().GlobalPoint + m_dir * m_endFactor;
}
}
///
/// References contained in this obstruction.
///
public List Refs
{
get { return m_refs; }
}
///
/// Extend this obstruction's interval in one direction.
///
/// index of direction, 0 => start, 1 => end
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.");
}
}
///
/// Build sections for References, it's a factory method to build sections.
/// A section contains several points through which the ray passes the obstruction(s).
/// for example, a section may contain 2 points when the obstruction is stand alone,
/// or contain 4 points if 2 obstructions are intersects with each other in the direction of the ray.
///
/// References
/// Pipe's direction
/// List of Section
public static List BuildSections(List allrefs, Autodesk.Revit.DB.XYZ dir)
{
List buildStack = new List();
List sections = new List();
Section current = null;
foreach (ReferenceWithContext geoRef in allrefs)
{
if (buildStack.Count == 0)
{
current = new Section(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;
}
///
/// Judge whether a Reference is already in the list of Reference, return the founded value.
///
/// List of Reference
/// Reference to test
/// One Reference has the same element's Id with entry
private static ReferenceWithContext Find(List arr, ReferenceWithContext entry)
{
foreach (ReferenceWithContext tmp in arr)
{
if (tmp.GetReference().ElementId == entry.GetReference().ElementId)
{
return tmp;
}
}
return null;
}
}
}