/* * Copyright 2016 Nathan Howard * * This file is part of OpenGrave * * OpenGrave 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 * (at your option) any later version. * * OpenGrave 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 OpenGrave. If not, see <http://www.gnu.org/licenses/>. */ package com.opengrave.common.pathing; import java.util.ArrayList; public class NavigationMesh { // What a mesh. public ArrayList<Point> pointList = new ArrayList<Point>(); public ArrayList<PathingArea> polygonList = new ArrayList<PathingArea>(); public ArrayList<PathingEdge> joins = new ArrayList<PathingEdge>(); public boolean changed = false; public boolean delayEdges = false; public NavigationMesh() { } public ArrayList<PathingEdge> getEdges(Line line) { ArrayList<PathingEdge> list = new ArrayList<PathingEdge>(); for (PathingEdge edge : joins) { if (edge.contains(line)) { list.add(edge); } } return list; } public ArrayList<PathingEdge> getEdges(PathingArea poly) { ArrayList<PathingEdge> list = new ArrayList<PathingEdge>(); for (PathingEdge edge : joins) { if (edge.contains(poly)) { list.add(edge); } } return list; } public ArrayList<PathingArea> getPolygonsAt(Point p) { ArrayList<PathingArea> list = new ArrayList<PathingArea>(); for (PathingArea poly : polygonList) { if (poly.isPointInside(p)) { list.add(poly); } } return list; } public boolean lineOfSight(Point point, Point end, double size) { ArrayList<PathingArea> polys = getPolygonsAt(point); if (polys.size() <= 0) { return false; } if (lineOfSight(polys.get(0), null, point, end, size)) { return true; } // if DERPY MODE ACTIVATE. Much less CPU intensive. Great unless there's a completely perfect LOS across more than 1 poly // for(PathingArea area : polys){ // if(area.isPointInside(end)){ return true; } // } return false; } public boolean lineOfSight(PathingArea pgon, Line exclude, Point start, Point end, double size) { if (pgon.isPointInside(end)) { return true; } Line lineOfSight = new Line(start, end, true); for (PathingEdge edge : getEdges(pgon)) { if (edge.getLine().equals(exclude)) { continue; } if (edge.getInnerLine(size).intersectsWith(lineOfSight)) { if (lineOfSight(edge.getNeighbour(pgon), edge.getLine(), start, end, size)) { return true; } } } // for (Line line : keepLines) { // Line miniLine = line.shortenEnd(size).shortenStart(size); // if (line.intersectsWith(lineOfSight)) { // for (PathingEdge edge : getEdges(line)) { // if (lineOfSight(edge.getNeighbour(pgon), line, start, end, size)) { return true; } // } // } // } return false; } public Point getPoint(int idx) { if (idx < pointList.size()) { return pointList.get(idx); } return null; } public void addPoint(Point pathingPoint) { if (pointList.contains(pathingPoint)) { return; } pointList.add(pathingPoint); changed = true; } public Point getNearestPoint(Point inPoint) { double distance = Double.MAX_VALUE; Point ret = null; for (int i = 0; i < pointList.size(); i++) { Point point = pointList.get(i); double nDist = point.getDistance(inPoint); if (nDist < distance) { ret = point; distance = nDist; } } return ret; } public void addPoly(ArrayList<Point> nextPoly) { PathingArea poly = new PathingArea(this, nextPoly); if (!poly.checkSimple()) { System.out.println("Given Polygon was not convex"); return; } if (polygonList.contains(poly)) { return; } polygonList.add(poly); if (!delayEdges) { fixEdges(); } changed = true; } public void fixEdges() { joins.clear(); for (int i = 0; i < polygonList.size(); i++) { PathingArea poly = polygonList.get(i); ArrayList<Line> lines = poly.getLines(); for (int j = i + 1; j < polygonList.size(); j++) { PathingArea poly2 = polygonList.get(j); PathingEdge edge = new PathingEdge(null, poly.getCenter().getDistance(poly2.getCenter()), poly, poly2); for (Line line : lines) { if (poly2.hasLine(line)) { if (edge.getLine() == null) { edge.setLine(line); } else { System.err.println("Cannot have two shared lines between polygonal areas"); } } } if (edge.getLine() != null) { joins.add(edge); } } } } }