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

1136 lines
41 KiB
VB.net

#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.
''
'' Written by M.Harada
''
#End Region
#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.
'Imports System.Linq
'Imports Autodesk.Revit
'Imports Autodesk.Revit.DB
'Imports Autodesk.Revit.UI
'Imports Autodesk.Revit.ApplicationServices
#End Region
#Region "Description"
'' Family API how to
''
#End Region
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_v2
Implements IExternalCommand
'' member variables
Dim m_rvtUIApp As UIApplication
Dim m_rvtUIDoc As UIDocument
Dim m_rvtApp As Application
Dim m_rvtDoc As Document
Dim m_familyMgr As FamilyManager
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Autodesk.Revit.UI.Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
'' Get the access to the top most objects.
'' (we may not use them all in this specific lab. just to show that the way we access is same as in the project.)
''
m_rvtUIApp = commandData.Application
m_rvtUIDoc = m_rvtUIApp.ActiveUIDocument
m_rvtApp = m_rvtUIApp.Application
m_rvtDoc = m_rvtUIDoc.Document
m_familyMgr = m_rvtDoc.FamilyManager '' specific to family context
'Dim res As TaskDialogResult '' result of task dialog
'' (1) Plan (insertion point, patametric origin).
'' like in the UI, you will still need to plan. choose a right template
If Not ValidateDocument(m_rvtDoc) Then
Return Result.Failed
End If
'' (2) add reference planes
AddReferencePlanes()
'' (3.1) add parameters
AddParameters()
'' (3.2) add dimensions
AddDimensions()
'res = TaskDialog.Show("Family API", "Do you want to continue?", (TaskDialogCommonButtons.Yes Or TaskDialogCommonButtons.No))
'If res = TaskDialogResult.No Then
' Return Result.Succeeded
'End If
'' (5) add types
AddTypes()
'' (7.1) add geometry
AddGeometrySolid()
'' (7.2) add another geometry
AddGeometryModelLine()
'res = TaskDialog.Show("Family API", "Do you want to continue?", (TaskDialogCommonButtons.Yes Or TaskDialogCommonButtons.No))
'If res = TaskDialogResult.No Then
' Return Result.Succeeded
'End If
'' (7.3) add another geometry
AddGeometrySymbolicLines()
'' finally return
Return Result.Succeeded
End Function
Public Sub New(ByVal commandData)
init(commandData)
End Sub
Sub init(ByVal commandData As ExternalCommandData)
'' Get the access to the top most objects.
'' (we may not use them all in this specific lab. just to show that the way we access is same as in the project.)
''
m_rvtUIApp = commandData.Application
m_rvtUIDoc = m_rvtUIApp.ActiveUIDocument
m_rvtApp = m_rvtUIApp.Application
m_rvtDoc = m_rvtUIDoc.Document
m_familyMgr = m_rvtDoc.FamilyManager '' specific to family context
End Sub
'' ============================================
'' 1. Plan.
'' ============================================
'' Like with UI, we will still need to use the right template to start with.
'' Using API, you can check if the document dontext is family editor.
'' Note: you can also contorl the visibility of a command in the addin manifest, too.
'' 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.
''
Function ValidateDocument(ByVal rvtDoc As Document) As Boolean
'' our command works in the context of family editor only
If Not rvtDoc.IsFamilyDocument Then
TaskDialog.Show("Family API", "This command works only in the family editor.")
Return False
End If
'' check if we have a right template
Dim ownerFamily As Family = rvtDoc.OwnerFamily
If ownerFamily Is Nothing Then
TaskDialog.Show("Family API", "This document does not have Owner Family.")
Return False
End If
'' check the family category of this document
'' we assume that we want to create a column. Hard-coding for simplicity.
Dim catColumn As Category = rvtDoc.Settings.Categories.Item(BuiltInCategory.OST_Columns)
If Not ownerFamily.FamilyCategory.Id.Equals(catColumn.Id) Then
TaskDialog.Show("Family API", "The category of this document does not match the context of this commands. Please open Metric Column.rft")
End If
'' Note: changing the category through API is not possible as of Revit 2011. (possible in the UI).
'' You will need to prepare a template before hand.
'' Revit SPR #187735 API wish: change family category.
'' if we come here, we should have a right template
Return True
End Function
Function ValidateDocument() As Boolean
'' our command works in the context of family editor only
If Not m_rvtDoc.IsFamilyDocument Then
TaskDialog.Show("Family API", "This command works only in the family editor.")
Return False
End If
'' check if we have a right template
Dim ownerFamily As Family = m_rvtDoc.OwnerFamily
If ownerFamily Is Nothing Then
TaskDialog.Show("Family API", "This document does not have Owner Family.")
Return False
End If
'' check the family category of this document
'' we assume that we want to create a column. Hard-coding for simplicity.
Dim catColumn As Category = m_rvtDoc.Settings.Categories.Item(BuiltInCategory.OST_Columns)
If Not ownerFamily.FamilyCategory.Id.Equals(catColumn.Id) Then
TaskDialog.Show("Family API", "The category of this document does not match the context of this commands. Please open Metric Column.rft")
End If
'' Note: changing the category through API is not possible as of Revit 2011. (possible in the UI).
'' You will need to prepare a template before hand.
'' Revit SPR #187735 API wish: change family category.
'' if we come here, we should have a right template
Return True
End Function
'' ============================================
'' 2. Add Reference Planes
'' ============================================
#Region "Reference Planes"
Sub AddReferencePlanes()
''
'' we are defining a simple L-shaped 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).
''
'' (1) add a horizonal reference plane 2-3.
AddReferencePlane_HorizontalOffset()
'' (2) add a vertical reference plane. 3-4
AddReferencePlane_VerticalOffset()
End Sub
Sub AddReferencePlane_HorizontalOffset()
'' thickness or offset value. Hard-coding for simplicity.
Dim td As Double = Utils.mmToFeet(150) '' if you are using metric, convert it.
'Dim td As Double = 0.5 '' in feet
'' (1) add a horizonal ref plane 2-3.
'' get a plan view
Dim pViewPlan As View = Utils.FindElement(m_rvtDoc, GetType(ViewPlan), "Lower Ref. Level")
'' we have predefined ref plane: front/back/left/right
'' get the ref plane at front, which is aligned to line 2-3
Dim refFront As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Front")
'' get the bubble and free ends from front ref plane and offset by td.
Dim p1 As XYZ = refFront.BubbleEnd
Dim p2 As XYZ = refFront.FreeEnd
Dim pt1 As New XYZ(p1.X, p1.Y + td, p1.Z)
Dim pt2 As New XYZ(p2.X, p2.Y + td, p2.Z)
'' create a reference plane
Dim refPlane As ReferencePlane = m_rvtDoc.FamilyCreate.NewReferencePlane(pt1, pt2, XYZ.BasisZ, pViewPlan)
refPlane.Name = "OffsetH"
End Sub
Sub AddReferencePlane_VerticalOffset()
'' offset value Hard-coding for simplicity.
Dim tw As Double = Utils.mmToFeet(150)
'Dim tw As Double = 0.5 '' in feet
'' get a plan view
Dim pViewPlan As View = Utils.FindElement(m_rvtDoc, GetType(ViewPlan), "Lower Ref. Level")
'' find the ref plane at left, which is aligned to line 3-4
Dim refLeft As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Left")
'' get the bubble and free ends from front ref plane and offset by tw.
Dim p1 As XYZ = refLeft.BubbleEnd
Dim p2 As XYZ = refLeft.FreeEnd
Dim pt1 As New XYZ(p1.X + tw, p1.Y, p1.Z)
Dim pt2 As New XYZ(p2.X + tw, p2.Y, p2.Z)
'' create a reference plane
Dim refPlane As ReferencePlane = m_rvtDoc.FamilyCreate.NewReferencePlane(pt1, pt2, XYZ.BasisZ, pViewPlan)
refPlane.Name = "OffsetV"
End Sub
#End Region
#Region "Parameters"
'' ============================================
'' (3.1) add parameters
'' ============================================
Sub AddParameters()
'' (1) add dimensional parameters Tw and Td.
AddParameter_Tw()
AddParameter_Td()
'' (2) add a parameter for material finish
'' we are adding material parameter in addMaterials function. See addMaterials for the actual implementation.
''
AddParameter_Material()
End Sub
Sub AddParameter_Tw()
'' parameter group for Dimension is PG_GEOMETRY in API.
'' for simplicity, we assume this is a length dimention in our context.
'' the 4th argument indicates if this is an instance parameter.
''
Dim paramTw As FamilyParameter = _
m_familyMgr.AddParameter("Tw", BuiltInParameterGroup.PG_GEOMETRY, ParameterType.Length, False)
'' give initial values.
Dim tw As Double = Utils.mmToFeet(150.0) '' in metric
'Dim tw As Double = 0.5 '' in feet
m_familyMgr.Set(paramTw, tw)
'' if you want, you can also add a formula.
'' here we set Tw as one fourth of Width.
m_familyMgr.SetFormula(paramTw, "Width / 4.0") '' Width is the parameter we have already.
End Sub
Sub AddParameter_Td()
'' parameter group for Dimension is PG_GEOMETRY in API.
'' for simplicity, we assume this is a length dimention in our context.
'' the 4th argument indicates if this is an instance parameter.
''
Dim paramTd As FamilyParameter = _
m_familyMgr.AddParameter("Td", BuiltInParameterGroup.PG_GEOMETRY, ParameterType.Length, False)
'' give initial values.
Dim td As Double = Utils.mmToFeet(150.0) '' in metric
'Dim td As Double = 0.5 '' in feet
m_familyMgr.Set(paramTd, td)
'' if you want, you can also add a formula.
'' here we set Td as one fourth of Depth.
m_familyMgr.SetFormula(paramTd, "Depth / 4.0") '' Depth is the parameter we have already.
End Sub
Sub AddParameter_Material()
'' add a parameter for material finish under "Materials and Finishes"
'' this time, we define instance parameter so that we can change it at the instance level.
'' you will see "(default)" after the name if it is an instance parameter.
Dim param As FamilyParameter = _
m_familyMgr.AddParameter("Column Finish", BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, True)
' '' find a material "Glass"
' '' if you do not specify, the default will be <By Category>
' ''
'Dim pMat As Material = Utils.FindElement(m_rvtDoc, GetType(Material), "Glass") ' hard coded fot simplicity.
'If pMat Is Nothing Then
' '' no material with the given name.
' Return
'End If
'Dim idMat As ElementId = pMat.Id
'' give an initial value
'' if you don't give the initial value, it will be <By Category>
'm_familyMgr.Set(param, idMat)
End Sub
#End Region
#Region "Dimensions"
'' ============================================
'' (3.2) add dimensions
'' ============================================
'' add two dimensions between the reference planes:
'' Tw = Left and OffsetV
'' Td = Front and OffsetH
''
Sub AddDimensions()
AddDimention_Tw()
AddDimention_Td()
End Sub
'' add dimension between 'Left' and 'OffsetV', and lable it as Tw.
''
Sub AddDimention_Tw()
'' find the plan view that we want to place a dimension
Dim pViewPlan As View = Utils.FindElement(m_rvtDoc, GetType(ViewPlan), "Lower Ref. Level")
'' find two reference planes which we want to add a dimension between
Dim ref1 As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Left")
Dim ref2 As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "OffsetV")
'' make an array of references
Dim pRefArray As New ReferenceArray
pRefArray.Append(ref1.Reference)
pRefArray.Append(ref2.Reference)
'' define a dimension line
Dim p0 As XYZ = ref1.FreeEnd
Dim p1 As XYZ = ref2.FreeEnd
Dim pLine As Line = m_rvtApp.Create.NewLineBound(p0, p1)
'' create a dimension
Dim pDimTw As Dimension = m_rvtDoc.FamilyCreate.NewDimension(pViewPlan, pLine, pRefArray)
'' add label to the dimension
pDimTw.Label = m_familyMgr.Parameter("Tw")
End Sub
''
'' same idea. add dimension between 'Front' and 'OffsetH', and lable it as 'Td
''
Sub AddDimention_Td()
'' find the plan view that we want to place a dimension
Dim pViewPlan As View = Utils.FindElement(m_rvtDoc, GetType(ViewPlan), "Lower Ref. Level")
'' find two reference planes which we want to add a dimension between
Dim ref1 As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Front")
Dim ref2 As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "OffsetH")
'' make an array of references
Dim pRefArray As New ReferenceArray
pRefArray.Append(ref1.Reference)
pRefArray.Append(ref2.Reference)
'' define a dimension line
Dim p0 As XYZ = ref1.FreeEnd
Dim p1 As XYZ = ref2.FreeEnd
Dim pLine As Line = m_rvtApp.Create.NewLineBound(p0, p1)
'' create a dimension
Dim pDimTw As Dimension = m_rvtDoc.FamilyCreate.NewDimension(pViewPlan, pLine, pRefArray)
'' add label to the dimension
pDimTw.Label = m_familyMgr.Parameter("Td")
End Sub
#End Region
#Region "Types"
'' ============================================
'' (5) add types
'' ============================================
'' since we have formulas set up between Width and Tw, and Depth and Td.
''
Sub AddTypes()
'' addType(name, Width, Depth )
''
AddType("600x900", 600.0, 900.0)
AddType("1000x300", 1000.0, 300.0)
AddType("600x600", 600.0, 600.0)
End Sub
'' add one type
''
Sub AddType(ByVal name As String, ByVal w As Double, ByVal d As Double)
'' add new types with the given name.
'' the new type becomes the current type
Dim type1 As FamilyType = m_familyMgr.NewType(name)
'' look for 'Width' and 'Depth' parameters and set them to the given value
''
Dim paramW As FamilyParameter = m_familyMgr.Parameter("Width")
Dim valW As Double = Utils.mmToFeet(w)
If paramW IsNot Nothing Then
m_familyMgr.Set(paramW, valW)
End If
Dim paramD As FamilyParameter = m_familyMgr.Parameter("Depth")
Dim valD As Double = Utils.mmToFeet(d)
If paramD IsNot Nothing Then
m_familyMgr.Set(paramD, valD)
End If
End Sub
#End Region
#Region "Geometry Solid"
'' ============================================
'' (7.1) add geometry solid
'' ============================================
Sub AddGeometrySolid()
Dim pSolid As Extrusion = CreateSolid()
m_rvtDoc.Regenerate()
AddAlignments(pSolid)
SetVisibility(pSolid)
addMaterials(pSolid)
End Sub
'' ============================================
'' (7.1.1) create a simple solid by extrusion with L-shape profile
'' ============================================
Function CreateSolid() As Extrusion
'' (1) define a simple L-shape profile
''
Dim pProfile As CurveArrArray = CreateProfileLShape()
'' (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.
''
Dim pRefPlane As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Reference Plane") ' need to know from the template
Dim pSketchPlane As SketchPlane = m_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.
''
Dim dHeight As Double = Utils.mmToFeet(4000) '' distance between Lower and Upper Ref Level.
'' (4) create an extrusion here. at this point.
''
Dim bIsSolid As Boolean = True '' as oppose to void.
Dim pSolid As Extrusion = m_rvtDoc.FamilyCreate.NewExtrusion(bIsSolid, pProfile, pSketchPlane, dHeight)
Return pSolid
End Function
'' ============================================
'' (7.1.1.1) create a simple L-shaped profile
'' ============================================
Function CreateProfileLShape() As CurveArrArray
''
'' define a simple L-shaped 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.
''
Dim w As Double = Utils.mmToFeet(600) '' those are hard coded for simplicity here. in practice, you may want to find out from the references)
Dim d As Double = Utils.mmToFeet(600)
Dim tw As Double = Utils.mmToFeet(150) '' thickness added for Lab2
Dim td As Double = Utils.mmToFeet(150)
'' define vertices
''
Const nVerts As Integer = 6 '' the number of vertices
Dim pts() As XYZ = {New XYZ(-w / 2, -d / 2, 0), New XYZ(w / 2, -d / 2, 0), New XYZ(w / 2, -d / 2 + td, 0), _
New XYZ(-w / 2 + tw, -d / 2 + td, 0), New XYZ(-w / 2 + tw, d / 2, 0), New XYZ(-w / 2, d / 2, 0), _
New XYZ(-w / 2, -d / 2, 0)} '' the last one is to make the loop simple
'' define a loop. define individual edges and put them in a curveArray
''
Dim pLoop As CurveArray = m_rvtApp.Create.NewCurveArray
Dim lines(nVerts - 1) As Line
For i As Integer = 0 To nVerts - 1
lines(i) = m_rvtApp.Create.NewLineBound(pts(i), pts(i + 1))
pLoop.Append(lines(i))
Next
'' then, put the loop in the curveArrArray as a profile
''
Dim pProfile As CurveArrArray = m_rvtApp.Create.NewCurveArrArray
pProfile.Append(pLoop)
'' if we come here, we have a profile now.
Return pProfile
End Function
'' ============================================
'' (7.1.2) add alignments
'' ============================================
Sub AddAlignments(ByVal pSolid As Extrusion)
AddAlignment_Level(pSolid, New XYZ(0.0, 0.0, 1.0), "Upper Ref Level")
AddAlignment_Level(pSolid, New XYZ(0.0, 0.0, -1.0), "Lower Ref. Level")
AddAlignment_ReferencePlane(pSolid, New XYZ(1.0, 0.0, 0.0), "Right")
AddAlignment_ReferencePlane(pSolid, New XYZ(-1.0, 0.0, 0.0), "Left")
AddAlignment_ReferencePlane(pSolid, New XYZ(0.0, -1.0, 0.0), "Front")
AddAlignment_ReferencePlane(pSolid, New XYZ(0.0, 1.0, 0.0), "Back")
AddAlignment_ReferencePlane(pSolid, New XYZ(1.0, 0.0, 0.0), "OffsetV")
AddAlignment_ReferencePlane(pSolid, New XYZ(0.0, 1.0, 0.0), "OffsetH")
End Sub
'' we want to constrain the upper face of the column to the "Upper Ref Level"
''
Sub AddAlignment_Level(ByVal pSolid As Extrusion, ByVal normal As XYZ, ByVal nameLevel As String)
'' which direction are we looking at?
Dim pView As View = Utils.FindElement(m_rvtDoc, GetType(View), "Front")
'' find the upper ref level. FindElement() is a helper function.
Dim pLevel As Level = Utils.FindElement(m_rvtDoc, GetType(Level), nameLevel)
'' find the face of the box. FindFace() is a helper function.
Dim pFace As PlanarFace = Utils.FindFace(pSolid, normal)
'' create alignments
m_rvtDoc.FamilyCreate.NewAlignment(pView, pLevel.PlaneReference, pFace.Reference)
End Sub
Sub AddAlignment_ReferencePlane(ByVal pSolid As Extrusion, ByVal normal As XYZ, ByVal nameRefPlane As String)
'' get the plan view
'' note: same name maybe used for different view types. either one should work.
Dim pViewPlan As View = Utils.FindElement(m_rvtDoc, GetType(ViewPlan), "Lower Ref. Level")
'' find reference planes
Dim refPlane As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), nameRefPlane)
'' find the face of the solid
Dim pFace As PlanarFace = Utils.FindFace(pSolid, normal, refPlane)
'' create alignments
m_rvtDoc.FamilyCreate.NewAlignment(pViewPlan, refPlane.Reference, pFace.Reference)
End Sub
'' ============================================
'' (7.1.3) set the visibility of the solid not to show in coarse
'' ============================================
Sub SetVisibility(ByVal pSolid As Extrusion)
'' set the visibility of the model not to shown in coarse.
Dim pVis As FamilyElementVisibility = New FamilyElementVisibility(FamilyElementVisibilityType.Model)
pVis.IsShownInCoarse = False
pSolid.SetVisibility(pVis)
End Sub
Sub addMaterials(ByVal pSolid As Extrusion)
'' 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 exercise, 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")
''
Dim pMat As Material = Utils.FindElement(m_rvtDoc, GetType(Material), "Glass") ' hard coded fot simplicity.
If pMat Is Nothing Then
'' no material with the given name.
Return
End If
Dim idMat As ElementId = 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) get a parameter for material finish
''
Dim paramFamilyMaterial As FamilyParameter = m_familyMgr.Parameter("Column Finish")
'' (2b.1) associate material parameter to the family parameter
''
Dim paramSolidMaterial As Parameter = pSolid.Parameter("Material")
m_familyMgr.AssociateElementParameterToFamilyParameter(paramSolidMaterial, paramFamilyMaterial)
'' (2b.2) for our combeniencem, let's add another type with Glass finish
''
AddType("Glass", 600.0, 600.0)
m_familyMgr.Set(paramFamilyMaterial, idMat)
End Sub
#End Region
#Region "Geometry Model Line"
'' ============================================
'' (7.3) add geometry model line
'' ============================================
Sub AddGeometryModelLine()
Dim pModelLine As ModelCurve = CreateModelLine()
m_rvtDoc.Regenerate()
AddAlignments(pModelLine)
SetVisibility(pModelLine)
End Sub
Function CreateModelLine() As ModelCurve
'' we define a simple vertical line at the center.
'' height. hard coding for simplicity. You could calculate from the two reference planes.
Dim h As Double = Utils.mmToFeet(4000.0) '' distance between Lower and Upper Ref Level.
'' define vertices
Dim pt0 As New XYZ(0.0, 0.0, 0.0)
Dim pt1 As New XYZ(0.0, 0.0, h)
'' create a sketch plane
Dim pRefPlane As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Center (Front/Back)")
Dim pSketchPlane As SketchPlane = m_rvtDoc.FamilyCreate.NewSketchPlane(pRefPlane.Plane)
'' create line objects: one model curve representing a column like a vertical stick.
Dim geomLine As Line = m_rvtApp.Create.NewLine(pt0, pt1, True)
Dim pLine As ModelCurve = m_rvtDoc.FamilyCreate.NewModelCurve(geomLine, pSketchPlane)
Return pLine
End Function
'' ============================================
'' add alignments to the model line
'' ============================================
Sub AddAlignments(ByVal pLine As ModelLine)
AddAlignment_Level(pLine, 1, "Upper Ref Level")
AddAlignment_Level(pLine, 0, "Lower Ref. Level")
AddAlignment_ReferencePlane(pLine, "Center (Left/Right)", "Front")
AddAlignment_ReferencePlane(pLine, "Center (Front/Back)", "Right")
End Sub
'' we want to constrain the upper face of the column to the "Upper Ref Level"
''
Sub AddAlignment_Level(ByVal pModelLine As ModelLine, ByVal indexEndPoint As Integer, ByVal nameLevel As String)
'' get the view.
Dim pView As View = Utils.FindElement(m_rvtDoc, GetType(View), "Front")
'' find the upper ref level.
Dim pLevel As Level = Utils.FindElement(m_rvtDoc, GetType(Level), nameLevel)
'' find the face of the box.
Dim pRefPoint As Reference = pModelLine.GeometryCurve.EndPointReference(indexEndPoint)
'' create alignments
m_rvtDoc.FamilyCreate.NewAlignment(pView, pLevel.PlaneReference, pRefPoint)
End Sub
Sub AddAlignment_ReferencePlane(ByVal pModelLine As ModelLine, ByVal nameRefPlane As String, ByVal nameView As String)
'' get the view
'' note: same name maybe used for different view types. either one should work.
Dim pView As View = Utils.FindElement(m_rvtDoc, GetType(View), nameView)
'' find reference planes
Dim refPlane As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), nameRefPlane)
'' create alignments
m_rvtDoc.FamilyCreate.NewAlignment(pView, refPlane.Reference, pModelLine.GeometryCurve.Reference)
End Sub
Sub SetVisibility(ByVal pModelLine As ModelLine)
'' set the visibilities of the model line to coarse only
Dim pVis As FamilyElementVisibility = New FamilyElementVisibility(FamilyElementVisibilityType.Model)
pVis.IsShownInFine = False
pVis.IsShownInMedium = False
pModelLine.SetVisibility(pVis)
End Sub
#End Region
#Region "Geometry Symbolic Line"
'' ============================================
'' (7.3) add geometry symbolic line
'' create simple line objects to be displayed in coarse level
'' ============================================
Sub AddGeometrySymbolicLines()
Dim pSymbolicLines As List(Of SymbolicCurve) = CreateSymbolicLines()
m_rvtDoc.Regenerate()
AddAlignments(pSymbolicLines)
SetVisibility(pSymbolicLines)
End Sub
Function CreateSymbolicLines() As List(Of SymbolicCurve)
''
'' define a simple L-shape detail line object
''
'' 0
'' + h = height
'' | (we also want to draw a vertical line here at point 1)
'' d |
'' +-----+
'' 1 2
'' w
''
'' sizes
Dim w As Double = Utils.mmToFeet(600) '' modified to match reference plane. otherwise, alignment won't work.
Dim d As Double = Utils.mmToFeet(600)
Dim t As Double = Utils.mmToFeet(50) '' slight offset for visbility
'' define vertices
''
Dim pts() As XYZ = {New XYZ(-w / 2 + t, d / 2, 0), _
New XYZ(-w / 2 + t, -d / 2 + t, 0), _
New XYZ(w / 2, -d / 2 + t, 0)}
''
'' (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 a sketch plane there.
'' findElement() is a helper function that find an element of the given type and name.
'' Note: we did the same in creating a profile.
''
Dim pRefPlane As ReferencePlane = Utils.FindElement(m_rvtDoc, GetType(ReferencePlane), "Reference Plane") '' need to know from the template
Dim pSketchPlane As SketchPlane = m_rvtDoc.FamilyCreate.NewSketchPlane(pRefPlane.Plane)
'' (4) create line objects: two symbolic curves on a plan and one model curve representing a column like a vertical stick.
''
Dim geomLine1 As Line = m_rvtApp.Create.NewLine(pts(0), pts(1), True)
Dim geomLine2 As Line = m_rvtApp.Create.NewLine(pts(1), pts(2), True)
Dim pLine1 As SymbolicCurve = m_rvtDoc.FamilyCreate.NewSymbolicCurve(geomLine1, pSketchPlane)
Dim pLine2 As SymbolicCurve = m_rvtDoc.FamilyCreate.NewSymbolicCurve(geomLine2, pSketchPlane)
Dim pLines As New List(Of SymbolicCurve)
pLines.Add(pLine1)
pLines.Add(pLine2)
Return pLines
End Function
Sub AddAlignments(ByVal pSymbolicLines As List(Of SymbolicCurve))
'' To Do. we leave this as an exercise.
'' The idea is the same as Solid and Model Curve.
'' You will need to set the alignments one by one.
End Sub
Sub SetVisibility(ByVal pSymbolicLines As List(Of SymbolicCurve))
'' set the visibilities of two lines to coarse only
Dim pVis As FamilyElementVisibility = New FamilyElementVisibility(FamilyElementVisibilityType.ViewSpecific)
pVis.IsShownInFine = False
pVis.IsShownInMedium = False
pSymbolicLines(0).SetVisibility(pVis)
pSymbolicLines(1).SetVisibility(pVis)
End Sub
#End Region
End Class
#Region "Step By Step Commands"
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_Validate
Implements IExternalCommand
'' member variables
Dim m_rvtUIApp As UIApplication
Dim m_rvtUIDoc As UIDocument
Dim m_rvtApp As Application
Dim m_rvtDoc As Document
Dim m_familyMgr As FamilyManager
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
If Not myCreateColumn.ValidateDocument() Then
Return Result.Failed
End If
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_Reference
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddReferencePlanes()
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_Parameter
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddParameters()
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_Dimension
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddDimensions()
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_Types
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddTypes()
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_Solid
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddGeometrySolid()
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_ModelLine
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddGeometryModelLine()
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumn_SymbolicLine
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
Dim myCreateColumn As New RvtCmd_CreateColumn_v2(commandData)
'myCreateColumn.init(commandData)
myCreateColumn.AddGeometrySymbolicLines()
Return Result.Succeeded
End Function
End Class
#End Region
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class RvtCmd_CreateColumnInstances
Implements IExternalCommand
'' member variables
Dim m_rvtUIApp As UIApplication
Dim m_rvtUIDoc As UIDocument
Dim m_rvtApp As Application
Dim m_rvtDoc As Document
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements Autodesk.Revit.UI.IExternalCommand.Execute
m_rvtUIApp = commandData.Application
m_rvtUIDoc = m_rvtUIApp.ActiveUIDocument
m_rvtApp = m_rvtUIApp.Application
m_rvtDoc = m_rvtUIDoc.Document
AddColumnInstances()
Return Result.Succeeded
End Function
Sub AddColumnInstances()
Dim typeCollector = New FilteredElementCollector(m_rvtDoc)
typeCollector.OfClass(GetType(FamilySymbol))
typeCollector.OfCategory(BuiltInCategory.OST_Columns)
Dim types As IList(Of Element) = typeCollector.ToElements
Dim level1 As Level = Utils.FindElement(m_rvtDoc, GetType(Level), "Level 1")
Dim x As Double = 0.0
'Dim pt As New XYZ(x, 0.0, 0.0)
For Each aType As FamilySymbol In types
Dim pt As New XYZ(x, 0.0, 0.0)
'AddColumnInstance(aType)
Dim aColumn As FamilyInstance = m_rvtDoc.Create.NewFamilyInstance( _
pt, aType, level1, StructuralType.NonStructural)
x += 3.0
Next
End Sub
End Class