Punktberechnung im Kreis

dredav

Aktives Mitglied
Hallo,

ich suche eine Möglichkeit zu prüfen, ob ein Punkt in einem Kreis ist. Nun meine frage, gibt es in Java eine Ressourcen schonend Möglichkeit zu prüfen ob ein Punkt in dem Kreis ist. Bisher prüfe ich nur ob die Koordinaten, dem Mittelpunkt des Kreises entsprechen.

Java:
public boolean pruefeObGetroffen (int x, int y) {
    if (x == koordinate.holeKoordinate("x") && y == koordinate.holeKoordinate("y")) {
        return true;
    }
    return false;
}

Grüße
David
 
M

Marcinek

Gast
Du berechnest den Abstand zwischen 2 Punkten (Mittelpunkt und dem zu prüfenden Punkt) mit der Formel aus der 8.Klasse.

Wenn der Abstand kleiner ist als der radius des Kreises, dann liegt der Punkt innerhalb des Kreises.

Das ganze ist in O(1) lösbar und damit effizient.
 

Marco13

Top Contributor
Das ganze ist in O(1) lösbar und damit effizient.

In diesem Fall macht die Betrachtung der asymptotischen Laufzeitkomplexität keinen Sinn. Lapidar formuliert: Wenn es "O(n)" wäre, was sollte 'n' denn dann überhaupt sein? :autsch:

So, wie du es beschrieben hast, sollte man das nicht machen:
Du berechnest den Abstand zwischen 2 Punkten...Wenn der Abstand kleiner ist als der radius des Kreises
Stattdessen:
Du berechnest den quadrierten Abstand zwischen 2 Punkten...Wenn der Abstand kleiner ist als der quadrierte radius des Kreises

Damit spart man sich das Wurzelziehen bei der Abstandsberechnung, und das ist SEHR viel schneller. Wenn dieser Test oft gemacht werden muss, lohnt sich das sogar richtig. Und selbst wenn nicht, macht man das aus Prinzip so :smoke: ;)
 

faetzminator

Gesperrter Benutzer
In deutsch: ein einfacher Pythagoras ;)
Java:
public boolean isInCircle(Point p, Circle c) {
    int x = Math.abs(p.getX() - c.getX());
    int y = Math.abs(p.getY() - c.getY());
    return Math.sqrt(x * x + y * y) <= c.getRadius();
}
 

Marco13

Top Contributor
Java:
public boolean isInCircle(Point p, Circle c) {
    int x = Math.abs(p.getX() - c.getX());
    int y = Math.abs(p.getY() - c.getY());
    int rr = c.getRadius() * c.getRadius();
    return (x * x + y * y) <= rr;
}
 

Final_Striker

Top Contributor
Java:
public boolean isInCircle(Point p, Circle c) {
    int x = Math.abs(p.getX() - c.getX());
    int y = Math.abs(p.getY() - c.getY());
    int r = c.getRadius();
    return (x * x + y * y) <= (r * r);
}

So hat man sich auch noch einen Methodenaufruf gespart. :-D
 

faetzminator

Gesperrter Benutzer
Freaks! :D

Edit:
wenn, dann sowieso als Methode in [c]Circle[/c], also :bae:
Java:
public boolean isInCircle(Point p) {
    int x = Math.abs(p.getX() - getX());
    int y = Math.abs(p.getY() - getY());
    int r = getRadius();
    return (x * x + y * y) <= (r * r);
}
 

Landei

Top Contributor
Wofür nehmt ihr denn alle abs, wenn sowieso quadriert wird?
Java:
public boolean isInCircle(Point p) {
    int x = p.getX() - getX();
    int y = p.getY() - getY();
    int r = getRadius();
    return (x * x + y * y) <= (r * r);
}
 

Semox

Bekanntes Mitglied
Hallo,

Also, wenn man die Punkte in einer ArrayList namens AllNodes hat, kann man doch nach Import von java.awt.Point folgende Operation laufen lassen. Wenn der Kreis einen Durchmesser mit dem Attribut DIA hat, dann erledigt das prüfen, ob z.B. ein Klick in einem Kreis liegt die Methode distance().

Java:
public void mouseClicked(MouseEvent e) {
		q = e.getPoint();
		for (Iterator<Point> iterator = AllNodes.iterator(); iterator
			.hasNext();) {
			Point p = iterator.next();
			if (p.distance(q) <= DIA) {
				System.out.println("Der Klick war innem Kreis");
			}
		}
}

Hilft das weiter?

Gruß,
Semo
 

Antoras

