/* 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 static java.util.Objects.requireNonNull; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import net.maritimecloud.message.MessageReader; import net.maritimecloud.message.MessageSerializer; import net.maritimecloud.message.MessageWriter; /** * A union of multiple areas * * @author Kasper Nielsen */ class AreaUnion extends Area { /** A serializer for area unions. */ public static final MessageSerializer<AreaUnion> SERIALIZER = new MessageSerializer<AreaUnion>() { /** {@inheritDoc} */ @Override public AreaUnion read(MessageReader reader) throws IOException { List<Area> list = reader.readList(1, "areas", Area.SERIALIZER); return new AreaUnion(list.toArray(new Area[list.size()])); } public void write(AreaUnion message, MessageWriter writer) throws IOException { writer.writeList(1, "areas", Arrays.asList(message.areas), Area.SERIALIZER); } }; /** serialVersionUID. */ private static final long serialVersionUID = 1L; /** The combined areas. */ final Area[] areas; /** * Creates a new AreaUnion. * * @param area * the areas to combine */ AreaUnion(Area... area) { ArrayList<Area> areas = new ArrayList<>(); for (Area ar : area) { requireNonNull(ar); if (ar instanceof AreaUnion) { areas.addAll(Arrays.asList(((AreaUnion) ar).areas)); } else { areas.add(ar); } } this.areas = areas.toArray(new Area[areas.size()]); } AreaUnion(List<? extends Area> areas) { this(areas.toArray(new Area[areas.size()])); } /** {@inheritDoc} */ @Override public boolean contains(Position position) { for (Area a : areas) { if (a.contains(position)) { return true; } } return false; } private boolean equals(AreaUnion other) { if (areas.length == other.areas.length) { List<Area> others = Arrays.asList(other.areas.clone()); for (Area area : areas) { boolean found = false; for (int i = 0; i < others.size(); i++) { Area otherArea = others.get(i); if (area == otherArea || area.equals(otherArea)) { found = true; others.remove(i); break; } } if (!found) { return false; } } } return false; } /** {@inheritDoc} */ @Override public boolean equals(Object other) { return other == this || other instanceof AreaUnion && equals((AreaUnion) other); } /** {@inheritDoc} */ @Override public Rectangle getBoundingBox() { // make boundry boxes for everyone // calculate vertical distances between each boundary box. // Combine boxes that are closes, recalculate // for each boundry box // Mht til dato linjen. Maa det vaere den mindste box der kan laves throw new UnsupportedOperationException(); } /** {@inheritDoc} */ @Override public Position getRandomPosition(Random random) { // Implementations // 1) // bounding box og saa blev ved indtil vi finder en position // Den er svaerd fordi det skal vaere i forhold til arealet. // 2) // Vi skal have en getAreaSize og saa bruge en // AliasedMethodTable http://www.keithschwarz.com/darts-dice-coins/ // We lazy calculater bliver noedt til at have et volatile temp object her der gemmer da shit throw new UnsupportedOperationException("getRandomPosition is not currently supported"); } /** {@inheritDoc} */ @Override public int hashCode() { if (areas.length == 0) { return 0; } // hashCode is commutative int hashCode = areas[0].hashCode(); for (int i = 1; i < areas.length; i++) { hashCode = hashCode ^ areas[i].hashCode(); } return hashCode; } /** {@inheritDoc} */ public AreaUnion immutable() { return this; } /** {@inheritDoc} */ @Override public boolean intersects(Area other) { for (Area a : areas) { if (a.intersects(other)) { return true; } } return false; } } // /** {@inheritDoc} */ // @Override // public double geodesicDistanceTo(Element other) { // double distance = Double.MAX_VALUE; // for (Area a : areas) { // distance = Math.min(distance, a.geodesicDistanceTo(other)); // } // return distance; // } // /** {@inheritDoc} */ // @Override // public double rhumbLineDistanceTo(Element other) { // double distance = Double.MAX_VALUE; // for (Area a : areas) { // distance = Math.min(distance, a.rhumbLineDistanceTo(other)); // } // return distance; // }