source: cpp/frams/genetics/f9/conv_f9.cpp @ 168

Last change on this file since 168 was 168, checked in by sz, 6 years ago

reformatting

  • Property svn:eol-style set to native
File size: 4.9 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "conv_f9.h"
6#include <frams/model/model.h>
7#include <string.h>
8#include <common/nonstd_stl.h> //ARRAY_LENGTH
9
10#define APPLY_DETERMINISTIC_BODY_NOISE //this representation easily produces perfectly vertical sticks that would stay upright forever. In most cases such infinite perfection is not desired, so we make the construct less perfect by perturbing its coordinates.
11
12GenoConv_f90::GenoConv_f90()
13{
14        name = "Turtle3D-ortho encoding";
15        in_format = '9';
16        out_format = '0';
17        mapsupport = 0; //would be easy and nice to add!
18}
19
20
21const char* turtle_commands_f9 = "LRDUBF";
22
23//const char* turtle_commandsX_f9="-+0000";
24//const char* turtle_commandsY_f9="00-+00";
25//const char* turtle_commandsZ_f9="0000-+";
26
27SString GenoConv_f90::convert(SString &in, MultiMap *map)
28{
29        vector<XYZ_LOC> vertices;
30        XYZ_LOC current;
31        Model m;
32        m.open();
33        int recently_added = addSegment(m, vertices, current, 0xDead);
34        for (int i = 0; i < in.len(); i++)
35        {
36                char command = in[i];
37                char *ptr = strchr((char*)turtle_commands_f9, command);
38                if (ptr)
39                {
40                        int delta[] = { 0, 0, 0 };
41                        int pos = ptr - turtle_commands_f9;
42                        int axis = pos / 2;
43                        int dir = pos % 2;
44                        (*(delta + axis)) += dir * 2 - 1; //+1 or -1 in the given axis
45                        current.add(delta);
46                        recently_added = addSegment(m, vertices, current, recently_added);
47                }
48        }
49#ifdef APPLY_DETERMINISTIC_BODY_NOISE
50        perturbPartLocations(m);
51#endif
52        setColors(m);
53        m.close();
54        if (m.getPartCount() < 2) //only one part <=> there were no valid turtle commands in the input genotype
55                return ""; //so we return an invalid f0 genotype
56        return m.getF0Geno().getGene();
57}
58
59int GenoConv_f90::addSegment(Model &m, vector<XYZ_LOC> &vertices, const XYZ_LOC &new_vertex, int recently_added)
60{
61        if (vertices.size() < 1) //empty model?
62        {
63                return addNewVertex(m, vertices, new_vertex);
64        }
65        else
66        {
67                int vertex_here = findVertexAt(vertices, new_vertex);
68                if (vertex_here < 0) //need to create a new Part
69                {
70                        vertex_here = addNewVertex(m, vertices, new_vertex);
71                } //else there already exists a Part in new_vertex; new Joint may or may not be needed
72                Part *p1 = m.getPart(recently_added);
73                Part *p2 = m.getPart(vertex_here);
74                if (m.findJoint(p1, p2) < 0 && m.findJoint(p2, p1) < 0) //new Joint needed? should always be true if we just created a new Part (vertex_here was <0)
75                {
76                        m.addNewJoint(p1, p2);
77                }
78                return vertex_here;
79        }
80}
81
82int GenoConv_f90::findVertexAt(vector<XYZ_LOC> &vertices, const XYZ_LOC &vertex)
83{
84        for (int i = 0; i < vertices.size(); i++)
85                if (vertices[i].same_coordinates(vertex)) return i;
86        return -1;
87}
88
89
90int GenoConv_f90::addNewVertex(Model &m, vector<XYZ_LOC> &vertices, const XYZ_LOC &new_vertex)
91{
92        Part *p = new Part;
93        p->p.x = new_vertex.x;
94        p->p.y = new_vertex.y;
95        p->p.z = new_vertex.z;
96        m.addPart(p);
97
98        vertices.push_back(new_vertex);
99        return vertices.size() - 1;
100}
101
102double mix(int *colortab, int maxind, double ind)
103{
104        int indpre = (int)ind;
105        int indpost = indpre + 1;
106        if (indpost > maxind) indpost = maxind;
107        int v1 = colortab[indpre];
108        int v2 = colortab[indpost];
109        double d1 = ind - indpre;
110        double d2 = indpost - ind;
111        double v = indpre == indpost ? v1 : d2*v1 + d1*v2; //d1+d2==1
112        return v;
113}
114
115void GenoConv_f90::setColors(Model &m) //sets fixed (independent from genes) colors and widths on a model, purely for aesthetic purposes
116{
117        //a rainbow on Joints: from the first one red, through middle green, to blue or violet - last
118        static int r[] = { 1, 1, 0, 0, 0, 1 };
119        static int g[] = { 0, 1, 1, 1, 0, 0 };
120        static int b[] = { 0, 0, 0, 1, 1, 1 };
121        int maxind = ARRAY_LENGTH(r) - 1;
122
123        int joints_count = m.getJointCount();
124        for (int i = 0; i < joints_count; i++)
125        {
126                Joint *j = m.getJoint(i);
127                double x = joints_count < 2 ? 0 : (double)i / (joints_count - 1); //0..1, postion in the rainbow
128                double ind = x*maxind;
129                j->vcolor.x = mix(r, maxind, ind);
130                j->vcolor.y = mix(g, maxind, ind);
131                j->vcolor.z = mix(b, maxind, ind);
132        }
133
134        int parts_count = m.getPartCount();
135        SList jlist;
136        for (int i = 0; i<parts_count; i++)
137        {
138                Part *p = m.getPart(i);
139                jlist.clear();
140                int count = m.findJoints(jlist, p);
141                Pt3D averagecolor(0, 0, 0); //Parts will get averaged colors from all attached Joints
142                FOREACH(Joint*, j, jlist)
143                        averagecolor += j->vcolor;
144                p->vcolor = averagecolor / count;
145                if (count>5) count = 5; //avoid too fat...
146                p->vsize = 0.3 + count / 15.0; //the more Joints is attached to a Part, the fatter it is
147        }
148}
149
150void GenoConv_f90::perturbPartLocations(Model &m) //deterministic "body noise", see APPLY_DETERMINISTIC_BODY_NOISE
151{
152        for (int i = 0; i < m.getPartCount(); i++)
153        {
154                Part *p = m.getPart(i);
155                Pt3D noise(
156                        ((i + 1) % 10) - 4.5,
157                        ((3 * i + 5) % 10) - 4.5,
158                        ((7 * i + 2) % 10) - 4.5
159                        ); //-4.5 .. 4.5 in each axis
160                p->p += noise / 1000;
161        }
162}
Note: See TracBrowser for help on using the repository browser.