random building placement

Blitz3D Forums/Blitz3D Beginners Area/random building placement

Nexus6(Posted 2013) [#1]
Hi Guys,

Ive been wracking my head over this problem for what seems ages now. My program creates a random city map, a 64x64 grid, each block on the grid is either assigned to be a road segment or building. The system is working pretty well and produces some nice random cities, the problem is, there are too many buildings and i would like to place the buildings only around the perimeter of the roads. At present the buildings all have the same footprint size but im working on a random building generator that will create random building sizes, shapes and footprint sizes. I want to be able to generate a percentage of big, medium and small buildings and to scatter them around the map, but only place them at the road side. Hope this makes sense. If anyone has any ideas, let me know.

Sorry forgot to mention, the map is stored in an array, with verticle roads, horizontal roads, crossroads, building etc all having a code.

Thanks.


RemiD(Posted 2013) [#2]
I have thought about how to generate a random city with random buildings and random roads, and i think that using a grid to position the buildings can be a good appraoch but it is too easy ;)

I think another approach is to first create the roads and then create the buildings around the roads.

After having created the roads, it is possible to determine the empty space between some roads depending on the width and length of the roads. I have not done it yet but i think it could work.

Concerning the procedural modeling of a building, i think that the more sensible approach is to know which possible parts to use and in which place depending on the building kind, and add the parts as if it was builders who were creating the structure. For example, pick randomly a part in a group of parts depending on the kind of the building. (residence, industry, shop, administration, school, etc...)

It does not answer your question but it can give you some ideas about the subject.


_PJ_(Posted 2013) [#3]
The way I see it, your problem is 2-fold.

1) Place buildings ONLY on locations that are adjacent to roads
2) Ensure building footprints do not overlap onto the road or each other

Are all the roads the same width? And are all building footprints square?For now, I will assume they are and this should make things a lot easier.

Const ARRAY_SIZE=64
Const EMPTY=0
Const BUILDING=1
Const ROAD=2
Const ROAD_HORIZONTAL=6
Const ROAD_VERTICAL=10
Const ROAD_CROSSROAD=18

;Dim Array(ARRAY_SIZE,ARRAY_SIZE)
Function PlaceBuilding()
 Local X
 Local Y
 Local Grid 
 Local Placed=False
  While (Not(Placed))
   ;Choose random location
   X=Rand(0,ARRAY_SIZE-1)
   Y=Rand(0,ARRAY_SIZE-1)
   Grid=Array(X,Y) 
   Select (Grid)
    ;Only Select road locations, we can then place buildings at the edge fo these
    Case VERTICAL_ROAD:
     Placed=PlaceAtVertical(X,Y)
    Case HORIZONTAL_ROAD:
     Placed=PlaceAtHorizontal(X,Y)
    Case CROSSROAD:
     Placed=PlaceAtCrossroads(X,Y)
    End Select
  Wend
End Function

Function PlaceAtCrossroads(X,Y)
;Assume Crossroad corners should be available
Local Grid
For PY=Y-1 To Y+1
 For PX=X-1 To X+1
  If ((PX=X) And (PY=Y))
   ;Skip central Crossroad location
   Else
    If (PX>0 and (PX<ARRAY_SIZE))  
     Grid=Array(PX,PY)
     If (Grid=EMPTY)
      PlaceBuilding(PX,PY)
      Return True
     End If
    End If
  End If
 Next
Next
End Function

Function PlaceAtHorizontal(X,Y)
;Assume Y is either side of road
Local Grid
For PY=Y-1 To Y+1
 If(PY=Y))
  ;Skip Horizontal road
 Else
  If (PY>0 and (PY<ARRAY_SIZE))  
   Grid=Array(X,PY)
   If (Grid=EMPTY)
    PlaceBuilding(X,PY)
    Return True
   End If
  End If
 End If
Next
End Function

Function PlaceAtVertical(X,Y)
;Assume X is either side of road
Local Grid
For PX=X-1 To X+1
 If(PX=X))
  ;Skip Vertical road
 Else
  If (PX>0 and (PX<ARRAY_SIZE))  
   Grid=Array(PX,Y)
   If (Grid=EMPTY)
    PlaceBuilding(PX,Y)
    Return True
   End If
  End If
 End If
Next
End Function


Function PlaceBuilding(X,Y)
 Array(X,Y)=BUILDING
End Function


I think one of the 'problems' is that you wanted the buildings placed randomly, otherwise, one could iterate along the length of roads placing buildings at every available space on the way.


