java - Recursive Collision Detection for Rectangles not quite working -
i have bunch of variable sized rectangles, laid out randomly in area.
i attempting (recursive) collision detection ensures not collide, shifting positions.
but, still wrong (some of rectangles still collide), , can't figure out what.. inability recursion right. grateful if checked out.
here's code, copy & paste & run it, , you'll see result instantly. requires javafx:
import javafx.application.application; import javafx.geometry.point2d; import javafx.geometry.rectangle2d; import javafx.scene.scene; import javafx.scene.layout.pane; import javafx.scene.paint.color; import javafx.scene.shape.rectangle; import javafx.stage.stage; import java.util.*; public class example extends application { public static void main(string[] args) { launch(args); } private pane root = new pane(); @override public void start(stage stage) throws exception { scene scene = new scene(root, 800, 600); stage.settitle("collision problem"); stage.setscene(scene); stage.setoncloserequest(e -> system.exit(0)); stage.show(); run(); } private static class node2d { private double x, y, w, h; public node2d() { w = randint(40, 80); h = randint(20, 40); } public void setposition(double x, double y) { this.x = x; this.y = y; } public double getwidth() { return w; } public double getheight() { return h; } } private static class layoutentity { private node2d obj = new node2d(); private double x, y; public void setlocationinlayout(double x, double y) { this.x = x; this.y = y; } public double getxinlayout() { return x; } public double getyinlayout() { return y; } } public void run() { layoutentity[] entitiestolayout = new layoutentity[100]; (int = 0; < entitiestolayout.length; i++) entitiestolayout[i] = new layoutentity(); randomizepositions(entitiestolayout); collisiondetection(entitiestolayout); (layoutentity entity : entitiestolayout) { node2d node = entity.obj; node.setposition(entity.getxinlayout(), entity.getyinlayout()); } // print possible collisions displaynodes(entitiestolayout); } private void displaynodes(layoutentity[] all) { (layoutentity entity : all) { node2d node = entity.obj; rectangle rect = new rectangle(node.x, node.y, node.w, node.h); rect.setstroke(color.black); rect.setfill(null); root.getchildren().add(rect); } } private void randomizepositions(layoutentity[] entities) { (layoutentity entity : entities) { entity.setlocationinlayout(randint(0, 512), randint(0, 512)); } } private void collisiondetection(layoutentity[] entities) { collisiondetection(arrays.aslist(entities)); } private void collisiondetection(collection<layoutentity> c) { list<layoutentity> collisions = new arraylist<>(); (layoutentity e1 : c) { (layoutentity e2 : c) { if (e1 == e2) continue; boolean collides = checkandresolvecollision(e1, e2); if (collides) collisions.add(e1); } } checkrecursively(collisions, c); } private void checkrecursively(list<layoutentity> collisions, collection<layoutentity> all) { if (collisions.isempty()) return; (layoutentity e1 : all) { (int = 0; < collisions.size(); i++) { layoutentity e2 = collisions.get(i); if (e2 == e1) continue; boolean collides = checkandresolvecollision(e1, e2); if (collides) { if (collisions.contains(e1)) continue; collisions.add(e1); checkrecursively(collisions, all); } } } } private boolean checkandresolvecollision(layoutentity e1, layoutentity e2) { node2d n1 = e1.obj; // ideally, want add gap around boxes double extraspace = 0; double w1 = n1.getwidth() + extraspace * 2; double h1 = n1.getheight() + extraspace * 2; rectangle2d b1 = new rectangle2d(e1.getxinlayout() - extraspace, e1.getyinlayout() - extraspace, w1, h1); node2d n2 = e2.obj; double w2 = n2.getwidth() + extraspace * 2; double h2 = n2.getheight() + extraspace * 2; rectangle2d b2 = new rectangle2d(e2.getxinlayout() - extraspace, e2.getyinlayout() - extraspace, w2, h2); if (b1.intersects(b2)) { point2d trans = getminimumtranslation(b1, b2); double x = e1.getxinlayout() + trans.getx(); double y = e1.getyinlayout() + trans.gety(); e1.setlocationinlayout(x, y); return true; } return false; } private point2d getminimumtranslation(rectangle2d source, rectangle2d target) { double mtdx, mtdy; point2d amin = new point2d(source.getminx(), source.getminy()); point2d amax = new point2d(source.getmaxx(), source.getmaxy()); point2d bmin = new point2d(target.getminx(), target.getminy()); point2d bmax = new point2d(target.getmaxx(), target.getmaxy()); double left = (bmin.getx() - amax.getx()); double right = (bmax.getx() - amin.getx()); double top = (bmin.gety() - amax.gety()); double bottom = (bmax.gety() - amin.gety()); if (left > 0 || right < 0) return point2d.zero; if (top > 0 || bottom < 0) return point2d.zero; if (math.abs(left) < right) mtdx = left; else mtdx = right; if (math.abs(top) < bottom) mtdy = top; else mtdy = bottom; // 0 axis largest mtd value. if (math.abs(mtdx) < math.abs(mtdy)) mtdy = 0; else mtdx = 0; return new point2d(mtdx, mtdy); } private static random rand = new random(); public static int randint(int min, int max) { return rand.nextint((max - min) + 1) + min; } }
from reading code, can predict is, problem in logic. inside checkandresolvecollision()
, when assigning new co-ordinate node
using
e1.setlocationinlayout(x, y);
you miss check whether new co-ordinate have assigned node, overlaps of other node's have checked against one.
you have generate logic, whenever changing co-ordinate of node, must again checked against every other node
hope helps
Comments
Post a Comment