* 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;
}

 

C语言求凸多边形面积, polygon_polygon