Wie funktioniert contains() für Path2D.Double

CptK

Bekanntes Mitglied
Hallo, ich habe eine Path2D.Double line, der folgendermaßen gezeichnet wird:
Java:
line = new Path2D.Double();
line.moveTo(origin.x, origin.y);
line.curveTo(origin.x, origin.y, anchor.x, anchor.y, destination.x, destination.y);
line.moveTo(destination.x, destination.y);
line.closePath();

Graphics2D g2 = (Graphics2D) g;
g2.draw(line);

Nun habe ich noch einen Methode onClick(), die ausgeführt wird, wenn geklickt wird. In dieser soll überprüft werden, ob der geklickte Punkt auf der Linie liegt:
Java:
public void onClick(int x, int y) {
    if(line.contains(x, y)) {
        ....
    }
}
Allerdings liefert der Test von contains() immer false, selbst wenn ich ihn mit einem der Punkte aufrufe, mit denen ich die Linie gezeichnet habe. Wie verwendet man das richtig, so dass es auch funktioniert?
 
Nun habe ich noch einen Methode onClick(), die ausgeführt wird, wenn geklickt wird. In dieser soll überprüft werden, ob der geklickte Punkt auf der Linie liegt:
contains überprüft ob sich der angegebene Punkt innerhalb des Polygons ,das durch den Pfad erzeugt wird, befindet.
Das setzt voraus, dass der Pfad geschlossen ist. Außerdem muss man auf die Reihenfolge der Punkte aufpassen. Z.B. 4 Punkte erzeugen in der richtigen Reihenfolge ein Rechteck. Andernfalls erhält man eine Form wo sich Linien kreuzen.
 
contains überprüft ob sich der angegebene Punkt innerhalb des Polygons ,das durch den Pfad erzeugt wird, befindet.
Das setzt voraus, dass der Pfad geschlossen ist. Außerdem muss man auf die Reihenfolge der Punkte aufpassen. Z.B. 4 Punkte erzeugen in der richtigen Reihenfolge ein Rechteck. Andernfalls erhält man eine Form wo sich Linien kreuzen.
hm okay also das Zeichnen funktioniert ja einwandfrei, und ich möchte ja nur diese eine Linie haben. Muss ich dann die gleiche Linie noch mal zurück zeichnen also ungefähr so:
Java:
line.moveTo(origin.x, origin.y);
line.curveTo(origin.x, origin.y, anchor.x, anchor.y, destination.x, destination.y);
line.moveTo(destination.x, destination.y);
line.curveTo(destination.x, destination.y, anchor.x, anchor.y, origin.x, origin.y);
line.closePath();
 
Der Pfad muss nicht geschlossen sein.
Code:
jshell> var path = new Path2D.Double();
path ==> java.awt.geom.Path2D$Double@7740a2

jshell> path.moveTo(10, 10)

jshell> path.lineTo(20, 10)

jshell> path.lineTo(20, 0)

jshell> path.contains(5, 5)
$36 ==> false

jshell> path.contains(15, 5)
$37 ==> true
 
Das mit dem contains() hat bei mir ja irgendwie nicht funktioniert, ich habe das jetzt so gelöst:
Java:
public boolean isClicked(int x, int y) {
    final int HIT_BOX_SIZE = 20;
    int boxX = x - HIT_BOX_SIZE / 2;
    int boxY = y - HIT_BOX_SIZE / 2;

    int width = HIT_BOX_SIZE;
    int height = HIT_BOX_SIZE;
    return line.intersects(boxX, boxY, width, height);
}
 
Das mit dem contains() hat bei mir ja irgendwie nicht funktioniert, ich habe das jetzt so gelöst:
Ja, das sieht gut aus. contains() prüft, ob der angegebene Punkt Teil der Fläche ist, die durch den Pfad begrenzt wird (nach festgelegten Regeln). Du willst eigentlich prüfen, ob ein Punkt auf dem Pfad selbst liegt. Das ist m. E. nicht unmittelbar möglich, aber über ein Rechteck, das den angeklickten Punkt umgibt, wirst Du einen Schnittpunkt mit dem Innern finden.
 
