Complete Street Rule Update

10-01-2015 01:29 PM

Complete Street Rule Update

Hi Geonet,

So after the first iteration of the Complete Street Rule I developed as part of ESRI Redlands I started working on a personal version of the rule I have decided to share because of how useful I found some of the changes. The rule being shared is a derivative work of the Complete Street Example released by ESRI Redlands.
Background: What is the Complete Street Rule?

"Complete Streets is a robust procedural street example that incorporates knowledge and ideas from various sources of transportation planning knowledge including NACTO Design Guidelines, AASHTO Design Recommendations, and MUTCD standards. The goal of the rule is to represent a diversity of street configurations to support multimodal planning in urban areas, and provide some basis for before and after comparisons of street treatments and transportation investments in CityEngine. Along with visualization, the street rule includes analytical reports on various aspects of the geometry of the street that can be used to inform rough cost estimates. In addition to these analytics, the street rule has various customizable thematics and reports that use information from the geometry and configuration of the street to suggest how it might impact the "stress levels" put on different modes. The street rule intends to represent transportation planning treatments for complete streets within urban areas and common highway configurations that might include shoulders, Jersey barriers, and HOV Lanes."- ESRI

The Github link here has a simple project that has the updated rule. You really only need the CGA rule because the assets for the rule have not changed yet (in the future they might). The version of CityEngine the rule is compatible with starts with 2014.1, and then varies by release on GitHub. 

Quick Download Link for the project is here:
Download the project or just the rule on Github here:
d-wasserman/Complete_Street_Rule: This i... - GitHub

Documentation for the rule can be found here:

Complete Street Rule Documentation & User Guide.pdf

Previous Feedback posts on the rule can be found here:

Esri Complete Street Rule Discussion-Feedback?

Webscene Using Rule with Recent Changes:

LTS Visualization

Please provide feedback if you have any.

CGA Rule Library, Transportation, 3D


Thank you David for continuing working on this complex and very useful rule.

Absolutely. Please let me know if you have any issues with some of the new features or have ideas for new ones. I am trying to be conservative on changes and focus on usability of the core functions. I might make a "Simple" version in the future that has a lot of extraneous attributes hidden.

Since you are planning (or considering) simpler version maybe you could build/include some styles like Single bike lane on both sides, bike lanes and bus lane, etc. or whatever you consider to be most common scenario. It is easy to make your own style from changes you make but having those would be excellent kick starter.

Oh I forgot about making styles. Before it had stability issues, but I think i will give that a shot again. Thanks.


Dear David,

Thank you very much for the updated rule.

I tired several times to open the zipped file but i got an error that "no projects are found to import". I used File>Import Zipped Project into Workspace. Do you have any suggestions?

kind regards,


Hey Aida,

I am not entirely sure what the issue is, but I will say I usually don't use import zipped project. I usually do one of two things.
1. Unzip the folder, grab Complete_Street.cga from the rules folder, replace the rule in a project you already have the rule. The assets folder has not changed, only the code.

2. Unzip the folder, and try File->Import-> Import Existing Project into Workspace- go into the directory one level and import the folder inside (I will work on fixing this by making it not a nested directory).
I think the reason why Import Zipped Project does not work is because the project folder is technically one level in. I will work on fixing this.


Thank you David. Your rule is very useful and precious.

Please, can you add the option to insert some walls next the sidewalks? It would be awesome!

Image 001.jpg

Thank you for prompt upgrade of the rule to support dashboards from CE 2015.2 and other improvements. I really appreciate your work.

It was actually a lot of fun, and much easier to implement than I thought it would be. =) No problem. Let me know if you find anything weird.

Hey Valerio,

There are a lot of parameters for the rule at the moment, and adding this feature would add at least 2-6 depending on the complexity desired. The rule already suffers from parameter overload. I might create a separate version of the rule that supports this in the same folder, but there is a long list of other things I need to work on before I get to it. =/  I also do a lot of the things with this rule set in my own time, so it is hard to balance actual work-life and projects I update and pursue at home.

