Class HilbertCurveBuilder

 1 /*
 2  * Copyright (c) 2019 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 org.locationtech.jts.geom.Coordinate;
16 import org.locationtech.jts.geom.Geometry;
17 import org.locationtech.jts.geom.GeometryFactory;
18 import org.locationtech.jts.geom.LineSegment;
19 import org.locationtech.jts.geom.LineString;
20 import org.locationtech.jts.shape.GeometricShapeBuilder;
21 import static org.locationtech.jts.shape.fractal.HilbertCode.*;
22  
23 /**
24  * Generates a {@link LineString} representing the Hilbert Curve
25  * at a given level.
26  * 
27  * @author Martin Davis
28  * @see HilbertCode
29  */
30 public class HilbertCurveBuilder
31 extends GeometricShapeBuilder
32 {
33   private int order = -1;
34  
35   /**
36    * Creates a new instance using the provided {@link GeometryFactory}.
37    * 
38    * @param geomFactory the geometry factory to use
39    */
40   public HilbertCurveBuilder(GeometryFactory geomFactory)
41   {
42     super(geomFactory);
43     // use a null extent to indicate no transformation
44     // (may be set by client)
45     extent = null;
46   }
47   
48   /**
49    * Sets the level of curve to generate.
50    * The level must be in the range [0 - 16].
51    * 
52    * @param level the order of the curve
53    */
54   public void setLevel(int level) {
55     this.numPts = size(level);  }
56   
57   @Override
58   public Geometry getGeometry() {
59     int level = level(numPts);
60     int nPts = size(level);
61     
62     double scale = 1;
63     double baseX = 0;
64     double baseY = 0;
65     if (extent != null) {
66       LineSegment baseLine = getSquareBaseLine();
67       baseX = baseLine.minX();
68       baseY = baseLine.minY();
69       double width = baseLine.getLength();
70       int maxOrdinate = maxOrdinate(level);
71       scale = width / maxOrdinate;
72     }
73     
74     Coordinate[] pts = new Coordinate[nPts];
75     for (int i = 0; i < nPts; i++) {
76        Coordinate pt = decode(level, i);
77        double x = transform(pt.getX(), scale, baseX );
78        double y = transform(pt.getY(), scale, baseY );
79        pts[i] = new Coordinate(x, y);
80     }
81     return geomFactory.createLineString(pts);
82   }
83   
84   private static double transform(double val, double scale, double offset) {
85     return val * scale + offset;
86   }
87   
88 }
89