Align buildings to streets

786
8
Jump to solution
03-12-2014 03:53 PM
ChrisRybski
New Contributor
Hi!
I'm very new to CityEngine, and I'm trying to write a CGA rule to create a basic house with a detached garage at the rear of the property.  I'm using real world lot and street network data which has been imported (separately) into CE.  Due to this, the lots don't naturally recognize the nearby streets. This is an issue as I would like the houses to be setback from the street, with the garage at the rear of the lot. 

Currently my rule file looks like this:
version "2010.3"  attr height = 10 attr blue = "#0066ff" attr angle = rand(35,45)  Lot-->    setback(10) { street.front : NIL | street.back: Backyard | remainder : Building }                 Building -->  s(10,height,10)  center(x)  extrude(height) comp(f) { side :  Facade | top(0):  Roof }    Backyard -->  setback(2) { street.back: NIL | remainder : Garage }      Garage -->   s(5,5,5)   center(x)   extrude(5) comp(f) { side :  Facade | top(0):  Roof }     Facade -->  color(blue)  Roof --> roofHip(angle) color(blue)


I discovered I am able to select and manually set one lot edge as the Street Front (shapes > Set Street Edges) and this mostly solves the problem. This is less than ideal when trying to apply a script to an entire city though! 

Wondering if someone could provide me with some tips on a more efficient way of achieving my goal?!

Attached are images of what my code produces, as well as what I'm aiming for (although fancy facades are not a priority).
Cheers!
0 Kudos
1 Solution

Accepted Solutions
MatthiasBuehler1
Frequent Contributor II
Hi,

There's a tool for this in CE2013. Shape Menu: Compute First/Street Edges. ( But you need street data ( graph segments ) for this to work, of course ). Otherwise, you need to set them manually.


Ok ?

matt

View solution in original post

0 Kudos
8 Replies
MatthiasBuehler1
Frequent Contributor II
Hi,

There's a tool for this in CE2013. Shape Menu: Compute First/Street Edges. ( But you need street data ( graph segments ) for this to work, of course ). Otherwise, you need to set them manually.


Ok ?

matt
0 Kudos
ChrisRybski
New Contributor
That seems to have done the trick! I didn't realize it was necessary to select the streets layer as well, as I was just trying to calculate the first edge with the Lots alone.

Thanks!
0 Kudos
ChrisRybski
New Contributor
Hi Matthias,

I'm trying to set an option to allow the user to flip the buildings to generate based on the back edge of the Lot (so the 'house" is generated facing the rear of the property).  Could you please help me out with how to do this?
Thanks!
0 Kudos
MatthiasBuehler1
Frequent Contributor II
you mean some sort of switch that places the building either in front or the back of the lot ?

that you can do with a split() in CGA. just make 2 cases and in each case, write the split differently..


ok ?

matt
0 Kudos
ChrisRybski
New Contributor
Hi Matthias,
Thanks for the reply.  I don't want to simply switch the position of the two building, but rather reverse the orientation completely so that the rear of the lot is treating as the First Edge (but only if the user designates it, so I suppose this means it has to be an attribute).  I'm going to try using a pair of Cases to see if that works.
0 Kudos
MatthiasBuehler1
Frequent Contributor II
Hi,

Maybe do a little graphic so I get the picture .. :)

Ok ?

matt
0 Kudos
ChrisRybski
New Contributor
Hi Matthias,

I got the orientation reversal working as I had hoped! I'm not sure if the method I used is the most efficient way, so I've attached an rpk in hopes that you can tell me if anything can be streamlined. EDIT: rpk is apparently too large, so I'm just pasting in the script...


version "2010.3"

######################################################
# Imported Rules
#

#import Plant_Distributor:"rules/Plant_Distributor_with_LumenRT_Models.cga"

######################################################
# Control Attributes (user accessible)
#

##Lot Attributes
@Group("Lot Attributes") 
 #Flip buildings to face rear of the lot. 
 @Group("Lot Attributes") @Order(1) @Range("true","false")
 attr FlipFront = "false"
 #Front and rear setbacks (unit = meters)
 @Group("Lot Attributes") @Order(2) @Range(1, 20)
 attr FrontSetback = 5
 @Group("Lot Attributes") @Order(3) @Range(1, 20)
 attr GarageSetback = 2

