/* Copyright (c) 2011 Danish Maritime Authority.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.maritimecloud.util.geometry;
import java.io.IOException;
import java.io.Serializable;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import net.maritimecloud.message.Message;
import net.maritimecloud.message.MessageReader;
import net.maritimecloud.message.MessageSerializer;
import net.maritimecloud.message.MessageWriter;
/**
* A shape has an area
**/
public abstract class Area implements Message, Serializable {
/** serialVersionUID. */
private static final long serialVersionUID = 1L;
static final String UNION = "union";
static final int UNION_TAG = 1;
static final String CIRCLE = "circle";
static final int CIRCLE_TAG = 2;
static final String RECTANGLE = "rectangle";
static final int RECTANGLE_TAG = 3;
static final String POLYGON = "polygon";
static final int POLYGON_TAG = 4;
static final String ELIPSE = "elipse";
static final int ELIPSE_TAG = 5;
/** A parser of areas. */
public static final MessageSerializer<Area> SERIALIZER = new MessageSerializer<Area>() {
/** {@inheritDoc} */
@Override
public Area read(MessageReader r) throws IOException {
if (r.isNext(UNION_TAG, UNION)) {
return new AreaUnion(r.readList(UNION_TAG, UNION, AreaUnion.SERIALIZER));
} else if (r.isNext(CIRCLE_TAG, CIRCLE)) {
return r.readMessage(CIRCLE_TAG, CIRCLE, Circle.SERIALIZER);
} else if (r.isNext(RECTANGLE_TAG, RECTANGLE)) {
return r.readMessage(RECTANGLE_TAG, RECTANGLE, Rectangle.SERIALIZER);
} else if (r.isNext(POLYGON_TAG, POLYGON)) {
return r.readMessage(POLYGON_TAG, POLYGON, Polygon.SERIALIZER);
} else if (r.isNext(ELIPSE_TAG, ELIPSE)) {
return r.readMessage(POLYGON_TAG, POLYGON, Polygon.SERIALIZER);
} else {
throw new UnsupportedOperationException();
}
}
/** {@inheritDoc} */
@Override
public void write(Area a, MessageWriter w) throws IOException {
if (a != null) {
if (a instanceof AreaUnion) {
w.writeMessage(UNION_TAG, UNION, (AreaUnion) a, AreaUnion.SERIALIZER);
} else if (a instanceof Circle) {
w.writeMessage(CIRCLE_TAG, CIRCLE, (Circle) a, Circle.SERIALIZER);
} else if (a instanceof Rectangle) {
w.writeMessage(RECTANGLE_TAG, RECTANGLE, (Rectangle) a, Rectangle.SERIALIZER);
} else if (a instanceof Polygon) {
w.writeMessage(POLYGON_TAG, POLYGON, (Polygon) a, Polygon.SERIALIZER);
} else {
throw new UnsupportedOperationException();
}
}
}
};
/**
* Returns <tt>true</tt> if the specified element is fully contained in the shape, otherwise <tt>false</tt>.
*
* @param area
* the area to test
* @return true if the specified element is fully contained in the shape, otherwise false
*/
public boolean contains(Area area) {
throw new UnsupportedOperationException();
}
public abstract boolean contains(Position position);
/**
* Returns a bounding box of the area.
*
* @return a bounding box of the area
*/
public abstract Rectangle getBoundingBox();
/**
* Returns a random position within the area.
*
* @return a random position within the area
*/
public final Position getRandomPosition() {
return getRandomPosition(ThreadLocalRandom.current());
}
/**
* Returns a random position within the area using a specified random source.
*
* @param random
* the random source
* @return a random position within the area
*/
public abstract Position getRandomPosition(Random random);
public abstract boolean intersects(Area other);
/** Returns a JSON representation of this message */
public String toJSON() {
return MessageSerializer.writeToJSON(this, SERIALIZER);
}
/**
* Returns a union of this area with the specified area.
*
* @param other
* the area to join with this area.
* @return the joined area
*/
public final Area unionWith(Area other) {
return new AreaUnion(this, other);
}
/**
* Creates a message of this type from a JSON throwing a runtime exception if the format of the message does not
* match a valid area.
*
* @param string
* the JSON string to parse
* @return the parsed area
*/
public static Area fromJSON(CharSequence string) {
return MessageSerializer.readFromJSON(SERIALIZER, string);
}
static double nextDouble(Random r, double least, double bound) {
return r.nextDouble() * (bound - least) + least;
}
public static Area unionOf(Area... areas) {
Area[] a = areas.clone();
return new AreaUnion(a);
}
}
// @Override
// public double rhumbLineDistanceTo(Position other) {
// throw new UnsupportedOperationException();
// }
// /** {@inheritDoc} */
// @Override
// public final double distanceTo(Element other, CoordinateSystem system) {
// return requireNonNull(system) == CoordinateSystem.CARTESIAN ? rhumbLineDistanceTo(other)
// : geodesicDistanceTo(other);
// }
// /** {@inheritDoc} */
// @Override
// public double geodesicDistanceTo(Element other) {
// throw new UnsupportedOperationException();
// }