TopographySurface as reference

TopographySurface as reference

l.virone
Enthusiast Enthusiast
1,066 Views
11 Replies
Message 1 of 12

TopographySurface as reference

l.virone
Enthusiast
Enthusiast

Hello everyone,

 

I'm trying to create SpotElevation automatically on a TopographySurface but i can't find a way to convert the TopographySurface to a Reference (I'm using this method : doc.Create.NewSpotElevation()).

Is there a way to get the surface as a reference ?

 

Tks,

Virone Lorenzo

0 Likes
1,067 Views
11 Replies
Replies (11)
Message 2 of 12

Omar_Amen
Advocate
Advocate

the "TopographySurface" class inherits from the Element class so I think you can use the Reference class constructor to get the "TopographySurface" object as a Reference object:

public Reference(Element element)

 

0 Likes
Message 3 of 12

l.virone
Enthusiast
Enthusiast

Hi,

 

Tks for your suggestion, but i've tried this and it seems to ignore the reference and not create the SpotElevation :

 

Reference d = new Reference(ts);
SpotDimension e = doc.Create.NewSpotElevation(current_view, d, p, p, p, p, true);

ts = TopographySurface

p = XYZ point

 

0 Likes
Message 4 of 12

l.virone
Enthusiast
Enthusiast

Hi,

 

After further tests, it seems like the constructor for reference works, but I can't create the SpotElevation (see pic).1.JPG

The Reference object is the same as if I had created the SpotElevation manually in Revit but an error occurs while trying to create the SpotElevation using code.

2.JPG

Maybe it is the XYZ object in the SpotElevation creation method ? I'm sure the XY is on the Topography, but i put zero to the Z value ?

 

TopographySurface ts = doc.GetElement(id) as TopographySurface;
XYZ p = new XYZ(x, y, 0);  //x and y are calculated
Reference r = new Reference(ts);

try
{
    SpotDimension e = doc.Create.NewSpotElevation(current_view, r, p, p, p, p, false);
}
catch (Exception e) { TaskDialog.Show("s", 
      "Reference ID: " + r.ElementId.ToString() + "\n" 
      + "Reference Type: " + r.ElementReferenceType + "\n\n\n" 
      + e.ToString()); }

 

Tks

0 Likes
Message 5 of 12

Omar_Amen
Advocate
Advocate

Hi @l.virone
may you call NewSpotElevation() func outside the TryCatch ? to get the original Revit exception error it may help for the error tracing!
I've searched about your problem and I think you have a problem in the point with Z=0 so u have to get the actual Z value on the surface!
I found that question on the forum with almost the same problem, so check this out I hope it will help:
"https://forums.autodesk.com/t5/revit-api-forum/how-to-create-spot-elevation-on-the-topographysurface..."
How to create spot elevation on the TopographySurface? - Autodesk Community - Revit Products

0 Likes
Message 6 of 12

l.virone
Enthusiast
Enthusiast

Hi @Omar_Amen ,

 

I've tested a very simple method alone and outside a try-catch and it didn't work:

 

XYZ ps = new XYZ(0, 0, 0);
SpotDimension es = doc.Create.NewSpotElevation(current_view, new Reference(topography), ps, ps, ps, ps, false);

 

lvirone_0-1630912405974.png

Tks for the link but I had already found this topic and their conclusion was to use an existing SpotElevation and copy/paste it where we need it. It works BUT not if there are subregions (because ID is different, it's another topographysurface), which is the case with all my projects! So basically I need an ElevationSpot on each possible Subregions to make it works, and that's not conceivable...

 

I would like to find a better way to create these ElevationSpots automatically, but it seems very difficult...

 

Tks again and sorry for the delay in response,

Virone Lorenzo

0 Likes
Message 7 of 12

jeremy_tammik
Alumni
Alumni

Sorry for the naive question, but just to make sure: can you create the desired spot elevation on the toposurface manually through the end user interface? If so, maybe you can analyse the result in RevitLookup to find out more about what elements, properties and parameters are involved and how they need to be set up. If not, the API will probably not support this either.

  

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

l.virone
Enthusiast
Enthusiast

Hi @jeremy_tammik ,

 

Do you mean create it manually in Revit ? Yes I can create it manually in all ViewTypes (2D plan, 2D section, 3D,...), in my test I'm using a basic ViewPlan.

 

I've analyzed above in the discussion (using Revit LookUp) the parameters of the point created by hand and I tried to do the same thing using code, I've achieved to get the same objects which have the same IDs and are of the same types, but impossible to create the point...  (Below a new example)

 

This is a point created in Revit manually :

1.JPG

This is the reference property I get using code :

2.JPG

I must specify that  that, it work on objects of others types (with just a correct X-Y, no need to specify Z) but not on TopographySurface objects.

 

Either the API does not support, or I missed something...

Tks,

0 Likes
Message 9 of 12

RPTHOMAS108
Mentor
Mentor

This has come up before, you can't add a spot elevation to a topo but you can copy one onto it from another temporary location using ElementTransformUtils.

 

https://forums.autodesk.com/t5/revit-api-forum/how-to-create-spot-elevation-on-the-topographysurface...

 

If you create a DirectShape at the model origin you can host the temporary spot elevation on the top face of this at 0,0,0 and then copy to the coordinates on the topo. To find such coords you can use ReferenceIntersector. Need to use a surface reference to host the temporary spot elevation.

0 Likes
Message 10 of 12

l.virone
Enthusiast
Enthusiast

Hi @RPTHOMAS108 ,

 

This solution is fine with me if it only needs one existing ElevationSpot, except when I perform the copy and the point is no longer on its original host (like a subregion), then the copy fails.

ElementTransformUtils.CopyElement(doc, existingSpot.Id, point);

 

I may have misunderstood, but it seems that the copied ElevationSpot must already be on the TopographySurface host which we want to copy the point.

 

Tks for your help

0 Likes
Message 11 of 12

RPTHOMAS108
Mentor
Mentor

No it doesn't have to be hosted on another topo surface or pre-existing. It can be created on something that has a surface reference but not a datum element such as level. The below creates a randomised topo and places spot elevations on it. The spot elevations are copied from a single spot elevation hosted on a direct shape which is created for the purpose and deleted at the end.

 

Private Function Obj_210906a(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result

        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim V As View = UIDoc.ActiveGraphicalView

        Dim SpotEl As Element = Nothing
        Dim DS As DirectShape = Nothing
        Dim Topo As Element = Nothing

        Dim Pts As New List(Of XYZ)
        Dim Nnum As Integer = 60
        Dim Mnum As Integer = 40
        Dim RND As New Random


        Dim Range As Integer() = New Integer() {Nnum / 3, Mnum / 3}
        Dim HeightLimits As Double() = New Double(1) {2 / 0.3048, 1 / 0.3048}
        For X = 0 To Range(0) - 1
            For Y = 0 To Range(1) - 1
                Dim H As Double = HeightLimits(0) + (RND.NextDouble() * (HeightLimits(1) - HeightLimits(0)))
                Dim Pt As New XYZ((X * 3) / 0.3048, (Y * 3) / 0.3048, H)

                Pts.Add(Pt)
            Next
        Next

        Using TR0 As New Transaction(IntDoc, "Create random topo")
            If TR0.Start = TransactionStatus.Started Then
                Topo = TopographySurface.Create(IntDoc, Pts)

                V.SetCategoryHidden(New ElementId(BuiltInCategory.OST_Topography), False)

                TR0.Commit()
            End If
        End Using

        Using Tg As New TransactionGroup(IntDoc, "Add topo spot elevation")
            If Tg.Start = TransactionStatus.Started Then

                'Create direct shape to host spot elevation
                Using TR0 As New Transaction(IntDoc, "Spot elev")
                    If TR0.Start = TransactionStatus.Started Then

                        Dim PL As Plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero)
                        Dim SKP As SketchPlane = SketchPlane.Create(IntDoc, PL)

                        DS = DirectShape.CreateElement(IntDoc, New ElementId(BuiltInCategory.OST_GenericModel))
                        Dim A0 As Arc = Arc.Create(PL, 1, 0, Math.PI)
                        Dim A1 As Arc = Arc.Create(PL, 1, Math.PI, 2 * Math.PI)

                        Dim CL As New CurveLoop
                        CL.Append(A0)
                        CL.Append(A1)

                        Dim S As Solid = GeometryCreationUtilities.CreateExtrusionGeometry({CL}.ToList, -XYZ.BasisZ, 0.25)
                        DS.SetShape(New GeometryObject() {S}.ToList)

                        TR0.Commit()
                    End If
                End Using

                'Add spot elevation to top face of newly created direct shape.
                Using TR1 As New Transaction(IntDoc, "Spot elev")
                    If TR1.Start = TransactionStatus.Started Then

                        Dim GeomEl As GeometryElement = DS.Geometry(New Options With {.DetailLevel = ViewDetailLevel.Fine, .ComputeReferences = True})
                        Dim S0 As Solid = GeomEl.Where(Function(x) x.GetType = GetType(Solid)).Cast(Of Solid).Where(Function(x) x.Volume > 0).FirstOrDefault
                        Dim TF As Face = Nothing
                        For i = 0 To S0.Faces.Size - 1
                            Dim F As PlanarFace = TryCast(S0.Faces.Item(i), PlanarFace)
                            If F Is Nothing Then Continue For Else
                            If F.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ) Then
                                TF = F
                            End If
                        Next

                        Dim P As XYZ = XYZ.Zero
                        SpotEl = IntDoc.Create.NewSpotElevation(V, TF.Reference, P, P, P, P, False)

                        TR1.Commit()
                    End If
                End Using

                'Copy onto topo
                Using TR2 As New Transaction(IntDoc, "Spot elev")
                    If TR2.Start = TransactionStatus.Started Then

                        For Each GP As XYZ In Pts
                            Dim Els As List(Of ElementId) = ElementTransformUtils.CopyElement(IntDoc, SpotEl.Id, GP)
                        Next

                        IntDoc.Delete(New ElementId() {DS.Id, SpotEl.Id}.ToList)

                        TR2.Commit()
                    End If
                End Using

                Tg.Assimilate()
            End If
        End Using

        Return Result.Succeeded
    End Function

In a new empty project you should then end up with something like the below:

210907.PNG

0 Likes
Message 12 of 12

l.virone
Enthusiast
Enthusiast

Hi @RPTHOMAS108,

 

Tks it works ! But only on the main topography surface and not on subcategories like subregions.

 

But it seems the problem is a Revit problem :

 --> Manually in Revit, try to copy an ElevationSpot from an element to a sub-region and it will fail, it doesn't matter if you use CTRL+V or if you keep CTRL down and move the element, it will fail because the copied element is not on his host...

 

I think Revit temporary copy the Spot on the main topographySurface, and after the copy process Revit realizes that the host is not right because a sub-regions has a different Id.

 

This is why I would have liked to succeed in directly creating the points on a topographysurface.

And this is why I had believed it wasn't possible to duplicate from another element, the problem isn't the topographySurface but the sub-regions.

 

Someone know a way to bypass this problem ?

 

Thanks for the previous answers!

 

0 Likes