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 }