Change the Curve that determines the 2D extents of Grids in Each View

@gerhard.p,
it is very clear to get them. The question is, how to adjust them on crop box.

Amazing work! @c.poupin

Two guestions;

  1. What do i have to change (in the code) to go from feet to mm. Or is it better to convert it with nodes?
  2. Is there something similar for Levels?

you can use this node

image

currently no, :face_with_peeking_eye:

Hi, I know this is an old thread but do you know if this method also works in Revit 2023? I have used this code as a base for my own script and for up to r22 all works, however no such luck for r23. The worst part is that the full code executes without an error warning although no changes are made to the grids.

Did you install IronPython?

1 Like

My understanding is that IronPython is being deprecated in favor of CPython3. As such I’d prefer a long term solution to the problem. BTW I’ve isolated the issue down to the logic branch in the def createDatumLine function.

It seems like there are 2x issues in the new Python version. Issue 1 seems to revolve around how the outInterR = clr.ReferenceIntersectionResultArray call is made. I’ve had to change this to a simpler outInterR = IntersectionResultArray() to create the Result Array. I’m only assuming that this is required as the previous method dosent seem to create the array at all and the change allows the code to proceed to the next step. Secondly, the if result == SetComparisonResult.Overlap: return is not being recognized (I’ve tried extending the logic to pick up all the other possible returns and they all bypass as well) and when looking into it further the array is being returned empty. Any thoughts or knowledge on how the code base is needing to be changed here?

Here an updated code compatible with all python engines

import clr
import sys
pyEngineName = sys.implementation.name 
import System
clr.AddReference('ProtoGeometry')
import Autodesk.DesignScript.Geometry as DSGeo
from Autodesk.DesignScript.Geometry import *

#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)


clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)


def createDatumLine(boundLines, grid):
	gridLine = None
	curveG = grid.Curve#.ToProtoType()
	vectGrid = curveG.Direction
	lstPtToLine = []
	for lineBound in boundLines:
		rayc = DB.Line.CreateUnbound(XYZ(curveG.Origin.X, curveG.Origin.Y, lineBound.GetEndPoint(0).Z) , vectGrid)
		if pyEngineName == "ironpython":
			outInterR = clr.Reference[IntersectionResultArray]()
			result = rayc.Intersect(lineBound, outInterR)
			print(result)
			if result == SetComparisonResult.Overlap:
				interResult = outInterR.Value
				lstPtToLine.append(interResult[0].XYZPoint)
		else:
			dummy_out = IntersectionResultArray()
			result, interResult = rayc.Intersect(lineBound, dummy_out)
			print((result, interResult))
			if result == SetComparisonResult.Overlap:
				lstPtToLine.append(interResult[0].XYZPoint)
		#
	print(lstPtToLine)
	if len(lstPtToLine) == 2:
		gridLine = Autodesk.Revit.DB.Line.CreateBound(lstPtToLine[0], lstPtToLine[1])
	return gridLine
	
def toList(x):
	if isinstance(x, list):
		return x
	elif hasattr(x, "GetType") and x.GetType().GetInterface("IEnumerable") is not None:
		return x
	else :
		return [x]

lstView = toList(UnwrapElement(IN[0]))
offset_number = IN[1]

TransactionManager.Instance.EnsureInTransaction(doc)
#
for activView in lstView:
	activView.CropBoxVisible = True
	doc.Regenerate()
	cropBox = activView.CropBox 
	
	fecMultiGrids_Ids = [id for m in FilteredElementCollector(doc).OfClass(MultiSegmentGrid).WhereElementIsNotElementType() for id in m.GetGridIds()]
	fecGrids = FilteredElementCollector(doc, activView.Id).OfClass(DatumPlane).ToElements()
	cutOffset = fecGrids[0].GetCurvesInView(DatumExtentType.ViewSpecific, activView)[0].GetEndPoint(0).Z
	fecGrids = [x for x in fecGrids if isinstance(x, DB.Grid) and x.Id not in fecMultiGrids_Ids]
	
	outLst = []
	shpManager = activView.GetCropRegionShapeManager()
	boundLines = shpManager.GetCropShape()[0]
	boundLines = CurveLoop.CreateViaOffset(boundLines, offset_number, activView.ViewDirection.Negate())
	
	if activView.ViewDirection.IsAlmostEqualTo(XYZ(0,0,1)):
		# get Current Elevation of boundLines
		currentZ = list(boundLines)[0].GetEndPoint(0).Z
		# transform boundLines CurveLoop
		tf = Transform.CreateTranslation( XYZ(0,0, cutOffset - currentZ))
		boundLines = CurveLoop.CreateViaTransform(boundLines, tf)
		for grid in fecGrids:
			outLst.append(grid.Curve.ToProtoType())
			newGLine = createDatumLine(boundLines, grid)
			if newGLine is not None:
				grid.SetCurveInView(DatumExtentType.ViewSpecific, activView, newGLine)
				
	else:
		for grid in fecGrids:
			outLst.append(grid.Curve.ToProtoType())
			newGLine = createDatumLine(boundLines, grid)
			if newGLine is not None:
				grid.SetCurveInView(DatumExtentType.ViewSpecific, activView, newGLine)

TransactionManager.Instance.TransactionTaskDone()

OUT =  lstView

Revit API, PythonNet, IronPython, .Net Framework, .Net Core, etc… all of this is evolving

it is an illusion to think that a code will never need to be corrected/fixed

3 Likes

You are an absolute star - works like a charm. Also, I totally agree that we will never have a permanent solution, my comment was more aimed at getting a solution that looks forward as you have supplied, rather than patching up the past.

1 Like