Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

11

26.04.2016, 16:03

Habe ich was übersehen, oder spricht etwas gegen das Trapez-Verfahren? Ein trivialer O(n) Algorithmus für die Flächenbestimmung beliebiger konkaver Polygone.

Kurzerklärung: Man sucht sich eine Kordinatenachse (X oder Y) und bildet von jeder Kante des (konkaven) Polygons ein Trapez zu dieser Achse. Für alle Kanten die in die Richtung der Kordinatenachse gehen, addiert man den Flächeninhalt dazu, für die Kanten die gegen die Richtung der Koordinatenachse gehen, zieht man ihn ab.

EDIT:
Mir ist nur gerade eingefallen, dass es allerdings ein Problem mit Flächen geben kann, die mehrfach eingeschlossen sind. Zum Beispiel ein fünfeckiger Stern. Die Mittelfläche würde doppelt gezählt.
Allerdings kann man diese Flächen eh unterschiedlich definieren. Je nachdem kann es auch gewünschtes Verhalten sein.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Spiele Programmierer« (26.04.2016, 16:25)


CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

12

26.04.2016, 16:28

Ich habe das gerade mal für ein Viereck ausprobiert. Die grüne Fläche kommt am Ende dabei heraus, denn die Flächen 1|2, 3|4 und 4|1 werdeb von 2|3 abgezogen. Ich hoffe ich hab das Verfahren nicht falsch verstanden. ;) Bild findet ihr im Anhang. Ich behaupte mal, dass der Algorithmus nicht für Vielecke geeignet ist, bei denen sich Kanten überschneiden.
»CeDoMain« hat folgendes Bild angehängt:
  • Fläche.png
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

13

26.04.2016, 17:09

Also du hast nicht ganz unrecht - das sich der Umlaufsinn und damit das Vorzeichen in den einzelnen Dreiecken umdreht, hatte ich tatsächlich übersehen. Konkave Polygone sollten aber funktionieren.

Ganz so komisch wie bei dir sieht es bei mir aber nicht aus.
Ich komme auf folgende Situation:
»Spiele Programmierer« hat folgendes Bild angehängt:
  • Fläche.png

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

14

27.04.2016, 10:58

Meine Idee wird wahrscheinlich zu leicht gedacht sein, aber ist es möglich

Die Kurzform: Finde alle Punkte, die nicht direkt miteinander verbunden sind.

Die Langform:
1. Punkte zu finden, die nicht DIREKT miteinander verbunden sind
2. Nur Verbindungen zeichnen zu dürfen, die innerhalb der Form liegen

?

http://imgur.com/X2eDC4p

Die blauen Linien sind verboten, da sie die Punkte nur verbinden können, indem sie Linien außerhalb des Polygons setzen. Die grüne Linie ist erlaubt, da sie logischerweise innerhalb liegt.

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

15

27.04.2016, 14:58

Nur Verbindungen zeichnen zu dürfen, die innerhalb der Form liegen
Dann lass das mal dein Programm rausfinden...

Dein Algorithmus sieht dann folgendermaßen aus:
  1. Zu jedem Ausgangspunkt die 2 direkt mit ihm verbundenen Ausgangspunkte herausfinden und so abspeichern, dass der Algorithmus schnell diese 2 Punkte/Strecken zu jedem Punkt herausfinden kann.
  2. Berechnung aller Schnittpunkte durch simples Durchiterieren aller Möglichkeiten. Diese Punkte werden dann so abgespeichert, dass der Algorithmus schnell zu jeder Strecke die Anzahl und die auf ihr befindlichen Schnittpunkte herausbekommen kann.
  3. Zu jedem Ausgangspunkt die beiden nächsten mit ihm verbundenen Punkte herausfinden:
    • Eine Strecke hat keinen Schnittpunkt - der Endpunkt ist der gesuchte Punkt.
    • Eine Strecke hat 1 Schnittpunkt - der Schnittpunkt ist der gesuchte Punkt.
    • Eine Strecke hat 2 Schnittpunkte - der am nächsten liegende Punkt ist der gesuchte Punkt - mit Pythagoras oder beim Schneiden gespeicherten Werten Werten herausfinden.
  4. Die beiden nächsten Punkte zu einem Ausgangspunkt spannen das Dreieck auf.
Warum machst du es nicht so? Bisher wurde nur dagegen eingewendet, dass es nur bis 2 Schnittpunkte funktioniert. Ist doch kein Problem - du musst so oder so die Schnittpunkte alle berechnen, dann kannst du sie auch gleich Zählen und je nach Anzahl verschiedene Algorithmen drauf loslassen:
  • Bei 0 Schnittpunkten: Das Trapezverfahren
  • Bei 1 bis 2 Schnittpunkten mein Verfahren aus dem Zitat oben
  • Bei 3 oder mehr Schnittpunkten müssen wir uns noch was überlegen! Darüber sollte man sich meiner Meinung nach ab jetzt in diesem Thread Gedanken machen.
