//
// (C) Copyright 2003-2019 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.
//
namespace Revit.SDK.Samples.CreateBeamSystem.CS
{
using System;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Collections.ObjectModel;
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Structure;
///
/// mixed data class save the data to show in UI
/// and the data used to create beam system
///
public class BeamSystemData
{
///
/// all beam types loaded in current Revit project
/// it is declared as static only because of PropertyGrid
///
private static Dictionary m_beamTypes = new Dictionary();
///
/// properties of beam system
///
private BeamSystemParam m_param;
///
/// buffer of ExternalCommandData
///
private ExternalCommandData m_commandData;
///
/// the lines compose the profile of beam system
///
private List m_lines = new List();
///
/// a number of beams that intersect end to end
/// so that form a profile used as beam system's profile
///
private List m_beams = new List();
///
/// properties of beam system
///
public BeamSystemParam Param
{
get
{
return m_param;
}
}
///
/// lines form the profile of beam system
///
public ReadOnlyCollection Lines
{
get
{
return new ReadOnlyCollection(m_lines);
}
}
///
/// buffer of ExternalCommandData
///
public ExternalCommandData CommandData
{
get
{
return m_commandData;
}
}
///
/// the data used to show in UI is updated
///
public event EventHandler ParamsUpdated;
///
/// constructor
/// if precondition in current Revit project isn't enough,
/// ErrorMessageException will be throw out
///
/// data from Revit
public BeamSystemData(ExternalCommandData commandData)
{
// initialize members
m_commandData = commandData;
PrepareData();
InitializeProfile(m_beams);
m_param = BeamSystemParam.CreateInstance(LayoutMethod.ClearSpacing);
List beamTypes = new List(m_beamTypes.Values);
m_param.BeamType = beamTypes[0];
m_param.LayoutRuleChanged += new LayoutRuleChangedHandler(LayoutRuleChanged);
}
///
/// change the direction to the next line in the profile
///
public void ChangeProfileDirection()
{
Line tmp = m_lines[0];
m_lines.RemoveAt(0);
m_lines.Add(tmp);
}
///
/// all beam types loaded in current Revit project
/// it is declared as static only because of PropertyGrid
///
///
public static Dictionary GetBeamTypes()
{
Dictionary beamTypes = new Dictionary(m_beamTypes);
return beamTypes;
}
///
/// initialize members using data from current Revit project
///
private void PrepareData()
{
UIDocument doc = m_commandData.Application.ActiveUIDocument;
m_beamTypes.Clear();
// iterate all selected beams
foreach (ElementId elementId in doc.Selection.GetElementIds())
{
object obj = doc.Document.GetElement(elementId);
FamilyInstance beam = obj as FamilyInstance;
if (null == beam)
{
continue;
}
// add beam to lists according to category name
string categoryName = beam.Category.Name;
if ("Structural Framing" == categoryName
&& beam.StructuralType == StructuralType.Beam)
{
m_beams.Add(beam);
}
}
//iterate all beam types
FilteredElementIterator itor = new FilteredElementCollector(doc.Document).OfClass(typeof(Family)).GetElementIterator();
itor.Reset();
while (itor.MoveNext())
{
// get Family to get FamilySymbols
Family aFamily = itor.Current as Family;
if (null == aFamily)
{
continue;
}
foreach (ElementId symbolId in aFamily.GetFamilySymbolIds())
{
FamilySymbol symbol = doc.Document.GetElement(symbolId) as FamilySymbol;
if (null == symbol.Category)
{
continue;
}
// add symbols to lists according to category name
string categoryName = symbol.Category.Name;
if ("Structural Framing" == categoryName)
{
m_beamTypes.Add(symbol.Family.Name + ":" + symbol.Name, symbol);
}
}
}
if (m_beams.Count == 0)
{
throw new ErrorMessageException("Please select beams.");
}
if (m_beamTypes.Count == 0)
{
throw new ErrorMessageException("There is no Beam families loaded in current project.");
}
}
///
/// retrieve the profiles using the selected beams
/// ErrorMessageException will be thrown out if beams can't make a closed profile
///
/// beams which may form a closed profile
private void InitializeProfile(List beams)
{
// retrieve collection of lines in beams
List lines = new List();
foreach (FamilyInstance beam in beams)
{
LocationCurve locationLine = beam.Location as LocationCurve;
Line line = locationLine.Curve as Line;
if (null == line)
{
throw new ErrorMessageException("Please don't select any arc beam.");
}
lines.Add(line);
}
// lines should in the same horizontal plane
if (!GeometryUtil.InSameHorizontalPlane(lines))
{
throw new ErrorMessageException("The selected beams can't form a horizontal profile.");
}
// sorted lines so that all lines are intersect end to end
m_lines = GeometryUtil.SortLines(lines);
// lines can't make a closed profile
if (null == m_lines)
{
throw new ErrorMessageException("The selected beams can't form a closed profile.");
}
}
///
/// layout rule of beam system has changed
///
/// changed method
private void LayoutRuleChanged(ref LayoutMethod layoutMethod)
{
// create BeamSystemParams instance according to changed LayoutMethod
m_param = m_param.CloneInstance(layoutMethod);
// raise DataUpdated event
OnParamsUpdated(new EventArgs());
// rebind delegate
m_param.LayoutRuleChanged += new LayoutRuleChangedHandler(LayoutRuleChanged);
}
///
/// the data used to show in UI is updated
///
///
protected virtual void OnParamsUpdated(EventArgs e)
{
if (null != ParamsUpdated)
{
ParamsUpdated(this, e);
}
}
}
}