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