* polygon.c
// gcc polygon.c -Wall -lm #include <stdio.h> #include <stdlib.h> #include <math.h> #ifndef null #define null ((void *)0) #endif typedef struct { float x; float y; } Point; typedef struct { Point p1; Point p2; } Line; typedef Point Vertex; typedef Line Edge; void *mymemset(void *s, int c, size_t n) { int i = 0; char *b = s; for (; i < n; i++) { b[i]= c; } return s; } char * const Vertex_toString(const Vertex const *v) { const size_t BUFFSIZE = 32; char *s = (char *)malloc(sizeof(char) * BUFFSIZE); mymemset(s, 0, BUFFSIZE); sprintf(s, "(%.3f,%.3f)", v->x, v->y); return s; } float Vertex_distance(const Vertex const *v1, const Vertex const *v2) { return sqrt( (v1->x -v2->x) * (v1->x - v2->x) + (v1->y - v2->y) * (v1->y - v2->y) ); } float Vertex_angle(const Vertex const *v1, const Vertex const *v2) { return atanf( (v2->y - v1->y) / (v2->x - v1->x) ); } void Edge_init(Edge *e, Vertex v1, Vertex v2) { e->p1 = v1; e->p2 = v2; } float Edge_len(const Edge *const e) { return Vertex_distance(&e->p1, &e->p2); } float Edge_angle(const Edge *const e) { return Vertex_angle(&e->p1, &e->p2); } float absf(float v) { return v > 0 ? v : -v; } float getAreaByAdjEdges(const Edge *const e1, const Edge *const e2) { float len1 = Edge_len(e1); float len2 = Edge_len(e2); float theta = Edge_angle(e2) - Edge_angle(e1); return (1.0/2) * len1 * len2 * absf( sinf(theta) ); } typedef struct { Vertex *v; size_t size; size_t cap; } Polygon; void Polygon_init(Polygon *p, size_t cap) { p->size = 0; p->cap = cap; p->v = malloc(sizeof(Vertex) * p->cap); } int Polygon_addVertex(Polygon *p, Vertex v) { if (p->size >= p->cap) { return -1; } p->v[ p->size++ ] = v; return 0; } Vertex *Polygon_getVertex(const Polygon *const p, int idx) { if (idx < 0 || idx > p->size) { return null; } return &p->v[ idx ]; } float Polygon_area(Polygon *p) { int i; Vertex v0, v1, v2; Edge e1, e2; float area = 0; for (i = 0; i < p->size-2; i++) { v0 = *Polygon_getVertex(p, i ); v1 = *Polygon_getVertex(p, i+1 ); v2 = *Polygon_getVertex(p, i+2 ); Edge_init( &e1, v0, v1 ); Edge_init( &e2, v0, v2 ); area += getAreaByAdjEdges( &e1, &e2 ); } return area; } void Polygon_print(const Polygon *p) { if (p->size < 1) { printf("Empty polygon.\n"); return; } int i; char * s = Vertex_toString(&p->v[0]); printf(s); free(s); for (i = 1; i < p->size; i++) { s = Vertex_toString(&p->v[i]); printf(", %s", s); free(s); } printf("\n"); } void Polygon_destroy(Polygon *p) { free(p->v); p->v = null; } int main() { Vertex v1 = {0, 0}; Vertex v2 = {1, 2}; Vertex v3 = {2, 0}; Vertex v4 = {1, -2}; printf("Distance=%.3f\n", Vertex_distance(&v1, &v2)); Polygon p; Polygon_init(&p, 3); Polygon_addVertex(&p, v1); Polygon_addVertex(&p, v2); Polygon_addVertex(&p, v3); Polygon_print(&p); printf("Polygon(p) area=%.3f\n", Polygon_area(&p)); Polygon_destroy(&p); Polygon q; Polygon_init(&q, 4); Polygon_addVertex(&q, v1); Polygon_addVertex(&q, v2); Polygon_addVertex(&q, v3); Polygon_addVertex(&q, v4); Polygon_print(&q); printf("Polygon(q) area=%.3f\n", Polygon_area(&q)); Polygon_destroy(&q); return 0; }