/* * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * * This file is part of PeerfactSim.KOM. * * PeerfactSim.KOM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * PeerfactSim.KOM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PeerfactSim.KOM. If not, see . * */ package de.tud.kom.p2psim.impl.topology.obstacles; import java.awt.Color; import java.util.List; import com.google.common.collect.Lists; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.MultiLineString; import org.locationtech.jts.geom.Polygon; import de.tud.kom.p2psim.impl.topology.util.PositionVector; /** * This Obstacle is build from a list of coordinates that form a Polygon. The * coordinates have to be specified in clockwise direction. * * @author Bjoern Richerzhagen * @version 1.0, 20.03.2012 */ public class PolygonObstacle extends AbstractObstacle { private final GeometryFactory factory = new GeometryFactory(); private Polygon poly; private double damping = 1.0; int[] xpoints; int[] ypoints; double minX = Double.POSITIVE_INFINITY; double minY = Double.POSITIVE_INFINITY; double maxX = Double.NEGATIVE_INFINITY; double maxY = Double.NEGATIVE_INFINITY; private Color customColor; private List vertices; /** * A Polygon that is damping the signal (no link through this obstacle is * possible) * * @param vertices */ public PolygonObstacle(List vertices) { this(vertices, 1.0); } public PolygonObstacle(List vertices, double damping) { if (damping > 1) damping = 1; if (damping < 0) damping = 0; this.damping = damping; rebuildPolygon(vertices); } /** * Returns the vertices this polygon was build with. Modifications * to this list won't affect the obstacle. Use rebuildPolygon() to * restructure the obstacle. * * @return */ public List getVertices() { return Lists.newArrayList(vertices); } public void rebuildPolygon(List vertices) { assert vertices.size() > 2 : "You have to specify at least 3 Points"; this.vertices = vertices; this.minX = Double.POSITIVE_INFINITY; this.minY = Double.POSITIVE_INFINITY; this.maxX = Double.NEGATIVE_INFINITY; this.maxY = Double.NEGATIVE_INFINITY; Coordinate[] coordinates = new Coordinate[vertices.size()+ 1]; xpoints = new int[vertices.size()]; ypoints = new int[vertices.size()]; PositionVector firstVertex = vertices.get(0); coordinates[coordinates.length - 1] = new Coordinate(firstVertex.getX(), firstVertex.getY()); int i = 0; for (PositionVector vertex : vertices) { coordinates[i] = new Coordinate(vertex.getX(), vertex.getY()); xpoints[i] = (int) vertex.getX(); ypoints[i] = (int) vertex.getY(); if (xpoints[i] < minX) { minX = xpoints[i]; } if (ypoints[i] < minY) { minY = ypoints[i]; } if (xpoints[i] > maxX) { maxX = xpoints[i]; } if (ypoints[i] > maxY) { maxY = ypoints[i]; } i++; } poly = factory.createPolygon(factory.createLinearRing(coordinates), null); } public int[] getXPoints() { return this.xpoints; } public int[] getYPoints() { return this.ypoints; } @Override public boolean intersectsWith(PositionVector a, PositionVector b) { /* * Adding a bit of greedy decisions, to not always use the poly-methods */ double dist = a.distanceTo(b); if (a.getX() + dist < minX || a.getX() - dist > maxX || a.getY() + dist < minY || a.getY() - dist > maxY) { return false; } Coordinate[] lineCoords = new Coordinate[]{new Coordinate(a.getX(), a.getY()), new Coordinate(b.getX(), b.getY())}; return poly.intersects(factory.createLineString(lineCoords)); } @Override public boolean contains(Geometry g) { return poly.contains(g); } @Override public double totalIntersectionLength(PositionVector a, PositionVector b) { Coordinate[] lineCoords = new Coordinate[] { new Coordinate(a.getX(), a.getY()), new Coordinate(b.getX(), b.getY()) }; Geometry testLine = factory.createLineString(lineCoords); double fullLength = testLine.getLength(); testLine = testLine.difference(poly); if (testLine instanceof MultiLineString) { // some intersections MultiLineString resultLines = (MultiLineString) testLine; return fullLength - resultLines.getLength(); } if (testLine instanceof GeometryCollection) { // all is intersected GeometryCollection geocol = (GeometryCollection) testLine; if (geocol.isEmpty()) return fullLength; assert (false) : "Geometry collection is not empty"; return fullLength; } else { // no intersection assert (testLine instanceof LineString); LineString resultLine = (LineString) testLine; return fullLength - resultLine.getLength(); } } @Override public double dampingFactor() { return damping; } public java.awt.Polygon getAwtPolygon(double scale) { int[] xScaled = new int[xpoints.length]; int[] yScaled = new int[ypoints.length]; for (int i = 0; i < yScaled.length; i++) { xScaled[i] = (int) (xpoints[i] / scale); yScaled[i] = (int) (ypoints[i] / scale); } return new java.awt.Polygon(xScaled, yScaled, yScaled.length); } @Override public Geometry getGeometry() { return this.poly; } public PositionVector getCentroid() { double xCenter = 0; double yCenter = 0; for (int i = 0; i < xpoints.length; i++) { xCenter += xpoints[i]; yCenter += ypoints[i]; } return new PositionVector(xCenter * (1/xpoints.length), yCenter * (1/ypoints.length)); } public void setDampeningFactor(double dampeningFactor) { this.damping = dampeningFactor; } public void setCustomColor(Color color) { this.customColor = color; } public Color getCustomColor() { return this.customColor; } }