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
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
@raber95 @Einar_Raknes @Mostafa_El_Ayoubi Are you looking to crop one view or multiple views:
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
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:
@raber95 And also which Revit version your using?
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)
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
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
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
OK, try this file then: roomViews.dyn (4.5 KB)
(I think I have fixed the codeblock aswell)
Yeah thx man it work
can i controle the offset of boudary with this code
Try to set expandVal to something else than 0 or maybe
expandVal = IN[1] and add another port to the python node
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
It all seems so simple when you read it, until you come write it!
Maybe you can try to follow this example:
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
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 ā¦
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