# Kreis auf Linie platzieren (-> Koordinatentransformation?)



## LurchiDerLurch (4. Nov 2010)

Hallo!

Ich bins mal wieder ^^

Diesmal will ich einen Kreis auf einer Linie platzieren. Und zwar an einem bestimmten Punkt. 
Der Kreis wird in seiner Bewegung die Linie schneiden. 




(Grün = Boundingbox, Blauer Punkt = Koordinate des Kreises, Roter Punkt = Nähester Punkt zum Kreis)

Der Kreis schneidet vereinfacht gesagt die Linie im roten Punkt. Allerdings lässt sich das nicht vermeiden, dass der Kreis kurz durch die Linie schwebt.





*Jetzt soll der Kreis auf die Linie platziert werden. Und zwar so, dass die Linie eine Tangente zum Kreis durch den roten Punkt ist!*






*Meine Idee: *

Man sieht das einfach aus der sicht von der Linie. Damit müsste der Kreis jetzt nurnoch das kleine Stückchen nach oben (der Teil vom Kreis, der unter der Linie ist). Zu sehen in Bild 2.

Aber was heißt "y nach oben gesehen von der Linie" für das normale Koordinatensystem?

Jetzt weiß ich, dass es Koordinatentransformation gibt

Koordinatentransformation ? Wikipedia

Aber so richtig darauf anwenden kann ich das irgendwie nicht. ???:L

Hat einer von euch vielleicht schon Erfahrung damit gemacht?

Hier noch ein bisschen Code, damit ihr nen Bezugspunkt habt:


```
//Der Kreis
Object2D circle = this;
//Die Linie mit welcher der Kreis kollidiert
Line2D line = new Line2D.Double(200,300,Main.mousePosition[0],Main.mousePosition[1]);
//Der Mittelpunkt vom Kreis
Point2D center = new Point2D.Double(circle.getX()+circle.weidth/2, circle.getY()+circle.getHeigth()/2);

//Radius vom Kreis	
double r = 25;
	
//Nähester Punkt zum Kreis (der rote)	
Point2D closest = Collision.closestPointToLine(line, center);

//Kollisionserkennung
if(closest.distanceSq(center) < r*r)
{
//System.out.println("Collision!");
//Jetzt müsste man den Kreis auf die Linie setzen!!! <----------------------------------
}

//MALEN (Nur die Punkte, Linie und Bounding Box)	    
g2.setPaint(Color.red);
g2.fill(new Ellipse2D.Double(closest.getX()-2, closest.getY()-2, 4, 4));
		
g2.setPaint(Color.green);
g2.draw(circle.getShape().getBounds2D());
		
g2.setPaint(Color.blue);
g2.fill(new Ellipse2D.Double(circle.getPos()[0]-2, circle.getPos()[1]-2, 4, 4));
		
g2.setPaint(Color.black);
g2.draw(line);
g2.fill(new Ellipse2D.Double(center.getX()-2, center.getY()-2, 4, 4));
```

MfG, Lurchi :rtfm:


----------



## slawaweis (5. Nov 2010)

LurchiDerLurch hat gesagt.:


> *Jetzt soll der Kreis auf die Linie platziert werden. Und zwar so, dass die Linie eine Tangente zum Kreis durch den roten Punkt ist!*


falls ich die Aufgabe richtig verstanden habe, steht hier schon die ganze Lösung.



LurchiDerLurch hat gesagt.:


> *Meine Idee: *
> 
> Man sieht das einfach aus der sicht von der Linie. Damit müsste der Kreis jetzt nurnoch das kleine Stückchen nach oben (der Teil vom Kreis, der unter der Linie ist). Zu sehen in Bild 2.
> 
> Aber was heißt "y nach oben gesehen von der Linie" für das normale Koordinatensystem?


Du musst in Vektoren denken. Zwischen Punkt Blau und Rot liegt ein Vektor, welcher senkrecht zum der Linie stehen muss. Weiterhin muss dieser Vektor der Länge nach dem Radius des Kreises entsprechen.

Das Vorgehen wäre:

1. aus dem gegebenem blauen Punkt den nähersten Punkt (Rot) auf der Linie ermitteln. So bekommt man den Vektor zwischen Rot und Blau. Dieser ist senkrecht zu der Linie
2. mit Pythagoras die Länge des Vektors ermitteln
3. die Differenz zwischen der Länge des Vektors und des Radius des Punktes berechnen.
4. nach den Ergebnissen aus Punkt 3 einen neuen Vektor erstellen, mit welchem der Kreis verschoben wird.

