vector<Symbol> apply_rule ( Symbol &node_parent, GNode *rule ) { // 1) create a new vector<Symbol> node_child as the return value; vector<Symbol> node_child; // 2) compare the rule -> function with the function name and decide the function we will apply // "Scale" => void Symbol::S(double x, double y, double z); if ( rule -> function == "scale" ) { vector< double > p; int dim = 0; for ( vector< pair< float, float > > :: iterator it = rule -> parameters.begin(); it != rule -> parameters.end(); it ++ ) { if ( it -> first == -1 ) // convert the dimention keyword from {-1,-2,-3} to {0,1,2} p.push_back ( node_parent.scale[0] * ( it -> second ) / node_parent.scale[dim] ); else if ( it -> first == -2 ) p.push_back ( node_parent.scale[1] * ( it -> second ) / node_parent.scale[dim] ); else if ( it -> first == -3 ) p.push_back ( node_parent.scale[2] * ( it -> second ) / node_parent.scale[dim] ); else p.push_back ( ( it -> first ) * ( it -> second ) ); dim ++; } node_child.push_back ( node_parent.S ( p[0], p[1], p[2], rule -> symbolNames[0])); } // no return value // "Trans" => void Symbol::T(double x, double y, double z); else if ( rule -> function == "trans" ) { vector< double > p; for ( vector< pair< float, float > > :: iterator it = rule -> parameters.begin(); it != rule -> parameters.end(); it ++ ) { if ( it -> first == -1 ) // convert the dimention keyword from {-1,-2,-3} to {0,1,2} p.push_back ( node_parent.scale[0] * ( it -> second ) ); else if ( it -> first == -2 ) p.push_back ( node_parent.scale[1] * ( it -> second ) ); else if ( it -> first == -3 ) p.push_back ( node_parent.scale[2] * ( it -> second ) ); else p.push_back ( ( it -> first ) * ( it -> second ) ); } node_child.push_back ( node_parent.T ( p[0], p[1], p[2], rule -> symbolNames[0]) ); } // no return value // "extrude" => Symbol extrude ( vector<double> p, string n) // extrude the 2D or 1D Symbol into 3D. // give pair or pairs of parameter and extrude the Symbol if ( rule -> function == "extrude" ) { vector< double > p; for ( vector< pair< float, float > > :: iterator it = rule -> parameters.begin(); it != rule -> parameters.end(); it ++ ) { if ( it -> first == -1 ) // convert the dimention keyword from {-1,-2,-3} to {0,1,2} p.push_back ( node_parent.scale[0] * ( it -> second ) ); else if ( it -> first == -2 ) p.push_back ( node_parent.scale[1] * ( it -> second ) ); else if ( it -> first == -3 ) p.push_back ( node_parent.scale[2] * ( it -> second ) ); else p.push_back ( ( it -> first ) * ( it -> second ) ); } node_child.push_back ( node_parent.extrude ( p, rule -> symbolNames[0])); } // "Rotate" => not valid at the moment // "Rename" => rename ( string symbolName ); // if name = "epsilon", then active = 0; else change the name else if ( rule -> function == "rename" ) { node_child = node_parent.rename ( rule -> symbolNames[0] ); } // "Subdiv" => vector<Symbol>Symbol::subDiv( int d, vector<double>&splits, vector<string> &symbols); // 0-x, 1-y, 2-z; splits are absolute value else if ( rule -> function == "subDiv" ) { vector< pair< float, float > > :: iterator it = rule -> parameters.begin(); int d; // parameter shows the cordinate we Subdiv along d = ( it -> first ) * ( -1 ) - 1; // convert the dimention keyword from {-1,-2,-3} to {0,1,2} vector<double> splits; // absolute value of the splits part. int r_count =0; // count of the relative value int i = 0; // index of the relative value vector<int> idx; // list of index for the relative values double sum_absolute = 0; it ++; while ( it != rule -> parameters.end() ) { if ( it -> first == -1 ) { splits.push_back ( node_parent.scale[0] * ( it -> second ) ); sum_absolute += * (splits.end() - 1); } else if ( it -> first == -2 ) { splits.push_back ( node_parent.scale[1] * ( it -> second ) ); sum_absolute += * (splits.end() - 1); } else if ( it -> first == -3 ) { splits.push_back ( node_parent.scale[2] * ( it -> second ) ); sum_absolute += * (splits.end() - 1); } else if ( it -> first == -4 ) { splits.push_back ( it -> second ); r_count += it -> second; idx.push_back ( i ); } else { splits.push_back ( ( it -> first ) * ( it -> second ) ); sum_absolute += * ( splits.end() -1); } i ++; // index of the relative value it ++; } double r = ( node_parent.scale[d] - sum_absolute ) / r_count; for ( int it_of_idx = 0; it_of_idx < idx.size(); it_of_idx ++) splits [ idx[ it_of_idx ] ] *= r; node_child = node_parent.subDiv ( d, splits, rule -> symbolNames ); } // "Component_split" => vector<Symbol>Symbol::comp( vector<string> symbols); // s gives us the name of the new Symbol else if ( rule -> function == "comp" ) { node_child = node_parent.comp ( rule -> symbolNames ); } // "Repeat" => vector<Symbol>Symbol::repeat( int dim, double size, string symbol); // 0-x, 1-y, 2-z; else if ( rule -> function == "repeat" ) { // take the parameters and symbol_IDs of the result vector< pair< float, float > > :: iterator it = rule -> parameters.begin(); int d = ( it -> first ) * ( -1 ) - 1; // convert the dimention keyword from {-1,-2,-3} to {0,1,2} it ++; double size; if ( it -> first == -1 ) // convert the dimention keyword from {-1,-2,-3} to {0,1,2} size = node_parent.scale[0] * ( it -> second ); else if ( it -> first == -2 ) size = node_parent.scale[1] * ( it -> second ); else if ( it -> first == -3 ) size = ( node_parent.scale[2] * ( it -> second )); else size = ( it -> first ) * ( it -> second ); string name = rule -> symbolNames [0]; // convert symbol name // pass parameter to the Symbol functions node_child = node_parent.repeat ( d, size, name ); } // "Occlusion" => return node_child; }