How to get the Boundary Profile of Toposurface(Revit 2023)

Hi everyone!

Is there a way to get the boundary edge/profile sketch of the Toposurface in Revit 2023, I’m only able to get the BoundingPoints and I believe they are in the order of create time, so its really hard for me to make it a close loop in the right sequence. I also checked the Polyline in Geometry API but seems like its not a full loop if points are not on the same Z .

Thanks!

This is what I used in the past, you essentially need to get your Bounding Points as you have been doing, sort around the centroid, and for good measure set all the Z values of the points to 0. It gets a bit more complicated if you have ‘holes’ in your topography however.

from pyrevit import revit,DB
import math

doc = revit.doc
boundaryLines=[]
topographyElements = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Topography).ToElements()

def Calculate_Centroid(points):
	total_x = sum([point.X for point in points])
	total_y = sum([point.Y for point in points])
	total_z = sum([point.Z for point in points])
	return DB.XYZ(total_x / len(points), total_y / len(points), total_z / len(points))

def sort_points_clockwise(points):
	centroid = Calculate_Centroid(points)
	sorted_points = sorted(points, key=lambda point: math.atan2(point.Y - centroid.Y, point.X - centroid.X))
	return sorted_points

# GET BOUNDARY POINTS FROM TOPOGRAPHY, SORT CLOCKWISE THEN PROJECT TO Z=0
xyzPoints = topographyElements[0].GetBoundaryPoints()
sortedPoints = sort_points_clockwise(xyzPoints)
projectedPoints = [DB.XYZ(point.X, point.Y, 0) for point in sortedPoints]


# CREATE LINES
for i in range(len(sortedPoints)):
	if i == len(sortedPoints) - 1:  # Special case for the last point
		startPoint = sortedPoints[i]
		endPoint = sortedPoints[0]
	else:
		startPoint = sortedPoints[i]
		endPoint = sortedPoints[i + 1]
	line = DB.Line.CreateBound(startPoint, endPoint)
	boundaryLines.append(line)


# CREATE MODEL LINES AS EXAMPLE
t = DB.Transaction(doc, 'Create Model Lines')
t.Start()
plane = doc.ActiveView.SketchPlane

for line in boundaryLines:
	doc.Create.NewModelCurve(line, plane)
t.Commit()
1 Like

Sorry for the late reply and thanks for the idea.

We thought of this idea but it will not work with odd shapes, another idea we could think of is connect all points and filter out intersection lines and make sure all points are only connected to 2 lines, which will be a lot of calculations.

I was just hoping there’s a easier way than manually create the boundary myself, was hoping there’s an API that allows me to get the boundary/sketch profile.

I’ve done it in a sort of convoluted way by getting the mesh of the toposurface, determining which mesh edges were boundary edges, and then sorting the edges iteratively. It works and doesn’t take too much time to compute, but it certainly isn’t super straight forward. This also enables me to sort edges from holes in the topo pretty easily

I haven’t really look into the mesh, are you filtering out the vertices by boundary points?