mwarnecke
(Marcus)
February 28, 2024, 7:00am
1
Is there a pyRevit utility that can generate elevation/s from selected WALLS?
I understand elevations can be generated for rooms, including obscure shape ones by utilising pyChilizer extension. Ability to generate elevations from selected WALLs would be fantastic for the generation of Precast Wall setout drawings, Window/Curtain Wall elevations, Feature Wall elevations etc…
I’ve spent 2 days trying to develop a dynamo script to undertake this, but have been unsuccessful.
Please help!
I am also aware of this guide, which utilises model lines - however, it does not work with walls, and it fails to consider view crop height to match the wall.
1 Like
@mwarnecke ,
the link is realy well explaned. The python snippets are good to convert look:
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
app = __revit__.Application
# ╔╦╗╔═╗╦╔╗╔
# ║║║╠═╣║║║║
# ╩ ╩╩ ╩╩╝╚╝ MAIN
# ==================================================
import time
start_time = time.time()
# 📝 conditions
toggle = True
# 0️⃣ Variables
elements = []
names = []
lst = []
# 🎯 Get ViewTypes
collector = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()
for i in collector:
if i.ViewFamily == ViewFamily.Elevation:
elements.append(i)
for j in i.Parameters:
if j.Definition.Name == "Type Name":
names.append(j.AsString())
lst.append(elements)
lst.append(names)
print(lst)
# ____________________________________________________________________
# ____________________________________________________________________
# Geometry
points = []
modelPoints = []
cropCurves = []
viewType = []
# ____________________________________________________________________
# 0️⃣ Variables
finalList = []
# 🎯 Get ViewTypes
if toggle == True:
# 🔓 Start
t = Transaction(doc, "Set View to Element")
t.Start()
for ind, point in enumerate(points):
modelMP = modelPoints[ind].ToXyz()
modelMPX = modelMP.X
modelMPY = modelMP.Y
cropLines = cropCurves[ind].ToXyz()
l1 = cropLines[0].ToRevitType()
l2 = cropLines[1].ToRevitType()
l3 = cropLines[2].ToRevitType()
l4 = cropLines[3].ToRevitType()
elevationPT = point.ToXyz()
elptRotate = XYZ(elevationPT.X, elevationPT.Y, elevationPT.Z+100)
ln = Line.CreateBound(elevationPT, elptRotate)
elevationPTY = elevationPT.Y
elevationPTX = elevationPT.X
combY = elevationPTY - modelMPY
combX = elevationPTX - modelMPX
ang = atan(combY, combX)
eleMarker = ElevationMarker.CreateElevationMarker(doc,viewType.Id, elevationPT, 100)
ele = eleMarker.CreateElevation(doc, eleMarker.Id, ln, ang)
crManager = ele.GetCropRegionShapeManager()
newCurveLoop = []
newCurveLoop.Add(l1)
newCurveLoop.Add(l2)
newCurveLoop.Add(l3)
newCurveLoop.Add(l4)
cLoop = CurveLoop.Create(newCurveLoop)
try:
crManager.SetCropRegionShape(cLoop)
finalList.append("Elevation Created")
except:
pass
finalList.append("Missed Elevation")
t.Commit()
# 🔒 Done!
print(finalList)
else:
print(finalList)
end_time = time.time()
print('\n Laufzeit: {} Sekunden'.format(end_time - start_time))
only one thing where i stuck is handling geometry. I hope here can someone help. I think pickObject methode and ISelection filter would work.
so i can use ISelection finally getting lines and points
Who can bridge the gab…
class CustomFilter(ISelectionFilter):
def AllowElement(self, element):
if element.Category.BuiltInCategory == BuiltInCategory.OST_Walls:
return True
# ⭕ ISelectionFilter - Category wall only
custom_filter = CustomFilter()
selected_walls = selection.PickElementsByRectangle(custom_filter, "Select walls ")
wallCurves = [i.Location.Curve for i in selected_walls]
# startpoints
startPoints = []
# endpoints
endPoints = []
for wall in selected_walls:
wallCurve = wall.Location.Curve
startPoints.append(wallCurve.GetEndPoint(0))
endPoints.append(wallCurve.GetEndPoint(1))
result = [i for i in zip(startPoints, endPoints)]
for i in result:
print(i)
for i in wallCurves:
print(i)
Jean-Marc
(Jean-Marc Couffin)
March 3, 2024, 10:24am
3
@ErikFrits showed a code snippet in its latest yt video
1 Like
@mwarnecke ,
i found this from PyRevitMEP
# coding: utf8
__doc__ = """Create sections from selected linear objects (eg. walls)
SHIFT-CLICK to display options"""
__title__ = "CreateSectionFrom"
__author__ = "Cyril Waechter"
__context__ = "selection"
from Autodesk.Revit.DB import (
Document,
Line,
FilteredElementCollector,
ViewFamilyType,
ViewFamily,
Element,
ViewSection,
Transform,
BoundingBoxXYZ,
XYZ,
BuiltInParameter,
)
from Autodesk.Revit.UI import UIDocument
from Autodesk.Revit import Exceptions
from pyrevit import script, forms, revit
uidoc = revit.uidoc # type: UIDocument
doc = revit.doc # type: Document
logger = script.get_logger()
section_types = {
Element.Name.__get__(vt): vt
for vt in FilteredElementCollector(doc).OfClass(ViewFamilyType)
if vt.ViewFamily == ViewFamily.Section
}
section_type = section_types.get(
forms.ask_for_one_item(
section_types.keys(),
section_types.keys()[0],
prompt="Select view section type to use for generated sections",
title="Select section type",
)
)
# Retrieve parameters from config file
_config = script.get_config()
prefix = _config.get_option("prefix", "Mur")
depth_offset = float(_config.get_option("depth_offset", "1"))
height_offset = float(_config.get_option("height_offset", "1"))
width_offset = float(_config.get_option("width_offset", "1"))
sections = []
for element_id in uidoc.Selection.GetElementIds():
element = doc.GetElement(element_id) # type: Element
# Determine if element can be used to create a section
try:
curve = element.Location.Curve
if not isinstance(curve, Line):
raise AttributeError
except AttributeError:
logger.info("{} has no Line Curve to guide section creation".format(element))
continue
# Create a BoundingBoxXYZ oriented parallel to the element
curve_transform = curve.ComputeDerivatives(0.5, True)
origin = curve_transform.Origin
wall_direction = curve_transform.BasisX.Normalize() # type: XYZ
up = XYZ.BasisZ
section_direction = wall_direction.CrossProduct(up)
right = up.CrossProduct(section_direction)
transform = Transform.Identity
transform.Origin = origin
transform.BasisX = wall_direction
transform.BasisY = up
transform.BasisZ = section_direction
section_box = BoundingBoxXYZ()
section_box.Transform = transform
# Try to retrieve element height, width and lenght
try:
el_depth = element.WallType.Width
except AttributeError:
el_depth = 2
el_width = curve.Length
el_bounding_box = element.get_BoundingBox(None)
z_min = el_bounding_box.Min.Z
z_max = el_bounding_box.Max.Z
el_height = z_max - z_min
# Get Wall Offset Params if Element is Wall
try:
base_offset = element.Parameter[BuiltInParameter.WALL_BASE_OFFSET].AsDouble()
except AttributeError:
base_offset = 0
# Set BoundingBoxXYZ's boundaries
section_box.Min = XYZ(
-el_width / 2 - width_offset,
-height_offset + base_offset,
-el_depth / 2 - depth_offset,
)
section_box.Max = XYZ(
el_width / 2 + width_offset,
el_height + height_offset + base_offset,
el_depth / 2 + depth_offset,
)
# Append necessary parameters to create sections in a list
suffix_param = element.get_Parameter(BuiltInParameter.DOOR_NUMBER)
sections.append(
{
"box": section_box,
"suffix": suffix_param.AsString() if suffix_param.HasValue else None,
}
)
with revit.Transaction("Create sections", doc):
fallback_suffix = 1
for section in sections:
section_view = ViewSection.CreateSection(doc, section_type.Id, section["box"])
base_suffix = section["suffix"]
if base_suffix:
try:
section_view.Name = "{} {}".format(prefix, base_suffix)
except Exceptions.ArgumentException:
print(
"Failed to rename view {}. Desired name already exist.".format(
section_view.Name
)
)
else:
while fallback_suffix < 10000:
try:
section_view.Name = "{} {}".format(prefix, fallback_suffix)
except Exceptions.ArgumentException:
fallback_suffix += 1
continue
break
it works great!
1 Like
ARavey
(Andrew)
June 4, 2024, 11:17am
6
Do you know if there’s a way of controlling the orientation of the section with this tool?
The tool works great, but I’d like to be able to specify which side of the wall for example.
Thanks
By a quick look at the code, you would need to change the origin
with the other end of the curve_transform
and invert the wall_direction
vector, so that the transformation matrix applied to the section_box
points to the other side.