I will let you know if I add this to the rules folder.


I am about to work on that complex intersection. Since you found dashboards too easy how about adding @Handles to it? It could be quite complicated to use but it is a part of the challenge. 

I can take a look, but I think when I scoped it out the first time it was much harder than I thought. I have been really focused on GIS integration as of late.

How do I add a grass median to a street (with trees)?

Hi Andre,

Questions about the rule in use are best put here:

Esri Complete Street Rule Discussion-Feedback?
Documentation for the rule is here:

The Official Unofficial Guide to the ESRI Complete Street Rule.pdf

Relevant attributes are in the Median Planting and Center Section attributes. In this case check to see if your Walkway_Width is overriding your current planting settings.


"So after the first iteration of the Complete Street Rule ...."

I'm a bit confused.  How come this update is released on Google drive and not the esri pages like before?  Is this first iteration link now out of date?  My company wont allow access to Google Drive.

Hi Ben,

This is a personal distribution of the rule I created while working at ESRI. Since then, I have continued work on it. I have discussed letting ESRI just take the rule and distribute, and I kept it pretty open to use like that by putting it on an Apache License. If you want to message me about discussing another way for you to get this version of the rule let me know. The improvements made are listed on this page. Does your company allow Drop Box? I can change how the rule is distributed if it would be easier

The reason why the original project is no longer used is that I no longer work for ESRI, thus do not have access to it.


Hey Ben,

Does your company allow access to Github? You can download the rule there, and if you already have the assets folder then the code is all you need. Hope this helps.
Holisticnature/Complete_Street_Rule: This i... - GitHub

Yep, I'm in.

Thanks David

Hi David,

I'm working on a new project that want to add your street rules to it. I can't understand how to solve the error on the rule package (image is  attached). Can you please help me on this?

Also, can I have your email address to discuss more about the copy/right things and how to cite you in a paper/workshop...

Kind regards,



I sent you an invite on linked in, I will send you my email over a message and we can discuss citation. I basically just would like to be cited by name.
 In terms of your error, I am unable to replicate the issue. I end up with a 108 MB rpk. Is your error that it won't even work? 

What version of CityEngine are you using? 

Thanks again David.

Hi David,

Is it possible to move the sidewalk trees location to the Rightside of the Bikelane? I tried changing the "sidewalkside" attribute to "Right" but it did not worked.

Hi Wendell, 

To clarify, you want the sidewalk side bike lanes to be between the trees and the angled parking correct? So the sidewalk highlighted would be "Walkway:Trees:Bike Lanes"?
If yes, you need to alter the splits in the sidewalk rule rather than change attributes. 
Relevant rule below: you would change the location of the bolded split to be in some other location relative to _Side_Sidewalk_Planting_Width (above it? have not tested). Save a separate version of the rule before testing. 

case valency>1:
Sidewalk_Pavement ("Corners")
case Sidewalk_Ground_Cover =="None":
split(v,unitSpace,0) {CurbtoPlantingGap:Sign_Loader(side)
|_Side_Sidewalk_Planting_Width(side):Sidewalk_WOPlant_Loading_Section (case side=="Right":0 else:2)# Uses a different loading section rule
|_Sidewalk_BikeLane_Width(case side=="Right":0 else: 2) :Sidewalk_Bike_Lane_Loader(case side=="Right":0 else: 2)
|~1: Sidewalk_Pavement ("Through Zone") People}
|_Side_Sidewalk_Planting_Width(side): Sidewalk_WPlant_Loading_Section (case side=="Right":0 else:2)
|_Sidewalk_BikeLane_Width(case side=="Right":0 else: 2) :Sidewalk_Bike_Lane_Loader(case side=="Right":0 else: 2)
|~1: Sidewalk_Pavement ("Through Zone") People}

Hi thanks for your quick reply. I will try this. Attached is a very rough mobile sketch of the section of where I want the location of the trees will be. 

