mirror of
https://github.com/jeremytammik/RevitSdkSamples.git
synced 2026-08-14 16:54:18 +00:00
906 lines
32 KiB
C#
906 lines
32 KiB
C#
#region Copyright
|
|
//
|
|
// (C) Copyright 2009-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 J. Tammik. Comment/description added by M.Harada
|
|
//
|
|
#endregion // Copyright
|
|
|
|
#region Namespaces
|
|
//using System;
|
|
//using Autodesk.Revit;
|
|
//using Autodesk.Revit.Elements;
|
|
//using Autodesk.Revit.Enums;
|
|
//using Autodesk.Revit.Geometry;
|
|
//using Autodesk.Revit.Parameters;
|
|
//using RvtElement = Autodesk.Revit.Element;
|
|
//using GeoElement = Autodesk.Revit.Geometry.Element;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq; // in System.Core
|
|
using Autodesk.Revit;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.UI;
|
|
using Autodesk.Revit.ApplicationServices;
|
|
|
|
#endregion // Namespaces
|
|
|
|
#region Description
|
|
/// <summary>
|
|
/// Revit Family Creation API Lab - 3
|
|
///
|
|
/// This command defines a column family, and creates a column family with a L-shape profile.
|
|
/// It adds a simple formula and materials.
|
|
///
|
|
/// Objective:
|
|
/// ----------
|
|
///
|
|
/// In the previous labs, we have learned the following:
|
|
///
|
|
/// 0. set up family environment
|
|
/// 1. create a solid
|
|
/// 2. set alignment
|
|
/// 3. add types
|
|
/// 4. add reference planes
|
|
/// 5. add parameters
|
|
/// 6. add dimensions
|
|
///
|
|
/// In this lab, we will learn the following:
|
|
///
|
|
/// 7. add formula
|
|
/// 8. add materials
|
|
///
|
|
/// To test this lab, open a family template "Metric Column.rft", and run a command.
|
|
///
|
|
/// Context:
|
|
/// --------
|
|
///
|
|
/// In the previous rfa labs (lab1 & lab2), we have defined a column family, using a L-shape profile.
|
|
///
|
|
/// 5 Tw 4
|
|
/// +-+
|
|
/// | | 3 h = height
|
|
/// Depth | +---+ 2
|
|
/// +-----+ Td
|
|
/// 0 1
|
|
/// 6 Width
|
|
///
|
|
/// in addition to what we have learned in the previous labs, we will do the following:
|
|
///
|
|
/// 1. add two formulas: Tw = Width / 4.0; Td = Depth / 4.0;
|
|
/// 2. add materials: create a material parameter and assign with a material (e.g. "Glass")
|
|
///
|
|
/// Desclaimer: code in these labs is written for the purpose of learning the Revit family API.
|
|
/// In practice, there will be much room for performance and usability improvement.
|
|
/// For code readability, minimum error checking.
|
|
/// </summary>
|
|
#endregion // Description
|
|
|
|
namespace FamilyLabsCS
|
|
{
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Automatic)]
|
|
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Automatic)]
|
|
class RvtCmd_FamilyCreateColumnFormulaMaterial : IExternalCommand
|
|
{
|
|
// member variables for top level access to the Revit database
|
|
//
|
|
Application _rvtApp;
|
|
Document _rvtDoc;
|
|
|
|
// command main
|
|
//
|
|
public Result Execute(
|
|
ExternalCommandData commandData,
|
|
ref string message,
|
|
ElementSet elements )
|
|
{
|
|
// objects for the top level access
|
|
//
|
|
_rvtApp = commandData.Application.Application;
|
|
_rvtDoc = commandData.Application.ActiveUIDocument.Document;
|
|
|
|
// (0) This command works in the context of family editor only.
|
|
// We also check if the template is for an appropriate category if needed.
|
|
// Here we use a Column(i.e., Metric Column.rft) template.
|
|
// Although there is no specific checking about metric or imperial, our lab only works in metric for now.
|
|
//
|
|
if (!isRightTemplate(BuiltInCategory.OST_Columns))
|
|
{
|
|
Util.ErrorMsg( "Please open Metric Column.rft" );
|
|
return Result.Failed;
|
|
}
|
|
|
|
// (1.1) add reference planes
|
|
addReferencePlanes();
|
|
|
|
// (1.2) create a simple extrusion. we create a L-shape extrusion.
|
|
Extrusion pSolid = createSolid();
|
|
|
|
// (2) add alignment
|
|
addAlignments( pSolid );
|
|
|
|
// (3.1) add parameters
|
|
addParameters();
|
|
|
|
// (3.2) add dimensions
|
|
addDimensions();
|
|
|
|
// (3.3) add types
|
|
addTypes();
|
|
|
|
// (4.1) add formula
|
|
addFormulas();
|
|
|
|
// (4.2) add materials
|
|
addMaterials( pSolid );
|
|
|
|
// finally return
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
// ============================================
|
|
// (0) check if we have a correct template
|
|
// ============================================
|
|
bool isRightTemplate(BuiltInCategory targetCategory)
|
|
{
|
|
// This command works in the context of family editor only.
|
|
//
|
|
if( !_rvtDoc.IsFamilyDocument )
|
|
{
|
|
Util.ErrorMsg( "This command works only in the family editor." );
|
|
return false;
|
|
}
|
|
|
|
// Check the template for an appropriate category here if needed.
|
|
//
|
|
Category cat = _rvtDoc.Settings.Categories.get_Item( targetCategory );
|
|
if( _rvtDoc.OwnerFamily == null )
|
|
{
|
|
Util.ErrorMsg( "This command only works in the family context." );
|
|
return false;
|
|
}
|
|
if( !cat.Id.Equals( _rvtDoc.OwnerFamily.FamilyCategory.Id ) )
|
|
{
|
|
Util.ErrorMsg( "Category of this family document does not match the context required by this command." );
|
|
return false;
|
|
}
|
|
|
|
// if we come here, we should have a right one.
|
|
return true;
|
|
}
|
|
|
|
// ==============================
|
|
// (1.1) add reference planes
|
|
// ==============================
|
|
void addReferencePlanes()
|
|
{
|
|
//
|
|
// we are defining a simple L-shape profile like the following:
|
|
//
|
|
// 5 tw 4
|
|
// +-+
|
|
// | | 3 h = height
|
|
// d | +---+ 2
|
|
// +-----+ td
|
|
// 0 1
|
|
// 6 w
|
|
//
|
|
//
|
|
// we want to add ref planes along (1) 2-3 and (2)3-4.
|
|
// Name them "OffsetH" and "OffsetV" respectively. (H for horizontal, V for vertical).
|
|
//
|
|
double tw = mmToFeet( 150.0 ); // thickness added for Lab2. Hard-coding for simplicity.
|
|
double td = mmToFeet( 150.0 );
|
|
|
|
//
|
|
// (1) add a horizonal ref plane 2-3.
|
|
//
|
|
// get a plan view
|
|
View pViewPlan = findElement( typeof( ViewPlan ), "Lower Ref. Level" ) as View;
|
|
|
|
// we have predefined ref plane: Left/Right/Front/Back
|
|
// get the ref plane at Front, which is aligned to line 2-3
|
|
ReferencePlane refFront = findElement( typeof( ReferencePlane ), "Front" ) as ReferencePlane;
|
|
|
|
// get the bubble and free ends from front ref plane and offset by td.
|
|
//
|
|
XYZ p1 = refFront.BubbleEnd;
|
|
XYZ p2 = refFront.FreeEnd;
|
|
XYZ pBubbleEnd = new XYZ(p1.X, p1.Y + td, p1.Z);
|
|
XYZ pFreeEnd = new XYZ(p2.X, p2.Y + td, p2.Z);
|
|
|
|
// create a new one reference plane and name it "OffsetH"
|
|
//
|
|
ReferencePlane refPlane = _rvtDoc.FamilyCreate.NewReferencePlane( pBubbleEnd, pFreeEnd, XYZ.BasisZ, pViewPlan );
|
|
refPlane.Name = "OffsetH";
|
|
|
|
//
|
|
// (2) do the same to add a vertical reference plane.
|
|
//
|
|
|
|
// find the ref plane at left, which is aligned to line 3-4
|
|
ReferencePlane refLeft = findElement( typeof( ReferencePlane ), "Left" ) as ReferencePlane;
|
|
|
|
// get the bubble and free ends from front ref plane and offset by td.
|
|
//
|
|
p1 = refLeft.BubbleEnd;
|
|
p2 = refLeft.FreeEnd;
|
|
pBubbleEnd = new XYZ(p1.X + tw, p1.Y, p1.Z);
|
|
pFreeEnd = new XYZ(p2.X + tw, p2.Y, p2.Z);
|
|
|
|
// create a new reference plane and name it "OffsetV"
|
|
//
|
|
refPlane = _rvtDoc.FamilyCreate.NewReferencePlane( pBubbleEnd, pFreeEnd, XYZ.BasisZ, pViewPlan );
|
|
refPlane.Name = "OffsetV";
|
|
}
|
|
|
|
// =================================================================
|
|
// (1.2) create a simple solid by extrusion with L-shape profile
|
|
// =================================================================
|
|
Extrusion createSolid()
|
|
{
|
|
//
|
|
// (1) define a simple L-shape profile
|
|
//
|
|
//CurveArrArray pProflie = createBox();
|
|
CurveArrArray pProfile = createProfileLShape(); // Lab2
|
|
|
|
//
|
|
// (2) create a sketch plane
|
|
//
|
|
// we need to know the template. If you look at the template (Metric Column.rft) and "Front" view,
|
|
// you will see "Reference Plane" at "Lower Ref. Level". We are going to create an extrusion there.
|
|
// findElement() is a helper function that find an element of the given type and name. see below.
|
|
//
|
|
ReferencePlane pRefPlane = findElement( typeof( ReferencePlane ), "Reference Plane" ) as ReferencePlane; // need to know from the template
|
|
SketchPlane pSketchPlane = _rvtDoc.FamilyCreate.NewSketchPlane( pRefPlane.Plane );
|
|
|
|
// (3) height of the extrusion
|
|
//
|
|
// same as profile, you will need to know your template. unlike UI, the alightment will not adjust the geometry.
|
|
// You will need to have the exact location in order to set alignment.
|
|
// Here we hard code for simplicity. 4000 is the distance between Lower and Upper Ref. Level.
|
|
// as an exercise, try changing those values and see how it behaves.
|
|
//
|
|
double dHeight = mmToFeet( 4000.0 );
|
|
|
|
// (4) create an extrusion here. at this point. just an box, nothing else.
|
|
//
|
|
bool bIsSolid = true; // as oppose to void.
|
|
return _rvtDoc.FamilyCreate.NewExtrusion( bIsSolid, pProfile, pSketchPlane, dHeight );
|
|
}
|
|
|
|
// ===========================================
|
|
// (1.2a) create a simple L-shaped profile
|
|
// ===========================================
|
|
CurveArrArray createProfileLShape()
|
|
{
|
|
//
|
|
// define a simple L-shape profile
|
|
//
|
|
// 5 tw 4
|
|
// +-+
|
|
// | | 3 h = height
|
|
// d | +---+ 2
|
|
// +-----+ td
|
|
// 0 1
|
|
// 6 w
|
|
//
|
|
|
|
// sizes (hard coded for simplicity)
|
|
// note: these need to match reference plane. otherwise, alignment won't work.
|
|
// as an exercise, try changing those values and see how it behaves.
|
|
//
|
|
double w = mmToFeet( 600.0 ); // those are hard coded for simplicity here. in practice, you may want to find out from the references)
|
|
double d = mmToFeet( 600.0 );
|
|
double tw = mmToFeet( 150.0 ); // thickness added for Lab2
|
|
double td = mmToFeet( 150.0 );
|
|
|
|
// define vertices
|
|
//
|
|
const int nVerts = 6; // the number of vertices
|
|
|
|
XYZ[] pts = new XYZ[] {
|
|
new XYZ(-w / 2.0, -d / 2.0, 0.0),
|
|
new XYZ(w / 2.0, -d / 2.0, 0.0),
|
|
new XYZ(w / 2.0, (-d / 2.0) + td, 0.0),
|
|
new XYZ((-w / 2.0) + tw, (-d / 2.0) + td, 0.0),
|
|
new XYZ((-w / 2.0) + tw, d / 2.0, 0.0),
|
|
new XYZ(-w / 2.0, d / 2.0, 0.0),
|
|
new XYZ(-w / 2.0, -d / 2.0, 0.0) }; // the last one is to make the loop simple
|
|
|
|
// define a loop. define individual edges and put them in a curveArray
|
|
//
|
|
CurveArray pLoop = _rvtApp.Create.NewCurveArray();
|
|
for( int i = 0; i < nVerts; ++i )
|
|
{
|
|
Line line = _rvtApp.Create.NewLineBound( pts[i], pts[i + 1] );
|
|
pLoop.Append( line );
|
|
}
|
|
|
|
// then, put the loop in the curveArrArray as a profile
|
|
//
|
|
CurveArrArray pProfile = _rvtApp.Create.NewCurveArrArray();
|
|
pProfile.Append( pLoop );
|
|
// if we come here, we have a profile now.
|
|
|
|
return pProfile;
|
|
}
|
|
|
|
// ==============================================
|
|
// (1.2b) create a simple rectangular profile
|
|
// ==============================================
|
|
CurveArrArray createProfileRectangle()
|
|
{
|
|
//
|
|
// define a simple rectangular profile
|
|
//
|
|
// 3 2
|
|
// +---+
|
|
// | | d h = height
|
|
// +---+
|
|
// 0 1
|
|
// 4 w
|
|
//
|
|
|
|
// sizes (hard coded for simplicity)
|
|
// note: these need to match reference plane. otherwise, alignment won't work.
|
|
// as an exercise, try changing those values and see how it behaves.
|
|
//
|
|
double w = mmToFeet( 600.0 );
|
|
double d = mmToFeet( 600.0 );
|
|
|
|
// define vertices
|
|
//
|
|
const int nVerts = 4; // the number of vertices
|
|
|
|
XYZ[] pts = new XYZ[] {
|
|
new XYZ(-w / 2.0, -d / 2.0, 0.0),
|
|
new XYZ(w / 2.0, -d / 2.0, 0.0),
|
|
new XYZ(w / 2.0, d / 2.0, 0.0),
|
|
new XYZ(-w / 2.0, d / 2.0, 0.0),
|
|
new XYZ(-w / 2.0, -d / 2.0, 0.0) };
|
|
|
|
// define a loop. define individual edges and put them in a curveArray
|
|
//
|
|
CurveArray pLoop = _rvtApp.Create.NewCurveArray();
|
|
for( int i = 0; i < nVerts; ++i )
|
|
{
|
|
Line line = _rvtApp.Create.NewLineBound( pts[i], pts[i + 1] );
|
|
pLoop.Append( line );
|
|
}
|
|
|
|
// then, put the loop in the curveArrArray as a profile
|
|
//
|
|
CurveArrArray pProfile = _rvtApp.Create.NewCurveArrArray();
|
|
pProfile.Append( pLoop );
|
|
// if we come here, we have a profile now.
|
|
|
|
return pProfile;
|
|
}
|
|
|
|
// ======================================
|
|
// (2.1) add alignments
|
|
// ======================================
|
|
void addAlignments( Extrusion pBox )
|
|
{
|
|
//
|
|
// (1) we want to constrain the upper face of the column to the "Upper Ref Level"
|
|
//
|
|
|
|
// which direction are we looking at?
|
|
//
|
|
View pView = findElement( typeof( View ), "Front" ) as View;
|
|
|
|
// find the upper ref level
|
|
// findElement() is a helper function. see below.
|
|
//
|
|
Level upperLevel = findElement( typeof( Level ), "Upper Ref Level" ) as Level;
|
|
Reference ref1 = upperLevel.PlaneReference;
|
|
|
|
// find the face of the box
|
|
// findFace() is a helper function. see below.
|
|
//
|
|
PlanarFace upperFace = findFace( pBox, new XYZ( 0.0, 0.0, 1.0 ) ); // find a face whose normal is z-up.
|
|
Reference ref2 = upperFace.Reference;
|
|
|
|
// create alignments
|
|
//
|
|
_rvtDoc.FamilyCreate.NewAlignment( pView, ref1, ref2 );
|
|
|
|
//
|
|
// (2) do the same for the lower level
|
|
//
|
|
|
|
// find the lower ref level
|
|
// findElement() is a helper function. see below.
|
|
//
|
|
Level lowerLevel = findElement( typeof( Level ), "Lower Ref. Level" ) as Level;
|
|
Reference ref3 = lowerLevel.PlaneReference;
|
|
|
|
// find the face of the box
|
|
// findFace() is a helper function. see below.
|
|
PlanarFace lowerFace = findFace( pBox, new XYZ( 0.0, 0.0, -1.0 ) ); // find a face whose normal is z-down.
|
|
Reference ref4 = lowerFace.Reference;
|
|
|
|
// create alignments
|
|
//
|
|
_rvtDoc.FamilyCreate.NewAlignment( pView, ref3, ref4 );
|
|
|
|
//
|
|
// (3) same idea for the Right/Left/Front/Back
|
|
//
|
|
// get the plan view
|
|
// note: same name maybe used for different view types. either one should work.
|
|
View pViewPlan = findElement( typeof( ViewPlan ), "Lower Ref. Level" ) as View;
|
|
|
|
// find reference planes
|
|
ReferencePlane refRight = findElement( typeof( ReferencePlane ), "Right" ) as ReferencePlane;
|
|
ReferencePlane refLeft = findElement( typeof( ReferencePlane ), "Left" ) as ReferencePlane;
|
|
ReferencePlane refFront = findElement( typeof( ReferencePlane ), "Front" ) as ReferencePlane;
|
|
ReferencePlane refBack = findElement( typeof( ReferencePlane ), "Back" ) as ReferencePlane;
|
|
ReferencePlane refOffsetV = findElement( typeof( ReferencePlane ), "OffsetV" ) as ReferencePlane; // added for L-shape
|
|
ReferencePlane refOffsetH = findElement( typeof( ReferencePlane ), "OffsetH" ) as ReferencePlane; // added for L-shape
|
|
|
|
// find the face of the box
|
|
// Note: findFace need to be enhanced for this as face normal is not enough to determine the face.
|
|
//
|
|
PlanarFace faceRight = findFace( pBox, new XYZ( 1.0, 0.0, 0.0 ), refRight ); // modified for L-shape
|
|
PlanarFace faceLeft = findFace( pBox, new XYZ( -1.0, 0.0, 0.0 ) );
|
|
PlanarFace faceFront = findFace( pBox, new XYZ( 0.0, -1.0, 0.0 ) );
|
|
PlanarFace faceBack = findFace( pBox, new XYZ( 0.0, 1.0, 0.0 ), refBack ); // modified for L-shape
|
|
PlanarFace faceOffsetV = findFace( pBox, new XYZ( 1.0, 0.0, 0.0 ), refOffsetV ); // added for L-shape
|
|
PlanarFace faceOffsetH = findFace( pBox, new XYZ( 0.0, 1.0, 0.0 ), refOffsetH ); // added for L-shape
|
|
|
|
// create alignments
|
|
//
|
|
_rvtDoc.FamilyCreate.NewAlignment( pViewPlan, refRight.Reference, faceRight.Reference );
|
|
_rvtDoc.FamilyCreate.NewAlignment( pViewPlan, refLeft.Reference, faceLeft.Reference );
|
|
_rvtDoc.FamilyCreate.NewAlignment( pViewPlan, refFront.Reference, faceFront.Reference );
|
|
_rvtDoc.FamilyCreate.NewAlignment( pViewPlan, refBack.Reference, faceBack.Reference );
|
|
_rvtDoc.FamilyCreate.NewAlignment( pViewPlan, refOffsetV.Reference, faceOffsetV.Reference ); // added for L-shape
|
|
_rvtDoc.FamilyCreate.NewAlignment( pViewPlan, refOffsetH.Reference, faceOffsetH.Reference ); // added for L-shape
|
|
}
|
|
|
|
// ======================================
|
|
// (3.1) add parameters
|
|
// ======================================
|
|
void addParameters()
|
|
{
|
|
FamilyManager mgr = _rvtDoc.FamilyManager;
|
|
|
|
// API parameter group for Dimension is PG_GEOMETRY:
|
|
//
|
|
FamilyParameter paramTw = mgr.AddParameter(
|
|
"Tw", BuiltInParameterGroup.PG_GEOMETRY,
|
|
ParameterType.Length, false );
|
|
|
|
FamilyParameter paramTd = mgr.AddParameter(
|
|
"Td", BuiltInParameterGroup.PG_GEOMETRY,
|
|
ParameterType.Length, false );
|
|
|
|
// set initial values:
|
|
//
|
|
double tw = mmToFeet( 150.0 );
|
|
double td = mmToFeet( 150.0 );
|
|
mgr.Set( paramTw, tw );
|
|
mgr.Set( paramTd, td );
|
|
|
|
// (2) add a parameter for material finish
|
|
// we are adding material arameter in addMaterials function.
|
|
// See addMaterials for the actual implementation.
|
|
//
|
|
}
|
|
|
|
// ======================================
|
|
// (3.2) add dimensions
|
|
// ======================================
|
|
void addDimensions()
|
|
{
|
|
// find the plan view
|
|
//
|
|
View pViewPlan = findElement( typeof( ViewPlan ), "Lower Ref. Level" ) as View;
|
|
|
|
// find reference planes
|
|
//
|
|
ReferencePlane refLeft = findElement( typeof( ReferencePlane ), "Left" ) as ReferencePlane;
|
|
ReferencePlane refFront = findElement( typeof( ReferencePlane ), "Front" ) as ReferencePlane;
|
|
ReferencePlane refOffsetV = findElement( typeof( ReferencePlane ), "OffsetV" ) as ReferencePlane; // OffsetV is added for L-shape
|
|
ReferencePlane refOffsetH = findElement( typeof( ReferencePlane ), "OffsetH" ) as ReferencePlane; // OffsetH is added for L-shape
|
|
|
|
//
|
|
// (1) add dimension between the reference planes 'Left' and 'OffsetV', and label it as 'Tw'
|
|
//
|
|
|
|
// define a dimension line
|
|
//
|
|
XYZ p0 = refLeft.FreeEnd;
|
|
XYZ p1 = refOffsetV.FreeEnd;
|
|
Line pLine = _rvtApp.Create.NewLineBound( p0, p1 );
|
|
|
|
// define references
|
|
//
|
|
ReferenceArray pRefArray = new ReferenceArray();
|
|
pRefArray.Append( refLeft.Reference );
|
|
pRefArray.Append( refOffsetV.Reference );
|
|
|
|
// create a dimension
|
|
//
|
|
Dimension pDimTw = _rvtDoc.FamilyCreate.NewDimension( pViewPlan, pLine, pRefArray );
|
|
|
|
// add label to the dimension
|
|
//
|
|
FamilyParameter paramTw = _rvtDoc.FamilyManager.get_Parameter( "Tw" );
|
|
pDimTw.Label = paramTw;
|
|
|
|
//
|
|
// (2) do the same for dimension between 'Front' and 'OffsetH', and lable it as 'Td'
|
|
//
|
|
|
|
// define a dimension line
|
|
//
|
|
p0 = refFront.FreeEnd;
|
|
p1 = refOffsetH.FreeEnd;
|
|
pLine = _rvtApp.Create.NewLineBound( p0, p1 );
|
|
|
|
// define references
|
|
//
|
|
pRefArray = new ReferenceArray();
|
|
pRefArray.Append( refFront.Reference );
|
|
pRefArray.Append( refOffsetH.Reference );
|
|
|
|
// create a dimension
|
|
//
|
|
Dimension pDimTd = _rvtDoc.FamilyCreate.NewDimension( pViewPlan, pLine, pRefArray );
|
|
|
|
// add label to the dimension
|
|
//
|
|
FamilyParameter paramTd = _rvtDoc.FamilyManager.get_Parameter( "Td" );
|
|
pDimTd.Label = paramTd;
|
|
}
|
|
|
|
// ======================================
|
|
// (3.3) add types
|
|
// ======================================
|
|
void addTypes()
|
|
{
|
|
// addType(name, Width, Depth)
|
|
//
|
|
//addType("600x900", 600.0, 900.0)
|
|
//addType("1000x300", 1000.0, 300.0)
|
|
//addType("600x600", 600.0, 600.0)
|
|
|
|
// addType(name, Width, Depth, Tw, Td)
|
|
//
|
|
addType( "600x900", 600.0, 900.0, 150.0, 225.0 );
|
|
addType( "1000x300", 1000.0, 300.0, 250.0, 75.0 );
|
|
addType( "600x600", 600.0, 600.0, 150.0, 150.0 );
|
|
}
|
|
|
|
// add one type (version 2)
|
|
//
|
|
void addType( string name, double w, double d, double tw, double td )
|
|
{
|
|
// get the family manager from the current doc
|
|
FamilyManager pFamilyMgr = _rvtDoc.FamilyManager;
|
|
|
|
// add new types with the given name
|
|
//
|
|
FamilyType type1 = pFamilyMgr.NewType( name );
|
|
|
|
// look for 'Width' and 'Depth' parameters and set them to the given value
|
|
//
|
|
|
|
// first 'Width'
|
|
//
|
|
FamilyParameter paramW = pFamilyMgr.get_Parameter( "Width" );
|
|
double valW = mmToFeet( w );
|
|
if( paramW != null )
|
|
{
|
|
pFamilyMgr.Set( paramW, valW );
|
|
}
|
|
|
|
// same idea for 'Depth'
|
|
//
|
|
FamilyParameter paramD = pFamilyMgr.get_Parameter( "Depth" );
|
|
double valD = mmToFeet( d );
|
|
if( paramD != null )
|
|
{
|
|
pFamilyMgr.Set( paramD, valD );
|
|
}
|
|
|
|
// let's set "Tw' and 'Td'
|
|
//
|
|
FamilyParameter paramTw = pFamilyMgr.get_Parameter( "Tw" );
|
|
double valTw = mmToFeet( tw );
|
|
if( paramTw != null )
|
|
{
|
|
pFamilyMgr.Set( paramTw, valTw );
|
|
}
|
|
FamilyParameter paramTd = pFamilyMgr.get_Parameter( "Td" );
|
|
double valTd = mmToFeet( td );
|
|
if( paramTd != null )
|
|
{
|
|
pFamilyMgr.Set( paramTd, valTd );
|
|
}
|
|
}
|
|
|
|
// add one type (version 1)
|
|
//
|
|
void addType( string name, double w, double d )
|
|
{
|
|
// get the family manager from the current doc
|
|
FamilyManager pFamilyMgr = _rvtDoc.FamilyManager;
|
|
|
|
// add new types with the given name
|
|
//
|
|
FamilyType type1 = pFamilyMgr.NewType( name );
|
|
|
|
// look for 'Width' and 'Depth' parameters and set them to the given value
|
|
//
|
|
// first 'Width'
|
|
//
|
|
FamilyParameter paramW = pFamilyMgr.get_Parameter( "Width" );
|
|
double valW = mmToFeet( w );
|
|
if( paramW != null )
|
|
{
|
|
pFamilyMgr.Set( paramW, valW );
|
|
}
|
|
|
|
// same idea for 'Depth'
|
|
//
|
|
FamilyParameter paramD = pFamilyMgr.get_Parameter( "Depth" );
|
|
double valD = mmToFeet( d );
|
|
if( paramD != null )
|
|
{
|
|
pFamilyMgr.Set( paramD, valD );
|
|
}
|
|
}
|
|
|
|
// ======================================
|
|
// (4.1) add formula
|
|
// ======================================
|
|
public void addFormulas()
|
|
{
|
|
// we will add the following fomulas
|
|
// Tw = Width / 4.0
|
|
// Td = Depth / 4.0
|
|
//
|
|
|
|
// first get the parameter
|
|
FamilyManager pFamilyMgr = _rvtDoc.FamilyManager;
|
|
|
|
FamilyParameter paramTw = pFamilyMgr.get_Parameter( "Tw" );
|
|
FamilyParameter paramTd = pFamilyMgr.get_Parameter( "Td" );
|
|
|
|
// set the formula
|
|
pFamilyMgr.SetFormula( paramTw, "Width / 4.0" );
|
|
pFamilyMgr.SetFormula( paramTd, "Depth / 4.0" );
|
|
}
|
|
|
|
// ======================================
|
|
// (4.2) add materials
|
|
// ======================================
|
|
//
|
|
// in Revit 2010, you cannot modify asset.
|
|
// SPR# 155053 - WishList: Ability to access\modify properties in Render Appearance of Materials using API.
|
|
// To Do in future: you can extend this functionality to create a new one in future.
|
|
//
|
|
// This function is only for reference. this is not used. If use this way, it is fixed at solid level. You cannot change it.
|
|
//
|
|
public void addMaterialsToSolid( Extrusion pSolid )
|
|
{
|
|
// We assume Material type "Glass" exists. Template "Metric Column.rft" include "Glass",
|
|
// which in fact is the only interesting one to see the effect.
|
|
// In practice, you will want to include in your template.
|
|
//
|
|
// To Do: For the exersize, create it with more appropriate ones in UI, then use the name here.
|
|
//
|
|
Material pMat = findElement( typeof( Material ), "Glass" ) as Material;
|
|
if( pMat != null )
|
|
{
|
|
// no material with the given name.
|
|
ElementId idMat = pMat.Id;
|
|
pSolid.get_Parameter( "Material" ).Set( idMat );
|
|
}
|
|
}
|
|
|
|
public void addMaterials( Extrusion pSolid )
|
|
{
|
|
// We assume Material type "Glass" exists. Template "Metric Column.rft" include "Glass",
|
|
// which in fact is the only interesting one to see the effect.
|
|
// In practice, you will want to include in your template.
|
|
//
|
|
// To Do: For the exersize, create it with more appropriate ones in UI, then use the name here.
|
|
//
|
|
|
|
// (1) get the materials id that we are intersted in (e.g., "Glass")
|
|
//
|
|
Material pMat = findElement( typeof( Material ), "Glass" ) as Material;
|
|
if( pMat != null )
|
|
{
|
|
ElementId idMat = pMat.Id;
|
|
// (2a) this add a material to the solid base. but then, we cannot change it for each column.
|
|
//
|
|
//pSolid.Parameter("Material").Set(idMat)
|
|
|
|
// (2b) add a parameter for material finish
|
|
//
|
|
// this time we use instance parameter so that we can change it at instance level.
|
|
//
|
|
FamilyManager pFamilyMgr = _rvtDoc.FamilyManager;
|
|
FamilyParameter famParamFinish = pFamilyMgr.AddParameter( "ColumnFinish", BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, true );
|
|
|
|
// (2b.1) associate material parameter to the family parameter we just added
|
|
//
|
|
Parameter paramMat = pSolid.get_Parameter( "Material" );
|
|
pFamilyMgr.AssociateElementParameterToFamilyParameter( paramMat, famParamFinish );
|
|
|
|
// (2b.2) for our convenience, let's add another type with Glass finish
|
|
//
|
|
addType( "Glass", 600.0, 600.0 );
|
|
pFamilyMgr.Set( famParamFinish, idMat );
|
|
}
|
|
}
|
|
|
|
#region Helper Functions
|
|
|
|
// =============================================================================================
|
|
// helper function: given a solid, find a planar face with the given normal (version 2)
|
|
// this is a slightly enhaced version of previous version and checks if the face is on the given reference plane.
|
|
// =============================================================================================
|
|
PlanarFace findFace( Extrusion pBox, XYZ normal, ReferencePlane refPlane )
|
|
{
|
|
// get the geometry object of the given element
|
|
//
|
|
Options op = new Options();
|
|
op.ComputeReferences = true;
|
|
GeometryObjectArray geomObjs = pBox.get_Geometry( op ).Objects;
|
|
|
|
// loop through the array and find a face with the given normal
|
|
//
|
|
foreach( GeometryObject geomObj in geomObjs )
|
|
{
|
|
if( geomObj is Solid ) // solid is what we are interested in.
|
|
{
|
|
Solid pSolid = geomObj as Solid;
|
|
FaceArray faces = pSolid.Faces;
|
|
foreach( Face pFace in faces )
|
|
{
|
|
PlanarFace pPlanarFace = pFace as PlanarFace;
|
|
// check to see if they have same normal
|
|
if( ( pPlanarFace != null ) && pPlanarFace.Normal.IsAlmostEqualTo( normal ) )
|
|
{
|
|
// additionally, we want to check if the face is on the reference plane
|
|
//
|
|
XYZ p0 = refPlane.BubbleEnd;
|
|
XYZ p1 = refPlane.FreeEnd;
|
|
Line pCurve = _rvtApp.Create.NewLineBound( p0, p1 );
|
|
if( pPlanarFace.Intersect( pCurve ) == SetComparisonResult.Subset )
|
|
{
|
|
return pPlanarFace; // we found the face
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// will come back later as needed.
|
|
//
|
|
//else if (geomObj is Instance)
|
|
//{
|
|
//}
|
|
//else if (geomObj is Curve)
|
|
//{
|
|
//}
|
|
//else if (geomObj is Mesh)
|
|
//{
|
|
//}
|
|
}
|
|
|
|
// if we come here, we did not find any.
|
|
return null;
|
|
}
|
|
|
|
// =============================================================
|
|
// helper function: find a planar face with the given normal
|
|
// =============================================================
|
|
PlanarFace findFace( Extrusion pBox, XYZ normal )
|
|
{
|
|
// get the geometry object of the given element
|
|
//
|
|
Options op = new Options();
|
|
op.ComputeReferences = true;
|
|
GeometryObjectArray geomObjs = pBox.get_Geometry( op ).Objects;
|
|
|
|
// loop through the array and find a face with the given normal
|
|
//
|
|
foreach( GeometryObject geomObj in geomObjs )
|
|
{
|
|
if( geomObj is Solid ) // solid is what we are interested in.
|
|
{
|
|
Solid pSolid = geomObj as Solid;
|
|
FaceArray faces = pSolid.Faces;
|
|
foreach( Face pFace in faces )
|
|
{
|
|
PlanarFace pPlanarFace = pFace as PlanarFace;
|
|
if( ( pPlanarFace != null ) && pPlanarFace.Normal.IsAlmostEqualTo( normal ) ) // we found the face
|
|
{
|
|
return pPlanarFace;
|
|
}
|
|
}
|
|
}
|
|
|
|
// will come back later as needed.
|
|
//
|
|
//else if (geomObj is Instance)
|
|
//{
|
|
//}
|
|
//else if (geomObj is Curve)
|
|
//{
|
|
//}
|
|
//else if (geomObj is Mesh)
|
|
//{
|
|
//}
|
|
}
|
|
|
|
// if we come here, we did not find any.
|
|
return null;
|
|
}
|
|
|
|
// ==================================================================================
|
|
// helper function: find an element of the given type and the name.
|
|
// You can use this, for example, to find Reference or Level with the given name.
|
|
// ==================================================================================
|
|
Element findElement( Type targetType, string targetName )
|
|
{
|
|
// get the elements of the given type
|
|
//
|
|
FilteredElementCollector collector = new FilteredElementCollector(_rvtDoc);
|
|
collector.WherePasses(new ElementClassFilter(targetType));
|
|
|
|
// parse the collection for the given name
|
|
// using LINQ query here.
|
|
//
|
|
var targetElems = from element in collector where element.Name.Equals(targetName) select element;
|
|
List<Element> elems = targetElems.ToList<Element>();
|
|
|
|
if (elems.Count > 0)
|
|
{ // we should have only one with the given name.
|
|
return elems[0];
|
|
}
|
|
|
|
// cannot find it.
|
|
return null;
|
|
}
|
|
|
|
// ===============================================
|
|
// helper function: convert millimeter to feet
|
|
// ===============================================
|
|
double mmToFeet( double mmVal )
|
|
{
|
|
return ( mmVal / 304.8 );
|
|
}
|
|
|
|
#endregion // Helper Functions
|
|
}
|
|
}
|