# Punkt auf Geometrie



## xtreme (11. Okt 2008)

Hi ihrs,

wollt mal fragen, ob es außer der Möglichkeit mit contains() zu ermitteln, ob ein Punkt in einer Geometrie liegt, auch eine Möglichkeit gibt zu ermitteln, ob ein Punkt genau auf einer Geometrie liegt, also sowas wie hit().

Denn per Mausklick kann ich zwar mit contains() eine Ellipse oder ein Rechteck markieren, wenn der Punkt darin liegt, aber das muss ja auch irgendwie mit einer Linie zu machen sein. Denn letztendlich will ich die auch markieren und später einmal verschieben oder verändern können.

Danke für Tipps


----------



## Marco13 (11. Okt 2008)

Ob es die in der API vorgefertigt gibt, kannst du selbst nachsehen. Aber wenn nicht: Falls es immer um ein "Shape" oder einen GeneralPath geht, kann man den Pfad natürlich langlaufen, und den Abstand des Punktes zu jedem Liniensegment bestimmen. Wenn der ungefähr 0 ist, hat man die Linie getroffen.


----------



## xtreme (13. Okt 2008)

> Falls es immer um ein "Shape" oder einen GeneralPath geht, kann man den Pfad natürlich langlaufen, und den Abstand des Punktes zu jedem Liniensegment bestimmen. Wenn der ungefähr 0 ist, hat man die Linie getroffen.



Mhm aber bei einer Linie liefert doch auch der PathIterator nicht alle Linienpunkte sondern nur Anfangs- und Endpunkt oder?


```
Line2D.Double shape = new Line2D.Double(xPoints, yPoints);
		
PathIterator itr = shape.getPathIterator(new AffineTransform());
		
double[] coords = new double[2];
		
while(!itr.isDone()){
	itr.currentSegment(coords);
	System.out.println(coords[0] + ", " + coords[1]);
	itr.next();
}
```

Will ich nun prüfen, ob der übergebene Punkt drauf liegt, sieht das Ganze so aus:



