Hello
instead of performing a Reverse Dimensions location, you can try to group walls by nearest Curves of Cropbox
here, an example with (IronPython)
Python code
import clr
import sys
import System
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
pf_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86)
sys.path.append(pf_path + '\\IronPython 2.7\\Lib')
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
def nearestWall(wall, line):
"""
Check if the input wall is nearest to the input line (and both are perpendicular)
if the distance is less than half the cropbox --> return True to add to the group
"""
global currZ, midCropX, midCropY
curveWall = wall.Location.Curve
# pull curve on view plane
pta, ptb = (curveWall.GetEndPoint(i) for i in range(2))
curveWall = DB.Line.CreateBound(XYZ(pta.X, pta.Y, currZ), XYZ(ptb.X, ptb.Y, currZ))
#
if abs(curveWall.Direction.DotProduct(l.Direction)) < 0.1: # if wall is perpendicular to the cropbox line
outrefClosest = clr.Reference[IList[ClosestPointsPairBetweenTwoCurves]](List[ClosestPointsPairBetweenTwoCurves]())
curveWall.ComputeClosestPoints(line, True, True, True, outrefClosest) # compute distance between curves
closestPoint = outrefClosest.Value[0]
min_distance = closestPoint.Distance
if line.Direction.IsAlmostEqualTo(XYZ.BasisX):
return min_distance < midCropY
else:
return min_distance < midCropX
return False
inputScale = IN[0]
view = doc.ActiveView
currZ = view.GenLevel.ProjectElevation
cropbox = view.CropBox
midCropX = (cropbox.Max.X - cropbox.Min.X) * 0.5
midCropY = (cropbox.Max.Y - cropbox.Min.Y) * 0.5
#
group_walls = []
region = view.GetCropRegionShapeManager().GetCropShape()
if len(region) > 0:
scale_curveloop = CurveLoop.CreateViaOffset(region[0], inputScale, XYZ(0,0,-1))
for l in scale_curveloop:
walls = FilteredElementCollector(doc, view.Id).OfClass(DB.Wall)\
.WhereElementIsNotElementType()\
.Where(System.Func[DB.Wall, bool](lambda w : nearestWall(w, l)))\
.ToList()
group_walls.append(walls)
OUT = view, [l.ToProtoType() for l in scale_curveloop], group_walls
Note another solution is to find the exterior walls and then group the other walls that are joined to each of these exterior walls
OMG! Thank you so much. I’ve been working on a graph for months.
I tried this on a project where the survey point height is different than the project height and I got null for the walls, I might have to experiment changing the " currZ = view.GenLevel.ProjectElevation " to the cut plane, perhaps pulling all lines to the cut plane would work too.
import clr
import sys
import System
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
pf_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86)
sys.path.append(pf_path + '\\IronPython 2.7\\Lib')
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
def nearestWall(wall, line):
"""
Check if the input wall is nearest to the input line (and both are perpendicular)
if the distance is less than half the cropbox --> return True to add to the group
"""
global currZ, midCropX, midCropY
curveWall = wall.Location.Curve
# pull curve on view plane
pta, ptb = (curveWall.GetEndPoint(i) for i in range(2))
curveWall = DB.Line.CreateBound(XYZ(pta.X, pta.Y, currZ), XYZ(ptb.X, ptb.Y, currZ))
#
if abs(curveWall.Direction.DotProduct(l.Direction)) < 0.1: # if wall is perpendicular to the cropbox line
outrefClosest = clr.Reference[IList[ClosestPointsPairBetweenTwoCurves]](List[ClosestPointsPairBetweenTwoCurves]())
curveWall.ComputeClosestPoints(line, True, True, True, outrefClosest) # compute distance between curves
closestPoint = outrefClosest.Value[0]
min_distance = closestPoint.Distance
if line.Direction.IsAlmostEqualTo(XYZ.BasisX):
return min_distance < midCropY
else:
return min_distance < midCropX
return False
inputScale = IN[0]
view = doc.ActiveView
viewRange = view.GetViewRange()
cutOffset = viewRange.GetOffset(PlanViewPlane.CutPlane)
currZ = view.GenLevel.ProjectElevation + cutOffset
cropbox = view.CropBox
midCropX = (cropbox.Max.X - cropbox.Min.X) * 0.5
midCropY = (cropbox.Max.Y - cropbox.Min.Y) * 0.5
#
group_walls = []
region = view.GetCropRegionShapeManager().GetCropShape()
if len(region) > 0:
scale_curveloop = CurveLoop.CreateViaOffset(region[0], inputScale, XYZ(0,0,-1))
for l in scale_curveloop:
walls = FilteredElementCollector(doc, view.Id).OfClass(DB.Wall)\
.WhereElementIsNotElementType()\
.Where(System.Func[DB.Wall, bool](lambda w : nearestWall(w, l)))\
.ToList()
group_walls.append(walls)
OUT = view, [l.ToProtoType() for l in scale_curveloop], group_walls