mirror of
https://github.com/jeremytammik/RevitSdkSamples.git
synced 2026-08-06 05:01:35 +00:00
536 lines
19 KiB
C#
536 lines
19 KiB
C#
//
|
|
// (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.FrameBuilder.CS
|
|
{
|
|
using System;
|
|
using System.Text;
|
|
using System.Collections.Generic;
|
|
|
|
using Autodesk.Revit;
|
|
using Autodesk.Revit.ApplicationServices;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.UI;
|
|
using UV = Autodesk.Revit.DB.UV;
|
|
|
|
/// <summary>
|
|
/// data class contains information to create framing
|
|
/// </summary>
|
|
public class FrameData
|
|
{
|
|
const int XNumberMaxValue = 50; // maximum number of Columns in the X Direction
|
|
const int XNumberMinValue = 2; // minimum number of Columns in the X Direction
|
|
const int XNumberDefault = 3; // default number of Columns in the X Direction
|
|
const int YNumberMaxValue = 50; // maximum number of Columns in the Y Direction
|
|
const int YNumberMinValue = 2; // minimum number of Columns in the Y Direction
|
|
const int YNumberDefault = 3; // default number of Columns in the Y Direction
|
|
const int TotalMaxValue = 200; // maximum total number of Columns to create
|
|
const int FloorNumberMinValue = 1; // minimum number of floors
|
|
const int FloorNumberMaxValue = 200; // maximum number of floors
|
|
const double DistanceMaxValue = 3000; // maxinum distance between 2 adjoining columns
|
|
const double DistanceMinValue = 1; // mininum distance between 2 adjoining columns
|
|
const double DistanceDefault = 5; // default distance between 2 adjoining columns
|
|
const double LevelHeightMaxValue = 100; // maximum height between 2 new levels
|
|
const double LevelHeightMinValue = 1; // minimum height between 2 new levels
|
|
const int DigitPrecision = 4; // the number of significant digits(precision)
|
|
|
|
int m_xNumber = XNumberDefault; // number of Columns in the X Direction
|
|
int m_yNumber = XNumberDefault; // number of Columns in the Y Direction
|
|
double m_distance = DistanceDefault; // distance between 2 adjoining columns
|
|
int m_floorNumber; // number of floors
|
|
double m_levelHeight; // increaced height of autogenerated levels
|
|
Autodesk.Revit.DB.UV m_frameOrigin = new Autodesk.Revit.DB.UV(0.0, 0.0); // bottom left point of the frame
|
|
double m_frameOriginAngle = 0.0; // the angle to rotate around bottom left point
|
|
int m_originalLevelSize; // the number of levels before invoke external command
|
|
|
|
FamilySymbol m_columnSymbol; // column's type
|
|
FamilySymbol m_beamSymbol; // beam's type
|
|
FamilySymbol m_braceSymbol; // brace's type
|
|
|
|
ExternalCommandData m_commandData;
|
|
FrameTypesMgr m_columnSymbolsMgr; // object manage all column types
|
|
FrameTypesMgr m_beambracesSymbolsMgr; // object manage all beam types
|
|
SortedList<double, Level> m_levels; // list of all levels in the order of Elevation
|
|
|
|
/// <summary>
|
|
/// command data pass from entry point
|
|
/// </summary>
|
|
public ExternalCommandData CommandData
|
|
{
|
|
get
|
|
{
|
|
return m_commandData;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// object manage all column types
|
|
/// </summary>
|
|
public FrameTypesMgr ColumnSymbolsMgr
|
|
{
|
|
get
|
|
{
|
|
return m_columnSymbolsMgr;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// object manage all beam types
|
|
/// </summary>
|
|
public FrameTypesMgr BeamSymbolsMgr
|
|
{
|
|
get
|
|
{
|
|
return m_beambracesSymbolsMgr;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// object manage all brace types
|
|
/// </summary>
|
|
public FrameTypesMgr BraceSymbolsMgr
|
|
{
|
|
get
|
|
{
|
|
return m_beambracesSymbolsMgr;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// number of Columns in the Y Direction
|
|
/// </summary>
|
|
public int YNumber
|
|
{
|
|
get
|
|
{
|
|
return m_yNumber;
|
|
}
|
|
set
|
|
{
|
|
if (value < YNumberMinValue || value > YNumberMaxValue)
|
|
{
|
|
string message = "Number of Columns in the Y Direction should no less than "
|
|
+ YNumberMinValue.ToString() + " and no more than "
|
|
+ YNumberMaxValue.ToString();
|
|
throw new ErrorMessageException(message);
|
|
}
|
|
CheckTotalNumber(value * XNumber * (m_floorNumber - 1));
|
|
m_yNumber = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// number of Columns in the X Direction
|
|
/// </summary>
|
|
public int XNumber
|
|
{
|
|
get
|
|
{
|
|
return m_xNumber;
|
|
}
|
|
set
|
|
{
|
|
if (value < XNumberMinValue || value > XNumberMaxValue)
|
|
{
|
|
string message = "Number of Columns in the X Direction should no less than "
|
|
+ XNumberMinValue.ToString() + " and no more than "
|
|
+ XNumberMaxValue.ToString();
|
|
throw new ErrorMessageException(message);
|
|
}
|
|
CheckTotalNumber(value * YNumber * (m_floorNumber - 1));
|
|
m_xNumber = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// distance between 2 adjoining columns
|
|
/// </summary>
|
|
public double Distance
|
|
{
|
|
get
|
|
{
|
|
return m_distance;
|
|
}
|
|
set
|
|
{
|
|
if (value < DistanceMinValue || value > DistanceMaxValue)
|
|
{
|
|
string message = "The distance between columns shoule no less than "
|
|
+ DistanceMinValue.ToString() + "and no more than "
|
|
+ DistanceMaxValue.ToString();
|
|
throw new ErrorMessageException(message);
|
|
}
|
|
m_distance = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// number of floors
|
|
/// </summary>
|
|
public int FloorNumber
|
|
{
|
|
get
|
|
{
|
|
return m_floorNumber;
|
|
}
|
|
set
|
|
{
|
|
if (value < FloorNumberMinValue || value > FloorNumberMaxValue)
|
|
{
|
|
string message = "Number of floors should no less than "
|
|
+ FloorNumberMinValue.ToString() + " and no more than "
|
|
+ FloorNumberMaxValue.ToString();
|
|
throw new ErrorMessageException(message);
|
|
}
|
|
CheckTotalNumber(XNumber * YNumber * (value - 1));
|
|
m_floorNumber = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// increased height of autogenerated levels
|
|
/// </summary>
|
|
public double LevelHeight
|
|
{
|
|
get
|
|
{
|
|
return Math.Round(m_levelHeight, DigitPrecision);
|
|
}
|
|
set
|
|
{
|
|
if (value < LevelHeightMinValue || value > LevelHeightMaxValue)
|
|
{
|
|
string message = "The distance between columns shoule no less than "
|
|
+ LevelHeightMinValue.ToString() + "and no more than "
|
|
+ LevelHeightMaxValue.ToString();
|
|
throw new ErrorMessageException(message);
|
|
}
|
|
m_distance = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// bottom left point of the frame
|
|
/// </summary>
|
|
public Autodesk.Revit.DB.UV FrameOrigin
|
|
{
|
|
get
|
|
{
|
|
return m_frameOrigin;
|
|
}
|
|
set
|
|
{
|
|
m_frameOrigin = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// the angle to rotate around bottom left point
|
|
/// </summary>
|
|
public double FrameOriginAngle
|
|
{
|
|
get
|
|
{
|
|
return m_frameOriginAngle;
|
|
}
|
|
set
|
|
{
|
|
m_frameOriginAngle = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// column's type
|
|
/// </summary>
|
|
public FamilySymbol ColumnSymbol
|
|
{
|
|
get
|
|
{
|
|
return m_columnSymbol;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// beam's type
|
|
/// </summary>
|
|
public FamilySymbol BeamSymbol
|
|
{
|
|
get
|
|
{
|
|
return m_beamSymbol;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// brace's type
|
|
/// </summary>
|
|
public FamilySymbol BraceSymbol
|
|
{
|
|
get
|
|
{
|
|
return m_braceSymbol;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// list of all levels in the ordr of Elevation
|
|
/// </summary>
|
|
public SortedList<double, Level> Levels
|
|
{
|
|
get
|
|
{
|
|
return m_levels;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// the number of levels before invoke external command
|
|
/// </summary>
|
|
public int OriginalLevelSize
|
|
{
|
|
get
|
|
{
|
|
return m_originalLevelSize;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// create FramingData object. applicationException will throw out,
|
|
/// if current Revit document doesn't satisfy the condition to create framing
|
|
/// </summary>
|
|
/// <param name="commandData"></param>
|
|
/// <returns></returns>
|
|
public static FrameData CreateInstance(ExternalCommandData commandData)
|
|
{
|
|
FrameData data = new FrameData(commandData);
|
|
data.Initialize();
|
|
data.Validate();
|
|
|
|
// initialize members after checking precondition
|
|
data.m_floorNumber = (data.m_levels.Count - 1) > 0 ? (data.m_levels.Count - 1) : 1;
|
|
data.m_columnSymbol = data.m_columnSymbolsMgr.FramingSymbols[0];
|
|
data.m_beamSymbol = data.m_beambracesSymbolsMgr.FramingSymbols[0];
|
|
data.m_braceSymbol = data.m_beambracesSymbolsMgr.FramingSymbols[0];
|
|
data.m_levelHeight = data.m_levels.Values[data.m_levels.Count - 1].Elevation
|
|
- data.m_levels.Values[data.m_levels.Count - 2].Elevation;
|
|
|
|
return data;
|
|
}
|
|
|
|
/// <summary>
|
|
/// cast object to FamilySymbol and set as column's type
|
|
/// </summary>
|
|
/// <param name="obj">FamilySymbol object</param>
|
|
/// <returns>failed to cast and set</returns>
|
|
public bool SetColumnSymbol(object obj)
|
|
{
|
|
FamilySymbol symbol = obj as FamilySymbol;
|
|
if (null == symbol)
|
|
{
|
|
return false;
|
|
}
|
|
m_columnSymbol = symbol;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// cast object to FamilySymbol and set as beam's type
|
|
/// </summary>
|
|
/// <param name="obj">FamilySymbol object</param>
|
|
/// <returns>failed to cast and set</returns>
|
|
public bool SetBeamSymbol(object obj)
|
|
{
|
|
FamilySymbol symbol = obj as FamilySymbol;
|
|
if (null == symbol)
|
|
{
|
|
return false;
|
|
}
|
|
m_beamSymbol = symbol;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// cast object to FamilySymbol and set as brace's type
|
|
/// </summary>
|
|
/// <param name="obj">FamilySymbol object</param>
|
|
/// <returns>failed to cast and set</returns>
|
|
public bool SetBraceSymbol(object obj)
|
|
{
|
|
FamilySymbol symbol = obj as FamilySymbol;
|
|
if (null == symbol)
|
|
{
|
|
return false;
|
|
}
|
|
m_braceSymbol = symbol;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// add more levels so that level number can meet floor number
|
|
/// </summary>
|
|
public void UpdateLevels()
|
|
{
|
|
double baseElevation = m_levels.Values[m_levels.Count - 1].Elevation;
|
|
Autodesk.Revit.Creation.Document createDoc = m_commandData.Application.ActiveUIDocument.Document.Create;
|
|
Autodesk.Revit.DB.Document m_Doc = m_commandData.Application.ActiveUIDocument.Document;
|
|
|
|
FilteredElementCollector collector = new FilteredElementCollector(m_Doc);
|
|
IList<Element> viewFamilyTypes = collector.OfClass(typeof(ViewFamilyType)).ToElements();
|
|
ElementId floorPlanId = new ElementId(-1);
|
|
foreach (Element e in viewFamilyTypes)
|
|
{
|
|
ViewFamilyType v = e as ViewFamilyType;
|
|
|
|
if (v != null && v.ViewFamily == ViewFamily.FloorPlan)
|
|
{
|
|
floorPlanId = e.Id;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int newLevelSize = (m_floorNumber + 1) - m_levels.Count;
|
|
if (newLevelSize == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int ii = 0; ii < newLevelSize; ii++)
|
|
{
|
|
double elevation = baseElevation + m_levelHeight * (ii + 1);
|
|
Level newLevel = Level.Create(m_commandData.Application.ActiveUIDocument.Document, elevation);
|
|
//createDoc.NewViewPlan(newLevel.Name, newLevel, Autodesk.Revit.DB.ViewPlanType.FloorPlan);
|
|
ViewPlan viewPlan = ViewPlan.Create(m_Doc, floorPlanId, newLevel.Id);
|
|
viewPlan.Name = newLevel.Name;
|
|
m_levels.Add(elevation, newLevel);
|
|
}
|
|
m_originalLevelSize = m_levels.Count;
|
|
}
|
|
|
|
/// <summary>
|
|
/// it is only used for object factory method
|
|
/// </summary>
|
|
/// <param name="commandData"></param>
|
|
private FrameData(ExternalCommandData commandData)
|
|
{
|
|
// initialize members
|
|
m_commandData = commandData;
|
|
m_columnSymbolsMgr = new FrameTypesMgr(commandData);
|
|
m_beambracesSymbolsMgr = new FrameTypesMgr(commandData);
|
|
m_levels = new SortedList<double, Level>();
|
|
m_originalLevelSize = m_levels.Count;
|
|
m_yNumber = YNumberDefault;
|
|
m_xNumber = XNumberDefault;
|
|
m_distance = DistanceDefault;
|
|
}
|
|
|
|
/// <summary>
|
|
/// check the total number of columns to create less than certain value
|
|
/// </summary>
|
|
/// <param name="number"></param>
|
|
/// <returns></returns>
|
|
private static void CheckTotalNumber(int number)
|
|
{
|
|
if (number > TotalMaxValue)
|
|
{
|
|
string message = "The total number of columns should less than "
|
|
+ TotalMaxValue.ToString();
|
|
throw new ErrorMessageException(message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// initialize list of column, beam and brace's type;
|
|
/// initialize list of level
|
|
/// </summary>
|
|
private void Initialize()
|
|
{
|
|
Application app = m_commandData.Application.Application;
|
|
Document doc = m_commandData.Application.ActiveUIDocument.Document;
|
|
|
|
FilteredElementCollector collector1 = new FilteredElementCollector(doc);
|
|
IList<Autodesk.Revit.DB.Element> a1 = collector1.OfClass(typeof(Level)).ToElements();
|
|
|
|
foreach (Level lev in a1)
|
|
{
|
|
m_levels.Add(lev.Elevation, lev);
|
|
}
|
|
|
|
a1.Clear();
|
|
|
|
Categories categories = doc.Settings.Categories;
|
|
BuiltInCategory bipColumn = BuiltInCategory.OST_StructuralColumns;
|
|
BuiltInCategory bipFraming = BuiltInCategory.OST_StructuralFraming;
|
|
Autodesk.Revit.DB.ElementId idColumn = categories.get_Item(bipColumn).Id;
|
|
Autodesk.Revit.DB.ElementId idFraming = categories.get_Item(bipFraming).Id;
|
|
|
|
ElementCategoryFilter filterColumn = new ElementCategoryFilter(bipColumn);
|
|
ElementCategoryFilter filterFraming = new ElementCategoryFilter(bipFraming);
|
|
LogicalOrFilter orFilter = new LogicalOrFilter(filterColumn, filterFraming);
|
|
|
|
ElementClassFilter filterSymbol = new ElementClassFilter(typeof(FamilySymbol));
|
|
LogicalAndFilter andFilter = new LogicalAndFilter(orFilter, filterSymbol);
|
|
//
|
|
// without filtering for the structural categories,
|
|
// our sample project was returning over 500 family symbols;
|
|
// adding the category filters reduced this number to 40:
|
|
//
|
|
FilteredElementCollector collector2 = new FilteredElementCollector(doc);
|
|
IList<Element> a2 = collector2.WherePasses(andFilter).ToElements();
|
|
|
|
foreach (FamilySymbol symbol in a2)
|
|
{
|
|
Autodesk.Revit.DB.ElementId categoryId = symbol.Category.Id;
|
|
|
|
if (idFraming.Equals(categoryId))
|
|
{
|
|
m_beambracesSymbolsMgr.AddSymbol(symbol);
|
|
}
|
|
else if (idColumn.Equals(categoryId))
|
|
{
|
|
m_columnSymbolsMgr.AddSymbol(symbol);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// validate the precondition to create framing
|
|
/// </summary>
|
|
private void Validate()
|
|
{
|
|
// level shouldn't less than 2
|
|
if (m_levels.Count < 2)
|
|
{
|
|
throw new ErrorMessageException("The level's number in active document is less than 2.");
|
|
}
|
|
// no Structural Column family is loaded in current document
|
|
if (m_columnSymbolsMgr.Size == 0)
|
|
{
|
|
throw new ErrorMessageException("No Structural Column family is loaded in current project.");
|
|
}
|
|
// no Structural Beam family is loaded in current document
|
|
if (m_beambracesSymbolsMgr.Size == 0)
|
|
{
|
|
throw new ErrorMessageException("No Structural Beam family is loaded in current project.");
|
|
}
|
|
}
|
|
}
|
|
} |