Crop Region by curve

revit

#1

Hey everyone
i 'm looking for a solution to have a Crop Region view by curves , someone have any idea to deal with that
Thx


Pick Rectangle Box at View
Copy cropbox from one view to another
#2

Hello raber95,

You can try something like this:

import clr

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

#prepare input
view = UnwrapElement(IN[0])
curves = IN[1]

#Create curveloop
loop = CurveLoop()
for c in curves:
	loop.Append(c.ToRevitType())
	
#Set cropregion in Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
view.CropBoxActive = True
view.GetCropRegionShapeManager().SetCropShape(loop)
TransactionManager.Instance.TransactionTaskDone()
OUT = view


Find Bounding Boxes of Multiple Scope Boxes
Floor Plans by Bounding Box
#3

@raber95 @Einar_Raknes @Mostafa_El_Ayoubi Are you looking to crop one view or multiple views:


#4

thank you for your reply
i’m looking to use room boundary to crop region

@Einar_Raknes i’ve this messssage when i use your script

" File “”, line 26, in
AttributeError: ‘NoneType’ object has no attribute ‘ToRevitType’

@Kulkul yes, i’m looking for thing like this

:slight_smile:


#5

Could you please paste a screenshot of your graph? You have both a view and curves attached to the python node?

See this link for crop regions from room:


#6

@raber95 And also which Revit version your using?


#7

hey there is the screenshot

i’m using revit 2016
thx


#8

I’m sorry but that’s not going to work. The python script can only take one view and crop it to match one set of curves. If you are looking for a view for each room it would be better to create new ones in the script.

If you wrap the python node in a custom node, you can make it work for several views and rooms. (two lists with same length)


#9

hey Einar , thx for your answer
i found a script C# in autodesk site to deal with what i’m looking for :

public void CropAroundRoom(Room room, View view)
{
if (view != null)
{
IList<IList<Autodesk.Revit.DB.BoundarySegment>> segments = room.GetBoundarySegments(new SpatialElementBoundaryOptions());

    if (null != segments)  //the room may not be bound
    {
        foreach (IList<Autodesk.Revit.DB.BoundarySegment> segmentList in segments)
        {
            CurveLoop loop = new CurveLoop();
            foreach (Autodesk.Revit.DB.BoundarySegment boundarySegment in segmentList)
            {
                loop.Append(boundarySegment.GetCurve());
            }

            ViewCropRegionShapeManager vcrShapeMgr = view.GetCropRegionShapeManager();
            vcrShapeMgr.SetCropShape(loop);
            break;  // if more than one set of boundary segments for room, crop around the first one
        }
    }
}

}

any idea to traduce that in python


#10

try this: http://dp-stuff.org/room-plans-non-rectangular-viewports-revit-2014/

#dp Stuff | http://dp-stuff.org | createRoomPlanViews
#this Revit Python Script batch generates Room Plan Views
#before running the script select the rooms to generate Plan Views for
 
import clr
import math
clr.AddReference('RevitAPI') 
clr.AddReference('RevitAPIUI') 
from Autodesk.Revit.DB import * 

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
 
doc = DocumentManager.Instance.CurrentDBDocument
 
collector = FilteredElementCollector(doc).OfClass(clr.GetClrType(ViewFamilyType))
collectorVP = FilteredElementCollector(doc).OfClass(clr.GetClrType(ViewPlan)).WhereElementIsNotElementType()
vtId = 0

expandVal = 0
 
#selected room elements
selEls = UnwrapElement(IN[0])
 
#get elementId of FloorPlan viewFamilyType
for el in collector:
	if el.ViewFamily == ViewFamily.FloorPlan:
		vtId = el.Id
		break
 
TransactionManager.Instance.EnsureInTransaction(doc)
for rm in selEls:
 
	if int(BuiltInCategory.OST_Rooms) == rm.Category.Id.IntegerValue:		
		rmbox = rm.get_BoundingBox(None)
		print rmbox
		minPt = XYZ(rmbox.Min.X-expandVal, rmbox.Min.Y-expandVal, 0)
		maxPt = XYZ(rmbox.Max.X+expandVal, rmbox.Max.Y+expandVal, 0)
		rmbox.Min = minPt
		rmbox.Max = maxPt
		lev = rm.Level
 
		#create a Plan View for the room
		vp = ViewPlan.Create(doc, vtId, lev.Id)
		print vp.Name		
 
		testName = rm.GetParameters('Name')[0].AsString() + ' ' + str(rm.GetParameters('Number')[0].AsString())
 
		for el in collectorVP:
			if el.Name == testName:
				testName = testName + ' (1)'
				break
 
		vp.Name = testName
 
		#2014 custom crop view boundary block
		opt = SpatialElementBoundaryOptions()
		rmBoundarySegListList = rm.GetBoundarySegments(opt)		
		bsList = 0
		crvList = list()
		#get first BoundarySegment Loop
		for bsL in rmBoundarySegListList:
			bsList = bsL
			break
		#create a Curve Loop and make sure they are all lines
		#if a segment is not a line then we tesselate it
		for bs in bsList:
			if bs.GetCurve() is clr.GetClrType(Line):
				crvList.append(bs.GetCurve())
			else:
				#we tesselate the curve
				pts = bs.GetCurve().Tessellate()
				i = -1
				for pt in pts:
					i+=1
					if i < len(pts)-1:
						#create and add linear segments to the future CropBoundary loop
						crvList.append(Line.CreateBound(pts[i], pts[i+1]))	
					myLoop = CurveLoop.Create(crvList)
		#assign CurveLoop to the CropBox of the view
		vp.CropBoxActive = True
		cropManager = vp.GetCropRegionShapeManager()
		if cropManager.IsCropRegionShapeValid(myLoop):					
			cropManager.SetCropShape(myLoop)
		else:
			print 'Not Allowed to manage Crop for ' + vp.Name + ' :-(' 
			vp.CropBox = rmbox
		#END 2014 custom crop view boundary block
		#you can fancy this up by assigning a particular view template etc
 
