66import org .poly2tri .triangulation .TriangulationPoint ;
77import org .poly2tri .triangulation .delaunay .DelaunayTriangle ;
88
9- import java .awt .Point ; // TODO: wrong point class!
10- import java .util .ArrayDeque ;
11- import java .util .ArrayList ;
12- import java .util .HashMap ;
13- import java .util .HashSet ;
14-
15- public final class LSystem { // TODO: Finish cleaning up this class
16- public static ArrayList <PolygonStorage > curves = new ArrayList <>();
17-
18- /**
19- * An array containing the args to generate a curve.
20- * index 0 = rules
21- * index 1 = angle
22- * index 2 = start string
23- */
9+ import java .awt .*; // TODO: Wrong point class!
10+ import java .util .*;
11+ import java .util .List ;
12+
13+ public final class LSystem { // TODO: Rewrite this class
14+ public static ArrayList <PolygonInfo > curves = new ArrayList <>();
15+
16+ // https://en.wikipedia.org/wiki/L-system
17+ //
18+ // System: {rules, angle, start_string}
19+ // Rules: rule1:rule_2:...:rule_n
20+ // Rule: from_substring>to_substring
21+ //
22+ // Each iteration, rules are applied to the string. After, string
23+ // is interpreted as commands for a pencil on a sheet of paper:
24+ // F - move forward by one step
25+ // + - turn clockwise by angle
26+ // - - turn counter-clockwise by angle
27+ // [ - save state (push to stack)
28+ // ] - restore state (pop from stack)
2429 public static final String [] TERDRAGON = {"F>+F----F++++F-" , "60" , "F" };
2530 public static final String [] DRAGON = {"X>X+YF:Y>FX-Y" , "90" , "FX" };
2631 public static final String [] TWINDRAGON = {"X>X+YF:Y>FX-Y" , "90" , "FX--FX" };
2732 public static final String [] VORTEX = {"X>X+YF:Y>FX-Y" , "90" , "FX---FX" };
2833
29- static { // Used to be in mod init
30- // TODO
34+ static {
35+ // TODO: Move to separate class
3136 LSystem .generateLSystem ("terdragon" , LSystem .TERDRAGON , 4 );
3237 LSystem .generateLSystem ("terdragon" , LSystem .TERDRAGON , 5 );
3338 //LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 6); // degenerate
@@ -83,73 +88,23 @@ public static void generateLSystem(String key, String[] args, int steps) {
8388 output = generate (args [2 ], steps , lSystemsRule );
8489
8590 //get the boundary of the polygon
86- PolygonStorage polygon = getBoundary (convertToPoints (angle , output , steps ));
91+ List < Point > polygon = getBoundary (convertToPoints (angle , output , steps ));
8792
8893 //replace the boundary of the polygon with a series of points representing triangles for rendering
89- polygon .points = tesselate (polygon );
90-
91- curves .add (polygon );
92- }
93-
94- /**
95- * Naively returns all of the points comprising the fractal
96- */
97- public static PolygonStorage getSpaceFillingCurve (ArrayList <double []> input ) {
98- // store max x and y values to create bounding box
99- int maxY = Integer .MIN_VALUE ;
100- int maxX = Integer .MIN_VALUE ;
101- int minY = Integer .MAX_VALUE ;
102- int minX = Integer .MAX_VALUE ;
103-
104- // store confirmed duplicates here
105- HashSet <Point > duplicates = new HashSet <>();
106-
107- // store possible singles here
108- HashSet <Point > singles = new HashSet <>();
109-
110- // list to store confirmed singles and output in the correct order
111- ArrayList <Point > output = new ArrayList <>();
112-
113- // sort into Hashmaps and hashsets to make contains operations possible,
114- // while testing for duplicates
115- for (double [] point : input ) {
116- // convert doubles to ints and record min/max values
117-
118- int xCoord = (int ) Math .round (point [0 ]);
119- int yCoord = (int ) Math .round (point [1 ]);
120-
121- if (xCoord > maxX ) {
122- maxX = xCoord ;
123- }
124- if (xCoord < minX ) {
125- minX = xCoord ;
126- }
127-
128- if (yCoord > maxY ) {
129- maxY = yCoord ;
130- }
131- if (yCoord < minY ) {
132- minY = yCoord ;
133- }
134- output .add (new Point (xCoord , yCoord ));
135- }
136- return new PolygonStorage (output , maxX , maxY , minX , minY );
94+ curves .add (new PolygonInfo (tesselate (polygon )));
13795 }
13896
13997 /**
14098 * Takes an unordered list of points comprising a fractal curve and builds a
14199 * closed polygon around it
142100 */
143- public static PolygonStorage getBoundary (ArrayList <double []> input ) {
101+ public static List < Point > getBoundary (ArrayList <double []> input ) {
144102 // store max x and y values to create bounding box
145103 int maxY = Integer .MIN_VALUE ;
146104 int maxX = Integer .MIN_VALUE ;
147105 int minY = Integer .MAX_VALUE ;
148106 int minX = Integer .MAX_VALUE ;
149107
150- // store confirmed duplicates here
151- HashSet <Point > duplicates = new HashSet <>();
152-
153108 // store possible singles here
154109 HashSet <Point > singles = new HashSet <>();
155110
@@ -159,24 +114,14 @@ public static PolygonStorage getBoundary(ArrayList<double[]> input) {
159114 // sort into Hashmaps and hashsets to make contains operations possible,
160115 // while testing for duplicates
161116 for (double [] point : input ) {
162- // convert doubles to ints and record min/max values
163-
164117 int xCoord = (int ) Math .round (point [0 ]);
165118 int yCoord = (int ) Math .round (point [1 ]);
166119
167- if (xCoord > maxX ) {
168- maxX = xCoord ;
169- }
170- if (xCoord < minX ) {
171- minX = xCoord ;
172- }
120+ if (xCoord > maxX ) maxX = xCoord ;
121+ if (xCoord < minX ) minX = xCoord ;
122+ if (yCoord > maxY ) maxY = yCoord ;
123+ if (yCoord < minY ) minY = yCoord ;
173124
174- if (yCoord > maxY ) {
175- maxY = yCoord ;
176- }
177- if (yCoord < minY ) {
178- minY = yCoord ;
179- }
180125 singles .add (new Point (xCoord , yCoord ));
181126 }
182127
@@ -235,7 +180,7 @@ public static PolygonStorage getBoundary(ArrayList<double[]> input) {
235180 }
236181 while (!(output .get (output .size () - 1 ).equals (firstPoint ) && output .size () > 1 ) && output .size () < singles .size ());
237182
238- return new PolygonStorage ( output , maxX , maxY , minX , minY ) ;
183+ return output ;
239184 }
240185
241186 /**
@@ -341,30 +286,50 @@ public static String generate(String start, int steps, HashMap<String, String> l
341286 }
342287
343288 // a data container class to transmit the important information about the polygon
344- public static class PolygonStorage {
345- public PolygonStorage (ArrayList <Point > points , int maxX , int maxY , int minX , int minY ) {
289+ public static class PolygonInfo {
290+ public final ArrayList <Point > points ;
291+
292+ public int maxX ;
293+ public final int maxY ;
294+ public final int minX ;
295+ public final int minY ;
296+
297+ public PolygonInfo (ArrayList <Point > points ) {
298+ int minX , minY , maxX , maxY ;
299+ minX = minY = maxX = maxY = 0 ;
300+
301+ // Find bounding box of the polygon
346302 this .points = points ;
347- this .maxX = maxX ;
348- this .maxY = maxY ;
303+ if (points .size () > 0 ) {
304+ Point firstPoint = points .get (0 );
305+ minX = firstPoint .x ;
306+ minY = firstPoint .y ;
307+ maxX = firstPoint .x ;
308+ maxY = firstPoint .y ;
309+
310+ for (Point point : points ) {
311+ if (point .x < minX ) minX = point .x ;
312+ if (point .y < minY ) minY = point .y ;
313+ if (point .x > maxX ) maxX = point .x ;
314+ if (point .y > maxY ) maxY = point .y ;
315+ }
316+ }
317+
349318 this .minX = minX ;
350319 this .minY = minY ;
320+ this .maxX = maxX ;
321+ this .maxY = maxY ;
351322 }
352-
353- public ArrayList <Point > points ;
354-
355- public int maxX ;
356- public int maxY ;
357- public int minX ;
358- public int minY ;
359323 }
360324
361- public static ArrayList <Point > tesselate (PolygonStorage polygon ) {
325+ // TODO: Use the GLU tesselator (GPU) instead of poly2tri (CPU): http://wiki.lwjgl.org/wiki/Using_GLU_Tesselator.html
326+ public static ArrayList <Point > tesselate (List <Point > polygon ) {
362327 ArrayList <Point > points = new ArrayList <>();
363328
364329 ArrayList <PolygonPoint > polyPoints = new ArrayList <>();
365330
366- for (int i = 0 ; i < polygon . points . size (); i ++ ) {
367- polyPoints .add (new PolygonPoint (polygon . points . get ( i ). x , polygon . points . get ( i ) .y ));
331+ for (Point p : polygon ) {
332+ polyPoints .add (new PolygonPoint (p . x , p .y ));
368333 }
369334
370335 Polygon poly = new Polygon (polyPoints );
@@ -379,88 +344,4 @@ public static ArrayList<Point> tesselate(PolygonStorage polygon) {
379344 }
380345 return points ;
381346 }
382-
383- // TODO: Figure out what this was meant to be
384- /*
385- public static ArrayList<Point> tesselate(Polygon polygon) {
386- ArrayList<Point> points = new ArrayList<>();
387-
388- Tessellator tess = new Tessellator();
389- double[] verticesC1 = new double[polygon.points.size() * 3];
390- for (int i = 0; i < verticesC1.length; i += 3) {
391- Point point = polygon.points.get(i / 3);
392- verticesC1[i] = point.x;
393- verticesC1[i + 1] = point.y;
394- verticesC1[i + 2] = 0;
395- }
396-
397- tess.glBeginPolygon();
398-
399- for (int i = 0; i < polygon.points.size(); i++) {
400- tess.gluTessVertex(verticesC1, i * 3, i);
401- }
402-
403- tess.gluEndPolygon();
404-
405-
406- //Prints out the result of the tessellation.
407- for (int i = 0; i < tess.primitives.size(); i++) {
408- System.out.println(tess.primitives.get(i).toString());
409- }
410- //To draw the shape it is now a simple matter to put the vertex data you passed in initially into a VBO, and the indices returned
411- //into an IBO (Index VBO). You have the types of the primitives and the number of indices for each one. Drawing the result should
412- //be a walk in the park, as long as you have read the appropriate tutorials here or elsewhere.
413-
414-
415- for (int i = 0; i < tess.primitives.size(); i++) {
416-
417- Primitives.Primitive prim = tess.primitives.get(i);
418- ArrayList<Integer> vIndex = prim.vertices;
419-
420- if (prim.type == GL11.GL_TRIANGLE_STRIP) {
421- for (int ii = 0; ii < vIndex.size() - 1; ii++) {
422- points.add(new Point((int) verticesC1[vIndex.get(ii) * 3], (int) verticesC1[vIndex.get(ii) * 3 + 1]));
423- points.add(new Point((int) verticesC1[vIndex.get(ii + 1) * 3], (int) verticesC1[vIndex.get(ii + 1) * 3 + 1]));
424- }
425- }
426-
427- if (prim.type == GL11.GL_TRIANGLES) {
428- for (int ii = 0; ii < vIndex.size(); ii++) {
429- points.add(new Point((int) verticesC1[vIndex.get(ii) * 3], (int) verticesC1[vIndex.get(ii) * 3 + 1]));
430- }
431- }
432-
433- if (prim.type == GL11.GL_TRIANGLE_FAN) {
434- Integer firstIndex = vIndex.get(0);
435- // points.add(new Point((int)verticesC1[vIndex.get(firstIndex)],(int) verticesC1[vIndex.get(firstIndex)+1]));
436-
437- Integer[] vertexList = new Integer[vIndex.size() * 3];
438- for (Integer ii = 0; ii < vIndex.size() - 2; ii++) {
439- vertexList[ii * 3] = vIndex.get(0);
440- vertexList[ii * 3 + 1] = vIndex.get(ii + 1);
441- vertexList[ii * 3 + 2] = vIndex.get(ii + 2);
442- }
443-
444- for (Integer vertex : vertexList) {
445- if (vertex != null) {
446- points.add(new Point((int) verticesC1[vertex * 3], (int) verticesC1[vertex * 3 + 1]));
447- } else {
448- break;
449- }
450- }
451- System.out.println(vertexList);
452- }
453-
454- // points.add(new Point((int)verticesC1[vIndex.get(firstIndex)],(int) verticesC1[vIndex.get(firstIndex)+1]));
455- // points.add(new Point((int)verticesC1[vIndex.get(ii)*3],(int) verticesC1[vIndex.get(ii)+1]));
456- // points.add(new Point((int)verticesC1[vIndex.get(ii+1)*3],(int) verticesC1[vIndex.get(ii+1)*3+1]));
457-
458- // points.add(new Point((int)verticesC1[index],(int)verticesC1[index+1]));
459- // System.out.println(verticesC1[index]+","+verticesC1[index+1]+","+verticesC1[index+2]);
460-
461-
462- //System.out.println(tess.primitives.get(i).toString());
463- }
464- return points;
465- }*/
466347}
0 commit comments