Two attributes changing each other in the Inspector

05-04-2018 04:38 AM
New Contributor II

I am currently working on 3D zoning, specifically with planning law and regulation in Bulgaria. I prepared the regulations in ArcMap for the different zones in the fields for setbacks, max heights, max GFA etc with the respective values. I assigned these fields to attributes in Cityengine and they work well. I also adapted the CGA rule from Tutorial 16: Urban Planning for highlighting the building stories which are over the specified 3D volume.

I face 3 issues for which I looked all over the forum, the help documentation and the tutorials and I can't figure out how to solve them. This is the question for the first one. Here is a link to the second and a link to the third one.

  1. Two attributes changing each other in the Inspector.
    As you see from the CGA code I have three parameters -  floorHeight, floorCount and buildingHeight. I extrude the building based on buildingHeight attribute which = floorHeight * floorCount and when I give the last two new values in the Inspector they affects the buildingHeight. But I want to be able to reverse the process in case the user wants to give value to the buildingHeight, not to the floorCount directly. What I don't achieve up until now is the floorCount to recalculate and show in the Inspector the new value when I manually give new value to buildingHeight. The Viewer shows the changes, but not the Inspector.
    Firstly I tried with :
    buildingHeight = floorHeight * floorCount
    floorCount = buildingHeight / floorHeight
    but CGA wants at least two attributes from the three to be defined. Then I added some cases in the attributes, additional attributes and Rules but I still can't manage to get it both ways - the change of floorCount to affect buildingHeight and the change of buildingHeight to affect floorCount both in the Viewer and the Inspector. The attached screenshots show the scene and the changes of the attributies. 

    FYI - I am an urbanist and GIS user
    with some basic coding understanding but not Python experience and new to Cityengine and CGA rule grammar. Your help will be highly appreciated. 

    attr floorHeight = 3.5
    attr floorCount = 0
    attr buildingHeight = floorHeight*floorCount
    @Order(4) @Hidden
    attr testerH = floorHeight*floorCount
    attr testerF = buildingHeight/floorHeight
    Building -->
         split(y){~floorHeight: Legal}*
    Legal -->
         case inside: color("#000fff")
         else: color("#ffff11")
    Input -->
         case  testerH == testerF : set(buildingHeight, testerH)
         else: set (floorCount, testerF)

0 Kudos
3 Replies
Esri Regular Contributor

Sorry, it is not possible to have attribute A depend on attribute B and at the same time have attribute B depend on attribute A.  The dependency can go only one way.

If you create another attribute to choose whether you use buildingHeight or floorCount to calculate the other, then the user can decide whether the building height should be used or the floor count should be used.  Then, you can have another function (not an attribute) that calculates the desired amount to extrude the building.  However, the values shown in the Inspector won't necessarily be the desired values.  If the user changes the value of an attribute, then the user's value is shown in bold.  The inspector shows only initial values for attributes.  Also, if you set an attribute later in the code, this will not be shown in the inspector.  If you want to see calculated values for buildingHeight and floorCount, then you'll have to report these.

Regular Contributor

I found an old test rule where I tried to get that to work, looks like I made two sets of variables with two sets of display fields and a switch. Needless to say, a rather convoluted solution..

If you want to try to solve it with Python, look up setAttributeSource.

@Group("0 Switcher")
attr Mode = "SubMulti"


@Group("1-1 SubMulti")
attr UA_sub = 5
attr UA_multi = 5

attr A_total = UA_sub*UA_multi
attr A_sub = UA_sub
attr A_multi = UA_multi


@Group("2-1 Total")
attr UB_total = 10
attr UB_multi = 2

attr B_total = UB_total
attr B_sub = UB_total/UB_multi
attr B_multi = UB_multi

 Lot --> 
           case Mode == "SubMulti": extrude(A_total) split(y){A_multi: X.}*
           else: extrude(B_total) split(y){B_total/B_multi: X.}*
New Contributor II

Thank you both for the answers.

I modified the rule that L R showed. It can be used as a workaround but not as an entire solution for situations like that. 

version "2017.1"

@Group("0 Switch Mode")
attr Mode = "A_Floor_to_Height"


@Order (1)
attr A_floorCount_change = 5
@Order (2)
attr A_floorHeight_change = 5
@Order (3)
attr A_totalHeight = A_floorCount_change*A_floorHeight_change


@Order (1)
attr B_floorCount = rint(B_totalHeight_change/B_floorHeight)
@Order (2)
attr B_floorHeight = 5
@Order (3)#@Range(min=1, max=30, stepsize=1)
attr B_totalHeight_change = 10

 Lot --> 
           case Mode == "A_Floor_to_Height": extrude(A_totalHeight) split(y){A_floorHeight_change: X.}*
           else: extrude(B_totalHeight_change) split(y){B_totalHeight_change/B_floorCount: X.}*
0 Kudos