Punkt 1 und 2 sind bereits im Quelltext enthalten. Es wird aber nur der Fall geprüft, ob der Kreis die Linie schneidet, nicht der Fall, ob der Kreis außerhalb der Linie liegt, also:


```
//Kollisionserkennung
if(closest.distanceSq(center) < r*r ||
   closest.distanceSq(center) > r*r)
{
//System.out.println("Collision!");
//Jetzt müsste man den Kreis auf die Linie setzen!!! <----------------------------------
}

// Alternativ

if(closest.distanceSq(center) != r*r)
{
//System.out.println("Collision!");
//Jetzt müsste man den Kreis auf die Linie setzen!!! <----------------------------------
}
```

Slawa


----------



## Marco13 (5. Nov 2010)

Den letzten Abschnitt nochmal überdenken... (hier wird mit floats gerechnet...)


----------



## LurchiDerLurch (5. Nov 2010)

slawaweis hat gesagt.:


> Du musst in Vektoren denken. Zwischen Punkt Blau und Rot liegt ein Vektor, welcher senkrecht zum der Linie stehen muss. Weiterhin muss dieser Vektor der Länge nach dem Radius des Kreises entsprechen.
> 
> Das Vorgehen wäre:
> 
> ...



Ich denke ich versteh das schon. Aber meinst du wirklich den blauen Punkt und nicht den Mittelpunkt vom Kreis?
Oder meinst du den blauen Punkt (also koordinaten vom kreis) und davon dann seperat wieder einen Punkt, der am nähesten auf der Linie liegt? (rot, allerdings nicht der im Bild)

Wenn ich dann die Differenz von der länge des Vektors und dem Radius habe. Wie erstell ich damit einen neuen Vektor? Das ist ja nur eine Zahl (Differenz) :rtfm:


----------



## Marco13 (5. Nov 2010)

Es ist die Differenz zwischen Kreismittelpunkt und dem roten Punkt gemeint. Wenn der Radius z.B. 20 ist, und der Abstand zwsichen Kreismittelpunkt und rotem Punkt ist nur 10, dann berechnet man die besagte Differenz (x,y), normiert die (teilt sie durch ihre Länge), und mutlipliziert den resultierenden Vektor mit 10 - da kommt dann raus, wie weit man den Kreis verschieben muss, damit er die Linie im roten Punkt berührt.


----------



## LurchiDerLurch (5. Nov 2010)

:applaus: oha jetzt gibts auf jeden fall ein gutes ergebnis danke 

Allerdings hab ich das mulitplizieren vom vektor weggelassen. Mit wurde der Kreis immer ruckartig über die Linie gesetzt aber nicht auf die Linie.

Hier mal der Code


```
double dx = center.getX() - closest.getX();
		double dy = center.getY() - closest.getY();
		double dis = center.distance(closest);
		Vektor v = new Vektor(dx, dy).normalize();
//Vektor v = new Vektor(dx, dy).normalize().times(dif); //multiplizieren?

		if(dis < r)
		{
			circle.setPos(circle.getPos()[0]+v.getX(), circle.getPos()[1]+v.getY());
			circle.moveVektor().set(0, 0);
			System.out.println("collision");
		}
```

Komisch ist jetzt allerdings noch, dass der Kreis sich recht langsam zu seiner posisiton bewegt.
Also er schneidet die Linie und fährt dann langsam zu der gewünschten Position. 
Ist zwar zu verkraften aber an was liegt das?


----------



## Marco13 (6. Nov 2010)

LurchiDerLurch hat gesagt.:


> Komisch ist jetzt allerdings noch, dass der Kreis sich recht langsam zu seiner posisiton bewegt.



Kann ich mir grad nicht vorstellen... ? ! ???:L


----------



## LurchiDerLurch (22. Nov 2010)

So hat zwar etwas gedauert weil ich leider wenig zeit für das programm hatte...

dafür hab ich meinen fehler selbst gefunden  

Man muss den vektor noch mit (Radius - (Abstand zwsichen Kreismittelpunkt und rotem Punkt)) multiplizieren.


----------

