/*
This software may only be used by you under license from AT&T Corp.
("AT&T"). A copy of AT&T's Source Code Agreement is available at
AT&T's Internet website having the URL:
<http://www.research.att.com/sw/tools/graphviz/license/source.html>
If you received this software without first entering into a license
with AT&T, you have an infringing copy of this software and cannot use
it without violating AT&T's intellectual property rights.
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <pathutil.h>
#include <tri.h>
#ifdef DMALLOC
#include "dmalloc.h"
#endif
typedef struct lvertex_2_t {
double x, y;
} lvertex_2_t;
typedef struct dpd_triangle {
Ppoint_t *v[3];
} ltriangle_t ;
#define ISCCW 1
#define ISCW 2
#define ISON 3
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
static int dpd_ccw (Ppoint_t * , Ppoint_t * , Ppoint_t * );
static int dpd_isdiagonal (int, int, Ppoint_t **, int);
static int dpd_intersects (Ppoint_t *, Ppoint_t *, Ppoint_t *, Ppoint_t * );
static int dpd_between (Ppoint_t *, Ppoint_t *, Ppoint_t *);
static void triangulate(Ppoint_t **pointp, int pointn, void (*fn)(void*, Ppoint_t*), void *vc);
static int dpd_ccw (Ppoint_t *p1, Ppoint_t *p2, Ppoint_t *p3) {
double d=((p1->y-p2->y)*(p3->x-p2->x))-((p3->y-p2->y)*(p1->x-p2->x));
return (d > 0) ? ISCW : ((d < 0) ? ISCCW : ISON);
}
void Ptriangulate(Ppoly_t *polygon, void (*fn)(void *, Ppoint_t*), void *vc)
{
int i ;
int pointn;
Ppoint_t **pointp;
pointn = polygon->pn;
pointp = (Ppoint_t **) malloc(pointn * sizeof(Ppoint_t *)) ;
for (i = 0 ; i < pointn ; i++ )
pointp[i] = &(polygon->ps[i]);
triangulate(pointp, pointn, fn, vc);
free(pointp);
}
static void
triangulate(Ppoint_t **pointp, int pointn, void (*fn)(void*, Ppoint_t*), void *vc)
{
int i, ip1, ip2, j;
Ppoint_t A[3];
if (pointn > 3) {
for (i = 0; i < pointn; i++) {
ip1 = (i + 1) % pointn;
ip2 = (i + 2) % pointn;
if (dpd_isdiagonal (i, ip2, pointp, pointn)) {
A[0] = *pointp[i];
A[1] = *pointp[ip1] ;
A[2] = *pointp[ip2] ;
fn(vc, A);
j = 0;
for (i = 0; i < pointn; i++)
if (i != ip1) pointp[j++] = pointp[i];
triangulate(pointp, pointn - 1, fn, vc);
return;
}
}
abort ();
}
else {
A[0] = *pointp[0];
A[1] = *pointp[1] ;
A[2] = *pointp[2] ;
fn(vc, A);
}
}
/* check if (i, i + 2) is a diagonal */
static int dpd_isdiagonal (int i, int ip2, Ppoint_t **pointp, int pointn) {
int ip1, im1, j, jp1, res;
/* neighborhood test */
ip1 = (i + 1) % pointn;
im1 = (i + pointn - 1) % pointn;
/* If P[i] is a convex vertex [ i+1 left of (i-1,i) ]. */
if (dpd_ccw (pointp[im1], pointp[i], pointp[ip1]) == ISCCW)
res = (dpd_ccw (pointp[i], pointp[ip2], pointp[im1]) == ISCCW) &&
(dpd_ccw (pointp[ip2], pointp[i], pointp[ip1]) == ISCCW);
/* Assume (i - 1, i, i + 1) not collinear. */
else
res = ((dpd_ccw (pointp[i], pointp[ip2], pointp[ip1]) == ISCW)
);
/*
&&
(dpd_ccw (pointp[ip2], pointp[i], pointp[im1]) != ISCW));
*/
if (!res) {
return FALSE;
}
/* check against all other edges */
for (j = 0; j < pointn; j++) {
jp1 = (j + 1) % pointn;
if (!((j == i) || (jp1 == i) || (j == ip2) || (jp1 == ip2)))
if (dpd_intersects (pointp[i], pointp[ip2], pointp[j],pointp[jp1])){
return FALSE;
}
}
return TRUE;
}
/* line to line intersection */
static int dpd_intersects (Ppoint_t *pa, Ppoint_t *pb, Ppoint_t *pc, Ppoint_t *pd) {
int ccw1, ccw2, ccw3, ccw4;
if (dpd_ccw(pa, pb, pc) == ISON || dpd_ccw (pa, pb, pd) == ISON ||
dpd_ccw (pc, pd, pa) == ISON || dpd_ccw (pc, pd, pb) == ISON) {
if (dpd_between (pa, pb, pc) || dpd_between (pa, pb, pd) ||
dpd_between (pc, pd, pa) || dpd_between (pc, pd, pb))
return TRUE;
} else {
ccw1 = (dpd_ccw (pa, pb, pc) == ISCCW) ? 1 : 0;
ccw2 = (dpd_ccw (pa, pb, pd) == ISCCW) ? 1 : 0;
ccw3 = (dpd_ccw (pc, pd, pa) == ISCCW) ? 1 : 0;
ccw4 = (dpd_ccw (pc, pd, pb) == ISCCW) ? 1 : 0;
return (ccw1 ^ ccw2) && (ccw3 ^ ccw4);
}
return FALSE;
}
static int dpd_between (Ppoint_t * pa, Ppoint_t * pb, Ppoint_t * pc) {
Ppoint_t pba, pca;
pba.x = pb->x - pa->x, pba.y = pb->y - pa->y;
pca.x = pc->x - pa->x, pca.y = pc->y - pa->y;
if (dpd_ccw (pa, pb, pc) != ISON)
return FALSE;
return (pca.x * pba.x + pca.y * pba.y >= 0) &&
(pca.x * pca.x + pca.y * pca.y <= pba.x * pba.x + pba.y * pba.y);
}
|