##House Attributes:
@Group("House Attributes")
 #House Height:
 @Group("House Attributes") @Order(1) @Range(5,25)
 attr HouseHeight = 5
 #House size (percentage of lot)
 @Group("House Attributes") @Order(2) @Range(0.35,0.7)
 attr HouseLength = rand(0.50,0.55)
 @Group("House Attributes") @Order(3) @Range(0.5,0.95)
 attr HouseWidth = rand(0.7, 0.75)

##Garage Attributes:
@Group("Garage Attributes")
 @Group("Garage Attributes") @Order(1) @Range(5,10)
 attr GarageHeight = 5

## Landscaping:
@Group("Landscaping")
 @Group("Landscaping") @Order(1) @Range(1,5)
 attr NumTrees = 1
 @Group("Landscaping") @Order(2) @Range(10,20)
 attr treesize = rand(15, 20) 

######################################################
# Constants (Landscaping only, hidden from user)
#

const grass = "grass/grass.jpg"
const tree = ("Plants/White_Oak/White_Oak_Model_0.obj")
//make dropdown for tree species selector?


######################################################
# Begin Rule with Lot
#
# Designate a setback from the front and rear of the property.
# Assign the front setback area as the Yard, the back setback as the Backyard
# Area not within the setbacks will be where the House is generated.

@StartRule
Lot-->  
 case FlipFront == "false":
 #Replicated grass across Lot 
 setupProjection(0, scope.xz, 5, 5) 
 projectUV(0)
 texture(grass) Ground. 
 setback(FrontSetback) { front: Yard | back: Backyard | remainder : House}         
   
 else: 
 #Flip the orientation to generate the buildings facing the rear
 mirrorScope(true, false, false)
 setupProjection(0, scope.xz, 5, 5) 
 projectUV(0)
 texture(grass) Ground. 
 setback(FrontSetback) { front: Backyard | back: Yard | remainder : House}



# Import the Plant distributor (2013 Vegegtation rule) and  
# Place a tree of random size in the front yard  
Yard -->
 offset(-2,inside)
 scatter(surface, NumTrees, gaussian) { Veg }
 
 Veg -->
 alignScopeToAxes(y)  s(0,treesize,0) i(tree)


House -->
 case FlipFront == "false":
 s('HouseWidth,HouseHeight,'HouseLength)
 center(xz)
 extrude(world.y, HouseHeight) comp(f) { front: FrontFacade | side : SideFacade | top:  Roof }
 
 else:
 rotateScope(180,0,180)
 s('HouseWidth,HouseHeight,'HouseLength)
 center(xz)
 extrude(world.y, HouseHeight) comp(f) { front: FrontFacade | side : SideFacade | top:  Roof }

Backyard -->
 case FlipFront == "false":
 setback(GarageSetback) { back: NIL | remainder : Garage } 
  
 else:
 setback(GarageSetback) { front: NIL | remainder : Garage } 
 
 
#Construct the garage in the back of the Lot  
Garage -->
 case FlipFront == "false":
 s(7,GarageHeight,5)
 center(xz)
 extrude(world.y, GarageHeight) comp(f) { back : GFront | front : SideFacade | side: Facade | top:  Roof }  

 else:
 rotateScope(180,0,180)
 s(7,GarageHeight,5)
 center(xz)
 extrude(world.y, GarageHeight) comp(f) { back : GFront | side:  Facade | top:  Roof }  




######################################################
# Building Facades
#

const minWallSizeAtCorner = 0.8

FrontFacade -->
 split(y) {4 : MainFloorFront | ~1 : Facade #UpperFloor?
  }
 
 HouseFront -->
  split(x) { minWallSizeAtCorner : Facade | ~1 : HouseFront | minWallSizeAtCorner : Facade }
 
 MainFloorFront -->
  split(x) { 3 : SideFacade | 1.2 : FrontDoorWall | 1 : Facade | ~1 : SideFacade }
 
 FrontDoorWall --> 
  split(y) { 2.2 : FrontDoor | ~1:  Facade }
 
 FrontDoor -->
  extrude(-0.15)
  setupProjection(0, scope.xy, scope.sx, scope.sy)
  projectUV(0)
  texture("textures/door.png")
