Sloader Posted March 24, 2022 Share Posted March 24, 2022 (edited) I found my error but can't see how to delete this topic My eventual goal is to build a set of massing models based on polygons with records for height etc. I can't see anything in the help files for the massing model custom object so what I have so far is based on exporting a script from a file with massing models in it. It looks like I should be able to change the fields for number of floors and height etc based on the records once I have got it to build massing models. So far what I have runs and creates massing models but they don't show on screen or export, I can select them and see their properties but there is clearly something very wrong with them. vs.SelectObj("T=GROUP") vs.Ungroup() def gone(h1): vs.ConvertToPolygon(h1, 0) vs.ForEachObject(gone, "T=POLYLINE" ) #loop for all the polylines and convert them to polygons def extrudebuildings(h):#Extrude buidlings based on records vs.CreateCustomObjectPath('Massing Model', h, none) h2 = vs.LNewObj() # get handle to new symbol instance vs.Record(vs.LNewObj(),'Massing Model'); vs.SetRField(vs.LNewObj(),'Massing Model','2Ddisplay','Roof'); vs.SetRField(vs.LNewObj(),'Massing Model','Height','6.096'); vs.SetRField(vs.LNewObj(),'Massing Model','NumFloors','2'); vs.SetRField(vs.LNewObj(),'Massing Model','WallMatl',''); vs.SetRField(vs.LNewObj(),'Massing Model','Custom Roof','False'); vs.SetRField(vs.LNewObj(),'Massing Model','Overhang','0.3048'); vs.SetRField(vs.LNewObj(),'Massing Model','RoofThk','0.3048'); vs.SetRField(vs.LNewObj(),'Massing Model','RoofMatl',''); vs.SetRField(vs.LNewObj(),'Massing Model','DrawPitchedRoof','False'); vs.SetRField(vs.LNewObj(),'Massing Model','EaveStyle','Square'); vs.SetRField(vs.LNewObj(),'Massing Model','RoofPitch','35'); vs.SetRField(vs.LNewObj(),'Massing Model','DrawFloorLevels','True'); vs.SetRField(vs.LNewObj(),'Massing Model','FloorThk','0.3048'); vs.SetRField(vs.LNewObj(),'Massing Model','Use Site Modifiers','False'); vs.SetRField(vs.LNewObj(),'Massing Model','Use Fence','True'); vs.SetRField(vs.LNewObj(),'Massing Model','Fence offset','0.0254'); vs.SetRField(vs.LNewObj(),'Massing Model','Use Shadow','False'); vs.ForEachObject(extrudebuildings, "T=POLY" ) #loop for all the polygons Edited March 24, 2022 by Sloader Quote Link to comment
Pat Stanford Posted March 28, 2022 Share Posted March 28, 2022 Here is a version that kind of works. CreateCustomObjectPath is expecting the handles to two polygons, one for the walls, one for the roof overhang. I did not both to try and figure out which is which. The Massing Model record is automatically part of the object created by the CreateCustomObjectPath command so you don't want to try and attach it with the vs.Record line. In your script you will want to replace all the vs.LNewObj calls in the SetRField functions with h2 so you don't recalculate the object every time. Be careful of the units you are running in. In a document set to Feet and Inches, the constant values in the SetRField functions are interpreted as Inches, so the model is very short. In millimeters it might be even worse. Set the values properly by reading the records attached to your polygons and you should be good. Be careful, the polygons are "incorporated" into the massing model. I don't know if the originals become part of the massing model or that data is used to create a new object inside the massing model, but if a new object is created you may loose you records. Even if you don't lose them, you will lose easy access to them as you will have to enter the Profile Group or the Path group to see the original object and read or change the record. You probably want to make a copy of the original poly with record attached and pass that to the CCOP procedure instead of passing the original. HTH vs.SelectObj("T=GROUP") vs.Ungroup() def gone(h1): vs.ConvertToPolygon(h1, 0) vs.ForEachObject(gone, "T=POLYLINE" ) #loop for all the polylines and convert them to polygons def extrudebuildings(h):#Extrude buidlings based on record pts_h1 = h pts_h2 = vs.OffsetPolyClosed(h, 12, 'False') vs.CreateCustomObjectPath('Massing Model', h, pts_h2) h2 = vs.LNewObj() # get handle to new symbol instance # vs.Record(vs.LNewObj(),'Massing Model'); vs.SetRField(vs.LNewObj(),'Massing Model','2Ddisplay','Roof'); vs.SetRField(vs.LNewObj(),'Massing Model','Height','6.096'); vs.SetRField(vs.LNewObj(),'Massing Model','NumFloors','2'); vs.SetRField(vs.LNewObj(),'Massing Model','WallMatl',''); vs.SetRField(vs.LNewObj(),'Massing Model','Custom Roof','False'); vs.SetRField(vs.LNewObj(),'Massing Model','Overhang','0.3048'); vs.SetRField(vs.LNewObj(),'Massing Model','RoofThk','0.3048'); vs.SetRField(vs.LNewObj(),'Massing Model','RoofMatl',''); vs.SetRField(vs.LNewObj(),'Massing Model','DrawPitchedRoof','False'); vs.SetRField(vs.LNewObj(),'Massing Model','EaveStyle','Square'); vs.SetRField(vs.LNewObj(),'Massing Model','RoofPitch','35'); vs.SetRField(vs.LNewObj(),'Massing Model','DrawFloorLevels','True'); vs.SetRField(vs.LNewObj(),'Massing Model','FloorThk','0.3048'); vs.SetRField(vs.LNewObj(),'Massing Model','Use Site Modifiers','False'); vs.SetRField(vs.LNewObj(),'Massing Model','Use Fence','True'); vs.SetRField(vs.LNewObj(),'Massing Model','Fence offset','0.0254'); vs.SetRField(vs.LNewObj(),'Massing Model','Use Shadow','False'); vs.ForEachObject(extrudebuildings, "T=POLY" ) #loop for all the polygons Quote Link to comment
Sloader Posted March 29, 2022 Author Share Posted March 29, 2022 Script below is cleaned up a bit. It now works with heights from my records and I have got GIS to do some guessing about which lines are too complex for a pitched roof in addition to cleaning up angles near 0 or 90. There will still be many polylines that are too complex so it would be good to suppress the failure messages so I don't have to sit and hold the return key whilst it runs, this would also mean I can relax the inputs on which polylines it tries to add a pitched roof to. storeyht=3 vs.SelectObj("T=GROUP") vs.Ungroup() def gone(h1): vs.ConvertToPolygon(h1, 0) vs.ForEachObject(gone, "T=POLYLINE" ) #loop for all the polylines and convert them to polygons def extrudebuildings(h):#make massing model buidlings based on records RecName=vs.GetName(vs.GetRecord(h,1)) Pitched=vs.GetRField(h, RecName,'PITCHED')#Get pitched boolean from record AOD=vs.GetRField(h, RecName,'TM_mean')#Get AOD height from record TM=eval(vs.GetRField(h, RecName,'TM_mean'))#convert AOD height to number SM=eval(vs.GetRField(h, RecName,'SM_max'))#Get max surface height as number BHT=SM-TM Storeys = ((SM-TM)-2)/storeyht Floors = vs.Round(Storeys) vs.CreateCustomObjectPath('Massing Model', h, None) h2 = vs.LNewObj() # get handle to new massing model vs.SetRField(h2,'Massing Model','2Ddisplay','Roof') vs.SetRField(h2,'Massing Model','Height',BHT) vs.SetRField(h2,'Massing Model','NumFloors',Floors) vs.SetRField(h2,'Massing Model','WallMatl','') vs.SetRField(h2,'Massing Model','Custom Roof','False') vs.SetRField(h2,'Massing Model','Overhang','0.3') vs.SetRField(h2,'Massing Model','RoofThk','0.3') vs.SetRField(h2,'Massing Model','RoofMatl','') vs.SetRField(h2,'Massing Model','DrawPitchedRoof',Pitched) vs.SetRField(h2,'Massing Model','EaveStyle','Square') vs.SetRField(h2,'Massing Model','RoofPitch','35') vs.SetRField(h2,'Massing Model','DrawFloorLevels','True') vs.SetRField(h2,'Massing Model','FloorThk','0.3') vs.SetRField(h2,'Massing Model','Use Site Modifiers','False') vs.SetRField(h2,'Massing Model','Use Fence','True') vs.SetRField(h2,'Massing Model','Fence offset','0.02') vs.SetRField(h2,'Massing Model','Use Shadow','False') vs.Move3DObj(h2, 0, 0, AOD) vs.ForEachObject(extrudebuildings, "T=POLY" ) #loop for all the polygons Quote Link to comment
Pat Stanford Posted March 29, 2022 Share Posted March 29, 2022 I don't think there is a way to suppress the error messages, so your best best is to try and "calculate" which polys are too complex and skip them until you can be present. Or try running the Simplify Polys command from the Modify:Drafting Aids... menu to get something reasonable. Quote Link to comment
DomC Posted March 30, 2022 Share Posted March 30, 2022 On 3/29/2022 at 1:06 PM, Sloader said: it would be good to suppress the failure messages Hello Does it maybe work if you do something like this: try: vs.SetRField(h2,'Massing Model','2Ddisplay','Roof') #your code except: pass #or do someting like taggging the object as "too complexe" or do another function Alternatively you can put something heavy on your enter key, while script is running. 1 1 Quote Link to comment
MullinRJ Posted March 31, 2022 Share Posted March 31, 2022 3 hours ago, DomC said: Alternatively you can put something heavy on your enter key, while script is running @DomC, That's one of the more creative suggestions I've ever heard. 🤣🤣🤣 Raymond Quote Link to comment
Sloader Posted March 31, 2022 Author Share Posted March 31, 2022 The try / except approach looks ideal - When I get time I'll try setting the roof to pitched (True) and false if it fails The something heavy on the key option was explored E7 S7 of the Simpsons which clearly demonstrates some of the drawbacks of this approach 1 Quote Link to comment
Sloader Posted April 5, 2022 Author Share Posted April 5, 2022 @DomC The "Try Except" approach works nicely so I have managed to get VW to do what I want and learnt something new in Python. I am still using the "Pitched" attribute from GIS so I can prevent buildings above or below a certain size from having pitched roofs but I should now be able to relax the restriction on how complex a roof I let it try and make pitched. try: vs.SetRField(h2,'Massing Model','DrawPitchedRoof',Pitched) except: pass 1 Quote Link to comment
Sloader Posted December 13, 2022 Author Share Posted December 13, 2022 My scripts (one to create the massing models and one to set the roofs to pitched) were working but now, presumably due to a service pack change, the pitched roof one no longer results in pitched roofs. As below the roofs are set to be pitched but not drawn pitched, If I paste the massing models into a new drawing VW tries to draw pitched roofs but fails on some and I get the repeating error messages - but now there are more messages so its even more irritating. def trypitched(h):#try making pitched roofs try: vs.SetRField(h,'Massing Model','DrawPitchedRoof',True) except: pass vs.ForEachObject(trypitched, "((PON='Massing Model'))" ) #loop for all the massing models DEMO.vwx Quote Link to comment
Pat Stanford Posted December 13, 2022 Share Posted December 13, 2022 I got it to work by putting a vs.ResetObject(h) after the vs.SetRField, but I still had to respond to a very large number of warning messages. Quote Link to comment
Sloader Posted December 14, 2022 Author Share Posted December 14, 2022 Is the issue that the error isn't a python error but a VW message so the try code always gets executed? I think vs.ResetObject(h) will be usefull Quote Link to comment
Pat Stanford Posted December 14, 2022 Share Posted December 14, 2022 Yes, I believe the issue is that it is a VW problem (pitched roof can't be calculated for some reason) and not a Python error. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.