diff --git a/fist/Include/api_fist.h b/fist/Include/api_fist.h new file mode 100644 index 0000000..eb7d21d --- /dev/null +++ b/fist/Include/api_fist.h @@ -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) ; \ No newline at end of file diff --git a/fist/Include/basic.h b/fist/Include/basic.h new file mode 100644 index 0000000..5ac0c1b --- /dev/null +++ b/fist/Include/basic.h @@ -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 + diff --git a/fist/Include/bv_tree.h b/fist/Include/bv_tree.h new file mode 100644 index 0000000..f77f5b1 --- /dev/null +++ b/fist/Include/bv_tree.h @@ -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))))) + diff --git a/fist/Include/coreatan2.h b/fist/Include/coreatan2.h new file mode 100644 index 0000000..1b552fa --- /dev/null +++ b/fist/Include/coreatan2.h @@ -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; + } +} + diff --git a/fist/Include/data.h b/fist/Include/data.h new file mode 100644 index 0000000..f981d9f --- /dev/null +++ b/fist/Include/data.h @@ -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) diff --git a/fist/Include/defs.h b/fist/Include/defs.h new file mode 100644 index 0000000..3c41205 --- /dev/null +++ b/fist/Include/defs.h @@ -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 + +#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 +#include + +template +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 +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 */ diff --git a/fist/Include/ext_appl_defs.h b/fist/Include/ext_appl_defs.h new file mode 100644 index 0000000..5e7def4 --- /dev/null +++ b/fist/Include/ext_appl_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 */ + diff --git a/fist/Include/fpkernel.h b/fist/Include/fpkernel.h new file mode 100644 index 0000000..c79760d --- /dev/null +++ b/fist/Include/fpkernel.h @@ -0,0 +1,335 @@ +#ifndef FPKERNEL_H +#define FPKERNEL_H + +#include +namespace { + const double fpkernel_DBL_MAX = DBL_MAX; +} + +#ifdef WITH_EXPR_WRAPPER +#define DOUBLE_OVERRIDE +typedef double machine_double; +#include +#include + +#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 +#include + +#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 m; \ + (x).rep()->rekCollectOp(m); \ + for(std::map::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 m; + (x).rep()->rekSequen(m); + for (std::map::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 +#include + +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 + + +typedef double machine_double; +#undef double + +#ifdef WITH_EXPR_WRAPPER +#define WITH_MPFR_DOUBLE +#include +#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 + +#else /* no object-based numeric backend */ + +#include + +#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 */ diff --git a/fist/Include/graphics.h b/fist/Include/graphics.h new file mode 100644 index 0000000..55fddf6 --- /dev/null +++ b/fist/Include/graphics.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 */ diff --git a/fist/Include/grid.h b/fist/Include/grid.h new file mode 100644 index 0000000..7e02c91 --- /dev/null +++ b/fist/Include/grid.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 */ diff --git a/fist/Include/header.h b/fist/Include/header.h new file mode 100644 index 0000000..79a3566 --- /dev/null +++ b/fist/Include/header.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); + diff --git a/fist/Include/io_dxf.h b/fist/Include/io_dxf.h new file mode 100644 index 0000000..2f68e0c --- /dev/null +++ b/fist/Include/io_dxf.h @@ -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 + diff --git a/fist/Include/ipe_io.h b/fist/Include/ipe_io.h new file mode 100644 index 0000000..fe9e767 --- /dev/null +++ b/fist/Include/ipe_io.h @@ -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); diff --git a/fist/Include/list.h b/fist/Include/list.h new file mode 100644 index 0000000..65f4a7e --- /dev/null +++ b/fist/Include/list.h @@ -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 diff --git a/fist/Include/martin.h b/fist/Include/martin.h new file mode 100644 index 0000000..c808246 --- /dev/null +++ b/fist/Include/martin.h @@ -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 diff --git a/fist/Include/mydefs.h b/fist/Include/mydefs.h new file mode 100644 index 0000000..7ca71e1 --- /dev/null +++ b/fist/Include/mydefs.h @@ -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 diff --git a/fist/Include/numerics.h b/fist/Include/numerics.h new file mode 100644 index 0000000..76ac2e5 --- /dev/null +++ b/fist/Include/numerics.h @@ -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)); \ + } \ +} + diff --git a/fist/Include/sgo.h b/fist/Include/sgo.h new file mode 100644 index 0000000..0c1e9cc --- /dev/null +++ b/fist/Include/sgo.h @@ -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]); diff --git a/fist/Include/vertex.h b/fist/Include/vertex.h new file mode 100644 index 0000000..faabce3 --- /dev/null +++ b/fist/Include/vertex.h @@ -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 diff --git a/fist/Lib/fistD32.lib b/fist/Lib/fistD32.lib new file mode 100644 index 0000000..9d9b0c3 Binary files /dev/null and b/fist/Lib/fistD32.lib differ diff --git a/fist/Lib/fistD32.pdb b/fist/Lib/fistD32.pdb new file mode 100644 index 0000000..deb382d Binary files /dev/null and b/fist/Lib/fistD32.pdb differ diff --git a/fist/Lib/fistD64.lib b/fist/Lib/fistD64.lib new file mode 100644 index 0000000..f85859c Binary files /dev/null and b/fist/Lib/fistD64.lib differ diff --git a/fist/Lib/fistR32.lib b/fist/Lib/fistR32.lib new file mode 100644 index 0000000..a32c494 Binary files /dev/null and b/fist/Lib/fistR32.lib differ diff --git a/fist/Lib/fistR64.lib b/fist/Lib/fistR64.lib new file mode 100644 index 0000000..6e1f94c Binary files /dev/null and b/fist/Lib/fistR64.lib differ