mirror of
https://github.com/jeremytammik/RevitSdkSamples.git
synced 2026-08-13 08:17:42 +00:00
442 lines
16 KiB
C#
442 lines
16 KiB
C#
|
|
//
|
||
|
|
// (C) Copyright 2003-2007 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 System.Windows.Forms;
|
||
|
|
|
||
|
|
using Autodesk;
|
||
|
|
using Autodesk.Revit;
|
||
|
|
using Autodesk.Revit.Elements;
|
||
|
|
using Autodesk.Revit.Geometry;
|
||
|
|
using Autodesk.Revit.Structural;
|
||
|
|
using Autodesk.Revit.Structural.Enums;
|
||
|
|
using Autodesk.Revit.Parameters;
|
||
|
|
|
||
|
|
namespace Revit.SDK.Samples.CreateViewSection.CS
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// The main class which given a linear element, such as a wall, floor or beam,
|
||
|
|
/// generates a section view across the mid point of the element.
|
||
|
|
/// </summary>
|
||
|
|
public class Command : IExternalCommand
|
||
|
|
{
|
||
|
|
// Private Members
|
||
|
|
Autodesk.Revit.Document m_project; // Store the current document in revit
|
||
|
|
String m_errorInformation; // Store the error information
|
||
|
|
const Double PRECISION = 0.0000000001; // Define a precision of double data
|
||
|
|
|
||
|
|
BoundingBoxXYZ m_box; // Store the BoundingBoxXYZ reference used in creation
|
||
|
|
Autodesk.Revit.Element m_currentComponent; // Store the selected element
|
||
|
|
SelectType m_type; // Indicate the type of the selected element.
|
||
|
|
// 0 - wall, 1 - beam, 2 - floor, -1 - invalid
|
||
|
|
const Double LENGTH = 10; // Define half length and width of BoudingBoxXYZ
|
||
|
|
const Double HEIGHT = 5; // Define height of the BoudingBoxXYZ
|
||
|
|
|
||
|
|
// Define a enum to indicate the selected element type
|
||
|
|
enum SelectType
|
||
|
|
{
|
||
|
|
WALL = 0,
|
||
|
|
BEAM = 1,
|
||
|
|
FLOOR = 2,
|
||
|
|
INVALID = -1
|
||
|
|
}
|
||
|
|
|
||
|
|
// Methods
|
||
|
|
/// <summary>
|
||
|
|
/// Default constructor of Command
|
||
|
|
/// </summary>
|
||
|
|
public Command()
|
||
|
|
{
|
||
|
|
m_type = SelectType.INVALID;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Implement this method as an external command for Revit.
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="commandData">An object that is passed to the external application
|
||
|
|
/// which contains data related to the command,
|
||
|
|
/// such as the application object and active view.</param>
|
||
|
|
/// <param name="message">A message that can be set by the external application
|
||
|
|
/// which will be displayed if a failure or cancellation is returned by
|
||
|
|
/// the external command.</param>
|
||
|
|
/// <param name="elements">A set of elements to which the external application
|
||
|
|
/// can add elements that are to be highlighted in case of failure or cancellation.</param>
|
||
|
|
/// <returns>Return the status of the external command.
|
||
|
|
/// A result of Succeeded means that the API external method functioned as expected.
|
||
|
|
/// Cancelled can be used to signify that the user cancelled the external operation
|
||
|
|
/// at some point. Failure should be returned if the application is unable to proceed with
|
||
|
|
/// the operation.</returns>
|
||
|
|
public IExternalCommand.Result Execute( ExternalCommandData commandData,
|
||
|
|
ref string message, ElementSet elements )
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
m_project = commandData.Application.ActiveDocument;
|
||
|
|
|
||
|
|
// Get the selected element and store it to data member.
|
||
|
|
if( !GetSelectedElement() )
|
||
|
|
{
|
||
|
|
message = m_errorInformation;
|
||
|
|
return IExternalCommand.Result.Failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create a BoundingBoxXYZ instance which used in NewViewSection() method
|
||
|
|
if( !GenerateBoundingBoxXYZ() )
|
||
|
|
{
|
||
|
|
message = m_errorInformation;
|
||
|
|
return IExternalCommand.Result.Failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create a section view.
|
||
|
|
ViewSection section = m_project.Create.NewViewSection( m_box );
|
||
|
|
if( null == section )
|
||
|
|
{
|
||
|
|
message = "Can't create the ViewSection.";
|
||
|
|
return IExternalCommand.Result.Failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Modify some parameters to make it look better.
|
||
|
|
section.get_Parameter( BuiltInParameter.VIEW_DETAIL_LEVEL ).Set( 2 );
|
||
|
|
|
||
|
|
// If everything goes right, give successful information and return succeeded.
|
||
|
|
MessageBox.Show( "Create view section successfully", "Revit" );
|
||
|
|
return IExternalCommand.Result.Succeeded;
|
||
|
|
}
|
||
|
|
catch( Exception e )
|
||
|
|
{
|
||
|
|
message = e.Message;
|
||
|
|
return IExternalCommand.Result.Failed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Get the selected element, and check whether it is a wall, a floor or a beam.
|
||
|
|
/// </summary>
|
||
|
|
/// <returns>true if the process succeed; otherwise, false.</returns>
|
||
|
|
Boolean GetSelectedElement()
|
||
|
|
{
|
||
|
|
// First get the selection, and make sure only one element in it.
|
||
|
|
ElementSet collection = m_project.Selection.Elements;
|
||
|
|
if( 1 != collection.Size )
|
||
|
|
{
|
||
|
|
m_errorInformation =
|
||
|
|
"Please select only one element, such as a wall, a beam or a floor.";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the selected element.
|
||
|
|
foreach( Autodesk.Revit.Element e in collection )
|
||
|
|
{
|
||
|
|
m_currentComponent = e;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Make sure the element to be a wall, beam or a floor.
|
||
|
|
if( m_currentComponent is Wall )
|
||
|
|
{
|
||
|
|
// Check whether the wall is a linear wall
|
||
|
|
LocationCurve location = m_currentComponent.Location as LocationCurve;
|
||
|
|
if( null == location )
|
||
|
|
{
|
||
|
|
m_errorInformation = "The selected wall should be linear.";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if( location.Curve is Line )
|
||
|
|
{
|
||
|
|
m_type = SelectType.WALL; // when the element is a linear wall
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_errorInformation = "The selected wall should be linear.";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
FamilyInstance beam = m_currentComponent as FamilyInstance;
|
||
|
|
if( null != beam && StructuralType.Beam == beam.StructuralType )
|
||
|
|
{
|
||
|
|
m_type = SelectType.BEAM; // when the elemnt is a beam
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if( m_currentComponent is Floor )
|
||
|
|
{
|
||
|
|
m_type = SelectType.FLOOR; // when the elemnt is a floor.
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// If it is not a wall, a beam or a floor, give error information.
|
||
|
|
m_errorInformation = "Please select an element, such as a wall, a beam or a floor.";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Generate a BoundingBoxXYZ instance which used in NewViewSection() method
|
||
|
|
/// </summary>
|
||
|
|
/// <returns>true if the instance can be created; otherwise, false.</returns>
|
||
|
|
Boolean GenerateBoundingBoxXYZ()
|
||
|
|
{
|
||
|
|
// First new a BoundingBoxXYZ, and set the MAX and Min property.
|
||
|
|
m_box = new BoundingBoxXYZ();
|
||
|
|
m_box.Enabled = true;
|
||
|
|
XYZ maxPoint = new XYZ( LENGTH, LENGTH, 0 );
|
||
|
|
XYZ minPoint = new XYZ( -LENGTH, -LENGTH, -HEIGHT );
|
||
|
|
m_box.Max = maxPoint;
|
||
|
|
m_box.Min = minPoint;
|
||
|
|
|
||
|
|
// Setting the Transform property is the most important thing.
|
||
|
|
// It defines the orgin and the directions (including RightDirection,
|
||
|
|
// UpDirection and ViewDirection) of the created view.
|
||
|
|
Transform transform = GenerateTransform();
|
||
|
|
if( null == transform )
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
m_box.Transform = transform;
|
||
|
|
|
||
|
|
// If all went well, return true.
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Generate a Transform instance which as Transform property of BoundingBoxXYZ
|
||
|
|
/// </summary>
|
||
|
|
/// <returns>the reference of Transform, return null if it can't be generated</returns>
|
||
|
|
Transform GenerateTransform()
|
||
|
|
{
|
||
|
|
// Because different element have different ways to create Transform.
|
||
|
|
// So, this method just call corresponding method.
|
||
|
|
if( SelectType.WALL == m_type )
|
||
|
|
{
|
||
|
|
return GenerateWallTransform();
|
||
|
|
}
|
||
|
|
else if( SelectType.BEAM == m_type )
|
||
|
|
{
|
||
|
|
return GenerateBeamTransform();
|
||
|
|
}
|
||
|
|
else if( SelectType.FLOOR == m_type )
|
||
|
|
{
|
||
|
|
return GenerateFloorTransform();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_errorInformation = "The program should never go here.";
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Generate a Transform instance which as Transform property of BoundingBoxXYZ,
|
||
|
|
/// when the user select a wall, this method will be called
|
||
|
|
/// </summary>
|
||
|
|
/// <returns>the reference of Transform, return null if it can't be generated</returns>
|
||
|
|
Transform GenerateWallTransform()
|
||
|
|
{
|
||
|
|
Transform transform = null;
|
||
|
|
Wall wall = m_currentComponent as Wall;
|
||
|
|
|
||
|
|
// Because the architecture wall and curtain wall don't have analytical Model lines.
|
||
|
|
// So Use Location property of wall object is better choice.
|
||
|
|
// First get the location line of the wall
|
||
|
|
LocationCurve location = wall.Location as LocationCurve;
|
||
|
|
Line locationLine = location.Curve as Line;
|
||
|
|
transform = Transform.Identity;
|
||
|
|
|
||
|
|
// Second find the middle point of the wall and set it as Origin property.
|
||
|
|
XYZ midPoint = XYZMath.FindMidPoint( locationLine.get_EndPoint( 0 ), locationLine.get_EndPoint( 1 ) );
|
||
|
|
// midPoint is mid point of the wall location, but not the wall's.
|
||
|
|
// The different is the elevation of the point. Then change it.
|
||
|
|
midPoint.Z += GetWallMidOffsetFromLocation( wall );
|
||
|
|
transform.Origin = midPoint;
|
||
|
|
|
||
|
|
// At last find out the directions of the created view, and set it as Basis property.
|
||
|
|
XYZ basisZ = XYZMath.FindDirection( locationLine.get_EndPoint( 0 ), locationLine.get_EndPoint( 1 ) );
|
||
|
|
XYZ basisX = XYZMath.FindRightDirection( basisZ );
|
||
|
|
XYZ basisY = XYZMath.FindUpDirection( basisZ );
|
||
|
|
|
||
|
|
transform.set_Basis( 0, basisX );
|
||
|
|
transform.set_Basis( 1, basisY );
|
||
|
|
transform.set_Basis( 2, basisZ );
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Generate a Transform instance which as Transform property of BoundingBoxXYZ,
|
||
|
|
/// when the user select a beam, this method will be called
|
||
|
|
/// </summary>
|
||
|
|
/// <returns>the reference of Transform, return null if it can't be generated</returns>
|
||
|
|
Transform GenerateBeamTransform()
|
||
|
|
{
|
||
|
|
Transform transform = null;
|
||
|
|
FamilyInstance instance = m_currentComponent as FamilyInstance;
|
||
|
|
|
||
|
|
// First check whether the beam is horizontal.
|
||
|
|
// In order to predigest the calculation, only allow it to be horizontal
|
||
|
|
double startOffset = instance.get_Parameter( BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION ).AsDouble();
|
||
|
|
double endOffset = instance.get_Parameter( BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION ).AsDouble();
|
||
|
|
if( -PRECISION > startOffset - endOffset || PRECISION < startOffset - endOffset )
|
||
|
|
{
|
||
|
|
m_errorInformation = "Please select a horizontal beam.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Second get the Analytical Model line.
|
||
|
|
AnalyticalModel model = instance.AnalyticalModel;
|
||
|
|
if( null == model )
|
||
|
|
{
|
||
|
|
m_errorInformation = "The selected beam doesn't have Analytical Model line.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
AnalyticalModelFrame modelFrame = model as AnalyticalModelFrame;
|
||
|
|
if( null == modelFrame )
|
||
|
|
{
|
||
|
|
m_errorInformation = "The program should never go here.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
Curve curve = modelFrame.Curve;
|
||
|
|
if( null == curve )
|
||
|
|
{
|
||
|
|
m_errorInformation = "The program should never go here.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Now I am sure I can create a transform instance.
|
||
|
|
transform = Transform.Identity;
|
||
|
|
|
||
|
|
// Third find the middle point of the line and set it as Origin property.
|
||
|
|
XYZ startPoint = curve.get_EndPoint( 0 );
|
||
|
|
XYZ endPoint = curve.get_EndPoint( 1 );
|
||
|
|
XYZ midPoint = XYZMath.FindMidPoint( startPoint, endPoint );
|
||
|
|
transform.Origin = midPoint;
|
||
|
|
|
||
|
|
// At last find out the directions of the created view, and set it as Basis property.
|
||
|
|
XYZ basisZ = XYZMath.FindDirection( startPoint, endPoint );
|
||
|
|
XYZ basisX = XYZMath.FindRightDirection( basisZ );
|
||
|
|
XYZ basisY = XYZMath.FindUpDirection( basisZ );
|
||
|
|
|
||
|
|
transform.set_Basis( 0, basisX );
|
||
|
|
transform.set_Basis( 1, basisY );
|
||
|
|
transform.set_Basis( 2, basisZ );
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Generate a Transform instance which as Transform property of BoundingBoxXYZ,
|
||
|
|
/// when the user select a floor, this method will be called
|
||
|
|
/// </summary>
|
||
|
|
/// <returns>the reference of Transform, return null if it can't be generated</returns>
|
||
|
|
Transform GenerateFloorTransform()
|
||
|
|
{
|
||
|
|
Transform transform = null;
|
||
|
|
Floor floor = m_currentComponent as Floor;
|
||
|
|
|
||
|
|
// First get the Analytical Model lines
|
||
|
|
AnalyticalModel model = floor.AnalyticalModel;
|
||
|
|
if( null == model )
|
||
|
|
{
|
||
|
|
m_errorInformation = "Please select a structual floor.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
AnalyticalModelFloor modelFloor = model as AnalyticalModelFloor;
|
||
|
|
if( null == modelFloor )
|
||
|
|
{
|
||
|
|
m_errorInformation = "The program should never go here.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
CurveArray curves = modelFloor.Curves;
|
||
|
|
if( null == curves || true == curves.IsEmpty )
|
||
|
|
{
|
||
|
|
m_errorInformation = "The program should never go here.";
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Now I am sure I can create a transform instance.
|
||
|
|
transform = Transform.Identity;
|
||
|
|
|
||
|
|
// Third find the middle point of the floor and set it as Origin property.
|
||
|
|
XYZ midPoint = XYZMath.FindMiddlePoint( curves );
|
||
|
|
transform.Origin = midPoint;
|
||
|
|
|
||
|
|
// At last find out the directions of the created view, and set it as Basis property.
|
||
|
|
XYZ basisZ = XYZMath.FindFloorViewDirection( curves );
|
||
|
|
XYZ basisX = XYZMath.FindRightDirection( basisZ );
|
||
|
|
XYZ basisY = XYZMath.FindUpDirection( basisZ );
|
||
|
|
|
||
|
|
transform.set_Basis( 0, basisX );
|
||
|
|
transform.set_Basis( 1, basisY );
|
||
|
|
transform.set_Basis( 2, basisZ );
|
||
|
|
return transform;
|
||
|
|
}
|
||
|
|
|
||
|
|
Double GetWallMidOffsetFromLocation( Wall wall )
|
||
|
|
{
|
||
|
|
// First get the "Base Offset" property.
|
||
|
|
Double baseOffset = wall.get_Parameter( BuiltInParameter.WALL_BASE_OFFSET ).AsDouble();
|
||
|
|
|
||
|
|
// Second get the "Unconnected Height" property.
|
||
|
|
Double height = wall.get_Parameter( BuiltInParameter.WALL_USER_HEIGHT_PARAM ).AsDouble();
|
||
|
|
|
||
|
|
// Get the middle of of wall elevation from the wall location.
|
||
|
|
// The elevation of wall location equals the elevation of "Base Constraint" level
|
||
|
|
Double midOffset = baseOffset + height / 2;
|
||
|
|
return midOffset;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Create a drafting view. -bzh
|
||
|
|
/// </summary>
|
||
|
|
public class CreateDraftingView : IExternalCommand
|
||
|
|
{
|
||
|
|
public IExternalCommand.Result Execute(
|
||
|
|
ExternalCommandData commandData,
|
||
|
|
ref string message,
|
||
|
|
ElementSet elements )
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
Autodesk.Revit.Document doc = commandData.Application.ActiveDocument;
|
||
|
|
ViewDrafting drafting = doc.Create.NewViewDrafting();
|
||
|
|
if( null == drafting )
|
||
|
|
{
|
||
|
|
message = "Can't create the drafting view.";
|
||
|
|
return IExternalCommand.Result.Failed;
|
||
|
|
}
|
||
|
|
MessageBox.Show( "Create drafting view succeeded.", "Revit" );
|
||
|
|
return IExternalCommand.Result.Succeeded;
|
||
|
|
}
|
||
|
|
catch( Exception e )
|
||
|
|
{
|
||
|
|
message = e.Message;
|
||
|
|
return IExternalCommand.Result.Failed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|