Hi Wendell, 
That is what I was imagining. You need to alter the rule as per my previous comment I think.

Do you think this is a common need Wendell? I don't do many sidewalk side paths with CE, so I don't know if I should add it as an option. 


I think it's common... here in the UAE at least... what about if I want to add another tree/planting strip after the walkway. So that the walkway will be in between the 2 trees. So it will be Parking...curb..Bikelane...tree..walkway..tree..remaining pavement. I'm doing 24 ROW/street configurations on a Masterplan with very wide ROW... it's a revitalization of an Industrial area that needs to maintain the existing ROW of mostly at least 60m.

I will take a look. I kept the sidewalk rule pretty simple. 

You could alter the sidewalk rules so that it inserts two planting areas. That would just be copy pasting the rule from planting twice, but parameterizing it would require deeper modifications. 

Thank you very much David...Got it (see attached image)... is there a way to make the texture of the "Through Zone" different that the rest of the sidewalk?

Wow, that is a massive right of way. What is the total width on that super arterial?

The modification you request is a parameter addition that requires deeper changes, but not terribly difficult. 

The steps for this are as follows generally for modifications like this:

1. Identify the attribute that controls the sidewalk texture. In this case: attr Sidewalk_Texture = Default_Pavement

2. Find all references to this attribute in the rule. Determine where it is relevant. Check its relationship to the rule actually generating geometry where you care about. In this case, you just modified this section, and noticed this rule: Sidewalk_Pavement ("Through Zone")

3. Follow that rule. It should lead you to: Sidewalk_Pavement (Location). 

