Reputation: 541
I'm currently working on intersect of bounds between different shapes with JavaFX. I would like to detect collision of two polygons on their points and not on their bounds (i.e. 2 polygons).
Please, see figure 1: not desired behavior, and figure 2: desired behavior.
Is there any existing algorithm to help me or any library to use? Thanks in advance :)
Here find my solution :
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class Tester extends Application {
@Override
public void start(Stage stage) throws Exception {
Pane root = new Pane();
root.setStyle("-fx-background-color:cyan;");
Polygon p1 = new Polygon();
p1.getPoints().addAll(new Double[]{
50.,50.,
50.,100.,
60.,100.,
60.,80.,
80.,70.,
80.,100.,
100.,100.,
100.,50.
});
p1.setFill(Color.GREEN);
Polygon p2 = new Polygon();
p2.getPoints().addAll(new Double[]{
65.,100.,
65.,90.,
75.,80.,
100.,100.
});
p2.setFill(Color.RED);
root.getChildren().addAll(p1,p2);
stage.setScene(new Scene(root));
stage.show();
Shape inter = Shape.intersect(p1, p2);
root.getChildren().add(inter);
System.out.println(inter.getLayoutBounds().getWidth() + ":" + inter.getLayoutBounds().getHeight());
if(inter.getLayoutBounds().getHeight()<=0 || inter.getLayoutBounds().getWidth()<=0) {
System.out.println("No intersection");
}
else {
System.out.println("intersection detected");
}
}
public static void main(String[] args) {
launch(args);
}
}
Output:
20.0:16.0
intersection detected
It seems to work properly, I will test with Path objects to replace Polygon objets.
Upvotes: 3
Views: 9500
Reputation: 92
Look at this reference OpenMap-java
Sample code example:
public static HashMap<AirDefenceZone, BoundingCircle> circleHashMap = new HashMap<>();
public static HashMap<AirDefenceZone, GeoRegion> regionHashMap = new HashMap<>();
public static boolean isPointInside(double lat, double lon, AirDefenceZone zone){
if(zone == null){
return false;
}
boolean isPointInside = false;
try {
Geo geo = new Geo(lat, lon, true);
if(zone.distance > 1){
BoundingCircle boundingCircle = circleHashMap.get(zone);
if(boundingCircle == null){
boundingCircle = newBoundingCircle(zone);
circleHashMap.put(zone, boundingCircle);
}
isPointInside = boundingCircle.intersects(geo, 0);
}else{
GeoRegion geoRegion = regionHashMap.get(zone);
if(geoRegion == null){
geoRegion = newGeoRegion(zone);
regionHashMap.put(zone, geoRegion);
}
isPointInside = geoRegion.isPointInside(geo);
}
} catch (Exception e) {}
return isPointInside;
}
private static BoundingCircle newBoundingCircle(AirDefenceZone zone){
List<Double> doubles = zone.locations.get(0);
double lon = doubles.get(0);
double lat = doubles.get(1);
double radius = zone.distance;
Geo center = Geo.makeGeoDegrees(lat, lon);
BoundingCircle boundingCircle = new BoundingCircle.Impl(center, radius);
return boundingCircle;
}
private static GeoRegion newGeoRegion(AirDefenceZone zone){
int i = 0;
double[] poly = new double[zone.locations.size() * 2];
for(List<Double> doubles : zone.locations){
double lon = doubles.get(0);
double lat = doubles.get(1);
poly[i++] = lat;
poly[i++] = lon;
}
//GeoArray ga = GeoArray.Double.createFromLatLonDegrees(poly);
GeoRegion reg = new GeoRegion.Impl(poly);
return reg;
}
Upvotes: 0
Reputation: 11
I was playing with your codes\, and I found this solution, I added mouse event to the polygon2
, then I modified the if statement. If not too late, try.
public class Tester extends Application {
Shape inter;
Point2D pc;
double initX, initY, mx, my;
@Override
public void start(Stage stage) throws Exception {
Pane root = new Pane();
root.setStyle("-fx-background-color:cyan;");
final Polygon p2 = new Polygon();
final Polygon p1 = new Polygon();
p1.getPoints().addAll(new Double[]{
50., 50.,
50., 100.,
60., 100.,
60., 55.,
80., 70.,
80., 100.,
100., 100.,
100., 50.
});
p1.setFill(Color.GREEN);
p2.getPoints().addAll(new Double[]{
65., 100.,
65., 45.,
75., 80.,
100., 100.
});
p2.setFill(Color.RED);
p1.setTranslateX(400);
p1.setTranslateY(250);
p2.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
initX = p2.getTranslateX();
initY = p2.getTranslateX();
pc = new Point2D(me.getSceneX(), me.getSceneY());
}
});
p2.setOnMouseDragged(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
double dragX = me.getSceneX() - pc.getX();
double dragY = me.getSceneY() - pc.getY();
double newXPosition = initX + dragX;
double newYPosition = initY + dragY;
p2.setTranslateX(newXPosition);
p2.setTranslateY(newYPosition);
System.out.println("no intersection");
if (Shape.intersect(p2, p1).getBoundsInLocal().isEmpty() == false) {
p1.setTranslateX(p2.getTranslateX() + mx);
p1.setTranslateY(p2.getTranslateY() + my);
System.out.println("colision");
} else {
mx = p1.getTranslateX() - p2.getTranslateX();
my = p1.getTranslateY() - p2.getTranslateY();
}
}
});
root.getChildren().addAll(p1, p2);
final Scene scene = new Scene(root, 1200, 850);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1
Reputation: 8005
If you can use the java.awt.geom
package in your application, I suggest you take a look at the Area
class and especially the intersect
method.
Basically you can do this:
area1.intersect(area2);
boolean areasintersect = !area1.isEmpty();
You can create arbitrary areas using the GeneralPath
class in the same package.
Upvotes: 1