Select to view content in your preferred language

Change front on a dynamic shape

1144
7
Jump to solution
03-16-2022 08:54 AM
PeterVickerman
New Contributor II

I am trying to create a rule file for a building that will only occur on a corner lot. 

The default first edge is the longest edge along a street and this sets the front of the building and the corresponding setback.

Is there a way to change this default first edge and corresponding front of the building to the street edge with the shortest dimension rather than the longest dimension?

On the attached image, I want the blue face to be the front and the red face to be the side but the default is the opposite. 

0 Kudos
1 Solution

Accepted Solutions
JonasObertuefer
Esri Contributor

thats because of floating point inprecision. the scope.sx returned from the comp function can be slightly different to the one you get from the comp operation. You can see this if you add print(scope.sx) after all case statements. So case scope.sx == streetFrontMax was to true for one of the sides.

You need to handle this somehow e.g comparing aginst the values after ceil() or floor() or by against a certain range.

btw. findMin(getStreetFrontEdgeLenghts ) will always return 0 because comp(fe) { street.front : scope.sx } does return an array containing all the values from the initial shape. edges which are not part of the street.front selector will be returned as 0. See comp function in the help.

 

 

View solution in original post

7 Replies
JonasObertuefer
Esri Contributor

Hi @PeterVickerman

The default first edge is not the longest edge along a street, it is calculated from the streetWidth paramter. So in your corner case if the streetWidth of the segment A is set to 12 and the streetWidth of the segment B is set 12.001 the first edge will be at the side of segment B.

for each lot in a block a streetWidth[] object attribute containing all the streetWidths from the surrounding block is automatically generated. You can access this streetWidth[] object attribute inside your cga code, see here:

 

Hope this helps!

Best,
Jonas

PeterVickerman
New Contributor II

Thank you Jonas. I was able to make it work by adjusting the streetWidth parameter, although this caused some other challenges with the overall model (shifting orientation of some of the automatically created lots). 

Do you know if CE automatically calculate the length of each of the edges along a road so I could compare and set the shortest as the first edge?

 

0 Kudos
JonasObertuefer
Esri Contributor

Hi again,

I think for your case you don't need to rely on the firstEdge at all. Here is a cga snippet that handles the street facades according to their lenght:

 

const getStreetFrontEdgeLenghts = comp(fe) { street.front : scope.sx }

findMax(array) = sortIndices(array)[size(array)-1]
max(array) = array[findMax(array)]

Lot -->
	extrude(15)
	comp(f) { side : Facades }
	
Facades -->
	case getStreetFrontEdgeLenghts[comp.index] > 0:			// street facades
		case scope.sx == max(getStreetFrontEdgeLenghts):	// longer street facade
			color("#FF0000")							
			MainStreetFacade
		else:												// shorter street facade
			color("#FFFF00")
			SecondaryStreetFacade
	else: 													//non street Facades
		BackFacade

 

 

You probably need to edit it a bit to make it work for your rule, but this should do the trick!

Cheers
Jonas

PeterVickerman
New Contributor II

Thank you so much for sharing this, I do appreciate it!

0 Kudos
PeterVickerman
New Contributor II

Jonas, you have been so helpful, I do appreciate it!

I copied this code into a new rule file but it is identifying both street sides as the SecondaryStreetFacade and I am struggling to understand why.

I added a new constant based on the max in the array and printed this to double check but it still doesn't want to id the longer street facade differently. Here is the code (not sure how to copy it in like you did):

const getStreetFrontEdgeLenghts = comp(fe) { street.front : scope.sx }
findMin(array) = sortIndices(array)[0]
findMax(array) = sortIndices(array)[size(array)-1]

min(array) = array[findMin(array)]
max(array) = array[findMax(array)]

const streetFrontMin = min(getStreetFrontEdgeLenghts)

const streetFrontMax = max(getStreetFrontEdgeLenghts)

Lot -->
extrude(15)
comp(f) { side : Facades }
print (getStreetFrontEdgeLenghts)
print (streetFrontMin)
print (streetFrontMax)

Facades -->
case getStreetFrontEdgeLenghts[comp.index] > 0: // street facades
case scope.sx == streetFrontMax: // longer street facade
color("#00a1d9")
MainStreetFacade


else: // shorter street facade
color("#FF0000")
SecondaryStreetFacade
else: //non street Facades
BackFacade

 

Here is the console print:

(4)[57.71571731567383,0,0,30.6853084564209]
0
57.71571731567383

So the scope.sx does indeed match streetFrontMax but it isn't coloring the sides any different.

PeterVickerman_0-1653588395983.png

 

0 Kudos
JonasObertuefer
Esri Contributor

thats because of floating point inprecision. the scope.sx returned from the comp function can be slightly different to the one you get from the comp operation. You can see this if you add print(scope.sx) after all case statements. So case scope.sx == streetFrontMax was to true for one of the sides.

You need to handle this somehow e.g comparing aginst the values after ceil() or floor() or by against a certain range.

btw. findMin(getStreetFrontEdgeLenghts ) will always return 0 because comp(fe) { street.front : scope.sx } does return an array containing all the values from the initial shape. edges which are not part of the street.front selector will be returned as 0. See comp function in the help.

 

 

PeterVickerman
New Contributor II

Thank you, I changed the following:

case ceil(scope.sx) == ceil(streetFrontMax): // longer street facade

So far this has worked with all the corner lots I have tested.  

I really appreciate you taking this time to help me understand this!

0 Kudos