Extern :
- aggiunto FIST 6.8 ( già modificato per integrazione nelle nostre librerie).
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* */
|
||||
/* Note: A polygonal area with a total of N vertices and H holes has exactly */
|
||||
/* N - 2 + 2 * H */
|
||||
/* triangles. */
|
||||
/* */
|
||||
|
||||
#include "martin.h"
|
||||
#include "defs.h"
|
||||
|
||||
// MODIF : includo questo file per rendere api_fist l'unico file da includere per utilizzare fist
|
||||
#include "header.h"
|
||||
|
||||
/* api_functions.cpp: */
|
||||
|
||||
boolean FIST_HandlePolyhedron(rt_options *rt_opt);
|
||||
|
||||
boolean FIST_HandlePolygon(rt_options *rt_opt);
|
||||
|
||||
boolean FIST_2D_PolyArray(int num_contours, int num_vertices[],
|
||||
double (*input_vtx)[2], int *num_triangles,
|
||||
int (*output_tri)[3]);
|
||||
|
||||
boolean FIST_3D_FaceArray(int num_contours, int num_vtx[],
|
||||
double (*input_vtx)[3], int *num_tri,
|
||||
int (*output_tri)[3]);
|
||||
|
||||
void FIST_TerminateProgram(global_struct *all);
|
||||
|
||||
void FIST_HandleError(errordef FistErrorCode);
|
||||
|
||||
const char* FIST_GetProgName();
|
||||
|
||||
const char* FIST_GetProgVersion();
|
||||
|
||||
const char* FIST_GetProgYear();
|
||||
|
||||
|
||||
|
||||
// funzioni aggiunte per integrazione con le nostre librerie
|
||||
/* fist_added_functions.cpp : */
|
||||
void AddLoopInFace( global_struct *all, int nHoles, boolean bFirstLoop, int nPoints) ;
|
||||
void OptimizeMemoryAllocation( global_struct *all, int nLoops, int nPoints) ;
|
||||
@@ -0,0 +1,310 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _BASIC_H_
|
||||
#define _BASIC_H_
|
||||
|
||||
#ifndef RAND
|
||||
#define RND_MAX 2147483647
|
||||
|
||||
#define UniformRandom(x) \
|
||||
{\
|
||||
x = ((machine_double) random()) / RND_MAX; }
|
||||
|
||||
#define RandomInteger(var, N) \
|
||||
(\
|
||||
assert(N > 0), \
|
||||
var = random(), \
|
||||
var - (var / (N)) * (N))
|
||||
|
||||
#define InitRandom(seed) \
|
||||
{\
|
||||
srandom(seed); }
|
||||
|
||||
#else
|
||||
|
||||
#ifdef RAND_MAX
|
||||
#define RND_MAX RAND_MAX
|
||||
#else
|
||||
#define RND_MAX 32767
|
||||
#endif
|
||||
|
||||
#define UniformRandom(x) \
|
||||
{\
|
||||
x = ((machine_double) rand()) / RND_MAX; }
|
||||
|
||||
#define RandomInteger(var, N) \
|
||||
(\
|
||||
assert(N > 0), \
|
||||
var = rand(), \
|
||||
var - (var / (N)) * (N))
|
||||
|
||||
#define InitRandom(seed) \
|
||||
{\
|
||||
srand(seed); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define RandomVertex(a) \
|
||||
{\
|
||||
UniformRandom((a).x); \
|
||||
UniformRandom((a).y); \
|
||||
UniformRandom((a).z); }
|
||||
|
||||
|
||||
|
||||
#define DetExp(u_x, u_y, u_z, v_x, v_y, v_z, w_x, w_y, w_z) \
|
||||
((u_x) * ((v_y) * (w_z) - (v_z) * (w_y)) - \
|
||||
(u_y) * ((v_x) * (w_z) - (v_z) * (w_x)) + \
|
||||
(u_z) * ((v_x) * (w_y) - (v_y) * (w_x)))
|
||||
|
||||
|
||||
#define Det3D(u, v, w) \
|
||||
((u).x * ((v).y * (w).z - (v).z * (w).y) - \
|
||||
(u).y * ((v).x * (w).z - (v).z * (w).x) + \
|
||||
(u).z * ((v).x * (w).y - (v).y * (w).x))
|
||||
|
||||
|
||||
#define Det2D(u, v, w) \
|
||||
(((u).x - (v).x) * ((v).y - (w).y) + ((v).y - (u).y) * ((v).x - (w).x))
|
||||
|
||||
|
||||
#define Length2D(u) \
|
||||
(((u).x * (u).x) + ((u).y * (u).y))
|
||||
|
||||
|
||||
#define Length2(u) \
|
||||
(((u).x * (u).x) + ((u).y * (u).y) + ((u).z * (u).z))
|
||||
|
||||
|
||||
#define Length_l1(u) \
|
||||
(Abs((u).x) + Abs((u).y) + Abs((u).z))
|
||||
|
||||
|
||||
#define Length_l2(u) \
|
||||
sqrt(((u).x * (u).x) + ((u).y * (u).y) + ((u).z * (u).z))
|
||||
|
||||
|
||||
#define DotProduct(u, v) \
|
||||
(((u).x * (v).x) + ((u).y * (v).y) + ((u).z * (v).z))
|
||||
|
||||
|
||||
#define DotProduct2D(u, v) \
|
||||
(((u).x * (v).x) + ((u).y * (v).y))
|
||||
|
||||
#define DotProduct2DTMD(u, v) \
|
||||
((TO_MDOUBLE((u).x) * TO_MDOUBLE((v).x)) + (TO_MDOUBLE((u).y) * TO_MDOUBLE((v).y)))
|
||||
|
||||
#define VectorProduct(p, q, r) \
|
||||
{(r).x = (p).y * (q).z - (q).y * (p).z; \
|
||||
(r).y = (q).x * (p).z - (p).x * (q).z; \
|
||||
(r).z = (p).x * (q).y - (q).x * (p).y; }
|
||||
|
||||
|
||||
#define VectorAdd(p, q, r) \
|
||||
{(r).x = (p).x + (q).x; \
|
||||
(r).y = (p).y + (q).y; \
|
||||
(r).z = (p).z + (q).z; }
|
||||
|
||||
#define LinearComb(p, q, r, t) \
|
||||
{(r).x = (p).x + (t) * ((q).x - (p).x); \
|
||||
(r).y = (p).y + (t) * ((q).y - (p).y); \
|
||||
(r).z = (p).z + (t) * ((q).z - (p).z); }
|
||||
|
||||
#define VectorSub(p, q, r) \
|
||||
{(r).x = (p).x - (q).x; \
|
||||
(r).y = (p).y - (q).y; \
|
||||
(r).z = (p).z - (q).z; }
|
||||
|
||||
|
||||
#define VectorAdd2D(p, q, r) \
|
||||
{(r).x = (p).x + (q).x; \
|
||||
(r).y = (p).y + (q).y; }
|
||||
|
||||
|
||||
#define VectorSub2D(p, q, r) \
|
||||
{(r).x = (p).x - (q).x; \
|
||||
(r).y = (p).y - (q).y; }
|
||||
|
||||
|
||||
#define LinearComb2D(p, q, r, t) \
|
||||
{(r).x = (p).x + (t) * ((q).x - (p).x); \
|
||||
(r).y = (p).y + (t) * ((q).y - (p).y); }
|
||||
|
||||
#define InvertVector(p) \
|
||||
{(p).x = -(p).x; \
|
||||
(p).y = -(p).y; \
|
||||
(p).z = -(p).z; }
|
||||
|
||||
|
||||
#define MultScalar(scalar, u) \
|
||||
{(u).x *= scalar; \
|
||||
(u).y *= scalar; \
|
||||
(u).z *= scalar; }
|
||||
|
||||
|
||||
#define DivScalar(scalar, u) \
|
||||
{(u).x /= scalar; \
|
||||
(u).y /= scalar; \
|
||||
(u).z /= scalar; }
|
||||
|
||||
|
||||
#define InvertVector2D(p) \
|
||||
{(p).x = -(p).x; \
|
||||
(p).y = -(p).y; }
|
||||
|
||||
|
||||
#define MultScalar2D(scalar, u) \
|
||||
{(u).x *= scalar; \
|
||||
(u).y *= scalar; }
|
||||
|
||||
|
||||
#define DivScalar2D(scalar, u) \
|
||||
{(u).x /= scalar; \
|
||||
(u).y /= scalar; }
|
||||
|
||||
|
||||
#define SignEps(var, x, eps) \
|
||||
(var = (x), \
|
||||
((var <= eps) ? ((var < -eps) ? -1 : 0) : 1))
|
||||
|
||||
|
||||
#define MinMax3(a, b, c, min, max) {\
|
||||
if ((a) < (b)) {\
|
||||
if ((a) < (c)) {\
|
||||
min = (a); \
|
||||
if ((b) < (c)) max = (c); \
|
||||
else max = (b); \
|
||||
}\
|
||||
else { \
|
||||
min = (c); \
|
||||
max = (b); \
|
||||
}\
|
||||
}\
|
||||
else { \
|
||||
if ((a) < (c)) {\
|
||||
min = (b); \
|
||||
max = (c); \
|
||||
} \
|
||||
else { \
|
||||
max = (a); \
|
||||
if ((b) < (c)) min = (b); \
|
||||
else min = (c); \
|
||||
} \
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
#define MinMax4(a, b, c, d, min, max) {\
|
||||
if ((a) < (b)) {\
|
||||
if ((a) < (c)) {\
|
||||
min = (a); \
|
||||
if ((b) < (c)) max = (c); \
|
||||
else max = (b); \
|
||||
} \
|
||||
else { \
|
||||
min = (c); \
|
||||
max = (b); \
|
||||
} \
|
||||
}\
|
||||
else { \
|
||||
if ((a) < (c)) { \
|
||||
min = (b); \
|
||||
max = (c); \
|
||||
} \
|
||||
else { \
|
||||
max = (a); \
|
||||
if ((b) < (c)) min = (b); \
|
||||
else min = (c); \
|
||||
}\
|
||||
} \
|
||||
if ((d) < min) min = (d); \
|
||||
else if ((d) > max) max = (d); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ScaleX(data,xc) ((xc - data->shift.x) * data->scale_factor)
|
||||
|
||||
#define ScaleY(data,yc) ((yc - data->shift.y) * data->scale_factor)
|
||||
|
||||
#define UnscaleX(data,xc) (data->shift.x + xc / data->scale_factor)
|
||||
|
||||
#define UnscaleY(data,yc) (data->shift.y + yc / data->scale_factor)
|
||||
|
||||
|
||||
|
||||
#define SortTwoNumbers(a, b, c) {\
|
||||
if (a > b) { \
|
||||
c = a; \
|
||||
a = b; \
|
||||
b = c; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define SortThreeNumbers(a, b, c, d) {\
|
||||
if (a < b) {\
|
||||
if (a < c) {\
|
||||
if (b > c) {\
|
||||
d = b; \
|
||||
b = c; \
|
||||
c = d; \
|
||||
}\
|
||||
}\
|
||||
else { \
|
||||
d = a; \
|
||||
a = c; \
|
||||
c = b; \
|
||||
b = d; \
|
||||
}\
|
||||
}\
|
||||
else { \
|
||||
if (a < c) { \
|
||||
d = a; \
|
||||
a = b; \
|
||||
b = d; \
|
||||
} \
|
||||
else { \
|
||||
if (b < c) {\
|
||||
d = a; \
|
||||
a = b; \
|
||||
b = c; \
|
||||
c = d; \
|
||||
}\
|
||||
else { \
|
||||
d = a; \
|
||||
a = c; \
|
||||
c = d; \
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
#define MinMax(a, b, min, max) {\
|
||||
if ((b) < (a)) {\
|
||||
min = (b); \
|
||||
max = (a); \
|
||||
} \
|
||||
else { \
|
||||
min = (a); \
|
||||
max = (b); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#define Pnt_In_BBox(data, bb1, i) \
|
||||
((((bb1).imax < i) ? false : \
|
||||
(((bb1).imin > i) ? false : \
|
||||
(((bb1).ymax < data->points[i].y) ? false : \
|
||||
(((bb1).ymin > data->points[i].y) ? false : true)))))
|
||||
|
||||
|
||||
|
||||
#define BBox_Overlap(bb1, bb2) \
|
||||
((((bb1).imax < (bb2).imin) ? false : \
|
||||
(((bb1).imin > (bb2).imax) ? false : \
|
||||
(((bb1).ymax < (bb2).ymin) ? false : \
|
||||
(((bb1).ymin > (bb2).ymax) ? false : true)))))
|
||||
|
||||
|
||||
#define BBox_Contained(bb1, bb2) \
|
||||
(((bb1).imin <= (bb2).imin) && ((bb1).imax >= (bb2).imax) && \
|
||||
((bb1).ymin <= (bb2).ymin) && ((bb1).ymax >= (bb2).ymax))
|
||||
|
||||
|
||||
|
||||
#define BBox_IdenticalLeaf(bb1, bb2) \
|
||||
(((bb1).imin == (bb2).imin) && ((bb1).imax == (bb2).imax))
|
||||
|
||||
|
||||
|
||||
#define BBox_Union(bb1, bb2, bb3) \
|
||||
{ (bb3).imin = Min((bb1).imin, (bb2).imin); \
|
||||
(bb3).imax = Max((bb1).imax, (bb2).imax); \
|
||||
(bb3).ymin = Min((bb1).ymin, (bb2).ymin); \
|
||||
(bb3).ymax = Max((bb1).ymax, (bb2).ymax); }
|
||||
|
||||
|
||||
|
||||
#define BBox_Area(data, bb, area) \
|
||||
{ area = (data->points[(bb).imax].x - data->points[(bb).imin].x) * \
|
||||
((bb).ymax - (bb).ymin); }
|
||||
|
||||
|
||||
|
||||
#define BBox_Copy(bb1, bb2) \
|
||||
{ (bb2).imin = (bb1).imin; \
|
||||
(bb2).imax = (bb1).imax; \
|
||||
(bb2).ymin = (bb1).ymin; \
|
||||
(bb2).ymax = (bb1).ymax; }
|
||||
|
||||
|
||||
|
||||
#define BBox_CopyInverted(bb1, bb2) \
|
||||
{ (bb2).imin = (bb1).imax; \
|
||||
(bb2).imax = (bb1).imin; \
|
||||
(bb2).ymin = (bb1).ymax; \
|
||||
(bb2).ymax = (bb1).ymin; }
|
||||
|
||||
|
||||
|
||||
#define BBox_Enlarge(bb1, bb2) \
|
||||
{ if ((bb1).imin < (bb2).imin) (bb2).imin = (bb1).imin; \
|
||||
if ((bb1).imax > (bb2).imax) (bb2).imax = (bb1).imax; \
|
||||
if ((bb1).ymin < (bb2).ymin) (bb2).ymin = (bb1).ymin; \
|
||||
if ((bb1).ymax > (bb2).ymax) (bb2).ymax = (bb1).ymax; }
|
||||
|
||||
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro computes the bounding box of a line segment whose end */
|
||||
/* points i, j are sorted according to x-coordinates. */
|
||||
/* */
|
||||
#define BBox(data, i, j, bb) \
|
||||
{ assert(InPointsList(data,i)); \
|
||||
assert(InPointsList(data,j)); \
|
||||
\
|
||||
MinMax(i, j, (bb).imin, (bb).imax); \
|
||||
MinMax(data->points[(bb).imin].y, data->points[(bb).imax].y, (bb).ymin, (bb).ymax); }
|
||||
|
||||
|
||||
|
||||
|
||||
#define BBox_Overlap_Extended(data, bb1, bb2) \
|
||||
((((bb1).ymax < (bb2).ymin) ? false : \
|
||||
(((bb1).ymin > (bb2).ymax) ? false : \
|
||||
(((bb1).xmax < data->points[(bb2).imin].x) ? false : \
|
||||
(((bb1).xmin > data->points[(bb2).imax].x) ? false : true)))))
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
inline double atan2(const double &y, const double &x)
|
||||
{
|
||||
if( fabs(x) >= fabs(y) )
|
||||
{
|
||||
// Sector to the right
|
||||
if( x > 0 )
|
||||
{
|
||||
const double phi = y/x;
|
||||
return atan(phi);
|
||||
}
|
||||
// Sector to the left
|
||||
else if( x < 0 )
|
||||
{
|
||||
const double phi = y/x;
|
||||
if( y >= 0) {
|
||||
return atan(phi) + M_PI;
|
||||
} else {
|
||||
return atan(phi) - M_PI;
|
||||
}
|
||||
}
|
||||
// Hence, x and y are zero
|
||||
else
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
else if( fabs(y) >= fabs(x) )
|
||||
{
|
||||
// Sector to the top
|
||||
if( y > 0 )
|
||||
{
|
||||
const double phi = x/y;
|
||||
return M_PI_2 - atan(phi);
|
||||
}
|
||||
// Sector to the bottom
|
||||
if( y < 0 )
|
||||
{
|
||||
const double phi = x/y;
|
||||
return - M_PI_2 - atan(phi);
|
||||
}
|
||||
// Actually, the impossible case, x=y=0. Should be catched above.
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
// This can only happen, if x or y is NaN.
|
||||
else
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define SetExtApplPnt(DATA, P, X) \
|
||||
{\
|
||||
assert(InPointsList(DATA,P)); \
|
||||
DATA->points[P].ext_appl = X; \
|
||||
}
|
||||
|
||||
|
||||
#define GetExtApplPnt(DATA, P) \
|
||||
(\
|
||||
assert(InPointsList(DATA, P)), \
|
||||
DATA->points[P].ext_appl)
|
||||
@@ -0,0 +1,916 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef FIST_DEFS_H
|
||||
#define FIST_DEFS_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "martin.h"
|
||||
#include "ext_appl_defs.h"
|
||||
|
||||
#define PROG_NAME "F I S T"
|
||||
#define PROG_VERSION "6.8"
|
||||
#define PROG_YEAR "1997-2025"
|
||||
#define NIL -1
|
||||
|
||||
#ifndef DOUBLE_OVERRIDE
|
||||
#define machine_double double
|
||||
#define double_global double
|
||||
#endif
|
||||
|
||||
#define machine_long long
|
||||
#define NEW_TRIANGLE_MIN 5
|
||||
|
||||
typedef enum {SEG, /* (input) line segment */
|
||||
ARC, /* (input) circular arc */
|
||||
PNT, /* (input) point/vertex */
|
||||
VDN, /* node of Voronoi diagram */
|
||||
VDE, /* edge of Voronoi diagram */
|
||||
DTE, /* edge of Delaunay triangulation */
|
||||
CCW, /* ccw offset arc */
|
||||
CW, /* cw offset arc */
|
||||
UNKNOWN} t_site;
|
||||
|
||||
typedef struct {
|
||||
int imin; /* lexicographically smallest point, determines min-x */
|
||||
int imax; /* lexicographically largest point, determines max-x */
|
||||
double ymin; /* minimum y-coordinate */
|
||||
double ymax; /* maximum y-coordinate */
|
||||
} bounding_box; /* bounding box */
|
||||
|
||||
typedef struct {
|
||||
int imin; /* lexicographically smallest point, determines min-x */
|
||||
int imax; /* lexicographically largest point, determines max-x */
|
||||
double xmin; /* minimum x-coordinate */
|
||||
double xmax; /* maximum x-coordinate */
|
||||
double ymin; /* minimum y-coordinate */
|
||||
double ymax; /* maximum y-coordinate */
|
||||
} bounding_box_extended;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
#ifdef EXT_APPL_SITES
|
||||
eas_type ext_appl; /* this field can be set by an application program to */
|
||||
/* refer to a user-defined entity. */
|
||||
#endif
|
||||
} vertex;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
#ifdef EXT_APPL_SITES
|
||||
eas_type ext_appl; /* this field can be set by an application program to */
|
||||
/* refer to a user-defined entity. */
|
||||
#endif
|
||||
} point;
|
||||
|
||||
/* This struct is needed for the PntPntDistSqd-Macro. */
|
||||
typedef struct {
|
||||
machine_double x;
|
||||
machine_double y;
|
||||
} md_point;
|
||||
|
||||
typedef int list_ind;
|
||||
|
||||
typedef struct {
|
||||
int v1;
|
||||
int v2;
|
||||
int v3;
|
||||
int color;
|
||||
#ifdef EXT_APPL_TRI
|
||||
eat_type ext_appl; /* this field can be set by an application program to */
|
||||
/* refer to a user-defined entity. */
|
||||
#endif
|
||||
#ifdef PARTITION_FIST
|
||||
list_ind ind1, ind2, ind3;
|
||||
boolean disabled;
|
||||
#endif
|
||||
} triangle;
|
||||
|
||||
#ifdef NORMALS
|
||||
typedef struct {
|
||||
int i1;
|
||||
int i2;
|
||||
int i3;
|
||||
} i_triangle;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int v1;
|
||||
int v2;
|
||||
int v3;
|
||||
int v4;
|
||||
#ifdef EXT_APPL_TRI
|
||||
eat_type ext_appl; /* this field can be set by an application program to */
|
||||
/* refer to a user-defined entity. */
|
||||
#endif
|
||||
} quadrangle;
|
||||
|
||||
typedef struct {
|
||||
list_ind ind;
|
||||
boolean ccw;
|
||||
} loop_list;
|
||||
|
||||
|
||||
typedef struct {
|
||||
list_ind ind;
|
||||
machine_double dist;
|
||||
} distance;
|
||||
|
||||
typedef struct {
|
||||
int index;
|
||||
list_ind prev;
|
||||
list_ind next;
|
||||
int convex;
|
||||
int original;
|
||||
boolean bridge;
|
||||
#ifdef NORMALS
|
||||
int t_index;
|
||||
int n_index;
|
||||
#endif
|
||||
#ifdef STAGES
|
||||
int stage;
|
||||
#endif
|
||||
#ifdef PARTITION_FIST
|
||||
boolean delete_reflex;
|
||||
#endif
|
||||
} list_node;
|
||||
|
||||
typedef struct {
|
||||
boolean color_graphics;
|
||||
boolean graphics;
|
||||
int step_size;
|
||||
char input_file[256];
|
||||
boolean read_input;
|
||||
boolean read_poly;
|
||||
boolean read_lines;
|
||||
boolean read_obj;
|
||||
boolean read_dxf;
|
||||
boolean save_poly;
|
||||
char output_file[256];
|
||||
boolean write_dxf;
|
||||
boolean verbose;
|
||||
boolean quiet;
|
||||
boolean scale_data;
|
||||
boolean ears_sorted;
|
||||
boolean ears_random;
|
||||
boolean ears_fancy;
|
||||
boolean ears_top;
|
||||
boolean do_quads;
|
||||
boolean keep_quads;
|
||||
boolean keep_convex;
|
||||
boolean write_geom;
|
||||
boolean write_tri;
|
||||
char tri_file[256];
|
||||
char ipe_file[256];
|
||||
boolean write_ipe7;
|
||||
boolean c2p; /* convert to triangle's .poly format */
|
||||
char c2p_file[256];
|
||||
boolean help;
|
||||
boolean time;
|
||||
boolean statistics;
|
||||
boolean copy;
|
||||
boolean use_colors;
|
||||
boolean draw_concave;
|
||||
boolean sgi_output;
|
||||
boolean draw_groups;
|
||||
boolean full_screen;
|
||||
int inputprec;
|
||||
int mpfr_prec;
|
||||
} rt_options;
|
||||
|
||||
|
||||
/* needed by memory.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
|
||||
#define MAX_MEMORY_CURSOR 1024
|
||||
|
||||
typedef struct {
|
||||
void *array_ptr;
|
||||
size_t size;
|
||||
unsigned int high;
|
||||
} memory_dbg;
|
||||
|
||||
typedef struct {
|
||||
unsigned long curr_memory;
|
||||
unsigned long max_memory;
|
||||
memory_dbg memory_history[MAX_MEMORY_CURSOR];
|
||||
int memory_dbg_cursor;
|
||||
} debug_memdef;
|
||||
|
||||
/* needed by list.x moved globals to this struct listdef *
|
||||
* call InitListDefaults(*list) to get the default initialization */
|
||||
typedef struct {
|
||||
list_node *list;
|
||||
int num_list;
|
||||
int max_num_list;
|
||||
|
||||
list_ind *loops;
|
||||
int num_loops;
|
||||
int max_num_loops;
|
||||
|
||||
int *faces;
|
||||
int num_faces;
|
||||
int max_num_faces;
|
||||
|
||||
list_ind first_node;
|
||||
|
||||
list_ind *chains;
|
||||
int num_chains;
|
||||
int max_num_chains;
|
||||
|
||||
debug_memdef *memptr;
|
||||
} listdef;
|
||||
|
||||
|
||||
/* needed by bridge.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
list_ind ind;
|
||||
int index;
|
||||
} left;
|
||||
|
||||
typedef struct {
|
||||
distance *distances;
|
||||
int max_num_dist;
|
||||
|
||||
left *left_most;
|
||||
int max_num_left_most;
|
||||
|
||||
debug_memdef *memptr;
|
||||
} bridgedef;
|
||||
|
||||
|
||||
/* needed by vertex.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
#ifdef NORMALS
|
||||
vertex *t_vertices;
|
||||
int num_t_vertices;
|
||||
int max_num_t_vertices;
|
||||
|
||||
vertex *v_normals;
|
||||
int num_v_normals;
|
||||
int max_num_v_normals;
|
||||
|
||||
i_triangle *i_triangles;
|
||||
int num_i_triangles;
|
||||
int max_num_i_triangles;
|
||||
#endif
|
||||
|
||||
vertex *vertices;
|
||||
int num_vertices;
|
||||
int max_num_vertices;
|
||||
|
||||
triangle *triangles;
|
||||
int num_triangles;
|
||||
int max_num_triangles;
|
||||
|
||||
quadrangle *quads;
|
||||
int num_quads;
|
||||
int max_num_quads;
|
||||
|
||||
int *groups;
|
||||
int num_groups;
|
||||
int max_num_groups;
|
||||
int num_group_tris;
|
||||
int *group_tris;
|
||||
int *group_quads;
|
||||
int *group_loops;
|
||||
|
||||
loop_list *convex_loops;
|
||||
int num_convex_loops;
|
||||
int num_concave_loops;
|
||||
int max_num_convex_loops;
|
||||
|
||||
debug_memdef *memptr;
|
||||
} vertexdef;
|
||||
|
||||
/* needed by data.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
point *points;
|
||||
int num_pnts;
|
||||
int max_num_pnts;
|
||||
|
||||
boolean data_scaled;
|
||||
double scale_factor;
|
||||
point shift;
|
||||
machine_double bbox_diagonal_sqd;
|
||||
|
||||
debug_memdef *memptr;
|
||||
} datadef;
|
||||
|
||||
/* needed by clean_data.x moved globals to this struct *
|
||||
* call InitXXXXDef(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
point p;
|
||||
list_ind ind;
|
||||
} sort_record;
|
||||
|
||||
typedef struct {
|
||||
sort_record *p_unsorted;
|
||||
int max_num_p_unsorted;
|
||||
debug_memdef *memptr;
|
||||
} cleandef;
|
||||
|
||||
/***************************** grid.x structs ***************************/
|
||||
typedef int seg_ind;
|
||||
typedef int pnt_ind;
|
||||
|
||||
typedef struct {
|
||||
int imin; /* lexicographically smaller point, determines min-x */
|
||||
int imax; /* lexicographically larger point, determines max-x */
|
||||
double ymin; /* minimum y-coordinate */
|
||||
double ymax; /* maximum y-coordinate */
|
||||
boolean checked; /* has this segment already been checked? */
|
||||
} segment; /* boundary segment i1, i2, with i1 < i2 */
|
||||
|
||||
typedef struct {
|
||||
int seg;
|
||||
seg_ind next;
|
||||
} segment_node;
|
||||
|
||||
typedef struct {
|
||||
int pnt;
|
||||
pnt_ind next;
|
||||
} pnt_node;
|
||||
|
||||
typedef struct {
|
||||
int ident_cntr;
|
||||
#ifdef STATISTICS
|
||||
unsigned machine_long pnt_tri_cntr;
|
||||
#endif
|
||||
boolean no_grid_yet;
|
||||
seg_ind *grid;
|
||||
int max_num_grid;
|
||||
pnt_ind *grid2;
|
||||
int max_num_grid2;
|
||||
pnt_ind *grid3;
|
||||
int max_num_grid3;
|
||||
int N, N_x, N_y;
|
||||
int N2, N_x2, N_y2;
|
||||
int N3, N_x3, N_y3;
|
||||
double_global grid_x, grid_y;
|
||||
double_global grid_min_x, grid_min_y, grid_max_x, grid_max_y;
|
||||
double *raster_x;
|
||||
double *raster_y;
|
||||
double_global grid_x2, grid_y2;
|
||||
double_global grid_min_x2, grid_min_y2, grid_max_x2, grid_max_y2;
|
||||
double *raster_x2;
|
||||
double *raster_y2;
|
||||
double_global grid_x3, grid_y3;
|
||||
double_global grid_min_x3, grid_min_y3, grid_max_x3, grid_max_y3;
|
||||
double *raster_x3;
|
||||
double *raster_y3;
|
||||
int max_num_raster_x;
|
||||
int max_num_raster_y;
|
||||
int max_num_raster_x2;
|
||||
int max_num_raster_y2;
|
||||
int max_num_raster_x3;
|
||||
int max_num_raster_y3;
|
||||
segment *segments;
|
||||
int num_segments;
|
||||
int max_num_segments;
|
||||
segment_node *seg_list;
|
||||
int num_seg_list;
|
||||
int max_num_seg_list;
|
||||
pnt_node *pnt_list;
|
||||
int num_pnt_list;
|
||||
int max_num_pnt_list;
|
||||
pnt_node *vtx_list;
|
||||
int num_vtx_list;
|
||||
int max_num_vtx_list;
|
||||
int *set;
|
||||
int max_num_set;
|
||||
int num_set;
|
||||
double_global step_x, step_y;
|
||||
double_global delta_x, delta_y;
|
||||
int num_reflex;
|
||||
int num_original_reflex;
|
||||
boolean buckets_initialized;
|
||||
|
||||
debug_memdef *memptr;
|
||||
} griddef;
|
||||
/************************* END grid.x structs ***************************/
|
||||
|
||||
typedef struct {
|
||||
segment *seg_addr;
|
||||
int seg_i;
|
||||
seg_ind ind_seg;
|
||||
} gridtmp;
|
||||
|
||||
/* needed by quads.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
int v1;
|
||||
int v2;
|
||||
int tri;
|
||||
} edge;
|
||||
|
||||
typedef struct {
|
||||
int v1;
|
||||
int v2;
|
||||
int tri;
|
||||
int next;
|
||||
} hash_table;
|
||||
|
||||
typedef struct {
|
||||
int num_grouped;
|
||||
int *heads;
|
||||
int max_num_heads;
|
||||
hash_table *table;
|
||||
hash_table *element;
|
||||
int num_table;
|
||||
int max_num_table;
|
||||
} quaddef;
|
||||
|
||||
typedef struct {
|
||||
machine_double x;
|
||||
machine_double y;
|
||||
} coord;
|
||||
|
||||
|
||||
/* needed by io_basic.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
int first_pnt, last_pnt, new_pnts, curr_loop, poly_vertex_number;
|
||||
list_ind last_ind;
|
||||
} iolistdef;
|
||||
|
||||
|
||||
/* needed by io_3D.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
} rgb;
|
||||
|
||||
typedef struct {
|
||||
boolean draw_concave;
|
||||
boolean sgi_output;
|
||||
boolean draw_groups;
|
||||
|
||||
rgb color;
|
||||
#ifdef NORMALS
|
||||
boolean tex_norm_data_exists;
|
||||
boolean vertex_normals;
|
||||
boolean texture_vertices;
|
||||
#endif
|
||||
} io_3ddef;
|
||||
|
||||
|
||||
/* needed by redraw.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
int index;
|
||||
int color;
|
||||
} pnt_buffer;
|
||||
|
||||
typedef struct {
|
||||
int index1;
|
||||
int index2;
|
||||
int color;
|
||||
} edge_buffer;
|
||||
|
||||
typedef struct {
|
||||
int index1;
|
||||
int index2;
|
||||
int index3;
|
||||
int color1;
|
||||
int color2;
|
||||
} tri_buffer;
|
||||
|
||||
typedef struct {
|
||||
pnt_buffer *pnt_buf;
|
||||
edge_buffer *edge_buf;
|
||||
tri_buffer *tri_buf;
|
||||
|
||||
int num_pnt_buf, max_num_pnt_buf;
|
||||
int num_edge_buf, max_num_edge_buf;
|
||||
int num_tri_buf, max_num_tri_buf;
|
||||
|
||||
debug_memdef *memptr;
|
||||
} redrawdef;
|
||||
|
||||
|
||||
/* needed by ipe_io.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
machine_double scale;
|
||||
machine_double ipe_x_min, ipe_x_max, ipe_y_min, ipe_y_max;
|
||||
machine_double x_min, x_max, y_min, y_max;
|
||||
|
||||
boolean ipe7;
|
||||
} ipe_iodef;
|
||||
|
||||
|
||||
/* needed by predicates.x moved globals to this struct */
|
||||
#ifdef JRC_PREDICATE
|
||||
typedef struct {
|
||||
/* = 2^ceiling(p / 2) + 1. Used to split floats in half. */
|
||||
double splitter;
|
||||
double epsilon; /* = 2^(-p). Used to estimate roundoff errors. */
|
||||
/* A set of coefficients used to calculate maximum roundoff errors. */
|
||||
double resulterrbound;
|
||||
double ccwerrboundA, ccwerrboundB, ccwerrboundC;
|
||||
double o3derrboundA, o3derrboundB, o3derrboundC;
|
||||
double iccerrboundA, iccerrboundB, iccerrboundC;
|
||||
double isperrboundA, isperrboundB, isperrboundC;
|
||||
} predicatesdef;
|
||||
#endif
|
||||
|
||||
|
||||
/* needed by heap.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct hnode {
|
||||
machine_double ratio;
|
||||
list_ind index;
|
||||
list_ind prev;
|
||||
list_ind next;
|
||||
} heap_node;
|
||||
|
||||
typedef struct {
|
||||
boolean ears_sorted;
|
||||
boolean ears_random;
|
||||
|
||||
heap_node *heap;
|
||||
int num_heap;
|
||||
int max_num_heap;
|
||||
int num_zero;
|
||||
|
||||
boolean deleted;
|
||||
boolean not_updated;
|
||||
boolean sorted;
|
||||
boolean ear_right;
|
||||
|
||||
#ifdef PARTITION_FIST
|
||||
int heap_idx;
|
||||
#endif
|
||||
debug_memdef *memptr;
|
||||
} heapdef;
|
||||
|
||||
/* needed by ear_clip.x moved globals to this struct *
|
||||
* call InitXXXXDefaults(*ptr) to get the default initialization */
|
||||
typedef struct {
|
||||
boolean ears_fancy;
|
||||
boolean ears_top;
|
||||
boolean use_colors;
|
||||
int tri_color; /* 0 ... output triangle equals input triangle */
|
||||
/* 1 ... output triangle belongs to input quad */
|
||||
/* 2 ... output triangle belongs to convex face */
|
||||
/* 3 ... output triangle belongs to concave face */
|
||||
boolean is_convex_polygon;
|
||||
boolean ears_may_have_changed;
|
||||
} eardef;
|
||||
|
||||
/* needed by macros in numerics.h */
|
||||
typedef struct {
|
||||
point numerics_h_p, numerics_h_q, numerics_h_r;
|
||||
double numerics_h_det, numerics_h_dot;
|
||||
int numerics_h_ori1, numerics_h_ori2;
|
||||
} tmp_data_def;
|
||||
|
||||
typedef struct {
|
||||
pnt_ind ind_pnt, ind_pnt1;
|
||||
list_ind ind_vtx;
|
||||
} tmp_grid_def;
|
||||
|
||||
typedef struct {
|
||||
#ifdef CUDA
|
||||
/* not jet used */
|
||||
#endif
|
||||
} cudadef;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SUCCESS,
|
||||
MEM_ALLOC_FAILED,
|
||||
FILE_ACCESS_FAILED,
|
||||
INSUFFICENT_INPUT,
|
||||
EOF_ENCOUNTERED,
|
||||
WRONG_INPUT_OPTION,
|
||||
WRONG_OBJ_FORMAT,
|
||||
MEM_TRACKING_EXHAUSTED,
|
||||
MEM_REALLOC_MISMATCH,
|
||||
MEM_TRACKING_MESSED_UP,
|
||||
MEM_TYPE_MISMATCH,
|
||||
MEM_NULL_POINTER,
|
||||
IPE_FILE_NOT_INITIALIZED,
|
||||
IPE_FILE_INIT_FAILED,
|
||||
UNKNOWN_ERROR
|
||||
} errordef;
|
||||
|
||||
|
||||
/* global_struct for ALL globals */
|
||||
/* all former globals are packed into this struct */
|
||||
typedef struct {
|
||||
rt_options rt_opt; /* run-time options */
|
||||
iolistdef c_iolist; /* globals from basic.x */
|
||||
listdef c_list; /* globals from list.x */
|
||||
bridgedef c_bridge; /* globals from bridge.x */
|
||||
vertexdef c_vertex; /* globals from vertex.x */
|
||||
datadef c_data; /* globals from data.x */
|
||||
cleandef c_clean; /* globals from clean_data.x */
|
||||
griddef c_grid; /* globals from grid.x */
|
||||
quaddef c_quad; /* globals from quads.x */
|
||||
io_3ddef c_io3d; /* globals from io_3D.x */
|
||||
#ifdef GRAPHICS
|
||||
redrawdef c_redraw; /* globals from redraw.x */
|
||||
#endif
|
||||
ipe_iodef c_ipe_io; /* globals from ipe_io.x */
|
||||
cudadef c_cuda; /* globals for ./gpu/.x */
|
||||
#ifdef JRC_PREDICATE
|
||||
predicatesdef c_pred; /* globals from predicates.x */
|
||||
#endif
|
||||
#ifdef DEBUG_MEMORY
|
||||
debug_memdef c_mem; /* globals from memory.x */
|
||||
#else
|
||||
void *c_mem;
|
||||
#endif
|
||||
eardef c_ear; /* globals from ear_clip.x */
|
||||
#ifdef PARTITION_FIST
|
||||
boolean partition_mode;
|
||||
int number_of_heaps;
|
||||
list_ind *corner_nodes;
|
||||
heapdef *c_heap; /* globals from heap.x */
|
||||
#else
|
||||
heapdef c_heap; /* globals from heap.x */
|
||||
#endif
|
||||
|
||||
point bb_min;
|
||||
point bb_max;
|
||||
|
||||
#ifdef GRAPHICS
|
||||
boolean draw_pnts;
|
||||
boolean draw_point_idx;
|
||||
#endif
|
||||
boolean is_convex_face;
|
||||
|
||||
int num_contours;
|
||||
|
||||
unsigned machine_long bb_cntr;
|
||||
unsigned machine_long cell_cntr;
|
||||
|
||||
boolean ccw_loop;
|
||||
boolean isolated_pnts;
|
||||
|
||||
int io_flag;
|
||||
machine_double x_delta, y_delta;
|
||||
|
||||
boolean new_input;
|
||||
boolean done;
|
||||
boolean reset;
|
||||
boolean troubles;
|
||||
boolean written;
|
||||
|
||||
machine_double cpu_time;
|
||||
#ifndef NO_CPUTIME
|
||||
timeval start, end;
|
||||
#endif
|
||||
|
||||
FILE *dxf_file;
|
||||
|
||||
int curr_loop_main; /* main.c's separate curr_loop */
|
||||
|
||||
/* from orientation.c */
|
||||
double *poly_area;
|
||||
int max_num_poly_area;
|
||||
|
||||
#ifdef CPUTIME_IN_MILLISECONDS
|
||||
unsigned long total_secs;
|
||||
unsigned long total_usecs;
|
||||
#else
|
||||
#ifdef CPUTIME_VIA_CLOCK
|
||||
clock_t total_cpu_time;
|
||||
boolean cpu_time_initialized;
|
||||
#else
|
||||
long total_cpu_time;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* from write_ipe.c */
|
||||
boolean ipe_initialized;
|
||||
#ifdef EXPR_WRAPPER
|
||||
boolean returncore;
|
||||
#endif
|
||||
} global_struct;
|
||||
/* ------------------------------ END global_struct ------------------------ */
|
||||
|
||||
/* */
|
||||
/* get the definitions for "exterior applications" */
|
||||
/* */
|
||||
#include "ext_appl_defs.h"
|
||||
|
||||
#define TriTriColor 0 /* 0 ... output triangle equals input triangle */
|
||||
#define TriQuadColor 1 /* 1 ... output triangle belongs to input quad */
|
||||
#define TriCvxColor 2 /* 2 ... output triangle belongs to convex face */
|
||||
#define TriCveColor 3 /* 3 ... output triangle belongs to concave face */
|
||||
|
||||
#ifdef DOUBLE_OVERRIDE /* if the CORE library is used */
|
||||
|
||||
const double C_0_0 = STRING_TO_REAL("0.0");
|
||||
const double C_0_1 = STRING_TO_REAL("0.1");
|
||||
const double C_0_3 = STRING_TO_REAL("0.3");
|
||||
const double C_1_0 = STRING_TO_REAL("1.0");
|
||||
const double C_1_1 = STRING_TO_REAL("1.1");
|
||||
const double C_2_0 = STRING_TO_REAL("2.0");
|
||||
const double C_m2_0 = STRING_TO_REAL("-2.0");
|
||||
const double C_3_0 = STRING_TO_REAL("3.0");
|
||||
const double C_4_0 = STRING_TO_REAL("4.0");
|
||||
const double C_20_0 = STRING_TO_REAL("20.0");
|
||||
|
||||
#else
|
||||
|
||||
#define C_0_0 0.0
|
||||
#define C_0_1 0.1
|
||||
#define C_0_3 0.3
|
||||
#define C_1_0 1.0
|
||||
#define C_1_1 1.1
|
||||
#define C_2_0 2.0
|
||||
#define C_m2_0 -2.0
|
||||
#define C_3_0 3.0
|
||||
#define C_4_0 4.0
|
||||
#define C_20_0 20.0
|
||||
|
||||
#endif
|
||||
|
||||
/* */
|
||||
/* Some constants are used in expressions that need pure machine_double */
|
||||
/* constants. So above constants cannot be used in conjunction with */
|
||||
/* defined(WITH_COREBACKEND). The following constants can be used instead. */
|
||||
/* */
|
||||
#define CD_0_0 0.0
|
||||
#define CD_0_001 0.001
|
||||
#define CD_0_01 0.01
|
||||
#define CD_0_05 0.05
|
||||
#define CD_0_3 0.3
|
||||
#define CD_1_0 1.0
|
||||
#define CD_m1_0 -1.0
|
||||
#define CD_1_5 1.5
|
||||
#define CD_2_0 2.0
|
||||
#define CD_2_5 2.5
|
||||
#define CD_3_0 3.0
|
||||
#define CD_20_0 20.0
|
||||
#define CD_1000_0 1000.0
|
||||
|
||||
/*
|
||||
* global precision thresholds
|
||||
*
|
||||
* ZERO ... "small" number used for checking whether a value equals zero
|
||||
* (in order to avoid a division by zero). if set to 0.0 then
|
||||
* any number other than 0.0 is regarded as a legitimate
|
||||
* denumerator. please note that this may cause a numerical
|
||||
* overflow! thus, please think twice prior to changing the
|
||||
* default value of ZERO!!
|
||||
*
|
||||
* EPS ... used for comparisons with zero; if set to 0.0 then grazing
|
||||
* contacts are likely to be mishandled. however, the code
|
||||
* should not crash, and a small speed-up can be expected. in
|
||||
* particular, setting EPS to 0.0 causes the comparison macros
|
||||
* (lt, le, ... see martin.h) to function like their conventional
|
||||
* counterparts if such a macro is supplied with EPS as the
|
||||
* precision threshold to be used. very likely, it is best not
|
||||
* to change the default value of EPS! the main use of this
|
||||
* threshold is for the evaluation of 3x3 determinants, i.e.,
|
||||
* for the computation of the sign of the signed area of a
|
||||
* triangle defined by three (input) points. (virtually all
|
||||
* predicates used by FIST boil down to the computation of
|
||||
* the signed area of a triangle.) three points are considered
|
||||
* collinear if the absolute value of the area of the
|
||||
* corresponding triangle is less than or equal to EPS.
|
||||
* depending on whether or not the run-time option "--scale"
|
||||
* is used, those areas are computed relative to the original
|
||||
* coordinates of the input points, or relative to scaled
|
||||
* copies of the input points. (if requested by the user,
|
||||
* scaling is performed such that the input data ends up in
|
||||
* [-1,1]x[-1,1].) note that setting EPS to a non-zero value
|
||||
* is a must if the compile-time option --DGRAZING is used;
|
||||
* see Imakefile for an explanation. (what is a good value for
|
||||
* EPS depends on your data and your intended application; the
|
||||
* value defined below seems to work for a wide range of data.
|
||||
* however, it is obvious that there may exist applications for
|
||||
* which a user might want to be more liberal or more conservative
|
||||
* in allowing FIST to classify items as degenerate. one way or
|
||||
* the other, FIST should not crash!)
|
||||
*/
|
||||
#ifdef DOUBLE_OVERRIDE
|
||||
|
||||
/* In case of using the MPFR backend, EPS and ZERO need to be set according the
|
||||
* MPFR precision, which is set at runtime. So EPS and ZERO need to be global
|
||||
* variables.
|
||||
*/
|
||||
#if defined(WITH_MPFRBACKEND) || defined (WITH_EXPR_WRAPPER)
|
||||
extern double EPS;
|
||||
extern double ZERO;
|
||||
#define ZERO_D 1.0e-16
|
||||
#else /* so we are using an exact backend */
|
||||
const double EPS = STRING_TO_REAL("0.0");
|
||||
const double ZERO = STRING_TO_REAL("0.0");
|
||||
#define ZERO_D 0.0
|
||||
#endif
|
||||
|
||||
#else /* DOUBLE OVERRIEDE */
|
||||
|
||||
#ifdef THRESHOLD
|
||||
#define THRES 1.0e-5
|
||||
#define EPS 1.0e-15
|
||||
#define ZERO 1.0e-16
|
||||
#define ZERO_D 1.0e-16
|
||||
#else /* don't even think about using this else branch! */
|
||||
#define THRES 0.0
|
||||
#define EPS 0.0
|
||||
#define ZERO 0.0
|
||||
#define ZERO_D 0.0
|
||||
#endif /* THRESHOLD */
|
||||
|
||||
#endif /* DOUBLE OVERRIDE */
|
||||
|
||||
|
||||
#ifdef MEM_COPY
|
||||
|
||||
/* */
|
||||
/* unfortunately, the following stuff is needed in order to make FIST comply */
|
||||
/* with CORE's memory re-allocation... */
|
||||
/* */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
template <class DATATYPE>
|
||||
DATATYPE* ReallocateArray_Copy(DATATYPE* old_mem, int old_size, int new_size, size_t size, const char var_name[])
|
||||
{
|
||||
DATATYPE* new_mem = NULL;
|
||||
|
||||
if (old_mem != NULL)
|
||||
{
|
||||
new_mem = new DATATYPE[new_size];
|
||||
if (new_mem != NULL)
|
||||
{
|
||||
for (int i = 0; i < old_size; i++)
|
||||
new_mem[i] = old_mem[i];
|
||||
delete []old_mem;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "*** Array `%s' cannot be reallocated! ***\n", var_name);
|
||||
fprintf(stderr, "*** Cannot get %d elements of %lu bytes... ***\n", new_size, (unsigned long) size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_mem = new DATATYPE[new_size];
|
||||
if (new_mem == NULL)
|
||||
{
|
||||
fprintf(stderr, "*** Array `%s' cannot be reallocated! ***\n", var_name);
|
||||
fprintf(stderr, "*** Cannot get %d elements of %lu bytes... ***\n", new_size, (unsigned long) size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return new_mem;
|
||||
}
|
||||
|
||||
template <class DATATYPE>
|
||||
void FreeMemory_Copy(DATATYPE** ptr, const char *)
|
||||
{
|
||||
if (*ptr == NULL) return;
|
||||
|
||||
delete []*ptr;
|
||||
*ptr = NULL;
|
||||
}
|
||||
|
||||
#define CORE_ReallocateArray(mem, array, old_size, new_size, type, var_name) \
|
||||
ReallocateArray_Copy((array), (old_size), \
|
||||
(new_size), sizeof(type), (var_name))
|
||||
|
||||
#define CORE_FreeMemory(mem, array, var_name) FreeMemory_Copy((array), (var_name))
|
||||
|
||||
#else /* MEM_COPY */
|
||||
|
||||
#define CORE_ReallocateArray(mem, array, old_size, new_size, type, var_name) \
|
||||
(type *) ReallocateArray((mem), (array), (new_size),\
|
||||
sizeof(type), (var_name))
|
||||
#define CORE_FreeMemory(mem, array, var_name) \
|
||||
FreeMemory((mem), (void**)(array), (var_name))
|
||||
|
||||
|
||||
#endif /* MEM_COPY */
|
||||
|
||||
#endif /* FIST_DEFS_H */
|
||||
@@ -0,0 +1,156 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef EXT_APPL_DEFS
|
||||
#define EXT_APPL_DEFS
|
||||
|
||||
|
||||
/* */
|
||||
/* the following data types are used for user-defined entities that are to */
|
||||
/* be stored as part of my data structures. you are welcome to redefine them */
|
||||
/* according to your needs. however, please note that it is your task to */
|
||||
/* make sure that the functions and macros for I/O operations are modified */
|
||||
/* accordingly in io_parse.c !! also, you'd need to redefine the constants */
|
||||
/* eas_NIL, and eat_NIL in the file ext_appl_defs.c to whatever constant */
|
||||
/* integral value or structure that can be used for initializing the */
|
||||
/* exterior application structures. see the sample use for eas_... below. */
|
||||
/* */
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
#define EXT_APPL_PNTS
|
||||
typedef int eas_type; /* ext. appl. hook for point and vertex */
|
||||
typedef int eap_type; /* needed for compatibility with VRONI */
|
||||
#endif
|
||||
#ifdef EXT_APPL_TRI
|
||||
typedef int eat_type; /* ext. appl. hook for triangle and quadrangle */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sample user-specific eas data:
|
||||
*
|
||||
* typedef struct {
|
||||
* long id;
|
||||
* char ch[10];
|
||||
* } eas_type;
|
||||
*/
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
extern const eas_type eas_NIL;
|
||||
extern const eap_type eap_NIL;
|
||||
#endif
|
||||
#ifdef EXT_APPL_TRI
|
||||
extern const eat_type eat_NIL;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* */
|
||||
/* macro definitions for application-specific macros */
|
||||
/* */
|
||||
|
||||
#define ExtApplFuncStoreTri_1
|
||||
|
||||
#define ExtApplFuncStoreTri_2
|
||||
|
||||
#define ExtApplFuncStoreQuad
|
||||
|
||||
#define ExtApplFuncStoreVNormal
|
||||
|
||||
#define ExtApplFuncStoreTVertex
|
||||
|
||||
#define ExtApplFuncStoreVertex
|
||||
|
||||
#define ExtApplFuncStorePnt
|
||||
|
||||
#define ExtApplFuncNewInput
|
||||
|
||||
#define ExtApplFuncDesperate
|
||||
|
||||
#define ExtApplFuncReligious
|
||||
|
||||
#define ExtApplFuncRestart
|
||||
|
||||
#define ExtApplFuncDoneOneChain
|
||||
|
||||
#define ExtApplFuncNextChain
|
||||
|
||||
#define ExtApplFuncFinished
|
||||
|
||||
#define ExtApplFuncTerminateProg
|
||||
|
||||
#define ExtApplFuncResetAll
|
||||
|
||||
#define ExtApplFuncNewPoly
|
||||
|
||||
#define ExtApplFuncNewFace
|
||||
|
||||
#define ExtApplFuncBeforeTriangulation
|
||||
|
||||
#define ExtApplFuncDesperate3D
|
||||
|
||||
#define ExtApplFuncReligious3D
|
||||
|
||||
#define ExtApplFuncRestart3D
|
||||
|
||||
#define ExtApplFuncDoneOneChain3D
|
||||
|
||||
#define ExtApplFuncNextChain3D
|
||||
|
||||
#define ExtApplFuncDoneOneFace
|
||||
|
||||
#define ExtApplFuncDoneOneGroup
|
||||
|
||||
#define ExtApplFuncFinished3D
|
||||
|
||||
#define ExtApplFuncStartPoly
|
||||
|
||||
#define ExtApplFuncClosePoly_1
|
||||
|
||||
#define ExtApplFuncClosePoly_2
|
||||
|
||||
#define ExtApplFuncAddPolyVertex_1
|
||||
|
||||
#define ExtApplFuncAddPolyVertex_2
|
||||
|
||||
#define ExtApplFuncAddPolyVertex_3
|
||||
|
||||
#define ExtApplFuncAddPolyVertex_4
|
||||
|
||||
#define ExtApplFuncFISTWarning
|
||||
|
||||
#define ExtApplFuncStoreIsoPnt
|
||||
|
||||
#define ExtApplFuncHandlePolyhedronStart
|
||||
|
||||
#define ExtApplFuncHandlePolyhedronEnd
|
||||
|
||||
#define ExtApplFuncHandlePolygonEnd
|
||||
|
||||
#define ExtApplFuncHandlePolygonStart
|
||||
|
||||
#define ExtApplFunc2D_PolyArrayEnd
|
||||
|
||||
#define ExtApplFunc2D_PolyArrayStart
|
||||
|
||||
#define ExtApplFunc3D_FaceArrayEnd
|
||||
|
||||
#define ExtApplFunc3D_FaceArrayStart
|
||||
|
||||
#define ExtApplFuncTerminateTriangulation
|
||||
|
||||
#define ExtApplFuncFIST_HandleError
|
||||
|
||||
|
||||
#endif /* EXT_APPL_DEFS */
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
#ifndef FPKERNEL_H
|
||||
#define FPKERNEL_H
|
||||
|
||||
#include<cfloat>
|
||||
namespace {
|
||||
const double fpkernel_DBL_MAX = DBL_MAX;
|
||||
}
|
||||
|
||||
#ifdef WITH_EXPR_WRAPPER
|
||||
#define DOUBLE_OVERRIDE
|
||||
typedef double machine_double;
|
||||
#include <ExprWrapper.h>
|
||||
#include <formattedIO.h>
|
||||
|
||||
#define double ExprWrapper::ExprWrapper
|
||||
#define double_global ExprWrapper::ExprWrapper
|
||||
|
||||
#define REAL_TO_INT(x) (x).intValue()
|
||||
#define TO_MDOUBLE(x) (x).doubleValue()
|
||||
#define REAL_TO_FLOAT(x) (x).floatValue()
|
||||
|
||||
#define DOUBLE_TO_IOMDOUBLE(x) (x).doubleValue()
|
||||
#define MDOUBLE_TO_IOMDOUBLE(x) (x)
|
||||
|
||||
#define SET_PRECISION(var, prec) var.set_k2precision(prec)
|
||||
#define SET_CORE_MPFR_KERNEL(var, valk1, valk2, name) var.set_k1k2val(valk1, valk2, name)
|
||||
#define SET_MPFR_KERNEL_PI(var) var.set_k2pi()
|
||||
|
||||
//atof
|
||||
#define FP_atof double
|
||||
|
||||
#define shift a68fe7dac8c32f30ad04d52fab4aa46be1068d82
|
||||
#elif defined(WITH_COREBACKEND)
|
||||
/* Set CORE Level to 4. Otherwise all unsigned long no longer work */
|
||||
#define CORE_LEVEL 4
|
||||
|
||||
#include<CORE/CORE.h>
|
||||
#include <formattedIO.h>
|
||||
|
||||
#undef double
|
||||
#define double Expr
|
||||
#define double_global Expr
|
||||
|
||||
#define double_arg const double &
|
||||
|
||||
//This is used to indicate that double gets a different meaning!
|
||||
#define DOUBLE_OVERRIDE
|
||||
|
||||
#define TO_MDOUBLE(x) (x).doubleValue()
|
||||
|
||||
inline CORE::BigInt cut_comma(const Expr & x) {
|
||||
CORE::BigInt v = floor(x);
|
||||
if(v < 0) {
|
||||
return v + 1;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
#include "coreatan2.h"
|
||||
|
||||
inline int intfloor(const Expr & e) {
|
||||
return floor(e).intValue();
|
||||
}
|
||||
|
||||
inline unsigned int uintceil(const Expr & e) {
|
||||
return (unsigned)ceil(e).intValue();
|
||||
}
|
||||
|
||||
//REAL_TO_INT behaves like (int)(x)
|
||||
#define REAL_TO_INT(x) cut_comma(x).intValue()
|
||||
#define REAL_TO_GLINT(x) cut_comma(x).intValue()
|
||||
#define REAL_TO_FLOAT(x) (x).floatValue()
|
||||
#define BIGINT_TO_INT(x) (x).intValue()
|
||||
#define TO_REAL(x) double(x)
|
||||
#define STRING_TO_REAL(x) double(x)
|
||||
|
||||
|
||||
#define DOUBLE_TO_IOMDOUBLE(x) (x).doubleValue()
|
||||
#define MDOUBLE_TO_IOMDOUBLE(x) (x)
|
||||
|
||||
//atof
|
||||
#define FP_atof double
|
||||
|
||||
//Definitions for functions undefined in CORE
|
||||
#define isnan(x) 0
|
||||
//#define atan2(y,x) atan2local((y),(x))
|
||||
#define signbit(x) (x < 0 ? 1 : 0)
|
||||
|
||||
#define CORE_EXPR_OPS(name, x) { \
|
||||
std::map<std::string, unsigned int > m; \
|
||||
(x).rep()->rekCollectOp(m); \
|
||||
for(std::map<std::string, unsigned int>::iterator it = m.begin(); it != m.end(); ++it) { \
|
||||
std::cout << it->second << "\t: " << it->first << std::endl; \
|
||||
}}
|
||||
|
||||
#ifdef WITH_CORE_EXPR_WRAPPER
|
||||
inline void CORE_EXPR_SEQ(std::string name, const Expr & x) {
|
||||
std::map<unsigned int, std::string > m;
|
||||
(x).rep()->rekSequen(m);
|
||||
for (std::map<unsigned int, std::string>::iterator it = m.begin(); it != m.end(); ++it) {
|
||||
std::cout << it->second << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CORE_EXPR_DEBUG1(std::string name, const Expr & x) {
|
||||
std::cout << name << " depth: " << (x).rep()->getDepth() << std::endl;
|
||||
std::cout << name << " elementCount: " << (x).rep()->getElementCount() << std::endl;
|
||||
CORE_EXPR_SEQ(name, (x));
|
||||
std::cout << name << " value: " << (x) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// The second argument is the SHA1sum of "shift\n". This avoids a
|
||||
// conflict with a shift function in CORE - VRONI uses some
|
||||
// variables named shift
|
||||
#define shift a68fe7dac8c32f30ad04d52fab4aa46be1068d82
|
||||
|
||||
#elif defined(WITH_RABACKEND)
|
||||
|
||||
#include<Default_real_algebraic.hpp>
|
||||
#include <formattedIO.h>
|
||||
|
||||
typedef double machine_double;
|
||||
#undef double
|
||||
#define double Default_real_algebraic
|
||||
#define double_global Default_real_algebraic
|
||||
|
||||
#define double_arg const double &
|
||||
|
||||
//This is used to indicate that double gets a different meaning!
|
||||
#define DOUBLE_OVERRIDE
|
||||
|
||||
inline machine_double TO_MDOUBLE(const double & x) {
|
||||
x.guarantee_relative_error_two_to(-53);
|
||||
return x.get_interval().get_median();
|
||||
}
|
||||
|
||||
inline int cut_comma(const double & x) {
|
||||
return (int)TO_MDOUBLE(x);
|
||||
}
|
||||
|
||||
|
||||
inline int intfloor(const double & e) {
|
||||
int cut = cut_comma(e);
|
||||
if ( e < 0) {
|
||||
return cut - 1;
|
||||
} else {
|
||||
return cut;
|
||||
}
|
||||
}
|
||||
|
||||
inline double string_to_ra(const char * str) {
|
||||
machine_double md = atof(str);
|
||||
return double(md);
|
||||
}
|
||||
|
||||
//inline unsigned int uintceil(const Expr & e) {
|
||||
// return (unsigned)ceil(e).intValue();
|
||||
//}
|
||||
|
||||
//REAL_TO_INT behaves like (int)(x)
|
||||
#define REAL_TO_INT(x) cut_comma(x)
|
||||
#define REAL_TO_GLINT(x) cut_comma(x)
|
||||
#define REAL_TO_FLOAT(x) TO_MDOUBLE(x)
|
||||
//#define BIGINT_TO_INT(x) (x).intValue()
|
||||
#define TO_REAL(x) double(machine_double(x))
|
||||
#define STRING_TO_REAL(x) string_to_ra(x)
|
||||
|
||||
#define DOUBLE_TO_IOMDOUBLE(x) TO_MDOUBLE(x)
|
||||
#define MDOUBLE_TO_IOMDOUBLE(x) (x)
|
||||
|
||||
//atof
|
||||
#define FP_atof STRING_TO_REAL
|
||||
|
||||
//Definitions for functions undefined in CORE
|
||||
#define isnan(x) 0
|
||||
//#define atan2(y,x) atan2local((y),(x))
|
||||
#define signbit(x) (x < 0 ? 1 : 0)
|
||||
|
||||
|
||||
// The second argument is the SHA1sum of "shift\n". This avoids a
|
||||
// conflict with a shift function in CORE - VRONI uses some
|
||||
// variables named shift
|
||||
#define shift a68fe7dac8c32f30ad04d52fab4aa46be1068d82
|
||||
|
||||
#elif defined(WITH_MPFRBACKEND)
|
||||
|
||||
#include <mpfr_class.h>
|
||||
|
||||
|
||||
typedef double machine_double;
|
||||
#undef double
|
||||
|
||||
#ifdef WITH_EXPR_WRAPPER
|
||||
#define WITH_MPFR_DOUBLE
|
||||
#include<ExprWrapper.h>
|
||||
#define double ExprWrapper::ExprWrapper
|
||||
#define double_global ExprWrapper::ExprWrapper
|
||||
#else
|
||||
#define double Mpfr_class
|
||||
#define double_global Mpfr_class_global
|
||||
#endif /* WITH_EXPR_WRAPPER */
|
||||
|
||||
|
||||
#define double_arg const double &
|
||||
|
||||
//This is used to indicate that double gets a different meaning!
|
||||
#define DOUBLE_OVERRIDE
|
||||
|
||||
|
||||
#define TO_MDOUBLE(x) (x).doubleValue()
|
||||
#define REAL_TO_INT(x) (x).intValue()
|
||||
#define REAL_TO_GLINT(x) (x).intValue()
|
||||
#define REAL_TO_FLOAT(x) (x).floatValue()
|
||||
#define TO_REAL(x) double(x)
|
||||
#define STRING_TO_REAL(x) double(x)
|
||||
|
||||
#ifdef EXPR_WRAPPER
|
||||
#define DOUBLE_TO_IOMDOUBLE(x) (x).odoubleValue()
|
||||
#define MDOUBLE_TO_IOMDOUBLE(x) (x).doubleValue()
|
||||
#else
|
||||
#define DOUBLE_TO_IOMDOUBLE(x) (x).doubleValue()
|
||||
#define MDOUBLE_TO_IOMDOUBLE(x) (x)
|
||||
#endif
|
||||
|
||||
//atof
|
||||
#define FP_atof double
|
||||
|
||||
#define SET_PRECISION(var, prec) var.set_precision(prec)
|
||||
#define SET_CORE_MPFR_KERNEL(var, valk1, valk2, name) var = (valk2)
|
||||
#define SET_MPFR_KERNEL_PI(var) var.set_pi()
|
||||
#define SET_CORE_KERNEL(var,val)
|
||||
|
||||
inline void CORE_EXPR_DEBUG1(std::string , const double & ) {}
|
||||
|
||||
inline long intfloor(const double & e) {
|
||||
#ifdef WITH_EXPR_WRAPPER
|
||||
return (int)floor(e);
|
||||
#else
|
||||
return floor(e).intValue();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned long uintceil(const double & e) {
|
||||
#ifdef WITH_EXPR_WRAPPER
|
||||
return (int)floor(e);
|
||||
#else
|
||||
return ceil(e).intValue();
|
||||
#endif
|
||||
}
|
||||
|
||||
//Definitions for functions undefined in CORE
|
||||
#if WITH_EXPR_WRAPPER
|
||||
#define is_nan(x) 0
|
||||
#define sign_bit(x) (x < 0 ? 1 : 0)
|
||||
#endif
|
||||
|
||||
#include <formattedIO.h>
|
||||
|
||||
#else /* no object-based numeric backend */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define TO_MDOUBLE(x) (x)
|
||||
#define DOUBLE_TO_IOMDOUBLE(x) (x)
|
||||
#define MDOUBLE_TO_IOMDOUBLE(x) (x)
|
||||
#define TO_MFLOAT(x) (x)
|
||||
#define REAL_TO_INT(x) (int)(x)
|
||||
#define REAL_TO_GLINT(x) (GLint)(x)
|
||||
#define REAL_TO_FLOAT(x) (float)(x)
|
||||
#define BIGINT_TO_INT(x) (x)
|
||||
#define TO_REAL(x) (x)
|
||||
|
||||
//atof
|
||||
#define FP_atof atof
|
||||
|
||||
#define machine_double double
|
||||
#define double_global double
|
||||
|
||||
#define double_arg double
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline int intfloor(const double e) {
|
||||
return (int)(floor(e));
|
||||
}
|
||||
|
||||
inline unsigned int uintceil(const double e) {
|
||||
return (unsigned)ceil(e);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CORE_EXPR_DEBUG1(x,y)
|
||||
|
||||
#define is_nan(x) isnan(x)
|
||||
#define sign_bit(x) signbit(x)
|
||||
|
||||
#ifdef DOUBLE_OVERRIDE
|
||||
#error "DOUBLE_OVERRIDE should not be defined here!"
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* WITH_COREBACKEND */
|
||||
|
||||
|
||||
/* Definitions that are equal among all numeric object backends */
|
||||
#ifdef DOUBLE_OVERRIDE
|
||||
|
||||
//formattedIO
|
||||
#define FP_printf formattedIO::fmc_printf
|
||||
#define FP_fprintf formattedIO::fmc_fprintf
|
||||
|
||||
inline const double * FP_PRNTARG(const double & x) { return &x; }
|
||||
|
||||
//[sf]scanf methods
|
||||
#define FP_fscanf formattedIO::cfscanf
|
||||
#define FP_sscanf formattedIO::csscanf
|
||||
|
||||
#else /* DOUBLE_OVERRIDE */
|
||||
|
||||
//IO
|
||||
#define FP_printf printf
|
||||
#define FP_fprintf fprintf
|
||||
|
||||
#define FP_PRNTARG(x) (x)
|
||||
|
||||
//[sf]scanf methods
|
||||
#define FP_fscanf fscanf
|
||||
#define FP_sscanf sscanf
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* FPKERNEL_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef FIST_GRAPHICS_H
|
||||
#define FIST_GRAPHICS_H
|
||||
/* */
|
||||
/* colors for OpenGL drawing */
|
||||
/* */
|
||||
#define NumColors 10
|
||||
#define NoColor 0
|
||||
#define Black 0
|
||||
#define Green 1
|
||||
#define ZeroColor 1
|
||||
#define Blue 2
|
||||
#define PntsColor 2
|
||||
#define White 3
|
||||
#define SplitColor 3
|
||||
#define Red 4
|
||||
#define TriColor 4
|
||||
#define BridgeColor 4
|
||||
#define Cyan 5
|
||||
#define ConvexColor 5
|
||||
#define Yellow 6
|
||||
#define PolyColor 6
|
||||
#define IsoPntsColor 6
|
||||
#define Orange 7
|
||||
#define TangentColor 7
|
||||
#define Magenta 8
|
||||
#define EarColor 8
|
||||
#define Gray 9
|
||||
#define TriFillColor 9
|
||||
|
||||
#endif /* FIST_GRAPHICS_H */
|
||||
@@ -0,0 +1,485 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef FIST_GRID_H
|
||||
#define FIST_GRID_H
|
||||
|
||||
boolean InGrid3(griddef *grid, int cell);
|
||||
|
||||
#ifdef EXPR_WRAPPER
|
||||
const ExprMD FUDGE = 1.0e-12;
|
||||
#else
|
||||
#define FUDGE 1.0e-12 /* purely for convenience purposes ;-) */
|
||||
#endif
|
||||
#define BLOCK_SIZE 32768
|
||||
|
||||
#define N_BUCKET CD_1_5
|
||||
#define N_GRID CD_2_5
|
||||
#define N_REFLEX 30
|
||||
|
||||
#define STR(x) #x
|
||||
#define pragma_omp_critical_start(x) \
|
||||
_Pragma( STR( omp critical (x) ) )
|
||||
|
||||
/* */
|
||||
/* computes the bounding box of segments[low,..,high]. */
|
||||
/* */
|
||||
#define BBox_Compute(grid, tmp, low, high, bb) \
|
||||
{ assert(InSegments(grid,low)); \
|
||||
assert(InSegments(grid,high)); \
|
||||
\
|
||||
tmp.seg_addr = &(grid->segments[low]); \
|
||||
BBox_Copy(*tmp.seg_addr, bb); \
|
||||
for (tmp.seg_i = low+1; tmp.seg_i <= high; ++tmp.seg_i) { \
|
||||
seg_addr = &(grid->segments[seg_i]); \
|
||||
BBox_Enlarge(*tmp.seg_addr, bb); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ResetSet(grid, tmp) \
|
||||
{ for (tmp.seg_i = 0; tmp.seg_i < grid->num_set; ++tmp.seg_i) { \
|
||||
grid->segments[grid->set[tmp.seg_i]].checked = false; \
|
||||
} \
|
||||
grid->num_set = 0; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define AddToSet(grid, ind) \
|
||||
{ if (grid->num_set >= grid->max_num_set) { \
|
||||
grid->max_num_set += BLOCK_SIZE; \
|
||||
grid->set = (int*) ReallocateArray(grid->memptr, grid->set, grid->max_num_set, sizeof(int), \
|
||||
"grid:set"); \
|
||||
}\
|
||||
grid->set[grid->num_set] = ind; \
|
||||
grid->segments[ind].checked = true; \
|
||||
++grid->num_set; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define StoreSegment(data, grid, tmp, i1, i2) \
|
||||
{ assert(InPointsList(data, i1)); \
|
||||
assert(InPointsList(data, i2)); \
|
||||
if (grid->num_segments >= grid->max_num_segments) { \
|
||||
grid->max_num_segments += BLOCK_SIZE; \
|
||||
grid->segments = CORE_ReallocateArray(grid->memptr, grid->segments, grid->max_num_segments - BLOCK_SIZE, \
|
||||
grid->max_num_segments, segment, \
|
||||
"grid:segments"); \
|
||||
} \
|
||||
tmp.seg_addr = &(grid->segments[grid->num_segments]); \
|
||||
BBox(data, i1, i2, *tmp.seg_addr); \
|
||||
tmp.seg_addr->checked = false; \
|
||||
++grid->num_segments; \
|
||||
}
|
||||
|
||||
|
||||
#define InsertAfterSeg(grid, k, iseg) \
|
||||
{ assert(InGrid(grid, k)); \
|
||||
assert(InSegments(grid, iseg)); \
|
||||
\
|
||||
if (grid->num_seg_list >= grid->max_num_seg_list) { \
|
||||
grid->max_num_seg_list += BLOCK_SIZE; \
|
||||
grid->seg_list = (segment_node*) ReallocateArray(grid->memptr, grid->seg_list, grid->max_num_seg_list, \
|
||||
sizeof(segment_node), \
|
||||
"grid:seg_list"); \
|
||||
} \
|
||||
grid->seg_list[grid->num_seg_list].seg = iseg; \
|
||||
grid->seg_list[grid->num_seg_list].next = grid->grid[k]; \
|
||||
grid->grid[k] = grid->num_seg_list; \
|
||||
++grid->num_seg_list; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define InsertAfterPnt(list, grid, data, k, ipnt) \
|
||||
{ assert(InGrid2(grid, k)); \
|
||||
assert(InPointsList(data, ipnt)); \
|
||||
\
|
||||
if (grid->num_pnt_list >= grid->max_num_pnt_list) { \
|
||||
grid->max_num_pnt_list += BLOCK_SIZE; \
|
||||
grid->pnt_list = (pnt_node*) ReallocateArray(grid->memptr, grid->pnt_list, grid->max_num_pnt_list, \
|
||||
sizeof(pnt_node), \
|
||||
"grid:pnt_list"); \
|
||||
} \
|
||||
\
|
||||
grid->pnt_list[grid->num_pnt_list].pnt = ipnt; \
|
||||
grid->pnt_list[grid->num_pnt_list].next = grid->grid2[k]; \
|
||||
grid->grid2[k] = grid->num_pnt_list; \
|
||||
++grid->num_pnt_list; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define InsertAfterVtx(list, grid, k, ivtx) \
|
||||
{ assert(InGrid3(grid, k)); \
|
||||
assert(InPolyList(list, ivtx)); \
|
||||
\
|
||||
if (grid->num_vtx_list >= grid->max_num_vtx_list) { \
|
||||
grid->max_num_vtx_list += BLOCK_SIZE; \
|
||||
grid->vtx_list = (pnt_node*) ReallocateArray(grid->memptr, grid->vtx_list, grid->max_num_vtx_list, \
|
||||
sizeof(pnt_node), \
|
||||
"grid:vtx_list"); \
|
||||
} \
|
||||
\
|
||||
grid->vtx_list[grid->num_vtx_list].pnt = ivtx; \
|
||||
grid->vtx_list[grid->num_vtx_list].next = grid->grid3[k]; \
|
||||
grid->grid3[k] = grid->num_vtx_list; \
|
||||
++grid->num_vtx_list; \
|
||||
++grid->num_reflex; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define InsertAfterVtxCells(list, grid, k, ivtx, full_cells) \
|
||||
{ assert(InGrid3(grid,k)); \
|
||||
assert(InPolyList(list,ivtx)); \
|
||||
\
|
||||
if (grid->num_vtx_list >= grid->max_num_vtx_list) { \
|
||||
grid->max_num_vtx_list += BLOCK_SIZE; \
|
||||
grid->vtx_list = (pnt_node*) ReallocateArray(grid->memptr, grid->vtx_list, grid->max_num_vtx_list, \
|
||||
sizeof(pnt_node), \
|
||||
"grid:vtx_list"); \
|
||||
} \
|
||||
\
|
||||
if (grid->grid3[k] == NIL) ++full_cells; \
|
||||
grid->vtx_list[grid->num_vtx_list].pnt = ivtx; \
|
||||
grid->vtx_list[grid->num_vtx_list].next = grid->grid3[k]; \
|
||||
grid->grid3[k] = grid->num_vtx_list; \
|
||||
++grid->num_vtx_list; \
|
||||
++grid->num_reflex; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define DetermineCell(grid, x, y, i, j, ii, jj) \
|
||||
{ \
|
||||
assert(x > grid->grid_min_x); \
|
||||
i = REAL_TO_INT(((x - grid->grid_min_x) / grid->grid_x)); \
|
||||
if (x < grid->raster_x[i]) { \
|
||||
ii = i; \
|
||||
--i; \
|
||||
} \
|
||||
else if (x > grid->raster_x[i+1]) { \
|
||||
ii = i; \
|
||||
++i; \
|
||||
} \
|
||||
else { \
|
||||
if (le(x - grid->raster_x[i], EPS)) ii = i - 1; \
|
||||
else if (le(grid->raster_x[i+1] - x, EPS)) ii = i + 1; \
|
||||
else ii = i; \
|
||||
} \
|
||||
assert((i >= 0) && (i < grid->N_x)); \
|
||||
assert((ii >= 0) && (ii < grid->N_x)); \
|
||||
\
|
||||
assert(y > grid->grid_min_y); \
|
||||
j = REAL_TO_INT(((y - grid->grid_min_y) / grid->grid_y)); \
|
||||
if (y < grid->raster_y[j]) { \
|
||||
jj = j; \
|
||||
--j; \
|
||||
} \
|
||||
else if (y > grid->raster_y[j+1]) { \
|
||||
jj = j; \
|
||||
++j; \
|
||||
} \
|
||||
else { \
|
||||
if (le(y - grid->raster_y[j], EPS)) jj = j - 1; \
|
||||
else if (le(grid->raster_y[j+1] - y, EPS)) jj = j + 1; \
|
||||
else jj = j; \
|
||||
} \
|
||||
assert((j >= 0) && (j < grid->N_y)); \
|
||||
assert((jj >= 0) && (jj < grid->N_y)); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define DetermineCellStrict(grid, x, y, i, j) \
|
||||
{ \
|
||||
assert(x > grid->grid_min_x); \
|
||||
i = REAL_TO_INT(((x - grid->grid_min_x) / grid->grid_x)); \
|
||||
if (x < grid->raster_x[i]) { \
|
||||
--i; \
|
||||
} \
|
||||
else if (x > grid->raster_x[i+1]) { \
|
||||
++i; \
|
||||
} \
|
||||
assert((i >= 0) && (i < grid->N_x)); \
|
||||
\
|
||||
assert(y > grid->grid_min_y); \
|
||||
j = REAL_TO_INT(((y - grid->grid_min_y) / grid->grid_y)); \
|
||||
if (y < grid->raster_y[j]) { \
|
||||
--j; \
|
||||
} \
|
||||
else if (y > grid->raster_y[j+1]) { \
|
||||
++j; \
|
||||
} \
|
||||
assert((j >= 0) && (j < grid->N_y)); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define Convert(grid, i, j, k) \
|
||||
{ k = i * grid->N_y + j; }
|
||||
|
||||
|
||||
|
||||
#define Convert2(grid, i, j, k) \
|
||||
{ k = i * grid->N_y2 + j; }
|
||||
|
||||
|
||||
|
||||
#define Convert3(grid, i, j, k) \
|
||||
{ k = i * grid->N_y3 + j; }
|
||||
|
||||
|
||||
|
||||
#define DetermineCell2(grid, x, y, i, j, ii, jj) \
|
||||
{ \
|
||||
assert(x > grid->grid_min_x2); \
|
||||
i = REAL_TO_INT(((x - grid->grid_min_x2) / grid->grid_x2)); \
|
||||
if (x < grid->raster_x2[i]) { \
|
||||
ii = i; \
|
||||
--i; \
|
||||
} \
|
||||
else if (x > grid->raster_x2[i+1]) { \
|
||||
ii = i; \
|
||||
++i; \
|
||||
} \
|
||||
else { \
|
||||
if (x <= (grid->raster_x2[i] + grid->step_x)) ii = i - 1; \
|
||||
else if (x >= (grid->raster_x2[i+1] - grid->step_x)) ii = i + 1; \
|
||||
else ii = i; \
|
||||
} \
|
||||
assert((i >= 0) && (i < grid->N_x2)); \
|
||||
if (ii < 0) ii = i; \
|
||||
else if (ii >= grid->N_x2) ii = i; \
|
||||
\
|
||||
assert(y > grid->grid_min_y2); \
|
||||
j = REAL_TO_INT(((y - grid->grid_min_y2) / grid->grid_y2)); \
|
||||
if (y < grid->raster_y2[j]) { \
|
||||
jj = j; \
|
||||
--j; \
|
||||
} \
|
||||
else if (y > grid->raster_y2[j+1]) { \
|
||||
jj = j; \
|
||||
++j; \
|
||||
} \
|
||||
else { \
|
||||
if (y <= (grid->raster_y2[j] + grid->step_y)) jj = j - 1; \
|
||||
else if (y >= (grid->raster_y2[j+1] - grid->step_y)) jj = j + 1; \
|
||||
else jj = j; \
|
||||
} \
|
||||
assert((j >= 0) && (j < grid->N_y2)); \
|
||||
if (jj < 0) jj = j; \
|
||||
else if (jj >= grid->N_y2) jj = j; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define DetermineCell3(grid, x, y, i, j, ii, jj) \
|
||||
{ \
|
||||
assert(x > grid->grid_min_x3); \
|
||||
i = REAL_TO_INT((x - grid->grid_min_x3) / grid->grid_x3); \
|
||||
if (x < grid->raster_x3[i]) { \
|
||||
ii = i; \
|
||||
--i; \
|
||||
} \
|
||||
else if (x > grid->raster_x3[i+1]) { \
|
||||
ii = i; \
|
||||
++i; \
|
||||
} \
|
||||
else { \
|
||||
if (le(x - grid->raster_x3[i], EPS)) ii = i - 1; \
|
||||
else if (le(grid->raster_x3[i+1] - x, EPS)) ii = i + 1; \
|
||||
else ii = i; \
|
||||
} \
|
||||
assert((i >= 0) && (i < grid->N_x3)); \
|
||||
if (ii < 0) ii = i; \
|
||||
else if (ii >= grid->N_x3) ii = i; \
|
||||
\
|
||||
assert(y > grid->grid_min_y3); \
|
||||
j = REAL_TO_INT((y - grid->grid_min_y3) / grid->grid_y3); \
|
||||
if (y < grid->raster_y3[j]) { \
|
||||
jj = j; \
|
||||
--j; \
|
||||
} \
|
||||
else if (y > grid->raster_y3[j+1]) { \
|
||||
jj = j; \
|
||||
++j; \
|
||||
} \
|
||||
else { \
|
||||
if (le(y - grid->raster_y3[j], EPS)) jj = j - 1; \
|
||||
else if (le(grid->raster_y3[j+1] - y, EPS)) jj = j + 1; \
|
||||
else jj = j; \
|
||||
} \
|
||||
assert((j >= 0) && (j < grid->N_y3)); \
|
||||
if (jj < 0) jj = j; \
|
||||
else if (jj >= grid->N_y3) jj = j; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define DetermineCell4(grid, x, y, i, j) \
|
||||
{ \
|
||||
assert(x > grid->grid_min_x3); \
|
||||
i = REAL_TO_INT((x - grid->grid_min_x3) / grid->grid_x3); \
|
||||
if (x < grid->raster_x3[i]) { \
|
||||
--i; \
|
||||
} \
|
||||
else if (x > grid->raster_x3[i+1]) { \
|
||||
++i; \
|
||||
} \
|
||||
assert((i >= 0) && (i < grid->N_x3)); \
|
||||
\
|
||||
assert(y > grid->grid_min_y3); \
|
||||
j = REAL_TO_INT((y - grid->grid_min_y3) / grid->grid_y3); \
|
||||
if (y < grid->raster_y3[j]) { \
|
||||
--j; \
|
||||
} \
|
||||
else if (y > grid->raster_y3[j+1]) { \
|
||||
++j; \
|
||||
} \
|
||||
assert((j >= 0) && (j < grid->N_y3)); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define Invert(grid, k, i, j) \
|
||||
{ \
|
||||
i = k / grid->N_y; \
|
||||
assert((0 <= i) && (i < grid->N_x)); \
|
||||
j = k - i * grid->N_y; \
|
||||
assert((0 <= j) && (j < grid->N_y)); \
|
||||
}
|
||||
|
||||
|
||||
#ifdef PARTITION_FIST
|
||||
#define DeleteFromCell(grid, tmp, k, i) \
|
||||
{ \
|
||||
tmp.ind_pnt = grid->grid3[k]; \
|
||||
if(tmp.ind_pnt != NIL) {\
|
||||
assert(InVtxList(grid,tmp.ind_pnt)); \
|
||||
tmp.ind_vtx = grid->vtx_list[tmp.ind_pnt].pnt; \
|
||||
if (tmp.ind_vtx == i) { \
|
||||
pragma_omp_critical_start(DFC) {\
|
||||
grid->grid3[k] = grid->vtx_list[tmp.ind_pnt].next; \
|
||||
--grid->num_reflex; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
tmp.ind_pnt1 = grid->vtx_list[tmp.ind_pnt].next; \
|
||||
while (tmp.ind_pnt1 != NIL) { \
|
||||
assert(InVtxList(grid,tmp.ind_pnt1)); \
|
||||
tmp.ind_vtx = grid->vtx_list[tmp.ind_pnt1].pnt; \
|
||||
if (tmp.ind_vtx == i) { \
|
||||
pragma_omp_critical_start(DFC) {\
|
||||
grid->vtx_list[tmp.ind_pnt].next = grid->vtx_list[tmp.ind_pnt1].next; \
|
||||
--grid->num_reflex; \
|
||||
} \
|
||||
tmp.ind_pnt1 = NIL; \
|
||||
} \
|
||||
else { \
|
||||
tmp.ind_pnt = tmp.ind_pnt1; \
|
||||
tmp.ind_pnt1 = grid->vtx_list[tmp.ind_pnt].next; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define DeleteFromCell(grid, tmp, k, i) \
|
||||
{ \
|
||||
tmp.ind_pnt = grid->grid3[k]; \
|
||||
if(tmp.ind_pnt != NIL) {\
|
||||
assert(InVtxList(grid,tmp.ind_pnt)); \
|
||||
tmp.ind_vtx = grid->vtx_list[tmp.ind_pnt].pnt; \
|
||||
if (tmp.ind_vtx == i) { \
|
||||
grid->grid3[k] = grid->vtx_list[tmp.ind_pnt].next; \
|
||||
--grid->num_reflex; \
|
||||
} \
|
||||
else { \
|
||||
tmp.ind_pnt1 = grid->vtx_list[tmp.ind_pnt].next; \
|
||||
while (tmp.ind_pnt1 != NIL) { \
|
||||
assert(InVtxList(grid,tmp.ind_pnt1)); \
|
||||
tmp.ind_vtx = grid->vtx_list[tmp.ind_pnt1].pnt; \
|
||||
if (tmp.ind_vtx == i) { \
|
||||
grid->vtx_list[tmp.ind_pnt].next = grid->vtx_list[tmp.ind_pnt1].next; \
|
||||
--grid->num_reflex; \
|
||||
tmp.ind_pnt1 = NIL; \
|
||||
} \
|
||||
else { \
|
||||
tmp.ind_pnt = tmp.ind_pnt1; \
|
||||
tmp.ind_pnt1 = grid->vtx_list[tmp.ind_pnt].next; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define Deter2D(u, v, w) \
|
||||
((u).x * ((v).y - (w).y) - (u).y * ((v).x - (w).x))
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef GRAZING
|
||||
#define ScanBridgeBucketCell(list, data, grid, k, i0, i1, ind1, ind_pnt, \
|
||||
distances, num_dist, base, x_start) \
|
||||
{ \
|
||||
ind_pnt = grid->grid3[k]; \
|
||||
while (ind_pnt != NIL) { \
|
||||
assert(InVtxList(grid,ind_pnt)); \
|
||||
ind1 = grid->vtx_list[ind_pnt].pnt; \
|
||||
assert(InPolyList(list, ind1)); \
|
||||
i1 = GetIndex(list, ind1); \
|
||||
if (data->points[i1].x <= x_start) { \
|
||||
PntPntDistSqd(data->points[i0], data->points[i1], base, \
|
||||
distances[*num_dist].dist); \
|
||||
distances[*num_dist].ind = ind1; \
|
||||
++(*num_dist); \
|
||||
} \
|
||||
ind_pnt = grid->vtx_list[ind_pnt].next; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define ScanBridgeBucketCell(list, data, grid, k, i0, i1, ind1, ind_pnt, \
|
||||
distances, num_dist, base) \
|
||||
{ \
|
||||
ind_pnt = grid->grid3[k]; \
|
||||
while (ind_pnt != NIL) { \
|
||||
assert(InVtxList(grid, ind_pnt)); \
|
||||
ind1 = grid->vtx_list[ind_pnt].pnt; \
|
||||
assert(InPolyList(list, ind1)); \
|
||||
i1 = GetIndex(list, ind1); \
|
||||
if (i1 <= i0) { \
|
||||
if (i1 < i0) { \
|
||||
PntPntDistSqd(data->points[i0], data->points[i1], base, distances[*num_dist].dist); \
|
||||
} \
|
||||
else { \
|
||||
distances[*num_dist].dist = CD_0_0; \
|
||||
} \
|
||||
distances[*num_dist].ind = ind1; \
|
||||
++(*num_dist); \
|
||||
} \
|
||||
ind_pnt = grid->vtx_list[ind_pnt].next; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FIST_GRID_H */
|
||||
@@ -0,0 +1,743 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/* compute.cpp: */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void Compute(global_struct *all);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void StatisticsFIST(global_struct *all);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void ResetAll(global_struct *all);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* memory.cpp: */
|
||||
|
||||
void *ReallocateArray(debug_memdef *mem, void *old_ptr, int number, size_t size,
|
||||
const char var_name[]);
|
||||
void FreeMemory(debug_memdef *mem, void **ptr, const char var_name[]);
|
||||
|
||||
void InitDebugMemDefaults(debug_memdef *mem);
|
||||
|
||||
unsigned machine_long ReportMaxNumberBytes(debug_memdef *mem);
|
||||
|
||||
unsigned machine_long ReportCurrNumberBytes(debug_memdef *mem);
|
||||
|
||||
boolean AllMemoryFreed(debug_memdef *mem);
|
||||
|
||||
void FreeMemory(debug_memdef *mem, void **ptr, const char var_name[]);
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
boolean IndexOutOfBounds(debug_memdef *mem, void *array_ptr,
|
||||
char var_name[], size_t size, int index);
|
||||
#endif
|
||||
|
||||
|
||||
/* data.cpp: */
|
||||
|
||||
void InitGlobalStruct(global_struct *all, rt_options *rt_opt,
|
||||
boolean stand_alone);
|
||||
|
||||
void InitDataDefaults(datadef *data);
|
||||
|
||||
void ScaleData(global_struct *all);
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
int StorePnt(datadef *data, double x, double y, eas_type ext_appl);
|
||||
#else
|
||||
int StorePnt(datadef *data, double x, double y);
|
||||
#endif
|
||||
|
||||
void InitPnts(datadef *data, int number);
|
||||
|
||||
void FreePnts(datadef *data);
|
||||
|
||||
void DecrementPoints(datadef *data);
|
||||
|
||||
void SetBoundingBox(datadef *data, point *bb_min, point *bb_max);
|
||||
|
||||
void ComputeBoundingBox(datadef *data, listdef *list, list_ind ind, point *bb_min, point *bb_max);
|
||||
|
||||
boolean InPointsList(datadef *data, int index);
|
||||
|
||||
void InitStoragePnts(datadef *data, int number);
|
||||
|
||||
|
||||
|
||||
/* redraw.cpp: */
|
||||
|
||||
#ifdef GRAPHICS
|
||||
|
||||
void FreeGraphics(void);
|
||||
|
||||
void InitRedrawDefaults(redrawdef *redraw);
|
||||
|
||||
void ResetBufferData(redrawdef *redraw);
|
||||
|
||||
void Redraw(global_struct *all);
|
||||
|
||||
void AddPntToBuffer(redrawdef *redraw, int index, int color);
|
||||
|
||||
void AddEdgeToBuffer(redrawdef *redraw, int index1, int index2, int color);
|
||||
|
||||
void AddTriToBuffer(redrawdef *redraw, int index1, int index2, int index3,
|
||||
int color1, int color2);
|
||||
|
||||
void DecrementPntBuffer(redrawdef *redraw);
|
||||
|
||||
void DecrementEdgeBuffer(redrawdef *redraw);
|
||||
|
||||
void FreeDrawingBuffer(redrawdef *redraw);
|
||||
|
||||
void ResetTriBuffer(redrawdef *redraw);
|
||||
|
||||
void UpdatePntEdgeBuffers(global_struct *all);
|
||||
|
||||
#ifdef PARTITION_FIST
|
||||
void UpdateTriBuffer(global_struct *all);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* graphics.cpp: */
|
||||
|
||||
#ifdef GRAPHICS
|
||||
|
||||
void UpdateScaleData(void);
|
||||
|
||||
void InitializeGraphics(int argc, char *argv[], global_struct *all);
|
||||
|
||||
void ProcessGraphicsEvents(void);
|
||||
|
||||
void DrawTri(point pnt1, point pnt2, point pnt3, int color1, int color);
|
||||
|
||||
void DrawSeg(point pnt1, point pnt2, int color);
|
||||
|
||||
void DrawPnt(point pnt, int color);
|
||||
|
||||
void ResetGraphicsData(void);
|
||||
|
||||
void DrawText(point pnt, int color, char* text);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* io_parse.cpp: */
|
||||
|
||||
boolean ReadOptionalNumber(FILE *input, int *data);
|
||||
|
||||
boolean ReadOptionalCoord(FILE *input, double *xy);
|
||||
|
||||
boolean ReadNumber(FILE *input, int *data);
|
||||
|
||||
boolean ReadVectorData(FILE *input, double *xc, double *yc);
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
boolean ReadPntData(FILE *input, double *xc, double *yc, eas_type *eas_data);
|
||||
#else
|
||||
boolean ReadPntData(FILE *input, double *xc, double *yc);
|
||||
#endif
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
void WritePntData(FILE *output, machine_double xc, machine_double yc,
|
||||
eas_type *eas_data);
|
||||
#else
|
||||
void WritePntData(FILE *output, machine_double xc, machine_double yc);
|
||||
#endif
|
||||
|
||||
void WriteNumber(FILE *output, int number);
|
||||
|
||||
void WriteVectorData(FILE *output, machine_double xc, machine_double yc);
|
||||
|
||||
|
||||
|
||||
/* io_basic.cpp: */
|
||||
|
||||
void InitIOListDefaults(iolistdef* iolist);
|
||||
|
||||
void ResetIOListData(iolistdef* iolist);
|
||||
|
||||
void Read2DInputData(global_struct *all);
|
||||
|
||||
void StartPoly(global_struct *all);
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
void AddPolyVertex(global_struct *all, double xc1, double yc1, eas_type eas_data);
|
||||
#else
|
||||
void AddPolyVertex(global_struct *all, double xc1, double yc1);
|
||||
#endif
|
||||
|
||||
void CloseCurrentPoly(global_struct *all);
|
||||
|
||||
void DXFStartPoly(global_struct *all);
|
||||
|
||||
void DXFAddPolyVertex(global_struct *all, double xc1, double yc1, double bulge);
|
||||
|
||||
void DXFCloseCurrentPoly(global_struct *all, double bulge);
|
||||
|
||||
void EnsureClosedPolygon(global_struct *all);
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
int HandlePnt(global_struct *all,
|
||||
double xc1, double yc1, eas_type ext_appl);
|
||||
|
||||
void HandleSeg(global_struct *all,
|
||||
double xc1, double yc1, double xc2, double yc2,
|
||||
eas_type ext_appl);
|
||||
|
||||
void HandleArc(global_struct *all,
|
||||
double xc1, double yc1, double xc2, double yc2,
|
||||
double xc3, double yc3, int attr, eas_type ext_appl);
|
||||
|
||||
#else
|
||||
int HandlePnt(global_struct *all, double xc1, double yc1);
|
||||
|
||||
void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2);
|
||||
|
||||
void HandleArc(global_struct *all,
|
||||
double xc1, double yc1, double xc2, double yc2,
|
||||
double xc3, double yc3, int attr);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* io_dxf.cpp: */
|
||||
|
||||
void ReadDXFFile(global_struct *all);
|
||||
|
||||
void WriteDXFLWPoly_Vertex(global_struct *all, machine_double xc1, machine_double yc1,
|
||||
machine_double bulge);
|
||||
|
||||
void WriteDXFLWPoly_Start(global_struct *all, boolean closed, int color);
|
||||
|
||||
void WriteDXFPoly_Vertex(global_struct *all, machine_double xc1, machine_double yc1,
|
||||
machine_double bulge);
|
||||
|
||||
void WriteDXFPoly_Start(global_struct *all, boolean closed, int color);
|
||||
|
||||
void WriteDXFArc(global_struct *all,
|
||||
machine_double xc1, machine_double yc1,
|
||||
machine_double xc2, machine_double yc2,
|
||||
machine_double xc3, machine_double yc3,
|
||||
boolean ccw_flag, int color);
|
||||
|
||||
void WriteDXFCircle(global_struct *all,
|
||||
machine_double xc1, machine_double yc1,
|
||||
machine_double radius, int color);
|
||||
|
||||
void WriteDXFPoint(global_struct *all,
|
||||
machine_double xc1, machine_double yc1, int color);
|
||||
|
||||
void WriteDXFLine(global_struct *all,
|
||||
machine_double xc1, machine_double yc1,
|
||||
machine_double xc2, machine_double yc2, int color);
|
||||
|
||||
void StartDXFFile(global_struct *all, char *file_name);
|
||||
|
||||
void FinishDXFFile(global_struct *all);
|
||||
|
||||
void WriteDXFPoly_End(global_struct *all);
|
||||
|
||||
|
||||
|
||||
|
||||
/* io_misc.cpp: */
|
||||
|
||||
void CopyOutputData(vertexdef *vert, int *num_tri, int (*output_tri)[3]);
|
||||
|
||||
void CopyInputData2D(global_struct *all, int num_contours, int *num_vtx, double (*input_vtx)[2]);
|
||||
|
||||
void CopyInputData3D(global_struct *all, int num_contours, int *num_vtx, double (*input_vtx)[3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void Help(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE *OpenFile(const char *file_name, const char *access);
|
||||
|
||||
void FIST_Warning(const char string[]);
|
||||
|
||||
void Copyright(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/* io_2D.cpp: */
|
||||
|
||||
void ReadPolygon(global_struct *all);
|
||||
|
||||
void ReadPoly(global_struct *all);
|
||||
|
||||
void ReadPolyLines(global_struct *all);
|
||||
|
||||
void WritePolygon(global_struct *all, char output_file[]);
|
||||
|
||||
void WriteFacesDXF(global_struct *all, char output_file[]);
|
||||
|
||||
void WritePolyFormat(global_struct *all);
|
||||
|
||||
|
||||
/* io_3D.cpp: */
|
||||
|
||||
void Init3dDefaults(io_3ddef *io3d);
|
||||
|
||||
void WriteGeomOutput(global_struct *all);
|
||||
|
||||
void WriteFaces(global_struct *all, char output_file[]);
|
||||
|
||||
void ReadPolyhedron(global_struct *all, char input_file[]);
|
||||
|
||||
|
||||
|
||||
|
||||
/* arg_eval.cpp: */
|
||||
|
||||
void InitDefaults(rt_options *rt_opt);
|
||||
|
||||
boolean ArgEval(int argc, char *argv[], rt_options *rt_opt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void EvalError(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* list.cpp: */
|
||||
void InitListDefaults(listdef* list);
|
||||
|
||||
void RemoveZeroEdges(listdef* list, list_ind *ind);
|
||||
|
||||
boolean GetBridgeNode(listdef* list, list_ind ind);
|
||||
|
||||
void SetBridgeNodePair(listdef* list, list_ind ind1, list_ind ind2);
|
||||
|
||||
int GetNumList(listdef* list);
|
||||
|
||||
void InitStorageList(listdef* list, int number);
|
||||
|
||||
void InitStorageLoops(listdef* list, int number);
|
||||
|
||||
void StoreChain(listdef* list, list_ind ind);
|
||||
|
||||
list_ind GetNextChain(listdef* list, boolean *done);
|
||||
|
||||
void ResetListData(listdef* list);
|
||||
|
||||
void RotateLinks(listdef* list, list_ind ind1, list_ind ind2);
|
||||
|
||||
void SplitSplice(listdef* list, list_ind ind1, list_ind ind2, list_ind ind3, list_ind ind4);
|
||||
|
||||
int GetOriginal(listdef* list, list_ind ind);
|
||||
|
||||
#ifdef NORMALS
|
||||
void SetTexNormData(listdef* list, list_ind ind, int index1, int index2);
|
||||
|
||||
int GetNormalIndex(listdef* list, list_ind ind);
|
||||
|
||||
int GetTextureIndex(listdef* list, list_ind ind);
|
||||
#endif
|
||||
|
||||
void SetOriginal(listdef* list, list_ind ind, int original);
|
||||
|
||||
void DeleteLinks(listdef* list, list_ind ind);
|
||||
|
||||
void InsertAfter(listdef* list, list_ind ind1, list_ind ind2);
|
||||
|
||||
list_ind MakeNode(listdef* list, int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int MakeLoopHeader(listdef* list);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
list_ind MakeHook(listdef* list);
|
||||
|
||||
void FreeList(listdef* list);
|
||||
|
||||
void DeleteHook(listdef* list, int curr_loop);
|
||||
|
||||
int CountListElements(listdef* list, list_ind ind1);
|
||||
|
||||
void DecrementLoops(listdef* list);
|
||||
|
||||
void UpdateIndex(listdef* list, list_ind ind, int index);
|
||||
|
||||
void SwapLinks(listdef* list, list_ind ind1);
|
||||
|
||||
boolean InPolyList(listdef* list, list_ind ind);
|
||||
|
||||
boolean InLoopList(listdef* list, int loop);
|
||||
|
||||
void ResetPolyList(listdef* list, list_ind ind);
|
||||
|
||||
list_ind GetNode(listdef* list);
|
||||
|
||||
void InitFace(listdef* list, int number);
|
||||
|
||||
void DecrementFaces(listdef* list);
|
||||
|
||||
#ifdef PARTITION_FIST
|
||||
boolean isCorner(global_struct *all, int current_partition, list_ind ind);
|
||||
#endif
|
||||
|
||||
|
||||
/* clean_data.cpp: */
|
||||
void InitCleanDefaults(cleandef *clean);
|
||||
|
||||
void CleanPolygon(global_struct *all, int *removed);
|
||||
|
||||
void CleanPolyhedralFace(global_struct *all, int loop_min, int loop_max, int *removed);
|
||||
|
||||
void FreeUnsorted(cleandef *clean);
|
||||
|
||||
|
||||
|
||||
/* numerics.cpp: */
|
||||
#if defined(WITH_MPFRBACKEND) || defined(WITH_EXPR_WRAPPER)
|
||||
void set_mpfrbackend_prec(mpfr_prec_t mpfr_prec, boolean verbose);
|
||||
#endif
|
||||
|
||||
#ifdef JRC_PREDICATE
|
||||
void exactinit();
|
||||
#endif
|
||||
|
||||
boolean PntInTri(datadef *data, int i1, int i2, int i3, int i4, double *area);
|
||||
|
||||
boolean PntInTriClass(datadef *data, int i1, int i2, int i3, int i4, double *area,
|
||||
int *pnt_on_edge);
|
||||
|
||||
double Angle(point p, point p1, point p2);
|
||||
|
||||
boolean InCone(int i, int j, int k, int l, boolean convex);
|
||||
|
||||
boolean SegIntersect(global_struct *all, int i1, int i2, int i3, int i4, int i5);
|
||||
|
||||
boolean SegIntersection(global_struct *all, int i1, int i2, int i3, int i4, int i5);
|
||||
|
||||
machine_double GetRatio(datadef *data, int i, int j, int k);
|
||||
|
||||
machine_double GetDoubleRatio(datadef *data, int i, int j, int k, int m);
|
||||
|
||||
double det2D(int i, int j, int k);
|
||||
|
||||
int orientation(int i, int j, int k);
|
||||
|
||||
void InitConstants(global_struct *all);
|
||||
|
||||
int SpikeAngle(listdef *list, datadef *data, int i, int j, int k, list_ind ind);
|
||||
|
||||
boolean PointInTriangle(int i1, int i2, int i3, int i4);
|
||||
|
||||
|
||||
/* orientation.cpp: */
|
||||
|
||||
void AdjustOrientation(global_struct *all, int i1, int i2);
|
||||
|
||||
void DetermineOrientation(global_struct *all, list_ind ind);
|
||||
|
||||
double PolygonArea(global_struct *all, list_ind ind);
|
||||
|
||||
void FreeOrientation(global_struct *all);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ear_clip.cpp: */
|
||||
|
||||
void InitEarDefaults(eardef *ear);
|
||||
|
||||
boolean IsEar(global_struct *all, heapdef *hp, list_ind ind2, list_ind *ind1,
|
||||
list_ind *ind3, machine_double *ratio);
|
||||
|
||||
void ClassifyEars(global_struct *all, list_ind ind);
|
||||
|
||||
void ClassifyAngles(global_struct *all, list_ind ind, int *num_reflex);
|
||||
|
||||
boolean ClipEar(global_struct *all, heapdef *hp, boolean *done);
|
||||
|
||||
void SetConvexityStatus(eardef *ear, boolean status);
|
||||
|
||||
void SetTangentNumber(int number);
|
||||
|
||||
void ResetEarStatus(eardef *ear);
|
||||
|
||||
|
||||
|
||||
/* heap.cpp: */
|
||||
|
||||
void InitHeapDefaults(heapdef *hp);
|
||||
|
||||
void FreeHeap(heapdef *hp);
|
||||
|
||||
void DumpOnHeap(heapdef *hp, machine_double ratio, list_ind ind, list_ind prev,
|
||||
list_ind next);
|
||||
|
||||
void InsertIntoHeap(heapdef *hp, machine_double ratio, list_ind ind, list_ind prev,
|
||||
list_ind next);
|
||||
|
||||
boolean DeleteFromHeap(heapdef *hp, list_ind *ind, list_ind *prev, list_ind *next);
|
||||
|
||||
void InitHeap(heapdef *hp, datadef *data);
|
||||
|
||||
#ifdef PARTITION_FIST
|
||||
void InitPartitionedHeap(global_struct *all);
|
||||
#endif
|
||||
|
||||
void MakeHeap(heapdef *hp);
|
||||
|
||||
|
||||
|
||||
/* vertex.cpp: */
|
||||
|
||||
void InitVertexDef(vertexdef* vert);
|
||||
|
||||
boolean InVertexList(vertexdef *vertex, int index);
|
||||
|
||||
void FreeVertices(vertexdef *verte);
|
||||
|
||||
void InitVertices(vertexdef *vert, int number);
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
int StoreVertex(vertexdef *vert, double x, double y, double z, eas_type eas_data);
|
||||
#else
|
||||
int StoreVertex(vertexdef *vert, double x, double y, double z);
|
||||
#endif
|
||||
|
||||
void FreeTriangles(vertexdef *vertex);
|
||||
|
||||
void StoreTriangle(global_struct *all, int i, int j, int k, int color);
|
||||
|
||||
int GetNumTriangles(vertexdef* vert);
|
||||
|
||||
void InitTriangles(vertexdef *vertex, int number);
|
||||
|
||||
void StoreQuad(vertexdef *vertex, int i, int j, int k, int l);
|
||||
|
||||
void FreeQuads(vertexdef *vertex);
|
||||
|
||||
void InitQuads(vertexdef *vertex, int number);
|
||||
|
||||
void FreeGroups(vertexdef *vertex);
|
||||
|
||||
boolean InGroupList(vertexdef *vertex, int index);
|
||||
|
||||
void InitGroupTriangles(vertexdef *vertex);
|
||||
|
||||
void StoreGroupNumber(listdef *list, vertexdef *vertex);
|
||||
|
||||
void StoreGroupData(vertexdef *vertex);
|
||||
|
||||
void StoreConvexLoop(global_struct *all, list_ind ind);
|
||||
|
||||
void FreeConvexLoops(vertexdef *vertex);
|
||||
|
||||
#ifdef NORMALS
|
||||
int StoreV_Normal(vertexdef *vert, double x, double y, double z);
|
||||
|
||||
void InitV_Normals(vertexdef *vert, int number);
|
||||
|
||||
void FreeV_Normals(vertexdef *vertex);
|
||||
|
||||
boolean InV_NormalList(vertexdef *vertex, int index);
|
||||
|
||||
int StoreT_Vertex(vertexdef *vert, double x, double y, double z);
|
||||
|
||||
void InitT_Vertices(vertexdef *vert, int number);
|
||||
|
||||
void FreeT_Vertices(vertexdef *vertex);
|
||||
|
||||
boolean InT_VertexList(vertexdef *vertex, int index);
|
||||
|
||||
void FreeI_Triangles(vertexdef *vertex);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* misc.cpp: */
|
||||
|
||||
void Fake3D(global_struct *all);
|
||||
|
||||
|
||||
|
||||
|
||||
/* desperate.cpp: */
|
||||
|
||||
boolean Desperate(global_struct *all, heapdef *hp, list_ind ind, int i, boolean *splitted);
|
||||
|
||||
boolean LetsHope(global_struct *all, heapdef *hp, list_ind ind);
|
||||
|
||||
void FreeDistances(bridgedef *bridge);
|
||||
|
||||
int WindingNumber(global_struct *all, list_ind ind, point p);
|
||||
|
||||
|
||||
|
||||
|
||||
/* bridge.cpp: */
|
||||
|
||||
void InitBridgeDefaults(bridgedef* bridge);
|
||||
|
||||
void FindLeftMostVertex(listdef* list, list_ind ind, list_ind *left_ind, int *left_i);
|
||||
|
||||
void ConstructBridges(global_struct* all, int i1, int i2);
|
||||
|
||||
boolean FindBridge(global_struct *all, list_ind ind, int i, int start, list_ind *ind1, int *i1);
|
||||
|
||||
void InsertBridge(global_struct *all, list_ind ind1, int i1, list_ind ind3, int i3);
|
||||
|
||||
int d_comp();
|
||||
|
||||
void FreeBridges(bridgedef* bridge);
|
||||
|
||||
|
||||
|
||||
|
||||
/* project.cpp: */
|
||||
|
||||
void ProjectFace(global_struct *all, int loop_min, int loop_max);
|
||||
|
||||
|
||||
|
||||
|
||||
/* triangulate.cpp: */
|
||||
|
||||
void Triangulate(global_struct *all);
|
||||
|
||||
|
||||
|
||||
/* write_ipe.cpp: */
|
||||
|
||||
void WriteIpePolygon(global_struct *all);
|
||||
|
||||
void WriteIpeOutput(global_struct *all);
|
||||
|
||||
|
||||
|
||||
|
||||
/* simple.cpp: */
|
||||
|
||||
boolean SimpleFace(global_struct *all, list_ind ind1, boolean ears_fancy);
|
||||
|
||||
boolean TrivialPolygon(global_struct *all, list_ind ind1);
|
||||
|
||||
|
||||
|
||||
/* elapsed.cpp: */
|
||||
|
||||
machine_double elapsed(global_struct *all);
|
||||
|
||||
|
||||
|
||||
/* grid.cpp: */
|
||||
|
||||
void InitGridDefaults(griddef *grid);
|
||||
|
||||
#ifdef GRAZING
|
||||
void ScanBridgeBuckets(global_struct *all,
|
||||
int i0, int grid_offset, distance *distances,
|
||||
int *num_dist, boolean *grid_exhausted,
|
||||
double x_start);
|
||||
#else
|
||||
void ScanBridgeBuckets(global_struct *all,
|
||||
int i0, int grid_offset, distance *distances,
|
||||
int *num_dist, boolean *grid_exhausted);
|
||||
#endif
|
||||
|
||||
void ResetGrid(griddef *grid);
|
||||
|
||||
void InitBuckets(global_struct *all);
|
||||
|
||||
void InsertPntIntoBridgeBuckets(global_struct *all, list_ind ind1);
|
||||
|
||||
void BuildBridgeBuckets(global_struct *all, list_ind ind0, boolean init_grid);
|
||||
|
||||
boolean GridIntersectionExists(global_struct *all, bounding_box bb,
|
||||
int i1, int i2,list_ind ind5, int i5);
|
||||
|
||||
void InsertSegmentIntoGrid(datadef *data, griddef *grid,
|
||||
bounding_box bb);
|
||||
|
||||
void BuildGrid(global_struct *all, int loop_min, int loop_max);
|
||||
|
||||
void FreeGrid(griddef *grid);
|
||||
|
||||
machine_double TopQualityGrid(global_struct *all, int i1, int i2);
|
||||
|
||||
void BuildPntsGrid(global_struct *all, int loop_ind);
|
||||
|
||||
void BuildBuckets(global_struct *all, list_ind ind);
|
||||
|
||||
boolean BucketIntersectionExists(global_struct *all,
|
||||
int i1, list_ind ind1, int i2, int i3,
|
||||
bounding_box bb, int *i_close,
|
||||
boolean check_close);
|
||||
|
||||
void SetReflexNumber(global_struct *all,int number);
|
||||
|
||||
void DeleteReflexVertex(global_struct *all, list_ind ind);
|
||||
|
||||
|
||||
|
||||
|
||||
/* bottleneck.cpp: */
|
||||
|
||||
boolean CheckBottleNeck(global_struct *all, int i1, int i2, int i3, list_ind ind4);
|
||||
|
||||
|
||||
|
||||
|
||||
/* quads.cpp: */
|
||||
void InitQuadsDefaults(quaddef *quad);
|
||||
|
||||
void DetermineQuads(global_struct *all);
|
||||
|
||||
|
||||
|
||||
/* degenerate.cpp: */
|
||||
|
||||
boolean HandleDegeneracies(global_struct *all, int i1, list_ind ind1, int i2,
|
||||
int i3, int i4,list_ind ind4);
|
||||
|
||||
|
||||
|
||||
/* thin.cpp: */
|
||||
|
||||
void Thin(char output_file[], boolean save_polygon, boolean new_input,
|
||||
int keep_pnts, boolean time, double *cpu_time);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* */
|
||||
/* I'm not sure whether those are indeed the colors used in DXF files. */
|
||||
/* Unfortunately, I do not seem to be able to get my hands on a decent */
|
||||
/* specification of DXF... */
|
||||
/* */
|
||||
#define DXF_NO_COLOR -1
|
||||
#define DXF_RED 1
|
||||
#define DXF_YELLOW 2
|
||||
#define DXF_GREEN 2
|
||||
#define DXF_CYAN 4
|
||||
#define DXF_BLUE 5
|
||||
#define DXF_MAGENTA 6
|
||||
#define DXF_WHITE 7
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DOUBLE_OVERRIDE
|
||||
#define machine_double double
|
||||
#define double_global double
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
FILE *InitIpe(ipe_iodef *ipeio, const char *file_name,
|
||||
machine_double xl, machine_double xr,
|
||||
machine_double yl, machine_double yr);
|
||||
|
||||
void CloseIpeFile(FILE *ipe_file);
|
||||
|
||||
void WriteBeginGroup(FILE *ipe_file);
|
||||
|
||||
void WriteEndGroup(FILE *ipe_file);
|
||||
|
||||
void WriteEnd(FILE *ipe_file);
|
||||
|
||||
void WriteLineBegin(FILE *ipe_file, int dashed, machine_double width,
|
||||
int no_vertices);
|
||||
|
||||
void WriteSegmentBegin(FILE *ipe_file, int dashed, machine_double width,
|
||||
int no_vertices);
|
||||
|
||||
void WriteArcBegin(FILE *ipe_file, int dashed, machine_double width);
|
||||
|
||||
void WriteObjStroke(FILE *ipe_file,
|
||||
machine_double r, machine_double g, machine_double b);
|
||||
|
||||
void WriteObjFill(FILE *ipe_file,
|
||||
machine_double r, machine_double g, machine_double b);
|
||||
|
||||
void WriteArcCCW(ipe_iodef *ipeio, FILE *ipe_file, machine_double xc, machine_double yc,
|
||||
machine_double r,
|
||||
machine_double alpha, machine_double beta);
|
||||
|
||||
void WriteArcCW(ipe_iodef *ipeio, FILE *ipe_file, machine_double xc, machine_double yc,
|
||||
machine_double r,
|
||||
machine_double alpha, machine_double beta);
|
||||
|
||||
void WriteMark(ipe_iodef *ipeio, FILE *ipe_file,
|
||||
machine_double r, machine_double g, machine_double b, int type,
|
||||
machine_double size, machine_double x, machine_double y);
|
||||
|
||||
void WriteLineFirstPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteLineNextPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSegmentFirstPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSegmentNextPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSegmentEndPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSegmentClosePnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSplineBegin(FILE *ipe_file, int dashed, machine_double width, int
|
||||
no_vertices);
|
||||
|
||||
void WriteSplineFirstPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSplineLastPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSplineSecondPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void WriteSplineNextPnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void SetIpeDimensions(ipe_iodef *ipeio,
|
||||
machine_double xmin, machine_double xmax,
|
||||
machine_double ymin, machine_double ymax);
|
||||
|
||||
void SetWorldDimensions(ipe_iodef *ipeio,
|
||||
machine_double xmin, machine_double xmax,
|
||||
machine_double ymin, machine_double ymax);
|
||||
|
||||
void SetScaleFactor(ipe_iodef *ipeio);
|
||||
|
||||
void WritePnt(ipe_iodef *ipeio, FILE *ipe_file, machine_double x, machine_double y);
|
||||
|
||||
void InitIpeDimensions(ipe_iodef *ipeio,
|
||||
machine_double xmin, machine_double ymin,
|
||||
machine_double xmax, machine_double ymax,
|
||||
machine_double ixmin, machine_double iymin,
|
||||
machine_double ixmax, machine_double iymax);
|
||||
|
||||
void WriteLineSegment(ipe_iodef *ipeio, FILE *ipe_file,
|
||||
machine_double r, machine_double g, machine_double b,
|
||||
machine_double width, int dashed,
|
||||
machine_double x1, machine_double y1,
|
||||
machine_double x2, machine_double y2);
|
||||
|
||||
void WriteCircularArc(ipe_iodef *ipeio, FILE *ipe_file,
|
||||
machine_double r, machine_double g, machine_double b,
|
||||
machine_double width, int dashed,
|
||||
machine_double xc, machine_double yc,
|
||||
machine_double x1, machine_double y1,
|
||||
machine_double x2, machine_double y2, boolean ccw);
|
||||
|
||||
void WriteDiscretizedCircularArc(ipe_iodef *ipeio, FILE *ipe_file,
|
||||
machine_double xc, machine_double yc,
|
||||
machine_double x1, machine_double y1,
|
||||
machine_double x2, machine_double y2,
|
||||
boolean ccw, machine_double delta,
|
||||
int *num_segs);
|
||||
@@ -0,0 +1,71 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* */
|
||||
/* obtains the interior angle associated with IND */
|
||||
/* */
|
||||
#define GetAngle(LIST,IND) \
|
||||
(\
|
||||
assert(InPolyList(LIST,IND)), \
|
||||
LIST->list[IND].convex)
|
||||
|
||||
|
||||
#define SetAngle(LIST,IND, ANGLE ) \
|
||||
{\
|
||||
assert(InPolyList(LIST,IND)); \
|
||||
LIST->list[IND].convex = ANGLE ; \
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* obtains the vertex index associated with IND */
|
||||
/* */
|
||||
#define GetIndex(LIST,IND) \
|
||||
(\
|
||||
assert(InPolyList(LIST,IND)), \
|
||||
LIST->list[IND].index)
|
||||
|
||||
|
||||
/* */
|
||||
/* returns pointer to the successor of IND in the circular list of nodes */
|
||||
/* */
|
||||
#define GetNextNode(LIST,IND) \
|
||||
(\
|
||||
assert(InPolyList(LIST,IND)), \
|
||||
LIST->list[IND].next)
|
||||
|
||||
|
||||
/* */
|
||||
/* returns pointer to the predecessor of IND in the circular list of nodes */
|
||||
/* */
|
||||
#define GetPrevNode(LIST,IND) \
|
||||
(\
|
||||
assert(InPolyList(LIST,IND)), \
|
||||
LIST->list[IND].prev)
|
||||
|
||||
|
||||
|
||||
#ifdef STAGES
|
||||
#define SetStage(LIST,IND, S) \
|
||||
{\
|
||||
assert(InPolyList(LIST,IND)); \
|
||||
LIST->list[IND].stage = S; \
|
||||
}
|
||||
|
||||
|
||||
#define GetStage(LIST,IND) \
|
||||
(\
|
||||
assert(InPolyList(LIST,IND)), \
|
||||
LIST->list[IND].stage)
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _MARTIN_H_
|
||||
#define _MARTIN_H_
|
||||
|
||||
#include "mydefs.h"
|
||||
/* */
|
||||
/* defines my boolean data type */
|
||||
/* */
|
||||
#ifdef BOOL_DEFINED
|
||||
typedef bool boolean;
|
||||
#else
|
||||
#define false 0
|
||||
#define true (!false)
|
||||
typedef unsigned char boolean;
|
||||
#endif
|
||||
|
||||
|
||||
/* */
|
||||
/* some useful constants; some of them might be defined in math.h... */
|
||||
/* we initialize them differently depending on whether or not this code is */
|
||||
/* to be used with the NYU's Core Library "CORE". */
|
||||
/* */
|
||||
#ifdef DOUBLE_OVERRIDE
|
||||
|
||||
#ifdef M_PI
|
||||
#undef M_PI
|
||||
#endif
|
||||
#ifdef M_2PI
|
||||
#undef M_2PI
|
||||
#endif
|
||||
#ifdef M_PI_180
|
||||
#undef M_PI_180
|
||||
#endif
|
||||
#if (defined(WITH_COREBACKEND) || defined(WITH_RABACKEND)) && !defined(WITH_MPFRBACKEND)
|
||||
const double M_PI = STRING_TO_REAL("3.14159265358979323846");
|
||||
const double M_2PI = STRING_TO_REAL("6.28318530717958647693");
|
||||
const double M_PI_180 = STRING_TO_REAL("0.01745329251994329576");
|
||||
#else
|
||||
extern double M_PI;
|
||||
extern double M_2PI;
|
||||
extern double M_PI_180;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#ifndef M_2PI
|
||||
#define M_2PI 6.28318530717958647693
|
||||
#endif
|
||||
#ifndef M_PI_180
|
||||
#define M_PI_180 0.01745329251994329576
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* */
|
||||
/* Some constants are used in expressions that need pure machine_double */
|
||||
/* constants. So above constants cannot be used in case */
|
||||
/* defined(WITH_COREBACKEND). The following constants can be used instead: */
|
||||
/* */
|
||||
#ifndef MD_2PI
|
||||
#define MD_2PI 6.28318530717958647693
|
||||
#endif
|
||||
#ifndef MD_PI
|
||||
#define MD_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
|
||||
/* */
|
||||
/* these macros are convenient... */
|
||||
/* */
|
||||
#define Min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define Max(a, b) ((b) < (a) ? (a) : (b))
|
||||
#define Min3(a, b, c) (((a) < (b)) ? \
|
||||
(((a) < (c)) ? \
|
||||
(a) : (c)) \
|
||||
: \
|
||||
(((b) < (c)) ? \
|
||||
(b) : (c)))
|
||||
#define Max3(a, b, c) (((a) < (b)) ? \
|
||||
(((b) < (c)) ? \
|
||||
(c) : (b)) \
|
||||
: \
|
||||
(((a) < (c)) ? \
|
||||
(c) : (a)))
|
||||
#define Min4(a, b, c, d) (((a) < (b)) ? \
|
||||
(((a) < (c)) ? \
|
||||
(((a) < (d)) ?\
|
||||
(a) : (d)) \
|
||||
: \
|
||||
(((c) < (d)) ? \
|
||||
(c) : (d))) \
|
||||
: \
|
||||
(((b) < (c)) ? \
|
||||
(((b) < (d)) ? \
|
||||
(b) : (d)) \
|
||||
: \
|
||||
(((c) < (d)) ? \
|
||||
(c) : (d))))
|
||||
#define Max4(a, b, c, d) (((a) < (b)) ? \
|
||||
(((b) < (c)) ? \
|
||||
(((c) < (d)) ?\
|
||||
(d) : (c)) \
|
||||
: \
|
||||
(((b) < (d)) ? \
|
||||
(d) : (b))) \
|
||||
: \
|
||||
(((a) < (c)) ? \
|
||||
(((c) < (d)) ? \
|
||||
(d) : (c)) \
|
||||
: \
|
||||
(((a) < (d)) ? \
|
||||
(d) : (a))))
|
||||
|
||||
#define Sign(var,x) \
|
||||
(var = x, \
|
||||
((var > 0.0) ? 1 : ((var < 0.0) ? -1 : 0)))
|
||||
#define Abs(x) (((x) >= 0.0) ? (x) : -(x))
|
||||
#define Square(x) ((x) * (x))
|
||||
/* #define xor(a, b) (!(a) ^ !(b)) */
|
||||
#define Odd(x) ((x) % 2 == 1)
|
||||
#define Even(x) (! Odd(x))
|
||||
#define Swap(i1, i2, i) \
|
||||
{i = i1; \
|
||||
i1 = i2; \
|
||||
i2 = i; }
|
||||
#define Ceiling(x) \
|
||||
(((x) == ((double) ((int) (x)))) ? ((int) (x)) : (1 + (int) (x)))
|
||||
|
||||
/* */
|
||||
/* some macros for epsilon-based comparisons with respect to zero... */
|
||||
/* */
|
||||
#define lt(a, eps) ( ((a) < -eps) )
|
||||
#define ge(a, eps) (! ((a) < -eps) )
|
||||
#define le(a, eps) ( ((a) <= eps) )
|
||||
#define gt(a, eps) (! ((a) <= eps) )
|
||||
#define eq(a, eps) ( (((a) <= eps) && !((a) < -eps)) )
|
||||
#define ne(a, eps) ( !((a) <= eps) || ((a) < -eps) )
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
// preprocessor definitions da usare per compilare correttamente
|
||||
|
||||
#define NO_CPUTIME
|
||||
#define BOOL_DEFINED
|
||||
#define RAND
|
||||
#define THRESHOLD
|
||||
#define GRAZING
|
||||
@@ -0,0 +1,490 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#define BaseLength(u, v, base, delta) { \
|
||||
(base).x = (v).x - (u).x; \
|
||||
(base).y = (v).y - (u).y; \
|
||||
delta = Abs(TO_MDOUBLE((base).x)) + Abs(TO_MDOUBLE((base).y)); }
|
||||
|
||||
|
||||
#define SideLength(u, v, base, delta) { \
|
||||
(base).x = (v).x - (u).x; \
|
||||
(base).y = (v).y - (u).y; \
|
||||
delta = (base).x * (base).x + (base).y * (base).y; }
|
||||
|
||||
#define PntPntDist(u, v, base, delta) { \
|
||||
(base).x = (v).x - (u).x; \
|
||||
(base).y = (v).y - (u).y; \
|
||||
delta = sqrt((base).x * (base).x + (base).y * (base).y); }
|
||||
|
||||
#define PntPntDistSqd(u, v, base, delta) { \
|
||||
(base).x = TO_MDOUBLE((v).x) - TO_MDOUBLE((u).x); \
|
||||
(base).y = TO_MDOUBLE((v).y) - TO_MDOUBLE((u).y); \
|
||||
delta = (base).x * (base).x + (base).y * (base).y; }
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether i3, which is collinear with i1, i2, is */
|
||||
/* between i1, i2. note that we rely on the lexicographic sorting of the */
|
||||
/* points! */
|
||||
/* */
|
||||
#define InBetween(i1, i2, i3) \
|
||||
((i1 <= i3) && (i3 <= i2))
|
||||
|
||||
|
||||
#define StrictlyInBetween(i1, i2, i3) \
|
||||
((i1 < i3) && (i3 < i2))
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether i3, which is collinear with i1, i2, is */
|
||||
/* between i1, i2. note that we do _not_ rely on the lexicographic sorting */
|
||||
/* of the points! */
|
||||
/* */
|
||||
#define InBetweenEps(data, i1, i2, i3) \
|
||||
(((Min(data->points[i1].x, data->points[i2].x) - EPS) <= data->points[i3].x) && \
|
||||
((Min(data->points[i1].y, data->points[i2].y) - EPS) <= data->points[i3].y) && \
|
||||
((Max(data->points[i1].x, data->points[i2].x) + EPS) >= data->points[i3].x) && \
|
||||
((Max(data->points[i1].y, data->points[i2].y) + EPS) >= data->points[i3].y))
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro computes the determinant det(points[i],points[j],points[k]) */
|
||||
/* in a consistent way. */
|
||||
/* */
|
||||
#ifdef JRC_PREDICATE
|
||||
double orient2dfast(point pa, point pb, point pc);
|
||||
double orient2d(point pa, point pb, point pc);
|
||||
#define StableDet2D(i, j, k, det) \
|
||||
{ assert(InPointsList(i)); \
|
||||
assert(InPointsList(j)); \
|
||||
assert(InPointsList(k)); \
|
||||
\
|
||||
if ((i == j) || (i == k) || (j == k)) { \
|
||||
det = C_0_0; \
|
||||
} \
|
||||
else { \
|
||||
det = orient2d(points[i], points[j], points[k]); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define StableDet2D(data, tmp, i, j, k, det) \
|
||||
{ assert(InPointsList(data,i)); \
|
||||
assert(InPointsList(data,j)); \
|
||||
assert(InPointsList(data,k)); \
|
||||
\
|
||||
if ((i == j) || (i == k) || (j == k)) { \
|
||||
det = C_0_0; \
|
||||
} \
|
||||
else { \
|
||||
tmp.numerics_h_p = data->points[i]; \
|
||||
tmp.numerics_h_q = data->points[j]; \
|
||||
tmp.numerics_h_r = data->points[k]; \
|
||||
\
|
||||
if (i < j) { \
|
||||
if (j < k) /* i < j < k */ \
|
||||
det = Det2D(tmp.numerics_h_p, tmp.numerics_h_q, tmp.numerics_h_r); \
|
||||
else if (i < k) /* i < k < j */ \
|
||||
det = -Det2D(tmp.numerics_h_p, tmp.numerics_h_r, tmp.numerics_h_q); \
|
||||
else /* k < i < j */ \
|
||||
det = Det2D(tmp.numerics_h_r, tmp.numerics_h_p, tmp.numerics_h_q); \
|
||||
} \
|
||||
else { \
|
||||
if (i < k) /* j < i < k */ \
|
||||
det = -Det2D(tmp.numerics_h_q, tmp.numerics_h_p, tmp.numerics_h_r); \
|
||||
else if (j < k) /* j < k < i */ \
|
||||
det = Det2D(tmp.numerics_h_q, tmp.numerics_h_r, tmp.numerics_h_p); \
|
||||
else /* k < j < i */ \
|
||||
det = -Det2D(tmp.numerics_h_r, tmp.numerics_h_q, tmp.numerics_h_p); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro sets ori to +1 if the points i, j, k are given in CCW order, */
|
||||
/* -1 if the points i, j, k are given in CW order, */
|
||||
/* 0 if the points i, j, k are collinear. */
|
||||
/* */
|
||||
#define Orientation(data, tmp, i, j, k, ori) \
|
||||
{ StableDet2D(data, tmp, i, j, k, tmp.numerics_h_det); \
|
||||
\
|
||||
if (lt(tmp.numerics_h_det, EPS)) ori = -1; \
|
||||
else if (gt(tmp.numerics_h_det, EPS)) ori = 1; \
|
||||
else ori = 0; \
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro sets ori to +1 if the points i, j, k are given in CCW order, */
|
||||
/* -1 if the points i, j, k are given in CW order, */
|
||||
/* 0 if the points i, j, k are collinear. */
|
||||
/* */
|
||||
#define OrientationThres(data, tmp, i, j, k, ori, thres) \
|
||||
{ StableDet2D(data, tmp, i, j, k, tmp.numerics_h_det); \
|
||||
\
|
||||
if (lt(tmp.numerics_h_det, thres)) ori = -1; \
|
||||
else if (gt(tmp.numerics_h_det, thres)) ori = 1; \
|
||||
else ori = 0; \
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether l is in the cone defined by i, j and j, k */
|
||||
/* */
|
||||
#define IsInConeStrict(data, tmp, i, j, k, l, convex, flag, thres) \
|
||||
{ assert(InPointsList(data, i)); \
|
||||
assert(InPointsList(data, j)); \
|
||||
assert(InPointsList(data, k)); \
|
||||
assert(InPointsList(data, l)); \
|
||||
\
|
||||
flag = true; \
|
||||
if (convex) { \
|
||||
if ((l != i) && (i != j)) { \
|
||||
OrientationThres(data, tmp, i, j, l, tmp.numerics_h_ori1, thres); \
|
||||
if (tmp.numerics_h_ori1 <= 0) flag = false; \
|
||||
} \
|
||||
if ((l != k) && (j != k) && (flag == true)) { \
|
||||
OrientationThres(data, tmp, j, k, l, tmp.numerics_h_ori2, thres); \
|
||||
if (tmp.numerics_h_ori2 <= 0) flag = false; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
OrientationThres(data, tmp, i, j, l, tmp.numerics_h_ori1, thres); \
|
||||
if (tmp.numerics_h_ori1 <= 0) { \
|
||||
OrientationThres(data, tmp, j, k, l, tmp.numerics_h_ori2, thres); \
|
||||
if (tmp.numerics_h_ori2 <= 0) flag = false; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether l is in the cone defined by i, j and j, k */
|
||||
/* */
|
||||
#define IsInCone(data, tmp, i, j, k, l, convex, flag) \
|
||||
{ assert(InPointsList(data, i)); \
|
||||
assert(InPointsList(data, j)); \
|
||||
assert(InPointsList(data, k)); \
|
||||
assert(InPointsList(data, l)); \
|
||||
\
|
||||
flag = true; \
|
||||
if (convex) { \
|
||||
if ((l != i) && (i != j)) { \
|
||||
Orientation(data, tmp, i, j, l, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
if (i < j) { \
|
||||
if (!InBetween(i, j, l)) flag = false; \
|
||||
} \
|
||||
else { \
|
||||
if (!InBetween(j, i, l)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if ((l != k) && (j != k) && (flag == true)) { \
|
||||
Orientation(data, tmp, j, k, l, tmp.numerics_h_ori2); \
|
||||
if (tmp.numerics_h_ori2 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori2 == 0) { \
|
||||
if (j < k) { \
|
||||
if (!InBetween(j, k, l)) flag = false; \
|
||||
} \
|
||||
else { \
|
||||
if (!InBetween(k, j, l)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
Orientation(data, tmp, i, j, l, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 <= 0) { \
|
||||
Orientation(data, tmp, j, k, l, tmp.numerics_h_ori2); \
|
||||
if (tmp.numerics_h_ori2 <= 0) { \
|
||||
if (tmp.numerics_h_ori1 == 0) { \
|
||||
if (!InBetween(i, j, l)) flag = false; \
|
||||
} \
|
||||
else if (tmp.numerics_h_ori2 == 0) { \
|
||||
if (!InBetween(j, k, l)) flag = false; \
|
||||
} \
|
||||
else flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether l is in the cone defined by i, j and j, k */
|
||||
/* */
|
||||
#define IsInConeEps(data, tmp, i, j, k, l, convex, flag) \
|
||||
{ assert(InPointsList(data, i)); \
|
||||
assert(InPointsList(data, j)); \
|
||||
assert(InPointsList(data, k)); \
|
||||
assert(InPointsList(data, l)); \
|
||||
\
|
||||
flag = true; \
|
||||
if (convex) { \
|
||||
if ((l != i) && (i != j)) { \
|
||||
Orientation(data, tmp, i, j, l, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
if (!InBetweenEps(data, i, j, l)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
if ((l != k) && (j != k) && (flag == true)) { \
|
||||
Orientation(data, tmp, j, k, l, tmp.numerics_h_ori2); \
|
||||
if (tmp.numerics_h_ori2 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori2 == 0) { \
|
||||
if (!InBetweenEps(data, j, k, l)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
Orientation(data, tmp, i, j, l, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 <= 0) { \
|
||||
Orientation(data, tmp, j, k, l, tmp.numerics_h_ori2); \
|
||||
if (tmp.numerics_h_ori2 <= 0) { \
|
||||
if (tmp.numerics_h_ori1 == 0) { \
|
||||
if (!InBetweenEps(data, i, j, l)) flag = false; \
|
||||
} \
|
||||
else if (tmp.numerics_h_ori2 == 0) { \
|
||||
if (!InBetweenEps(data, j, k, l)) flag = false; \
|
||||
} \
|
||||
else flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether the diagonal j, l is in the cone defined by */
|
||||
/* i, j and j, k. if left then j, k, l forms the ear to be tested. */
|
||||
/* otherwise, i, j, k forms the ear to be tested. */
|
||||
/* */
|
||||
#define DiagIsInConeEps(data, tmp, i, j, k, l, convex, left, flag) \
|
||||
{ assert(InPointsList(data, i)); \
|
||||
assert(InPointsList(data, j)); \
|
||||
assert(InPointsList(data, k)); \
|
||||
assert(InPointsList(data, l)); \
|
||||
\
|
||||
flag = true; \
|
||||
if (convex) { \
|
||||
if (left) { \
|
||||
if ((l != i) && (i != j)) { \
|
||||
Orientation(data, tmp, i, j, l, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
if (InBetweenEps(data, j, l, i)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
if ((l != k) && (j != k)) { \
|
||||
Orientation(data, tmp, j, k, l, tmp.numerics_h_ori2); \
|
||||
if (tmp.numerics_h_ori2 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori2 == 0) { \
|
||||
if (InBetweenEps(data, j, l, k)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define DiagIsInCone(data, tmp, i, j, k, l, convex, left, flag) \
|
||||
{ assert(InPointsList(data, i)); \
|
||||
assert(InPointsList(data, j)); \
|
||||
assert(InPointsList(data, k)); \
|
||||
assert(InPointsList(data, l)); \
|
||||
\
|
||||
flag = true; \
|
||||
if (convex) { \
|
||||
if (left) { \
|
||||
if ((l != i) && (i != j)) { \
|
||||
Orientation(data, tmp, i, j, l, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
if (InBetween(j, l, i)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
if ((l != k) && (j != k)) { \
|
||||
Orientation(data, tmp, j, k, l, tmp.numerics_h_ori2); \
|
||||
if (tmp.numerics_h_ori2 < 0) flag = false; \
|
||||
else if (tmp.numerics_h_ori2 == 0) { \
|
||||
if (InBetween(j, l, k)) flag = false; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* returns */
|
||||
/* -2 ... if angle is 360 degrees */
|
||||
/* -1 ... if angle between 180 and 360 degrees */
|
||||
/* 0 ... if angle is 180 degrees */
|
||||
/* 1 ... if angle between 0 and 180 degrees */
|
||||
/* 2 ... if angle is 0 degrees */
|
||||
/* 3 ... if angle is about 180 degrees and triangle is very small */
|
||||
/* */
|
||||
inline int IsConvexAngle(listdef *list, datadef *data, int i, int j, int k,
|
||||
list_ind ind) {
|
||||
assert(InPointsList(data, i));
|
||||
assert(InPointsList(data, j));
|
||||
assert(InPointsList(data, k));
|
||||
tmp_data_def tmp;
|
||||
|
||||
if (i == j) {
|
||||
if (j == k) {
|
||||
/* */
|
||||
/* all three vertices are identical. we set the angle to -2. */
|
||||
/* using -2 means to err on the safe side, as all the */
|
||||
/* incarnations of this vertex will be clipped right at the */
|
||||
/* start of the ear-clipping algorithm. thus, eventually there */
|
||||
/* will be no other duplicates at this vertex position, and the */
|
||||
/* regular classification of angles will yield the correct */
|
||||
/* answer for j. */
|
||||
/* */
|
||||
return -2;
|
||||
}
|
||||
else {
|
||||
/* */
|
||||
/* two of the three vertices are identical; we set the angle to */
|
||||
/* to 2 order to enable clipping of j. */
|
||||
/* */
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else if (j == k) {
|
||||
/* */
|
||||
/* two vertices are identical. we could either determine the angle */
|
||||
/* by means of yet another lengthy analysis, or simply set the */
|
||||
/* angle to -1. using -1 means to err on the safe side, as all the */
|
||||
/* incarnations of this vertex will be clipped right at the start */
|
||||
/* of the ear-clipping algorithm. thus, eventually there will be no */
|
||||
/* other duplicates at this vertex position, and the regular */
|
||||
/* classification of angles will yield the correct answer for j. */
|
||||
/* */
|
||||
return -1;
|
||||
} else {
|
||||
StableDet2D(data, tmp, i, j, k, tmp.numerics_h_det);
|
||||
if (gt(tmp.numerics_h_det, EPS)) {
|
||||
return 1;
|
||||
}
|
||||
else if (lt(tmp.numerics_h_det, EPS)) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
/* */
|
||||
/* 0, 180, or 360 degrees. */
|
||||
/* */
|
||||
VectorSub2D(data->points[i], data->points[j], tmp.numerics_h_p);
|
||||
VectorSub2D(data->points[k], data->points[j], tmp.numerics_h_q);
|
||||
tmp.numerics_h_dot = DotProduct2D(tmp.numerics_h_p, tmp.numerics_h_q);
|
||||
if (tmp.numerics_h_dot < C_0_0) {
|
||||
/* */
|
||||
/* 180 degrees. */
|
||||
/* */
|
||||
/*data->numerics_h_dot = sqrt(Length2D(data->numerics_h_p)); */
|
||||
/*data->numerics_h_dot += sqrt(Length2D(data->numerics_h_q)); */
|
||||
if (tmp.numerics_h_det > C_0_0) return 1;
|
||||
else return 0;
|
||||
}
|
||||
else {
|
||||
/* */
|
||||
/* 0 or 360 degrees? this cannot be judged locally, and more */
|
||||
/* work is needed. */
|
||||
/* */
|
||||
return SpikeAngle(list, data, i, j, k, ind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether point i4 is inside of or on the boundary */
|
||||
/* of the triangle i1, i2, i3 */
|
||||
/* */
|
||||
#define PntInTriangle(data, tmp, i1, i2, i3, i4, inside) \
|
||||
{ \
|
||||
inside = false; \
|
||||
Orientation(data, tmp, i2, i3, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 >= 0) { \
|
||||
Orientation(data, tmp, i1, i2, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 >= 0) { \
|
||||
Orientation(data, tmp, i3, i1, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 >= 0) inside = true; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
/* this macro checks whether point i4 is inside of or on the boundary */
|
||||
/* of the triangle i1, i2, i3. it also returns a classification if i4 is */
|
||||
/* on the boundary of the triangle (except for the edge i2, i3). */
|
||||
/* */
|
||||
#define VtxInTriangle(data, tmp, i1, i2, i3, i4, inside, classifier) \
|
||||
{ \
|
||||
inside = false; \
|
||||
Orientation(data, tmp, i2, i3, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 >= 0) { \
|
||||
Orientation(data, tmp, i1, i2, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 > 0) { \
|
||||
Orientation(data, tmp, i3, i1, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 > 0) { \
|
||||
inside = true; \
|
||||
classifier = 0; \
|
||||
} \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
inside = true; \
|
||||
classifier = 1; \
|
||||
} \
|
||||
} \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
Orientation(data, tmp, i3, i1, i4, tmp.numerics_h_ori1); \
|
||||
if (tmp.numerics_h_ori1 > 0) { \
|
||||
inside = true; \
|
||||
classifier = 2; \
|
||||
} \
|
||||
else if (tmp.numerics_h_ori1 == 0) { \
|
||||
inside = true; \
|
||||
classifier = 3; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define ComputeRatio(A, B, C, RATIO) \
|
||||
{ \
|
||||
if (Min(B, C) <= ZERO) { \
|
||||
RATIO = Min(B, C); \
|
||||
} \
|
||||
else { \
|
||||
RATIO = CD_1_0 + (A - B - C) / (CD_2_0 * sqrt(B * C)); \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
void WriteFileMagic(FILE *fp);
|
||||
|
||||
void WriteFileEnd(FILE *outf);
|
||||
|
||||
void WriteObjType(FILE *outf, int num_tri);
|
||||
|
||||
void WriteSgiTri(FILE *fp, float sgi_tri[3][3]);
|
||||
@@ -0,0 +1,29 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* F I S T : Fast, Industrial-Strength Triangulation */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* (C) Martin Held */
|
||||
/* (C) Universitaet Salzburg, Salzburg, Austria */
|
||||
/* */
|
||||
/* This code is not in the public domain. All rights reserved! Please make */
|
||||
/* sure to read the full copyright statement contained in api_functions.cpp. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef EXT_APPL_SITES
|
||||
|
||||
#define SetExtApplVtx(V, X) \
|
||||
{\
|
||||
assert(InVertexList(vert, V)); \
|
||||
vert->vertices[V].ext_appl = X; \
|
||||
}
|
||||
|
||||
|
||||
#define GetExtApplVtx(V) \
|
||||
(\
|
||||
assert(InVertexList(vert, V)), \
|
||||
vert->vertices[V].ext_appl)
|
||||
|
||||
#endif
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user