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.
I have posted previously about Section View creation, but here is a nice workflow from Jeremy Graham on Module 2 at the Learn Dynamo website, original post here. Great work and an excellent explanaβ¦
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