0

I have a problem in my app. I draw lines and points with the help of mouse and I need to detect wether I intersect the line or get the point. And with points it works well, but with lines it doesn't work. I add lines to the AnchorPane. Then I spotted, when cursor is situated inside of 3 lines (Triange) - it's always intersect. Here is my example:

ArrayList<Line> lines = new ArrayList<Line>();
    Line l1 = new Line(10, 150, 50, 10);
    Line l2 = new Line(10, 150, 100, 150);
    Line l3 = new Line(100, 150, 50, 10);
    lines.add(l1);
    lines.add(l2);
    lines.add(l3);

    for (int i=0; i<lines.size();++i) {
        if (lines.get(i).intersects(48, 48, 4, 4)) {
            System.out.println("found a bug!" + " line #"+i);
        }
    }

If someone knew the answer - it would be great!

lummycoder
  • 588
  • 1
  • 7
  • 20
  • I think your question is currently too unclear to answer definitively. Perhaps this related question may help you: [Checking collision of shapes with JavaFX](http://stackoverflow.com/questions/15013913/checking-collision-of-shapes-with-javafx) – jewelsea May 17 '13 at 21:26
  • I've seen this post, it didn't help. I have a click event, and by it I wanna know - if I chose a line (with the help of method intersects), I choose line by line from the list of it and check out whether the line.intersects(event.getX()-2, event.getY()-2, 4,4). But this method works wrongly or maybe I use it not correctly?? – lummycoder May 17 '13 at 22:19

1 Answers1

1

I'll imagine that your question is: how to pick a line by clicking anywhere within two pixels of the line?

In the sample output below, the user has just clicked very close to the right line of the triangle, causing that line to be highlighted.

sample output

The code below works by testing each shape in the pane and seeing if the shape intersects a rectangular box 2 pixels on either side of a mouse press location. The solution is very similar to that used in solving: Checking Collision of Shapes with JavaFX.

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.shape.*;
import javafx.stage.Stage;

public class LinePicker extends Application {
  public static void main(String[] args) { Application.launch(LinePicker.class); }

  @Override public void start(final Stage stage) throws Exception {
    final Pane pane = new Pane();

    pane.getChildren().setAll(
      new Line( 10, 150,  50,  10),
      new Line( 10, 150, 100, 150),
      new Line(100, 150,  50,  10)
    );

    pane.setPrefSize(
      200, 200
    );

    Scene scene = new Scene(addPickHandler(pane));
    stage.setScene(scene);
    stage.show();
  }

  private Pane addPickHandler(final Pane pane) {
    pane.setOnMousePressed(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent event) {
        final Rectangle hotspot = new Rectangle(
          event.getX() - 2, 
          event.getY() - 2, 
          4, 
          4
        );

        for (Node child : pane.getChildren()) {
          if (child instanceof Shape) {
            final Shape shape = (Shape) child;

            Shape intersect = Shape.intersect(shape, hotspot);
            if (intersect.getBoundsInLocal().getWidth() != -1) {
              shape.setStyle("-fx-stroke: red;");
            } else {
              shape.setStyle("-fx-stroke: black;");
            }
          }
        }
      }
    });

    return pane;
  }
}

Comment

It is a little confusing to me why shved90 was unable to get the above solution to function for him in his application.

Shev comments that "In Line, as I understand, it checks all the bounds and if the line would be with some angle its bound would be like rectangle and as a result I check whether I spotted on it (not only on line and its nearest points). But I needed geometry operation."

However the solution presented here is a geometry based solution in that the click hotspot must intersect the actual line and not the rectangular bounds encompassing the line. This is because the Shape.intersect method used in the solution works on the intersection of the actual shapes involved and not the bounds of the shapes involved.

Note however that in the shved90's original question, he uses the Node intersects method rather than the Shape.intersect method. The documentation of Node intersects states "The default behavior of this function is simply to check if the given coordinates intersect with the local bounds.", which, from his comment, is obviously not what shved90 wanted.

Shev does note that "I've found Line2d class in javaFx, as like in Java2D, I convert to this line and use it's intersection". I would not recommend using the Line2D class bundled with JavaFX as it is a private com.sun api that is not guaranteed to be present or have a binary backward compatible API in future JavaFX releases.

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • I've found a workaround)) Your solution didn't suit me, I don't know why, but in my ap, it doesn't work. I've found Line2d class in javaFx, as like in Java2D, I convert to this line and use it's intersection. In Line, as I understand, it checks all the bounds and if the line would be with some angle its bound would be like rectangle and as a result I check whether I spotted on it (not only on line and its nearest points). But I needed geometry operation. – lummycoder May 18 '13 at 15:54
  • Updated answer based on comment. – jewelsea May 20 '13 at 20:40
  • @lummycoder in case you need **geometric operations with lines** (especially `intersect` and `distance`): see: http://stackoverflow.com/questions/32475229/which-point2d-should-i-use/32477652#32477652 – bvdb Sep 10 '15 at 16:31