package iamrescue.routing.gui;
import iamrescue.belief.IAMWorldModel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import maps.util.Polygon;
import maps.util.PolygonSplitter;
import maps.util.Triangle;
import maps.util.Triangulation;
import rescuecore2.misc.geometry.Line2D;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.misc.gui.ScreenTransform;
import rescuecore2.standard.entities.Area;
import rescuecore2.standard.view.StandardViewLayer;
import rescuecore2.view.RenderedObject;
import rescuecore2.view.ViewComponent;
import rescuecore2.view.ViewListener;
public class PolygonDivisionLayer extends StandardViewLayer implements
ViewListener {
private IAMWorldModel worldModel;
private Area clicked = null;
private Polygon[] splitPolygons;
private Polygon[] triangulatedPolygons;
private double maxNodes = 30;// 150000;
private double maxCircumference = 20000;
private double minDegree = 0;
public PolygonDivisionLayer() {
// this.worldModel = worldModel;
}
/*
* (non-Javadoc)
*
* @see rescuecore2.view.ViewLayer#getName()
*/
@Override
public String getName() {
return "Polygon Division";
}
/*
* (non-Javadoc)
*
* @see rescuecore2.view.ViewLayer#render(java.awt.Graphics2D,
* rescuecore2.misc.gui.ScreenTransform, int, int)
*/
@Override
public Collection<RenderedObject> render(Graphics2D g,
ScreenTransform transform, int width, int height) {
if (clicked != null) {
if (splitPolygons == null) {
createPolygons();
}
g.setColor(Color.BLACK);
if (triangulatedPolygons != null) {
for (Polygon polygon : triangulatedPolygons) {
drawPolygon(polygon, transform, g);
}
}
g.setColor(Color.RED);
for (Polygon polygon : splitPolygons) {
drawPolygon(polygon, transform, g);
}
/*
* int cutDistance = 20000;
*
* List<Edge> edges = clicked.getEdges();
*
* int[] apexList = clicked.getApexList();
*
* int length = 0;
*
* for (int i = 0; i < apexList.length - 2; i = i + 2) { double midX
* = (apexList[i] + apexList[i + 2]) / 2; double midY = (apexList[i
* + 1] + apexList[i + 3]) / 2; double directionX = -apexList[i + 1]
* + apexList[i + 3]; double directionY = apexList[i] - apexList[i +
* 2];
*
* length += Math.sqrt(directionX * directionX + directionY
* directionY);
*
* if (length > cutDistance) { length = 0; Line2D orthogonal = new
* Line2D(midX, midY, directionX, directionY);
*
* int negatives = 0; int positives = 0;
*
* double lowestNegative = Double.MAX_VALUE; double lowestPositive =
* Double.MAX_VALUE;
*
* for (Edge edge : edges) { Line2D otherLine = edge.getLine(); if
* (edge.getStartX() == apexList[i] || edge.getEndX() ==
* apexList[i]) { // Ignore same edge. continue; } double
* intersection = orthogonal .getIntersection(otherLine); if
* (intersection != Double.NaN) {
*
* double otherIntersection = otherLine
* .getIntersection(orthogonal); if (otherIntersection >= 0 &&
* otherIntersection <= 1) {
*
* g.setColor(Color.GREEN); g.drawOval(transform.xToScreen(midX +
* intersection * directionX), transform .yToScreen(midY +
* intersection directionY), 5, 5); g.drawString("" + intersection,
* transform .xToScreen(midX + intersection directionX), transform
* .yToScreen(midY + intersection directionY));
* g.setColor(Color.BLACK);
*
* if (intersection < 0) { negatives++; intersection *= -1; if
* (intersection < lowestNegative) { lowestNegative = intersection;
* } } else if (intersection > 0) { positives++; if (intersection <
* lowestPositive) { lowestPositive = intersection; } } else {
* System.out.println("Something went wrong. " +
* "Intersection is at " + midX + "," + midY); } } } else { //
* Parallel. Check if they intersect double otherX =
* otherLine.getOrigin().getX(); double otherY =
* otherLine.getOrigin().getY();
*
* double scalar = (otherX - midX) / directionX; if (Math.abs(scalar
* * directionY + midY - otherY) < 0.000000001) { // Yes, assume
* they intersect if (scalar < 0) { negatives++; } else if (scalar >
* 1) { positives++; } else {
* System.out.println("Something went wrong " +
* "with parallel lines. " + "Intersection is at " + midX + "," +
* midY);
*
* } } } } double scalar = 0; if (negatives % 2 != 0) { // Use
* intersection of negative side scalar = - lowestNegative; } else
* if (positives % 2 != 0) { scalar = lowestPositive; } else {
* System.out.println("Something went wrong. " +
* "Same number of positives and negatives"); g.setColor(Color.RED);
* g.drawOval(transform.xToScreen(midX), transform .yToScreen(midY),
* 5, 5); g.setColor(Color.BLACK); continue; }
* g.drawLine(transform.xToScreen(midX), transform .yToScreen(midY),
* transform.xToScreen(midX + directionX * scalar),
* transform.yToScreen(midY + directionY * scalar)); } }
*/
}
/*
*
*
*
*
* g.setColor(Color.BLACK);
*
* SimpleGraph graph = routing.getGraph(); List<Node> nodes =
* graph.getNodes();
*
* Set<Node> done = new FastSet<Node>(); for (Node node : nodes) {
* PositionXY xy = routing.getConverter().getSimpleGraphNode(
* node.getID()).getRepresentativePoint(); int x1 =
* transform.xToScreen(xy.getX()); int y1 =
* transform.yToScreen(xy.getY());
*
* for (Node neighbour : node.getNeighbours()) { if
* (!done.contains(neighbour)) { PositionXY xy2 =
* routing.getConverter().getSimpleGraphNode(
* neighbour.getID()).getRepresentativePoint(); int x2 =
* transform.xToScreen(xy2.getX()); int y2 =
* transform.yToScreen(xy2.getY());
*
* g.drawLine(x1, y1, x2, y2); } } g.drawString("N " + node.getID(), x1,
* y1); done.add(node); } if (path != null) { g.setColor(Color.RED);
* PositionXY last = path.getXYPath().get(0); for (int i = 1; i <
* path.getXYPath().size(); i++) { PositionXY next =
* path.getXYPath().get(i); int x1 = transform.xToScreen(next.getX());
* int y1 = transform.yToScreen(next.getY()); int x2 =
* transform.xToScreen(last.getX()); int y2 =
* transform.yToScreen(last.getY()); last = next; g.drawLine(x1, y1, x2,
* y2); } }
*/
return new ArrayList<RenderedObject>();
}
/**
*
*/
private void createPolygons() {
int[] apexList = clicked.getApexList();
double[] xs = new double[apexList.length / 2];
double[] ys = new double[apexList.length / 2];
for (int i = 0; i < apexList.length; i = i + 2) {
xs[xs.length - i / 2 - 1] = apexList[i];
ys[xs.length - i / 2 - 1] = apexList[i + 1];
}
Polygon originalPolygon = new Polygon(xs, ys);
// originalPolygon = PolygonSplitter.reduceEdges(originalPolygon,
// minDegree);
splitPolygons = PolygonSplitter.splitPolygon(originalPolygon, maxNodes,
maxCircumference);
// splitPolygons = new Polygon[] { splitPolygons[(int)
// (splitPolygons.length * Math
// .random())] };
// splitPolygons = new Polygon[] { originalPolygon };
List<Polygon> triangulated = new ArrayList<Polygon>();
for (Polygon p : splitPolygons) {
Triangle[] triangulatedPolygon = Triangulation.triangulatePolygon(
p.x, p.y, p.x.length);
if (triangulatedPolygon != null) {
Polygon[] polygons = Triangulation.polygonizeTriangles(
triangulatedPolygon, minDegree);
for (Polygon triP : polygons) {
triangulated.add(triP);
}
}
}
triangulatedPolygons = triangulated.toArray(new Polygon[0]);
}
public void setMaxNodes(double maxNodes) {
this.maxNodes = maxNodes;
splitPolygons = null;
component.repaint();
}
public void setMaxCircumference(double maxCircumference) {
this.maxCircumference = maxCircumference;
}
public void setMinDegree(double minDegree) {
this.minDegree = minDegree;
splitPolygons = null;
component.repaint();
}
/**
* @return the maxCircumference
*/
public double getMaxNodes() {
return maxNodes;
}
public double getMaxCircumference() {
return maxCircumference;
}
/**
* @return the minDegree
*/
public double getMinDegree() {
return minDegree;
}
/*
* (non-Javadoc)
*
* @seerescuecore2.view.ViewListener#objectsClicked(rescuecore2.view.
* ViewComponent, java.util.List)
*/
@Override
public void objectsClicked(ViewComponent view, List<RenderedObject> objects) {
for (RenderedObject obj : objects) {
if (obj.getObject() instanceof Area) {
Area area = (Area) obj.getObject();
clicked = area;
splitPolygons = null;
triangulatedPolygons = null;
view.repaint();
}
}
}
/*
* (non-Javadoc)
*
* @seerescuecore2.view.ViewListener#objectsRollover(rescuecore2.view.
* ViewComponent, java.util.List)
*/
@Override
public void objectsRollover(ViewComponent view, List<RenderedObject> objects) {
// TODO Auto-generated method stub
}
private void drawPolygon(Polygon polygon, ScreenTransform transform,
Graphics g) {
double[] pxs = polygon.x;
double[] pys = polygon.y;
for (int i = 0; i < pxs.length - 1; i++) {
g.drawLine(transform.xToScreen(pxs[i]),
transform.yToScreen(pys[i]), transform
.xToScreen(pxs[i + 1]), transform
.yToScreen(pys[i + 1]));
int lower = (i == 0) ? (pxs.length - 1) : (i - 1);
int middle = i;
int upper = (i == pxs.length - 1) ? (0) : (i + 1);
Line2D line1 = new Line2D(new Point2D(pxs[lower], pys[lower]),
new Point2D(pxs[middle], pys[middle]));
Line2D line2 = new Line2D(new Point2D(pxs[middle], pys[middle]),
new Point2D(pxs[upper], pys[upper]));
// double angle = GeometryTools2D
// .getRightAngleBetweenLines(line1, line2);
// g
// .drawString("" + Math.round(angle), transform
// .xToScreen(pxs[i]), transform
// .yToScreen(pys[i]));
}
g.drawLine(transform.xToScreen(pxs[pxs.length - 1]), transform
.yToScreen(pys[pxs.length - 1]), transform.xToScreen(pxs[0]),
transform.yToScreen(pys[0]));
}
}