Files
2024-12-12 09:51:40 +01:00

514 lines
16 KiB
C#

#region Copyright
//
// (C) Copyright 2010 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.
//
// Migrated to C# by Adam Nagy
//
#endregion // Copyright
#region Imports
// Import the following name spaces in the project properties/references.
// Note: VB.NET has a slighly different way of recognizing name spaces than C#.
// if you explicitely set them in each .vb file, you will need to specify full name spaces.
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.ApplicationServices; //' Application class
using Autodesk.Revit.Attributes; //' specific this if you want to save typing for attributes. e.g.,
using Autodesk.Revit.UI.Selection; //' for selection
#endregion
#region Description
// Revit Intro Lab - 2
//
// In this lab, you will learn how an element is represended in Revit.
// Disclaimer: minimum error checking to focus on the main topic.
//
#endregion
namespace RevitIntroCS
{
// DBElement - identifying element
//
[Transaction( TransactionMode.Automatic )]
[Regeneration( RegenerationOption.Manual )]
public class DBElement : IExternalCommand
{
Application _rvtApp;
Document _rvtDoc;
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements )
{
// Get the access to the top most objects.
// Notice that we have UI and DB versions for application and Document.
// (We list them both here to show two versions.)
UIApplication rvtUIApp = commandData.Application;
UIDocument rvtUIDoc = rvtUIApp.ActiveUIDocument;
_rvtApp = rvtUIApp.Application;
_rvtDoc = rvtUIDoc.Document;
// (1) select an object on a screen. (We'll come back to
// the selection in the UI Lab later.)
Reference r = rvtUIDoc.Selection.PickObject(
ObjectType.Element, "Pick an element" );
// we have picked something.
Element elem = r.Element;
// (2) let's see what kind of element we got.
// Key properties that we need to check are:
// Class, Category and if an element is ElementType or not.
ShowBasicElementInfo( elem );
// check the basic info of the element type
//Dim elemTypeId As ElementId = elem.GetTypeId
//Dim elemType As ElementType = _rvtDoc.Element(elemTypeId)
//ShowBasicElementInfo(elemType)
// (3) now, we are going to identify each major types of element.
IdentifyElement( elem );
// Now look at other properties - important ones are
// parameters, locations and geometry.
// (4) first parameters.
ShowParameters( elem, "Element Parameters: " );
// check to see its type parameter as well
ElementId elemTypeId = elem.GetTypeId();
ElementType elemType = _rvtDoc.get_Element( elemTypeId ) as ElementType;
ShowParameters( elemType, "Type Parameters: " );
// we saw a set or parameters for a given element or element type.
// how can we access each parameter? For example, how can we get
// the value of "length" information?
RetrieveParameter( elem, "Element Parameter (by Name and BuiltInParameter): " );
// the same logic applies to the type parameter.
RetrieveParameter( elemType, "Type Parameter (by Name and BuiltInParameter): " );
// (5) location
ShowLocation( elem );
// (6) geometry - the last piece. (Optional)
ShowGeometry( elem );
// these are the common proerties.
// there may be more properties specific to the given element class,
// such as Wall.Width, .Flipped and Orientation. Expore using RevitLookup and RevitAPI.chm.
return Result.Succeeded;
}
//-------1---------2---------3----------4---------5--------6---------7---
//-----------------------------------------------------------------------
// ShowBasicElementInfo()
//
// Show hows basic information about the given element.
// Note: we are intentionally including both element and element type
// here to compare the output on the same dialog.
// Compare, for example, the categories of element and element type.
//-----------------------------------------------------------------------
public void ShowBasicElementInfo( Element elem )
{
// let's see what kind of element we got.
string s = "You picked:" + "\n";
s = s + " Class name = " + elem.GetType().Name + "\n";
s = s + " Category = " + elem.Category.Name + "\n";
s = s + " Element id = " + elem.Id.ToString() + "\n" + "\n";
// and check its type info.
//Dim elemType As ElementType = elem.ObjectType '' Note: this is obsolete.
ElementId elemTypeId = elem.GetTypeId();
ElementType elemType = ( ElementType ) _rvtDoc.get_Element( elemTypeId );
s = s + "Its ElementType:" + "\n";
s = s + " Class name = " + elemType.GetType().Name + "\n";
s = s + " Category = " + elemType.Category.Name + "\n";
s = s + " Element type id = " + elemType.Id.ToString() + "\n";
TaskDialog.Show( "Revit Intro Lab", s );
}
// identify the type of the element known to the UI.
//
public void IdentifyElement( Element elem )
{
// An instance of a system family has a designated class.
// You can use it identify the type of element.
// e.g., walls, floors, roofs.
string s = "";
if( elem is Wall )
{
s = "Wall";
}
else if( elem is Floor )
{
s = "Floor";
}
else if( elem is RoofBase )
{
s = "Roof";
}
else if( elem is FamilyInstance )
{
// An instance of a component family is all FamilyInstance.
// We'll need to further check its category.
// e.g., Doors, Windows, Furnitures.
if( elem.Category.Id.IntegerValue == ( int ) BuiltInCategory.OST_Doors )
{
s = "Door";
}
else if( elem.Category.Id.IntegerValue == ( int ) BuiltInCategory.OST_Windows )
{
s = "Window";
}
else if( elem.Category.Id.IntegerValue == ( int ) BuiltInCategory.OST_Furniture )
{
s = "Furniture";
}
else
{
// e.g. Plant
s = "Component family instance";
}
}
// check the base class. e.g., CeilingAndFloor.
else if( elem is HostObject )
{
s = "System family instance";
}
else
{
s = "Other";
}
s = "You have picked: " + s;
TaskDialog.Show( "Revit Intro Lab", s );
}
//
// show the parameter values of the element
//
public void ShowParameters( Element elem, [System.Runtime.InteropServices.DefaultParameterValueAttribute( "" )] string header )
{
string s = header + "\n" + "\n";
ParameterSet @params = elem.Parameters;
foreach( Parameter param in @params )
{
string name = param.Definition.Name;
// to get the value, we need to pause the param depending on the strage type
// see the helper function below
string val = ParameterToString( param );
s = s + name + " = " + val + "\n";
}
TaskDialog.Show( "Revit Intro Lab", s );
}
//
// Helper function: return a string from of a given parameter.
//
public static string ParameterToString( Parameter param )
{
string val = "none";
if( param == null )
{
return val;
}
// get the parameter value depending on its storage type
switch( param.StorageType )
{
case StorageType.Double:
double dVal = param.AsDouble();
val = dVal.ToString();
break;
case StorageType.Integer:
int iVal = param.AsInteger();
val = iVal.ToString();
break;
case StorageType.String:
string sVal = param.AsString();
val = sVal;
break;
case StorageType.ElementId:
ElementId idVal = param.AsElementId();
val = idVal.IntegerValue.ToString();
break;
case StorageType.None:
break;
default:
break;
}
return val;
}
// examples of retrieving a specific parameter indivisually.
// (hard coded for simplicity. This function works best
// with walls and doors.)
public void RetrieveParameter(
Element elem,
[System.Runtime.InteropServices.DefaultParameterValueAttribute( "" )] string header )
{
string s = header + "\n\n";
// as an experiment, let's pick up some arbitrary parameters.
// note: most instances have this parameter
// (1) by BuiltInParameter.
Parameter param = elem.get_Parameter(
BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS );
if( param != null )
{
s = s + "Comments (by BuiltInParameter) = "
+ ParameterToString( param ) + "\n";
}
// (2) by name. (Mark - most instances have this parameter.)
// if you use this method, it will be language specific.
param = elem.get_Parameter( "Mark" );
if( param != null )
{
s = s + "Mark (by Name) = " + ParameterToString( param ) + "\n";
}
// though the first one is the most commonly used,
// other possible methods are:
// (3) by definition
//param = elem.Parameter(Definition)
// (4) and for shared parameters, you can also use GUID.
//parameter = Parameter(GUID)
// the following should be in most types
param = elem.get_Parameter( BuiltInParameter.ALL_MODEL_TYPE_COMMENTS );
if( param != null )
{
s = s + "Type Comments (by BuiltInParameter) = "
+ ParameterToString( param ) + "\n";
}
param = elem.get_Parameter( "Fire Rating" );
if( param != null )
{
s = s + "Fire Rating (by Name) = "
+ ParameterToString( param ) + "\n";
}
// using the BuiltInParameter, you can sometimes access
// one that is not in the parameters set.
// Note: this works only for element type.
// [MH3i: To Do - check c# version. 4/26. ]
param = elem.get_Parameter(
BuiltInParameter.SYMBOL_FAMILY_AND_TYPE_NAMES_PARAM );
if( param != null )
{
s = s + "SYMBOL_FAMILY_AND_TYPE_NAMES_PARAM (only by BuiltInParameter) = "
+ ParameterToString( param ) + "\n";
}
param = elem.get_Parameter( BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM );
if( param != null )
{
s = s + "SYMBOL_FAMILY_NAME_PARAM (only by BuiltInParameter) = "
+ ParameterToString( param ) + "\n";
}
TaskDialog.Show( "Revit Intro Lab", s );
}
// show the location information of the given element.
// location can be LocationPoint (e.g., furniture), and LocationCurve (e.g., wall).
//
public void ShowLocation( Element elem )
{
string s = "Location Information: " + "\n" + "\n";
Location loc = elem.Location;
if( loc is LocationPoint )
{
// (1) we have a location point
LocationPoint locPoint = loc as LocationPoint;
XYZ pt = locPoint.Point;
double r = locPoint.Rotation;
s = s + "LocationPoint" + "\n";
s = s + "Point = " + PointToString( pt ) + "\n";
s = s + "Rotation = " + r.ToString() + "\n";
}
else if( loc is LocationCurve )
{
// (2) we have a location curve
LocationCurve locCurve = loc as LocationCurve;
Curve crv = locCurve.Curve;
s = s + "LocationCurve" + "\n";
s = s + "EndPoint(0)/Start Point = " + PointToString( crv.get_EndPoint( 0 ) ) + "\n";
s = s + "EndPoint(1)/End point = " + PointToString( crv.get_EndPoint( 1 ) ) + "\n";
s = s + "Length = " + crv.Length.ToString() + "\n";
s = s + "JoinType(0) = " + locCurve.get_JoinType( 0 ).ToString() + "\n";
s = s + "JoinType(1) = " + locCurve.get_JoinType( 1 ).ToString() + "\n";
}
TaskDialog.Show( "Revit Intro Lab", s );
}
// Helper Function: return XYZ in a string form.
public static string RealToString( double a )
{
return a.ToString( "F2" );
}
public static string PointToString( XYZ p )
{
return null == p
? string.Empty
: "(" + RealToString( p.X )
+ ", " + RealToString( p.Y )
+ ", " + RealToString( p.Z ) + ")";
}
// This is lengthy. So Optional:
// show the geometry information of the given element. Here is how to access it.
// you can go through by RevitLookup, instead.
public void ShowGeometry( Element elem )
{
string s = "Geometry Information: " + "\n" + "\n";
// first, set a geometry option
Options opt = _rvtApp.Create.NewGeometryOptions();
opt.DetailLevel = DetailLevels.Fine;
// does the element have the geometry data?
GeometryElement geomElem = elem.get_Geometry( opt );
if( geomElem == null )
{
TaskDialog.Show( "Revit Intro Lab", s + "no data" );
return;
}
// get the geometry information from the geom elem.
// geometry informaion can easily go into depth.
// here we look at at top level. use RevitLookup for complee dril down.
//
s = GeometryElementToString( geomElem );
// show it.
TaskDialog.Show( "Revit Intro Lab", s );
}
// Helper Function: parse the geometry element by geometry type.
// see ReviCommands in the SDK sample for complete implementation.
//
public static string GeometryElementToString( GeometryElement geomElem )
{
GeometryObjectArray geomObjs = geomElem.Objects;
string str = "Total number of GeometryObject: " + geomObjs.Size.ToString() + "\n";
foreach( GeometryObject geomObj in geomObjs )
{
if( geomObj is Solid )
{
// ex. wall
Solid solid = ( Solid ) geomObj;
//str = str & GeometrySolidToString(solid)
str = str + "Solid" + "\n";
}
else if( geomObj is GeometryInstance )
{
// ex. door/window
str = str + " -- Geometry.Instance -- " + "\n";
GeometryInstance geomInstance = ( GeometryInstance ) geomObj;
GeometryElement geoElem = geomInstance.SymbolGeometry;
str = str + GeometryElementToString( geoElem );
}
else if( geomObj is Curve )
{
// ex.
Curve curv = ( Curve ) geomObj;
//str = str & GeometryCurveToString(curv)
str = str + "Curve" + "\n";
}
else if( geomObj is Mesh )
{
// ex.
Mesh mesh = ( Mesh ) geomObj;
//str = str & GeometryMeshToString(mesh)
str = str + "Mesh" + "\n";
}
else
{
str = str + " *** unkown geometry type" + geomObj.GetType().ToString();
}
}
return str;
}
}
}