// End of Front



#####################################################
# The Window mayhem
#
# ~A work in progress~

const Window_Width = 2.2
const SingleWindow = 1.2
const DoubleWindow = 3.4

SideFacade -->
 split(x) { minWallSizeAtCorner: Facade | ~1 : WindowArea | minWallSizeAtCorner: Facade}
 
WindowArea -->
 split(y) { 1 : Facade | 1.75 : WallSplitter | ~1 :  Facade }

# ^above is working




#####################################################
# Split walls into segments for window placement
#


WallSplitter-->
 case scope.sx > (DoubleWindow):
 split(x) {3.4 : WindowFrame2 | ~1: Facade }*
 
 case scope.sx > SingleWindow:
 split(x) { 1.2 : WindowFrame | ~1: Facade }*
 
 else:
 Facade
 
WindowFrame -->
 split(x) { ~1 : Facade | 1.2 : WindowActual | ~1: Facade }

WindowFrame2 -->
 split(x) { 0.5: Facade | 1.2 : WindowActual | 1.2 : WindowActual | 0.5 : Facade }
 
DoubleWindowFrame -->
 split(x) { 0.5: Facade | 1.2 : WindowActual | 1.2 : WindowActual | 0.5 : Facade }
 
# Drops in the window texture
DoubleWindowActual -->
  #extrude(-0.15)
  setupProjection(0, scope.xy, scope.sx, scope.sy)
  projectUV(0)  
  texture("textures/window.png")

# Drops in the window texture
WindowActual -->
  #extrude(-0.15)
  setupProjection(0, scope.xy, scope.sx, scope.sy)
  projectUV(0)
  texture("textures/window.png")



#####################################################
# The Garage!
#
#
GFront --> 
 split(x) {0.67 : Facade | ~1 : GarageDoor | 0.67 : Facade}
 #split(y) {0 : Facade | ~1 : GarageDoor | 0.5 : Facade }
 
GarageDoor -->
 split(y) { ~1 : GarageDoorTx | 1 : Facade }

GarageDoorTx -->
 setupProjection(0, scope.xy, scope.sx, scope.sy)
 projectUV(0)
 texture("textures/DoubleGarage2.png")
 #texture("textures/garage.jpg")



#####################################################
# The main wall Facade
#
# Other textures to be added for Randomization

const FacadeRandTexture = "textures/wall_stones.png"

Facade -->
 setupProjection(0, scope.xy, 10, 10)
 projectUV(0)
 texture(FacadeRandTexture)



######################################################
# Roof Texturing
# Note: 50% chance of Hipped roof, else Gable roof.
#
# Other textures to be added for Randomization

#Roof Angle (house and garage)
const roofangle = rand(33,35)
const RoofRandTexture = "textures/roof.jpg"

Roof --> 
  case p(0.5) :
  roofHip(roofangle, 0.75)
  comp(f) {all: RoofTexture}
  
  else:
  roofGable(30, 0.75)
  comp(f) {top: RoofTexture | side : Facade}
  
 RoofTexture -->
  alignScopeToGeometry(yUp, any, world.lowest)
  setupProjection(0, scope.xz, 6, 6)
  projectUV(0)
  texture(RoofRandTexture)
  



Currently I'm trying to incorporate the CityEngine 2013 vegetation rule into my code, so that I can have some more natural looking trees in the front Yard of the property (for those interested in the veg rule, it can be found here). Unfortunately, it seems the area for tree placement appears to be too small unless I increase the initial setbacks (on the lot size I'm testing at least).  Wondering if you could provide any advice on which part of the vegetation rule could be modified to be more forgiving of small placement areas. 
Thanks!
[ATTACH=CONFIG]33307[/ATTACH]
0 Kudos
MatthiasBuehler1
Frequent Contributor II
looking good ! ;)
0 Kudos