1 /******************************************************************************* 2 * Copyright (c) 2015 Voyager Search and MITRE 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 /** 14 * The base interface defining a geometric shape. Shape instances should be 15 * instantiated via one of the create* methods on a {@link SpatialContext} or 16 * by reading WKT which calls those methods; they should <em>not</em> be 17 * created directly. 18 * <p> 19 * Shapes are generally immutable and thread-safe. If a particular shape has a 20 * <code>reset(...)</code> method then its use means the shape is actually 21 * mutable. Mutating shape state is considered expert and should be done with care. 22 */ 23 public interface Shape { 24 25 /** 26 * Describe the relationship between the two objects. For example 27 * <ul> 28 * <li>this is WITHIN other</li> 29 * <li>this CONTAINS other</li> 30 * <li>this is DISJOINT other</li> 31 * <li>this INTERSECTS other</li> 32 * </ul> 33 * Note that a Shape implementation may choose to return INTERSECTS when the 34 * true answer is WITHIN or CONTAINS for performance reasons. If a shape does 35 * this then it <i>must</i> document when it does. Ideally the shape will not 36 * do this approximation in all circumstances, just sometimes. 37 * <p> 38 * If the shapes are equal then the result is CONTAINS (preferred) or WITHIN. 39 */ 40 SpatialRelation relate(Shape other); 41 42 /** 43 * Get the bounding box for this Shape. This means the shape is within the 44 * bounding box and that it touches each side of the rectangle. 45 * <p> 46 * Postcondition: <code>this.getBoundingBox().relate(this) == CONTAINS</code> 47 */ 48 Rectangle getBoundingBox(); 49 50 /** 51 * Does the shape have area? This will be false for points and lines. It will 52 * also be false for shapes that normally have area but are constructed in a 53 * degenerate case as to not have area (e.g. a circle with 0 radius or 54 * rectangle with no height or no width). 55 */ 56 boolean hasArea(); 57 58 /** 59 * Calculates the area of the shape, in square-degrees. If ctx is null then 60 * simple Euclidean calculations will be used. This figure can be an 61 * estimate. 62 */ 63 double getArea(SpatialContext ctx); 64 65 /** 66 * Returns the center point of this shape. This is usually the same as 67 * <code>getBoundingBox().getCenter()</code> but it doesn't have to be. 68 * <p> 69 * Postcondition: <code>this.relate(this.getCenter()) == CONTAINS</code> 70 */ 71 Point getCenter(); 72 73 /** 74 * Returns a buffered version of this shape. The buffer is usually a 75 * rounded-corner buffer, although some shapes might buffer differently. This 76 * is an optional operation. 77 * 78 * @return Not null, and the returned shape should contain the current shape. 79 */ 80 Shape getBuffered(double distance, SpatialContext ctx); 81 82 /** 83 * Shapes can be "empty", which is to say it exists nowhere. The underlying coordinates are 84 * typically NaN. 85 */ 86 boolean isEmpty(); 87 88 /** The sub-classes of Shape generally implement the 89 * same contract for {@link Object#equals(Object)} and {@link Object#hashCode()} 90 * amongst the same sub-interface type. This means, for example, that multiple 91 * Point implementations of different classes are equal if they share the same x 92 * & y. */ 93 @Override 94 public boolean equals(Object other); 95 96 97 /** 98 * Get the SpatialContext that created the Shape 99 */ 100 public SpatialContext getContext(); 101 } 102