4. From here you have several options- separate the "Through Zone" location string from the rest of the flow of the rule (remove corners or give it a separate if statement. From here you can make a new attribute called attr Sidewalk_Through_Texture= Default_Pavement. Place it somewhere appropriate in the rule if you want to use the rule again. You now can just replace that new texture attribute so that the altered Sidewalk_Pavement rule references that texture attribute. Copy the relevant description/range @annotations in the sidewalk_texture attribute. Another option is to modify the string so it sans "New Through Zone" and alter the "else" portion of the rule. Not sure all the consequences of the last one.


That's a 65meter ROW  . Whew those steps looks  complicated but I will try it anyways... I will not stop 'til I solved it...more thanks to you!!!

Managed to change the texture of the through zone....thank you very much David

Hi David, 

Are you the one who made the PARKING LOT. CGA included in the Complete Street Project also? If so, how can I add trees in the planting strip/island same way as you did in the sidewalk in the Complete Street.cga.? 



Hi Wendell, 

I did not, but I would be more than willing to discuss the issue on this forum
Can you post a comment with a copy of the CGA rule and it source? 


Thanks for this rule David, this is just amzing! 

I took the liberty of tweaking this rule for a European/Scandinavian highway style.

Agian, thanks and keep up the good work.


Anonymous User

David,  Thanks again for this wonderful rule.

Call me tickled pink when I found out I could use it to quickly hack an off-street trail without having to write my own code.

Off-Street Bike Trail using Complete Streets code

Street Settings:

streetWidth - set to total bike trail width.
sidewalk left and right = 0

Style Settings:

@Description("Off-Street Bike Trail Hack")
style BikeLaneTrickery
attr Lane_Width = 0.0
attr Traffic_Direction = "left-hand"
attr Begin_Crosswalk_To_Stop_Bar = 0.0
attr End_Crosswalk_To_Stop_Bar = 0.0
attr Right_Bike_Lane_Width = 3.0
attr Left_Bike_Lane_Width = 3.0
attr Bike_Lane_Type = "Two-way"
attr Buffer_Protection = "false"
attr Bike_Lane_Color = "black"
attr Bike_Paint_Line_Sides = "Right"
attr Bike_Symbol_Spacing = 50
attr Bicycles_Per_KM = 10

Nice! I love seeing comments like this every once a while. Creative rule application can be a substitute for many lines of code!


Thank you David for this amazing rule, I have 2 questions though. 

1. I cannot find out how to have random scale for the plantations. Either for the sidewalk or the median part. Is there anyway to do that?

2. My second question, I dont know if its relevant here, using the datasmith for unreal, the plantations come fine as instances which can be easily replaced in unreal later, however, it seems like there is no way to do the same for other elements like the lamp posts, benches... they usually come either as one static mesh for all elements e.g (all lamp posts one static mesh) or either as a part of the street e.g (sidewalk all one static mesh including all benches, lamp posts...) I tried all possible combinations for merging and instacing while exporting.

Is there something that can be modified in the rule to make those elements exported for unreal as instances just like the plantation?

Thank you!

Hi Sherif, 
All very good questions. Ones I would like help resolving. 

  1. Currently the heights are set based on the vegetation. Completely randomized heights might be something you need to add to the CGA code. You can uncomment the handles code and replace the size adjustment parameter with something more random.
    1. For example, line 312 is: attr Sidewalk_Tree_1_Height = Tree._heightMin(Tree._indexFromCommonName(Sidewalk_Tree_1_Type))
    2. Could be: attr Sidewalk_Tree_1_Height = Tree._heightMin(Tree._indexFromCommonName(Sidewalk_Tree_1_Type)) + rand(0,2)
  2. This I actually need someone to work with on this. So thanks. So the plants are easy to split off, but the other street components are not? Is that correct? It might be that those shapes need a different label or something else. Can you provide screenshots from Unreal?

Hello David, Thank you for your answer,

First of all, I am a not too familiar with the cga rule concpet, I tried to add + rand(0,2) at the corresponding line also for the median tree attribute, right click saved the rule, hit generate nothing happens. I am sure I am missing something

For the second point:

Palm tree only can be selected and has instance meshes with correct transform and rotation values

So As you can see, in the viewport and in the outliner, I can select each instance of this palm tree or the trees in the sidewalk individually, they are all instances and grouped under one actor, and can be very easily replaced with a couple of clicks as shown in the next screenshot.

However, the other elements are only split into shapes, one shape for the street with all its content, one shape for each of the sidewalks. I moved the left sidewalk a little so it is clearer, you can also see it is one shape in the outliner.

I asked about the same issue on the forum (DataSmith Unreal Engine), I had a clear answer from Benjamin that I think should be very helpful, however I don't know where to start editing in the rule

Currently all the geometry which is generated by CGA (not an inserted object with the insert operation ) are merged (as specified by the export options, for example "per initial shape" or "by material"). Typically objects like benches or lamp post are actually inserted (with CGA insert command) objects so they should be instanced as well?


So the only way to achieve what you want is to use CGA insert operation for all the objects you later want to replace in Unreal (we actually do this as well for some of our demo content).


We do not export all leaf shapes (CGA essentials—Help | Documentation ) as Actors. Our thinking is that exporting all objects individually would lead to a lot of Actors/instances in Unreal which in turn will lead to bad performance for larger scenes.

Thank you,

Hi Sherif, 

1. I will investigate this further. Thinking on it, that likely does nothing because it is done at rule application, not for each tree.I think the answer is on line 2742. 

case Location == "Median":

Can you try this and tell me if it works? 
2. This is so weird, because those objects are inserted with  insert operations. It is possible it is related to the material/leaf settings in the planting rule. IF I tried to fix this case, what would you want most to be separated out? 

Dear David,

Thank you a lot for your answer,

1. Works like a charm!! I really like it, I believe this subtle randomness gives much more realism.

2. The most that I want to be separated out would definitely be the street lights, that why I was investigating this issue in the first place.

I can replace the models as OBJ in CityEngine and maybe change their materials later in Unreal which is fine for me but for the street light however, if you want to do a night scene, if the street lights are merged and you want to add a light at each you would have to do it manually, imagine if you have thousand of them.

If they are instances you can just copy all of them then replace the with a spotlight for example. Unless there is a better CE-UE workflow for something like this?

Hi Sherif, 

1. I might make a permanent variation adjustment to the rule. It likely will be a hidden parameter, but for now I am thinking it should vary as a percentage of the total height for any particular tree. Let me know what you think of this idea. I am trying not to add MORE parameters to the rule, but some baseline variation makes sense in High LOD scenarios. 

2. Understood. I for now I will target street lights. There HAS to be something in the planting rule in Esri lib making this separate out. I hope you are open to testing new versions of the rule!

Hi David,

1. I think that would be great!

2. I really hope that could work. It will save me a ton of time. I am always open to test new versions

thank you so much david for your help!

Hi Sherif, 

On 1. I have updated the complete street rule's development branch to have a hidden "deviation" parameter. If you download from that branch, you should be able to test it out. 

See details here: Add Percent Deviation to Tree / Planting Heights · d-wasserman/Complete_Street_Rule@bc55c5b · GitHub 
On 2. I am going to work on next week. I had an email with Cheryl Lau‌ that referenced the post you provided. I think the thing I picked up from that email that I did not get from the post is it is possible that successive operations are merging layers. I am going to investigate this later. 


Anonymous User

Regarding answer 2,  the difference between the trees and the lights is that trees are generated outside the Complete Streets Rule by Generate.Trees.   You can easily create a "StreetLights.Generate" code as such:

1. Create a new CGA code called "StreetLights" or such

2.  Write some quick code  (this could be simplified more but I copied the formats from Complete Street Code):

attr Street_Lamp_Object     = Default_Lamp

const Default_Lamp = (LampsFolder +"/Overhanging_Street_-_Light_off.glb")
const LampsFolder     = ObjectFolder+"/Dir_Lamps"
const ObjectFolder     = CompleteStreetFolder +"/Street_Furniture_and_Objects"
const CompleteStreetFolder      = case fileExists(fileRandom("Complete_Streets/Lanes*.jpg")):"Complete_Streets" else: "/ESRI.lib/assets/Streets"


Go back to the Compete Streets Code :

MAKE A COPY of  Compete Streets Code  - Maybe your own Complete Street editing version

1.  Find a place to  import your "StreetLights" rule at the top (drag and drop the cga filepath right to that place as any other import).

2.  Find around ~line 3155 (I have already made some edits to my code so this may be off) - the single line "insert object" "i(streetLamp)"for the sidewalk lamp and replace it with "StreetLights.Generate"

- Don't change any other lines, just that one.

3. Regenerate

4. Export and you should be good to go.

Hi Brian, 
I realize that is a difference between them, but I was unclear if it was the  difference for the purposes of Unreal's split out. If you are right...Every object insertion we wanted to be different would need to be fed into the rule via some import. This is not an ideal solution for the purposes of maintaining the rule (granted more libraries for the rules would be great, but not forced by the need for insertion split out). My current understanding is it is the use of successive operations on other insertions causing the problem. 

That said, did you test this change? Did it split out streetlights in Unreal for your tests? 

If this is the solution, I will review it, but I doubt I will integrate it. This seems like something labels or material settings should address rather than complete changes to how the CS rule is organized. 


I think instancing should be supported as long as the geometry was not changed after the i() operation.  You can use geometry.isInstanced() to check.

geometry function—CGA | Documentation 

There is more info in Beni's post here: 

in which he references a blog post which describes how to use i() to insert an obj, export with instancing, and replace those assets in Unreal: 

Thanks Cheryl, that will be helpful for checking. I will see what I can do. I did some minor experiments to modify the insertion modification, and it was definitely tricky.

Cheryl Lau‌, thanks again. Your suggestions were really helpful. I have not added material names, but I think I fixed instancing. 

GitHub - d-wasserman/Complete_Street_Rule: This is an updated version of the ESRI Complete Street Ru... 

Sherif Salama‌ - can you test this most recent update to the rule? Do the lamps separate out? What doesn't? 

Hi David,

Just tested it. Worked beautifully!! Thank you so much for your effort.

Version history
Last update:
‎10-01-2015 01:29 PM
Updated by: