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

263 lines
9.9 KiB
VB.net

#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.
''
#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
Public Class Utils
'' Helper function: find a list of element with the given Class, Name and Category (optional).
''
Public Shared Function FindElements(ByVal rvtDoc As Document, _
ByVal targetType As Type, ByVal targetName As String, _
Optional ByVal targetCategory As BuiltInCategory = Nothing) As IList(Of Element)
'' first, narrow down to the elements of the given type and category
Dim collector = New FilteredElementCollector(rvtDoc).OfClass(targetType)
If Not (targetCategory = Nothing) Then
collector.OfCategory(targetCategory)
End If
'' parse the collection for the given names
'' using LINQ query here.
Dim elems = _
From element In collector _
Where element.Name.Equals(targetName) _
Select element
'' put the result as a list of element for accessibility.
Return elems.ToList()
End Function
'' Helper function: searches elements with given Class, Name and Category (optional),
'' and returns the first in the elements found.
'' This gets handy when trying to find, for example, Level and View
'' e.g., FindElement(m_rvtDoc, GetType(Level), "Level 1")
''
Public Shared Function FindElement(ByVal rvtDoc As Document, _
ByVal targetType As Type, ByVal targetName As String, _
Optional ByVal targetCategory As BuiltInCategory = Nothing) As Element
'' find a list of elements using the overloaded method.
Dim elems As IList(Of Element) = FindElements(rvtDoc, targetType, targetName, targetCategory)
'' return the first one from the result.
If elems.Count > 0 Then
Return elems(0)
End If
Return Nothing
End Function
'' ============================================
'' helper function: given a solid, find a planar face with the given normal (version 2)
'' this is a slightly enhanced version which checks if the face is on the given reference plane.
'' ============================================
'' FindFace2 is not used.
Public Shared Function FindFace2(ByVal aSolid As Extrusion, ByVal normal As XYZ, ByVal refPlane As ReferencePlane) As PlanarFace
'' get the geometry object of the given element
''
Dim op As New Options
op.ComputeReferences = True
Dim geomObjs As GeometryObjectArray = aSolid.Geometry(op).Objects
'' loop through the array and find a face with the given normal
''
For Each geomObj As GeometryObject In geomObjs
If TypeOf geomObj Is Solid Then '' solid is what we are interested in.
Dim pSolid As Solid = geomObj
Dim faces As FaceArray = pSolid.Faces
For Each pFace As Face In faces
Dim pPlanarFace As PlanarFace = pFace
If Not (pPlanarFace Is Nothing) Then
'' check to see if they have same normal
If pPlanarFace.Normal.IsAlmostEqualTo(normal) Then
' '' additionally, we want to check if the face is on the reference plane
' ''
'Dim p0 As XYZ = refPlane.BubbleEnd
'Dim p1 As XYZ = refPlane.FreeEnd
'Dim pCurve As Line = _rvtApp.Create.NewLineBound(p0, p1)
'Dim res As SetComparisonResult = pPlanarFace.Intersect(pCurve)
'If res = SetComparisonResult.Subset Then
' Return (pPlanarFace) '' we found the face
'End If
'' get a point on the face. Any point will do.
Dim pEdge As Edge = pPlanarFace.EdgeLoops.Item(0).Item(0)
Dim pt As XYZ = pEdge.Evaluate(0.0)
Dim res As Boolean = IsPointOnPlane(pt, refPlane)
End If
End If
Next
ElseIf TypeOf geomObj Is GeometryInstance Then
'' will come back later as needed.
ElseIf TypeOf geomObj Is Curve Then
'' will come nack later as needed.
ElseIf TypeOf geomObj Is Mesh Then
'' will come back later as needed.
Else
'' what else do we have?
End If
Next
'' if we come here, we did not find any.
Return Nothing
End Function
Public Shared Function FindFace(ByVal aSolid As Extrusion, ByVal normal As XYZ, Optional ByVal refPlane As ReferencePlane = Nothing) As PlanarFace
'' get the geometry object of the given element
''
Dim op As New Options
op.ComputeReferences = True
Dim geomObjs As GeometryObjectArray = aSolid.Geometry(op).Objects
'' loop through the array and find a face with the given normal
''
For Each geomObj As GeometryObject In geomObjs
If TypeOf geomObj Is Solid Then '' solid is what we are interested in.
Dim pSolid As Solid = geomObj
Dim faces As FaceArray = pSolid.Faces
For Each pFace As Face In faces
Dim pPlanarFace As PlanarFace = pFace
If Not (pPlanarFace Is Nothing) Then
'' check to see if they have same normal
If pPlanarFace.Normal.IsAlmostEqualTo(normal) Then
If refPlane Is Nothing Then
Return pPlanarFace '' we found the face.
Else
'' additionally, we want to check if the face is on the reference plane
'' get a point on the face. Any point will do.
Dim pEdge As Edge = pPlanarFace.EdgeLoops.Item(0).Item(0)
Dim pt As XYZ = pEdge.Evaluate(0.0)
'' is the point on the reference plane?
Dim res As Boolean = IsPointOnPlane(pt, refPlane)
If res Then
Return pPlanarFace '' we found the face
End If
End If
End If
End If
Next
ElseIf TypeOf geomObj Is GeometryInstance Then
'' will come back later as needed.
ElseIf TypeOf geomObj Is Curve Then
'' will come nack later as needed.
ElseIf TypeOf geomObj Is Mesh Then
'' will come back later as needed.
Else
'' what else do we have?
End If
Next
'' if we come here, we did not find any.
Return Nothing
End Function
'' test if a given point lies on the given reference plane.
'' linear equation of plane: ax + by + cz = d
'' the normal is orthogonal to any vector on the plane:
'' n.(p1 - p0) = 0
''
Public Shared Function IsPointOnPlane(ByVal p1 As XYZ, ByVal plane As ReferencePlane)
'' get the plane equation
Dim n As XYZ = plane.Normal
Dim p0 As XYZ = plane.Plane.Origin
Dim dt As Double = n.DotProduct(p1 - p0)
If IsAlmostEqual(dt, 0.0) Then Return True
Return False
End Function
'' compare two double values and judges if it is "almost equal".
'' Note: you may need to adjust the tolorance to fit your needs.
''
Public Shared Function IsAlmostEqual(ByVal val1 As Double, ByVal val2 As Double)
Const tol As Double = 0.0001 '' hard coding the tolerance here.
If Math.Abs(val1 - val2) < tol Then Return True
Return False
End Function
''=============================================
'' Helper Functions
''=============================================
'' convert millimeter to feet
''
Public Shared Function mmToFeet(ByVal mmVal As Double) As Double
Return mmVal / 304.8 '' * 0.00328;
End Function
End Class