Smooth by Angle - Hide Lines by Angle

Hello

We are currently working as a research team with different modeling programs for an H-BIM model in Rome. The geometries not created in Revit are imported via Rhino.Inside.Revit. In order to avoid manual reworking of the line visibilities for components such as round arches, I am currently writing a Python script for automation. The aim is to hide all lines of the surfaces with a defined angle (e.g. 30°) to each other. An example of the functionality would be Blenders Smooth by angle. Unfortunately, I am a complete beginner in Python and Dynamo. Enclosed is the script that I created with the help of ChatGBT after some thought and several attempts. So far nothing works. I would be very grateful for your help!

The Python Script:

import clr
import math
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *
clr.AddReference(‘RevitServices’)
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference(‘RevitAPI’)
import Autodesk
from Autodesk.Revit.DB import *

Inputs

element = UnwrapElement(IN[0]) # The selected element in Revit
angle_threshold = IN[1] # Angle threshold in degrees
line_style_index = IN[2] # Index of the desired line style

Revit Document

doc = DocumentManager.Instance.CurrentDBDocument

Extract geometry

geometry = element.get_Geometry(Options())
solid = [geo for geo in geometry if isinstance(geo, Autodesk.Revit.DB.Solid)][0]

Extract faces and edges

faces = list(solid.Faces)
edges = list(solid.Edges)

Calculate face normals

normals = [face.ComputeNormal(UV(0.5, 0.5)) for face in faces]

Calculate angles between adjacent faces

angles =
for i in range(len(normals)):
for j in range(i + 1, len(normals)):
angle = normals[i].AngleTo(normals[j])
angles.append(math.degrees(angle))

Filter edges by angle

filtered_edges =
for edge in edges:
edge_faces = [face for face in faces if face.FaceEdges.Contains(edge)]
if len(edge_faces) == 2:
angle = edge_faces[0].ComputeNormal(UV(0.5, 0.5)).AngleTo(edge_faces[1].ComputeNormal(UV(0.5, 0.5)))
angle_deg = math.degrees(angle)
if angle_deg < angle_threshold:
filtered_edges.append(edge)

Load line styles from Revit

line_styles = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines).SubCategories
line_style = [style for i, style in enumerate(line_styles) if i == line_style_index][0]

Start transaction

TransactionManager.Instance.EnsureInTransaction(doc)

Apply line style to filtered edges

for edge in filtered_edges:
model_curve = doc.Create.NewModelCurve(edge.AsCurve(), SketchPlane.Create(doc, Plane.CreateByNormalAndOrigin(normals[0], XYZ.Zero)))
model_curve.LineStyle = line_style

Complete transaction

TransactionManager.Instance.TransactionTaskDone()

Output

OUT = filtered_edges

How would you do this in the user interface? Are you in the working in the family environment or the project environment?

Hi, thank you for your reply. Currently we’re working in the project environment. If I understand you correctly I would do it in the user interface by pressing “LW” and overriding single Edges with an other Line Style (“Hidden Lines”).

The Linework command (LW) isn’t available via the API. You’ll have to change how you bring the geometry into Revit to change the way it displays.

Okay, thanks. Any ideas on how to achieve this? I mean to import it without the unnecessary lines. If we import it as OBJ we aren’t able of overwriting specific edges…

Yes - step back to the RhinoInside portion and build a custom geometry creation tool to build the geometry that displays the way you want it to.

This will not be an easy task; you’re going to have to experiment quite a bit. I’d start by learning how to generate a cuboid with no edges, then a tessellated sphere with no edges, then a cuboid with edges, then a sphere edges, then a cuboid with a sphere taken out of one side, then your actual geometry.

1 Like