Bestimmung der Kugeltangenten

Tangenten bilden mit einem Radius zum Berührungspunkt immer einen rechten Winkel. Wir können also ein rechtwinkliges Dreieck wie in folgender Skizze ansetzen:
Figure: Ermittlung der Tangentenpunkte aus einer Beobachtungsposition $\vec{F}$
\includegraphics[width=20cm]{HTMLBilder/tangenten}
$\vec{b}$ entspricht dem Kreisradius mit Betrag $r$ und für ein rechtwinkliges Dreieck gilt:
$\displaystyle \vec{a} \vec{b}=0$      
$\displaystyle \vec{a} = \vec{b} + \vec{c}$      
$\displaystyle \left\vert \vec{b} \right\vert = r \Leftrightarrow b_{y} = \sqrt{ r^{2} - b_{x}^{2} }$      

Die Längen $h$ und $q$ sind Werte aus Formelsammlungen und müssen nicht weiter hergeleitet werden. Der Vektor $\vec{q}$ hat die Richtung der Verbindungslinie vom Kreismittelpunkt $\vec{P}$ zum Beobachtungspunkt $\vec{F}$, von dem aus die Tangentenschnittpunkte mit dem Kreis berechnet werden sollen. Die Richtung des Vektors $\vec{h}$ steht senkrecht dazu. Um diese Richtung zu ermitteln nützt folgende Überlegung: Das Skalarprodukt von senkrecht aufeinander stehenden Vektoren ist immer Null. In 2 Dimensionen bedeutet das:

$\displaystyle 0 = \vec{a} \vec{b} = 0 = a_{x} b_{x} + a_{y} b_{y}
$

Der Vektor mit den Komponenten $b_{x} = - a_{y}$ und $b_{y} = a_{x}$ steht immer senkrecht auf $\vec{a}$ weil das Skalarprodukt immer Null ergibt. Damit lässt sich die Richtung von $\vec{h}$ bestimmen. Die Tangentenpositionen befinden sich an den beiden Punkten $\vec{T}_{1/2} = \vec{P} + \vec{q} \pm \vec{h}$.

Folgende Funktion in Javasript gibt die Beiden Positionen als Liste von zwei Vekoren zurück.

 function TANGENTEN(ZENTRUM,RADIUS,BEOBACHTUNGSPUNKT,dst){
    dst = dst || [new MatType(3),new MatType(3)] ;
    FMINUSP=subtractVectors(BEOBACHTUNGSPUNKT,ZENTRUM);
    FMINUSPBETRAGSQUADRAT= lengthSq(FMINUSP);
    FMINUSPBETRAG= Math.sqrt(FMINUSPBETRAGSQUADRAT);
    q=scaleVector(FMINUSP, RADIUS*RADIUS/FMINUSPBETRAGSQUADRAT);
    NORMALE=new MatType(3);
    NORMALE[0]=FMINUSP[2]/FMINUSPBETRAG;
    NORMALE[1]=FMINUSP[1]/FMINUSPBETRAG;
    NORMALE[2]=FMINUSP[0]/FMINUSPBETRAG*-1;
    h=scaleVector(NORMALE, RADIUS/FMINUSPBETRAG*Math.sqrt(FMINUSPBETRAG*FMINUSPBETRAG-RADIUS*RADIUS));
    dst[0]=addVectors(ZENTRUM, addVectors(q, h) ) ;
    dst[1]=addVectors(ZENTRUM, subtractVectors(q, h) ) ;
    return dst;
}