TransactionManager.Instance.TransactionTaskDone()

OUT = 0

Python Nodes Basics
#11

Thank you for your efforts , i have this message when i paste the code in python node :

Avertissement:IronPythonEvaluator.EvaluateIronPythonScript l’opération a échoué.
File “”, line 31
if el.ViewFamily == ViewFamily.FloorPlan:

^

SyntaxError: expected an indented block


#12

OK, try this file then: roomViews.dyn (4.5 KB)

(I think I have fixed the codeblock aswell)


#13

Yeah thx man it work :slight_smile:
can i controle the offset of boudary with this code


#14

Try to set expandVal to something else than 0 or maybe
expandVal = IN[1] and add another port to the python node


#15

Hi @Einar_Raknes

I am trying to modify this script to work with multiple views and multiple curves. I’ve spotted your comment that if this was wrapped in a custom node, this would be possible. I’ve been learning a bit of Python (mostly on a high level) not really dynamo specific. - but hopefully not too far off.

I’ve had a stab at modifying the python script to place everything within a for loop, but I can’t get it quite worked out. Could you give me a bit of advice, or if it would be easier wrapped in a custom node, what that would entail.

My fumblings are shown below:

import clr

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

#prepare input
views = UnwrapElement(IN[0])
curves = IN[1]
curvelist =[]
viewlist = []

#Create curveloop
TransactionManager.Instance.EnsureInTransaction(doc)

for curve,view in curves, views:
	loop = CurveLoop()
	for c in curves:
		loop.Append(c)

#Set cropregion in Transaction

	view.CropBoxActive = True
	view.GetCropRegionShapeManager().SetCropRegionShape(loop)
	viewlist.append(view)
	TransactionManager.Instance.TransactionTaskDone()

OUT = view

I’m getting the error as shown …

this came out of the discussion Find Bounding Boxes of Multiple Scope Boxes

Cheers


#16

It all seems so simple when you read it, until you come write it!


#17

Maybe you can try to follow this example:


#18

CRACKED IT ! My first successfully working Python API node.

I have modified the code and it working! @Einar_Raknes

I was walking home and had a light bulb-esque moment.

I transposed the graph, to produce a combined list with both the view and curve per item, then iterated through the originl script per item.

I was thinking this method could apply to any definition which will work only once, but for which you want to iterate multiple times.

Anyway enough chat, here’s the code…

import clr

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

#prepare input
combinedlist = IN[0]
outputlist = []

for i in combinedlist:
	view = UnwrapElement(i[0])
	curves = i[1]


	#Create curveloop
	loop = CurveLoop()
	for c in curves:
		loop.Append(c.ToRevitType())

	#Set cropregion in Transaction
	TransactionManager.Instance.EnsureInTransaction(doc)
	view.CropBoxActive = True
	view.GetCropRegionShapeManager().SetCropShape(loop)
outputlist.append(view)
TransactionManager.Instance.TransactionTaskDone()


OUT = outputlist

#19

However it hasn’t solved the main problem. I am struggling to place views on sheets, i was trying to find n alternate way to crop the views to see if they would pack onto the sheets, but alas I have the same error.

I have noticed this has also been recently commented on in the following thread.

Previously i had the same error, it seemed the view was too large for the sheet. However now, even the numbers are smaller so i’m a bit confused …


#20

Nice that you got it to work!

If you wanted to combine the lists in python you could have used zip()

for view,curves in zip(views,curvelist):

	#Create curveloop
	loop = CurveLoop()
	for c in curves:
		loop.Append(c.ToRevitType())

	#Set cropregion in Transaction
	TransactionManager.Instance.EnsureInTransaction(doc)
	view.CropBoxActive = True
	view.GetCropRegionShapeManager().SetCropShape(loop)
outputlist.append(view)
TransactionManager.Instance.TransactionTaskDone()


OUT = outputlist

Python Nodes Basics