How to generate buildings when I have the shapes of roofs?

965
4
09-18-2020 07:18 AM
RegasGeorgiou
New Contributor II

In CityEngine, I have a GIS dataset that includes the shapes of #roofs on their proper altitudes, meaning that the shapes are in the air (they have x, y and z values). I also have the terrain surface and a height for each shape/building (an average height probably).

Any idea of how I can properly generate the buildings using that information?

I have tried extruding downwards but the results are not very good. Not that a number of roof shapes are inclined and I don't want to lose that amount of detail.

I was thinking of projecting the roof shapes to the terrain and then extruding the copied shapes to the original roof shapes. Anyone know if this is somehow possible?

Tags (2)
0 Kudos
4 Replies
CherylLau
Esri Regular Contributor

I would have recommended using comp to get the bottom face of the roof and then extruding downwards the height of the building.  Note that since I assume the bottom face has a normal pointing towards the ground, the extrude is in the positive direction.

const building_height = 10

RoofMass -->
	comp(f) { bottom= RoofFootprint }
	
RoofFootprint -->
	extrude(building_height)‍‍‍‍‍

What doesn't work for you when you extrude downwards?  Does the bottom face not point towards the ground?

It's also possible to extrude upwards in the world.up direction and translate everything down.  (Note: reverseNormals would help to switch the direction of the face normal.)

extrude operation—ArcGIS CityEngine Resources | Documentation 

Alternatively, you could also extract the RoofFootprint, convert the footprints to shapes (Shapes -> Convert Models to Shapes), align them to the terrain (Align Shapes to Terrain icon in toolbar), and extrude upwards the building height.  If the height doesn't match, things get more complicated.  In this case, some tricks like using a python script to write the scope.elevation to an object attribute might be useful.  Or, using minimumDistance with IDs for each roof in the label might be useful.

0 Kudos
RegasGeorgiou
New Contributor II

Thanks a lot for your answer.

My main issue is that I have a number of roofs that are inclined or more complicated for which I have the exact shape of the roof and I wouldn't like to lose this level of detail.

What I have already done is:

1. Copy the all roof shapes (roofs layer) to a new layer (the footprints layer)

2. Make all footprints horizontal (by changing their y-value to 0)

3. Align all footprint shapes to terrain (translate to maximum - offset: 0)

4. Align terrain to footprints layer

So now I have horizontal footprints aligned with terrain (white shapes in screenshot) and horizontal/non horizontal roofs (red shapes) on the exact location above their footprints. What I would like to do is extrude the footprints up to the roofs which means that every corner of a footprint shape should be extruded to a different height. Something that I have no idea how to do.

Alternatively would there be a way to extrude the roof shapes downwards in the world.up direction until they meet the terrain and then somehow make the footprints flat?

0 Kudos
romainjanil
New Contributor III

assuming eaves of each roof shape can be uneven, and that you want to project your roof shapes back to y=0 (which might not be the case if buildings on a terrain, in that conditions you might need to store and use real elevation attributes) you can do that:

version "2020.0"

@Hidden
attr elev = 0
@Hidden
attr rfHeight = 0

RF-->
alignScopeToAxes(world.y)
set(elev,scope.elevation)
set(rfHeight,abs(scope.sy))
extrude(world.y,-250) Vol // 250 is a large enough value assuming this is houses not highrises

Vol-->
print(geometry.height)
print(elev)
split(y){elev+rfHeight:House.|'1:NIL}

Might work better if roof planes are combined per houses btw. The you have to restore your scopes back to a usable position.

Hope this helps.

R

0 Kudos
CherylLau
Esri Regular Contributor

Here's another idea:

Create an attribute terrainElevation and connect it to the terrain's elevation:  Click on the drop down box next to the attribute in the Inspector -> Connect attribute -> Layer attribute -> Terrain Imagery -> elevation.  This sets the attribute value to the terrain's elevation below the scope origin of the initial shape.  The following rule extrudes upwards in the world.up direction and then translates the building down to the terrain.  Note: This will be an approximation only because the attribute can only get the terrain elevation under the initial shape's origin.  The building might not align to the terrain exactly.

attr terrainElevation = 0
attr distToTerrain = 0

RoofMass -->
	set(distToTerrain, scope.elevation - terrainElevation)
	comp(f) { bottom= RoofFootprint }
	
RoofFootprint -->
	extrude(world.up, distToTerrain)
	t(0, -distToTerrain, 0)
0 Kudos