How can i Get block center value

587
4
Jump to solution
11-10-2022 01:52 AM
JeoCho
by
New Contributor II

I have  many blocks

In each blocks , i would like to get center corrdinate x  z

How can i that ?

0 Kudos
1 Solution

Accepted Solutions
CherylLau
Esri Regular Contributor

I assume you are working with dynamic shapes, meaning blocks and lots that are automatically created by CityEngine in a street network.  I assume you want CityEngine to automatically divide the blocks into lots.  In this case, unfortunately, I can't think of a way in cga for each Lot to know the centroid or any information about the block it belongs to.

 

The only way I can think of is to start with the dynamically created blocks, do not subdivide them automatically (select blocks, set Subdivision Type = "No Subdivision" in Inspector), and subdivide them in your cga rule instead.  Here is some code that calculates the block's centroid, places an invisible cube at the centroid, and subdivides the block into lots.  Each lot queries its minimumDistance to the invisible cube at the centroid.  If you don't need the exact centroid, it would be simpler to skip the centroid calculation and center the invisible cube in the block's scope instead.  You can replace the SubdivideIntoLots rule with any algorithm you prefer.  I know it's not ideal, but maybe this gives you some ideas of how to proceed.

const numBlockVertices = geometry.nVertices

const sumOfBlockVertices =
	[ sum(comp(v) { all: convert(x, scope, world, pos, 0, 0, 0) }),
	  sum(comp(v) { all: convert(y, scope, world, pos, 0, 0, 0) }),
	  sum(comp(v) { all: convert(z, scope, world, pos, 0, 0, 0) }) ]

const centroidInWorld = sumOfBlockVertices./numBlockVertices

const cubeWidth = 1
const blockCentroidLabel = "BlockCentroid"

const splitDist = 30

const tallBuildingThres = 10


Block -->
	BlockCenter
	SubdivideIntoLots
	
BlockCenter
	with(
		centroidInScope := convert(world, scope, pos, centroidInWorld)
	) -->
	primitiveCube
	s(cubeWidth, cubeWidth, cubeWidth)
	t(centroidInScope[0]-0.5*cubeWidth, centroidInScope[1]-0.5*cubeWidth, centroidInScope[2]-0.5*cubeWidth)
	label(blockCentroidLabel)
	NIL
	
SubdivideIntoLots -->
	splitAndSetbackPerimeter(0) { splitDist: splitDist: Lot }*
								{ remainder: SubdivideIntoLots }
	
Lot
	with(
		distToCentroid := minimumDistance(intra, blockCentroidLabel)
	) -->
	case distToCentroid < tallBuildingThres:
		TallBuilding
	else:
		House

 

View solution in original post

4 Replies
plfontes
New Contributor III

Hi JeoCho,

If your intent is only to know the centre points, you can run the following python script on any selected block:

'''
Created on 10 Nov 2022

@author: Plfontes
'''
from scripting import *

# get a CityEngine instance
ce = CE()

@noUIupdate
def getBlockCentroid():
    # get selected blocks
    blocks = ce.getObjectsFrom(ce.selection(),ce.isBlock)
    for block in blocks:
        # get/print centroid
        print(ce.getOID(block), ce.getPosition(block))

if __name__ == '__main__':
    getBlockCentroid()

This will print to the console the block ID and its centroid (x, y, z) position.

 

Hope this helps.

JeoCho
by
New Contributor II

Really thank you for reply

really  sorry  ,I have a other question

Example)

I would like to make this cga  , but your code is python

If i have  3  block   a  , b ,c

 Dist   =  The value of distance between a  block center and lot 

 

if dist  < 1000     ->  high building

 If dist  > 1000    ->  residental house

 

I make this process

How can i make in cga?

0 Kudos
CherylLau
Esri Regular Contributor

I assume you are working with dynamic shapes, meaning blocks and lots that are automatically created by CityEngine in a street network.  I assume you want CityEngine to automatically divide the blocks into lots.  In this case, unfortunately, I can't think of a way in cga for each Lot to know the centroid or any information about the block it belongs to.

 

The only way I can think of is to start with the dynamically created blocks, do not subdivide them automatically (select blocks, set Subdivision Type = "No Subdivision" in Inspector), and subdivide them in your cga rule instead.  Here is some code that calculates the block's centroid, places an invisible cube at the centroid, and subdivides the block into lots.  Each lot queries its minimumDistance to the invisible cube at the centroid.  If you don't need the exact centroid, it would be simpler to skip the centroid calculation and center the invisible cube in the block's scope instead.  You can replace the SubdivideIntoLots rule with any algorithm you prefer.  I know it's not ideal, but maybe this gives you some ideas of how to proceed.

const numBlockVertices = geometry.nVertices

const sumOfBlockVertices =
	[ sum(comp(v) { all: convert(x, scope, world, pos, 0, 0, 0) }),
	  sum(comp(v) { all: convert(y, scope, world, pos, 0, 0, 0) }),
	  sum(comp(v) { all: convert(z, scope, world, pos, 0, 0, 0) }) ]

const centroidInWorld = sumOfBlockVertices./numBlockVertices

const cubeWidth = 1
const blockCentroidLabel = "BlockCentroid"

const splitDist = 30

const tallBuildingThres = 10


Block -->
	BlockCenter
	SubdivideIntoLots
	
BlockCenter
	with(
		centroidInScope := convert(world, scope, pos, centroidInWorld)
	) -->
	primitiveCube
	s(cubeWidth, cubeWidth, cubeWidth)
	t(centroidInScope[0]-0.5*cubeWidth, centroidInScope[1]-0.5*cubeWidth, centroidInScope[2]-0.5*cubeWidth)
	label(blockCentroidLabel)
	NIL
	
SubdivideIntoLots -->
	splitAndSetbackPerimeter(0) { splitDist: splitDist: Lot }*
								{ remainder: SubdivideIntoLots }
	
Lot
	with(
		distToCentroid := minimumDistance(intra, blockCentroidLabel)
	) -->
	case distToCentroid < tallBuildingThres:
		TallBuilding
	else:
		House

 

JeoCho
by
New Contributor II

Thank you 

Thank you

This is what i was looking for

Really really thank you

0 Kudos