Create section view of the wall by python

Hi,

I’m working on python scirpt (in Dynamo) which create section view of the wall. Because I have just basic knowledge of python and c#, I used @jeremytammik expierence and just try to translate his code from the website Create Section View Parallel to Wall.
At the first look it works, but the problem starts when the walls have different Base Constraint then level 0. So, for example if bottom of the wall is level +1 and top level +2, the crop region of the section is moved by one level up:

I’ve checked all steps one by one and found nothing unusal. All values from the bounding box look right, have no idea why on upper levels crop region does not match to the wall.
Is there anyone who know where could I look the problem?

My code:

import clr

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitServices')
import RevitServices

from RevitServices.Persistence import DocumentManager
doc =  DocumentManager.Instance.CurrentDBDocument

from RevitServices.Transactions import TransactionManager

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *


wall = UnwrapElement(IN[0])
secTypeName = IN[1]

viewFamilyTypes = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()
vftLst = []
for vf in viewFamilyTypes:
	if vf.LookupParameter("Type Name").AsString() == secTypeName:
		vftLst.append(vf.Id)

# Determine section box
lc = wall.Location
line = lc.Curve

p = line.GetEndPoint(0)
q = line.GetEndPoint(1)
v = q - p

bb = wall.get_BoundingBox(None)
minZ = bb.Min.Z
maxZ = bb.Max.Z

w = v.GetLength()
h = maxZ - minZ
d = wall.WallType.Width
offset = 100 / 304.8

min = XYZ(-0.5*w - offset, minZ - offset, - offset - 0.5*d)
max = XYZ(0.5*w + offset, maxZ + offset, offset + 0.5*d)

midpoint = p + 0.5*v
walldir = v.Normalize()
up = XYZ.BasisZ
viewdir = walldir.CrossProduct(up)

t = Transform.Identity
t.Origin = midpoint
t.BasisX = walldir
t.BasisY = up
t.BasisZ = viewdir

sectionBox = BoundingBoxXYZ()
sectionBox.Transform = t
sectionBox.Min = min
sectionBox.Max = max

TransactionManager.Instance.EnsureInTransaction(doc)

newSection = ViewSection.CreateSection(doc, vftLst[0], sectionBox)

TransactionManager.Instance.TransactionTaskDone()

OUT = newSection

Dynamo script looks easy:
2020-01-01_1726

It looks that was the problem…

Coordinates “Z” always refer to base constraint of the wall, didn’t know about it.

Hi @martin.marek, it’s great that you found where the issue where, but are you able to apply the final solution?
I am doing the same as you, my problem is just that the section view is created far above the element. Any ideas?

Hi @srb,
To see what’s the problem is with your code, please publish it, so maybe I can check what’s wrong.

Not whole script I did in Python, but here is the main part:

import clr

clr.AddReference('RevitServices')
import RevitServices

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import DisplayUnitType, UnitUtils, FilteredElementCollector, ViewFamilyType, BuiltInParameter, XYZ, Transform, BoundingBoxXYZ, ViewSection

from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc =  DocumentManager.Instance.CurrentDBDocument

def units(mmToFeets):
	dut = DisplayUnitType.DUT_MILLIMETERS
	return UnitUtils.ConvertToInternalUnits(mmToFeets, dut)

# wall selection
walls = UnwrapElement(IN[0])

# Check if an input data is a list
if not isinstance(IN[0], list):
    walls = [walls]

# user section type name
sectionTypeName = IN[1]

# user offset (crop region = far clip)
offset = units(IN[2])

# filtering user section type name (id)
viewFamilyTypes = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()

for vf in viewFamilyTypes:
	if vf.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString() == sectionTypeName:
		viewFamilyTypeId = vf.Id

newSections = []
for wall in walls:
    def builtInParam(wallParam):
        return units(float(wall.get_Parameter(wallParam).AsValueString()))

    # Determine section box
    lc = wall.Location
    line = lc.Curve

    p = line.GetEndPoint(0)
    q = line.GetEndPoint(1)
    v = q - p

    bb = wall.get_BoundingBox(None)
    minZ = bb.Min.Z
    maxZ = bb.Max.Z

    w = v.GetLength()
    h = maxZ - minZ
    d = wall.WallType.Width
    wallBaseOffset = builtInParam(BuiltInParameter.WALL_BASE_OFFSET)
    wallUnconnectedHeight = builtInParam(BuiltInParameter.WALL_USER_HEIGHT_PARAM)

    # XYZ(min/max section line length, min/max height of the section box, min/max far clip)
    min = XYZ(-0.5*w - offset, wallBaseOffset - offset, - offset - 0.5*d)
    max = XYZ(0.5*w + offset, wallBaseOffset + wallUnconnectedHeight + offset, offset + 0.5*d)

    # factor for direction of section view
    if p.X > q.X or (p.X == q.X and p.Y < q.Y): fc = 1
    else: fc = -1

    midpoint = p + 0.5*v
    walldir = fc*v.Normalize()
    up = XYZ.BasisZ
    viewdir = walldir.CrossProduct(up)

    t = Transform.Identity
    t.Origin = midpoint
    t.BasisX = walldir
    t.BasisY = up
    t.BasisZ = viewdir

    sectionBox = BoundingBoxXYZ()
    sectionBox.Transform = t
    sectionBox.Min = min # scope box bottom
    sectionBox.Max = max # scope box top

    # Create wall section view
    TransactionManager.Instance.EnsureInTransaction(doc)

    newSection = ViewSection.CreateSection(doc, viewFamilyTypeId, sectionBox)
    newSections.append(newSection)

    TransactionManager.Instance.TransactionTaskDone()

OUT = newSections
2 Likes