Class MortonCurveBuilder

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