Class SierpinskiCarpetBuilder

 1 /*
 2  * Copyright (c) 2016 Martin Davis.
 3  *
 4  * All rights reserved. This program and the accompanying materials
 5  * are made available under the terms of the Eclipse Public License 2.0
 6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
 7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
 8  * and the Eclipse Distribution License is available at
 9  *
10  * http://www.eclipse.org/org/documents/edl-v10.php.
11  */
12  
13 package org.locationtech.jts.shape.fractal;
14  
15 import java.util.ArrayList;
16 import java.util.List;
17  
18 import org.locationtech.jts.geom.Coordinate;
19 import org.locationtech.jts.geom.CoordinateList;
20 import org.locationtech.jts.geom.Geometry;
21 import org.locationtech.jts.geom.GeometryFactory;
22 import org.locationtech.jts.geom.LineSegment;
23 import org.locationtech.jts.geom.LinearRing;
24 import org.locationtech.jts.geom.Polygon;
25 import org.locationtech.jts.shape.GeometricShapeBuilder;
26  
27  
28 public class SierpinskiCarpetBuilder 
29 extends GeometricShapeBuilder
30 {
31     private CoordinateList coordList = new CoordinateList();
32     
33     public SierpinskiCarpetBuilder(GeometryFactory geomFactory)
34     {
35         super(geomFactory);
36     }
37     
38     public static int recursionLevelForSize(int numPts)
39     {
40         double pow4 = numPts / 3;
41         double exp = Math.log(pow4)/Math.log(4);
42         return (int) exp;
43     }
44     
45     public Geometry getGeometry()
46     {
47         int level = recursionLevelForSize(numPts);
48         LineSegment baseLine = getSquareBaseLine();
49         Coordinate origin = baseLine.getCoordinate(0);
50         LinearRing[] holes = getHoles(level, origin.x, origin.y, getDiameter());
51         LinearRing shell = ((Polygon) geomFactory.toGeometry(getSquareExtent())).getExteriorRing();
52         return geomFactory.createPolygon(
53                 shell, holes);
54     }
55     
56     private LinearRing[] getHoles(int n, double originX, double originY, double width) 
57     {
58         List holeList = new ArrayList();
59         
60         addHoles(n, originX, originY, width, holeList );
61         
62         return GeometryFactory.toLinearRingArray(holeList);
63     }
64  
65     private void addHoles(int n, double originX, double originY, double width, List holeList) 
66     {
67         if (n < 0return;
68         int n2 = n - 1;
69         double widthThird = width / 3.0;
70         addHoles(n2, originX,                                     originY, widthThird, holeList);
71         addHoles(n2, originX + widthThird,             originY, widthThird, holeList);
72         addHoles(n2, originX + 2 * widthThird,     originY, widthThird, holeList);
73         
74         addHoles(n2, originX,                                     originY + widthThird, widthThird, holeList);
75         addHoles(n2, originX + 2 * widthThird,     originY + widthThird, widthThird, holeList);
76  
77         addHoles(n2, originX,                                     originY + 2 * widthThird, widthThird, holeList);
78         addHoles(n2, originX + widthThird,             originY + 2 * widthThird, widthThird, holeList);
79         addHoles(n2, originX + 2 * widthThird,     originY + 2 * widthThird, widthThird, holeList);
80  
81         // add the centre hole
82         holeList.add(createSquareHole(originX + widthThird, originY + widthThird, widthThird));
83     }
84  
85     private LinearRing createSquareHole(double x, double y, double width)
86     {
87         Coordinate[] pts = new Coordinate[]{
88         new Coordinate(x, y),
89         new Coordinate(x + width, y),
90         new Coordinate(x + width, y + width),
91         new Coordinate(x, y + width),
92         new Coordinate(x, y)
93         }    ;
94         return geomFactory.createLinearRing(pts); 
95     }
96     
97  
98 }
99