Hi everyone,
I’m creating Revit Sections via Python (Revit 2024) using ViewSection_CreateSection, and I’m stuck at a behavior that seems inconsistent between mathematical transform correctness and Revit’s final section orientation.
I would really appreciate insight from anyone who has deep experience with section view transforms.
I want to:
-
Create a section view that looks straight at an inclined bottom surface
-
The section plane is defined by a surface normal
-
A curve lying on that surface should define the horizontal direction on screen
-
Result:
This works only when the surface is horizontal.
As soon as the surface is inclined in 3D, the resulting section view becomes vertical on screen, even though the transform basis seems correct.
-
curve : Dynamo curve lying on the surface
-
surfaceNormal : normal vector of the surface (correct direction)
-
midpoint : center of section
Everything is geometrically correct, but Revit seems to reinterpret or clamp the section orientation, especially when the surface is inclined.
I’m trying to understand whether:
Any insight would be greatly appreciated 
# View normal (look direction)
viewZ = surfaceNormal.Normalize()
# Curve direction (should be horizontal on screen)
viewX = curveDirection.Normalize()
# Up direction
viewY = viewZ.CrossProduct(viewX).Normalize()
# Re-orthogonalize
viewX = viewY.CrossProduct(viewZ).Normalize()
# Build transform
t = Transform.Identity
t.Origin = midpoint
t.BasisX = viewX
t.BasisY = viewY
t.BasisZ = viewZ
Best to post the full Python to reproduce the issue - my gut tells me the method requires some conversion of parameters based on Revit’s expected sequencing, but as we don’t see where you’re calling the method and all the content leading to it we can only guess.
1 Like
Yes, Sir. This is code:
try:
UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
except:
UIunit = Document.GetUnits(doc).GetFormatOptions(SpecTypeId.Length).GetUnitTypeId()
def tolist(input):
if isinstance(input,list):
return input
else:
return [input]
curves = tolist(IN[0])
viewFamilyType = IN[1]
height = UnitUtils.ConvertToInternalUnits(IN[2],UIunit)
offsetFromWall = UnitUtils.ConvertToInternalUnits(IN[3],UIunit)
depth_ = UnitUtils.ConvertToInternalUnits(IN[4],UIunit)
normalZ = IN[5]
if isinstance(normalZ, list):
if len(normalZ) > 0:
normalZ = normalZ[0]
watch = []
def DSCurveToViewSection(c, vft, offset, doc, height, depth):
locC = c.ToRevitType()
sp = locC.GetEndPoint(0)
ep = locC.GetEndPoint(1)
# Direction of curve
v = ep.Subtract(sp)
w = v.GetLength()
lineDir = v.Normalize()
startPoint = c.StartPoint
endPoint = c.EndPoint
lineDir = Vector.ByTwoPoints(endPoint, startPoint).ToXyz().Normalize()
# Midpoint
midpoint = sp.Add(v.Multiply(0.5))
viewZ = normalZ.ToXyz().Normalize()
# -----------------------------
# Transform
# -----------------------------
viewX = lineDir
viewY = viewZ.CrossProduct(viewX).Normalize()
# Re-orthogonalize
viewX = viewY.CrossProduct(viewZ).Normalize()
t = Transform.Identity
t.Origin = midpoint
t.BasisX = viewX
t.BasisY = viewY
t.BasisZ = viewZ
# -----------------------------
# BoundingBox
# -----------------------------
vsBB = BoundingBoxXYZ()
vsBB.Transform = t
vsBB.Min = XYZ(-w / 2, 0, -offset)
vsBB.Max = XYZ( w / 2, height, depth)
# -----------------------------
# Create section
# -----------------------------
section = ViewSection.CreateSection(doc, vft.Id, vsBB)
return section, t
TransactionManager.Instance.EnsureInTransaction(doc)
for cvs in curves:
watch.append(DSCurveToViewSection(cvs, viewFamilyType, offsetFromWall, doc,height,depth_))
TransactionManager.Instance.TransactionTaskDone
OUT = watch