source: cpp/frams/model/model.h @ 227

Last change on this file since 227 was 197, checked in by Maciej Komosinski, 11 years ago

GDK used by developers since 1999, distributed on the web since 2002

  • Property svn:eol-style set to native
File size: 13.4 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#ifndef _MODEL_H_
6#define _MODEL_H_
7
8#include <common/nonstd_math.h>
9#include <stdlib.h>
10#include <stdio.h>
11
12#include "modelparts.h"
13#include <frams/util/advlist.h>
14#include <frams/util/usertags.h>
15
16extern ParamEntry f0_model_paramtab[];
17
18//#define EASYMAPDEBUG
19
20enum ModelBuildStatus {empty,building,invalid,valid};
21
22class MultiMap;
23
24class VisualModel;
25
26/**
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)
45digraph 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
59{
60  protected:
61Geno geno,f0geno;
62char modelfromgenotype;
63char f0genoknown;
64/// make model map in build()
65bool autobuildmaps;
66/// valid if build from f0 genotype
67int f0errorposition;
68/// valid if build from f0 genotype
69int f0warnposition;
70
71ModelBuildStatus buildstatus;
72/// NULL if the map is not (yet) created
73MultiMap *map,*f0map;
74
75SList parts,joints,neurons;
76char partmappingchanged;
77
78#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*/
83int oldneurocount;
84char oldconnections;
85
86/** calculate oldNeuroCount */
87void calcOldNeuroCount();
88/** some new calls can invalidate old compatibility data */
89void 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*/
97int reorderToOldLayout();
98
99/** check if compatibility should be preserved */
100int hasOldNeuroLayout() {return oldneurocount>=0;}
101
102/** add inputs to the old "-" units.
103    @return 1=ok, 0=invalid input detected  */
104int addOldConnectionsInputs();
105#endif
106
107void internalCopy(const Model &mod);
108
109/// make the model from current genotype
110void build();
111
112friend class NeuroNetFactory;
113friend class VisualModel;
114friend class GLVisualModel;
115friend class Creature;
116friend class PartBase;
117
118int checklevel;
119
120void updateNeuroRefno(); // set Neuro::refno for all neurons
121int internalcheck(int final);
122
123void moveNeuro(int oldpos,int newpos);
124
125void init(const Geno &srcgen);
126void init();
127
128void delMap();
129void delF0Map();
130void initMap();
131void initF0Map();
132
133public:
134/** get current model state.
135\f[(dot)
136digraph M
137 {
138 node [fontsize=12]
139 edge [fontsize=10]
140 building [label="building = can be modified"]
141 valid -> building [label="open()"]
142 building -> valid [label="close()"]
143 invalid -> building [label="open()"]
144 building -> invalid [label="close() [failed]"]
145 empty -> building [label="open()"]
146 }
147\f]
148*/
149ModelBuildStatus getStatus() const {return buildstatus;}
150int isValid() const {return buildstatus==valid;}
151int getErrorPosition(bool includingwarnings=false);
152
153void updateRefno(); // set ::refno for all elements
154
155/// The bounding box size. Valid if the model is valid. Read only.
156Pt3D size;
157
158SString vis_style;
159double startenergy;
160Callback delmodel_list;
161ModelUserTags userdata;
162
163/// Create empty model with invalid empty genotype
164Model();
165
166/** Create a model based on provided genotype
167   @param buildmaps if not 0, generate mapping information for the model.
168   default is 0, because mapping uses additional time and memory.
169   @see getMap()
170 */
171Model(const Geno &src,bool buildmaps=false);
172Model(const Model &mod,bool buildmaps=false);
173/** duplicate the model.
174    the resulting object's status is 'building' (opened).
175    @see getStatus()
176 */
177void operator=(const Model &source);
178
179/** move all elements from 'source' into our model object.
180    'source' becomes empty after this operation.
181    the model will be opened if it is not already open.
182    @see addElementsFrom(const Model &source);
183 */
184void moveElementsFrom(Model &source);
185
186/** copy all elements from 'source' into our model object
187    without affecting the 'source'.
188    the model will be opened if it is not already open.
189    @see moveElementsFrom(Model &source);
190 */
191void addElementsFrom(const Model &source)
192{Model m(source); moveElementsFrom(m);}
193
194void operator+=(const Model &source)
195{addElementsFrom(source);}
196
197~Model();
198
199/** @return source genotype.
200    @warn source genotype will not automatically change
201    when the model is modified. this behaviour is inconsistent
202    with the previous release. use getF0Geno() if you need
203    the updated genotype.
204    @see getF0Geno(), setGeno()
205*/
206const Geno &getGeno() const;
207
208/// change source genotype
209void setGeno(const Geno& newgeno);
210
211/** @return f0 genotype - generated from current model state
212    don't use between open()-close()
213*/
214const Geno getF0Geno();
215
216/// make f0 genotype from current construction (low level version of getF0Geno)
217void makeGeno(Geno &,MultiMap *map=0,bool handle_defaults=true);
218
219/** @return mapping from source genotype (0-based position in text) to model elements reference numbers.
220    the map can be empty if the mapping hasn't been requested earlier (in constructor)
221    or the converters don't support mapping.
222    if you create or modify the model using singleStepBuild() or direct manipulation
223    the map will be not changed or created automatically - it is your responsibility.
224    @see Model(const Geno &src,int buildmaps=0), singleStepBuild(), PartBase::addMapping()
225    @see clearMap()
226    @see convmap
227
228*/
229MultiMap &getMap();
230
231/** @return mapping from f0 genotype (0-based position in text) to model elements reference numbers
232 */
233const MultiMap &getF0Map();
234
235/** discard all mapping information for this model.
236    getMap().clear() also works, but it doesn't remove mappings from model elements.
237    if there are any, the will be incorporated into model map during close().
238    @see close(), getMap(), PartBase::clearMapping()
239 */
240void clearMap();
241
242/** generate mapping from the current genotype to the f0 genotype.
243    this works only if both current and f0 maps are already known.
244    @see convmap
245*/
246void getCurrentToF0Map(MultiMap& m);
247
248void setValidationLevel(int level)
249        {checklevel=level;}
250
251/// calculate location of the new part connected to the existing one
252/// using delta option
253Pt3D whereDelta(const Part& start,const Pt3D& rot, const Pt3D& delta);
254
255/// create the whole model from scratch, using current genotype
256void rebuild(bool buildmaps);
257
258/// setGeno(newgeno); rebuild();
259void rebuild(const Geno& newgeno,bool buildmaps) {setGeno(newgeno); rebuild(buildmaps);}
260
261/// reuse current model object but discard all model data
262void clear();
263
264/** execute single line of <B>f0</B> genotype.
265    return value is non-negative reference number of the created item,
266    or negative value. reference number can be used to access
267    the item using getPart(int), getJoint(int) and getNeuroItem(int) methods.
268    @param srcrange source genotype range which will be mapped to this element
269*/
270int singleStepBuild(const SString &singleline,const MultiRange* srcrange=0);
271
272/// separate build stages (for future use)
273void checkpoint();
274
275/// call resetDelta() on all joints
276void resetAllDelta();
277
278/// call useDelta() on all joints
279void useAllDelta(bool yesno);
280
281/// final validity check of the model, all model data has to be available at this point.
282/// if the model was modified, the genotype will be also updated.
283/// it also calls "validate" with all side effects.
284/// @return > 0 means "valid"
285int close();
286
287/// enable model building.
288/// you should use it if you need to create new model, modify the model after close
289/// or modify the model created from the genotype.
290/// between open() and close() the model is not fully usable,
291void open();
292
293/// current model written as f0 genotype while building
294/// (not cached, not validated, probably unusable and bad if used before close(). but good for debugging.)
295Geno rawGeno();
296
297/// partial validity check - you can use this call
298/// anytime between open - close.
299/// this function will check (and repair)
300/// - part-joint-neuro connections
301/// - model geometry (if "delta option" was used)
302/// - physical/biological limits
303/// @return 1 = valid
304/// @return 0 = invalid
305/// validate doesn't make the model fully usable (for simulation)
306/// you still need to use close if you have changed anything
307int validate();
308
309int getPartCount() const;
310/// you can access parts 0 .. getPartCount()-1.
311Part *getPart(int i) const;
312
313int getJointCount() const;
314/// you can access joints 0 .. getJointCount()-1.
315Joint *getJoint(int i) const;
316
317int getNeuroCount() const;
318int getConnectionCount() const;
319/// you can access neurons 0 .. getNeuroCount()-1.
320Neuro *getNeuro(int i) const;
321
322#ifdef MODEL_V1_COMPATIBLE
323/* compatibility calls for accessing old Neuro objects */
324
325/// @deprecated Neuro class will be removed soon
326/// @see compat
327int old_getNeuroCount();
328/// you can access neurons 0 .. getNeuroCount()-1.
329/// @deprecated Neuro class will be removed soon
330Neuro *old_getNeuro(int i);
331/// @see addNewNeuro, addNeuro
332/// @deprecated Neuro class will be removed soon
333Neuro *old_addNewNeuro();
334/// @return neuro index or -1 if not found
335/// @deprecated Neuro class will be removed soon
336int old_findNeuro(Neuro* n);
337#endif
338
339/** create new Part and add it to the model. @see addPart()  */
340Part *addNewPart(Part::Shape shape=Part::SHAPE_DEFAULT) {return addPart(new Part(shape));}
341/** create new Joint and add it to the model. @see addJoint() */
342Joint *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;}
343/** create new Neuro and add it to the model. @see addNeuro() */
344Neuro *addNewNeuro() {return addNeuro(new Neuro());}
345
346/** add p to the model. p->refno is adjusted. @return the Part just added (==p). */
347Part *addPart(Part *p);
348/** add j to the model. j->refno is adjusted. @return the Joint just added (==j). */
349Joint *addJoint(Joint *j);
350/** add n to the model. n->refno is adjusted. @return the Neuro just added (==n). */
351Neuro *addNeuro(Neuro *n);
352
353/** remove the part from model.
354    @param removeattachedjoints if not 0 -> remove all joints connected with this part
355    @param removeattachedneurons if not 0 -> remove neurons attached to this part */
356void removePart(int partindex,int removeattachedjoints=1,int removeattachedneurons=1);
357
358/** remove the joint from model.
359    @param removeattachedneurons if not 0 -> remove neurons attached to this joint */
360void removeJoint(int jointindex,int removeattachedneurons=1);
361
362/** remove the neuron from model.
363    @param removereferences if true -> look for references to this neuron
364    (i.e. connections from other neurons) and remove them as well */
365void removeNeuro(int neuroindex,bool removereferences=true);
366
367void removeNeuros(SList &nlist);
368
369/// @return part index or -1 if not found in the model
370int findPart(Part* p);
371/// @return joint index or -1 if not found in the model
372int findJoint(Joint* j);
373/// @return neuro index or -1 if not found in the model
374int findNeuro(Neuro* nu);
375/// @return joint index or -1 if not found in the model
376int findJoint(Part *p1, Part *p2);
377
378/** make the list of neuros satisfying given search criteria: classname,part,joint
379    @param result objects will be appended here
380    @return number of objects found  */
381int findNeuros(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0);
382
383/** search for joints connected to the part
384    @param result objects will be appended here
385    @return number of objects found  */
386int findJoints(SList& result,const Part* part=0);
387
388void disturb(double amount);
389
390#ifdef EASYMAPDEBUG
391static int partToMap(int i) {return 0+i;}
392static int jointToMap(int i) {return 10+i;}
393static int neuroToMap(int i) {return 20+i;}
394static int mapToPart(int i) {return i-0;}
395static int mapToJoint(int i) {return i-10;}
396static int mapToNeuro(int i) {return i-20;}
397#else
398static int partToMap(int i) {return 0x10000000+i;}
399static int jointToMap(int i) {return 0x20000000+i;}
400static int neuroToMap(int i) {return 0x30000000+i;}
401static int mapToPart(int i) {return i-0x10000000;}
402static int mapToJoint(int i) {return i-0x20000000;}
403static int mapToNeuro(int i) {return i-0x30000000;}
404#endif
405
406static void makeGenToGenMap(MultiMap& result,const MultiMap& gen1tomodel,const MultiMap& gen2tomodel);
407
408///////////////////////////
409
410static Part& getMinPart();
411static Part& getMaxPart();
412static Part& getDefPart();
413static Joint& getMinJoint();
414static Joint& getMaxJoint();
415static Joint& getDefJoint();
416static Neuro& getMinNeuro();
417static Neuro& getMaxNeuro();
418static Neuro& getDefNeuro();
419};
420
421#endif
Note: See TracBrowser for help on using the repository browser.