Can values be passed on between cga files?

3172
8
Jump to solution
08-25-2015 07:17 AM
NicolaiSteinø
Occasional Contributor

I am testing how to link cga files by means of the "import" operation. I want to do my site layouts (i.e. where to put buildings on the ground) in one cga file and import another cga file containing scripts for building envelopes (i.e. the form of each building) into it.

My problem is: I want to be able to report the floor area ratio (FAR) for which I need the lot area and the floor areas of each building. However, the lot area is generated in the script of the first cga file while the floor areas are generated in the script of the second cga file.

Is there a way to pass on the floor area from an attribute in the first cga file to be used in the reporting of the second cga file?

I have been trying to import the lot area from file 1 into file 2, but as file 1 also imports file 2, the whole thing gets cyclical…

Should I do the reporting in file 1 instead? Is there a "best practice" on this?

I hope you understand my problem.

0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable

Here is what is happening:

All attributes are evaluated before the rule runs (same with constants). Your parent rule and child rules both have an attribute with the same name "lotArea", which causes the lotArea in the child rule to have the value of the parent rule lotArea. This all happens before the rule is run. So once your rule starts running, setting the lotArea in the rule, will not set the value in the child rule. That parent-child attribute matching only happens before the rule starts. Try this:

Change this in the parent rule:

attr lotArea = geometry.area

And remove this line:

set(lotArea, geometry.area)

Also using the print command and having the CGA console open to see the results is extremely useful for debugging. Open the CGA console, and then make your parent rule start with this:

Lot -->

print("parent lotArea = " + lotArea)

print("child lotArea = " + f1.lotArea)

You will see the initial value of the parent lotArea is handed down to the child rule, before any other CGA is run.

Chris

View solution in original post

8 Replies
by Anonymous User
Not applicable

Nicolai,

There are several ways to pass attributes, values, and geometry down to the imported rule.

First: Read everything on this page: import

1. You can automatically pass attributes from parent to child rule by naming attributes the same.

2. You can call functions in imported rules, which return values.

3. You can pass values into rules in the imported file via parameters.

What you can't do is:

1. Send geometry into the imported rule and then have it returned (unlike a function that returns values - you can't return geometry from the imported rule).

2. You can't have cyclical imports. Two rules that import each other is a no.

3. The imported rule cannot call functions or rules in the parent rule (the importing rule).

This help?

0 Kudos
NicolaiSteinø
Occasional Contributor

Hmm… I can make it work using a parameter, but I'll have to pass it on quite a bit, which I don't find very neat.

According to 1. in your answer, it would be possible to set an attr in the parent rule and pass it on to the child rule.

It would be nicer to set the value of an attr lotArea in the parent rule and pass it on to an identical attr in the child rule. But that doesn't seem to work. I made a test report of attr lotArea in both parent and child rule, but it only reported correctly from the parent rule. I pasted both rules below.

Did I misunderstand something?

/**

* File:    parent_rule.cga

* Created: 27 Aug 2015 21:22:33 GMT

* Author:  Nic

*/

version "2015.1"

import f1 : "child_rule.cga"

attr lotArea = 1

Lot --> case scope.sx < scope.sz : rotateScope(0,90,0) X(geometry.area)

  else : X(geometry.area)

X(sqm) --> report("lotArea", geometry.area)

  set(lotArea, geometry.area)

  report("testParentLotArea", lotArea)

  split(x) { '0.5 : Footprint(sqm) | '0.5 : Green }

Footprint(sqm) --> f1.Footprint(sqm)

Green --> color(0.5,1,0.5)

/**

* File:    child_rule.cga

* Created: 27 Aug 2015 21:22:59 GMT

* Author:  Nic

*/

version "2015.1"

attr bldgH = 12

attr floorH = 3

attr lotArea = 1

Footprint(sqm) --> report("testChildLotArea",lotArea)

  extrude(bldgH)

  Envelope(sqm)

Envelope(sqm) --> split(y) { ~floorH : Floor(sqm) }*

Floor(sqm) --> comp(f) { bottom : FloorShape(sqm) }

FloorShape(sqm) --> report("floorArea",geometry.area)

  report("FAR", geometry.area/sqm) # Here I would prefer to insert the attribute "lotArea" instead of the parameter "sqm"

0 Kudos
by Anonymous User
Not applicable

Before talking about the main question, there is an error in your parent rule that should stop it from compiling. In this line:

split { '0.5 : Footprint(sqm) | '0.5 : Green }

There needs to be a axis supplied for the split operation, like this:

split ( x ) { '0.5 : Footprint(sqm) | '0.5 : Green }

Chris

0 Kudos
NicolaiSteinø
Occasional Contributor

Yes, the split command has the correct syntax in my actual rule file – don't know why it's missing above…

Anyway, I still cannot make the child file adopt the attribute values of namesake attributes in the parent file.

The issue is not just an aesthetic one (that it looks nicer). Passing on parameters a long way is also more prone to errors. Besides, I plan to link multiple child files to the parent file, all of which will use the lotArea parameter value. It is going to be a lot of Ariadne threads of parameters to keep track of.

As you see, I inserted a report("testChildLotArea",lotArea) operation in the Footprint rule of the child rule. In the inspector, this reports the initial value of the attribute (of the child rule file). Had the value been passed on from the parent rule file equivalent, I would expect that value (which is set) to be reported. Or am I wrong?

Any suggestions to a solution?

Is it a CE 2015.1 bug?

0 Kudos
by Anonymous User
Not applicable

Here is what is happening:

All attributes are evaluated before the rule runs (same with constants). Your parent rule and child rules both have an attribute with the same name "lotArea", which causes the lotArea in the child rule to have the value of the parent rule lotArea. This all happens before the rule is run. So once your rule starts running, setting the lotArea in the rule, will not set the value in the child rule. That parent-child attribute matching only happens before the rule starts. Try this:

Change this in the parent rule:

attr lotArea = geometry.area

And remove this line:

set(lotArea, geometry.area)

Also using the print command and having the CGA console open to see the results is extremely useful for debugging. Open the CGA console, and then make your parent rule start with this:

Lot -->

print("parent lotArea = " + lotArea)

print("child lotArea = " + f1.lotArea)

You will see the initial value of the parent lotArea is handed down to the child rule, before any other CGA is run.

Chris

NicolaiSteinø
Occasional Contributor

Thanxissimo! This means the world to me – or at least my simulation of it…

Although, I don't really understand what happens (which, of course, annoys me, as I won't be able to replicate the trick in another context).

How does the script know which geometry.area to use in attr lotArea? I use the geometry.area function in more places throughout the script. In addition, attr lotArea is no longer referenced anywhere in the script.

Also, it seems that the parent attr does not simply overrule the namesake child attr. Rather it seems to work in conjunction with it: I cannot write whatever value for the child attr (this would be the case if it was overwritten, I suppose). It must be set to geometry.area like the parent attr in order to work.

How is that?

PS: Yes, the console is truly helpful when debugging.

0 Kudos
by Anonymous User
Not applicable

Set the lotArea attribute in the parent rule.

attr lotArea = geometry.area

Since all attrs evaluate before the rule executes, it uses the area of the starting geometry. The child also takes the same value for lotArea, regardless of its own geometry. Regardless of what the area is at any other time. This is what you wanted, yes?

Chris

by Anonymous User
Not applicable

With importing rules, all of the child attributes whose names match a parent attr will be set to the parent value before the start rule begins.

Chris

0 Kudos