View Reference Location

View Reference Location

josh.roth.MEI
Enthusiast Enthusiast
2,063 Views
6 Replies
Message 1 of 7

View Reference Location

josh.roth.MEI
Enthusiast
Enthusiast

I am making a simple tool to add a leader annotation symbol to a View Reference, but have run into a bit of an issue. From Revit Lookup, it doesn't appear that the location of a View Reference is defined anywhere in the API. Looking through the API docs as well, I can't find a class for View Reference either, which makes me think that its properties aren't accessible. Am I missing something? Obviously a simple workaround is to just have the user click a start and end point, but ideally I'd like to have the start be defined by the View Reference location.

 

joshrothMEI_0-1641575164708.png

 

 

0 Likes
Accepted solutions (1)
2,064 Views
6 Replies
Replies (6)
Message 2 of 7

jeremy_tammik
Alumni
Alumni

The Revit API supports exactly (and only) two data types for the Location property: LocationPoint and LocationCurve. Some elements have different kinds of location definitions that do not fit into either of these two. In that case, they are not accessible in the API, just as you surmised. Is the view reference location visible in any way in the end user interface? What does it look like in that context? Is there any reason why it might be considered something that does not fit into a point or a curve?

    

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 7

josh.roth.MEI
Enthusiast
Enthusiast

Hi Jeremy, thanks for the response!

 

Here is our view reference family, unselected and selected:

 

joshrothMEI_0-1641611977465.pngjoshrothMEI_1-1641611994828.png

 

At first I thought it would use a location point as a lot of annotation elements do, but as the screenshot in the original post showed, opening the Location in RevitLookup didn't show Location Point or Curve.

 

I know this isn't technically an API question (thought it's API related), but is there something with how the family was created that might influence the Location property?

 

0 Likes
Message 4 of 7

RPTHOMAS108
Mentor
Mentor
Accepted solution

Classes that show up as Element have no specific API functionality beyond element.

 

As the location of the element it not exposed nor is the geometry you have two options:

 

Centre of BoundingBox or Implement IExportContext2D and gather the geometry via that. I would do the latter as it gives you more control.

 

1) Use OnElementBegin2D to check the id against the element you want to look at then pass Skip or Proceed depending on if your id matches

2)  OnCurve will give you details of curves (called for each).

3)  OnText will give you details of text*. Note that this will happen regardless of what you set for RenderNodeAction in  OnElementBegin2D. The best way to avoid calling it for text elements you are not interested in is to do as follows:

 

During OnElementBegin2d store the ElemendId as a variable

During OnElementEnd2d set the ElementId variable to ElementId.InvalidElementId

During OnText exit the sub if variable is not set to Elementid.InvalidElementId

 

*To export text you need to set CustomExporter.Export2DIncludingAnnotationObjects to true

 

I'm finding the best approach is to implement IExportContext2D via a general class and then inherit that. This then avoids having to implement all the members each time and you can build in some filtering similar to above:

 

Imports Autodesk.Revit.DB

Public Class RT_ExportContext2d_Limited
    Implements IExportContext2D

    Private IntDoc As Document = Nothing
    Private FilterEIDs As List(Of ElementId) = Nothing
    Private IntCurrentEID As ElementId = ElementId.InvalidElementId

    Public Property DefaultAction As RenderNodeAction = RenderNodeAction.Proceed

    Public Sub New(D As Document, Optional TargetElementIds As List(Of ElementId) = Nothing)
        FilterEIDs = TargetElementIds
        IntDoc = D
    End Sub

    Public Overridable Function Start() As Boolean Implements IExportContext.Start
        Return True
    End Function
    Public Overridable Sub Finish() Implements IExportContext.Finish
    End Sub
    Public Overridable Function IsCanceled() As Boolean Implements IExportContext.IsCanceled
        Return False
    End Function

#Region "OnBegins"
    Public Overridable Function OnViewBegin(node As ViewNode) As RenderNodeAction Implements IExportContext.OnViewBegin
        Return DefaultAction
    End Function
    Public Function OnElementBegin2D(node As ElementNode) As RenderNodeAction Implements IExportContext2D.OnElementBegin2D
        IntCurrentEID = node.ElementId

        If FilterEIDs IsNot Nothing Then
            If FilterEIDs.Contains(node.ElementId) Then
                Return RenderNodeAction.Proceed
            Else
                Return RenderNodeAction.Skip
            End If
        Else
            Return RenderNodeAction.Proceed
        End If

        OnElementBegin2D_Overridable(node)
    End Function
    Public Overridable Sub OnElementBegin2D_Overridable(node As ElementNode)
    End Sub

    Public Function OnElementBegin(elementId As ElementId) As RenderNodeAction Implements IExportContext.OnElementBegin
        'Never called for 2D export
        Return DefaultAction
    End Function
    Public Function OnInstanceBegin(node As InstanceNode) As RenderNodeAction Implements IExportContext.OnInstanceBegin
        Return DefaultAction
    End Function
    Public Function OnFaceBegin(node As FaceNode) As RenderNodeAction Implements IExportContext.OnFaceBegin
        Return DefaultAction
    End Function
    Public Overridable Function OnFaceEdge2D(node As FaceEdgeNode) As RenderNodeAction Implements IExportContext2D.OnFaceEdge2D
        Return DefaultAction
    End Function

    Public Function OnLinkBegin(node As LinkNode) As RenderNodeAction Implements IExportContext.OnLinkBegin
        Return DefaultAction
    End Function


