Ich schlage mich seit anderthalb Tagen mit einem problem herum. Ich bin Schriftgestalter und möchte aus einem einfachen, auf einem Raster basierenden Buchstaben, der eine Vektorgrafik ist, einen dreidimensionalen Turm bauen. Das Schriftenprogramm FontLab hat eine Python-Schnittstelle.
Im konkreten geht es aber nur um einfache Geradenfunktionen aus dem Gymnasium, genauer um den Schnittpunkt zweier Geraden (s. roter Kreis). Ich brauche diese Schnittpunkte, weil Vektorgrafiken in Schriften keine "unendliche" Genauigkeit haben, sondern die Zeile nur 1000 em-Einheiten hoch ist und sich jeder Punkt auf diesem relativ groben Raster befindet. So kommt es an manchen Stellen zu Ungenauigkeiten, wenn ein Punkt über einer Geraden liegen soll. Wenn ich an der selben Stellen auf der Geraden aber noch einen Punkt einfüge, macht die Gerade zwar einen minimalen Umweg (unsichtbar), dafür liegen beide Punkte dann exakt übereinander.
Gerade 1 wird definiert durch die Punkte k1 und k2, die zweite Gerade wird definiert durch den Punkt d und die negative Steigung der blauen Hilfslinie (FontLab kann schiefe Hilfslinien). Der Schnittpunkt soll errechnet werden. Ich habe dazu die normalen Formeln aus der Schule benutzt:
y = m * x + n
bzw.
m = (y2 - y1) / (x2 - x1)
bzw.
n = y - m * x
Ich habe den Abschnitt mal in Python und in Perl isoliert. Die anfangs angegebenen Variablen werden eigentlich zuvor in einer Iteration aus einer Liste geladen. Hier der Einfachheit halber direkt als Variablen.
Um das Ergebnis schonmal vorweg zu nehmen: Perl kann's, Python nicht. Der Hund liegt schon bei der Steigung bzw. Nullpunkt der ersten Geraden (Zeile 24 und 25) begraben.
Das richtige Ergebnis, das ich auch mit dem Taschenrechner per Hand herausbekomme ist (274, 128)
Am Ende werden alle benutzten Variablen zur Überprüfung ausgegeben. Die beiden letzten Werte xp und yp sind der Schnittpunkt.
Code: Alles auswählen
import math
# Gerade 1 wird definiert durch die beiden Punkte k1 und k2
xk1 = 324
yk1 = 215
xk2 = 200
yk2 = 0
# Gerade 2 wird definiert durch den punkt d und die negative Steigung
xd = 224
yd = 215
neigungswinkel = 30
richtung = 1 # 1 oder -1 (Nach links oder rechts geneigt)
# Errechnung der x und y Werte durch Definitionen am rechtwinkligen Dreieck
# sin(alpha) = a / c bzw. cos(alpha) = b / c
def xoffset(c):
return math.cos((90 - neigungswinkel) * math.pi / 180) * c
def yoffset(c):
return math.sin((90 - neigungswinkel) * math.pi / 180) * c
# Geradenfunktionen
# Fkt durch zwei Punkte auf der Kontur (k)
mk = (yk2 - yk1) / (xk2 - xk1) * richtung
nk = yk1 - mk * xk1
# Fkt durch Punkt und schräge Hilfslinie
md = yoffset(500) / xoffset(500) * -richtung
nd = yd - md * xd
# Gleichsetzung der beiden Geradengleichungen
xp = (nd - nk) / (mk - md) # Nach x aufgelöst
yp = md * xp + nd # y = f(x)
# Achtung, dilletantisch per Hand umgebrochen
print "xk1(" + str(xk1) + ") yk1(" + str(yk1) + ") xk2(" + str(xk2) + \
") yk2(" + str(yk2) + ") xd(" + str(xd) + ") yd(" + str(yd) + ") mk(" + \
str(mk) + ") nk(" + str(nk) + ") md(" + str(md) + ") nd(" + str(nd) + \
") xp(" + str(math.floor(xp)) + ") yp(" + str(math.floor(yp)) + ")"
Code: Alles auswählen
xk1(324) yk1(215) xk2(200) yk2(0) xd(224) yd(215) mk(1) nk(-109) \
md(-1.73205080757) nd(602.979380895) xp(260.0) yp(151.0)
Code: Alles auswählen
#!/usr/bin/perl
# Gerade 1 wird definiert durch die beiden Punkte k1 und k2
$xk1 = 324;
$yk1 = 215;
$xk2 = 200;
$yk2 = 0;
# Gerade 2 wird definiert durch den punkt d und die negative Steigung
$xd = 224;
$yd = 215;
$neigungswinkel = 30;
$richtung = 1; # 1 oder -1 (Nach links oder rechts geneigt)
# Errechnung der x und y Werte durch Definitionen am rechtwinkligen Dreieck
# sin(alpha) = a / c bzw. cos(alpha) = b / c
$pi = 3.141635;
sub xoffset
{ $c = shift; return (cos((90 - $neigungswinkel) * $pi / 180) * $c); }
sub yoffset
{ $c = shift; return (sin((90 - $neigungswinkel) * $pi / 180) * $c); }
# Geradenfunktionen
# Fkt durch zwei Punkte auf der Kontur (k)
$mk = ($yk2 - $yk1) / ($xk2 - $xk1) * $richtung;
$nk = $yk1 - $mk * $xk1;
# Fkt durch Punkt und schräge Hilfslinie
$md = yoffset(500) / xoffset(500) * -$richtung;
$nd = $yd - $md * $xd;
# Gleichsetzung der beiden Geradengleichungen
$xp = ($nd - $nk) / ($mk - $md); # Nach x aufgelöst
$yp = $md * $xp + $nd; # y = f(x)
# Achtung, dilletantisch per Hand umgebrochen
print "xk1(" . $xk1 . ") yk1(" . $yk1 . ") xk2(" . $xk2 . ") yk2(" . \
$yk2 . ") xd(" . $xd . ") yd(" . $yd . ") mk(" . $mk . ") nk(" . $nk . ") \
md(" . $md . ") nd(" . $nd . ") xp(" . int($xp) . ") yp(" . int($yp) . ")";
Code: Alles auswählen
xk1(324) yk1(215) xk2(200) yk2(0) xd(224) yd(215) mk(1.73387096774194) nk(-346.774193548387) \
md(-1.73210727082961) nd(602.992028665833) xp(274) yp(128)
Vielen Dank an Jeden, der hier mal draufschauen will.