package iamrescue.util; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.apache.log4j.Logger; import rescuecore2.misc.Pair; import rescuecore2.standard.entities.Area; import rescuecore2.standard.entities.Blockade; import rescuecore2.standard.entities.Building; import rescuecore2.standard.entities.Edge; import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.Road; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardWorldModel; import rescuecore2.worldmodel.WorldModel; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LinearRing; public class SpatialUtils { private final static GeometryFactory factory = new GeometryFactory(); private static final Logger LOGGER = Logger.getLogger(SpatialUtils.class); /** * Converts a list of coordinates into a Geometry object. If a single * coordinate is given, the shape is converted to a Point, otherwise to a * Polygon. * * @param apexes * Coordinates. * @return A geometry object representing the shape given by the * coordinates. */ public static Geometry convertApexes(PositionXY[] apexes) { List<Pair<Integer, Integer>> list = new ArrayList<Pair<Integer, Integer>>( apexes.length); for (int i = 0; i < apexes.length; i++) { list.add(new Pair<Integer, Integer>(apexes[i].getX(), apexes[i] .getY())); } return convertApexes(list); } public static Geometry convertApexes(int[] apexes) { List<Pair<Integer, Integer>> list = new ArrayList<Pair<Integer, Integer>>( apexes.length / 2); for (int i = 0; i < apexes.length; i = i + 2) { list.add(new Pair<Integer, Integer>(apexes[i], apexes[i + 1])); } return convertApexes(list); } public static Geometry convertApexes(Pair<Integer, Integer> point) { return convertApexes(Collections.singletonList(point)); } /** * Converts a list of coordinates into a Geometry object. If a single * coordinate is given, the shape is converted to a Point, otherwise to a * Polygon. * * @param apexes * Coordinates. * @return A geometry object representing the shape given by the * coordinates. */ public static Geometry convertApexes(List<Pair<Integer, Integer>> apexes) { if (apexes.size() == 0) { throw new IllegalArgumentException( "Cannot handle empty apex array."); } if (apexes.size() == 1) { return factory.createPoint(new Coordinate(apexes.get(0).first(), apexes.get(0).second())); } else if (apexes.size() == 2) { Coordinate[] coordinates = new Coordinate[2]; int i = 0; for (Pair<Integer, Integer> pair : apexes) { coordinates[i] = new Coordinate(pair.first(), pair.second()); i++; } return factory.createLineString(coordinates); } else { Coordinate[] coordinates = new Coordinate[apexes.size() + 1]; int i = 0; for (Pair<Integer, Integer> pair : apexes) { coordinates[i] = new Coordinate(pair.first(), pair.second()); i++; } coordinates[apexes.size()] = coordinates[0]; return factory.createPolygon(factory.createLinearRing(coordinates), new LinearRing[0]); } } public static Geometry convertApexes(PositionXY apex) { return factory.createPoint(new Coordinate(apex.getX(), apex.getY())); } public static boolean isSpatialObject(StandardEntity se) { return (se instanceof Building || se instanceof Road || se instanceof Human || se instanceof Blockade); } public static Geometry createGeometry(StandardEntity se, StandardWorldModel worldModel) { if (!isSpatialObject(se)) { LOGGER.error("Not a spatial object: " + se.getFullDescription()); return null; } List<Pair<Integer, Integer>> coordPairs = new LinkedList<Pair<Integer, Integer>>(); if (se instanceof Area) { Area a = (Area) se; if (a.isEdgesDefined()) { coordPairs = convertEdgesToApexes(a.getEdges()); } } else if (se instanceof Blockade) { Blockade b = (Blockade) se; if (b.isApexesDefined()) { return convertApexes(b.getApexes()); } } else { Human h = (Human) se; if (h.isPositionDefined()) { coordPairs.add(h.getLocation(worldModel)); } } if (coordPairs.size() == 0) { LOGGER.error("No coordinates: " + se.getFullDescription()); return null; } else { return convertApexes(coordPairs); } } /** * @param edges * @return */ private static List<Pair<Integer, Integer>> convertEdgesToApexes( List<Edge> edges) { List<Pair<Integer, Integer>> edgesList = new ArrayList<Pair<Integer, Integer>>(); for (Edge edge : edges) { edgesList.add(new Pair<Integer, Integer>(edge.getStartX(), edge .getStartY())); } // Don't need last x/y return edgesList; } public static Envelope createBoundingEnvelope(StandardEntity se, StandardWorldModel worldModel) { List<Pair<Integer, Integer>> coordPairs = new LinkedList<Pair<Integer, Integer>>(); if (se instanceof Area) { Area a = (Area) se; if (a.isEdgesDefined()) { coordPairs = convertEdgesToApexes(a.getEdges()); } } else if (se instanceof Blockade) { Blockade b = (Blockade) se; if (b.isApexesDefined()) { int[] apexes = b.getApexes(); for (int i = 0; i < apexes.length; i = i + 2) { coordPairs.add(new Pair<Integer, Integer>(apexes[i], apexes[i + 1])); } } } else { Human h = (Human) se; if (h.isXDefined() && h.isYDefined()) { coordPairs.add(h.getLocation(worldModel)); } } if (coordPairs.size() == 0) { return null; } int minX = Integer.MAX_VALUE; int maxX = Integer.MIN_VALUE; int minY = Integer.MIN_VALUE; int maxY = Integer.MIN_VALUE; for (Pair<Integer, Integer> pair : coordPairs) { if (pair == null) { return null; } if (pair.first() < minX) { minX = pair.first(); } if (pair.first() > maxX) { maxX = pair.first(); } if (pair.second() < minY) { minY = pair.second(); } if (pair.second() > maxY) { maxY = pair.second(); } } return new Envelope(minX, maxX, minY, maxY); } /* * public static int computeSearchRadius(AgentConfiguration * agentConfiguration) { int maxDistancePerTurn = agentConfiguration * .getInt(AgentConfigurationConstants.MAX_TRAVELLED_DISTANCE_PER_TURN); * double searchRadiusScaler = agentConfiguration * .getDouble(AgentConfigurationConstants.SEARCH_RADIUS_SCALER); return * (int) (maxDistancePerTurn * searchRadiusScaler); } */ public static StandardEntity getFixedPosition(StandardEntity object, WorldModel<StandardEntity> worldModel) { if (object == null) return null; StandardEntity pos = object; while (pos != null && (pos instanceof Human)) { pos = worldModel.getEntity(((Human) pos).getPosition()); } return pos; } }