Probier das Ganze doch schonmal für 0 bis 2 Schnittpunkte in deinem Programm aus!? Schreib mal ob das funktioniert und währendessen überlegen wir uns noch die fehlenden Algorithmen. ;)

Vielleicht lässt sich mein Vorschlag auch so verallgemeinern, dass eine Berechnung bei mehr als 2 Schnittpunkten möglich ist. Das Problem ist doch nur die Behauptung meinerseits:
Da du ja maximal 5 verschiedene Ausgangspunkte hast, ist die Zahl der Flächen begrenzt, die sich erzeugen lassen. Es lassen sich maximal 3 Flächen konstruieren. Es gibt maximal 2 Schnittpunkte - daher muss jedes Dreieck mindestens eine Ecke haben, die ein Ausgangspunkt ist. Das ist ein Vorteil: Wenn du für jeden Ausgangspunkt die angrenzende Fläche gefunden hast, dann hast du zwingend alle Teilflächen gefunden. Außerdem kann jeder Ausgangspunkt nur eine einzige angrenzende Fläche haben.
Das müsste man umgehen, damit das dem Algorithmus nicht mehr wichtig sein muss. Ich denke, ich habe auch schon eine Idee - ich probiere mal aus und formuliere das mal verständlich!
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

16

27.04.2016, 15:44

Danke nochmal, ich werde es ausprobieren. Ich berechne momentan die Schnittpunkte. Meine Berechnungen sehen so aus:

C#-Quelltext

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/// ------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Berechnet die Schnittpunkte
        /// </summary>
        private void BerechneSchnittpunkte()
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = i + 1; j < 5; j++)
                {
                    BerechneSchnittpunkte(i, j);
                }
            }
        }

        /// ------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Berechnet die Schnittpunkte
        /// </summary>
        /// <param name="start1"></param>
        /// <param name="start2"></param>
        private void BerechneSchnittpunkte(int start1, int start2)
        {
            int ende1 = start1 + 1;
            if (ende1 == 5)
            {
                ende1 = 0;
            }
            int ende2 = start2 + 1;
            if (ende2 == 5)
            {
                ende2 = 0;
            }
            BerechneSchnittpunkte(punktListe[start1], punktListe[ende1], punktListe[start2], punktListe[ende2]);
        }

        /// ------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Berechnet die Schnittpunkte von 2 Linien - y = m*x+b
        /// </summary>
        private void BerechneSchnittpunkte(Point start1, Point ende1, Point start2, Point ende2)
        {
            double dx1 = ende1.X - start1.X;
            double dy1 = ende1.Y - start1.Y;
            double dx2 = ende2.X - start2.X;
            double dy2 = ende2.Y - start2.Y;

            double m1 = dy1 / dx1;
            double m2 = dy2 / dx2;

            double b1 = start1.Y - start1.X * m1;
            double b2 = start2.Y - start2.X * m2;

            double schnittpunktX = (b1 - b2) / (m2 - m1);
            double schnittpunktY = m1 * schnittpunktX + b1;

            //------- TEST

            if (m1 == m2 && b1 == b2)
            {
                Console.WriteLine("Unendlich viele Schnittpunkte "
                + "Xs: " + schnittpunktX + " Ys: " + schnittpunktY);
            }
            else if (m1 == m2 && b1 != b2)
            {
                Console.WriteLine("0 Schnittpunkte "
                + "Xs: " + schnittpunktX + " Ys: " + schnittpunktY);
            }
            else
            {
                Console.WriteLine("1 Schnittpunkt "
                    + "Xs: " + schnittpunktX + " Ys: " + schnittpunktY);
            }

            Rectangle rect = new Rectangle(Convert.ToInt32(schnittpunktX), Convert.ToInt32(schnittpunktY), Convert.ToInt32(b1), Convert.ToInt32(b2));
            if (rect.Contains(Convert.ToInt32(schnittpunktX), Convert.ToInt32(schnittpunktY)))
            {
                Console.WriteLine("Punkt liegt drin");
            }
            else
            {
                Console.WriteLine("Punkt liegt nicht drin");
            }

            //------- TEST
        }


Wobei ich glaube das meine Berechnung mit dem Rechteck falsch und völliger quatsch ist :thumbsup:

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

17

27.04.2016, 17:47

Hey du machst es aber kompliziert... Nimm doch einfach die Parameterdarstellung von Geraden - dann brauchst du auch kein Rechteck verwenden. Hier steht wies geht.

Ich fasse mal zusammen:
Du hast die beiden Strecken in Parameterdarstellung:
§\overline{AB}: \vec{x}=A+s(B-A)§
§\overline{CD}: \vec{x}=C+t(D-C)§

