Visualisierung2
L_System.cpp
Go to the documentation of this file.
1 #include "L_System.h"
10 L_System::L_System(int w, int h, std::string t)
11 {
12  //set parameter
13  width = w; height = h;
14  segmentcount = 0;
15  type = t;
16 
17  initCurve(width, height); //initialize the standart curve
18 
19  // initialize the indivitual curveparameters
20  if(strcmp(type.c_str(),"hilbert")==0)
21  {
22  initHilbert();
23  }
24  if(strcmp(type.c_str(),"gosper")==0)
25  {
26  initGosper();
27  }
28 
29  // initialize the needed buffers
30  GLuint posbuf;
31  glGenBuffers(1, &posbuf);
32  glBindBuffer(GL_ARRAY_BUFFER, posbuf);
33  glBufferData(GL_ARRAY_BUFFER, positioncount[0] * sizeof(float), &points[0][0], GL_STATIC_DRAW);
34  glBindBuffer(GL_ARRAY_BUFFER, 0);
35 
36  GLuint vaobuf;
37  glGenVertexArrays(1,&vaobuf);
38  glBindVertexArray(vaobuf);
39 
40  glBindBuffer(GL_ARRAY_BUFFER, posbuf);
41  glEnableVertexAttribArray(0);
42  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
43  positionBuffer.push_back(posbuf);
44  vao.push_back(vaobuf);
45 
46  glBindVertexArray(0);
47  glBindBuffer(GL_ARRAY_BUFFER, 0);
48 }
49 
54 {
55  distance = std::min(width,height); //set length for the curvesegments
56  double poscount = 4 * 3; //set the positioncount
57  positioncount.push_back(poscount);
58  iteration = 1; //initialize the current maximum order
59  drawingIteration = iteration - 1; //initialize the current order, whitch will be drawend
60 
61  //initialize a curve for order 0
62  glm::vec3 point;
63  std::vector<glm::vec3> pos;
64  point = glm::vec3(-0.9f,-0.9f,0.0f);
65  pos.push_back(point);
66  point = glm::vec3(-0.9f,0.9f,0.0f);
67  pos.push_back(point);
68  point = glm::vec3(0.9f,0.9f,0.0f);
69  pos.push_back(point);
70  point = glm::vec3(0.9f,-0.9f,0.0f);
71  pos.push_back(point);
72 
73  points.push_back(pos);
74 }
79 {
80  rules.clear(); //clear rules
81  delta = 90; //90 degrees
82  //set up the rules for the hilbert curve
83  currentString = "L";
84  std::string rule1 = "L->+RF-LFL-FR+";
85  rules.push_back(rule1);
86  std::string rule2 = "R->-LF+RFR+FL-";
87  rules.push_back(rule2);
88 
89  iterate(); //make an initial iteration
90 }
95 {
96  rules.clear(); //clear rules
97  delta = 60; //60 degrees
98  //set up the rules for the gosper curve
99  currentString = "RF";
100  //std::string rule1 = "L->LF-RF--RF+LF++LFLF+RF-";
101  std::string rule1 = "L->L+RF++RF-FL--FLFL-RF+";
102  rules.push_back(rule1);
103  //std::string rule2 = "R->+LF-RFRF--RF-LF++LF+RF";
104  std::string rule2 = "R->-FL+RFRF++RF+FL--FL-R";
105  rules.push_back(rule2);
106 
107  iterate(); //make an initial iteration
108 }
109 
113 std::string L_System::getRule(char var)
114 {
115  for (int i = 0; i < rules.size(); i++) //searching for a rule of char
116  {
117  std::string rule = rules[i];
118  if (rule[0] == var) //if a rule exists. return it
119  return rules[i].substr(3,rules[i].length());
120  }
121  return std::string(&var); //otherwise return the char
122 }
123 
125 {
126  for(int i = 0; i < positionBuffer.size();i++) //free the space of the buffers
127  {
128  glDeleteBuffers(1, &positionBuffer[i]);
129  glDeleteVertexArrays(1, &vao[i]);
130  }
131 }
132 
136 void L_System::draw(GLuint shader)
137 {
138  //set the color for the curve in the shader
139  auto baseColor_location = glGetUniformLocation(shader, "color");
140  glUniform4f(baseColor_location, 0.0f, 0.5f, 0.0f, 1.0f);
141 
142  //draw the curve with linewidth 2.0
143  glLineWidth(2.0);
144  glBindVertexArray(vao[drawingIteration]);
145  glDrawArrays(GL_LINE_STRIP,0, positioncount[drawingIteration]/3);
146  glBindVertexArray(0);
147  glLineWidth(1.0);
148 }
152 double L_System::degToRad(double angle)
153 {
154  return (M_PI * angle) / 180;
155 }
160 {
161  return segmentcount;
162 }
167 {
168  return iteration-1;
169 }
174 {
175  return drawingIteration;
176 }
181 {
182  if(order < iteration-1)
183  {
184  drawingIteration = order+1;
185  }
186 }
190 std::string L_System::getType()
191 {
192  return type;
193 }
198 {
199  if(drawingIteration == (iteration-1)) //if the current drawing order equal the current maximum order, calculate the points for the new maximal order
200  {
201  iterate();
202  }else{
203  drawingIteration++; //otherwise increase the drawing order by one
204  }
205 }
210 {
211  if (drawingIteration > 1) //if the current drawing order grater than 1, decrease the order by one
212  {
214  }
215 }
219 std::vector<glm::vec3> L_System::getPoints(int order)
220 {
221  if((order+1) >= iteration) //if order is grater than the current maximum order. Calculate all orders up to the given order
222  {
223  for(int i = 0; i < ((order+2) - iteration);i++)
224  {
225  iterate();
226  }
227  }
228  return points[order+1]; //return the points
229 }
234 {
235  iteration++; //increase the current maximum order
236  drawingIteration = iteration - 1; //update the current drawing order
237  //set up the length of the curve segments, dependent on the curve type
238  // It would be better to get the maximum and minimum position of the Curve and map them into the rigth space. But i have no time for this. Maybe in the next version
239  if(iteration > 0)
240  {
241  if(strcmp(type.c_str(),"hilbert")==0)
242  {
243  double nenner = std::pow(2,(iteration+1));
244  distance = (1.8/(nenner-1)) * 8;
245  }
246  if(strcmp(type.c_str(),"gosper")==0)
247  {
248  double nenner = std::pow(2.7,(iteration+1));
249  distance = (1.8/(nenner-1)) * 16;
250  }
251  }
252 
253  //set up a new state and outstring
254  std::string tmp = "" ;
255  state dummystate(-0.9f,-0.9f,0);
256  std::vector<glm::vec3> dummypoints;
257 
258  //set up the individual starting points
259  if(strcmp(type.c_str(),"hilbert")==0)
260  {
261  segmentcount = pow(4,(iteration-1))-1;
262  dummystate.x = -0.9f;
263  dummystate.y = -0.9f;
264  }
265  if(strcmp(type.c_str(),"gosper")==0)
266  {
267  segmentcount = (int)pow(7,(iteration-1));
268  dummystate.x = -0.7f + (float)(iteration - 3)/25;
269  dummystate.y = 0.0f - (float)(iteration - 3)/5;
270  }
271 
272  glm::vec3 dummypoint;
273  dummypoint = glm::vec3(dummystate.x, dummystate.y, 0.0f);
274  dummypoints.push_back(dummypoint);
275 
276  for (int i = 0; i < currentString.length(); i++) //iterate threw the current string
277  {
278  switch (currentString[i])
279  {
280  case 'F': //F means draw a Curve segment. In this project, there is no need to check if F has a rule. Would only need time.
281  {
282  /*int index = existRule(text[i]);
283  if (index > -1)
284  {
285  tmp += rules[index];
286  }
287  else
288  {*/
289  //
290  dummystate.x += distance * std::cos(degToRad(dummystate.angle));
291  dummystate.y += distance * std::sin(degToRad(dummystate.angle));
292  tmp += 'F';
293 
294  glm::vec3 dummypoint;
295  dummypoint = glm::vec3(dummystate.x, dummystate.y, 0.0f);
296  dummypoints.push_back(dummypoint);
297  //}
298 
299  break;
300  }
301  /*case 'f': //f means go further in the curve without drawing. Until there are no holes in the space filling curves, there is no need to check for this
302  {
303  dummy.x += distance * Math.Cos(degToRad(dummy.angle));
304  dummy.y += distance * Math.Sin(degToRad(dummy.angle));
305 
306  int index = existRule(text[i]);
307  if (index > -1)
308  {
309  tmp += rules[index];
310  }
311  else
312  {
313  tmp += 'f';
314  }
315  break;
316  }*/
317  case '+': //+ means rotate the angle for the next line segment
318  {
319  dummystate.angle += delta;
320  tmp += '+';
321  break;
322  }
323  case '-': //- means rotate the angle for the next line segment
324  {
325  dummystate.angle -= delta;
326  tmp += '-';
327  break;
328  }
329  /*
330  // [,] are operators to split the curves in subcurves an go threw every subcurve in each iterations. Space filling curves doesnt have this, so check this only needs time for nothing
331  case '[':
332  {
333  //statestack.Push(dummy);
334  tmp += '[';
335  break;
336  }
337  case ']':
338  {
339  //dummy = statestack.Pop();
340  tmp += ']';
341  break;
342  }
343  */
344  default: //check if the churrent char is a rule
345  {
346  char isrule = currentString[i];
347  tmp += getRule(isrule);
348  break;
349  }
350  }
351  }
352  //push back the new points
353  points.push_back(dummypoints);
354  currentString = tmp;
355  //set the positioncount for this iteration order
356  int poscount = points[iteration-1].size() * 3;
357  positioncount.push_back(poscount);
358 
359  //set all the buffers for this iteration order
360  GLuint posbuf;
361  glGenBuffers(1, &posbuf);
362  glBindBuffer(GL_ARRAY_BUFFER, posbuf);
363  glBufferData(GL_ARRAY_BUFFER, poscount/*Anzahl Knoten*/ * sizeof(float), &points[iteration-1][0], GL_STATIC_DRAW);
364  glBindBuffer(GL_ARRAY_BUFFER, 0);
365 
366  GLuint vaobuf;
367  glGenVertexArrays(1, &vaobuf);
368  glBindVertexArray(vaobuf);
369 
370  glBindBuffer(GL_ARRAY_BUFFER, posbuf);
371  glEnableVertexAttribArray(0);
372  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
373  positionBuffer.push_back(posbuf);
374  vao.push_back(vaobuf);
375 
376  glBindVertexArray(0);
377  glBindBuffer(GL_ARRAY_BUFFER, 0);
378 }
std::vector< std::vector< glm::vec3 > > points
Liste von Positionslisten. An der Stelle i sind die Knotenpositionen der Kurve von Grad i-1...
Definition: L_System.h:49
std::string type
Aktueller Kurventyp.
Definition: L_System.h:58
void decreaseDrawingIteration()
veringere die zu zeichnende Iterationsstufe um 1.
Definition: L_System.cpp:209
std::string currentString
Aktueller String der zu berechnenden Iterationsstufe.
Definition: L_System.h:59
std::vector< glm::vec3 > getPoints(int order)
Gibt die Kurveneckpunkte in der Iterationstiefe order zurueck. Sollte order groesser als die aktuell ...
Definition: L_System.cpp:219
std::vector< int > positioncount
Liste von Anzahl der Knoten. An der Stelle i ist die Knotenanzahl der Kurve von Grad i-1...
Definition: L_System.h:48
int segmentcount
Anzahl der Segmente der aktuell maximalen Iterationsstufe.
Definition: L_System.h:57
L_System(int width, int height, std::string t)
Dem Konstruktor wird die Breite und Hoehe des Fensters uebergeben. Diese werden nur fuer die Initialk...
Definition: L_System.cpp:10
int getDrawingIteration()
Gibt die Iterationstiefe zurueck die aktuell gezeichnet wird.
Definition: L_System.cpp:173
double delta
Winkel der bei einer Winkelaenderung auf den aktuellen Winkel ab oder angerechnet wird...
Definition: L_System.h:56
std::string getRule(char var)
Ueberprueft ob es fuer den uebergebenen char eine Ersetzungsregel gibt und gibt diese, falls vorhanden, zurueck.
Definition: L_System.cpp:113
int drawingIteration
Aktuell zu zeichnende Iterationsstufe.
Definition: L_System.h:54
int height
Definition: main.cpp:28
std::string getType()
Gibt den Typ der Kurve zurueck ("hilbert" oder "gosper").
Definition: L_System.cpp:190
double x
Aktuelle x Koordinate.
Definition: L_System.h:67
std::vector< GLuint > vao
Liste von Vertex Array Objects. An der Stelle i ist das vao der Kurve von Grad i-1.
Definition: L_System.h:46
void draw(GLuint shader)
Zeichnet die aktuelle Kurve.
Definition: L_System.cpp:136
double distance
Laenge eines Kurvensegments.
Definition: L_System.h:55
void initHilbert()
Setzt den Startstring und die Kurveneigenschaften der Hilbertkurve.
Definition: L_System.cpp:78
void initCurve(int w, int h)
Initialisiert eine Standartkurve als Order 0 Kurve und allgemeine Parameter.
Definition: L_System.cpp:53
void iterate()
Die maximale Iterationsstufe wird um 1 erhoeht und die Punkte der naechsten Iterationsstufe berechnet...
Definition: L_System.cpp:233
int width
Definition: main.cpp:29
int iteration
Aktuell maximale Iterationsstufe.
Definition: L_System.h:53
void initGosper()
Setzt den Startstring und die Kurveneigenschaften der Gosperkurve.
Definition: L_System.cpp:94
int height
Hoehe des Anzeigefensters.
Definition: L_System.h:52
int getSegmentCount()
Gibt die aktuelle Anzahl der Kurvensegmente zurueck.
Definition: L_System.cpp:159
void setDrawingIteration(int order)
Setzt die zu zeichnende Iterationsstufe auf order falls order kleiner als die maximale Iterationsstuf...
Definition: L_System.cpp:180
double y
Aktuelle y Koordinate.
Definition: L_System.h:68
~L_System(void)
Definition: L_System.cpp:124
double angle
Aktueller Winkel.
Definition: L_System.h:69
void increaseDrawingIteration()
erhoehe die zu zeichnende Iterationsstufe um 1.
Definition: L_System.cpp:197
GLuint shader
Enthaellt den Zeichenshader.
Definition: main.cpp:26
int width
Breite des Anzeigefensters.
Definition: L_System.h:51
std::vector< GLuint > positionBuffer
Liste von Positionsbuffern. An der Stelle i ist der Buffer der Kurve von Grad i-1.
Definition: L_System.h:47
std::vector< std::string > rules
Liste von Ersetzungsregeln.
Definition: L_System.h:60
int getIteration()
Gibt die aktuell maximale Iterationstiefe zurueck.
Definition: L_System.cpp:166
double degToRad(double angle)
Rechnet Gradwinkel in Radiant um.
Definition: L_System.cpp:152