Finden Sie heraus, ob 4 Punkte auf einer Ebene ein Rechteck bilden?
Lesezeit: 9 Minuten
Pete
Kann mir bitte jemand in Pseudocode im C-Stil zeigen, wie man eine Funktion schreibt (die Punkte beliebig darstellt), die wahr zurückgibt, wenn 4 Punkte (Argumente für die Funktion) ein Rechteck bilden, und andernfalls falsch?
Ich habe mir eine Lösung ausgedacht, die zuerst versucht, 2 verschiedene Punktpaare mit gleichem x-Wert zu finden, und dies dann für die y-Achse tut. Aber der Code ist ziemlich lang. Einfach mal gespannt, was andere sich einfallen lassen.
Du bist auf die Lösung gekommen? Wo ist es? Sie können es hier zeigen und wir können Ihnen helfen, es kürzer und sauberer zu machen.
– Milan Babuškov
20. Februar 2010 um 19:05 Uhr
Interessante Frage. Ich stelle fest, dass Ihre Lösung nur funktioniert, wenn das Rechteck parallel zur Achse ist.
– Christian Madsen
20. Februar 2010 um 19:09 Uhr
Gman – ja in beliebiger Reihenfolge. Milan – das wurde von mir während eines Interviews gefragt, also habe ich meinen Code nicht (ich muss Code nicht unbedingt sehen … ein Algorithmus wäre auch großartig!). Christian – guter Punkt, dass es parallel zur Achse sein muss.
– Peter
20. Februar 2010 um 19:11 Uhr
Quark
Finden Sie den Massenmittelpunkt der Eckpunkte: cx=(x1+x2+x3+x4)/4, cy=(y1+y2+y3+y4)/4
Testen Sie, ob das Abstandsquadrat vom Massenmittelpunkt zu allen 4 Ecken gleich ist
(Natürlich sollte in der Praxis das Testen auf Gleichheit zweier Fließkommazahlen a und b mit endlicher Genauigkeit durchgeführt werden: zB abs(ab) < 1E-6)
Das ist eine clevere Lösung. Es findet im Grunde den Umkreis des “Rechtecks” und überprüft, ob alle vier Ecken darauf liegen.
– rlbond
20. Februar 2010 um 23:03 Uhr
Das ist SEHR ineffizient. Verwenden Sie die Punktproduktmethode von Vlad. Quadratwurzeln benötigen Hunderte von Taktzyklen. Auch das Punktproduktverfahren ist numerisch stabiler.
– Axel Gneiting
20. Februar 2010 um 23:33 Uhr
@Axel & @Curd: Wurde die Lösung seit der ursprünglichen Veröffentlichung bearbeitet? Ich sehe keine Quadratwurzeln. Ich gehe davon aus sqr(x) == x*x was bedeutet ddi ist eigentlich das Quadrat der Entfernung von cx zu xi. Das sollte verdammt schnell gehen.
– Brett Pontarelli
21. Februar 2010 um 4:46 Uhr
Okay, dann muss ich mich entschuldigen. Ich dachte, sqr steht für Quadratwurzel.
– Axel Gneiting
21. Februar 2010 um 17:46 Uhr
Einige Überlegungen zur Leistung: Diese Lösung erfordert 20 Additionen/Subtraktionen/Divisionen durch konstante 4- und 8-Multiplikationen. Es könnte sogar optimiert werden, die Berechnungen des verbleibenden Quadratabstands fallen zu lassen, wenn der erste oder zweite Vergleich fehlschlägt. Die obigen Zahlen sind also der schlimmste Fall. Selbst dieser Worst Case ist so gut wie der Best Case und dreimal besser als der Worst Case der Lösung von Vlad.
– Quark
21. Februar 2010 um 22:21 Uhr
Vlad
struct point
{
int x, y;
}
// tests if angle abc is a right angle
int IsOrthogonal(point a, point b, point c)
{
return (b.x - a.x) * (b.x - c.x) + (b.y - a.y) * (b.y - c.y) == 0;
}
int IsRectangle(point a, point b, point c, point d)
{
return
IsOrthogonal(a, b, c) &&
IsOrthogonal(b, c, d) &&
IsOrthogonal(c, d, a);
}
Wenn die Reihenfolge im Voraus nicht bekannt ist, benötigen wir eine etwas kompliziertere Prüfung:
int IsRectangleAnyOrder(point a, point b, point c, point d)
{
return IsRectangle(a, b, c, d) ||
IsRectangle(b, c, a, d) ||
IsRectangle(c, a, b, d);
}
@Larry: Ihr Test dient nur dazu, ein Parallelogramm zu sein
– Vlad
20. Februar 2010 um 19:15 Uhr
@Larry: Mit der Überprüfung der Diagonalen ist es jetzt richtig, aber Ihr Test erfordert das Ziehen von 6 Quadratwurzeln.
– Vlad
20. Februar 2010 um 19:22 Uhr
@Timmy: In diesem Fall muss man eine kompliziertere Prüfung durchführen: if (IsOrthogonal(a, b, c)) return IsRectangle(a, b, c, d); else if (IsOrthogonal(a, b, d)) return IsRectangle(a, b, d, c); else return false;
– Vlad
20. Februar 2010 um 19:28 Uhr
Ich habe die Antwort entsprechend geändert
– Vlad
20. Februar 2010 um 19:32 Uhr
IsOrthogonal( (10,9), (15,9), (15,6) ) = 0 oder False. (15-10)*(15-15)+(9-9)*(9-6)=0. Gibt es eine ! fehlen?
– Harvey
20. Februar 2010 um 19:47 Uhr
1. Find all possible distances between given 4 points. (we will have 6 distances)
2. XOR all distances found in step #1
3. If the result after XORing is 0 then given 4 points are definitely vertices of a square or a rectangle otherwise, return false (given 4 points do not form a rectangle).
4. Now, to differentiate between square and rectangle
a. Find the largest distance out of 4 distances found in step #1.
b. Check if the largest distance / Math.sqrt (2) is equal to any other distance.
c. If answer is No, then given four points form a rectangle otherwise they form a square.
Hier verwenden wir geometrische Eigenschaften von Rechteck/Quadrat und Bit-Magie.
Rechteckeigenschaften im Spiel
Gegenüberliegende Seiten und Diagonalen eines Rechtecks sind gleich lang.
Wenn die diagonale Länge eines Rechtecks sqrt(2) mal seiner Länge ist, dann ist das Rechteck ein Quadrat.
Bit-Magie
Die XOR-Verknüpfung gleicher Zahlen gibt 0 zurück.
Da die Abstände zwischen 4 Ecken eines Rechtecks immer 3 Paare bilden, eines für die Diagonale und zwei für jede Seite unterschiedlicher Länge, ergibt die XOR-Verknüpfung aller Werte 0 für ein Rechteck.
coole Idee, aber möglicherweise unpraktisch, wenn Sie die Gleichheit mit einer kleinen Toleranz testen müssen, um die Float-Präzision zu berücksichtigen. Es ist wahrscheinlich auch erwähnenswert, dass der xor-Trick funktioniert, weil xor kommutativ und assoziativ ist
– Ed Bordin
3. April 2019 um 0:23 Uhr
4.b. Warum nicht einfach prüfen, ob 4 Abstände gleich sind?
– Diegoide
11. August 2019 um 1:37 Uhr
Verschieben Sie das Viereck so, dass einer seiner Eckpunkte jetzt im Ursprung liegt
die drei verbleibenden Punkte bilden drei Vektoren vom Ursprung
einer von ihnen muss die Diagonale darstellen
die anderen beiden müssen die Seiten darstellen
bis zum Parallelogrammregel Bilden die Seiten die Diagonale, haben wir ein Parallelogramm
Bilden die Seiten einen rechten Winkel, handelt es sich um ein Parallelogramm mit rechtem Winkel
gegenüberliegende Winkel eines Parallelogramms sind gleich
aufeinanderfolgende Winkel eines Parallelogramms ergänzen sich
(Wenn Sie möchten, dass es mit Fließkommawerten funktioniert, ersetzen Sie bitte nicht einfach blind die int Erklärungen in den Kopfzeilen. Es ist schlechte Praxis. Sie sind aus einem bestimmten Grund da. Man sollte immer mit einer Obergrenze für den Fehler arbeiten, wenn man Fließkommaergebnisse vergleicht.)
Carlos Gutierrez
Der Abstand von einem Punkt zum anderen 3 sollte ein rechtwinkliges Dreieck bilden:
d1 = (x2-x1)^2 + (y2-y1)^2
d2 = (x3-x1)^2 + (y3-y1)^2
d3 = (x4-x1)^2 + (y4-y1)^2
if d1 == d2+d3 or d2 == d1+d3 or d3 == d1+d2 then return true
@andras – Einige Parallelogramme getestet und alle als falsch bewertet. Denken Sie an einen bestimmten Fall?
– Carlos Gutierrez
21. Februar 2010 um 21:48 Uhr
Angenommen, wir haben Punkte x1=3, y1=3; x2=0, y2=0; x3=6, y3=0; x4=9, y4=3; Jetzt ist d1 = 18; d2 = 18; d3 = 36; Es wird allerdings spät. 🙂 Würden Sie bitte nachsehen?
– András Wass
21. Februar 2010 um 22:35 Uhr
@andras – Du hast Recht, es sieht so aus, als müsste der Test mit 3 der Punkte als Startpunkt wiederholt werden.
– Carlos Gutierrez
21. Februar 2010 um 23:09 Uhr
bitte, dann tun Sie etwas dagegen.
– András Wass
28. Februar 2010 um 0:13 Uhr
das ist falsch, die letzte Zeile muss d1^2 == d2^2+d3^2 oder d2^2 == d1^2 + d3^2 oder d3^2 == d1^2 + d2 ^2 sein
– Masud Darzi
23. Januar 2021 um 6:55 Uhr
Axel Gneiting
Wenn die Punkte A, B, C & D sind und Sie die Reihenfolge kennen, berechnen Sie die Vektoren:
x=BA, y=CB, z=DC und w=AD
Nimm dann die Punktprodukte (x Punkt y), (y Punkt z), (z Punkt w) und (w Punkt x). Wenn sie alle Null sind, dann haben Sie ein Rechteck.
@andras – Einige Parallelogramme getestet und alle als falsch bewertet. Denken Sie an einen bestimmten Fall?
– Carlos Gutierrez
21. Februar 2010 um 21:48 Uhr
Angenommen, wir haben Punkte x1=3, y1=3; x2=0, y2=0; x3=6, y3=0; x4=9, y4=3; Jetzt ist d1 = 18; d2 = 18; d3 = 36; Es wird allerdings spät. 🙂 Würden Sie bitte nachsehen?
– András Wass
21. Februar 2010 um 22:35 Uhr
@andras – Du hast Recht, es sieht so aus, als müsste der Test mit 3 der Punkte als Startpunkt wiederholt werden.
– Carlos Gutierrez
21. Februar 2010 um 23:09 Uhr
bitte, dann tun Sie etwas dagegen.
– András Wass
28. Februar 2010 um 0:13 Uhr
das ist falsch, die letzte Zeile muss d1^2 == d2^2+d3^2 oder d2^2 == d1^2 + d3^2 oder d3^2 == d1^2 + d2 ^2 sein
– Masud Darzi
23. Januar 2021 um 6:55 Uhr
manugupt1
Wir wissen, dass zwei gerade Linien senkrecht sind, wenn das Produkt ihrer Steigungen -1 ist, da eine Ebene gegeben ist, können wir die Steigungen von drei aufeinanderfolgenden Linien finden und sie dann multiplizieren, um zu prüfen, ob sie wirklich senkrecht sind oder nicht. Angenommen, wir haben die Linien L1, L2, L3. Wenn nun L1 senkrecht zu L2 und L2 senkrecht zu L3 ist, dann ist es ein Rechteck und eine Steigung von m(L1)*m(L2)=-1 und m(L2)*m(L3)=-1, dann ist es impliziert, dass es sich um ein Rechteck handelt. Der Code lautet wie folgt
Du bist auf die Lösung gekommen? Wo ist es? Sie können es hier zeigen und wir können Ihnen helfen, es kürzer und sauberer zu machen.
– Milan Babuškov
20. Februar 2010 um 19:05 Uhr
Interessante Frage. Ich stelle fest, dass Ihre Lösung nur funktioniert, wenn das Rechteck parallel zur Achse ist.
– Christian Madsen
20. Februar 2010 um 19:09 Uhr
Gman – ja in beliebiger Reihenfolge. Milan – das wurde von mir während eines Interviews gefragt, also habe ich meinen Code nicht (ich muss Code nicht unbedingt sehen … ein Algorithmus wäre auch großartig!). Christian – guter Punkt, dass es parallel zur Achse sein muss.
– Peter
20. Februar 2010 um 19:11 Uhr