Top Contributor
Wer versichert dir, dass Point nicht eine selbst erstellte Klasse ist? Man muss nicht java.awt.Point benutzen. Im übrigen berechnet distance() noch die Wurzel. Das ist wie schon gesagt langsamer als eine Multiplikation.
Außerdem gibt es in Java mittlerweile eine foreach-Schleife, die man auch verwenden sollte.
 

Semox

Bekanntes Mitglied
Wer versichert dir, dass Point nicht eine selbst erstellte Klasse ist? Man muss nicht java.awt.Point benutzen. Im übrigen berechnet distance() noch die Wurzel. Das ist wie schon gesagt langsamer als eine Multiplikation.
Außerdem gibt es in Java mittlerweile eine foreach-Schleife, die man auch verwenden sollte.

Ich verstehe Deine Frage nicht. Wie meinst Du das?

Man muß meinen Vorschlag auch nicht annehmen.

Warum sollte das Wurzelziehen langsamer sein? Das ist nicht wahr, denn intern wird der Prozi sich wegen dieser Kleinigkeit bestimmt nicht wirklich beeindrucken lassen, denn die Wurzel wird ohnehin über Potenzgesetze intern als eine Multiplikation angesehen.

For-Each - stimmt - kann man auch benutzen. Jeder nach seiner Façon... ;)

Gruß,
Semo
 

Antoras

Top Contributor
Ich meinte damit, dass man mit deiner Lösung nur dann was anfangen kann wenn man java.awt.Point verwendet.

Bei der Wurzelberechnung kenne ich nur ein paar Software-Algos, die um einiges langsamen und komplexer als eine Multiplikation sind. Wie die CPU/FPU das berechnet weiß ich nicht. Selbst wenn der Geschwindigkeitsunterschied nur minimal ist dürfte das aber ohnehin nur einen spürbaren Unterschied machen wenn man mal eine Million Punkte hat.
 

Semox

Bekanntes Mitglied
Ich weiß auch nicht, ob es relevant ist die Point Klasse einzusetzen. Das geht aus dem Startpost auch nicht hervor, ob das für ihn/sie rein von mathematischem Interesse ist, oder ob das mal ein Kollisionstest für ein Spiel o.ä. werden soll.

Ich fand es schlicht smarter eine fertige Methode zu nutzen, die in der API bereitsteht. Vorallem dann, wenn man sich damit einige Zeilen Code und der daraus resultierenden Fehlerquellen sparen kann (obwohl die paar Zeilen den Kohl auch nicht fett machen würden). :D

Letztendlich kann er/sie auf jeden Fall mal in der Klasse nachschauen, wie die Java Coder das machen... Ich finde deren Ideen doch recht kurz und prägnant. Und je kürzer desto schöner... :toll:

Viele Grüße,
Semo
 

Marco13

Top Contributor
Das ist nicht wahr, denn intern wird der Prozi sich wegen dieser Kleinigkeit bestimmt nicht wirklich beeindrucken lassen, denn die Wurzel wird ohnehin über Potenzgesetze intern als eine Multiplikation angesehen.

Es gibt schon einen Grund, warum es in der Point-Klasse auch eine Methode "distanceSq" gibt: Wurzelberechnung IST aufwändig. Sie wird nativ durchgeführt, aber es ist auf jeden Fall besser, wenn sie nicht durchgeführt werden muss.

Ein kleiner Monte-Carlo-PI-Brechnungs-Microbenchmark (der mit der üblichen Vorsicht zu genießen ist, aber schon einen Unterschied zeigt)
Java:
import java.util.*;
import java.awt.*;
import java.util.List;

class DistanceTest
{
    static int size = 1000;

    public static void main(String args[])
    {
        int min = 500000;
        int max = 5000000;
        for (int n=min; n<=max; n+=(max-min)/5)
        {
            System.out.println("n="+n);

            Random random = new Random(0);
            List<Point> points = new ArrayList<Point>();
            for (int i=0; i<n; i++)
            {
                int x = random.nextInt(size);
                int y = random.nextInt(size);
                points.add(new Point(x,y));
            }

            long before, after;
            double pi, time;

            before = System.nanoTime();
            pi = test(points);
            after = System.nanoTime();
            time = (after-before)/1e6;
            System.out.println("PI: "+pi+" time         "+time+"ms");

            before = System.nanoTime();
            pi = testSq(points);
            after = System.nanoTime();
            time = (after-before)/1e6;
            System.out.println("PI: "+pi+" time squared "+time+"ms");
        }


    }

