@Override public void run() { LOS los1 = new LOS(BRESENHAM); LOS los2 = new LOS(BRESENHAM); // if a non-solid midpoint on the path can see both the start and end, consider the two ends // to be able to see each other if (resistanceMap[testx][testy] < 1 && radiusStrategy.radius(startx, starty, testx, testy) <= radiusStrategy.radius(startx, starty, targetx, targety) && los1.isReachable(resistanceMap, testx, testy, targetx, targety, radiusStrategy) && los2.isReachable(resistanceMap, startx, starty, testx, testy, radiusStrategy)) { // record actual sight path used path = new LinkedList<>(los2.lastPath); path.addAll(los1.lastPath); succeeded = true; } }
private boolean bresenhamReachable(Radius radiusStrategy) { Queue<Coord> path = Bresenham.line2D(startx, starty, targetx, targety); lastPath = new LinkedList<>(); lastPath.add(Coord.get(startx, starty)); double force = 1; double decay = 1 / radiusStrategy.radius(startx, starty, targetx, targety); double currentForce = force; for (Coord p : path) { lastPath.offer(p); if (p.x == targetx && p.y == targety) { return true; // reached the end } if (p.x != startx || p.y != starty) { // don't discount the start location even if on resistant cell currentForce -= resistanceMap[p.x][p.y]; } double r = radiusStrategy.radius(startx, starty, p.x, p.y); if (currentForce - (r * decay) <= 0) { return false; // too much resistance } } return false; // never got to the target point }
private boolean rayReachable(Radius radiusStrategy) { lastPath = new LinkedList<>(); // save path for later retreival lastPath.add(Coord.get(startx, starty)); if (startx == targetx && starty == targety) { // already there! return true; } int width = resistanceMap.length; int height = resistanceMap[0].length; CoordDouble start = new CoordDouble(startx, starty); CoordDouble end = new CoordDouble(targetx, targety); // find out which direction to step, on each axis int stepX = (int) Math.signum(end.x - start.x); int stepY = (int) Math.signum(end.y - start.y); double deltaY = end.x - start.x; double deltaX = end.y - start.y; deltaX = Math.abs(deltaX); deltaY = Math.abs(deltaY); int testX = (int) start.x; int testY = (int) start.y; double maxX = (float) (start.x % 1); double maxY = (float) (start.y % 1); int endTileX = (int) end.x; int endTileY = (int) end.y; CoordDouble collisionPoint = new CoordDouble(); while (testX >= 0 && testX < width && testY >= 0 && testY < height && (testX != endTileX || testY != endTileY)) { lastPath.add(Coord.get(testX, testY)); if (maxX < maxY) { maxX += deltaX; testX += stepX; if (resistanceMap[testX][testY] >= 1f) { collisionPoint.y = testY; collisionPoint.x = testX; end = collisionPoint; break; } } else if (maxY < maxX) { maxY += deltaY; testY += stepY; if (resistanceMap[testX][testY] >= 1f) { collisionPoint.y = testY; collisionPoint.x = testX; end = collisionPoint; break; } } else { // directly on diagonal, move both full step maxY += deltaY; testY += stepY; maxX += deltaX; testX += stepX; if (resistanceMap[testX][testY] >= 1f) { collisionPoint.y = testY; collisionPoint.x = testX; end = collisionPoint; break; } } if (radiusStrategy.radius(testX, testY, start.x, start.y) > radiusStrategy.radius(startx, starty, targetx, targety)) { // went too far break; } } if (end.x >= 0 && end.x < width && end.y >= 0 && end.y < height) { lastPath.add(Coord.get((int) end.x, (int) end.y)); } return (int) end.x == targetx && (int) end.y == targety; }