View Javadoc
1   /*******************************************************************************
2    * Copyright (c) 2016 David Smiley
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Apache License, Version 2.0 which
5    * accompanies this distribution and is available at
6    *    http://www.apache.org/licenses/LICENSE-2.0.txt
7    ******************************************************************************/
8   
9   package org.locationtech.spatial4j.shape;
10  
11  import org.locationtech.spatial4j.context.SpatialContext;
12  
13  import java.util.List;
14  
15  /**
16   * A factory for {@link Shape}s.
17   * Stateless and thread-safe, except for any returned builders.
18   */
19  public interface ShapeFactory {
20  
21    SpatialContext getSpatialContext();
22  
23    /** If true then {@link #normX(double)} will wrap longitudes outside of the standard
24     * geodetic boundary into it. Example: 181 will become -179. */
25    boolean isNormWrapLongitude();
26  
27    // TODO annoying that a ShapeReader must remember to call norm* methods.  Perhaps
28    //  there should be another shapeFactory impl for shape reading?  :-/  Or not.
29  
30    /** Normalize the 'x' dimension. Might reduce precision or wrap it to be within the bounds. This
31     * is called by {@link org.locationtech.spatial4j.io.ShapeReader}s before creating a shape. */
32    double normX(double x);
33  
34    /** @see #normX(double)  */
35    double normY(double y);
36  
37    /** (disclaimer: the Z dimension isn't fully supported)
38     * @see #normX(double) */
39    double normZ(double z);
40  
41    /**
42     * Called to normalize a value that isn't X or Y or Z. X & Y & Z are normalized via
43     * {@link org.locationtech.spatial4j.context.SpatialContext#normX(double)} & normY & normZ. This
44     * is called by a {@link org.locationtech.spatial4j.io.ShapeReader} before creating a shape.
45     */
46    double normDist(double d);
47  
48    /** Ensure fits in the world bounds. It's called by any shape factory method that
49     * gets an 'x' dimension. */
50    void verifyX(double x);
51  
52    /** @see #verifyX(double)  */
53    void verifyY(double y);
54  
55    /** (disclaimer: the Z dimension isn't fully supported)
56     *  @see #verifyX(double)  */
57    void verifyZ(double z);
58  
59    /** Construct a point. */
60    Point pointXY(double x, double y);
61  
62    /** Construct a point of latitude, longitude coordinates */
63    default Point pointLatLon(double latitude, double longitude) {
64      return pointXY(longitude, latitude);
65    }
66  
67    /** Construct a point of 3 dimensions.  The implementation might ignore unsupported
68     * dimensions like 'z' or throw an error. */
69    Point pointXYZ(double x, double y, double z);
70  
71    /** Construct a rectangle. */
72    Rectangle rect(Point lowerLeft, Point upperRight);
73  
74    /**
75     * Construct a rectangle. If just one longitude is on the dateline (+/- 180) and if
76     * {@link SpatialContext#isGeo()}
77     * then potentially adjust its sign to ensure the rectangle does not cross the
78     * dateline (aka anti-meridian).
79     */
80    Rectangle rect(double minX, double maxX, double minY, double maxY);
81  
82    /** Construct a circle. The units of "distance" should be the same as x & y. */
83    Circle circle(double x, double y, double distance);
84  
85    /** Construct a circle. The units of "distance" should be the same as x & y. */
86    Circle circle(Point point, double distance);
87  
88    /** Constructs a line string with a possible buffer. It's an ordered sequence of connected vertexes,
89     * with a buffer distance along the line in all directions. There
90     * is no official shape/interface for it so we just return Shape. */
91    @Deprecated // use a builder
92    Shape lineString(List<Point> points, double buf);
93  
94    /** Construct a ShapeCollection, analogous to an OGC GeometryCollection. */
95    @Deprecated // use a builder
96    <S extends Shape> ShapeCollection<S> multiShape(List<S> coll);
97  
98    // BUILDERS:
99  
100   /** (Builder) Constructs a line string, with a possible buffer.
101    * It's an ordered sequence of connected vertexes.
102    * There is no official shape/interface for it yet so we just return Shape. */
103   LineStringBuilder lineString();
104 
105   /** (Builder) Constructs a polygon.
106    * There is no official shape/interface for it yet so we just return Shape. */
107   PolygonBuilder polygon();
108 
109   /** (Builder) Constructs a Shape aggregate in which each component/member
110    * is an instance of the specified class.
111    */
112   <T extends Shape> MultiShapeBuilder<T> multiShape(Class<T> shapeClass);
113 
114   /** (Builder) Constructs a MultiPoint. */
115   MultiPointBuilder multiPoint();
116 
117   /** (Builder) Constructs a MultiLineString, or possibly the result of that buffered. */
118   MultiLineStringBuilder multiLineString();
119 
120   /** (Builder) Constructs a MultiPolygon. */
121   MultiPolygonBuilder multiPolygon();
122 
123   // misc:
124   //Shape buffer(Shape shape);  ?
125 
126   // TODO need Polygon shape
127   // TODO need LineString shape
128   // TODO need BufferedLineString shape
129   // TODO need ShapeCollection to be typed
130 
131   /** Builds a point and returns the generic specified type (usually whatever "this" is). */
132   interface PointsBuilder<T> {
133     /** @see ShapeFactory#pointXY(double, double) */
134     T pointXY(double x, double y);
135     /** @see ShapeFactory#pointXYZ(double, double, double) */
136     T pointXYZ(double x, double y, double z);
137     /** @see ShapeFactory#pointLatLon(double, double)  */
138     default T pointLatLon(double latitude, double longitude) {
139       return pointXY(longitude, latitude);
140     }
141   }
142 
143   /** @see #lineString() */
144   interface LineStringBuilder extends PointsBuilder<LineStringBuilder> {
145     // TODO add dimensionality hint method?
146 
147     LineStringBuilder buffer(double distance);
148 
149     Shape build();
150   }
151 
152   /** @see #polygon() */
153   interface PolygonBuilder extends PointsBuilder<PolygonBuilder> {
154     // TODO add dimensionality hint method?
155 
156     /** Starts a new hole. You must add at least 4 points; furthermore the first and last must be the same.
157      * And don't forget to call {@link HoleBuilder#endHole()}! */
158     HoleBuilder hole();
159 
160     /** Builds the polygon and renders this builder instance invalid. */
161     Shape build();// never a Rect
162 
163     Shape buildOrRect();
164 
165     interface HoleBuilder extends PointsBuilder<HoleBuilder> {
166       /** Finishes the hole and returns the {@link PolygonBuilder}.*/
167       PolygonBuilder endHole();
168     }
169   }
170 
171   // TODO add dimensionality hint method to the multi* builders?
172 
173   /** @see #multiShape(Class) */
174   interface MultiShapeBuilder<T extends Shape> {
175     // TODO add dimensionality hint method?
176 
177     MultiShapeBuilder<T> add(T shape);
178 
179     //ShapeCollection<T> build(); TODO wait till it's a typed interface
180     Shape build();
181   }
182 
183   /** @see #multiPoint() */
184   interface MultiPointBuilder extends PointsBuilder<MultiPointBuilder> {
185 
186     Shape build();  // TODO MultiShape<Point>
187   }
188 
189   /** @see #multiLineString() */
190   interface MultiLineStringBuilder {
191 
192     LineStringBuilder lineString();
193 
194     MultiLineStringBuilder add(LineStringBuilder lineStringBuilder);
195 
196     Shape build(); // TODO MultiShape<LineString>
197   }
198 
199   /** @see #multiPolygon() */
200   interface MultiPolygonBuilder {
201 
202     PolygonBuilder polygon();
203 
204     MultiPolygonBuilder add(PolygonBuilder polygonBuilder);
205 
206     Shape build(); // TODO MultiShape<Polygon>
207   }
208 }