#End Region

#Region "OnFunctions_Returns"
    Public Overridable Function OnFaceSilhouette2D(node As FaceSilhouetteNode) As RenderNodeAction Implements IExportContext2D.OnFaceSilhouette2D
        Return DefaultAction
    End Function
    Public Overridable Function OnCurve(node As CurveNode) As RenderNodeAction Implements IExportContextBase.OnCurve
        Return DefaultAction
    End Function
    Public Overridable Function OnPolyline(node As PolylineNode) As RenderNodeAction Implements IExportContextBase.OnPolyline
        Return DefaultAction
    End Function
#End Region

#Region "OnEnds_NoReturns"
    Public Sub OnElementEnd2D(node As ElementNode) Implements IExportContext2D.OnElementEnd2D
        IntCurrentEID = Nothing
        OnElementEnd2D_Overridable(node)
    End Sub
    Public Overridable Sub OnElementEnd2D_Overridable(node As ElementNode)
    End Sub

    Public Overridable Sub OnViewEnd(elementId As ElementId) Implements IExportContext.OnViewEnd
    End Sub
    Public Sub OnElementEnd(elementId As ElementId) Implements IExportContext.OnElementEnd
    End Sub

    Public Overridable Sub OnInstanceEnd(node As InstanceNode) Implements IExportContext.OnInstanceEnd
    End Sub
    Public Overridable Sub OnLinkEnd(node As LinkNode) Implements IExportContext.OnLinkEnd
    End Sub
    Public Overridable Sub OnFaceEnd(node As FaceNode) Implements IExportContext.OnFaceEnd
    End Sub
#End Region

#Region "OnSubs_NoReturns"
    Public Overridable Sub OnLineSegment(segment As LineSegment) Implements IExportContextBase.OnLineSegment
    End Sub
    Public Overridable Sub OnPolylineSegments(segments As PolylineSegments) Implements IExportContextBase.OnPolylineSegments
    End Sub
    Public Sub OnText(node As TextNode) Implements IExportContextBase.OnText
        'For tags etc. some calls to this will be during on instance
        'e.g. fixed text within family
        'Some call will be outside OnInstance but before OnElementEnd2D of associated element
        'e.g. tag values (variable text).


        If IntCurrentEID = ElementId.InvalidElementId Then Exit Sub Else
        OnText_Overridable(node)
    End Sub

    Public Overridable Sub OnText_Overridable(node As TextNode)
    End Sub

    Public Overridable Sub OnRPC(node As RPCNode) Implements IExportContext.OnRPC
    End Sub
    Public Overridable Sub OnLight(node As LightNode) Implements IExportContext.OnLight
    End Sub
    Public Overridable Sub OnMaterial(node As MaterialNode) Implements IExportContext.OnMaterial
    End Sub
    Public Overridable Sub OnPolymesh(node As PolymeshTopology) Implements IExportContext.OnPolymesh
    End Sub
#End Region

End Class

 

A lot of the members are not called for the 2D scenario.

Message 5 of 7

josh.roth.MEI
Enthusiast
Enthusiast

Thanks so much! That's a clever implementation of IExportContext2d. Appreciate the help!

0 Likes
Message 6 of 7

RPTHOMAS108
Mentor
Mentor

Thanks, there is just this below correction required to OnText i.e. check the list of filtered contains the current id.

 

 

 Public Sub OnText(node As TextNode) Implements IExportContextBase.OnText
        If FilterEIDs IsNot Nothing Then
            If FilterEIDs.Contains(IntCurrentEID) = False Then
                Exit Sub
            End If
        End If

        OnText_Overridable(node)
End Sub

 

 

The best way to understand the order of the exporter method calls is to log them.

 

0 Likes
Message 7 of 7

jeremy_tammik
Alumni
Alumni

Thank you for sharing this useful example and your insights. Added to the blog for posterity:

 

https://thebuildingcoder.typepad.com/blog/2022/01/detailed-2d-text-and-other-element-geometry.html#4

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes