Punktkoordinaten zum Zeichnen berechnen

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Hallo

heute habe ich eine Frage zur Geometrie.

Gegeben sind die Punkte P1 (x1/y1) und P2 (x2/y2). Durch die beiden Punkte verläuft eine Gerade.

Auf dieser Gerade sollen nun die Koordinaten des Punktes berechnet werden, der genau x Längeneinheiten von Punkt P1 entfernt ist. Meine eingerosteten bis nicht mehr existenten Geometriekenntnisse sagen mir, dass man dafür zuerst die Steigung und danach die Funktionsgleichung berechnen muss. Die Steigung bekomme ich mit m = (y1 - y2) / (x1 - x2) noch hin, aber danach hört es auf.

Wie berechnet man so etwas?

Gruß
Atalanttore
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe dein Problem noch nicht verstanden. Soll x *auf* der Geraden sein? In Richtung P2? Oder wie soll der genau liegen?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Man nimmt Vektorrechnung: a + (b-a) * x/|b-a|
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__deets__: Genau. Der Punkt P3 (x3/y3) soll mit dem Abstand x zu Punkt P1 in Richtung zu Punkt P2 auf der Geraden liegen.

@Sirius3: Danke für die Formel, aber was muss man für a, b und x einsetzen?

Gruß
Atalanttore
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Vektoren - P1 ist a, P2 b und x die Länge. Geradengleichungen helfen dir nicht. Vektorrechnung schon.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__deets__: Danke für die Aufklärung.

Gruß
Atalanttore
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Meine Beispielwerte habe ich nun in die Formel eingesetzt.
P1 (1920, 504)
P2 (371, 1080)
x = 100

Das sieht jetzt so aus:
Bild

Wie berechnet man damit jetzt den Punkt P3?

Gruß
Atalanttore
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da ist was falsch. Du musst den richtungsvektor in der Länge normalisieren. Das ist der Term ganz rechts. Das ist aber nur ein Vektor. Das muss die LÄNGE sein.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Ich habe Informationen dazu gefunden, wie man einen Vektor normiert. Ist Normieren ein anderes Wort für Normalisieren?

Gruß
Atalanttore
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

"Normierung" ist der richtige Ausdruck.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ui. Ich bin rostig. Normalenvektor steht senkrecht auf irgendwas. Ein normierter Vektor hat die Länge 1.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Ich habe nun zum allerersten Mal einen Vektor normiert (bzw. so gemacht wie ich die Erklärung verstanden habe) und die Formel sieht jetzt so aus:

Bild

Kann man damit den gesuchten Punkt P3 berechnen?

Gruß
Atalanttore
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Atalanttore: und leider falsch normiert: |P2-P1| also erst die Differenz bilden und dann die Norm.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

In der Reihenfolge |P2-P1|

Bild

Ist das nun so richtig?

Gruß
Atalanttore
ArtooDetoo
User
Beiträge: 60
Registriert: Dienstag 4. Dezember 2018, 16:57

Du bildest hier die Differenz der Normen, musst aber die Norm der Differenz berechnen. Das heißt: zuerst komponentenweise subtrahieren und erst danach der Kram mit der Wurzel und den Quadraten.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Atalanttore: Ich weiss ist hier allgemein gestellt, ohne Bezug zu irgend einem Rahmenwerk, aber falls es etwas mit Qt zu tun hat, könnte man da auch Klassen von Qt zur Hilfe nehmen:

Code: Alles auswählen

#!/usr/bin/env python3
from PyQt5.QtCore import QLineF


def main():
    line = QLineF(1920, 504, 371, 1080)
    line.setLength(100)
    print(line.p2())


if __name__ == '__main__':
    main()
Und in der Standardbibliothek gäbe es mit `turtle.Vec2D` eine fertige Vektor-Klasse mit der sich die Formel von Sirius 1:1 in Code übersetzen liesse:

Code: Alles auswählen

In [508]: a = turtle.Vec2D(1920, 504); b = turtle.Vec2D(371, 1080)

In [509]: a + (b-a) * (100/abs(b-a))
Out[509]: (1826.27,538.85)
Mit `QtGui.QVector2D` funtkioniert es fast genau so, nur das die nicht mit der `abs()`-Funktion verwendet werden können, aber eine `length()`-Methode haben. Aaaaber damit geht es noch ein bisschen einfacher, weil es eine `normalized()`-Methode gibt:

Code: Alles auswählen

In [518]: a = QVector2D(1920, 504); b = QVector2D(371, 1080)

In [519]: a + (b-a).normalized() * 100
Out[519]: PyQt5.QtGui.QVector2D(1826.2705078125, 538.8535766601562)
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__blackjack__: Danke für den Beispielcode. Der bringt mich gut weiter.
Qt wird in dem Code, für den diese Berechnung gedacht ist, bereits an anderen Stellen verwendet. Außerdem ist natürlich alles willkommen, was dabei hilft, mathematische Berechnungen nicht selbst machen zu müssen. :P

Gruß
Atalanttore
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Ich habe ein kleines Beispielprogramm gebastelt, wo durch zwei zufällig auf einem Rechteck (= Größe eines HD-Monitors) liegende Punkte eine Route erstellt wird. Der Start- und Endpunkt einer Linie, mit einer zufällig festgelegten Länge, soll so nach und nach über die Route durch des Rechteck wandern. Momentan hakt es mindestens noch an der Berechnung der passenden Start- und Endpunkte der Linie. Mathematisch komme ich da nicht mehr weiter. Wie macht man so etwas?

Code: Alles auswählen

#!/usr/bin/python3

from random import randint, choice
from time import monotonic, sleep
from PyQt5.QtGui import QVector2D

WIDTH = 1920
HEIGHT = 1080
SIDES = ["left", "right", "top", "bottom"]
start = monotonic()
line_length = randint(100, 500)


def calculate_random_point(exclude=None):

    remaining = [x for x in SIDES if x is not exclude]

    side = choice(remaining)

    if side == "left":
        x = 0
        y = randint(0, HEIGHT)
    elif side == "right":
        x = WIDTH
        y = randint(0, HEIGHT)
    elif side == "bottom":
        x = randint(0, WIDTH)
        y = HEIGHT
    elif side == "top":
        x = randint(0, WIDTH)
        y = 0
    return x, y, side


def main():

    start_point_x, start_point_y, position = calculate_random_point()
    end_point_x, end_point_y, _ = calculate_random_point(position)

    start_point = QVector2D(start_point_x, start_point_y)
    end_point = QVector2D(end_point_x, end_point_y)

    while True:

        elapsed = monotonic() - start

        line_start_point = start_point + (end_point - start_point).normalized() * elapsed
        line_end_point = start_point + (end_point - start_point).normalized() * line_length * elapsed


        print(f"Startpunkt ({start_point_x} / {start_point_y}), Endpunkt ({end_point_x} / {end_point_y}), Linienlänge: {line_length}"
              f"\nAnfang Linie ({line_start_point.x()} / {line_start_point.y()}),"
              f"\nEnde Linie ({line_end_point.x()} / {line_end_point.y()})"
              "\n================================================================")
        sleep(0.5)


if __name__ == '__main__':
    main()
Gruß
Atalanttore
Antworten