*(Posted 2013) [#4]
Wouldnt a box sorting algorithm make it easier for each city block to fit buildings into it, wasted space at the end could just be pavement.


Nexus6(Posted 2013) [#5]
Thanks for the quick reply guys.

@ RemiD, your idea on procedural building creation was exactly what i had in mind.

@ _PJ_ thanks for taking the time to write that code, i must confess i havent had time to have a good look at it yet, but i will do. All roads are the same width and at present all building footprints are square, but that is something that will definitely change.

@ EdzUp[GD] ive read up a bit on box sorting, and it does look ideal for this situation, unfortunately im nowhere near the level of programmer required to code and implement this, but ill look at it again, it might be easier than i think.

Heres a few screenshots of what i have so far -

Random roads


Whole city


Underpass


Underpass


Street Level


Street Level


Roof Level


The buildings are just placeholders for now until i code the procedural building code, but i would really like to get the placement sorted before i do that.

Thanks again guys.


_PJ_(Posted 2013) [#6]
That's all l.,ooking quite impressive already!

I would agree that EdZupp's suggestion for box-sorting would be the way to go I think, but it's beyond me too I fear.

The code I wrote above is pretty basic and can be time consuming as it iterates over and over until it finds a vacant spot - this will take longer and longer as the buildings fill up.
This wont be suitable for different-sized buildings either.

Whilst I htink about it, I reckon that identifying the areas between roads is what's required. These would be either four points or two points and a width/height or perhaps just two points at opposite corners (since all these areas will be rectangular)
Once you have these regions defined (or per region as you go) - then you can place buildings along each of the four sides something like:
Function BuildInRegion(XZ1,XZ2)
;START_X=Lowest X point of region XZ1 XZ2
;START_Z=Lowest Z point of region XZ1 XZ2
;END_X=Highest Z point of region XZ1 XZ2
;END_Z=Highest Z point of region XZ1 XZ2

;First do the Left-Hand sides
For Z=START_Z To END_Z
 X=START_X
 BX=Rand(1,4);Random range of Building sizeX
 BZ=Rand(1,4);Random range of Building sizeZ
  If (Z+BZ>END_Z)
    BZ=END_Z-Z; Unless required to obtain a completely different building   
  End If

  If (BZ);No zero-sized buildings!
   PlaceBuilding(X,Z,BX,BZ)
  End If
  Z=Z+BZ ; Make sure next building placed correctly
Next

;Now the Right-Hand Side
For Z=START_Z To END_Z
 X=END_X
 BX=Rand(1,4);Random range of Building sizeX
 BZ=Rand(1,4);Random range of Building sizeZ
  If (Z+BZ>END_Z)
    BZ=END_Z-Z; Unless required to obtain a completely different building   
  End If

  If (BZ);No zero-sized buildings!
   PlaceBuilding(X-BX,Z,BX,BZ)
  End If
  Z=Z+BZ ; Make sure next building placed correctly
Next

;Next, the North/Upper Edge
For X=START_X To END_X
 Z=START_Z
 BX=Rand(1,4);Random range of Building sizeX
 BZ=Rand(1,4);Random range of Building sizeZ
  If (X+BX>END_X)
    BX=END_X-X; Unless required to obtain a completely different building   
  End If

  If (BX);No zero-sized buildings!
   PlaceBuilding(X,Z,BX,BZ)
  End If
  X=X+BX ; Make sure next building placed correctly
Next

;Finally, the South/Lower Edge
For X=START_X To END_X
 Z=START_Z
 BX=Rand(1,4);Random range of Building sizeX
 BZ=Rand(1,4);Random range of Building sizeZ
  If (X+BX>END_X)
    BX=END_X-X; Unless required to obtain a completely different building   
  End If

  If (BX);No zero-sized buildings!
   PlaceBuilding(X,Z-BZ,BX,BZ)
  End If
  X=X+BX ; Make sure next building placed correctly
Next
End Function

Function PlaceBuilding(X,Z,BX,BZ)
; Places a Building at X,Z with Size BX * BZ
End Function



One potential problem I can forsee already with this method, though, is that each the corners will be processed twice (once whern doing the horiz then when doing the vertical), This might be alleviated if you make START and END smaller in magnitude by 'nX * nZ', and then place buildigns of nX * nZ at each corner etc.
Hope that all makes sense. If I get time, and if you need it, I'll try and get something more concrete for you.


Hardcoal(Posted 2013) [#7]
CAn I be a resident of your city!?