Select to view content in your preferred language

The problem I'm having about Split. It's a difficult question. Please help me.

876
3
Jump to solution
08-29-2022 05:24 AM
MikeJane
Occasional Contributor

   Hello. I'm working on a CGA related to 3D building modeling. Things got a little messy when "Align Shapes to Terrain" got involved. For example, there is a building with 4 floors, each floor is 3 meters. Total height 12 m. When I sit this building on the real terrain model with the Align Shape to Terrain command, I naturally need to use the extrude(world.up.Flattop) command to keep it upright on the surface.When I do this, the height of the 12-meter building changes according to the terrain model.

   Now let's get to the main topic. If we just look at the front of the building, for example, the left part of the building, which should have been 12 meters, became 17.2 meters and the right part became 13.2 meters. I have a 4-storey building and the 5th floor cannot be rectangular, since the right corner is 13.2 meters. How can I apply a process so that the top 3 floors are 3 meters and the rest is the ground floor? 

  Using the comp(fe) function I am able to determine the lengths of the object.right and left values. But since CGA works as a tree system, even if I "set" the values via comp(fe), I cannot re-pass this information on shape. I am attaching the sample code and the image I want to make below. I will be grateful if you could help me.

 

@Hidden
attr LeftHeight = 0

@Hidden
attr RightHeight = 0

BuildingFront-->
alignScopeToAxes(world.y)
comp(fe) { object.left : LeftSide | object.right : RightSide | all : NIL}
BuildingFrontNew

LeftSide-->
set(LeftHeight,scope.sx)
report("LeftHeight",LeftHeight)

RightSide-->
set(RightHeight,scope.sx)
report("RightHeight",RightHeight)

With this example code, I cannot continue over BuildingFrontNew because the values I set still appear as zero on BuildingFrontNew.

 

 

 

0 Kudos
2 Solutions

Accepted Solutions
Houskan
Esri Contributor

Hi MikeJane,

Thank you for reaching out.

I believe your problem can be solved with an advanced split pattern:

 

const floorHeight = 3
const nFloors = 3

BuildingFrontNew -->
    split(y) { ~1 : BottomFloor | nFloors*floorHeight : { floorHeight : Floor }* }

Floor --> ...
BottomFloor --> ...

 

This split will create nFloors at the top and 1 BottomFloor from the remaining space.

Notes to your approach: setting an attribute value will only affect the current shape and its successors and can't be passed backwards. If you want to calculate local variables and use them in the current rule, you might want to check out the with keyword.

Let me know if that helps!

Best, houskan

 

 

View solution in original post

MikeJane
Occasional Contributor

@Houskan Thank you again. The solution you suggested developed my thoughts and I reached the solution. I was able to find the right and left values using comp(fe) but I couldn't use it in the rest of the rule. The example I gave is actually a trapezoid. The area of the trapezoid can be calculated with the formula ((a+b)/2)*h. Since scope.sy = 1 edge, scope.sx= h, we can find the short edge. Because the total area is known.

   BuildingFront-->
set(BuildingLeft,scope.sy)
set(BuildingRight,(((geometry.area/scope.sx)*2)-scope.sy))

   This way I was able to detect the short edge without separating it into any component. After I find the measure of the short side, I can correctly determine the number of floors that should really be using your formula.

View solution in original post

0 Kudos
3 Replies
Houskan
Esri Contributor

Hi MikeJane,

Thank you for reaching out.

I believe your problem can be solved with an advanced split pattern:

 

const floorHeight = 3
const nFloors = 3

BuildingFrontNew -->
    split(y) { ~1 : BottomFloor | nFloors*floorHeight : { floorHeight : Floor }* }

Floor --> ...
BottomFloor --> ...

 

This split will create nFloors at the top and 1 BottomFloor from the remaining space.

Notes to your approach: setting an attribute value will only affect the current shape and its successors and can't be passed backwards. If you want to calculate local variables and use them in the current rule, you might want to check out the with keyword.

Let me know if that helps!

Best, houskan

 

 

MikeJane
Occasional Contributor

If I could make a definition using the right and left values of the building, I would get a more accurate result. I cannot use the "with" function because I am using an old version. It did not solve my problem exactly, but it is a solution that will work for me. In some cases "Align Shapes to Terrain" height differences are huge and -1. -2. basements are required. If so, I have to correct with manual values. For standard cases, the code you shared is quite enough. Thank you.

0 Kudos
MikeJane
Occasional Contributor

@Houskan Thank you again. The solution you suggested developed my thoughts and I reached the solution. I was able to find the right and left values using comp(fe) but I couldn't use it in the rest of the rule. The example I gave is actually a trapezoid. The area of the trapezoid can be calculated with the formula ((a+b)/2)*h. Since scope.sy = 1 edge, scope.sx= h, we can find the short edge. Because the total area is known.

   BuildingFront-->
set(BuildingLeft,scope.sy)
set(BuildingRight,(((geometry.area/scope.sx)*2)-scope.sy))

   This way I was able to detect the short edge without separating it into any component. After I find the measure of the short side, I can correctly determine the number of floors that should really be using your formula.

0 Kudos