    private static double test(List<Point> points)
    {
        int count = 0;
        for (Point point : points)
        {
            if (point.distance(0,0) < size)
            {
                count++;
            }
        }
        return 4.0*count/points.size();
    }
    private static double testSq(List<Point> points)
    {
        int count = 0;
        int ss = size*size;
        for (Point point : points)
        {
            if (point.distanceSq(0,0) < ss)
            {
                count++;
            }
        }
        return 4.0*count/points.size();
    }
}
 

Semox

Bekanntes Mitglied
Hübscher Test. Gefällt mir. Es steht natürlich außer Frage, daß man bei Millionen Punkten tatsächlich einen hübschen Betrag Zeit braucht, wenn alles über Umwandlungen von Wurzeln laufen muß.

Mich würde mal der perfekte Algo interessieren, wie der wohl aussieht?

Grüße,
Semo
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
YAZZ BlueJ Bewegung einer Figur im Kreis Java Basics - Anfänger-Themen 4
J Kreis soll die gleiche Fläche wie das Rechteck haben wie mache ich das? Java Basics - Anfänger-Themen 3
N Kreismuster auf Bestehendem Kreis erstellen Java Basics - Anfänger-Themen 10
E Kreis soll eine Raupe darstellen Java Basics - Anfänger-Themen 37
C Kleinsten Kreis einer Punktmenge bestimmen Java Basics - Anfänger-Themen 4
CptK Interface Kleine Kreise in großem Kreis anordnen Java Basics - Anfänger-Themen 3
Y Kreis auf einer Kreisbahn bewegen Java Basics - Anfänger-Themen 5
P Erste Schritte Kreis animieren Java Basics - Anfänger-Themen 2
A Kreisumfang/-Fläche vom Kreis berechnen Java Basics - Anfänger-Themen 39
H Kreis verschieben Java Basics - Anfänger-Themen 10
Z Object Kreis am Frame abprallen lassen! Java Basics - Anfänger-Themen 12
X Kreis/Linie Programmieren Java Basics - Anfänger-Themen 1
D Algorithmus für Punkte auf einem Kreis Java Basics - Anfänger-Themen 0
L Dreieck Kreis Java Basics - Anfänger-Themen 12
A Kreis,Radius Programm Java Basics - Anfänger-Themen 3
N Per Button Kreis zeichnen Java Basics - Anfänger-Themen 8
C Kreis nach Mausklick zeichnen Java Basics - Anfänger-Themen 5
A wie Kreis mit Schleife versetzten? Java Basics - Anfänger-Themen 25
O Punkte auf einem Kreis "wandern" lassen Java Basics - Anfänger-Themen 3
U Kreis um Textfelder zeichnen Java Basics - Anfänger-Themen 4
D Kreis mit Pfeiltaste bewegen Java Basics - Anfänger-Themen 3
K Bild auf Kreis packen Java Basics - Anfänger-Themen 2
E Kreis erstellen Java Basics - Anfänger-Themen 10
B Einen Kreis erzeugen Java Basics - Anfänger-Themen 3
S Erzeuge einen Kreis Java Basics - Anfänger-Themen 16
B Kreis,Punkt,Zylinder Java Basics - Anfänger-Themen 6
TheKing Bild nur in Kreis sichtbar machen Java Basics - Anfänger-Themen 6
K Kreis mit neuer Position zeichnen Java Basics - Anfänger-Themen 3
M Umfang von Rechteck oder Kreis anhand der Parameter Java Basics - Anfänger-Themen 2
L Klickbarer Bereich in einem Kreis Java Basics - Anfänger-Themen 13
D kreis gelb gefüllt aber schwarzer rand. Java Basics - Anfänger-Themen 2
K Kreis Zeichnen ? Code Richtig aber keine Zeichung Java Basics - Anfänger-Themen 8
L Kreis der sich bewegt Java Basics - Anfänger-Themen 11
G Kreis auf JComponent zeichnen Java Basics - Anfänger-Themen 8
0 Klasse Kreis Java Basics - Anfänger-Themen 4
P Java-Applet, Kreis zeichnen Java Basics - Anfänger-Themen 4
E Kreis in Frame ,den man mit der Maus versetzen kann? Java Basics - Anfänger-Themen 2
7 Kreis zeichnen Java Basics - Anfänger-Themen 4
J Kreis herumfliegen & abprallen von Rändern Java Basics - Anfänger-Themen 7
G contains - Punkt in Kreis enthalten? Java Basics - Anfänger-Themen 6
A Kreis mit gedrückter Maustaste bewegen. Java Basics - Anfänger-Themen 2
S Thread - Kugel im Kreis hin-und herflitzen lassen Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben