Jump to content

Sloader

Member
  • Posts

    29
  • Joined

  • Last visited

Everything posted by Sloader

  1. We often receive base-mapping as DWGs, one of the supply options has layer names that do not translate into class names correctly. Names like "Road Or Track_Structure , Manmade , Bridge" get translated to something like "$TD_AUDIT_GENERATED_(A9)" which isn't very helpful. AutoCAD and QGIS interpret the names correctly and if I re-export from QGIS as a DXF with the commas replaced the names are interpreted ok.
  2. @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
  3. 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
  4. 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
  5. I am trying to create a site model that has a hole in it. The single crop object does have a hole but the resulting donut is more of a cake. Can it be done without cutting a thin slice out of the donut?
  6. When creating massing models some don't work because of the line geometry, this is fine but can I let VW ignore the issues without me holding down the return key?
  7. 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
  8. Move3DObj does work, many thanks. I see its listed right by Move3D in the Function reference and I still didn't spot it. I also seem to be missing something about how to use the search tool in the procedures dialogue within VW.
  9. I have the script below which places, scales and rotates tree symbols based on a set of 2d Loci created in GIS. I would like to set the Z position of the symbols based on an attribute but can't get it to work. I am trying to use Move3D as below but no joy. def ReplaceRAND1s(h):#Function to replace all loci from imported shapefile with scaled canopy symbols rand=vs.GetRField(h, 'TreePointsForSymbolsRec','RAND_COLOU')#Get the random colour for the canopy loci sym= vs.Concat('Canopy-'+ rand)#Convert the colour code to canopy symbol name ScaleX=vs.GetRField(h, 'TreePointsForSymbolsRec','RAD')#Get scale from loci record ScaleY=vs.GetRField(h, 'TreePointsForSymbolsRec','RAD')#Get scale from loci record ScaleZ=vs.GetRField(h, 'TreePointsForSymbolsRec','rvalue_1')#Get tree height from loci record AOD=vs.GetRField(h, 'TreePointsForSymbolsRec','DTM_1')#Get AOD height from loci record X, Y = vs.GetLocPt(h)#Get location from loci to place symbol randrot= vs.Random()*100 #create a random number to rotate the symbol by vs.Symbol(sym, X, Y, randrot) # place symbol based on loci postion, random colour and random rotation vs.Move3D(0, 0, AOD) h2 = vs.LNewObj() # get handle to new symbol instance vs.SetObjectVariableInt(h2, 101, 3) #Set symbol scaling to asymetric vs.SetObjectVariableReal(h2, 102, ScaleX)#Set X scale vs.SetObjectVariableReal(h2, 103, ScaleY)#Set Y scale vs.SetObjectVariableReal(h2, 104, ScaleZ)#Set Z scale/ height vs.DelObject(h)#clean up loci vs.ForEachObject(ReplaceRAND1s, ("T=LOCUS")) #loop for all the loci in the file TreeLoci.vwx
  10. Yes, I import shapefiles frequently - the importer is flakey but does mean you have records to to use for things like scaling tree symbols or extruding buildings which you don't get with DWG/DXF. vs.ImportDXFDWGFile is a pain as you can't (as far as I know) set the options like units and prefixes from the script. I'll look at adding some feedback. Doing some digging it looks like I might be able to use vs.SetLastDXFImportOpt(selector, value) to sort out my DXF imports
  11. vs.LNewObj() is the Key - no idea how I would have found it, I see its filed under document list handling which now makes sense. Better than doing receptive tasks manually, but VW could be more accessible. I need to spend the time to figure out a proper environment with debugging etc but that looks painful. I can't see a way to import a shapefile which is a shame. Code below seems to work - Takes tree canopy points created by a GIS script from LiDAR def ReplaceRAND1s(h):#Function to replace all loci from imported shapefile with scaled canopy symbols rand=vs.GetRField(h, 'TreePointsForSymbolsRec','RAND_COLOU')#Get the random colour for the canopy loci sym= vs.Concat('Canopy-'+ rand)#Convert the colour code to canopy symbol name ScaleX=vs.GetRField(h, 'TreePointsForSymbolsRec','RAD')#Get scale from loci record ScaleY=vs.GetRField(h, 'TreePointsForSymbolsRec','RAD')#Get scale from loci record ScaleZ=vs.GetRField(h, 'TreePointsForSymbolsRec','rvalue_1')#Get height from loci record X, Y = vs.GetLocPt(h)#Get location from loci to place symbol randrot= vs.Random()*100 #create a random number to rotate the symbol by vs.Symbol(sym, X, Y, randrot) # place symbol based on loci postion, random colour and random rotation h2 = vs.LNewObj() # get handle to new symbol instance vs.SetObjectVariableInt(h2, 101, 3) #Set symbol scaling to asymetric vs.SetObjectVariableReal(h2, 102, ScaleX)#Set X scale vs.SetObjectVariableReal(h2, 103, ScaleY)#Set Y scale vs.SetObjectVariableReal(h2, 104, ScaleZ)#Set Z scale/ height vs.DelObject(h)#clean up loci vs.ForEachObject(ReplaceRAND1s, "T=LOCUS" ) #loop for all the loci in the file
  12. Gotcha! thanks The loop just deletes everything it created. This also explains why I was getting confusing results trying to attach a record to the new symbols. Now I am struggling with attaching the record to the new symbol and transferring data into the values def ReplaceLOCI(h): ScaleX=vs.GetRField(h, 'canopyPNTSRec','RAD') ScaleY=vs.GetRField(h, 'canopyPNTSRec','RAD') ScaleZ=vs.GetRField(h, 'canopyPNTSRec','rvalue_1') X, Y = vs.GetLocPt(h) CreatedSymbol=vs.Symbol('Canopy-1', X, Y, 0) SymbolHandle= vs.GetObject(CreatedSymbol) vs.SetRecord(SymbolHandle,'canopyPNTSRec') vs.SetRField(SymbolHandle, 'canopyPNTSRec','RAD', ScaleZ) vs.DelObject(h) vs.ForEachObject(ReplaceLOCI, "T=Locus" )
  13. The code supplied below doesn't work as if you have the vs.DelObject(h) line in it deletes the newly created symbols as well as the loci, which doesn't make sense to me. When the new symbol is inserted that object seems to take the reference of h. If I run a later line referencing h such as vs.SetRecord(h,'canopyPNTSRec') the function is applied to the new symbol which would be workable if I could set the field values based on my ScaleX, ScaleY and ScaleZ variables def ReplaceRAND1s(h): X, Y = vs.GetLocPt(h) vs.Symbol(newsym1, X, Y, 0) vs.DelObject(h)
  14. After hours of searching I did find SetObjectVariable and verified by looking in a python script exported by VW. The below assumes I have manually converted all loci to symbols so attaching records and transferring the values from loci to new symbols is the next bit to look at. Cheers again def ReplaceRAND1s(h): X, Y = vs.GetLocPt(h) rand=vs.GetRField(h, 'canopyPNTSRec','RAND_COLOU') sym= vs.Concat('Canopy-'+ rand) ScaleX=vs.GetRField(h, 'canopyPNTSRec','RAD') ScaleY=vs.GetRField(h, 'canopyPNTSRec','RAD') ScaleZ=vs.GetRField(h, 'canopyPNTSRec','rvalue_1') symh= vs.Symbol(sym, X, Y, 0) vs.SetObjectVariableInt(symh, 101, 3) vs.SetObjectVariableReal(symh, 102, ScaleX) vs.SetObjectVariableReal(symh, 103, ScaleY) vs.SetObjectVariableReal(symh, 104, ScaleZ) vs.ForEachObject(ReplaceRAND1s, "L='canopyPNTS'" )
  15. Thanks for the help I saw that placing a symbol at each of the loci would be easier but the next step is to scale the symbol based on a field value so I don't want to lose the records. The correct usage of vs.SetHDef(h, vs.GetObject(newsym1)) is useful to know as I could replace all loci with a symbol before I run the script. I have cleaned up the concept a little so I don't need 5 loops as I can pick the right symbol as part of the one function Currently struggling with the scaling as the below doesn't scale the symbol in place and I expect its to do with coordinates def ReplaceRAND1s(h): rand=vs.GetRField(h, 'canopyPNTSRec','RAND_COLOU') sym= vs.Concat('Canopy-'+ rand) vs.SetHDef(h, vs.GetObject(sym)) ptXY = vs.GetSymLoc(h) PtX = ptXY[0] PtY = ptXY[1] vs.HScale2D(h, PtY, PtX, 1, 1, 0) vs.ForEachObject(ReplaceRAND1s, "L='canopyPNTS'" )
  16. I am scripting this because I will be repeating it frequently. I have a set of loci that I need to replace with symbols, a different symbol depending on a record value. My plan, which is a bit rough, was to have a loop for each of the 5 symbols which selects by the attribute 'canopyPNTSRec'.'RAND_COLOU' and then replaces with the appropriate symbol. I have two problems: The only procedure I can find to replace sybols "vs.SetHDef" doesn't apparently work on loci The criteria for selection (('canopyPNTSRec'.'RAND_COLOU'=1)) needs to be re-formated for python but I can't get my head around how newsym1 = 'Canopy-1' def ReplaceRAND1s(h): vs.SetHDef(h, newsym1) vs.ForEachObject(ReplaceRAND1s,("INSYMBOL & INVIEWPORT & ('canopyPNTSRec'.'RAND_COLOU'=1)") )
  17. Cheers Pat! GetLocus3D is much better for what I want, I use the wiki to search for functions but it's easy to miss useful ones. As far as I can tell (and I may be wrong) with Python GetLocus3D returns a tuple rather than individual parameters so I have to extract Z value. I could have used your Vectorscript but learning some Python is hopefully a by product of automating some things in vectorworks. The code below seems to work vs.DSelectAll() MyZ = -100 def Execute(h): TupXYZ = vs.GetLocus3D(h) pZ = TupXYZ[2] if pZ < MyZ: vs.SetSelect(h) vs.ForEachObject(Execute,"T=LOCUS3D") vs.DeleteObjs()
  18. I am importing XYZ survey data and null data points are set to -9999. I need to delete these null data points (Loci with a Z value of -9999) I have managed to get this working for small areas of data using ForEachObject and checking the ZCoordinate but it's too slow for big sections. Any other approaches that might be quicker? nulv = int("-900") def deletenulls(h): HeightValue = vs.ZCoordinate("T=LOCUS3D") if HeightValue < nulv: vs.DelObject(h) vs.ForEachObject(deletenulls,"T=LOCUS3D")
  19. Thanks for trying, I can't see how I would ever have found vs.GetVPGroup would get a handle to the cameras - shame the view doesn't update. I have been trying to use vs.SetViewMatrix with the cameras deleted which does update and I can make incremental changes to the views but I haven't figured out how to make a simple 20degree rotation. I did the rotations manually then checked the parameters and it seems it isn't just the Y Rotation angle that changes. The sequence of parameters below are for a set of cameras rotated 20 degrees - I can't figure out why the offsets (X,Y,Z) change RotX=-90.0RotY=90.0RotZ=0.0X=415369.5 Y=94456.215 Z=105.2183062590922 RotX=90.0RotY=70.0RotZ=180.0X=415341.2491173034 Y=94456.215 Z=66.99958883375739 RotX=90.0RotY=50.00000000000002RotZ=180.0X=415301.6304000912 Y=94456.215 Z=40.748113042233484 RotX=90.0RotY=30.000000000000018RotZ=180.0X=415255.4224503691 Y=94456.215 Z=29.630194295498455
  20. I I would like to duplicate a viewport (linked to a camera) and change the rotation of the camera in the new viewport From the reference I have found VS:GetViewMatrix and VS:SetViewMatrix and managed to get, change and set the rotationXAng parameter but it doesn't change the direction of the camera. Hoffset = 0.117236 Y =0 viewport = vs.FSActLayer() VPparams = vs.GetViewMatrix(viewport) VPparamsList = list (VPparams) Myoffset = VPparamsList[1] MyrotationXAng = VPparamsList[2] MyrotationYAng = VPparamsList[3] MyrotationZAng = VPparamsList[4] MyrotationYAng = 45 VpCylR1 = vs.HDuplicate(viewport,Hoffset,Y) vs.SetViewMatrix(VpCylR1, Myoffset, MyrotationXAng, MyrotationYAng, MyrotationZAng) VpCylR2 =vs.HDuplicate(viewport,Hoffset*2,Y) VpCylR3 =vs.HDuplicate(viewport,Hoffset*3,Y) VpCylL1 =vs.HDuplicate(viewport,0-Hoffset,Y) VpCylL2 =vs.HDuplicate(viewport,0-Hoffset*2,Y) VpCylL2 =vs.HDuplicate(viewport,0-Hoffset*3,Y)
  21. Is this what you are looking for? https://developer.vectorworks.net/index.php/VS:SetObjMaterialHandle FUNCTION SetObjMaterialHandle( VAR objectHandle :HANDLE; materialHandle :HANDLE) : BOOLEAN;
  22. I tried to translate your code and I think I got it to run but it crashed, I think it was stuck in a loop looking for the previous object or something. vs.ForEachObjectInLayer seems much better than While MyObject <> Nil DO for me. Defining the new procedure and passing handles around makes a lot more sense now.
  23. The code below uses "ForEachObjectInLayer" and seems to work. I am a bit fuzzy on how to correctly pass the HANDLE from ForEachObject to SetParent isBatch = True MyLayer = vs.GetLayerByName('LiDARContours') def sendtoconstraints(h): vs.SetParent(h, MyLayer) Contours1m = vs.ImportDXFDWGFile('/LiDARScript/1m3dContours.dxf', isBatch) vs.ForEachObjectInLayer(sendtoconstraints, 0, 0, 0 ) Contours50cm = vs.ImportDXFDWGFile('/LiDARScript/50cm3dContours.dxf', isBatch) vs.ForEachObjectInLayer(sendtoconstraints, 0, 0, 0 ) MyLayer = vs.GetLayerByName('Noise') RoadLQ16 = vs.ImportDXFDWGFile('/LiDARScript/RoadLQ16.dxf', isBatch); vs.ForEachObjectInLayer(sendtoconstraints, 0, 0, 0 ) RailLQ16 = vs.ImportDXFDWGFile('/LiDARScript/RailLQ16.dxf', isBatch); vs.ForEachObjectInLayer(sendtoconstraints, 0, 0, 0 )
  24. I think the issue is that the vs.ImportDXFDWGFile function returns and integer not the objects imported? therefore the HANDLE isn't any use? I have found the code below but I can't make much sense of it # use : assigns a new layer to objects selected by criteria def object_layer_assign_criteria(vSelection_Criteria, vLayer_Destination_Name): vLayer_Destination_Handle = vs.GetLayerByName(vLayer_Destination_Name) if vLayer_Destination_Handle == None: vLayer_Actual_Handle = vs.ActLayer() vLayer_Actual_Name = vs.GetLName(vLayer_Actual_Handle) vs.Layer(vLayer_Destination_Name) vLayer_Destination_Handle = vs.ActLayer() vs.Layer(vLayer_Actual_Name) def object_layer_assign_iterator(vObject_Handle): vs.SetParent(vObject_Handle, vLayer_Destination_Handle) vs.ForEachObject(object_layer_assign_iterator, vSelection_Criteria)
  25. I am trying to automate importing a number of DXF files, I got this working in batch mode based on help here. isBatch = True RoadLQ16 = vs.ImportDXFDWGFile('/Users/some.guy/Desktop/Script/RoadLQ16.dxf', isBatch) This works fine but I want to group the imports into specific layers. I have tried using vs.SetParent and VS:CreateDuplicateObject but I am misunderstanding something about handles (I think) These attempts don't work isBatch = True RoadLQ16 = vs.ImportDXFDWGFile('/Users/some.guy/Desktop/Script/RoadLQ16.dxf', isBatch) vLayer_Destination_Handle = vs.GetLayerByName('Noise') vs.CreateDuplicateObject('RoadLQ16', vLayer_Destination_Handle) isBatch = True RoadLQ16 = vs.ImportDXFDWGFile('/Users/some.guy/Desktop/Script/RoadLQ16.dxf', isBatch) vLayer_Destination_Handle = vs.GetLayerByName('Noise') vs.SetParent('RoadLQ16', vLayer_Destination_Handle)
×
×
  • Create New...