/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eAdventure 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with eAdventure. If not, see <http://www.gnu.org/licenses/>. */ package es.eucm.ead.tools.pathfinding; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.poly2tri.Poly2Tri; import org.poly2tri.geometry.polygon.Polygon; import org.poly2tri.triangulation.TriangulationPoint; import org.poly2tri.triangulation.delaunay.DelaunayTriangle; import org.poly2tri.triangulation.point.TPoint; public class PathFinder extends AStar<DelaunayTriangle> { private Map<DelaunayTriangle, List<DelaunayTriangle>> sucessorsMap; private Polygon polygon; private List<DelaunayTriangle> allTriangles; private DelaunayTriangle endNode; public PathFinder() { allTriangles = new ArrayList<DelaunayTriangle>(); } public void setPolygon(Polygon p) { this.polygon = p; Poly2Tri.triangulate(p); allTriangles.clear(); // Fetch all triangles (including not interiors) for (DelaunayTriangle t : polygon.getTriangles()) { if (!allTriangles.contains(t)) { allTriangles.add(t); } for (DelaunayTriangle n : t.neighbors) { if (n != null && !allTriangles.contains(n)) { allTriangles.add(n); } } } sucessorsMap = new HashMap<DelaunayTriangle, List<DelaunayTriangle>>(); for (DelaunayTriangle t : polygon.getTriangles()) { ArrayList<DelaunayTriangle> sucessors = new ArrayList<DelaunayTriangle>(); for (DelaunayTriangle n : t.neighbors) { if (n != null && n.isInterior()) sucessors.add(n); } sucessorsMap.put(t, sucessors); } } public List<Float> getPath(float startX, float startY, float endX, float endY) { ArrayList<Float> list = new ArrayList<Float>(); list.add(startX); list.add(startY); if (!isPossibleStraightLine(startX, startY, endX, endY)) { DelaunayTriangle startNode = getTriangleIn(startX, startY); endNode = getTriangleIn(endX, endY); // Point out of trajectory if (endNode == null) { TriangulationPoint p = getNearestPoint(endX, endY); endNode = getTriangleIn(p.getXf(), p.getYf()); endX = (int) p.getXf(); endY = (int) p.getYf(); } if (startNode != null && endNode != null) { if (startNode != endNode && !isPossibleStraightLine(startX, startY, endX, endY)) { List<DelaunayTriangle> path = super.compute(startNode); path.remove(0); path.remove(0); float lastX = startX; float lastY = startY; for (DelaunayTriangle t : path) { TriangulationPoint p = t.nearest(lastX, lastY); list.add((float) p.getX()); list.add((float) p.getY()); lastX = p.getXf(); lastY = p.getYf(); } } } } list.add(endX); list.add(endY); return list; } private TriangulationPoint getNearestPoint(float endX, float endY) { TriangulationPoint p = null; float dist = 0; for (DelaunayTriangle t : polygon.getTriangles()) { TriangulationPoint p1 = t.nearest(endX, endY); float dist1 = (endX - p1.getXf()) * (endX - p1.getXf()) + (endY - p1.getYf()) * (endY - p1.getYf()); if (p == null || dist1 < dist) { p = p1; dist = dist1; } } return p; } /** * Returns if is possible a straight line from start to end * * @return */ private boolean isPossibleStraightLine(float startX, float startY, float endX, float endY) { for (DelaunayTriangle t : allTriangles) { if (!t.isInterior() && t.intersects(startX, startY, endX, endY)) { return false; } } return true; } public DelaunayTriangle getTriangleIn(float x, float y) { TPoint p = new TPoint(x, y); for (DelaunayTriangle t : polygon.getTriangles()) { if (t.inside(p)) { return t; } } return null; } @Override protected boolean isGoal(DelaunayTriangle node) { return node == endNode; } @Override protected Double g(DelaunayTriangle from, DelaunayTriangle to) { double diffX = from.centroid().getX() - to.centroid().getX(); double diffY = from.centroid().getY() - to.centroid().getY(); return diffX * diffX + diffY * diffY; } @Override protected Double h(DelaunayTriangle from, DelaunayTriangle to) { return g(from, to); } @Override protected List<DelaunayTriangle> generateSuccessors(DelaunayTriangle node) { return sucessorsMap.get(node); } public Map<DelaunayTriangle, List<DelaunayTriangle>> getSucessorsMap() { return sucessorsMap; } public Polygon getPolygon() { return polygon; } }