Teil 1 – Einführung
Teil 2 – Kollision mit Gerade
Teil 2 – Kollision mit Gerade – Demoprogramm
Teil 3 – Kollision mit Strecke
Teil 3 – Kollision mit Strecke – Demoprogramm

Zur Demonstration der bisherigen Lösung habe ich ein kleines Programm geschrieben, in welchem man sich die berechnete Lösung für beliebe Ausgangssituationen anzeigen lassen kann. Es zeigt intuitiv die Probleme, die bisher noch nicht gelöst wurden.
Screenshot:

Bedienung :
Linke Maustaste, Drag&Drop : roter und schwarzer Kreis, Enden der schwarzen Linie
Rechte Maustaste, Drag&Drop : Bildschirmausschnitt
Mausrad : Zoomen

Ausprobieren : win-04.02.2011-21.26

Relevanter Quellcodeausschnitt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
void TestBoundedMovement::UpdateCorrectDest()
{
	sf::Vector2f s = myCircleStart.GetPosition();
	sf::Vector2f v = myVector;
	sf::Vector2f pl1 = myLineBound.GetP1();
	sf::Vector2f pl2 = myLineBound.GetP2();
 
	sf::Vector2f z = s + v;
 
	sf::Vector2f ng0;
 
	if ( MathUtils::ComputeNormal( pl1, pl2, ng0 ) ) {
 
		if( MathUtils::DotProduct( v, ng0 ) > 0 ) {
			//Bewegungsvektor zeigt von BoundingLine weg,
			//also wird keine Kollisionserkennung vorgenommen,
			//also ist myCircleCorrectDest = myCircleDest
			myCircleCorrectDest.SetPosition( z );
			return;
		}
 
		if( MathUtils::DotProduct( s - pl2, ng0 ) < 0 ) {
			//Der Startpunkt liegt hinter der Line
			//also wird keine Kollisionserkennung vorgenommen,
			//also ist myCircleCorrectDest = myCircleDest
			myCircleCorrectDest.SetPosition( z );
			return;
		}
 
 
		float r = radius;
		float d = ( MathUtils::DotProduct( z - pl2, ng0 ) );
 
		if( d >= r ) {
			//Es findet gar keine Kollision statt
			//also ist myCircleCorrectDest = myCircleDest
			myCircleCorrectDest.SetPosition( z );
			return;
		}
 
		float cosAlpha = MathUtils::DotProduct( v, pl2 - pl1 ) / 
				( MathUtils::VectorLen( v ) *  
				  MathUtils::VectorLen( pl2 - pl1 ) );
 
 
		float sinAlpha = sqrt( 1 - cosAlpha * cosAlpha );
 
		if( sinAlpha != 0 ) {
			float x = ( r - d ) / sinAlpha;
 
			sf::Vector2f z2 = z - x * v / MathUtils::VectorLen( v );
			myCircleCorrectDest.SetPosition( z2 );
		}
	} else {
		//Normale konnte nicht berechnet werden, 
		//also liegen pl1 und pl2 auf einem Punkt,
		//also ist BoundingLine nicht vorhanden,
		//also ist myCircleCorrectDest = myCircleDest
		myCircleCorrectDest.SetPosition( z );
	}
}
  1. […] Bewegung mit Kollisionserkennung Teil 2 – Demonstrationsprogramm […]