Wenn du die gleichsetzt und die Parameter §s§ und §t§ auf eine Seite bringst, erhältst du:
§s(B-A)-t(D-C)=C-A§

Dann machst du ein LGS draus, indem du die §x§- und §y§-Komponenten in zwei Gleichungen aufteilst:
§s(B_x-A_x)-t(D_x-C_x)=C_x-A_x§
§s(B_y-A_y)-t(D_y-C_y)=C_y-A_y§

Dieses Gleichungssystem muss dein Programm lösen - also die Werte der beiden Parameter herausbekommen. Wie du das machst, ist dir überlassen. Wenn die Parameter beide im Intervall [1,0] liegen, dann Schneiden sich die Strecken - andernfalls nur deren Geraden.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »CeDoMain« (27.04.2016, 21:42) aus folgendem Grund: Leserlicher Formatiert


CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

18

27.04.2016, 21:37

Wie du das machst, ist dir überlassen.
Da mir diese Aussage dann doch ein bisschen fies vorkommt, schreib ich mal eine Lösungsmöglichkeit auf: Mit der Cramerschen Regel und Determinanten lässt sich ein 2x2 LGS sehr leicht lösen. Damit ich nicht so viel schreiben muss, definiere ich erstmal ein paar Konstanten. Das kannst du im Programm dann auch machen.
§B_x-A_x=m_x§
§D_x-C_x=n_x§ <= Diese Zeile hat einen kleinen Fehler. Erklärung & Behebung hier.
§C_x-A_x=o_x§
§B_y-A_y=m_y§
§D_y-C_y=n_y§ <= Diese Zeile hat einen kleinen Fehler. Erklärung & Behebung hier.
§C_y-A_y=o_y§

Dann berechnest du die drei benötigten Determinanten:
§d_0=m_xn_y-m_yn_x§
§d_s=o_xn_y-o_yn_x§
§d_t=m_xo_y-m_yo_x§

Jetzt kannst du schon einiges über etwaige Schnittpunkte sagen:
  • Wenn §d_0=d_s=d_t=0§ ist, dann liegen die Strecken aufeinander. Dein Programm sollte den Benutzer auffordern andere Punkte zu wählen.
  • Wenn §d_0=0§, §d_s\neq0§ und §d_t\neq0§, dann gibt es keinen Schnittpunkt. Dein Programm kann abbrechen.
  • Wenn §d_0\neq0§ ist, dann hast du genau einen Schnittpunkt. Dein Programm macht mit der Lösungsberechnung unten weiter.
Die Lösungen für §s§ und §t§ sind dann:
§s=\frac{d_s}{d_0}§
§t=\frac{d_t}{d_0}§

Jetzt prüfst du, ob §s§ und §t§ im Intervall [0,1] liegen - wenn ja, dann hast du einen Schnittpunkt, der auf den Strecken liegt, andernfalls liegt er nur auf den beiden Geraden, die durch die Strecken gehen.

Die Koordinaten des Schnittpunktes §S§ berechnen sich mit:
§S_x=A_x+s(B_x-A_x)§
§S_y=A_y+s(B_y-A_y)§

Ich hoffe, dass du das schnell in ein Programm umsetzen kannst - ich habe mich bemüht es so aufzuschreiben, dass das schnell möglich sein sollte. Letztendlich brauchst du nur das, was in diesem Post hier steht zu Programmieren. Das aus dem Vorhergehenden ist nur die Herleitung. Bei Fragen oder Problemen melde dich!
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »CeDoMain« (30.04.2016, 00:23) aus folgendem Grund: Fehler markiert


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

19

28.04.2016, 11:14

Üblicherweise wird die Fläche solcher Polygone über die Anzahl an Schnittpunkten, die ein beliebiger Strahl von einem Punkt aus mit den Kanten des Polygons (alle Punkte mit ungerader Anzahl gelten als innerhalb des Polygons, alle mit gerader Anzahl als außerhalb) hat, definiert. Wie schon bemerkt wurde, funktioniert die Trapezformel nur für einfache Polygone und nicht für die allgemeine, überschlagene Form, mit der es du hier zu tun hast.

Eine Lösung wäre wohl, das Polygon zu triangularisieren und einfach die Summe der Fläche aller Dreiecke zu berechnen. Was genau willst du denn erreichen; geht es dir wirklich nur darum, den Flächeninhalt zu berechnen, oder steckt da eigentlich noch mehr dahinter?

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

20

29.04.2016, 07:49

Hey,
vielen Dank @CeDoMain für die Ansätze.

Das Hauptziel ist wirklich "nur" am Ende sagen zu können "bei den zufällig entstandenen einzelnen Flächen hat Fläche1 eine Fläche von xy, Fläche2 eine Fläche von ..."

Und diese Berechnungen sollen für alle generierten Polygone möglich sein :)

Werbeanzeige