Flächeninhalt eines n-Ecks durch Koordinaten berechnen



  • Hallo, ich soll für ein Testat ein C Programm schreiben, das die Fläche eines n-Ecks berechnet:

    Je zwei aufeinander folgende Eckpunkte, zB P1=(a/b) und P2=(c/d), bilden mit dem Ursprung dabei ein Dreieck, dessen Fläche |cb - ad | /2 ist. Die Gesamtfläche ist dann die Summe dieser Teilflächen.
    Irgendwo in meiner Rechnung muss sich noch ein Fehler befinden, da zB bei einer zur y-Achse symmetrischen Fläche 0 als Ergebnis ausgegeben wird.
    Für Tipps wäre ich sehr dankbar.

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main(void) {
        
        int i,j,n;
        
        int F = 0;
        
        printf("\n Geben Sie die Anzahl der Ecken ein: ");
        scanf("%d",&n);
        
        int A[n];
    
        float P[n][2];
        
        for(i=0;i<n;i++){
            for(j=0;j<2;j++){
                
                printf(" P_%d,%d =",i,j);
                scanf("%f",&(P[i][j]));
            }
        }
        
        for(i=0;i<n;i++){
            for(j=0;j<2;j++){
                
                A[i] = ((P[i][j+1]*P[i+1][j]) - (P[i][j]*P[i+1][j+1]))* (-1)/2;
    
            }
        }
                
        for(i=0;i<n;i++){
            
            F += A[i];
        }
        
        printf(" Fläche: %d \n",F);
            
        return 0;
        
    }
    


  • @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    j+1

    Wenn man einen Index von 0 bis zur Obergrenze laufen lässt, geht das nicht gut.



  • @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    (-1)/2

    Welchen Wert ergibt dieser Ausdruck?



  • @Swordfish *(-1) habe ich gerechnet, damit ich den Betrag bekomme



  • @manni66 wie könnte ich denn alternativ festlegen, dass mit der Koordinate vom nächsten Punkt gerechnet werden soll?



  • i + 1 (bzw. j + 1) passt schon. Nur musst Du Dir eben überlegen welchen Wert i maximal haben darf damit i + 1 noch in den Arraygrenzen ist.

    for (i = 0; i < n - 1; ++i)
    

    Die innere Schleife kann somit weg. (Nicht der Inhalt des Schleifenkörpers sondern die Schleife)

    Ich bin immer noch der Meinung daß Du wahrscheinlich nicht mit Integern rechnen willst.

    @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    int i,j,n;
    

    Deklariere Variablen bitte so nah wie möglich an der Stelle an der sie auch benötigt werden:

    for (int i = 0; i < n - 1; ++i)
    


  • @Swordfish danke, ich habe es jetzt mal etwas umgeschrieben.

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main(void) {
        
        int n;
        
        int GF = 0;
        int TF = 0;
        int RF = 0;
        
        printf("\n Geben Sie die Anzahl der Ecken ein: ");
        scanf("%d",&n);
        
    
        float P[n][2];
        
        for(int i=0;i<n;i++){
            for(int j=0;j<2;j++){
                
                printf(" P_%d,%d =",i,j);
                scanf("%f",&(P[i][j]));
            }
        }
        
        for(int i=0;i<n;i++){
    
                TF += (P[i][1]*P[i+1][0]) - (P[i][0]*P[i+1][1]);
    
            }
    
        
        RF = (P[0][0]*P[n-1][1])-(P[n-1][0]*P[0][1]);
        
        GF = TF + RF;
        
        printf(" Fläche: %d \n", abs (GF) /2);
            
        return 0;
        
    }
    

    Ich habe noch eine Restfläche RF ergänzt, die das letzte Dreieck berücksichtigt, das von dem letzten und ersten Punkt gebildet wird.



  • @Swordfish Warum wäre es ungünstig Integer zu benutzen ?



  • Genauigkeit? 3 / 2 = 1 aber 3 / 2. = 1.5.



  • @Swordfish okay dann ändere ich das in float.



  • @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    @Swordfish *(-1) habe ich gerechnet, damit ich den Betrag bekomme

    Für den Betrag kannst du die Funktion fabs benutzen.

    Generell solltest du unbedingt Einlesen und Berechnen in zwei Funktionen auslagern. Dann kannst du dir auch leicht ein paar Beispiel-n-Ecks fest kodieren und alle auf einmal mit deiner Funktion testen.

    Du kannst auch einen "echten" Punkt mit x und y machen anstatt ein weiteres 2-elementiges Array zu nehmen, z.B. so:

    typedef struct { 
        double x; 
        double y;
    } point_t;
    


  • @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    @Swordfish okay dann ändere ich das in float.

    ich hoffe Du hast den Punkt hinter der 2 in

    @Swordfish sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    3 / 2. = 1.5

    bemerkt.

    2. (oder auch 2.0) ist ein double literal
    2f (oder auch 2.0f) ist ein float literal



  • @Swordfish alles klar. So ganz funktioniert das Programm momentan noch nicht. Für manche Beispiele bekomme ich das richtige Ergebnis und für andere nicht



  • @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    So ganz funktioniert das Programm momentan noch nicht. Für manche Beispiele bekomme ich das richtige Ergebnis und für andere nicht

    Was sind eigentlich GF, TF und RF? Ein paar mehr Buchstaben tun gut, damit man die Variablen gleich versteht. Nimm Abstand von diesen stark abgekürzten Variablennamen! (Ausnahme: int i für Zähler sowie x und y für gleichnamige Koordinaten sind ok - und ggf. weitere Konventionen oder fachlich übliche Abkürzungen).

    Du hattest oben auch noch irgendwo ein "abs". Ist daraus auch ein fabs geworden? Wie sieht dein Code jetzt aus?



  • @wob

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main(void) {
        
        int n;
        
        double GF = 0; // Gesamtfläche
        double TF = 0; // Teilfläche
        double RF = 0; // Restfläche
        
        printf("\n Geben Sie die Anzahl der Ecken ein: ");
        scanf("%d",&n);
        
    
        float P[n][2];
        
        for(int i=0;i<n;i++){          // Koordinaten einlesen
            for(int j=0;j<2;j++){
                
                printf(" P_%d,%d =",i,j);
                scanf("%f",&(P[i][j]));
            }
        }
        
        for(int i=0;i<n;i++){        // Teilflächen berechnen
    
                TF += (P[i][1]*P[i+1][0]) - (P[i][0]*P[i+1][1]);
    
            }
    
        
        RF = (P[0][0]*P[n-1][1])-(P[n-1][0]*P[0][1]);
        
        GF = TF + RF;
        
        printf(" Fläche: %f \n", fabs (GF) /2);
            
        return 0;
        
    }
    

    für das Beispiel: P1(1/-1), P2(0/1), P3(-1/-1) funktioniert es

    für: P1(1/-1),P2(2/1),P3(-1/1),P4(-2/-2) hingegen nicht



  • @lfahs sagte in Flächeninhalt eines n-Ecks durch Koordinaten berechnen:

    P[i+1][0]

    Das läuft immer noch zu weit.



  • This post is deleted!


  • @manni66 ah danke, hab es jetzt endlich richtig und auch verstanden



  • Wie gesagt, nimm dir zu Herzen, den Code in Funktionen zu teilen, z.B. so:

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    typedef struct {
        double x;
        double y;
    } point_t;
    
    
    double area(point_t P[], size_t n)
    {
        double GF = 0; // Gesamtfläche
        double TF = 0; // Teilfläche
        double RF = 0; // Restfläche
    
        // Teilflächen berechnen
        for (size_t i = 0; i < n - 1; i++) {
            TF += (P[i].y * P[i + 1].x) - (P[i].x * P[i + 1].y);
        }
    
        RF = (P[0].x * P[n - 1].y) - (P[n - 1].x * P[0].y);
        GF = TF + RF;
        return GF / 2;
    }
    
    
    int main(void)
    {
        point_t quadrat[4] = {
            {.x = 0, .y = 0},
            {.x = 0, .y = 1},
            {.x = 1, .y = 1},
            {.x = 1, .y = 0}
        };
        point_t quadratVerschoben[4] = {
            {.x = 0.4, .y = 0.7},
            {.x = 0.4, .y = 1.7},
            {.x = 1.4, .y = 1.7},
            {.x = 1.4, .y = 0.7}
        };
        point_t dreieck[3] = {
            {.x = -0.5, .y = 0.},
            {.x = 0.5, .y = 0.},
            {.x = 0, .y = 1}
        };
    
        printf(" Fläche Quadrat: %f \n", area(quadrat, 4));
        printf(" Fläche Quadrat (verschoben): %f \n", area(quadratVerschoben, 4));
        printf(" Fläche Dreieck: %f \n", area(dreieck, 3));
    
        return 0;
    }
    

    Analog zu meinen Tests könntest du dann einfach eine Eingabefunktion schreiben. Aber so brauchst du nicht jedes Mal beim Ausprobieren deines Codes neu Zahlen einzugeben. Aber mir scheint das so nicht korrekt, wenn ich auf die Fläche des Dreiecks gucke... Du solltest vielleicht auch noch ein andere, größere n-Ecken testen.



  • #include <stddef.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct point_tag {
        double x;
        double y;
    } point_t;
    
    bool read_point(FILE *stream, point_t *point)
    {
        point_t tmp;
        if (fscanf(stream, "%lf %lf", &tmp.x, &tmp.y) != 2)
            return false;
        *point = tmp;
        return true;
    }
    
    void print_point(FILE *stream, point_t const *point)
    {
        fprintf(stream, "(%lf, %lf)", point->x, point->y);
    }
    
    void print_points(FILE *stream, point_t const *points, size_t num_points)
    {
        for (size_t i = 0; i < num_points; ++i) {
            fprint_point(stream, &points[i]);
            putchar('\n');
        }
    }
    
    size_t read_points(FILE *stream, point_t **points)
    {
        size_t num_points = 0;
        *points = NULL;
        for (point_t tmp = { 0 }; fread_point(stream, &tmp);) {
            point_t *new_points = realloc(*points, sizeof * new_points * (num_points + 1));
            if (!new_points) {
                free(*points);
                return 0;
            }
            new_points[num_points++] = tmp;
            *points = new_points;        
        }
        return num_points;
    }
    
    double area(point_t *points, size_t num_points)
    {
        double area = 0.;
        for (size_t i = 0; i < num_points - 1; ++i)
            area += (points[i].x + points[i + 1].x) * (points[i].y - points[i + 1].y);
        return area / 2.;
    }
    
    int main()
    {
        point_t *points;
        size_t num_points = read_points(stdin, &points);
        print_points(stdout, points, num_points);
        printf("Area: %f", area(points, num_points));
        free(points);
    }
    

    Aber bitte beachten daß das nur für sich nicht selbst schneidende Polygone funktioniert. Sonst siehe Bentley–Ottmann algorithm.


Log in to reply