Skip to content

Commit ce524a0

Browse files
committed
add InterpolateColors predefined module. add **kwd unpacking
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/vplants/vplants/trunk/lpy@16901 ab253cce-29fb-0310-bb2f-979600cdbdeb
1 parent 5ba6492 commit ce524a0

10 files changed

+177
-30
lines changed

src/cpp/lpy_parser.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ std::string LpyParsing::lstring2pyparam( std::string::const_iterator& beg,
13771377
pprod->append_module_value(LsysContext::current()->evaluate(*itArg));
13781378
}
13791379
else {
1380-
std::string m = "PackedArgs(";
1380+
std::string m = "PackedArgs(";
13811381
if(itArg->size() > m.size() && std::string(itArg->begin(),itArg->begin()+m.size()) == m) {
13821382
pprod->append_module_star_variable();
13831383
result += "," + std::string(itArg->begin()+m.size(),itArg->end()-1);
@@ -1487,10 +1487,11 @@ parseAModule( std::string::const_iterator& _it,
14871487
while(lastcoma != endpos && (*lastcoma == ' ' || *lastcoma == '\t') )++lastcoma;
14881488
if(*lastcoma == '*'){
14891489
std::string::const_iterator lit = lastcoma+1;
1490-
if (LpyParsing::isValidVariableName(lastcoma+1,_it-1)){
1490+
if(*lit == '*') ++lit;
1491+
if (LpyParsing::isValidVariableName(lit,_it-1)){
14911492
mod_args += std::string(_it2,lastcoma);
14921493
mod_args += "PackedArgs(";
1493-
mod_args += std::string(lastcoma+1,_it);
1494+
mod_args += std::string(lit,_it);
14941495
without_unpacking = false;
14951496
}
14961497
}

src/cpp/module.cpp

+72-13
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,71 @@ boost::python::object LPY::getFunctionRepr() { return GlobalContext::getFunction
9191

9292
/*---------------------------------------------------------------------------*/
9393

94-
void processArgList(ParamModule::ParameterList& args, boost::python::object arg, size_t start = 0){
95-
object iter_obj = object( handle<>( PyObject_GetIter( arg.ptr() ) ) );
96-
for(size_t i = 0; i < start; ++i) iter_obj.attr( "next" )();
97-
try { while( true ) appendParam(args,iter_obj.attr( "next" )()); }
98-
catch( error_already_set ){ PyErr_Clear(); }
94+
void processArgList(ModuleClassPtr mclass, ParamModule::ParameterList& args, boost::python::object arg, size_t start = 0){
95+
extract<boost::python::dict> isdict(arg);
96+
if (!isdict.check()){
97+
object iter_obj = object( handle<>( PyObject_GetIter( arg.ptr() ) ) );
98+
for(size_t i = 0; i < start; ++i) iter_obj.attr( "next" )();
99+
try { while( true ) appendParam(args,iter_obj.attr( "next" )()); }
100+
catch( error_already_set ){ PyErr_Clear(); }
101+
}
102+
else {
103+
boost::python::object iter_obj = isdict().iteritems();
104+
size_t nbstdparam = args.size();
105+
if (nbstdparam + len(arg) < mclass->getNamedParameterNb()){
106+
std::stringstream str;
107+
str << mclass->name << " takes exactly " << mclass->getNamedParameterNb()<< " (" << nbstdparam + len(arg) << " given)";
108+
LsysError(str.str());
109+
}
110+
pgl_hash_set<size_t> missingargs;
111+
112+
while( true )
113+
{
114+
boost::python::object obj;
115+
try { obj = iter_obj.attr( "next" )(); }
116+
catch( boost::python::error_already_set ){ PyErr_Clear(); break; }
117+
118+
std::string pname = extract<std::string>( obj[0] )();
119+
size_t pposition = mclass->getParameterPosition(pname);
120+
if (pposition == ModuleClass::NOPOS) {
121+
std::stringstream str;
122+
str << "Invalid parameter name '" << pname << "' for module '" << mclass->name << "'.";
123+
LsysError(str.str());
124+
}
125+
else if (pposition < nbstdparam) {
126+
std::stringstream str;
127+
str << mclass->name << " got multiple values for parameter '" << pname << "'.";
128+
LsysError(str.str());
129+
}
130+
else {
131+
size_t nbactualparam = args.size();
132+
if(nbactualparam > pposition) {
133+
args[pposition] = obj[1];
134+
pgl_hash_set<size_t>::const_iterator itmarg = missingargs.find(pposition);
135+
if (itmarg != missingargs.end())
136+
missingargs.erase(itmarg);
137+
}
138+
else {
139+
for (size_t i = nbactualparam ; i < pposition; ++i ){
140+
appendParam(args,object());
141+
missingargs.insert(i);
142+
}
143+
appendParam(args,obj[1]);
144+
}
145+
}
146+
}
147+
if (missingargs.size() > 0) {
148+
std::stringstream str;
149+
str << mclass->name << " takes exactly " << mclass->getNamedParameterNb()<< " (" << missingargs.size() << " missing)";
150+
LsysError(str.str());
151+
}
152+
}
99153
}
100154

101-
void processLastArg(ParamModule::ParameterList& args, boost::python::object arg){
155+
void processLastArg(ModuleClassPtr mclass, ParamModule::ParameterList& args, boost::python::object arg){
102156
extract<PackedArgs> pka(arg);
103157
if(pka.check()){
104-
processArgList(args,pka().args);
158+
processArgList(mclass,args,pka().args);
105159
}
106160
else { appendParam(args,arg); }
107161
}
@@ -121,10 +175,11 @@ void processConstruction(ParamModule& module,
121175
for(size_t i = start; i < l-1; ++i){
122176
appendParam(args,arg[i]);
123177
}
124-
if(l > start){processLastArg(args,arg[l-1]);}
178+
if(l > start){processLastArg(module.getClass(), args,arg[l-1]);}
125179
}
126180
}
127181

182+
128183
/*---------------------------------------------------------------------------*/
129184

130185
ParamModule::ParamModule():
@@ -205,19 +260,19 @@ ParamModule::ParamModule(boost::python::list t):
205260

206261
ParamModule::ParamModule(const std::string& name,
207262
const boost::python::object& a):
208-
BaseType(name) { processLastArg(__args(),a); }
263+
BaseType(name) { processLastArg(getClass(),__args(),a); }
209264

210265
ParamModule::ParamModule(const std::string& name,
211266
const boost::python::object& a,
212267
const boost::python::object& b):
213-
BaseType(name) { appendParam(__args(),a); processLastArg(__args(),b); }
268+
BaseType(name) { appendParam(__args(),a); processLastArg(getClass(), __args(),b); }
214269

215270
ParamModule::ParamModule(const std::string& name,
216271
const boost::python::object& a,
217272
const boost::python::object& b,
218273
const boost::python::object& c):
219274
BaseType(name)
220-
{ appendParam(__args(),a); appendParam(__args(),b); processLastArg(__args(),c); }
275+
{ appendParam(__args(),a); appendParam(__args(),b); processLastArg(getClass(),__args(),c); }
221276

222277
ParamModule::ParamModule(const std::string& name,
223278
const boost::python::object& a,
@@ -226,7 +281,7 @@ ParamModule::ParamModule(const std::string& name,
226281
const boost::python::object& d):
227282
BaseType(name)
228283
{ appendParam(__args(),a); appendParam(__args(),b);
229-
appendParam(__args(),c); processLastArg(__args(),d); }
284+
appendParam(__args(),c); processLastArg(getClass(), __args(),d); }
230285

231286
ParamModule::ParamModule(const std::string& name,
232287
const boost::python::object& a,
@@ -237,14 +292,18 @@ ParamModule::ParamModule(const std::string& name,
237292
BaseType(name)
238293
{ appendParam(__args(),a); appendParam(__args(),b);
239294
appendParam(__args(),c); appendParam(__args(),d);
240-
processLastArg(__args(),e); }
295+
processLastArg(getClass(), __args(),e); }
241296

242297

243298

244299
ParamModule::~ParamModule()
245300
{
246301
}
247302

303+
void ParamModule::appendArgumentList(const boost::python::object& arglist)
304+
{
305+
processArgList(getClass(),__args(),arglist);
306+
}
248307

249308

250309

src/cpp/module.h

+1
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ class LPY_API ParamModule : public AbstractParamModule<boost::python::object> {
405405
inline bool operator!=(const std::string& other) const
406406
{ return other != name();}
407407

408+
void appendArgumentList(const boost::python::object& arglist) ;
408409

409410

410411
protected:

src/cpp/moduleclass.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ typedef pgl_hash_map_string<size_t> ParameterNameDict;
102102
MACRO(SetWidth) \
103103
MACRO(IncColor) \
104104
MACRO(DecColor) \
105-
MACRO(SetColor) \
105+
MACRO(SetColor) \
106+
MACRO(InterpolateColors) \
106107
MACRO(DivScale) \
107108
MACRO(MultScale) \
108109
MACRO(SetScale) \

src/cpp/packedargs.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/* ---------------------------------------------------------------------------
22
#
3-
# L-Py: L-systems in Python
4-
#
5-
# Copyright 2003-2008 UMR Cirad/Inria/Inra Dap - Virtual Plant Team
6-
#
7-
# File author(s): F. Boudon (frederic.boudon@cirad.fr)
3+
# L-Py: L-systems in Python
4+
#
5+
# Copyright 2003-2008 UMR Cirad/Inria/Inra Dap - Virtual Plant Team
6+
#
7+
# File author(s): F. Boudon (frederic.boudon@cirad.fr)
88
#
99
# ---------------------------------------------------------------------------
1010
#
@@ -40,8 +40,8 @@ LPY_BEGIN_NAMESPACE
4040

4141
struct LPY_API PackedArgs {
4242
public:
43-
PackedArgs(const boost::python::list _args): args(_args) {}
44-
boost::python::list args;
43+
PackedArgs(const boost::python::object _args): args(_args) {}
44+
boost::python::object args;
4545
};
4646

4747
/*---------------------------------------------------------------------------*/

src/cpp/paramproduction.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,12 @@ class LPY_API ParametricProduction : public TOOLS(RefCountObject) {
123123
if(itArg->isStarArg) {
124124
ParamModule& m = res[itArg->moduleid];
125125
bp::object argi = bp::object(args[i]);
126-
if(itArg->isNewName)m.setName(bp::extract<std::string>(argi[0])());
127-
bp::object iter_obj( bp::handle<>( PyObject_GetIter( argi.ptr() ) ) );
128-
if(itArg->isNewName)iter_obj.attr( "next" )();
129-
try { while( true ) m.append(iter_obj.attr( "next" )()); }
130-
catch( bp::error_already_set ){ PyErr_Clear(); }
126+
if(itArg->isNewName){
127+
bp::extract<bp::dict> pdict(argi);
128+
if (pdict.check()) m.setName(bp::extract<std::string>(argi["name"])());
129+
else m.setName(bp::extract<std::string>(argi[0])());
130+
}
131+
m.appendArgumentList(argi);
131132
}
132133
else {
133134
if(itArg->isNewName)res[itArg->moduleid].setName(bp::extract<std::string>(args[i])());

src/cpp/predefinedmodules.cpp

+28-1
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,32 @@ DeclareModuleBegin(setColor,"Set the current material. Params : 'index' (positiv
513513
}
514514
DeclareModuleEnd
515515

516+
DeclareModuleBegin(interpolateColors,"Set the current material. Params : 'index1', 'index2', 'alpha' .",eColor)
517+
{
518+
#if PGL_VERSION >= 0x021300
519+
size_t nbargs = m.size();
520+
switch (nbargs) {
521+
case 0:
522+
case 1:
523+
{
524+
LsysWarning("Argument missing for module "+m.name());
525+
break;
526+
}
527+
case 2:
528+
t.interpolateColors(m._getInt(0),m._getInt(1)); break;
529+
default:
530+
t.interpolateColors(m._getInt(0),m._getInt(1),m._getReal(2)); break;
531+
}
532+
#else
533+
#ifdef _MSC_VER
534+
#pragma message("InterpolateColors module will be disabled. Upgrade PlantGL.")
535+
#else
536+
#warning InterpolateColors module will be disabled. Upgrade PlantGL.
537+
#endif
538+
#endif
539+
}
540+
DeclareModuleEnd
541+
516542
DeclareModuleBegin(divScale,"Divides the current turtle scale by a scale factor, Params : 'scale_factor' (optional, default = 1.0).",eScale)
517543
{
518544
if (m.empty())t.divScale();
@@ -981,7 +1007,8 @@ void ModuleClass::createPredefinedClasses() {
9811007
SetWidth = new DeclaredModule(setWidth)("SetWidth");
9821008
IncColor = new DeclaredModule(incColor)(";","IncColor");
9831009
DecColor = new DeclaredModule(decColor)(",","DecColor");
984-
SetColor = new DeclaredModule(setColor)("SetColor");
1010+
SetColor = new DeclaredModule(setColor)("SetColor");
1011+
InterpolateColors = new DeclaredModule(interpolateColors)("InterpolateColors");
9851012
DivScale = new DeclaredModule(divScale)("@Dd","DivScale");
9861013
MultScale = new DeclaredModule(multScale)("@Di","MultScale");
9871014
SetScale = new DeclaredModule(scale)("@D","SetScale");

test/lpytest/test_deflateargs.lpy

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
def End(lstring):
2+
print lstring, type(lstring[0][0])
3+
assert lstring == Lstring('A(0,1)')
4+
5+
module A(x,y)
6+
7+
Axiom: A(0,0)
8+
9+
derivation length: 1
10+
production:
11+
12+
A(*p) :
13+
print p
14+
p[1] += 1
15+
produce A(*p)
16+
17+
interpretation:
18+
19+
20+
endlsystem

test/lpytest/test_deflatekwd.lpy

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
def End(lstring):
2+
print lstring, type(lstring[0][0])
3+
assert lstring == Lstring('A(0,1)')
4+
5+
module A(x,y)
6+
7+
Axiom: A(0,0)
8+
9+
derivation length: 1
10+
production:
11+
12+
A(**p) :
13+
print p
14+
p['y'] += 1
15+
#del p['x']
16+
#p['z'] = 0
17+
produce A(**p)
18+
19+
interpretation:
20+
21+
22+
endlsystem

test/ui/test_interpolatecolors.lpy

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from openalea.plantgl.all import *
2+
3+
dt = 0.05
4+
5+
Axiom: [ I(2,3) ] [ @M(0,2,0) I(2,5) ] [ @M(0,4,0) I(3,5) ]
6+
7+
derivation length: 1
8+
production:
9+
10+
I(c1,c2):
11+
for t in xrange(int(1/dt)):
12+
nproduce InterpolateColors(c1,c2,t*dt) @g(Box(0.5))f(1)
13+
14+
15+
endlsystem

0 commit comments

Comments
 (0)