Select to view content in your preferred language

Using layer.extrusion in a Python script

1661
9
Jump to solution
11-01-2022 07:11 PM
clc
by
Regular Contributor

I am developing a Python script tool to transform a 2D feature class into a multipatch.

Right now, I have to split the script into 2 scripts and manually do the extrusion, because I cannot figure out how to make the extrusion based on a field. I could apply a fixed extrusion by writing:

expression = "5"
lyr.extrusion("BASE_HEIGHT", expression)
But I would like a extrusion based on one of the field of my feature class (and also set the unit as it is possible in the Feature Layer Tab in Pro). I tried (among other combinations):
expression = "!Extrusion_ft! / 3.28084"
lyr.extrusion("BASE_HEIGHT", expression)
The script runs without error but no extrusion...
Thanks for any help.
 
 
Tags (1)
0 Kudos
2 Solutions

Accepted Solutions
by Anonymous User
Not applicable

You can get the value field from a SearchCursor and then use it in your expression.

expression = str(list(set([hgts[0] for hgts in arcpy.da.SearchCursor(fc, 'Field holding hgt')]))[0])

This will grab the first value from the distinct list in case your field has multiple differing values.

View solution in original post

clc
by
Regular Contributor

To conclude on the subject, in case someone encountered the same difficulty:

I managed to finish my script to create a multipatch fc from a 2d polygon fc. I had 2 huge hurdles: the extrusion and the symbology. For the extrusion, I decided to use Python CIM access. I created an extrusion object with my field as expression and I updated the CIM definition of my layer. For the symbology, I applied the workaround already discussed: creating a new layer and using updateConnectionProperties on the new layer.

View solution in original post

0 Kudos
9 Replies
by Anonymous User
Not applicable

You can get the value field from a SearchCursor and then use it in your expression.

expression = str(list(set([hgts[0] for hgts in arcpy.da.SearchCursor(fc, 'Field holding hgt')]))[0])

This will grab the first value from the distinct list in case your field has multiple differing values.

clc
by
Regular Contributor

Thanks a lot, it worked perfectly and I would never have thought of it!

0 Kudos
clc
by
Regular Contributor

Sorry to ask again, but I just realized that it did not work completely for me. The extrusion expression holds only one value (the one of the first feature), so the extrusion is the same for all the features in the layer.

I tried to pass the list of field values (which would match each feature with its field value) but no extrusion happened.  Any  suggestions? Thanks again.

0 Kudos
by Anonymous User
Not applicable

I was wondering about that and was going to add a warning that it would set every feature to that single height... I don't think there is mechanism yet for 'extrude by attribute' programmatically beyond this single value. That polygon image in the docs is a little misleading and I think it was the result of the manual process they listed below... but, the expression parameter makes me curious if one could use an arcade expression there...

"return $feature.HeightField"

I haven't seen anything regarding arcade in arcpy so I'd be surprised if that worked.  Might be worth posting this to the ideas section.

0 Kudos
clc
by
Regular Contributor

Yes the doc is very misleading. You would think that because it is written expression, you could enter more than one value!

I had noticed too that the expression for the feature layer extrusion in Pro offered only Arcade and VBScript. I tried your suggestion for returning an Arcade expression, but no success as you feared it. Thanks again for your help. I think I may end up splitting my layer by extrusion values, do the extrusion for each, run arcpy.Layer3DToFeatureClass_3d on each and combined all the features.

0 Kudos
clc
by
Regular Contributor

To conclude on the subject, in case someone encountered the same difficulty:

I managed to finish my script to create a multipatch fc from a 2d polygon fc. I had 2 huge hurdles: the extrusion and the symbology. For the extrusion, I decided to use Python CIM access. I created an extrusion object with my field as expression and I updated the CIM definition of my layer. For the symbology, I applied the workaround already discussed: creating a new layer and using updateConnectionProperties on the new layer.

0 Kudos
AnonymousUser23
Occasional Contributor

@clc , how did you end up modifying the cim extrusion. I am not finding any python documentation for this. Thanks

0 Kudos
clc
by
Regular Contributor

I used: CreateCIMObjectFromClassName found in the Creating CIM objects section of https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm#

Here is my code:

# Get the layer CIM definition of my layer to be extruded

cim_lay = lay.getDefinition('V2')

# Create a CIM object

cim_obj = arcpy.cim.CreateCIMObjectFromClassName('CIMFeatureExtrusion','V2')

cim_obj.extrusionType = 'Base'

cim_obj.extrusionUnit = {'uwkid': 9002}

cim_obj.extrusionExpressionInfo.expression = '$feature.Extrusion_ft'

# Set the extrusion property 

cim_lay.extrusion = cim_obj

Hope this helps. Catherine

0 Kudos
AnonymousUser23
Occasional Contributor

Thanks Catherine. I also knocked it out. I noticed in Pro 3.1 that my 2D layer would not move to 3D without marking isflattened to false. Just for anyone else trying to do this. 

 

                        cim = l.getDefinition('V3')

                        expressioninfo = arcpy.cim.CreateCIMObjectFromClassName('CIMExpressionInfo', 'V3')
                        expressioninfo.expression = 40
                        expressioninfo.title = "Custom"
                        extrude = arcpy.cim.CreateCIMObjectFromClassName('CIMFeatureExtrusion', 'V3')
                        extrude.extrusionType = "Base"
                        extrude.extrusionExpressionInfo = expressioninfo


                        cim.extrusion = extrude

                        cim.isFlattened = "false"
0 Kudos