1. import id : filePath

  2. import id ( styleId, ... , styleId ) : filePath

  3. import id : filePath ( attrId, ... , attrId )

  4. import id : filePath ( )

  5. import id : filePath ( attrId = expression, ... , attrId = expression )

  6. import id : filePath ( extensionId --> operations, ... , extensionId --> operations )

(notations can be combined with each other)



Import and reference rule files (Syntax 1 and 2)

Imports can be annotated to control their attribute presentation in the inspector. See Annotations.

Attribute and rule override

Attribute redefinition by propagation

Attribute protection (Syntax 3 and 4)

Explicit attribute and rule override (Syntax 5 and 6)

Attribute propagation and explicit overrides only redefine attributes and rules in the Default style.

Setting the attribute source of an imported attribute in the inspector to something else than "Rule default" will disable any redefining behavior for that attribute and the value will be taken from the designated source instead.

Dynamic imports

Dynamic attribute and rule override

Re-initialization of attributes

For dynamic imports, attributes are redefined in any case, independent from the current attribute source of the imported attribute in the inspector.



Extension rule override

This example illustrates how extension rules can be redefined in an import statement and how start rules can be used in overrides.

Simple temple model

In the following rule file temple.cga the start rule Temple generates a simple temple model. Each column is generated by the extension rule Column. The roof is generated by the extension rule Roof. The height of the columns is set by the attribute columnHeight. Both extension rules and attributes can be redefined in import statements in order to customize the temple model.

// temple.cga

attr columnHeight = 12
start Temple --> CreateColumns
extension Column --> primitiveCube
extension Roof --> roofHip(22)

const columnWidth = columnHeight/9
CreateColumns -->
    offset(-columnWidth, border) 
    comp(f) { all :
        split(x) {
            { ~columnWidth : Column | ~2*columnWidth : NIL }* | ~columnWidth : NIL
CreateRoof --> t(0,columnHeight,0) Roof

The resulting model looks like this:


Customized columns

In the following rule files corinthianColumn.cga and ionicColumn.cga the rules CorinthianColumn and IonicColumn generate columns in a different manner as the default behavior defined by the rule Column in temple.cga. Both CorinthianColumn and IonicColumn are defined as a start rule and can therefore be used in rule overrides of import statements.

// corinthianColumn.cga

start CorinthianColumn --> split(y) { ~1 : Shaft | '0.1 : Base } 
Base --> primitiveCube
Shaft --> s('0.8, '1,'0.8) center(xz) primitiveCube
// ionicColumn.cga

start IonicColumn --> split(y) { '0.1: Base | ~1 : Shaft | '0.1: Base } 

Base --> primitiveCube
Shaft --> primitiveCylinder

Customized temple model

The following rule file myTemple.cga imports the rule file temple.cga using the prefix identifier CorinthianTemple and the prefix identifier IonicTemple. In each import statement the attribute columnHeight and extension rules are redefined. The redifinitions of Column invoke the start rules of corinthianColumn.cga and ionicColumn.cga respectively. The redefinition of the Roof rule sets a color and invokes the rule MyRoof in the current ruleset (in the same rule file). Within the Init rule the start rule of temple.cga is invoked. Depending on which prefix identifier is used a different temple model is generated.

// myTemple.cga

import CorinthianColumn : "corinthianColumn.cga" 
import CorinthianTemple : "temple.cga" ( 
    columnHeight = 8,
    Column --> CorinthianColumn.start,  
    Roof --> color(1,0.5,0.5) MyRoof )

import IonicColumn : "ionicColumn.cga" 
import IonicTemple : "temple.cga" ( 
    columnHeight = 16,
    Column --> IonicColumn.start,  
    Roof --> color(1,0.5,0) MyRoof )

@Enum("Corinthian", "Ionic")
attr type = "Corinthian"
Init --> case type == "Corinthian" : CorinthianTemple.start   
         else                      : IonicTemple.start
MyRoof --> roofGable(22)

The resulting models look like this:

type == "Corinthian"

type == "Ionic"

Using plant loader with dynamic import

In the following example ESRI.lib's plant loader is used to randomly insert three different trees. The attribute plant.Name is redefined in a static import. For each customization of the plant loader we use a separate import statement. The dimensions of a tree are defined by attributes plant.Height and plant.Radius and automatically adjusted in Plant_Loader.cga according to plant.Name.

import bay    : "/ESRI.lib/rules/Plants/Plant_Loader.cga"
                ( Name = "California Bay" )
import cedar  : "/ESRI.lib/rules/Plants/Plant_Loader.cga"
                ( Name = "California Incense Cedar" )
import walnut : "/ESRI.lib/rules/Plants/Plant_Loader.cga"
                ( Name = "California Walnut" )

Lot --> scatter(surface, 10, uniform) { Plant }

Plant -->  33% : bay.Generate
           33% : cedar.Generate
          else : walnut.Generate

Instead of defining several static imports, the attribute plant.Name can be redefined in a dynamic import. This provides the flexibilty to set values dynamically at runtime. All dependent attributes such as plant.Height and plant.Radius are re-initialized depending on plant.Name resulting in correct tree dimensions.

import plant:"/ESRI.lib/rules/Plants/Plant_Loader.cga"

getName =  33% : "California Bay"
           33% : "California Incense Cedar"
          else : "California Walnut"

Lot --> scatter(surface, 10, uniform) { Plant }

Plant --> plant( Name = getName ).Generate

Copyright ©2008-2023 Esri R&D Center Zurich. All rights reserved.