📄 obstacleworld.java
字号:
/* * Copyright (c) 2006, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: ObstacleWorld.java,v 1.2 2007/03/23 21:13:43 fros4943 Exp $ */package se.sics.mrm;import java.awt.Point;import java.awt.geom.*;import java.util.Collection;import java.util.Enumeration;import java.util.Vector;import org.apache.log4j.Logger;import org.jdom.Element;/** * This class represents an area with obstacles. * Obstacles may only be of rectangular shape. * * @author Fredrik Osterlind */class ObstacleWorld { private static Logger logger = Logger.getLogger(ObstacleWorld.class); // All registered obstacles private Vector<Rectangle2D> allObstacles = null; // All registered obstacles, with spatial information private int spatialResolution = 10; private Vector<Rectangle2D>[][] allObstaclesSpatial = new Vector[spatialResolution][spatialResolution]; private boolean obstaclesOrganized = false; // Outer bounds of all obstacles private Rectangle2D outerBounds = null; /** * Creates a new obstacle world without any obstacles. */ public ObstacleWorld() { // No obstacles present so far allObstacles = new Vector<Rectangle2D>(); for (int x=0; x < spatialResolution; x++) for (int y=0; y < spatialResolution; y++) allObstaclesSpatial[x][y] = new Vector<Rectangle2D>(); outerBounds = new Rectangle2D.Double(0,0,0,0); } /** * @return The total number of registered obstacles */ public int getNrObstacles() { return allObstacles.size(); } /** * This method can be used to find extreme coordinates of all obstacles. * * @return Outer bounds of all registered obstacles */ public Rectangle2D getOuterBounds() { return outerBounds; } /** * Returns obstacle registered at given position. * The coordinates of an obstacles should never * be changed directly on an object returned by this method. * * @param i Obstacle position * @return Obstacle at given position */ public Rectangle2D getObstacle(int i) { return allObstacles.get(i); } /** * @return All registered obstacles */ public Vector<Rectangle2D> getAllObstacles() { return allObstacles; } /** * Returns at least all registered obstacles that contains given point. * Note that obstacles close to but not containing the point may also * be returned. * * @param center Center point * @return All obstacles containing or near center */ public Vector<Rectangle2D> getAllObstaclesNear(Point2D center) { double boxWidth = outerBounds.getWidth() / (double) spatialResolution; double boxHeight = outerBounds.getHeight() / (double) spatialResolution; double areaStartX = outerBounds.getMinX(); double areaStartY = outerBounds.getMinY(); double centerX = (center.getX() - areaStartX)/boxWidth; double centerY = (center.getY() - areaStartY)/boxHeight; Vector<Rectangle2D> allNearObstacles = new Vector<Rectangle2D>(); Point pointToAdd = new Point((int) centerX, (int) centerY); if (pointToAdd.x >= 0 && pointToAdd.x < allObstaclesSpatial.length && pointToAdd.y >= 0 && pointToAdd.y < allObstaclesSpatial[0].length) allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); // Add borders if needed boolean addedXBorder = false; boolean addedYBorder = false; if (Math.floor(centerX) == centerX) { pointToAdd = new Point((int) centerX-1, (int) centerY); if (pointToAdd.x >= 0 && pointToAdd.x < allObstaclesSpatial.length && pointToAdd.y >= 0 && pointToAdd.y < allObstaclesSpatial[0].length) { allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); addedXBorder = true; } } if (Math.floor(centerY) == centerY) { pointToAdd = new Point((int) centerX, (int) centerY-1); if (pointToAdd.x >= 0 && pointToAdd.x < allObstaclesSpatial.length && pointToAdd.y >= 0 && pointToAdd.y < allObstaclesSpatial[0].length) { allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); addedYBorder = true; } } if (addedXBorder && addedYBorder) { pointToAdd = new Point((int) centerX-1, (int) centerY-1); allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); } return allNearObstacles; } /** * Returns at least all registered obstacles inside the given angle * interval when at the given center point. Note that obstacles partly or * completely outside the interval may also be returned. * All obstacles are preferably returned in order of distance from given * center point, although this is not guaranteed. * * @param center Center point * @param angleInterval Angle interval * @return All obstacles in given angle interval */ public Vector<Rectangle2D> getAllObstaclesInAngleInterval(Point2D center, AngleInterval angleInterval) { Vector<Rectangle2D> obstaclesToReturn = new Vector<Rectangle2D>(); if (!obstaclesOrganized) { reorganizeSpatialObstacles(); } double boxWidth = outerBounds.getWidth() / (double) spatialResolution; double boxHeight = outerBounds.getHeight() / (double) spatialResolution; double areaStartX = outerBounds.getMinX(); double areaStartY = outerBounds.getMinY(); // Calculate which boxes to check (and in which order) Point centerInArray = new Point( (int) ((center.getX() - areaStartX)/boxWidth), (int) ((center.getY() - areaStartY)/boxHeight) ); Vector<Point> pointsToCheck = new Vector<Point>(); int currentDistance = 0; while (currentDistance < 2*spatialResolution) { if (currentDistance > 0) { int currentX = centerInArray.x - currentDistance; int currentY = centerInArray.y - currentDistance; // Step right while (currentX < centerInArray.x + currentDistance) { if (currentX >= 0 && currentX < allObstaclesSpatial.length && currentY >= 0 && currentY < allObstaclesSpatial[0].length) pointsToCheck.add(new Point(currentX, currentY)); currentX++; } // Step right while (currentY < centerInArray.y + currentDistance) { if (currentX >= 0 && currentX < allObstaclesSpatial.length && currentY >= 0 && currentY < allObstaclesSpatial[0].length) pointsToCheck.add(new Point(currentX, currentY)); currentY++; } // Step left while (currentX > centerInArray.x - currentDistance) { if (currentX >= 0 && currentX < allObstaclesSpatial.length && currentY >= 0 && currentY < allObstaclesSpatial[0].length) pointsToCheck.add(new Point(currentX, currentY)); currentX--; } // Step up while (currentY > centerInArray.y - currentDistance) { if (currentX >= 0 && currentX < allObstaclesSpatial.length && currentY >= 0 && currentY < allObstaclesSpatial[0].length) pointsToCheck.add(new Point(currentX, currentY)); currentY--; } } else { if (centerInArray.x >= 0 && centerInArray.x < allObstaclesSpatial.length && centerInArray.y >= 0 && centerInArray.y < allObstaclesSpatial[0].length) { pointsToCheck.add(new Point(centerInArray.x, centerInArray.y)); } } currentDistance++; } for (int pointNr=0; pointNr < pointsToCheck.size(); pointNr++) { // Check which obstacles should be in this box boolean hit = false; int x = pointsToCheck.get(pointNr).x; int y = pointsToCheck.get(pointNr).y; // Test if we are inside test box if (!hit) { if (new Rectangle2D.Double( areaStartX + x*boxWidth, areaStartY + y*boxHeight, boxWidth, boxHeight).contains(center)) { hit = true; for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) { if (!obstaclesToReturn.contains(allObstaclesSpatial[x][y].get(i))) obstaclesToReturn.add(allObstaclesSpatial[x][y].get(i)); } } } // Test first diagonal if (!hit) { AngleInterval testInterval = AngleInterval.getAngleIntervalOfLine( center, new Line2D.Double( areaStartX + x*boxWidth, areaStartY + y*boxHeight, areaStartX + (x+1)*boxWidth, areaStartY + (y+1)*boxHeight) ); if (testInterval.intersects(angleInterval)) { hit = true; for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) { if (!obstaclesToReturn.contains(allObstaclesSpatial[x][y].get(i))) obstaclesToReturn.add(allObstaclesSpatial[x][y].get(i)); } } } // Test second diagonal if (!hit) { AngleInterval testInterval = AngleInterval.getAngleIntervalOfLine( center, new Line2D.Double( areaStartX + x*boxWidth, areaStartY + (y+1)*boxHeight, areaStartX + (x+1)*boxWidth, areaStartY + y*boxHeight) ); if (testInterval.intersects(angleInterval)) { hit = true; for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) { if (!obstaclesToReturn.contains(allObstaclesSpatial[x][y].get(i))) obstaclesToReturn.add(allObstaclesSpatial[x][y].get(i)); } } } } return obstaclesToReturn; } /** * Removes all registered obstacles. */ public void removeAll() { allObstacles.removeAllElements(); for (int x=0; x < spatialResolution; x++) for (int y=0; y < spatialResolution; y++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -