Changeset 522 for cpp/frams/model


Ignore:
Timestamp:
06/23/16 00:15:59 (4 years ago)
Author:
Maciej Komosinski
Message:

Code formatting

Location:
cpp/frams/model
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/model/model.cpp

    r519 r522  
    1111Model::Model()
    1212{
    13 autobuildmaps=false;
    14 init();
     13        autobuildmaps = false;
     14        init();
    1515}
    1616
    1717void Model::init()
    1818{
    19 partmappingchanged=0;
    20 buildstatus=empty;
    21 modelfromgenotype=0;
    22 startenergy=1.0;
    23 checklevel=1;
     19        partmappingchanged = 0;
     20        buildstatus = empty;
     21        modelfromgenotype = 0;
     22        startenergy = 1.0;
     23        checklevel = 1;
    2424#ifdef MODEL_V1_COMPATIBLE
    25 oldneurocount=-1; // == unknown
    26 oldconnections=0;
     25        oldneurocount=-1; // == unknown
     26        oldconnections=0;
    2727#endif
    28 map=0;
    29 f0map=0;
    30 f0genoknown=1;
    31 shape=SHAPE_UNKNOWN;
     28        map = 0;
     29        f0map = 0;
     30        f0genoknown = 1;
     31        shape = SHAPE_UNKNOWN;
    3232}
    3333
    3434void Model::moveElementsFrom(Model &source)
    3535{
    36 int i;
    37 open();
    38 for (i=0;i<source.getPartCount();i++)
    39         addPart(source.getPart(i));
    40 for (i=0;i<source.getJointCount();i++)
    41         addJoint(source.getJoint(i));
    42 for (i=0;i<source.getNeuroCount();i++)
    43         addNeuro(source.getNeuro(i));
    44 source.parts.clear(); source.joints.clear(); source.neurons.clear();
    45 source.clear();
     36        int i;
     37        open();
     38        for (i = 0; i < source.getPartCount(); i++)
     39                addPart(source.getPart(i));
     40        for (i = 0; i < source.getJointCount(); i++)
     41                addJoint(source.getJoint(i));
     42        for (i = 0; i < source.getNeuroCount(); i++)
     43                addNeuro(source.getNeuro(i));
     44        source.parts.clear(); source.joints.clear(); source.neurons.clear();
     45        source.clear();
    4646}
    4747
    4848void Model::internalCopy(const Model &mod)
    4949{
    50 geno=mod.geno;
    51 f0genoknown=0;
    52 startenergy=mod.startenergy;
    53 if (mod.getStatus()==valid)
    54         {
    55         modelfromgenotype=mod.modelfromgenotype;
    56         {for (int i=0;i<mod.getPartCount();i++)
    57                 addPart(new Part(*mod.getPart(i)));}
    58         {for (int i=0;i<mod.getJointCount();i++)
    59                 {
    60                 Joint *oldj=mod.getJoint(i);
    61                 Joint *j=new Joint(*oldj);
     50        geno = mod.geno;
     51        f0genoknown = 0;
     52        startenergy = mod.startenergy;
     53        if (mod.getStatus() == valid)
     54        {
     55                modelfromgenotype = mod.modelfromgenotype;
     56                {for (int i = 0; i < mod.getPartCount(); i++)
     57                        addPart(new Part(*mod.getPart(i))); }
     58        {for (int i = 0; i < mod.getJointCount(); i++)
     59        {
     60                Joint *oldj = mod.getJoint(i);
     61                Joint *j = new Joint(*oldj);
    6262                addJoint(j);
    63                 j->attachToParts(oldj->part1->refno,oldj->part2->refno);
    64                 }}
    65         {for (int i=0;i<mod.getNeuroCount();i++)
    66                 {
    67                 Neuro *oldn=mod.getNeuro(i);
    68                 Neuro *n=new Neuro(*oldn);
     63                j->attachToParts(oldj->part1->refno, oldj->part2->refno);
     64        }}
     65        {for (int i = 0; i < mod.getNeuroCount(); i++)
     66        {
     67                Neuro *oldn = mod.getNeuro(i);
     68                Neuro *n = new Neuro(*oldn);
    6969                addNeuro(n);
    70                 if (oldn->part_refno>=0) n->attachToPart(oldn->part_refno);
     70                if (oldn->part_refno >= 0) n->attachToPart(oldn->part_refno);
    7171                else n->attachToJoint(oldn->joint_refno);
    72                 }}
    73         for (int i=0;i<mod.getNeuroCount();i++)
    74                 {
    75                 Neuro *oldn=mod.getNeuro(i);
    76                 Neuro *n=getNeuro(i);
    77                 for (int ni=0;ni < oldn->getInputCount();ni++)
     72        }}
     73                for (int i = 0; i < mod.getNeuroCount(); i++)
     74                {
     75                        Neuro *oldn = mod.getNeuro(i);
     76                        Neuro *n = getNeuro(i);
     77                        for (int ni = 0; ni < oldn->getInputCount(); ni++)
    7878                        {
    79                         double w;
    80                         Neuro *oldinput=oldn->getInput(ni,w);
    81                         SString info=n->getInputInfo(ni);
    82                         n->addInput(getNeuro(oldinput->refno),w,&info);
     79                                double w;
     80                                Neuro *oldinput = oldn->getInput(ni, w);
     81                                SString info = n->getInputInfo(ni);
     82                                n->addInput(getNeuro(oldinput->refno), w, &info);
    8383                        }
    8484                }
     
    8787
    8888
    89 Model::Model(const Geno &src,bool buildmaps)
     89Model::Model(const Geno &src, bool buildmaps)
    9090        :autobuildmaps(buildmaps)
    91 {init(src);}
     91{
     92        init(src);
     93}
    9294
    9395void Model::operator=(const Model &mod)
    9496{
    95 clear();
    96 open();
    97 internalCopy(mod);
    98 buildstatus=mod.buildstatus;
    99 }
    100 
    101 Model::Model(const Model &mod,bool buildmaps)
     97        clear();
     98        open();
     99        internalCopy(mod);
     100        buildstatus = mod.buildstatus;
     101}
     102
     103Model::Model(const Model &mod, bool buildmaps)
    102104        :autobuildmaps(buildmaps)
    103105{
    104 init();
    105 open();
    106 internalCopy(mod);
    107 buildstatus=mod.buildstatus;
     106        init();
     107        open();
     108        internalCopy(mod);
     109        buildstatus = mod.buildstatus;
    108110}
    109111
    110112void Model::init(const Geno &src)
    111113{
    112 init();
    113 modelfromgenotype=1;
    114 geno=src;
    115 build();
     114        init();
     115        modelfromgenotype = 1;
     116        geno = src;
     117        build();
    116118}
    117119
    118120void Model::resetAllDelta()
    119121{
    120 for (int i=0;i<getJointCount();i++)
    121         getJoint(i)->resetDelta();
     122        for (int i = 0; i < getJointCount(); i++)
     123                getJoint(i)->resetDelta();
    122124}
    123125
    124126void Model::useAllDelta(bool yesno)
    125127{
    126 for (int i=0;i<getJointCount();i++)
    127         getJoint(i)->useDelta(yesno);
     128        for (int i = 0; i < getJointCount(); i++)
     129                getJoint(i)->useDelta(yesno);
    128130}
    129131
    130132Model::~Model()
    131133{
    132 delmodel_list.action((intptr_t)this);
    133 clear();
     134        delmodel_list.action((intptr_t)this);
     135        clear();
    134136}
    135137
    136138void Model::clear()
    137139{
    138 FOREACH(Part*,p,parts)
     140        FOREACH(Part*, p, parts)
     141                delete p;
     142        FOREACH(Joint*, j, joints)
     143                delete j;
     144        FOREACH(Neuro*, n, neurons)
     145                delete n;
     146        parts.clear(); joints.clear(); neurons.clear();
     147        delMap();
     148        delF0Map();
     149        init();
     150        geno = Geno();
     151        f0geno = Geno();
     152}
     153
     154Part *Model::addPart(Part *p)
     155{
     156        p->owner = this;
     157        p->refno = parts.size();
     158        parts += p;
     159        return p;
     160}
     161
     162Joint *Model::addJoint(Joint *j)
     163{
     164        j->owner = this;
     165        j->refno = joints.size();
     166        joints += j;
     167        return j;
     168}
     169
     170Neuro *Model::addNeuro(Neuro *n)
     171{
     172        n->owner = this;
     173        n->refno = neurons.size();
     174        neurons += n;
     175        return n;
     176}
     177
     178void Model::removeNeuros(SList &nlist)
     179{
     180        FOREACH(Neuro*, nu, nlist)
     181        {
     182                int i = findNeuro(nu);
     183                if (i >= 0) removeNeuro(i);
     184        }
     185}
     186
     187void Model::removePart(int partindex, int removeattachedjoints, int removeattachedneurons)
     188{
     189        Part *p = getPart(partindex);
     190        if (removeattachedjoints)
     191        {
     192                SList jlist;
     193                findJoints(jlist, p);
     194                FOREACH(Joint*, j, jlist)
     195                {
     196                        int i = findJoint(j);
     197                        if (i >= 0) removeJoint(i, removeattachedneurons);
     198                }
     199        }
     200        if (removeattachedneurons)
     201        {
     202                SList nlist;
     203                findNeuros(nlist, 0, p);
     204                removeNeuros(nlist);
     205        }
     206        parts -= partindex;
    139207        delete p;
    140 FOREACH(Joint*,j,joints)
     208}
     209
     210void Model::removeJoint(int jointindex, int removeattachedneurons)
     211{
     212        Joint *j = getJoint(jointindex);
     213        if (removeattachedneurons)
     214        {
     215                SList nlist;
     216                findNeuros(nlist, 0, 0, j);
     217                removeNeuros(nlist);
     218        }
     219        joints -= jointindex;
    141220        delete j;
    142 FOREACH(Neuro*,n,neurons)
    143         delete n;
    144 parts.clear(); joints.clear(); neurons.clear();
    145 delMap();
    146 delF0Map();
    147 init();
    148 geno=Geno();
    149 f0geno=Geno();
    150 }
    151 
    152 Part *Model::addPart(Part *p)
    153 {
    154 p->owner=this;
    155 p->refno=parts.size();
    156 parts+=p;
    157 return p;
    158 }
    159 
    160 Joint *Model::addJoint(Joint *j)
    161 {
    162 j->owner=this;
    163 j->refno=joints.size();
    164 joints+=j;
    165 return j;
    166 }
    167 
    168 Neuro *Model::addNeuro(Neuro *n)
    169 {
    170 n->owner=this;
    171 n->refno=neurons.size();
    172 neurons+=n;
    173 return n;
    174 }
    175 
    176 void Model::removeNeuros(SList &nlist)
    177 {
    178 FOREACH(Neuro*,nu,nlist)
    179         {
    180         int i=findNeuro(nu);
    181         if (i>=0) removeNeuro(i);
    182         }
    183 }
    184 
    185 void Model::removePart(int partindex,int removeattachedjoints,int removeattachedneurons)
    186 {
    187 Part *p=getPart(partindex);
    188 if (removeattachedjoints)
    189         {
    190         SList jlist;
    191         findJoints(jlist,p);
    192         FOREACH(Joint*,j,jlist)
    193                 {
    194                 int i=findJoint(j);
    195                 if (i>=0) removeJoint(i,removeattachedneurons);
    196                 }
    197         }
    198 if (removeattachedneurons)
    199         {
    200         SList nlist;
    201         findNeuros(nlist,0,p);
    202         removeNeuros(nlist);
    203         }
    204 parts-=partindex;
    205 delete p;
    206 }
    207 
    208 void Model::removeJoint(int jointindex,int removeattachedneurons)
    209 {
    210 Joint *j=getJoint(jointindex);
    211 if (removeattachedneurons)
    212         {
    213         SList nlist;
    214         findNeuros(nlist,0,0,j);
    215         removeNeuros(nlist);
    216         }
    217 joints-=jointindex;
    218 delete j;
    219 }
    220 
    221 void Model::removeNeuro(int neuroindex,bool removereferences)
    222 {
    223 Neuro* thisN=getNeuro(neuroindex);
    224 
    225 if (removereferences)
    226         {
    227         Neuro* n;
    228 // remove all references to thisN
    229         for (int i=0;n=(Neuro*)neurons(i);i++)
    230                 {
    231                 Neuro *inp;
    232                 for (int j=0;inp=n->getInput(j);j++)
    233                         if (inp==thisN)
     221}
     222
     223void Model::removeNeuro(int neuroindex, bool removereferences)
     224{
     225        Neuro* thisN = getNeuro(neuroindex);
     226
     227        if (removereferences)
     228        {
     229                Neuro* n;
     230                // remove all references to thisN
     231                for (int i = 0; n = (Neuro*)neurons(i); i++)
     232                {
     233                        Neuro *inp;
     234                        for (int j = 0; inp = n->getInput(j); j++)
     235                                if (inp == thisN)
    234236                                {
    235237                                n->removeInput(j);
     
    239241        }
    240242
    241 neurons-=neuroindex;
    242 delete thisN;
     243        neurons -= neuroindex;
     244        delete thisN;
    243245}
    244246
    245247MultiMap& Model::getMap()
    246248{
    247 if (!map) map=new MultiMap();
    248 return *map;
     249        if (!map) map = new MultiMap();
     250        return *map;
    249251}
    250252
    251253void Model::delMap()
    252254{
    253 if (map) {delete map; map=0;}
     255        if (map) { delete map; map = 0; }
    254256}
    255257void Model::delF0Map()
    256258{
    257 if (f0map) {delete f0map; f0map=0;}
    258 }
    259 
    260 void Model::makeGenToGenMap(MultiMap& result,const MultiMap& gen1tomodel,const MultiMap& gen2tomodel)
    261 {
    262 result.clear();
    263 MultiMap m;
    264 m.addReversed(gen2tomodel);
    265 result.addCombined(gen1tomodel,m);
     259        if (f0map) { delete f0map; f0map = 0; }
     260}
     261
     262void Model::makeGenToGenMap(MultiMap& result, const MultiMap& gen1tomodel, const MultiMap& gen2tomodel)
     263{
     264        result.clear();
     265        MultiMap m;
     266        m.addReversed(gen2tomodel);
     267        result.addCombined(gen1tomodel, m);
    266268}
    267269
    268270void Model::getCurrentToF0Map(MultiMap& result)
    269271{
    270 result.clear();
    271 if (!map) return;
    272 const MultiMap& f0m=getF0Map();
    273 makeGenToGenMap(result,*map,f0m);
     272        result.clear();
     273        if (!map) return;
     274        const MultiMap& f0m = getF0Map();
     275        makeGenToGenMap(result, *map, f0m);
    274276}
    275277
    276278void Model::rebuild(bool buildm)
    277279{
    278 autobuildmaps=buildm;
    279 clear();
    280 build();
     280        autobuildmaps = buildm;
     281        clear();
     282        build();
    281283}
    282284
    283285void Model::initMap()
    284286{
    285 if (!map) map=new MultiMap();
    286 else map->clear();
     287        if (!map) map = new MultiMap();
     288        else map->clear();
    287289}
    288290
    289291void Model::initF0Map()
    290292{
    291 if (!f0map) f0map=new MultiMap();
    292 else f0map->clear();
     293        if (!f0map) f0map = new MultiMap();
     294        else f0map->clear();
    293295}
    294296
    295297void Model::build()
    296298{
    297 f0errorposition=-1;
    298 f0warnposition=-1;
    299 MultiMap *convmap=autobuildmaps ? new MultiMap() : NULL;
    300 f0geno=(geno.getFormat()=='0')? geno : geno.getConverted('0',convmap);
    301 f0genoknown=1;
    302 if (f0geno.isInvalid())
    303         {
    304         buildstatus=invalid;
    305         if (convmap) delete convmap;
    306         return;
    307         }
    308 SString f0txt=f0geno.getGene();
    309 buildstatus=building; // was: open();
    310 if (autobuildmaps)
    311         {
    312         partmappingchanged=0;
    313         initMap();
    314         initF0Map();
    315         }
    316 int pos=0,lnum=1,lastpos=0;
    317 SString line;
    318 MultiRange frommap;
    319 LoggerToMemory mh(LoggerBase::Enable | LoggerBase::DontBlock);
    320 for (;f0txt.getNextToken(pos,line,'\n');lnum++)
    321         {
    322         if (autobuildmaps)
    323                 {
    324                 frommap.clear();
    325                 frommap.add(lastpos,pos-1);
    326                 }
    327         mh.reset();
    328         if (singleStepBuild(line,lnum,autobuildmaps ? (&frommap) : 0) == -1)
    329                 {
    330                 buildstatus=invalid;
    331                 f0errorposition=lastpos;
     299        f0errorposition = -1;
     300        f0warnposition = -1;
     301        MultiMap *convmap = autobuildmaps ? new MultiMap() : NULL;
     302        f0geno = (geno.getFormat() == '0') ? geno : geno.getConverted('0', convmap);
     303        f0genoknown = 1;
     304        if (f0geno.isInvalid())
     305        {
     306                buildstatus = invalid;
    332307                if (convmap) delete convmap;
    333308                return;
    334                 }
    335         if (mh.getWarningCount())
    336                 {if (f0warnposition<0) f0warnposition=lastpos;}
    337         lastpos=pos;
    338         }
    339 mh.disable();
    340 close();
    341 if (convmap)
    342         {
    343         *f0map=*map;
    344         if (geno.getFormat()!='0')
    345                 {
    346                 MultiMap tmp;
    347                 tmp.addCombined(*convmap,getMap());
    348                 *map=tmp;
    349                 }
    350         delete convmap;
     309        }
     310        SString f0txt = f0geno.getGene();
     311        buildstatus = building; // was: open();
     312        if (autobuildmaps)
     313        {
     314                partmappingchanged = 0;
     315                initMap();
     316                initF0Map();
     317        }
     318        int pos = 0, lnum = 1, lastpos = 0;
     319        SString line;
     320        MultiRange frommap;
     321        LoggerToMemory mh(LoggerBase::Enable | LoggerBase::DontBlock);
     322        for (; f0txt.getNextToken(pos, line, '\n'); lnum++)
     323        {
     324                if (autobuildmaps)
     325                {
     326                        frommap.clear();
     327                        frommap.add(lastpos, pos - 1);
     328                }
     329                mh.reset();
     330                if (singleStepBuild(line, lnum, autobuildmaps ? (&frommap) : 0) == -1)
     331                {
     332                        buildstatus = invalid;
     333                        f0errorposition = lastpos;
     334                        if (convmap) delete convmap;
     335                        return;
     336                }
     337                if (mh.getWarningCount())
     338                {
     339                        if (f0warnposition < 0) f0warnposition = lastpos;
     340                }
     341                lastpos = pos;
     342        }
     343        mh.disable();
     344        close();
     345        if (convmap)
     346        {
     347                *f0map = *map;
     348                if (geno.getFormat() != '0')
     349                {
     350                        MultiMap tmp;
     351                        tmp.addCombined(*convmap, getMap());
     352                        *map = tmp;
     353                }
     354                delete convmap;
    351355        }
    352356}
     
    354358const MultiMap& Model::getF0Map()
    355359{
    356 if (!f0map)
    357         {
    358         f0map=new MultiMap();
    359         makeGeno(f0geno,f0map);
    360         f0genoknown=1;
    361         }
    362 return *f0map;
     360        if (!f0map)
     361        {
     362                f0map = new MultiMap();
     363                makeGeno(f0geno, f0map);
     364                f0genoknown = 1;
     365        }
     366        return *f0map;
    363367}
    364368
    365369Geno Model::rawGeno()
    366370{
    367 Geno tmpgen;
    368 makeGeno(tmpgen);
    369 return tmpgen;
    370 }
    371 
    372 void Model::makeGeno(Geno &g,MultiMap *map,bool handle_defaults)
    373 {
    374 if ((buildstatus!=valid)&&(buildstatus!=building))
    375         {
    376         g=Geno(0,0,0,"invalid model");
    377         return;
    378         }
    379 
    380 SString gen;
    381 
    382 Param modelparam(f0_model_paramtab);
    383 Param partparam(f0_part_paramtab);
    384 Param jointparam(f0_joint_paramtab);
    385 Param neuroparam(f0_neuro_paramtab);
    386 Param connparam(f0_neuroconn_paramtab);
    387 
    388 static Part defaultpart;
    389 static Joint defaultjoint;
    390 static Neuro defaultneuro;
    391 static Model defaultmodel;
    392 static NeuroConn defaultconn;
    393 //static NeuroItem defaultneuroitem;
    394 
    395 Part *p;
    396 Joint *j;
    397 Neuro *n;
    398 int i;
    399 int len;
    400 int a,b;
    401 //NeuroItem *ni;
    402 
    403 SString mod_props;
    404 modelparam.select(this);
    405 modelparam.save2(mod_props,handle_defaults ? &defaultmodel : NULL,true,!handle_defaults);
    406 if (mod_props.len()>1) //are there any non-default values? ("\n" is empty)
    407         {
    408         gen+="m:";
    409         gen+=mod_props;
    410         }
    411 
    412 for (i=0;p=(Part*)parts(i);i++)
    413         {
    414         partparam.select(p);
    415         len=gen.len();
    416         gen+="p:";
    417         partparam.save2(gen,handle_defaults ? &defaultpart : NULL,true,!handle_defaults);
    418         if (map)
    419                 map->add(len,gen.len()-1,partToMap(i));
    420         }
    421 for (i=0;j=(Joint*)joints(i);i++)
    422         {
    423         jointparam.select(j);
    424         len=gen.len();
    425         jointparam.setParamTab(j->usedelta?f0_joint_paramtab:f0_nodeltajoint_paramtab);
    426         gen+="j:";
    427         jointparam.save2(gen,handle_defaults ? &defaultjoint : NULL,true,!handle_defaults);
    428         if (map)
    429                 map->add(len,gen.len()-1,jointToMap(i));
    430         }
    431 for (i=0;n=(Neuro*)neurons(i);i++)
    432         {
    433         neuroparam.select(n);
    434         len=gen.len();
    435         gen+="n:";
    436         neuroparam.save2(gen,handle_defaults ? &defaultneuro : NULL,true,!handle_defaults);
    437         if (map)
    438                 map->add(len,gen.len()-1,neuroToMap(i));
    439         }
    440 for (a=0;a<neurons.size();a++)
     371        Geno tmpgen;
     372        makeGeno(tmpgen);
     373        return tmpgen;
     374}
     375
     376void Model::makeGeno(Geno &g, MultiMap *map, bool handle_defaults)
     377{
     378        if ((buildstatus != valid) && (buildstatus != building))
     379        {
     380                g = Geno(0, 0, 0, "invalid model");
     381                return;
     382        }
     383
     384        SString gen;
     385
     386        Param modelparam(f0_model_paramtab);
     387        Param partparam(f0_part_paramtab);
     388        Param jointparam(f0_joint_paramtab);
     389        Param neuroparam(f0_neuro_paramtab);
     390        Param connparam(f0_neuroconn_paramtab);
     391
     392        static Part defaultpart;
     393        static Joint defaultjoint;
     394        static Neuro defaultneuro;
     395        static Model defaultmodel;
     396        static NeuroConn defaultconn;
     397        //static NeuroItem defaultneuroitem;
     398
     399        Part *p;
     400        Joint *j;
     401        Neuro *n;
     402        int i;
     403        int len;
     404        int a, b;
     405        //NeuroItem *ni;
     406
     407        SString mod_props;
     408        modelparam.select(this);
     409        modelparam.save2(mod_props, handle_defaults ? &defaultmodel : NULL, true, !handle_defaults);
     410        if (mod_props.len() > 1) //are there any non-default values? ("\n" is empty)
     411        {
     412                gen += "m:";
     413                gen += mod_props;
     414        }
     415
     416        for (i = 0; p = (Part*)parts(i); i++)
     417        {
     418                partparam.select(p);
     419                len = gen.len();
     420                gen += "p:";
     421                partparam.save2(gen, handle_defaults ? &defaultpart : NULL, true, !handle_defaults);
     422                if (map)
     423                        map->add(len, gen.len() - 1, partToMap(i));
     424        }
     425        for (i = 0; j = (Joint*)joints(i); i++)
     426        {
     427                jointparam.select(j);
     428                len = gen.len();
     429                jointparam.setParamTab(j->usedelta ? f0_joint_paramtab : f0_nodeltajoint_paramtab);
     430                gen += "j:";
     431                jointparam.save2(gen, handle_defaults ? &defaultjoint : NULL, true, !handle_defaults);
     432                if (map)
     433                        map->add(len, gen.len() - 1, jointToMap(i));
     434        }
     435        for (i = 0; n = (Neuro*)neurons(i); i++)
     436        {
     437                neuroparam.select(n);
     438                len = gen.len();
     439                gen += "n:";
     440                neuroparam.save2(gen, handle_defaults ? &defaultneuro : NULL, true, !handle_defaults);
     441                if (map)
     442                        map->add(len, gen.len() - 1, neuroToMap(i));
     443        }
     444        for (a = 0; a < neurons.size(); a++)
    441445        { // inputs
    442         n=(Neuro*)neurons(a);
    443 //      if ((n->getInputCount()==1)&&(n->getInput(0).refno <= n->refno))
    444 //              continue; // already done with Neuro::conn_refno
    445 
    446         for (b=0;b<n->getInputCount();b++)
    447                 {
    448                 double w;
    449                 NeuroConn nc;
    450                 Neuro* n2=n->getInput(b,w);
    451 //              if (((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno)) ^
    452 //                  (n2.neuro_refno>=0))
    453 //                      printf("!!!! bad Neuro::neuro_refno ?!\n");
    454 
    455 //              if ((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno))
    456 //              if (n2.neuro_refno>=0)
    457 //                      continue; // already done with Neuro::neuro_refno
    458 
    459                 nc.n1_refno=n->refno; nc.n2_refno=n2->refno;
    460                 nc.weight=w;
    461                 SString **s=n->inputInfo(b);
    462                 if ((s)&&(*s))
    463                 nc.info=**s;
    464                 connparam.select(&nc);
    465                 len=gen.len();
    466                 gen+="c:";
    467                 connparam.save2(gen,handle_defaults ? &defaultconn : NULL,true,!handle_defaults);
    468                 if (map)
    469                         map->add(len,gen.len()-1,neuroToMap(n->refno));
    470                 }
    471         }
    472 g=Geno(gen.c_str(),'0');
     446                n = (Neuro*)neurons(a);
     447                //      if ((n->getInputCount()==1)&&(n->getInput(0).refno <= n->refno))
     448                //              continue; // already done with Neuro::conn_refno
     449
     450                for (b = 0; b < n->getInputCount(); b++)
     451                {
     452                        double w;
     453                        NeuroConn nc;
     454                        Neuro* n2 = n->getInput(b, w);
     455                        //              if (((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno)) ^
     456                        //                  (n2.neuro_refno>=0))
     457                        //                      printf("!!!! bad Neuro::neuro_refno ?!\n");
     458
     459                        //              if ((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno))
     460                        //              if (n2.neuro_refno>=0)
     461                        //                      continue; // already done with Neuro::neuro_refno
     462
     463                        nc.n1_refno = n->refno; nc.n2_refno = n2->refno;
     464                        nc.weight = w;
     465                        SString **s = n->inputInfo(b);
     466                        if ((s) && (*s))
     467                                nc.info = **s;
     468                        connparam.select(&nc);
     469                        len = gen.len();
     470                        gen += "c:";
     471                        connparam.save2(gen, handle_defaults ? &defaultconn : NULL, true, !handle_defaults);
     472                        if (map)
     473                                map->add(len, gen.len() - 1, neuroToMap(n->refno));
     474                }
     475        }
     476        g = Geno(gen.c_str(), '0');
    473477}
    474478
     
    477481void Model::open()
    478482{
    479 if (buildstatus==building) return;
    480 buildstatus=building;
    481 modelfromgenotype=0;
    482 partmappingchanged=0;
    483 f0genoknown=0;
    484 delMap();
     483        if (buildstatus == building) return;
     484        buildstatus = building;
     485        modelfromgenotype = 0;
     486        partmappingchanged = 0;
     487        f0genoknown = 0;
     488        delMap();
    485489}
    486490
     
    490494void Model::setGeno(const Geno& newgeno)
    491495{
    492 geno=newgeno;
     496        geno = newgeno;
    493497}
    494498
    495499void Model::clearMap()
    496500{
    497 Part *p; Joint *j; Neuro *n;
    498 int i;
    499 delMap();
    500 delF0Map();
    501 for (i=0;p=(Part*)parts(i);i++)
    502         p->clearMapping();
    503 for (i=0;j=(Joint*)joints(i);i++)
    504         j->clearMapping();
    505 for (i=0;n=(Neuro*)neurons(i);i++)
    506         n->clearMapping();
     501        Part *p; Joint *j; Neuro *n;
     502        int i;
     503        delMap();
     504        delF0Map();
     505        for (i = 0; p = (Part*)parts(i); i++)
     506                p->clearMapping();
     507        for (i = 0; j = (Joint*)joints(i); i++)
     508                j->clearMapping();
     509        for (i = 0; n = (Neuro*)neurons(i); i++)
     510                n->clearMapping();
    507511}
    508512
    509513int Model::close()
    510514{
    511 if (buildstatus!=building)
    512         logPrintf("Model","close",LOG_WARN,"Unexpected close() - no open()");
    513 if (internalcheck(1)>0)
    514         {
    515         buildstatus=valid;
    516 
    517         if (partmappingchanged)
    518                 {
    519                 getMap();
    520                 Part *p; Joint *j; Neuro *n;
    521                 int i;
    522                 for (i=0;p=(Part*)parts(i);i++)
    523                         if (p->getMapping())
    524                                 map->add(*p->getMapping(),partToMap(i));
    525                 for (i=0;j=(Joint*)joints(i);i++)
    526                         if (j->getMapping())
    527                                 map->add(*j->getMapping(),jointToMap(i));
    528                 for (i=0;n=(Neuro*)neurons(i);i++)
    529                         if (n->getMapping())
    530                                 map->add(*n->getMapping(),neuroToMap(i));
    531                 }
    532         }
    533 else
    534         buildstatus=invalid;
    535 
    536 return (buildstatus==valid);
     515        if (buildstatus != building)
     516                logPrintf("Model", "close", LOG_WARN, "Unexpected close() - no open()");
     517        if (internalcheck(1) > 0)
     518        {
     519                buildstatus = valid;
     520
     521                if (partmappingchanged)
     522                {
     523                        getMap();
     524                        Part *p; Joint *j; Neuro *n;
     525                        int i;
     526                        for (i = 0; p = (Part*)parts(i); i++)
     527                                if (p->getMapping())
     528                                        map->add(*p->getMapping(), partToMap(i));
     529                        for (i = 0; j = (Joint*)joints(i); i++)
     530                                if (j->getMapping())
     531                                        map->add(*j->getMapping(), jointToMap(i));
     532                        for (i = 0; n = (Neuro*)neurons(i); i++)
     533                                if (n->getMapping())
     534                                        map->add(*n->getMapping(), neuroToMap(i));
     535                }
     536        }
     537        else
     538                buildstatus = invalid;
     539
     540        return (buildstatus == valid);
    537541}
    538542
    539543int Model::validate()
    540544{
    541 return internalcheck(0);
    542 }
    543 
    544 Pt3D Model::whereDelta(const Part& start,const Pt3D& rot, const Pt3D& delta)
    545 {
    546 Orient roto;
    547 roto=rot;
    548 Orient o;
    549 roto.transform(o,start.o);
    550 //o.x=start.o/roto.x;
    551 //o.y=start.o/roto.y;
    552 //o.z=start.o/roto.z;
    553 return o.transform(delta)+start.p;
    554 }
    555 
    556 int Model::singleStepBuild(const SString &singleline,const MultiRange* srcrange)
    557 {
    558 return singleStepBuild(singleline,0,srcrange);
    559 }
    560 
    561 int Model::singleStepBuild(const SString &singleline,int line_num,const MultiRange* srcrange)
    562 {
    563 SString error_message;
    564 int result=singleStepBuildNoLog(singleline,error_message,srcrange);
    565 if (result<0)
    566         {
    567         if (error_message.len()==0) // generic error when no detailed message is available
    568                 error_message="Invalid f0 code";
    569         if (line_num>0)
    570                 error_message+=SString::sprintf(", line #%d",line_num);
    571         error_message+=nameForErrors();
    572         logPrintf("Model","build",LOG_ERROR,"%s",error_message.c_str());
    573         }
    574 return result;
    575 }
    576 
    577 int Model::singleStepBuildNoLog(const SString &line,SString& error_message,const MultiRange* srcrange)
    578 {
    579 error_message=SString::empty();
    580 int pos=0; const char*t=line.c_str();
    581 for (;*t;t++,pos++)
    582         if (!strchr(" \r\t",*t)) break;
    583 if (*t=='#') return 0;
    584 if (!*t) return 0;
    585 if (!strncmp(t,"p:",2))
    586         {
    587         Param partparam(f0_part_paramtab);
    588         Part *p=new Part();
    589         partparam.select(p);
    590         pos+=2;
    591         if (partparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete p; error_message="Invalid 'p:'"; return -1;}
    592         p->o.rotate(p->rot);
    593         parts+=p;
    594         p->owner=this;
    595         if (srcrange) p->setMapping(*srcrange);
    596         return getPartCount()-1;
    597         }
    598 if (!strncmp(t,"m:",2))
    599         {
    600         Param modelparam(f0_model_paramtab);
    601         modelparam.select(this);
    602         pos+=2;
    603         if (modelparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message="Invalid 'm:'"; return -1;}
    604         return 0;
    605         }
    606 else if (!strncmp(t,"j:",2))
    607         {
    608         Param jointparam(f0_joint_paramtab);
    609         Joint *j=new Joint();
    610         jointparam.select(j);
    611         pos+=2;
    612         j->owner=this;
    613         if (jointparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete j; error_message="Invalid 'j:'"; return -1;}
    614         bool p1_ok=false, p2_ok=false;
    615         if ((p1_ok=((j->p1_refno>=0)&&(j->p1_refno<getPartCount())))&&
    616             (p2_ok=((j->p2_refno>=0)&&(j->p2_refno<getPartCount()))))
    617                 {
    618                 addJoint(j);
    619                 if ((j->d.x != JOINT_DELTA_MARKER) || (j->d.y != JOINT_DELTA_MARKER) || (j->d.z != JOINT_DELTA_MARKER))
     545        return internalcheck(0);
     546}
     547
     548Pt3D Model::whereDelta(const Part& start, const Pt3D& rot, const Pt3D& delta)
     549{
     550        Orient roto;
     551        roto = rot;
     552        Orient o;
     553        roto.transform(o, start.o);
     554        //o.x=start.o/roto.x;
     555        //o.y=start.o/roto.y;
     556        //o.z=start.o/roto.z;
     557        return o.transform(delta) + start.p;
     558}
     559
     560int Model::singleStepBuild(const SString &singleline, const MultiRange* srcrange)
     561{
     562        return singleStepBuild(singleline, 0, srcrange);
     563}
     564
     565int Model::singleStepBuild(const SString &singleline, int line_num, const MultiRange* srcrange)
     566{
     567        SString error_message;
     568        int result = singleStepBuildNoLog(singleline, error_message, srcrange);
     569        if (result < 0)
     570        {
     571                if (error_message.len() == 0) // generic error when no detailed message is available
     572                        error_message = "Invalid f0 code";
     573                if (line_num>0)
     574                        error_message += SString::sprintf(", line #%d", line_num);
     575                error_message += nameForErrors();
     576                logPrintf("Model", "build", LOG_ERROR, "%s", error_message.c_str());
     577        }
     578        return result;
     579}
     580
     581int Model::singleStepBuildNoLog(const SString &line, SString& error_message, const MultiRange* srcrange)
     582{
     583        error_message = SString::empty();
     584        int pos = 0; const char*t = line.c_str();
     585        for (; *t; t++, pos++)
     586                if (!strchr(" \r\t", *t)) break;
     587        if (*t == '#') return 0;
     588        if (!*t) return 0;
     589        if (!strncmp(t, "p:", 2))
     590        {
     591                Param partparam(f0_part_paramtab);
     592                Part *p = new Part();
     593                partparam.select(p);
     594                pos += 2;
     595                if (partparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete p; error_message = "Invalid 'p:'"; return -1; }
     596                p->o.rotate(p->rot);
     597                parts += p;
     598                p->owner = this;
     599                if (srcrange) p->setMapping(*srcrange);
     600                return getPartCount() - 1;
     601        }
     602        if (!strncmp(t, "m:", 2))
     603        {
     604                Param modelparam(f0_model_paramtab);
     605                modelparam.select(this);
     606                pos += 2;
     607                if (modelparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message = "Invalid 'm:'"; return -1; }
     608                return 0;
     609        }
     610        else if (!strncmp(t, "j:", 2))
     611        {
     612                Param jointparam(f0_joint_paramtab);
     613                Joint *j = new Joint();
     614                jointparam.select(j);
     615                pos += 2;
     616                j->owner = this;
     617                if (jointparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete j; error_message = "Invalid 'j:'"; return -1; }
     618                bool p1_ok = false, p2_ok = false;
     619                if ((p1_ok = ((j->p1_refno >= 0) && (j->p1_refno < getPartCount()))) &&
     620                        (p2_ok = ((j->p2_refno >= 0) && (j->p2_refno < getPartCount()))))
     621                {
     622                        addJoint(j);
     623                        if ((j->d.x != JOINT_DELTA_MARKER) || (j->d.y != JOINT_DELTA_MARKER) || (j->d.z != JOINT_DELTA_MARKER))
    620624                        {
    621                         j->useDelta(1);
    622                         j->resetDeltaMarkers();
     625                                j->useDelta(1);
     626                                j->resetDeltaMarkers();
    623627                        }
    624                 j->attachToParts(j->p1_refno,j->p2_refno);
    625                 if (srcrange) j->setMapping(*srcrange);
    626                 return j->refno;
    627                 }
    628         else
    629                 {
    630                 error_message=SString::sprintf("Invalid reference to Part #%d",p1_ok?j->p1_refno:j->p2_refno);
    631                 delete j;
    632                 return -1;
    633                 }
    634         }
    635 else if (!strncmp(t,"n:",2)) // neuro (or the old neuro object as the special case)
    636         {
    637         Param neuroparam(f0_neuro_paramtab);
    638         Neuro *nu=new Neuro();
    639         neuroparam.select(nu);
    640         pos+=2;
    641         if (neuroparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; error_message="Invalid 'n:'"; return -1;}
     628                        j->attachToParts(j->p1_refno, j->p2_refno);
     629                        if (srcrange) j->setMapping(*srcrange);
     630                        return j->refno;
     631                }
     632                else
     633                {
     634                        error_message = SString::sprintf("Invalid reference to Part #%d", p1_ok ? j->p1_refno : j->p2_refno);
     635                        delete j;
     636                        return -1;
     637                }
     638        }
     639        else if (!strncmp(t, "n:", 2)) // neuro (or the old neuro object as the special case)
     640        {
     641                Param neuroparam(f0_neuro_paramtab);
     642                Neuro *nu = new Neuro();
     643                neuroparam.select(nu);
     644                pos += 2;
     645                if (neuroparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete nu; error_message = "Invalid 'n:'"; return -1; }
    642646#ifdef MODEL_V1_COMPATIBLE
    643         if (nu->neuro_refno>=0) // parent specified...
    644                 {
    645                 if (nu->neuro_refno >= getNeuroCount()) // and it's illegal
     647                if (nu->neuro_refno>=0) // parent specified...
     648                {
     649                        if (nu->neuro_refno >= getNeuroCount()) // and it's illegal
     650                        {
     651                                delete nu;
     652                                return -1;
     653                        }
     654                        Neuro *parentNU=getNeuro(nu->neuro_refno);
     655                        parentNU->addInput(nu,nu->weight);
     656                        // default class for parented units: n-n link
     657                        //if (nu->moredata.len()==0) nu->moredata="-";
     658                }
     659                else
     660#endif
     661                {
     662                        // default class for unparented units: standard neuron
     663                        if (nu->getClassName().len() == 0) nu->setClassName("N");
     664                }
     665                /*
     666                        if (nu->conn_refno>=0) // input specified...
     667                        {
     668                        if (nu->conn_refno >= getNeuroCount()) // and it's illegal
    646669                        {
    647670                        delete nu;
    648671                        return -1;
    649672                        }
    650                 Neuro *parentNU=getNeuro(nu->neuro_refno);
    651                 parentNU->addInput(nu,nu->weight);
    652                 // default class for parented units: n-n link
    653                 //if (nu->moredata.len()==0) nu->moredata="-";
    654                 }
    655         else
     673                        Neuro *inputNU=getNeuro(nu->conn_refno);
     674                        nu->addInput(inputNU,nu->weight);
     675                        }
     676                        */
     677#ifdef MODEL_V1_COMPATIBLE
     678                nu->weight=1.0;
    656679#endif
    657                 {
    658                 // default class for unparented units: standard neuron
    659                 if (nu->getClassName().len()==0) nu->setClassName("N");
    660                 }
    661 /*
    662         if (nu->conn_refno>=0) // input specified...
    663                 {
    664                 if (nu->conn_refno >= getNeuroCount()) // and it's illegal
    665                         {
     680                nu->owner = this;
     681                // attach to part/joint
     682                if (nu->part_refno >= 0)
     683                        nu->attachToPart(nu->part_refno);
     684                if (nu->joint_refno >= 0)
     685                        nu->attachToJoint(nu->joint_refno);
     686                if (srcrange) nu->setMapping(*srcrange);
     687                // todo: check part/joint ref#
     688#ifdef MODEL_V1_COMPATIBLE
     689                if (hasOldNeuroLayout())
     690                {
     691                        int count=old_getNeuroCount();
     692                        neurons.insert(count,nu);
     693                        oldneurocount=count+1;
     694                        return oldneurocount-1;
     695                }
     696                else
     697#endif
     698                {
     699                        neurons += nu;
     700                        return neurons.size() - 1;
     701                }
     702        }
     703        else if (!strncmp(t, "c:", 2)) // add input
     704        {
     705                Param ncparam(f0_neuroconn_paramtab);
     706                NeuroConn c;
     707                ncparam.select(&c);
     708                pos += 2;
     709                if (ncparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message = "Invalid 'c:'"; return -1; }
     710                bool n1_ok = false, n2_ok = false;
     711                if ((n1_ok = ((c.n1_refno >= 0) && (c.n1_refno < getNeuroCount())))
     712                        && (n2_ok = ((c.n2_refno >= 0) && (c.n2_refno < getNeuroCount()))))
     713                {
     714                        Neuro *na = getNeuro(c.n1_refno);
     715                        Neuro *nb = getNeuro(c.n2_refno);
     716                        na->addInput(nb, c.weight, &c.info);
     717                        if (srcrange)
     718                                na->addMapping(*srcrange);
     719                        return 0;
     720                }
     721                error_message = SString::sprintf("Invalid reference to Neuro #%d", n1_ok ? c.n2_refno : c.n1_refno);
     722                return -1;
     723        }
     724#ifdef MODEL_V1_COMPATIBLE
     725        else if (!strncmp(t,"ni:",3)) // old neuroitem
     726        {
     727                // we always use old layout for "ni:"
     728                Param neuroitemparam(f0_neuroitem_paramtab);
     729                Neuro *nu=new Neuro();
     730                neuroitemparam.select(nu);
     731                pos+=3;
     732                if (neuroitemparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; return -1;}
     733                // illegal parent?
     734                if ((nu->neuro_refno<0)||(nu->neuro_refno>=old_getNeuroCount()))
     735                {
    666736                        delete nu;
    667737                        return -1;
    668                         }
    669                 Neuro *inputNU=getNeuro(nu->conn_refno);
    670                 nu->addInput(inputNU,nu->weight);
    671                 }
    672 */
    673 #ifdef MODEL_V1_COMPATIBLE
    674         nu->weight=1.0;
     738                }
     739                Neuro *parentN=getNeuro(nu->neuro_refno);
     740                // copy part/joint refno from parent, if possible
     741                if ((nu->part_refno<0)&&(parentN->part_refno>=0))
     742                        nu->part_refno=parentN->part_refno;
     743                if ((nu->joint_refno<0)&&(parentN->joint_refno>=0))
     744                        nu->joint_refno=parentN->joint_refno;
     745                nu->owner=this;
     746                // attach to part/joint
     747                if (nu->part_refno>=0)
     748                        nu->attachToPart(nu->part_refno);
     749                if (nu->joint_refno>=0)
     750                        nu->attachToJoint(nu->joint_refno);
     751                if (srcrange)
     752                        nu->setMapping(*srcrange);
     753                // special case: old muscles
     754                // PARENT neuron will be set up to be the CHILD of the current one (!)
     755                if (nu->isOldEffector())
     756                {
     757                        nu->neuro_refno=parentN->refno;
     758                        neurons+=nu;
     759                        nu->owner=this;
     760                        nu->addInput(parentN,nu->weight); // (!)
     761                        nu->weight=1.0;
     762                        parentN->invalidateOldItems();
     763                        return 0; // !!! -> ...getItemCount()-1;
     764                }
     765                parentN->addInput(nu,nu->weight);
     766                neurons+=nu;
     767                parentN->invalidateOldItems();
     768                if (nu->getClassName().len()==0)
     769                {
     770                        nu->setClassName("-");
     771                        // for compatibility, "ni" can define a n-n connection
     772                        // referring to non-existent neuron (which will be hopefully defined later)
     773                        // internal check will add the proper input to this unit
     774                        // if conn_refno >=0 and input count==0
     775                        oldconnections=1;
     776                        if (srcrange)
     777                                parentN->addMapping(*srcrange);
     778                }
     779                else
     780                        nu->weight=1.0;
     781                return 0; // !!! -> ...getItemCount()-1;
     782        }
    675783#endif
    676         nu->owner=this;
    677         // attach to part/joint
    678         if (nu->part_refno>=0)
    679                 nu->attachToPart(nu->part_refno);
    680         if (nu->joint_refno>=0)
    681                 nu->attachToJoint(nu->joint_refno);
    682         if (srcrange) nu->setMapping(*srcrange);
    683         // todo: check part/joint ref#
    684 #ifdef MODEL_V1_COMPATIBLE
    685         if (hasOldNeuroLayout())
    686                 {
    687                 int count=old_getNeuroCount();
    688                 neurons.insert(count,nu);
    689                 oldneurocount=count+1;
    690                 return oldneurocount-1;
    691                 }
    692         else
    693 #endif
    694                 {
    695                 neurons+=nu;
    696                 return neurons.size()-1;
    697                 }
    698         }
    699 else if (!strncmp(t,"c:",2)) // add input
    700         {
    701         Param ncparam(f0_neuroconn_paramtab);
    702         NeuroConn c;
    703         ncparam.select(&c);
    704         pos+=2;
    705         if (ncparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message="Invalid 'c:'"; return -1; }
    706         bool n1_ok=false,n2_ok=false;
    707         if ((n1_ok=((c.n1_refno>=0)&&(c.n1_refno<getNeuroCount())))
    708             && (n2_ok=((c.n2_refno>=0)&&(c.n2_refno<getNeuroCount()))))
    709                 {
    710                 Neuro *na=getNeuro(c.n1_refno);
    711                 Neuro *nb=getNeuro(c.n2_refno);
    712                 na->addInput(nb,c.weight,&c.info);
    713                 if (srcrange)
    714                         na->addMapping(*srcrange);
    715                 return 0;
    716                 }
    717         error_message=SString::sprintf("Invalid reference to Neuro #%d",n1_ok ? c.n2_refno : c.n1_refno);
    718         return -1;
    719         }
    720 #ifdef MODEL_V1_COMPATIBLE
    721 else if (!strncmp(t,"ni:",3)) // old neuroitem
    722         {
    723         // we always use old layout for "ni:"
    724         Param neuroitemparam(f0_neuroitem_paramtab);
    725         Neuro *nu=new Neuro();
    726         neuroitemparam.select(nu);
    727         pos+=3;
    728         if (neuroitemparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; return -1;}
    729         // illegal parent?
    730         if ((nu->neuro_refno<0)||(nu->neuro_refno>=old_getNeuroCount()))
    731                 {
    732                 delete nu;
    733                 return -1;
    734                 }
    735         Neuro *parentN=getNeuro(nu->neuro_refno);
    736         // copy part/joint refno from parent, if possible
    737         if ((nu->part_refno<0)&&(parentN->part_refno>=0))
    738                 nu->part_refno=parentN->part_refno;
    739         if ((nu->joint_refno<0)&&(parentN->joint_refno>=0))
    740                 nu->joint_refno=parentN->joint_refno;
    741         nu->owner=this;
    742         // attach to part/joint
    743         if (nu->part_refno>=0)
    744                 nu->attachToPart(nu->part_refno);
    745         if (nu->joint_refno>=0)
    746                 nu->attachToJoint(nu->joint_refno);
    747         if (srcrange)
    748                 nu->setMapping(*srcrange);
    749         // special case: old muscles
    750         // PARENT neuron will be set up to be the CHILD of the current one (!)
    751         if (nu->isOldEffector())
    752                 {
    753                 nu->neuro_refno=parentN->refno;
    754                 neurons+=nu;
    755                 nu->owner=this;
    756                 nu->addInput(parentN,nu->weight); // (!)
    757                 nu->weight=1.0;
    758                 parentN->invalidateOldItems();
    759                 return 0; // !!! -> ...getItemCount()-1;
    760                 }
    761         parentN->addInput(nu,nu->weight);
    762         neurons+=nu;
    763         parentN->invalidateOldItems();
    764         if (nu->getClassName().len()==0)
    765                 {
    766                 nu->setClassName("-");
    767                 // for compatibility, "ni" can define a n-n connection
    768                 // referring to non-existent neuron (which will be hopefully defined later)
    769                 // internal check will add the proper input to this unit
    770                 // if conn_refno >=0 and input count==0
    771                 oldconnections=1;
    772                 if (srcrange)
    773                         parentN->addMapping(*srcrange);
    774                 }
    775         else
    776                 nu->weight=1.0;
    777         return 0; // !!! -> ...getItemCount()-1;
    778         }
    779 #endif
    780 else return -1;
     784        else return -1;
    781785}
    782786
     
    784788int Model::addOldConnectionsInputs()
    785789{
    786 if (!oldconnections) return 1;
    787 Neuro* n;
    788 for (int i=0;i<neurons.size();i++)
    789         {
    790         n=(Neuro*)neurons(i);
    791         if (n->conn_refno>=0)
    792                 if (n->isNNConnection())
    793                         if (n->conn_refno < old_getNeuroCount())
     790        if (!oldconnections) return 1;
     791        Neuro* n;
     792        for (int i=0;i<neurons.size();i++)
     793        {
     794                n=(Neuro*)neurons(i);
     795                if (n->conn_refno>=0)
     796                        if (n->isNNConnection())
     797                                if (n->conn_refno < old_getNeuroCount())
    794798                                { // good reference
    795                                 Neuro* parent=n->parent; // nn connection has exactly one parent
    796                                 int inp=parent->findInput(n);
    797                                 Neuro* target=getNeuro(n->conn_refno);
    798                                 parent->setInput(inp,target,n->weight);
    799                                 removeNeuro(i,0); // no need to remove references
    800                                 i--;
     799                        Neuro* parent=n->parent; // nn connection has exactly one parent
     800                        int inp=parent->findInput(n);
     801                        Neuro* target=getNeuro(n->conn_refno);
     802                        parent->setInput(inp,target,n->weight);
     803                        removeNeuro(i,0); // no need to remove references
     804                        i--;
    801805                                }
     806                                else
     807                                {
     808                                        logPrintf("Model","internalCheck",LOG_ERROR,
     809                                                "illegal N-N connection #%d (reference to #%d)%s",
     810                                                i,n->conn_refno,nameForErrors().c_str());
     811                                        return 0;
     812                                }
     813        }
     814        oldconnections=0;
     815        return 1;
     816}
     817#endif
     818
     819/////////////
     820
     821/** change the sequence of neuro units
     822        and fix references in "-" objects (n-n connections)  */
     823void Model::moveNeuro(int oldpos, int newpos)
     824{
     825        if (oldpos == newpos) return; // nop!
     826        Neuro *n = getNeuro(oldpos);
     827        neurons -= oldpos;
     828        neurons.insert(newpos, n);
     829        // conn_refno could be broken -> fix it
     830#ifdef MODEL_V1_COMPATIBLE
     831        for (int i=0;i<neurons.size();i++)
     832        {
     833                Neuro *n2=getNeuro(i);
     834                if (n2->isNNConnection())
     835                        if (n2->conn_refno == oldpos) n2->conn_refno=newpos;
    802836                        else
    803                                 {
    804                                 logPrintf("Model","internalCheck",LOG_ERROR,
    805                                          "illegal N-N connection #%d (reference to #%d)%s",
    806                                           i,n->conn_refno,nameForErrors().c_str());
    807                                 return 0;
    808                                 }
    809         }
    810 oldconnections=0;
    811 return 1;
    812 }
    813 #endif
    814 
    815 /////////////
    816 
    817 /** change the sequence of neuro units
    818     and fix references in "-" objects (n-n connections)  */
    819 void Model::moveNeuro(int oldpos,int newpos)
    820 {
    821 if (oldpos==newpos) return; // nop!
    822 Neuro *n=getNeuro(oldpos);
    823 neurons-=oldpos;
    824 neurons.insert(newpos,n);
    825  // conn_refno could be broken -> fix it
    826 #ifdef MODEL_V1_COMPATIBLE
    827 for (int i=0;i<neurons.size();i++)
    828         {
    829         Neuro *n2=getNeuro(i);
    830         if (n2->isNNConnection())
    831                 if (n2->conn_refno == oldpos) n2->conn_refno=newpos;
    832                 else
    833                 { if (n2->conn_refno > oldpos) n2->conn_refno--;
    834                   if (n2->conn_refno >= newpos) n2->conn_refno++; }
    835         }
    836 invalidateOldNeuroCount();
     837                        { if (n2->conn_refno > oldpos) n2->conn_refno--;
     838                if (n2->conn_refno >= newpos) n2->conn_refno++; }
     839        }
     840        invalidateOldNeuroCount();
    837841#endif
    838842}
     
    840844#ifdef MODEL_V1_COMPATIBLE
    841845/** move all old neurons (class "N") to the front of the neurons list.
    842     @return number of old neurons
    843   */
     846        @return number of old neurons
     847        */
    844848int Model::reorderToOldLayout()
    845849{
    846 Neuro *n;
    847 int neurocount=0;
    848 for (int i=0;i<neurons.size();i++)
    849         {
    850         n=(Neuro*)neurons(i);
    851         if (n->isOldNeuron())
    852                 {
    853                 moveNeuro(i,neurocount);
    854                 neurocount++;
    855                 i=neurocount-1;
    856                 }
    857         }
    858 return neurocount;
     850        Neuro *n;
     851        int neurocount=0;
     852        for (int i=0;i<neurons.size();i++)
     853        {
     854                n=(Neuro*)neurons(i);
     855                if (n->isOldNeuron())
     856                {
     857                        moveNeuro(i,neurocount);
     858                        neurocount++;
     859                        i=neurocount-1;
     860                }
     861        }
     862        return neurocount;
    859863}
    860864#endif
     
    863867void Model::updateNeuroRefno()
    864868{
    865 for (int i=0;i<neurons.size();i++)
    866         {
    867         Neuro* n=(Neuro*)neurons(i);
    868         n->refno=i;
     869        for (int i = 0; i < neurons.size(); i++)
     870        {
     871                Neuro* n = (Neuro*)neurons(i);
     872                n->refno = i;
    869873        }
    870874}
     
    882886void Model::updateRefno()
    883887{
    884 int i;
    885 for (i=0;i<getPartCount();i++) getPart(i)->refno=i;
    886 for (i=0;i<getJointCount();i++) getJoint(i)->refno=i;
    887 for (i=0;i<getNeuroCount();i++) getNeuro(i)->refno=i;
     888        int i;
     889        for (i = 0; i < getPartCount(); i++) getPart(i)->refno = i;
     890        for (i = 0; i < getJointCount(); i++) getJoint(i)->refno = i;
     891        for (i = 0; i < getNeuroCount(); i++) getNeuro(i)->refno = i;
    888892}
    889893
    890894SString Model::nameForErrors() const
    891895{
    892 if (geno.getName().len()>0)
    893         return SString::sprintf(" in '%s'",geno.getName().c_str());
    894 return SString::empty();
     896        if (geno.getName().len()>0)
     897                return SString::sprintf(" in '%s'", geno.getName().c_str());
     898        return SString::empty();
    895899}
    896900
    897901int Model::internalcheck(int final)
    898902{
    899 Part *p;
    900 Joint *j;
    901 Neuro *n;
    902 int i,k;
    903 int ret=1;
    904 shape=SHAPE_UNKNOWN;
    905 if ((parts.size()==0)&&(neurons.size()==0)) return 0;
    906 if (parts.size()==0)
    907         size=Pt3D_0;
    908 else
    909         {
    910 Pt3D bbmin=((Part*)parts(0))->p, bbmax=bbmin;
    911 for (i=0;i<parts.size();i++)
    912         {
    913         p=(Part*)parts(i);
    914         p->owner=this;
    915         p->refno=i;
    916         if (p->shape==0)
    917                 {
    918                 if (checklevel>0)
    919                         p->mass=0.0;
    920                 }
    921 //      VALIDMINMAX(p,part,mass);
    922         VALIDMINMAX(p,Part,size);
    923         VALIDMINMAX(p,Part,density);
    924         VALIDMINMAX(p,Part,friction);
    925         VALIDMINMAX(p,Part,ingest);
    926         VALIDMINMAX(p,Part,assim);
    927         p->flags&=~LINKFLAG; // for delta joint cycle detection
    928         if (p->p.x-p->size < bbmin.x) bbmin.x=p->p.x-p->size;
    929         if (p->p.y-p->size < bbmin.y) bbmin.y=p->p.y-p->size;
    930         if (p->p.z-p->size < bbmin.z) bbmin.z=p->p.z-p->size;
    931         if (p->p.x+p->size > bbmax.x) bbmax.x=p->p.x+p->size;
    932         if (p->p.y+p->size > bbmax.y) bbmax.y=p->p.y+p->size;
    933         if (p->p.z+p->size > bbmax.z) bbmax.z=p->p.z+p->size;
    934         if (shape==SHAPE_UNKNOWN)
    935                 shape=(p->shape==Part::SHAPE_DEFAULT)?SHAPE_OLD:SHAPE_NEW;
    936         else if (shape!=SHAPE_ILLEGAL)
    937                 {
    938                 if ((p->shape==Part::SHAPE_DEFAULT) ^ (shape==SHAPE_OLD))
     903        Part *p;
     904        Joint *j;
     905        Neuro *n;
     906        int i, k;
     907        int ret = 1;
     908        shape = SHAPE_UNKNOWN;
     909        if ((parts.size() == 0) && (neurons.size() == 0)) return 0;
     910        if (parts.size() == 0)
     911                size = Pt3D_0;
     912        else
     913        {
     914                Pt3D bbmin = ((Part*)parts(0))->p, bbmax = bbmin;
     915                for (i = 0; i < parts.size(); i++)
     916                {
     917                        p = (Part*)parts(i);
     918                        p->owner = this;
     919                        p->refno = i;
     920                        if (p->shape == 0)
    939921                        {
    940                         shape=SHAPE_ILLEGAL;
    941                         logPrintf("Model","internalCheck",LOG_WARN,"Inconsistent part shapes (mixed old and new shapes)%s",nameForErrors().c_str());
     922                                if (checklevel > 0)
     923                                        p->mass = 0.0;
    942924                        }
    943                 }
    944         }
    945 size=bbmax-bbmin;
    946 for (i=0;i<joints.size();i++)
    947         {
    948         j=(Joint*)joints(i);
    949         VALIDMINMAX(j,Joint,stamina);
    950         VALIDMINMAX(j,Joint,stif);
    951         VALIDMINMAX(j,Joint,rotstif);
    952         j->refno=i;
    953         j->owner=this;
    954         if (j->part1 && j->part2 && (j->part1 != j->part2))
    955                 {
    956                 j->p1_refno=j->part1->refno;
    957                 j->p2_refno=j->part2->refno;
    958                 if (checklevel>0)
     925                        //      VALIDMINMAX(p,part,mass);
     926                        VALIDMINMAX(p, Part, size);
     927                        VALIDMINMAX(p, Part, density);
     928                        VALIDMINMAX(p, Part, friction);
     929                        VALIDMINMAX(p, Part, ingest);
     930                        VALIDMINMAX(p, Part, assim);
     931                        p->flags &= ~LINKFLAG; // for delta joint cycle detection
     932                        if (p->p.x - p->size < bbmin.x) bbmin.x = p->p.x - p->size;
     933                        if (p->p.y - p->size < bbmin.y) bbmin.y = p->p.y - p->size;
     934                        if (p->p.z - p->size < bbmin.z) bbmin.z = p->p.z - p->size;
     935                        if (p->p.x + p->size > bbmax.x) bbmax.x = p->p.x + p->size;
     936                        if (p->p.y + p->size > bbmax.y) bbmax.y = p->p.y + p->size;
     937                        if (p->p.z + p->size > bbmax.z) bbmax.z = p->p.z + p->size;
     938                        if (shape == SHAPE_UNKNOWN)
     939                                shape = (p->shape == Part::SHAPE_DEFAULT) ? SHAPE_OLD : SHAPE_NEW;
     940                        else if (shape != SHAPE_ILLEGAL)
    959941                        {
    960                         if (j->part1->shape==0)
    961                                 j->part1->mass+=1.0;
    962                         if (j->part2->shape==0)
    963                                 j->part2->mass+=1.0;
    964                         }
    965                 if ((j->usedelta)&&((j->d.x!=JOINT_DELTA_MARKER)||(j->d.y!=JOINT_DELTA_MARKER)||(j->d.z!=JOINT_DELTA_MARKER)))
    966                         { // delta positioning -> calc. orient.
    967                         if (j->part2->flags & LINKFLAG)
     942                                if ((p->shape == Part::SHAPE_DEFAULT) ^ (shape == SHAPE_OLD))
    968943                                {
    969                                 ret=0;
    970                                 logPrintf("Model","internalCheck",LOG_ERROR,
    971                                          "Delta joint cycle detected at Joint #%d%s",
    972                                          i,nameForErrors().c_str());
    973                                 }
    974                         j->resetDeltaMarkers();
    975                         j->o=j->rot;
    976                         j->part1->o.transform(j->part2->o,j->o);
    977 //                      j->part2->o.x=j->part1->o/j->o.x;
    978 //                      j->part2->o.y=j->part1->o/j->o.y;
    979 //                      j->part2->o.z=j->part1->o/j->o.z;
    980                         j->part2->p=j->part2->o.transform(j->d)+j->part1->p;
    981                         j->part2->flags|=LINKFLAG; j->part1->flags|=LINKFLAG; // for delta joint cycle detection
    982                         }
    983                 else
    984                         { // abs.positioning -> calc. delta
    985                         if (final)
    986                         {
    987                         // calc orient delta
    988 //                      Orient tmpo(j->part2->o);
    989 //                      tmpo*=j->part1->o;
    990                         Orient tmpo;
    991                         j->part1->o.revTransform(tmpo,j->part2->o);
    992                         tmpo.getAngles(j->rot);
    993                         j->o=j->rot;
    994                         // calc position delta
    995                         Pt3D tmpp(j->part2->p);
    996                         tmpp-=j->part1->p;
    997                         j->d=j->part2->o.revTransform(tmpp);
    998                         }
    999                         }
    1000                 if (final)
    1001                         {
    1002                         if (j->shape!=Joint::SHAPE_SOLID)
    1003                                 {
    1004                         if (j->d()>getMaxJoint().d.x)
    1005                         {
    1006                         ret=0;
    1007                         logPrintf("Model","internalCheck",LOG_ERROR,"Joint #%d too long%s",i,nameForErrors().c_str());
    1008                         }
     944                                        shape = SHAPE_ILLEGAL;
     945                                        logPrintf("Model", "internalCheck", LOG_WARN, "Inconsistent part shapes (mixed old and new shapes)%s", nameForErrors().c_str());
    1009946                                }
    1010947                        }
    1011948                }
    1012         else
    1013                 {
    1014                 logPrintf("Model","internalCheck",LOG_ERROR,"Illegal part references in Joint #%d%s",i,nameForErrors().c_str());
    1015                 ret=0;
    1016                 }
    1017         if (shape!=SHAPE_ILLEGAL)
    1018                 {
    1019                 if ((j->shape==Joint::SHAPE_DEFAULT) ^ (shape==SHAPE_OLD))
     949                size = bbmax - bbmin;
     950                for (i = 0; i < joints.size(); i++)
     951                {
     952                        j = (Joint*)joints(i);
     953                        VALIDMINMAX(j, Joint, stamina);
     954                        VALIDMINMAX(j, Joint, stif);
     955                        VALIDMINMAX(j, Joint, rotstif);
     956                        j->refno = i;
     957                        j->owner = this;
     958                        if (j->part1 && j->part2 && (j->part1 != j->part2))
    1020959                        {
    1021                         shape=SHAPE_ILLEGAL;
    1022                         logPrintf("Model","internalCheck",LOG_WARN,"Inconsistent joint shapes (mixed old and new shapes)%s",nameForErrors().c_str());
    1023                         }
    1024                 }
    1025         }
    1026         }
    1027 #ifdef MODEL_V1_COMPATIBLE
    1028 if (!addOldConnectionsInputs())
    1029         return 0;
    1030 #endif
    1031 
    1032 updateNeuroRefno(); // valid refno is important for n-n connections check (later)
    1033 
    1034 for (i=0;i<neurons.size();i++)
    1035         {
    1036         n=(Neuro*)neurons(i);
    1037         VALIDMINMAX(n,Neuro,state);
    1038 #ifdef MODEL_V1_COMPATIBLE
    1039         VALIDMINMAX(n,Neuro,inertia);
    1040         VALIDMINMAX(n,Neuro,force);
    1041         VALIDMINMAX(n,Neuro,sigmo);
    1042         n->conn_refno=-1;
    1043         n->weight=1.0;
    1044         n->neuro_refno=-1;
    1045 #endif
    1046         n->part_refno=(n->part)?n->part->refno:-1;
    1047         n->joint_refno=(n->joint)?n->joint->refno:-1;
    1048         }
    1049 
    1050 if (parts.size()&&(checklevel>0))
    1051         {
    1052         for (i=0;i<parts.size();i++)
    1053                 {
    1054                 p=(Part*)parts(i);
    1055                 if (p->shape==0)
    1056                         if (p->mass<=0.001)
    1057                                 p->mass=1.0;
    1058                 p->flags&=~LINKFLAG;
    1059                 }
    1060         getPart(0)->flags|=LINKFLAG;
    1061         int change=1;
    1062         while(change)
    1063                 {
    1064                 change=0;
    1065                 for (i=0;i<joints.size();i++)
    1066                         {
    1067                         j=(Joint*)joints(i);
    1068                         if (j->part1->flags&LINKFLAG)
     960                                j->p1_refno = j->part1->refno;
     961                                j->p2_refno = j->part2->refno;
     962                                if (checklevel > 0)
    1069963                                {
    1070                                 if (!(j->part2->flags&LINKFLAG))
     964                                        if (j->part1->shape == 0)
     965                                                j->part1->mass += 1.0;
     966                                        if (j->part2->shape == 0)
     967                                                j->part2->mass += 1.0;
     968                                }
     969                                if ((j->usedelta) && ((j->d.x != JOINT_DELTA_MARKER) || (j->d.y != JOINT_DELTA_MARKER) || (j->d.z != JOINT_DELTA_MARKER)))
     970                                { // delta positioning -> calc. orient.
     971                                        if (j->part2->flags & LINKFLAG)
    1071972                                        {
    1072                                         change=1;
    1073                                         j->part2->flags|=LINKFLAG;
     973                                                ret = 0;
     974                                                logPrintf("Model", "internalCheck", LOG_ERROR,
     975                                                        "Delta joint cycle detected at Joint #%d%s",
     976                                                        i, nameForErrors().c_str());
     977                                        }
     978                                        j->resetDeltaMarkers();
     979                                        j->o = j->rot;
     980                                        j->part1->o.transform(j->part2->o, j->o);
     981                                        //                      j->part2->o.x=j->part1->o/j->o.x;
     982                                        //                      j->part2->o.y=j->part1->o/j->o.y;
     983                                        //                      j->part2->o.z=j->part1->o/j->o.z;
     984                                        j->part2->p = j->part2->o.transform(j->d) + j->part1->p;
     985                                        j->part2->flags |= LINKFLAG; j->part1->flags |= LINKFLAG; // for delta joint cycle detection
     986                                }
     987                                else
     988                                { // abs.positioning -> calc. delta
     989                                        if (final)
     990                                        {
     991                                                // calc orient delta
     992                                                //                      Orient tmpo(j->part2->o);
     993                                                //                      tmpo*=j->part1->o;
     994                                                Orient tmpo;
     995                                                j->part1->o.revTransform(tmpo, j->part2->o);
     996                                                tmpo.getAngles(j->rot);
     997                                                j->o = j->rot;
     998                                                // calc position delta
     999                                                Pt3D tmpp(j->part2->p);
     1000                                                tmpp -= j->part1->p;
     1001                                                j->d = j->part2->o.revTransform(tmpp);
    10741002                                        }
    10751003                                }
    1076                         else
    1077                         if (j->part2->flags&LINKFLAG)
     1004                                if (final)
    10781005                                {
    1079                                 if (!(j->part1->flags&LINKFLAG))
     1006                                        if (j->shape != Joint::SHAPE_SOLID)
    10801007                                        {
    1081                                         change=1;
    1082                                         j->part1->flags|=LINKFLAG;
     1008                                                if (j->d() > getMaxJoint().d.x)
     1009                                                {
     1010                                                        ret = 0;
     1011                                                        logPrintf("Model", "internalCheck", LOG_ERROR, "Joint #%d too long%s", i, nameForErrors().c_str());
     1012                                                }
    10831013                                        }
    10841014                                }
    10851015                        }
    1086                 }
    1087         for (i=0;i<parts.size();i++)
    1088                 {
    1089                 p=(Part*)parts(i);
    1090                 if (!(p->flags&LINKFLAG))
     1016                        else
    10911017                        {
    1092                         logPrintf("Model","internalCheck",LOG_ERROR,"Not all parts connected (eg. Part #0 and Part #%d)%s",i,nameForErrors().c_str());
    1093                         ret=0;
     1018                                logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal part references in Joint #%d%s", i, nameForErrors().c_str());
     1019                                ret = 0;
     1020                        }
     1021                        if (shape != SHAPE_ILLEGAL)
     1022                        {
     1023                                if ((j->shape == Joint::SHAPE_DEFAULT) ^ (shape == SHAPE_OLD))
     1024                                {
     1025                                        shape = SHAPE_ILLEGAL;
     1026                                        logPrintf("Model", "internalCheck", LOG_WARN, "Inconsistent joint shapes (mixed old and new shapes)%s", nameForErrors().c_str());
     1027                                }
     1028                        }
     1029                }
     1030        }
     1031#ifdef MODEL_V1_COMPATIBLE
     1032        if (!addOldConnectionsInputs())
     1033                return 0;
     1034#endif
     1035
     1036        updateNeuroRefno(); // valid refno is important for n-n connections check (later)
     1037
     1038        for (i = 0; i < neurons.size(); i++)
     1039        {
     1040                n = (Neuro*)neurons(i);
     1041                VALIDMINMAX(n, Neuro, state);
     1042#ifdef MODEL_V1_COMPATIBLE
     1043                VALIDMINMAX(n,Neuro,inertia);
     1044                VALIDMINMAX(n,Neuro,force);
     1045                VALIDMINMAX(n,Neuro,sigmo);
     1046                n->conn_refno=-1;
     1047                n->weight=1.0;
     1048                n->neuro_refno=-1;
     1049#endif
     1050                n->part_refno = (n->part) ? n->part->refno : -1;
     1051                n->joint_refno = (n->joint) ? n->joint->refno : -1;
     1052        }
     1053
     1054        if (parts.size() && (checklevel > 0))
     1055        {
     1056                for (i = 0; i < parts.size(); i++)
     1057                {
     1058                        p = (Part*)parts(i);
     1059                        if (p->shape == 0)
     1060                                if (p->mass <= 0.001)
     1061                                        p->mass = 1.0;
     1062                        p->flags &= ~LINKFLAG;
     1063                }
     1064                getPart(0)->flags |= LINKFLAG;
     1065                int change = 1;
     1066                while (change)
     1067                {
     1068                        change = 0;
     1069                        for (i = 0; i < joints.size(); i++)
     1070                        {
     1071                                j = (Joint*)joints(i);
     1072                                if (j->part1->flags&LINKFLAG)
     1073                                {
     1074                                        if (!(j->part2->flags&LINKFLAG))
     1075                                        {
     1076                                                change = 1;
     1077                                                j->part2->flags |= LINKFLAG;
     1078                                        }
     1079                                }
     1080                                else
     1081                                        if (j->part2->flags&LINKFLAG)
     1082                                        {
     1083                                        if (!(j->part1->flags&LINKFLAG))
     1084                                        {
     1085                                                change = 1;
     1086                                                j->part1->flags |= LINKFLAG;
     1087                                        }
     1088                                        }
     1089                        }
     1090                }
     1091                for (i = 0; i < parts.size(); i++)
     1092                {
     1093                        p = (Part*)parts(i);
     1094                        if (!(p->flags&LINKFLAG))
     1095                        {
     1096                                logPrintf("Model", "internalCheck", LOG_ERROR, "Not all parts connected (eg. Part #0 and Part #%d)%s", i, nameForErrors().c_str());
     1097                                ret = 0;
     1098                                break;
     1099                        }
     1100                }
     1101        }
     1102
     1103        for (i = 0; i < joints.size(); i++)
     1104        {
     1105                j = (Joint*)joints(i);
     1106                if (j->p1_refno == j->p2_refno)
     1107                {
     1108                        logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal self connection, Joint #%d%s", i, nameForErrors().c_str());
     1109                        ret = 0;
    10941110                        break;
     1111                }
     1112                for (k = i + 1; k < joints.size(); k++)
     1113                {
     1114                        Joint* j2 = (Joint*)joints(k);
     1115                        if (((j->p1_refno == j2->p1_refno) && (j->p2_refno == j2->p2_refno))
     1116                                || ((j->p1_refno == j2->p2_refno) && (j->p2_refno == j2->p1_refno)))
     1117                        {
     1118                                logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal duplicate Joint #%d and Joint #%d%s", i, k, nameForErrors().c_str());
     1119                                ret = 0;
     1120                                break;
    10951121                        }
    10961122                }
    10971123        }
    1098 
    1099 for (i=0;i<joints.size();i++)
    1100         {
    1101         j=(Joint*)joints(i);
    1102         if (j->p1_refno==j->p2_refno)
    1103                 {
    1104                 logPrintf("Model","internalCheck",LOG_ERROR,"Illegal self connection, Joint #%d%s",i,nameForErrors().c_str());
    1105                 ret=0;
    1106                 break;
    1107                 }
    1108         for (k=i+1;k<joints.size();k++)
    1109                 {
    1110                 Joint* j2=(Joint*)joints(k);
    1111                 if (((j->p1_refno==j2->p1_refno)&&(j->p2_refno==j2->p2_refno))
    1112                     || ((j->p1_refno==j2->p2_refno)&&(j->p2_refno==j2->p1_refno)))
    1113                         {
    1114                         logPrintf("Model","internalCheck",LOG_ERROR,"Illegal duplicate Joint #%d and Joint #%d%s",i,k,nameForErrors().c_str());
    1115                         ret=0;
    1116                         break;
    1117                         }
    1118                 }
    1119         }
    1120 if (shape==SHAPE_ILLEGAL)
    1121         ret=0;
    1122 return ret;
     1124        if (shape == SHAPE_ILLEGAL)
     1125                ret = 0;
     1126        return ret;
    11231127}
    11241128
     
    11271131int Model::getErrorPosition(bool includingwarnings)
    11281132{
    1129 return includingwarnings?
    1130         ((f0errorposition>=0) ? f0errorposition : f0warnposition)
    1131         :
    1132         f0errorposition;
     1133        return includingwarnings ?
     1134                ((f0errorposition >= 0) ? f0errorposition : f0warnposition)
     1135                :
     1136                f0errorposition;
    11331137}
    11341138
    11351139const Geno& Model::getGeno() const
    11361140{
    1137 return geno;
     1141        return geno;
    11381142}
    11391143
    11401144const Geno Model::getF0Geno()
    11411145{
    1142 if (buildstatus==building)
    1143         logPrintf("Model","getGeno",LOG_WARN,"Model was not completed - missing close()");
    1144 if (buildstatus!=valid)
    1145         return Geno("",'0',"","invalid");
    1146 if (!f0genoknown)
    1147         {
    1148         if (autobuildmaps)
    1149                 {
    1150                 initF0Map();
    1151                 makeGeno(f0geno,f0map);
    1152                 }
    1153         else
    1154                 {
    1155                 delF0Map();
    1156                 makeGeno(f0geno);
    1157                 }
    1158         f0genoknown=1;
    1159         }
    1160 return f0geno;
     1146        if (buildstatus == building)
     1147                logPrintf("Model", "getGeno", LOG_WARN, "Model was not completed - missing close()");
     1148        if (buildstatus != valid)
     1149                return Geno("", '0', "", "invalid");
     1150        if (!f0genoknown)
     1151        {
     1152                if (autobuildmaps)
     1153                {
     1154                        initF0Map();
     1155                        makeGeno(f0geno, f0map);
     1156                }
     1157                else
     1158                {
     1159                        delF0Map();
     1160                        makeGeno(f0geno);
     1161                }
     1162                f0genoknown = 1;
     1163        }
     1164        return f0geno;
    11611165}
    11621166
    11631167int Model::getPartCount() const
    11641168{
    1165 return parts.size();
     1169        return parts.size();
    11661170}
    11671171
    11681172Part* Model::getPart(int i) const
    11691173{
    1170 return ((Part*)parts(i));
     1174        return ((Part*)parts(i));
    11711175}
    11721176
    11731177int Model::getJointCount() const
    11741178{
    1175 return joints.size();
     1179        return joints.size();
    11761180}
    11771181
    11781182Joint* Model::getJoint(int i) const
    11791183{
    1180 return ((Joint*)joints(i));
    1181 }
    1182 
    1183 int Model::findJoints(SList& result,const Part* part)
    1184 {
    1185 Joint *j;
    1186 int n0=result.size();
    1187 if (part)
    1188    for(int i=0;j=(Joint*)joints(i);i++)
    1189      if ((j->part1 == part) || (j->part2 == part)) result+=(void*)j;
    1190 return result.size()-n0;
     1184        return ((Joint*)joints(i));
     1185}
     1186
     1187int Model::findJoints(SList& result, const Part* part)
     1188{
     1189        Joint *j;
     1190        int n0 = result.size();
     1191        if (part)
     1192                for (int i = 0; j = (Joint*)joints(i); i++)
     1193                        if ((j->part1 == part) || (j->part2 == part)) result += (void*)j;
     1194        return result.size() - n0;
    11911195}
    11921196
    11931197int Model::findNeuro(Neuro* n)
    1194 {return neurons.find(n);}
     1198{
     1199        return neurons.find(n);
     1200}
    11951201
    11961202int Model::findPart(Part* p)
    1197 {return parts.find(p);}
     1203{
     1204        return parts.find(p);
     1205}
    11981206
    11991207int Model::findJoint(Joint* j)
    1200 {return joints.find(j);}
     1208{
     1209        return joints.find(j);
     1210}
    12011211
    12021212int Model::findJoint(Part *p1, Part *p2)
    12031213{
    1204 Joint* j;
    1205 for(int i=0;j=getJoint(i);i++)
    1206         if ((j->part1==p1)&&(j->part2==p2)) return i;
    1207 return -1;
     1214        Joint* j;
     1215        for (int i = 0; j = getJoint(i); i++)
     1216                if ((j->part1 == p1) && (j->part2 == p2)) return i;
     1217        return -1;
    12081218}
    12091219
     
    12141224void Model::calcOldNeuroCount()
    12151225{
    1216 if (oldneurocount>=0) return;
    1217 oldneurocount=reorderToOldLayout();
     1226        if (oldneurocount>=0) return;
     1227        oldneurocount=reorderToOldLayout();
    12181228}
    12191229
    12201230int Model::old_getNeuroCount()
    12211231{ calcOldNeuroCount();
    1222  return oldneurocount;}
     1232return oldneurocount;}
    12231233
    12241234Neuro* Model::old_getNeuro(int i)
     
    12331243Neuro *Model::old_addNewNeuro()
    12341244{
    1235 int count=old_getNeuroCount();
    1236 Neuro *nu=addNewNeuro();
    1237 nu->setClassName("N");
    1238 moveNeuro(nu->refno,oldneurocount);
    1239 oldneurocount=count+1;
    1240 return (Neuro*)nu;
     1245        int count=old_getNeuroCount();
     1246        Neuro *nu=addNewNeuro();
     1247        nu->setClassName("N");
     1248        moveNeuro(nu->refno,oldneurocount);
     1249        oldneurocount=count+1;
     1250        return (Neuro*)nu;
    12411251}
    12421252#endif
     
    12451255
    12461256int Model::getNeuroCount() const
    1247 {return neurons.size();}
     1257{
     1258        return neurons.size();
     1259}
    12481260
    12491261Neuro* Model::getNeuro(int i) const
    1250 {return (Neuro*)neurons(i);}
     1262{
     1263        return (Neuro*)neurons(i);
     1264}
    12511265
    12521266int Model::getConnectionCount() const
    12531267{
    1254 int n=0;
    1255 for(int i=0;i<getNeuroCount();i++)
    1256         n+=getNeuro(i)->getInputCount();
    1257 return n;
     1268        int n = 0;
     1269        for (int i = 0; i < getNeuroCount(); i++)
     1270                n += getNeuro(i)->getInputCount();
     1271        return n;
    12581272}
    12591273
    12601274int Model::findNeuros(SList& result,
    1261                           const char* classname,const Part* part,const Joint* joint)
    1262 {
    1263 Neuro *nu;
    1264 SString cn(classname);
    1265 int n0=result.size();
    1266 for(int i=0;nu=(Neuro*)neurons(i);i++)
    1267         {
    1268         if (part)
    1269                 if (nu->part != part) continue;
    1270         if (joint)
    1271                 if (nu->joint != joint) continue;
    1272         if (classname)
    1273                 if (nu->getClassName() != cn) continue;
    1274         result+=(void*)nu;
    1275         }
    1276 return result.size()-n0;
     1275        const char* classname, const Part* part, const Joint* joint)
     1276{
     1277        Neuro *nu;
     1278        SString cn(classname);
     1279        int n0 = result.size();
     1280        for (int i = 0; nu = (Neuro*)neurons(i); i++)
     1281        {
     1282                if (part)
     1283                        if (nu->part != part) continue;
     1284                if (joint)
     1285                        if (nu->joint != joint) continue;
     1286                if (classname)
     1287                        if (nu->getClassName() != cn) continue;
     1288                result += (void*)nu;
     1289        }
     1290        return result.size() - n0;
    12771291}
    12781292
     
    12811295void Model::disturb(double amount)
    12821296{
    1283 int i;
    1284 if (amount<=0) return;
    1285 for(i=0;i<parts.size();i++)
    1286         {
    1287         Part *p=getPart(i);
    1288         p->p.x+=(rnd01-0.5)*amount;
    1289         p->p.y+=(rnd01-0.5)*amount;
    1290         p->p.z+=(rnd01-0.5)*amount;
    1291         }
    1292 for(i=0;i<joints.size();i++)
    1293         {
    1294         Joint *j=getJoint(i);
    1295         Pt3D tmpp(j->part2->p);
    1296         tmpp-=j->part1->p;
    1297         j->d=j->part2->o.revTransform(tmpp);
     1297        int i;
     1298        if (amount <= 0) return;
     1299        for (i = 0; i < parts.size(); i++)
     1300        {
     1301                Part *p = getPart(i);
     1302                p->p.x += (rnd01 - 0.5)*amount;
     1303                p->p.y += (rnd01 - 0.5)*amount;
     1304                p->p.z += (rnd01 - 0.5)*amount;
     1305        }
     1306        for (i = 0; i < joints.size(); i++)
     1307        {
     1308                Joint *j = getJoint(i);
     1309                Pt3D tmpp(j->part2->p);
     1310                tmpp -= j->part1->p;
     1311                j->d = j->part2->o.revTransform(tmpp);
    12981312        }
    12991313}
     
    13011315void Model::move(const Pt3D& shift)
    13021316{
    1303 FOREACH(Part*,p,parts)
    1304         p->p+=shift;
     1317        FOREACH(Part*, p, parts)
     1318                p->p += shift;
    13051319}
    13061320
    13071321void Model::rotate(const Orient& rotation)
    13081322{
    1309 FOREACH(Part*,p,parts)
    1310         {
    1311         p->p=rotation.transform(p->p);
    1312         p->setOrient(rotation.transform(p->o));
     1323        FOREACH(Part*, p, parts)
     1324        {
     1325                p->p = rotation.transform(p->p);
     1326                p->setOrient(rotation.transform(p->o));
    13131327        }
    13141328}
     
    13161330void Model::buildUsingNewShapes(const Model& old, Part::Shape default_shape, float thickness)
    13171331{
    1318 for(int i=0;i<old.getJointCount();i++)
    1319         {
    1320         Joint *oj=old.getJoint(i);
    1321         Part *p = addNewPart(default_shape);
    1322         p->p=(oj->part1->p+oj->part2->p)/2;
    1323         Orient o;
    1324         o.lookAt(oj->part1->p-oj->part2->p);
    1325         p->rot=o.getAngles();
    1326         p->scale.x=oj->part1->p.distanceTo(oj->part2->p)/2;
    1327         p->scale.y = thickness;
    1328         p->scale.z = thickness;
    1329         }
    1330 for(int i=0;i<old.getPartCount();i++)
    1331         {
    1332         Part *op=old.getPart(i);
    1333         for(int j=0;j<old.getJointCount();j++)
    1334                 {
    1335                 Joint *oj=old.getJoint(j);
    1336                 if ((oj->part1==op)||(oj->part2==op))
     1332        for (int i = 0; i < old.getJointCount(); i++)
     1333        {
     1334                Joint *oj = old.getJoint(i);
     1335                Part *p = addNewPart(default_shape);
     1336                p->p = (oj->part1->p + oj->part2->p) / 2;
     1337                Orient o;
     1338                o.lookAt(oj->part1->p - oj->part2->p);
     1339                p->rot = o.getAngles();
     1340                p->scale.x = oj->part1->p.distanceTo(oj->part2->p) / 2;
     1341                p->scale.y = thickness;
     1342                p->scale.z = thickness;
     1343        }
     1344        for (int i = 0; i < old.getPartCount(); i++)
     1345        {
     1346                Part *op = old.getPart(i);
     1347                for (int j = 0; j < old.getJointCount(); j++)
     1348                {
     1349                        Joint *oj = old.getJoint(j);
     1350                        if ((oj->part1 == op) || (oj->part2 == op))
    13371351                        {
    1338                         for(int j2=j+1;j2<old.getJointCount();j2++)
     1352                                for (int j2 = j + 1; j2 < old.getJointCount(); j2++)
    13391353                                {
    1340                                 Joint *oj2=old.getJoint(j2);
    1341                                 if ((oj2->part1==op)||(oj2->part2==op))
     1354                                        Joint *oj2 = old.getJoint(j2);
     1355                                        if ((oj2->part1 == op) || (oj2->part2 == op))
    13421356                                        {
    1343                                         addNewJoint(getPart(j),getPart(j2),Joint::SHAPE_SOLID);
     1357                                                addNewJoint(getPart(j), getPart(j2), Joint::SHAPE_SOLID);
    13441358                                        }
    13451359                                }
    1346                         break;
     1360                                break;
    13471361                        }
    13481362                }
     
    13521366//////////////////////
    13531367
    1354 class MinPart: public Part {public: MinPart() {Param par(f0_part_paramtab,this);par.setMin();}};
    1355 class MaxPart: public Part {public: MaxPart() {Param par(f0_part_paramtab,this);par.setMax();}};
    1356 class MinJoint: public Joint {public: MinJoint() {Param par(f0_joint_paramtab,this);par.setMin();}};
    1357 class MaxJoint: public Joint {public: MaxJoint() {Param par(f0_joint_paramtab,this);par.setMax();}};
    1358 class MinNeuro: public Neuro {public: MinNeuro() {Param par(f0_neuro_paramtab,this);par.setMin();}};
    1359 class MaxNeuro: public Neuro {public: MaxNeuro() {Param par(f0_neuro_paramtab,this);par.setMax();}};
    1360 
    1361 Part& Model::getMinPart() {static MinPart part; return part;}
    1362 Part& Model::getMaxPart() {static MaxPart part; return part;}
    1363 Part& Model::getDefPart() {static Part part; return part;}
    1364 Joint& Model::getMinJoint() {static MinJoint joint; return joint;}
    1365 Joint& Model::getMaxJoint() {static MaxJoint joint; return joint;}
    1366 Joint& Model::getDefJoint() {static Joint joint; return joint;}
    1367 Neuro& Model::getMinNeuro() {static MinNeuro neuro; return neuro;}
    1368 Neuro& Model::getMaxNeuro() {static MaxNeuro neuro; return neuro;}
    1369 Neuro& Model::getDefNeuro() {static Neuro neuro; return neuro;}
     1368class MinPart : public Part { public: MinPart() { Param par(f0_part_paramtab, this); par.setMin(); } };
     1369class MaxPart : public Part { public: MaxPart() { Param par(f0_part_paramtab, this); par.setMax(); } };
     1370class MinJoint : public Joint { public: MinJoint() { Param par(f0_joint_paramtab, this); par.setMin(); } };
     1371class MaxJoint : public Joint { public: MaxJoint() { Param par(f0_joint_paramtab, this); par.setMax(); } };
     1372class MinNeuro : public Neuro { public: MinNeuro() { Param par(f0_neuro_paramtab, this); par.setMin(); } };
     1373class MaxNeuro : public Neuro { public: MaxNeuro() { Param par(f0_neuro_paramtab, this); par.setMax(); } };
     1374
     1375Part& Model::getMinPart() { static MinPart part; return part; }
     1376Part& Model::getMaxPart() { static MaxPart part; return part; }
     1377Part& Model::getDefPart() { static Part part; return part; }
     1378Joint& Model::getMinJoint() { static MinJoint joint; return joint; }
     1379Joint& Model::getMaxJoint() { static MaxJoint joint; return joint; }
     1380Joint& Model::getDefJoint() { static Joint joint; return joint; }
     1381Neuro& Model::getMinNeuro() { static MinNeuro neuro; return neuro; }
     1382Neuro& Model::getMaxNeuro() { static MaxNeuro neuro; return neuro; }
     1383Neuro& Model::getDefNeuro() { static Neuro neuro; return neuro; }
  • cpp/frams/model/model.h

    r495 r522  
    1818//#define EASYMAPDEBUG
    1919
    20 enum ModelBuildStatus {empty,building,invalid,valid};
     20enum ModelBuildStatus { empty, building, invalid, valid };
    2121
    2222class MultiMap;
     
    2525
    2626/**
    27     "Model" is the skeleton of the Framsticks creature.
    28     This object can be used for 2 purposes:
    29      - you can build a creature from any supported Framsticks genotype
    30     format
    31      - or generate low level f0 genotype from existing construct.
    32 
    33     In both cases you have access to geometry and neuron net data.
    34     Using this standard class assures compatibility and good
    35     integration with core Framsticks engine.
    36 
    37     Model contains 3 kinds of objects:
    38     - Parts (class Part).
    39     - Joints (class Joint). Each Joint is connected with 2 Parts. (@see Joint::attachToParts()).
    40     - Neurons (class Neuro). Neuron can have 0 or more inputs - other neurons. (@see Neuro::addInput()).
    41       Each Neuron can be located on the physical structure, i.e. it can ba attached to Part or Joint
    42       (@see Neuro::attachToPart(), Neuro::attachToJoint()).
    43 
    44 \f[(dot)
    45 digraph Model
    46  {
    47   Joint1; Joint2;
    48   node [ shape=box ]
    49   Part1; Part2; Part3;
    50   Joint1 -> Part1; Joint1 -> Part2; Joint2 -> Part2; Joint2 -> Part3
    51   node [ shape=diamond ]
    52   Neuro1 -> Neuro2; Neuro1 -> Neuro3; Neuro2 -> Neuro2; Neuro3 -> Neuro2;
    53   Neuro1 -> Part1; Neuro2 -> Joint2;
    54  }
    55 \f]
    56 */
    57 
    58 class Model: public DestrBase
     27        "Model" is the skeleton of the Framsticks creature.
     28        This object can be used for 2 purposes:
     29        - you can build a creature from any supported Framsticks genotype
     30        format
     31        - or generate low level f0 genotype from existing construct.
     32
     33        In both cases you have access to geometry and neuron net data.
     34        Using this standard class assures compatibility and good
     35        integration with core Framsticks engine.
     36
     37        Model contains 3 kinds of objects:
     38        - Parts (class Part).
     39        - Joints (class Joint). Each Joint is connected with 2 Parts. (@see Joint::attachToParts()).
     40        - Neurons (class Neuro). Neuron can have 0 or more inputs - other neurons. (@see Neuro::addInput()).
     41        Each Neuron can be located on the physical structure, i.e. it can ba attached to Part or Joint
     42        (@see Neuro::attachToPart(), Neuro::attachToJoint()).
     43
     44        \f[(dot)
     45        digraph Model
     46        {
     47        Joint1; Joint2;
     48        node [ shape=box ]
     49        Part1; Part2; Part3;
     50        Joint1 -> Part1; Joint1 -> Part2; Joint2 -> Part2; Joint2 -> Part3
     51        node [ shape=diamond ]
     52        Neuro1 -> Neuro2; Neuro1 -> Neuro3; Neuro2 -> Neuro2; Neuro3 -> Neuro2;
     53        Neuro1 -> Part1; Neuro2 -> Joint2;
     54        }
     55        \f]
     56        */
     57
     58class Model : public DestrBase
    5959{
    60   protected:
    61 Geno geno,f0geno;
    62 char modelfromgenotype;
    63 char f0genoknown;
    64 /// make model map in build()
    65 bool autobuildmaps;
    66 /// valid if build from f0 genotype
    67 int f0errorposition;
    68 /// valid if build from f0 genotype
    69 int f0warnposition;
    70 
    71 ModelBuildStatus buildstatus;
    72 /// NULL if the map is not (yet) created
    73 MultiMap *map,*f0map;
    74 
    75 SList parts,joints,neurons;
    76 char partmappingchanged;
     60protected:
     61        Geno geno, f0geno;
     62        char modelfromgenotype;
     63        char f0genoknown;
     64        /// make model map in build()
     65        bool autobuildmaps;
     66        /// valid if build from f0 genotype
     67        int f0errorposition;
     68        /// valid if build from f0 genotype
     69        int f0warnposition;
     70
     71        ModelBuildStatus buildstatus;
     72        /// NULL if the map is not (yet) created
     73        MultiMap *map, *f0map;
     74
     75        SList parts, joints, neurons;
     76        char partmappingchanged;
    7777
    7878#ifdef MODEL_V1_COMPATIBLE
    79 /** NeuroCount value.
    80     compatibility_neurocount = -1 if its value is unknown and the layout is not compatible
    81     @see reorderToOldLayout()
    82 */
    83 int oldneurocount;
    84 char oldconnections;
    85 
    86 /** calculate oldNeuroCount */
    87 void calcOldNeuroCount();
    88 /** some new calls can invalidate old compatibility data */
    89 void invalidateOldNeuroCount() {oldneurocount=-1;}
    90 /**
    91    for compatibility with old NeuroClass the layout of Neurons
    92    is changed when old 'Neuro' accessing methods are in use.
    93    Neurons:
    94    0 .. compatibility_neurocount-1                : old Neurons (class "N")
    95    compatibility_neurocount .. neurons.size()-1   : other units
    96 */
    97 int reorderToOldLayout();
    98 
    99 /** check if compatibility should be preserved */
    100 int hasOldNeuroLayout() {return oldneurocount>=0;}
    101 
    102 /** add inputs to the old "-" units.
    103     @return 1=ok, 0=invalid input detected  */
    104 int addOldConnectionsInputs();
     79        /** NeuroCount value.
     80                compatibility_neurocount = -1 if its value is unknown and the layout is not compatible
     81                @see reorderToOldLayout()
     82                */
     83        int oldneurocount;
     84        char oldconnections;
     85
     86        /** calculate oldNeuroCount */
     87        void calcOldNeuroCount();
     88        /** some new calls can invalidate old compatibility data */
     89        void invalidateOldNeuroCount() {oldneurocount=-1;}
     90        /**
     91           for compatibility with old NeuroClass the layout of Neurons
     92           is changed when old 'Neuro' accessing methods are in use.
     93           Neurons:
     94           0 .. compatibility_neurocount-1                : old Neurons (class "N")
     95           compatibility_neurocount .. neurons.size()-1   : other units
     96           */
     97        int reorderToOldLayout();
     98
     99        /** check if compatibility should be preserved */
     100        int hasOldNeuroLayout() {return oldneurocount>=0;}
     101
     102        /** add inputs to the old "-" units.
     103                @return 1=ok, 0=invalid input detected  */
     104        int addOldConnectionsInputs();
    105105#endif
    106106
    107 void internalCopy(const Model &mod);
    108 
    109 /// make the model from current genotype
    110 void build();
    111 
    112 friend class NeuroNetFactory;
    113 friend class VisualModel;
    114 friend class GLVisualModel;
    115 friend class Creature;
    116 friend class PartBase;
    117 
    118 int checklevel;
    119 
    120   public:
    121 enum Shape {SHAPE_UNKNOWN,SHAPE_ILLEGAL,SHAPE_OLD,SHAPE_NEW};
    122   protected:
    123 Shape shape;
    124 
    125 void updateNeuroRefno(); // set Neuro::refno for all neurons
    126 SString nameForErrors() const;
    127 int internalcheck(int final);
    128 
    129 void moveNeuro(int oldpos,int newpos);
    130 
    131 void init(const Geno &srcgen);
    132 void init();
    133 
    134 void delMap();
    135 void delF0Map();
    136 void initMap();
    137 void initF0Map();
     107        void internalCopy(const Model &mod);
     108
     109        /// make the model from current genotype
     110        void build();
     111
     112        friend class NeuroNetFactory;
     113        friend class VisualModel;
     114        friend class GLVisualModel;
     115        friend class Creature;
     116        friend class PartBase;
     117
     118        int checklevel;
    138119
    139120public:
    140 /** get current model state.
    141 \f[(dot)
    142 digraph M
    143  {
    144  node [fontsize=12]
    145  edge [fontsize=10]
    146  building [label="building = can be modified"]
    147  valid -> building [label="open()"]
    148  building -> valid [label="close()"]
    149  invalid -> building [label="open()"]
    150  building -> invalid [label="close() [failed]"]
    151  empty -> building [label="open()"]
    152  }
    153 \f]
    154 */
    155 ModelBuildStatus getStatus() const {return buildstatus;}
    156 int isValid() const {return buildstatus==valid;}
    157 int getErrorPosition(bool includingwarnings=false);
    158 Shape getShape() {return shape;}
    159 
    160 void updateRefno(); // set ::refno for all elements
    161 
    162 /// The bounding box size. Valid if the model is valid. Read only.
    163 Pt3D size;
    164 
    165 SString vis_style;
    166 double startenergy;
    167 Callback delmodel_list;
    168 ModelUserTags userdata;
    169 
    170 /// Create empty model with invalid empty genotype
    171 Model();
    172 
    173 /** Create a model based on provided genotype
    174    @param buildmaps if not 0, generate mapping information for the model.
    175    default is 0, because mapping uses additional time and memory.
    176    @see getMap()
    177  */
    178 Model(const Geno &src,bool buildmaps=false);
    179 Model(const Model &mod,bool buildmaps=false);
    180 /** duplicate the model.
    181     the resulting object's status is 'building' (opened).
    182     @see getStatus()
    183  */
    184 void operator=(const Model &source);
    185 
    186 /** move all elements from 'source' into our model object.
    187     'source' becomes empty after this operation.
    188     the model will be opened if it is not already open.
    189     @see addElementsFrom(const Model &source);
    190  */
    191 void moveElementsFrom(Model &source);
    192 
    193 /** copy all elements from 'source' into our model object
    194     without affecting the 'source'.
    195     the model will be opened if it is not already open.
    196     @see moveElementsFrom(Model &source);
    197  */
    198 void addElementsFrom(const Model &source)
    199 {Model m(source); moveElementsFrom(m);}
    200 
    201 void operator+=(const Model &source)
    202 {addElementsFrom(source);}
    203 
    204 ~Model();
    205 
    206 /** @return source genotype.
    207     @warn source genotype will not automatically change
    208     when the model is modified. this behaviour is inconsistent
    209     with the previous release. use getF0Geno() if you need
    210     the updated genotype.
    211     @see getF0Geno(), setGeno()
    212 */
    213 const Geno &getGeno() const;
    214 
    215 /// change source genotype
    216 void setGeno(const Geno& newgeno);
    217 
    218 /** @return f0 genotype - generated from current model state
    219     don't use between open()-close()
    220 */
    221 const Geno getF0Geno();
    222 
    223 /// make f0 genotype from current construction (low level version of getF0Geno)
    224 void makeGeno(Geno &,MultiMap *map=0,bool handle_defaults=true);
    225 
    226 /** @return Mapping from source genotype (0-based position in text) to model elements reference numbers.
    227     Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf
    228     The map can be empty if the mapping hasn't been requested earlier (in constructor)
    229     or the converters don't support mapping.
    230     If you create or modify the model using singleStepBuild() or direct manipulation
    231     the map will be not changed or created automatically - it is your responsibility.
    232     @see Model(const Geno &src,int buildmaps=0), singleStepBuild(), PartBase::addMapping()
    233     @see clearMap()
    234     @see convmap
    235 
    236 */
    237 MultiMap &getMap();
    238 
    239 /** Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf
    240     @return mapping from f0 genotype (0-based position in text) to model elements reference numbers
    241  */
    242 const MultiMap &getF0Map();
    243 
    244 /** discard all mapping information for this model.
    245     getMap().clear() also works, but it doesn't remove mappings from model elements.
    246     If there are any mappings, they will be incorporated into model map during close().
    247     @see close(), getMap(), PartBase::clearMapping()
    248  */
    249 void clearMap();
    250 
    251 /** Generate mapping from the current genotype to the f0 genotype.
    252     This works only if both current and f0 maps are already known.
    253     Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf
    254     @see convmap
    255 */
    256 void getCurrentToF0Map(MultiMap& m);
    257 
    258 void setValidationLevel(int level)
    259         {checklevel=level;}
    260 
    261 /// calculate location of the new part connected to the existing one
    262 /// using delta option
    263 Pt3D whereDelta(const Part& start,const Pt3D& rot, const Pt3D& delta);
    264 
    265 /// create the whole model from scratch, using current genotype
    266 void rebuild(bool buildmaps);
    267 
    268 /// setGeno(newgeno); rebuild();
    269 void rebuild(const Geno& newgeno,bool buildmaps) {setGeno(newgeno); rebuild(buildmaps);}
    270 
    271 /// reuse current model object but discard all model data
    272 void clear();
    273 
    274 /** Execute single line of <B>f0</B> genotype.
    275     Return value is non-negative reference number of the created item,
    276     or negative value. reference number can be used to access
    277     the item using getPart(int), getJoint(int) and getNeuroItem(int) methods.
    278     @param line_num optional line number used in error messages
    279     @param srcrange source genotype range which will be mapped to this element
    280 */
    281 int singleStepBuild(const SString &singleline,int line_num,const MultiRange* srcrange=NULL);
    282 /** Execute single line of <B>f0</B> genotype - compatiblity variant */
    283 int singleStepBuild(const SString &singleline,const MultiRange* srcrange=NULL);
    284 /** Execute single line of <B>f0</B> genotype - low level variant, used by Model::build(), error messages returned as string instead of calling logger */
    285 int singleStepBuildNoLog(const SString &singleline,SString& error_message,const MultiRange* srcrange=0);
    286 
    287 /// separate build stages (for future use)
    288 void checkpoint();
    289 
    290 /// call resetDelta() on all joints
    291 void resetAllDelta();
    292 
    293 /// call useDelta() on all joints
    294 void useAllDelta(bool yesno);
    295 
    296 /// Final validity check of the model, all model data has to be available at this point.
    297 /// If the model was modified, the genotype will be also updated.
    298 /// It also calls "validate" with all side effects.
    299 /// @return > 0 means "valid"
    300 int close();
    301 
    302 /// Enable model building.
    303 /// You should use it if you need to create new model, modify the model after close
    304 /// or modify the model created from the genotype.
    305 /// Between open() and close() the model is not fully usable.
    306 void open();
    307 
    308 /// Current model written as f0 genotype while building
    309 /// (not cached, not validated, probably unusable and bad if used before close(). But good for debugging.)
    310 Geno rawGeno();
    311 
    312 /// partial validity check - you can use this call
    313 /// anytime between open - close.
    314 /// this function will check (and repair)
    315 /// - part-joint-neuro connections
    316 /// - model geometry (if "delta option" was used)
    317 /// - physical/biological limits
    318 /// @return 1 = valid
    319 /// @return 0 = invalid
    320 /// validate doesn't make the model fully usable (for simulation)
    321 /// you still need to use close if you have changed anything
    322 int validate();
    323 
    324 int getPartCount() const;
    325 /// you can access parts 0 .. getPartCount()-1.
    326 Part *getPart(int i) const;
    327 
    328 int getJointCount() const;
    329 /// you can access joints 0 .. getJointCount()-1.
    330 Joint *getJoint(int i) const;
    331 
    332 int getNeuroCount() const;
    333 int getConnectionCount() const;
    334 /// you can access neurons 0 .. getNeuroCount()-1.
    335 Neuro *getNeuro(int i) const;
     121        enum Shape { SHAPE_UNKNOWN, SHAPE_ILLEGAL, SHAPE_OLD, SHAPE_NEW };
     122protected:
     123        Shape shape;
     124
     125        void updateNeuroRefno(); // set Neuro::refno for all neurons
     126        SString nameForErrors() const;
     127        int internalcheck(int final);
     128
     129        void moveNeuro(int oldpos, int newpos);
     130
     131        void init(const Geno &srcgen);
     132        void init();
     133
     134        void delMap();
     135        void delF0Map();
     136        void initMap();
     137        void initF0Map();
     138
     139public:
     140        /** get current model state.
     141        \f[(dot)
     142        digraph M
     143        {
     144        node [fontsize=12]
     145        edge [fontsize=10]
     146        building [label="building = can be modified"]
     147        valid -> building [label="open()"]
     148        building -> valid [label="close()"]
     149        invalid -> building [label="open()"]
     150        building -> invalid [label="close() [failed]"]
     151        empty -> building [label="open()"]
     152        }
     153        \f]
     154        */
     155        ModelBuildStatus getStatus() const { return buildstatus; }
     156        int isValid() const { return buildstatus == valid; }
     157        int getErrorPosition(bool includingwarnings = false);
     158        Shape getShape() { return shape; }
     159
     160        void updateRefno(); // set ::refno for all elements
     161
     162        /// The bounding box size. Valid if the model is valid. Read only.
     163        Pt3D size;
     164
     165        SString vis_style;
     166        double startenergy;
     167        Callback delmodel_list;
     168        ModelUserTags userdata;
     169
     170        /// Create empty model with invalid empty genotype
     171        Model();
     172
     173        /** Create a model based on provided genotype
     174           @param buildmaps if not 0, generate mapping information for the model.
     175           default is 0, because mapping uses additional time and memory.
     176           @see getMap()
     177           */
     178        Model(const Geno &src, bool buildmaps = false);
     179        Model(const Model &mod, bool buildmaps = false);
     180        /** duplicate the model.
     181                the resulting object's status is 'building' (opened).
     182                @see getStatus()
     183                */
     184        void operator=(const Model &source);
     185
     186        /** move all elements from 'source' into our model object.
     187                'source' becomes empty after this operation.
     188                the model will be opened if it is not already open.
     189                @see addElementsFrom(const Model &source);
     190                */
     191        void moveElementsFrom(Model &source);
     192
     193        /** copy all elements from 'source' into our model object
     194                without affecting the 'source'.
     195                the model will be opened if it is not already open.
     196                @see moveElementsFrom(Model &source);
     197                */
     198        void addElementsFrom(const Model &source)
     199        {
     200                Model m(source); moveElementsFrom(m);
     201        }
     202
     203        void operator+=(const Model &source)
     204        {
     205                addElementsFrom(source);
     206        }
     207
     208        ~Model();
     209
     210        /** @return source genotype.
     211                @warn source genotype will not automatically change
     212                when the model is modified. this behaviour is inconsistent
     213                with the previous release. use getF0Geno() if you need
     214                the updated genotype.
     215                @see getF0Geno(), setGeno()
     216                */
     217        const Geno &getGeno() const;
     218
     219        /// change source genotype
     220        void setGeno(const Geno& newgeno);
     221
     222        /** @return f0 genotype - generated from current model state
     223                don't use between open()-close()
     224                */
     225        const Geno getF0Geno();
     226
     227        /// make f0 genotype from current construction (low level version of getF0Geno)
     228        void makeGeno(Geno &, MultiMap *map = 0, bool handle_defaults = true);
     229
     230        /** @return Mapping from source genotype (0-based position in text) to model elements reference numbers.
     231                Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf
     232                The map can be empty if the mapping hasn't been requested earlier (in constructor)
     233                or the converters don't support mapping.
     234                If you create or modify the model using singleStepBuild() or direct manipulation
     235                the map will be not changed or created automatically - it is your responsibility.
     236                @see Model(const Geno &src,int buildmaps=0), singleStepBuild(), PartBase::addMapping()
     237                @see clearMap()
     238                @see convmap
     239
     240                */
     241        MultiMap &getMap();
     242
     243        /** Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf
     244                @return mapping from f0 genotype (0-based position in text) to model elements reference numbers
     245                */
     246        const MultiMap &getF0Map();
     247
     248        /** discard all mapping information for this model.
     249                getMap().clear() also works, but it doesn't remove mappings from model elements.
     250                If there are any mappings, they will be incorporated into model map during close().
     251                @see close(), getMap(), PartBase::clearMapping()
     252                */
     253        void clearMap();
     254
     255        /** Generate mapping from the current genotype to the f0 genotype.
     256                This works only if both current and f0 maps are already known.
     257                Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf
     258                @see convmap
     259                */
     260        void getCurrentToF0Map(MultiMap& m);
     261
     262        void setValidationLevel(int level)
     263        {
     264                checklevel = level;
     265        }
     266
     267        /// calculate location of the new part connected to the existing one
     268        /// using delta option
     269        Pt3D whereDelta(const Part& start, const Pt3D& rot, const Pt3D& delta);
     270
     271        /// create the whole model from scratch, using current genotype
     272        void rebuild(bool buildmaps);
     273
     274        /// setGeno(newgeno); rebuild();
     275        void rebuild(const Geno& newgeno, bool buildmaps) { setGeno(newgeno); rebuild(buildmaps); }
     276
     277        /// reuse current model object but discard all model data
     278        void clear();
     279
     280        /** Execute single line of <B>f0</B> genotype.
     281                Return value is non-negative reference number of the created item,
     282                or negative value. reference number can be used to access
     283                the item using getPart(int), getJoint(int) and getNeuroItem(int) methods.
     284                @param line_num optional line number used in error messages
     285                @param srcrange source genotype range which will be mapped to this element
     286                */
     287        int singleStepBuild(const SString &singleline, int line_num, const MultiRange* srcrange = NULL);
     288        /** Execute single line of <B>f0</B> genotype - compatiblity variant */
     289        int singleStepBuild(const SString &singleline, const MultiRange* srcrange = NULL);
     290        /** Execute single line of <B>f0</B> genotype - low level variant, used by Model::build(), error messages returned as string instead of calling logger */
     291        int singleStepBuildNoLog(const SString &singleline, SString& error_message, const MultiRange* srcrange = 0);
     292
     293        /// separate build stages (for future use)
     294        void checkpoint();
     295
     296        /// call resetDelta() on all joints
     297        void resetAllDelta();
     298
     299        /// call useDelta() on all joints
     300        void useAllDelta(bool yesno);
     301
     302        /// Final validity check of the model, all model data has to be available at this point.
     303        /// If the model was modified, the genotype will be also updated.
     304        /// It also calls "validate" with all side effects.
     305        /// @return > 0 means "valid"
     306        int close();
     307
     308        /// Enable model building.
     309        /// You should use it if you need to create new model, modify the model after close
     310        /// or modify the model created from the genotype.
     311        /// Between open() and close() the model is not fully usable.
     312        void open();
     313
     314        /// Current model written as f0 genotype while building
     315        /// (not cached, not validated, probably unusable and bad if used before close(). But good for debugging.)
     316        Geno rawGeno();
     317
     318        /// partial validity check - you can use this call
     319        /// anytime between open - close.
     320        /// this function will check (and repair)
     321        /// - part-joint-neuro connections
     322        /// - model geometry (if "delta option" was used)
     323        /// - physical/biological limits
     324        /// @return 1 = valid
     325        /// @return 0 = invalid
     326        /// validate doesn't make the model fully usable (for simulation)
     327        /// you still need to use close if you have changed anything
     328        int validate();
     329
     330        int getPartCount() const;
     331        /// you can access parts 0 .. getPartCount()-1.
     332        Part *getPart(int i) const;
     333
     334        int getJointCount() const;
     335        /// you can access joints 0 .. getJointCount()-1.
     336        Joint *getJoint(int i) const;
     337
     338        int getNeuroCount() const;
     339        int getConnectionCount() const;
     340        /// you can access neurons 0 .. getNeuroCount()-1.
     341        Neuro *getNeuro(int i) const;
    336342
    337343#ifdef MODEL_V1_COMPATIBLE
    338 /* compatibility calls for accessing old Neuro objects */
    339 
    340 /// @deprecated Neuro class will be removed soon
    341 /// @see compat
    342 int old_getNeuroCount();
    343 /// you can access neurons 0 .. getNeuroCount()-1.
    344 /// @deprecated Neuro class will be removed soon
    345 Neuro *old_getNeuro(int i);
    346 /// @see addNewNeuro, addNeuro
    347 /// @deprecated Neuro class will be removed soon
    348 Neuro *old_addNewNeuro();
    349 /// @return neuro index or -1 if not found
    350 /// @deprecated Neuro class will be removed soon
    351 int old_findNeuro(Neuro* n);
     344        /* compatibility calls for accessing old Neuro objects */
     345
     346        /// @deprecated Neuro class will be removed soon
     347        /// @see compat
     348        int old_getNeuroCount();
     349        /// you can access neurons 0 .. getNeuroCount()-1.
     350        /// @deprecated Neuro class will be removed soon
     351        Neuro *old_getNeuro(int i);
     352        /// @see addNewNeuro, addNeuro
     353        /// @deprecated Neuro class will be removed soon
     354        Neuro *old_addNewNeuro();
     355        /// @return neuro index or -1 if not found
     356        /// @deprecated Neuro class will be removed soon
     357        int old_findNeuro(Neuro* n);
    352358#endif
    353359
    354 /** create new Part and add it to the model. @see addPart()  */
    355 Part *addNewPart(Part::Shape shape=Part::SHAPE_DEFAULT) {return addPart(new Part(shape));}
    356 /** create new Joint and add it to the model. @see addJoint() */
    357 Joint *addNewJoint(Part *p1=NULL,Part *p2=NULL,Joint::Shape shape=Joint::SHAPE_DEFAULT) { Joint *j=addJoint(new Joint()); j->shape=shape; if ((p1!=NULL)&&(p2!=NULL)) j->attachToParts(p1,p2); return j;}
    358 /** create new Neuro and add it to the model. @see addNeuro() */
    359 Neuro *addNewNeuro() {return addNeuro(new Neuro());}
    360 
    361 /** add p to the model. p->refno is adjusted. @return the Part just added (==p). */
    362 Part *addPart(Part *p);
    363 /** add j to the model. j->refno is adjusted. @return the Joint just added (==j). */
    364 Joint *addJoint(Joint *j);
    365 /** add n to the model. n->refno is adjusted. @return the Neuro just added (==n). */
    366 Neuro *addNeuro(Neuro *n);
    367 
    368 /** remove the part from model.
    369     @param removeattachedjoints if not 0 -> remove all joints connected with this part
    370     @param removeattachedneurons if not 0 -> remove neurons attached to this part */
    371 void removePart(int partindex,int removeattachedjoints=1,int removeattachedneurons=1);
    372 
    373 /** remove the joint from model.
    374     @param removeattachedneurons if not 0 -> remove neurons attached to this joint */
    375 void removeJoint(int jointindex,int removeattachedneurons=1);
    376 
    377 /** remove the neuron from model.
    378     @param removereferences if true -> look for references to this neuron
    379     (i.e. connections from other neurons) and remove them as well */
    380 void removeNeuro(int neuroindex,bool removereferences=true);
    381 
    382 void removeNeuros(SList &nlist);
    383 
    384 /// @return part index or -1 if not found in the model
    385 int findPart(Part* p);
    386 /// @return joint index or -1 if not found in the model
    387 int findJoint(Joint* j);
    388 /// @return neuro index or -1 if not found in the model
    389 int findNeuro(Neuro* nu);
    390 /// @return joint index or -1 if not found in the model
    391 int findJoint(Part *p1, Part *p2);
    392 
    393 /** make the list of neuros satisfying given search criteria: classname,part,joint
    394     @param result objects will be appended here
    395     @return number of objects found  */
    396 int findNeuros(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0);
    397 
    398 /** search for joints connected to the part
    399     @param result objects will be appended here
    400     @return number of objects found  */
    401 int findJoints(SList& result,const Part* part=0);
    402 
    403 void disturb(double amount);
    404 void move(const Pt3D& shift);
    405 /// rotate around the origin (move-rotate-move to rotate around arbitrary point)
    406 void rotate(const Orient& rotation);
    407 /// rotate around the origin (move-rotate-move to rotate around arbitrary point)
    408 void rotate(const Pt3D& angles) {Orient o=Orient_1; o.rotate(angles); rotate(o);}
    409 
    410 /// build this model using new shapes, based on the provided model that uses old shapes. See also shapeconvert.cpp.
    411 void buildUsingNewShapes(const Model& src_old_shapes, Part::Shape default_shape = Part::SHAPE_CYLINDER, float thickness = 0.2);
     360        /** create new Part and add it to the model. @see addPart()  */
     361        Part *addNewPart(Part::Shape shape = Part::SHAPE_DEFAULT) { return addPart(new Part(shape)); }
     362        /** create new Joint and add it to the model. @see addJoint() */
     363        Joint *addNewJoint(Part *p1 = NULL, Part *p2 = NULL, Joint::Shape shape = Joint::SHAPE_DEFAULT) { Joint *j = addJoint(new Joint()); j->shape = shape; if ((p1 != NULL) && (p2 != NULL)) j->attachToParts(p1, p2); return j; }
     364        /** create new Neuro and add it to the model. @see addNeuro() */
     365        Neuro *addNewNeuro() { return addNeuro(new Neuro()); }
     366
     367        /** add p to the model. p->refno is adjusted. @return the Part just added (==p). */
     368        Part *addPart(Part *p);
     369        /** add j to the model. j->refno is adjusted. @return the Joint just added (==j). */
     370        Joint *addJoint(Joint *j);
     371        /** add n to the model. n->refno is adjusted. @return the Neuro just added (==n). */
     372        Neuro *addNeuro(Neuro *n);
     373
     374        /** remove the part from model.
     375                @param removeattachedjoints if not 0 -> remove all joints connected with this part
     376                @param removeattachedneurons if not 0 -> remove neurons attached to this part */
     377        void removePart(int partindex, int removeattachedjoints = 1, int removeattachedneurons = 1);
     378
     379        /** remove the joint from model.
     380                @param removeattachedneurons if not 0 -> remove neurons attached to this joint */
     381        void removeJoint(int jointindex, int removeattachedneurons = 1);
     382
     383        /** remove the neuron from model.
     384                @param removereferences if true -> look for references to this neuron
     385                (i.e. connections from other neurons) and remove them as well */
     386        void removeNeuro(int neuroindex, bool removereferences = true);
     387
     388        void removeNeuros(SList &nlist);
     389
     390        /// @return part index or -1 if not found in the model
     391        int findPart(Part* p);
     392        /// @return joint index or -1 if not found in the model
     393        int findJoint(Joint* j);
     394        /// @return neuro index or -1 if not found in the model
     395        int findNeuro(Neuro* nu);
     396        /// @return joint index or -1 if not found in the model
     397        int findJoint(Part *p1, Part *p2);
     398
     399        /** make the list of neuros satisfying given search criteria: classname,part,joint
     400                @param result objects will be appended here
     401                @return number of objects found  */
     402        int findNeuros(SList& result, const char* classname = 0, const Part* part = 0, const Joint* joint = 0);
     403
     404        /** search for joints connected to the part
     405                @param result objects will be appended here
     406                @return number of objects found  */
     407        int findJoints(SList& result, const Part* part = 0);
     408
     409        void disturb(double amount);
     410        void move(const Pt3D& shift);
     411        /// rotate around the origin (move-rotate-move to rotate around arbitrary point)
     412        void rotate(const Orient& rotation);
     413        /// rotate around the origin (move-rotate-move to rotate around arbitrary point)
     414        void rotate(const Pt3D& angles) { Orient o = Orient_1; o.rotate(angles); rotate(o); }
     415
     416        /// build this model using new shapes, based on the provided model that uses old shapes. See also shapeconvert.cpp.
     417        void buildUsingNewShapes(const Model& src_old_shapes, Part::Shape default_shape = Part::SHAPE_CYLINDER, float thickness = 0.2);
    412418
    413419#ifdef EASYMAPDEBUG
    414 static int partToMap(int i) {return 0+i;}
    415 static int jointToMap(int i) {return 10+i;}
    416 static int neuroToMap(int i) {return 20+i;}
    417 static int mapToPart(int i) {return i-0;}
    418 static int mapToJoint(int i) {return i-10;}
    419 static int mapToNeuro(int i) {return i-20;}
     420        static int partToMap(int i) {return 0+i;}
     421        static int jointToMap(int i) {return 10+i;}
     422        static int neuroToMap(int i) {return 20+i;}
     423        static int mapToPart(int i) {return i-0;}
     424        static int mapToJoint(int i) {return i-10;}
     425        static int mapToNeuro(int i) {return i-20;}
    420426#else
    421 static int partToMap(int i) {return 0x10000000+i;}
    422 static int jointToMap(int i) {return 0x20000000+i;}
    423 static int neuroToMap(int i) {return 0x30000000+i;}
    424 static int mapToPart(int i) {return i-0x10000000;}
    425 static int mapToJoint(int i) {return i-0x20000000;}
    426 static int mapToNeuro(int i) {return i-0x30000000;}
     427        static int partToMap(int i) { return 0x10000000 + i; }
     428        static int jointToMap(int i) { return 0x20000000 + i; }
     429        static int neuroToMap(int i) { return 0x30000000 + i; }
     430        static int mapToPart(int i) { return i - 0x10000000; }
     431        static int mapToJoint(int i) { return i - 0x20000000; }
     432        static int mapToNeuro(int i) { return i - 0x30000000; }
    427433#endif
    428434
    429 static void makeGenToGenMap(MultiMap& result,const MultiMap& gen1tomodel,const MultiMap& gen2tomodel);
    430 
    431 ///////////////////////////
    432 
    433 static Part& getMinPart();
    434 static Part& getMaxPart();
    435 static Part& getDefPart();
    436 static Joint& getMinJoint();
    437 static Joint& getMaxJoint();
    438 static Joint& getDefJoint();
    439 static Neuro& getMinNeuro();
    440 static Neuro& getMaxNeuro();
    441 static Neuro& getDefNeuro();
     435        static void makeGenToGenMap(MultiMap& result, const MultiMap& gen1tomodel, const MultiMap& gen2tomodel);
     436
     437        ///////////////////////////
     438
     439        static Part& getMinPart();
     440        static Part& getMaxPart();
     441        static Part& getDefPart();
     442        static Joint& getMinJoint();
     443        static Joint& getMaxJoint();
     444        static Joint& getDefJoint();
     445        static Neuro& getMinNeuro();
     446        static Neuro& getMaxNeuro();
     447        static Neuro& getDefNeuro();
    442448};
    443449
Note: See TracChangeset for help on using the changeset viewer.