Ich habe jetzt noch eine weiterführende Frage:
Ich habe nun ein Objekt, dass ich dann um einen gewissen Winkel rotiere:
Java:
AffineTransform old = g2.getTransform();
g2.rotate(Math.toRadians(rotationAngle), from.x(), from.y());
line.moveTo(from.x(), from.y());
line.curveTo(from.x(), from.y(), anchor.x - 40, anchor.y + 10, anchor.x, anchor.y);
line.moveTo(anchor.x, anchor.y);
line.curveTo(anchor.x, anchor.y, anchor.x + 40, anchor.y + 10, to.x(), to.y());
line.moveTo(to.x(), to.y());
line.closePath();
g2.drawString(String.valueOf(letter), anchor.x - 2, anchor.y - 5);
g2.draw(line);
g2.setTransform(old);

Wenn ich jetzt aber meine Schnittberechnung darauf anwende, funktioniert das logischerweise nicht, weil das Objekt an sich ja nicht rotiert ist, sondern nur die Zeichnung. Wie mache ich das, dass meine Schnitt-Erkennung auch mit der rotierten Zeichnung umgehen kann?
Im Prinzip wäre es doch am einfachsten, das Viereck, mit dem ich vergleiche, mit dem gleichen Winkel um den gleichen Mittelpunkt zu rotieren und dann abzugleichen richtig? Jetzt komme ich nur nicht auf eine Abbildung, mit der das gelingt..
 
Vermutlich irgendwas wie
Java:
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(rotationAngle), from.x(), from.y());
Shape rotated = at.createTransformedShape(rectangle);
line.intersects(rotated);
Wobei der Winkel entgegengesetzt sein müsste.
 
Vermutlich irgendwas wie
Java:
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(rotationAngle), from.x(), from.y());
Shape rotated = at.createTransformedShape(rectangle);
line.intersects(rotated);
Wobei der Winkel entgegengesetzt sein müsste.

Java:
final int HIT_BOX_SIZE = 10;
Rectangle2D rectangle = new Rectangle(x - HIT_BOX_SIZE / 2, y - HIT_BOX_SIZE / 2, HIT_BOX_SIZE, HIT_BOX_SIZE);
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(360 - rotationAngle), from.x(),from.y());
Shape rotated = at.createTransformedShape(rectangle);
return line.intersects(rotated);
Ich kann intersects() nicht mit einem aktualen Parameter vom typ Shape aufrufen und Shape kann man auch nicht zu Rectangle2D casten. Ich finde keine Lösung, mit der das funktioniert
 
Zuletzt bearbeitet:
Java:
final int HIT_BOX_SIZE = 10;
Rectangle2D rectangle = new Rectangle(x - HIT_BOX_SIZE / 2, y - HIT_BOX_SIZE / 2, HIT_BOX_SIZE, HIT_BOX_SIZE);
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(360 - rotationAngle), from.x(),from.y());
Shape rotated = at.createTransformedShape(rectangle);
return line.intersects(rotated);
Ich kann intersects() nicht mit einem aktualen Parameter vom typ Shape aufrufen und Shape kann man auch nicht zu Rectangle2D casten. Ich finde keine Lösung, mit der das funktioniert
Habs:
Java:
return line.intersects(rotated.getBounds2D());
 
Diese Linien machen mich noch wahnsinnig.... Ich habe ein Problem:
Die Linien gehen vom Mittelpunkt eines Kreises zum Mittelpunk eines anderen Kreisen und laufen über einen Ankerpunkt. Wenn ich diesen Ankerpunkt jetzt verschiebe, laufen die Linien nicht mehr durch den Ankerpunkt, sondern daneben, wodurch sich 2 Probleme ergeben:
1. Die Pfeilspitzen am Ende der Linie passen nicht mehr richtig
2. Ich nutze den Anker auch, um eine Position für eine Beschriftung zu finden, allerdings ist diese dann sehr weit von der Linie entfernt

Hier einmal ein Bild von dem, was ich meine:
1616534857454.png

Hier nochmal der Code wie ich die Line rotiere:
Java:
AffineTransform old = g2.getTransform();
g2.rotate(Math.toRadians(rotationAngle), from.x(), from.y());
line.moveTo(from.x(), from.y());
line.curveTo(from.x(), from.y(), anchor.x - 40, anchor.y + 10, anchor.x, anchor.y);
line.moveTo(anchor.x, anchor.y);
line.curveTo(anchor.x, anchor.y, anchor.x + 40, anchor.y + 10, to.x(), to.y());
line.moveTo(to.x(), to.y());
line.closePath();
g2.drawString(String.valueOf(letter), anchor.x - 2, anchor.y - 5);
g2.draw(line);
g2.setTransform(old);

Hat da jemand einen Tipp, wie ich das besser lösen könnte?
 

Neue Themen


Zurück
Oben