/*******************************************************************************
* Copyright (c) 2015 Voyager Search and MITRE
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License, Version 2.0 which
* accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package org.locationtech.spatial4j.shape;
import org.locationtech.spatial4j.context.SpatialContext;
/**
* The base interface defining a geometric shape. Shape instances should be
* instantiated via one of the create* methods on a {@link SpatialContext} or
* by reading WKT which calls those methods; they should <em>not</em> be
* created directly.
* <p>
* Shapes are generally immutable and thread-safe. If a particular shape has a
* <code>reset(...)</code> method then its use means the shape is actually
* mutable. Mutating shape state is considered expert and should be done with care.
*/
public interface Shape {
/**
* Describe the relationship between the two objects. For example
* <ul>
* <li>this is WITHIN other</li>
* <li>this CONTAINS other</li>
* <li>this is DISJOINT other</li>
* <li>this INTERSECTS other</li>
* </ul>
* Note that a Shape implementation may choose to return INTERSECTS when the
* true answer is WITHIN or CONTAINS for performance reasons. If a shape does
* this then it <i>must</i> document when it does. Ideally the shape will not
* do this approximation in all circumstances, just sometimes.
* <p>
* If the shapes are equal then the result is CONTAINS (preferred) or WITHIN.
*/
SpatialRelation relate(Shape other);
/**
* Get the bounding box for this Shape. This means the shape is within the
* bounding box and that it touches each side of the rectangle.
* <p>
* Postcondition: <code>this.getBoundingBox().relate(this) == CONTAINS</code>
*/
Rectangle getBoundingBox();
/**
* Does the shape have area? This will be false for points and lines. It will
* also be false for shapes that normally have area but are constructed in a
* degenerate case as to not have area (e.g. a circle with 0 radius or
* rectangle with no height or no width).
*/
boolean hasArea();
/**
* Calculates the area of the shape, in square-degrees. If ctx is null then
* simple Euclidean calculations will be used. This figure can be an
* estimate.
*/
double getArea(SpatialContext ctx);
/**
* Returns the center point of this shape. This is usually the same as
* <code>getBoundingBox().getCenter()</code> but it doesn't have to be.
* <p>
* Postcondition: <code>this.relate(this.getCenter()) == CONTAINS</code>
*/
Point getCenter();
/**
* Returns a buffered version of this shape. The buffer is usually a
* rounded-corner buffer, although some shapes might buffer differently. This
* is an optional operation.
*
*
* @param distance
* @return Not null, and the returned shape should contain the current shape.
*/
Shape getBuffered(double distance, SpatialContext ctx);
/**
* Shapes can be "empty", which is to say it exists nowhere. The underlying coordinates are
* typically NaN.
*/
boolean isEmpty();
/** The sub-classes of Shape generally implement the
* same contract for {@link Object#equals(Object)} and {@link Object#hashCode()}
* amongst the same sub-interface type. This means, for example, that multiple
* Point implementations of different classes are equal if they share the same x
* & y. */
@Override
public boolean equals(Object other);
/**
* Get the SpatialContext that created the Shape
*/
public SpatialContext getContext();
}