> public boolean Hit(Point pt)
> {
> boolean hit = false;
> 
> ...



Das geht allerdings nur bedingt. Denn nur wenn ich auf den ersten und letzten Punkt der Linie klicke, bekomme ich eine TRUE zurück. In coords[0] und coords[1] liegen doch jeweils x und y im jeweiligen Schleifendurchlauf oder nicht? Wie muss ich es sonst anstellen?


----------



## Marco13 (13. Okt 2008)

Du kannst dir aus zwei aufeinanderfolgenden Punkte eine http://java.sun.com/j2se/1.4.2/docs/api/java/awt/geom/Line2D.Double.html erstellen und dann mit http://java.sun.com/j2se/1.4.2/docs/api/java/awt/geom/Line2D.html#ptLineDist(double,%20double) die Entfernung des Punktes zu der Linie abfragen. So ein GeneralPath kann aber auch Bezier-Segmente enthalten, da muss man ggf. ein bißchen basteln...


----------



## xtreme (13. Okt 2008)

Hi,

danke erstmal für deine Tipps. Irgendwie verhält sich das aber sehr komisch bei mir.

Ich versuche eine Linie zu markieren und sie dann zu bewegen. Bilde ich aus dem Path ein Rechteck, kann ich die Line jederzeit anfassen. Versuche ich es über die ptLineDist kann ich die Line einmal anfassen. Danach geht es nur noch, wenn ich die Linie am unteren Ende anfasse.

Hier mal mein Code:


```
public boolean Hit(Point pt)
    {
        Rectangle rec = super.getPathBounds();
        rec.x -= getPenWidth() + 5;
        rec.y -= getPenWidth() + 5;
        rec.width += 2 * (getPenWidth() + 5);
        rec.height += 2 * (getPenWidth() + 5);

        return rec.contains(pt);
    }
```

oder eben


```
public boolean Hit(Point pt)
    {        
        Line2D.Double myLine = new Line2D.Double(super.getStart(), super.getEnd());
        int dist = (int)myLine.ptLineDist(pt);
        
        if(dist < 5)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
```


----------



## Marco13 (13. Okt 2008)

Was auch immer "super" im zweiten Fall ist: Diese Linie muss man natürlich nicht nur für EIN Liniensegment des Paths erstellen, sondern für alle Segmente ... also wie du vorher schon angedeutet hattest, mit einem PathIterator durchgehen und jeweils eine Line2D für den vorherigen und den aktuellen Punkt erstellen.


----------



## xtreme (13. Okt 2008)

getStart() und getEnd() stehen für den Start- und Endpunkt der Linie, die ich in einer übergeordneten Klasse (deswegen super) als Member führe. Demnach brauche ich aus dem Path keine Linie für einzelne Segmente bilden, sondern kann die  komplette Linie von Anfang bis Ende mit meinen beiden Punkten neubilden. 

Aber wie gesagt, so ganz funktioniert es nicht.


----------



## Marco13 (13. Okt 2008)

???:L Wenn man einen Path hat, der die form von einem "U" hat, dann bringt es nichts, wenn man die Linie zwischen dem Start- und dem Endpunkt betrachtet - dort "ist" ja keine linie. Man muss schon die einzelnen Segmente durchgehen....  ???:L


----------



## xtreme (13. Okt 2008)

Versteh ich nicht wirklich.

Ich habe einen Path. Dieser Path ist eine Linie!!! Diese Linie bilde ich aus zwei Punkten. Nun möchte ich schauen, ob ein Mausklick auf eben dieser Linie liegt.

OK man kann den Umweg über den Path vergessen. Nehmen wir einfach an, wir haben eine Linie (keinen Path). Dann habe ich das obige Problem aber immer noch. Ich checke ob mein Punkt in einer bestimmten Distanz zu meiner Linie liegt. Wenn er diese Distanz oder darunter einhält, dann soll diese Linie markiert werden (wie diese Markierung läuft, sei mal egal). 

Aber leider kann ich über dtLineDist nur einmal die Distanz abfragen, danach funktioniert es nicht mehr. Aber warum?

Sorry wenns vorher ein wenig unverständlich war, hoffe hiermit gehts besser.


----------



## Marco13 (13. Okt 2008)

Ein Path ist aber im Allgemeinen MEHR als eine Linie. Wenn er nur eine Linie ist, kann man auch gleich Line verwenden. However - kannst du ein compilierbares Codestück posten, wo das Problem auftritt?


----------



## xtreme (13. Okt 2008)

Wie du möchtest. Ist ein wenig lang, aber ich habe schon das meiste herausgenommen bzw. eine kleine Testapi geschrieben. Das Packet habe ich testpaint genannt und die Hauptklasse heißt Main. Achtung: Ich habe alles in eine Datei geschoben und mir daher keine Gedanken über die Übergabe von Parametern gemacht, sondern diese mehr oder wenig auch global benutzt. 

Das Problem taucht auch hier auf. Ich kann die Linie einmal verschieben, danach ist sie nur noch verschiebbar, wenn man den unteren linken Punkt geklickt hält.


```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package testpaint;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

/**
 *
 * @author Administrator
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
      DrawingSurface m = new DrawingSurface();
      m.setSize(500, 500);
      m.setLocation(0, 0);
      m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      m.setVisible(true);
    }

}


class DrawingSurface extends JFrame implements MouseMotionListener, MouseListener
{
   private PaintingComponent paintingComponent = new PaintingComponent(this);
   
   MyLine _geo = new MyLine(new Point(10,10), new Point(100,100));
   
   //Selektiertes Object
   Geometry _selectedGeometry = null;
   
   //Mausposition der Selektion
   private Point _lastMouseLocation;

   public DrawingSurface() {
        getContentPane().add(paintingComponent);
        getContentPane().addMouseMotionListener(this);
        getContentPane().addMouseListener(this);   
   }
   
   public void redraw()
   {
       paintingComponent.repaint();
   }


   
   public void mousePressed(MouseEvent e) {
        //Bei linkem Mausklick wird das Fenster aktiviert und...
        if (this.contains(e.getPoint()) && !e.isMetaDown())
        {
            if (_geo.Hit(e.getPoint()))
            {
                _selectedGeometry = _geo;

                _lastMouseLocation = e.getPoint();
            }
        }
    }
   
   public void mouseDragged(MouseEvent e) {
        if(!e.isMetaDown() && _selectedGeometry != null)
        {
            _selectedGeometry.Move(e.getPoint().x - _lastMouseLocation.x, e.getPoint().y - _lastMouseLocation.y);

            _lastMouseLocation = e.getPoint();

            this.redraw();
        }
    }
   
    public void mouseReleased(MouseEvent e) {
        _selectedGeometry = null;
    }

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }
}



class Geometry {
    
    Point _start;
    Point _end;
            
    Path2D.Double _path = new Path2D.Double();
    
    public Geometry(Point start, Point end){
        _start = start;
        _end = end;
    }
    
    public void Move(int deltaX, int deltaY)
    {

        AffineTransform at = new AffineTransform(); 
        at.translate(deltaX, deltaY);
        _path.transform(at);

        //Setzen der neuen Start- und Endpunkte
        _start.x += deltaX;
        _start.x += deltaY;

        _end.x += deltaX;
        _end.y += deltaY;
    }
    
    //Methode zum Zeichnen des Pfades und ggf. des Rahmens
    public void draw(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;

        g2d.setColor(Color.black);
        g2d.setStroke(new BasicStroke(1));
        g2d.draw(_path);
    }
    
    public boolean Hit(Point pt)
    {
        return false;
    }
    
    //Methode zum Hinzufügen der Geometry zum Path
    protected void AddToPath() 
    {           
        //Default
        _path = new Path2D.Double(new Line2D.Double(_start, _end));
    }
}


class MyLine extends Geometry{
    public MyLine(Point start, Point end){
        super(start, end);
        AddToPath();
    }
    
    @Override
    public boolean Hit(Point pt)
    {   
        Line2D.Double myLine = new Line2D.Double(super._start, super._end);
        int dist = (int)myLine.ptLineDist(pt);
        
        if(dist < 5)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    @Override protected void AddToPath()
    {
        super._path.append(new Line2D.Double(super._start, super._end), true);
    }
}


class PaintingComponent extends JComponent
{
    private DrawingSurface _surface;
    
    public PaintingComponent(DrawingSurface surface)
    {
        _surface = surface;
    }
    
   public void paintComponent(Graphics g){
       super.paintComponents(g);
       _surface._geo.draw(g);
   }
}
```


----------



## Marco13 (13. Okt 2008)

Der Code ist als KSKB perfekt: Rauskopieren, in TextPad einfügen, Compilieren, Starten. Kein Zusammenkopieren einzelner Dateien, kein Aufräumen von imports, kein Hinzufügen einer main - so sollten alle KSKBs sein.

Und dann findet man auch schnell eine Lösung.

```
class MyLine extends Geometry
{
...
    public void draw(Graphics g)
    {
        super.draw(g);
        g.setColor(Color.RED);
        g.fillOval(super._start.x-2, super._start.y-2, 4,4);
        g.fillOval(super._end.x-2, super._end.y-2, 4,4);
    }
}
```

Einfügen, starten, Linie verschieben, kurz irritiert gucken, Fehler finden :wink: 

(Das mit dem Path und so sieht etwas merkwürdig aus ... aber du wirst schon wissen, was du tust...)


----------



## xtreme (13. Okt 2008)

Oh man, DANKE! 

Den Fehler muss man erstmal in seinem im Originial etwas fetteren Code finden! 

Aber cool, nun gehts.


----------



## Loonatic (20. Jul 2009)

Hallo zusamen, hab vollgendes Problem ich brauch eine gängige Formel um die Schnittpunkte von einem Kreis und einer Geraden zu bestimmen. Hab schon eineige Formeln gesehen aber leider kann ich nichts mie ihenen anfangen würde mich sehr freuen wenn da jemand was parat hat...

Danke im Vorraus. 

mfg Loonatic


----------



## Marco13 (20. Jul 2009)

Schau mal unter Geometric Tools: Intersection  "Intersection of lines, rays, or line segments with circles or arcs (2D).". Da gibt's ein PDF, kannst mal schauen was drinsteht, und im Zweifelsfall gibt's auch gleich den Code, den man i.a. mit relativ wenig Aufwand nach Java portieren kann.


----------



## Loonatic (21. Jul 2009)

Hey geil auf den ersten Bilck sieht es richtig gut aus muss allerdings noch die Sachen genauer durchsehen aber ich denk mal damit kann ich sicher was anfangen 

Danke nochmal 

mfg Loonati


----------



## Loonatic (23. Jul 2009)

Hallo zusammen hoffe das untereuch jemand ist der mir vielleicht helfen kann. 

Ich hab ein 2d Grid mit 10 mal 10 zellen. In diese Zellen werden nun Kreisflächen mit random eingefügt. jetzt brauch ich einen Algorithmus der mir anhand der Kreisfläche sagen kann welche Zellen der Kreis berührt also auch die Zellen die von der Ausenkande geschnitten werden und die Zellen die komplett im Kreis liegen. 

Ich komm da sowas wie von nicht weiter und hoffe jemand kann mir dabei helfen. 

Wäre zu tiefst dankbar. 

mfg Loonatic???:L


----------



## Marco13 (23. Jul 2009)

Schau mal unter Geometric Tools: Intersection  "Intersection of lines, rays, or line segments with circles or arcs (2D).". Da gibt's ein PDF, kannst mal schauen was drinsteht, und im Zweifelsfall gibt's auch gleich den Code, den man i.a. mit relativ wenig Aufwand nach Java portieren kann.


----------



## Loonatic (23. Jul 2009)

ja danke leider komm ich damit auch nicht weiter trotzdem danke


----------



## Marco13 (23. Jul 2009)

Ja, sollte nur ein Wink sein. Bei einem regelmäßigen Gitter braucht man ja gar nicht so aufwändig rumzurechnen. Da reicht es schon, wenn man schaut, ob die Entfernung des Mittelpunktes des Kreises zu irgendeiner Linie größer oder kleiner ist als der Radius....


----------



## Loonatic (23. Jul 2009)

Ja klar das dachte ich mir auch schon aber was wenn der Radius über 3 Zellen geht. und was machste mit den Zellen die schräg über oder unter der Zelle sind in der sich der Punkt befindet. Bin auf etwas gestoßen das vielleicht helfen könnte. wollte mal eure meinung hören und vorallem einige vorschlage zur syntax da ich java nicht behersche es aber in java machen muss. 

also der Punkt A liegt in einer Zelle Punkt B Zellkoordinate wie komm ich am besten auf B??

Dann wollte ich den Vektor BA bestimmen in demfall u dann den Vektor AC also v

v ist aber mein radius der ist bei mir fest definiert mit 5 

aus Vektor u und v kann ich w bestimmen und dann soll der Vektor v als Zeiger um den Punkt A rotieren und mir alle Wetre ausgeben.


----------



## Marco13 (23. Jul 2009)

Ich kapier's nicht. Vielleicht schafft's jemand anderes.


----------



## Loonatic (23. Jul 2009)

Ich kapiers auch nicht!!!  Aber trotzdem danke für die Hilfe:lol::toll:


----------



## Marco13 (23. Jul 2009)

Wenn das eine Aufgabe ist, gibt es doch bestimmt eine Aufgabenbeschreibung, die so präzise ist, dass auch ein normaler Informatiker was damit anfangen kann?


----------



## Loonatic (24. Jul 2009)

es ist eine teilaufgabe von einer großen. Ich muss datenstrukturen vergleichen 
und zu den strukturen die ich vergleichen muss gehört eine ArrayListe dann ein 1D Grid also mehrere Zellen in X richtung und dann noch das 2D grid also in X und X richtung das sind schon mal 3 strukturen. bei allen wird eben diese Punktwolke eingeführt und dann muss eine Nachbarschaftssuche statt finden. 

So, um zeit zu sparen und nicht Zelle für Zelle auf Punkte indefall Kreise weil ich ja noch einen Radius habe, zu überprüfen wird ein Kreis in einer Zelle genommen und durch den Radius geschaut welche umliegenden Zellen Berührt werden und welche Zellen im Kreis liegen. Dann such ich genau in diesen Zellen nach dem nächsten Kreisnachbar. So wird garantiert das die Suche nicht wirder über alle Zellen geht sondern nur über die die von einem Kreis berührt sind. 

Ich hoffe es ist jetzt bisschen klarer geworden. Naja ich muss da einfach mal warten bis mein Betreuer wieder da is der kann mir sicher weiter helfen, dachte ich würde es auch ohne ihn hinbekommen. :autsch:


----------

