cbec90699f
- creato il progetto in Visual Studio per compilare come libreria statica - modifiche al codice originale per integrarlo nelle nostre librerie.
482 lines
15 KiB
C++
482 lines
15 KiB
C++
/*****************************************************************************/
|
|
/* */
|
|
/* 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. */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
/* get standard libraries */
|
|
/* */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <float.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
|
|
/* */
|
|
/* get my header files */
|
|
/* */
|
|
#include "fpkernel.h"
|
|
#include "martin.h"
|
|
#include "defs.h"
|
|
#include "list.h"
|
|
#include "basic.h"
|
|
#include "header.h"
|
|
#ifdef GRAPHICS
|
|
#include "graphics.h"
|
|
#endif
|
|
|
|
|
|
/* */
|
|
/* function prototypes of functions provided in this file */
|
|
/* */
|
|
void InitIOListDefaults(iolistdef *iolist);
|
|
void ResetIOListData(iolistdef *iolist);
|
|
void Read2DInputData(global_struct *all);
|
|
void StartPoly(global_struct *all);
|
|
void CloseCurrentPoly(global_struct *all);
|
|
void DXFStartPoly(global_struct *all);
|
|
void DXFCloseCurrentPoly(global_struct *all, double bulge);
|
|
#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 DXFAddPolyVertex(global_struct *all, double xc1, double yc1, double bulge);
|
|
void EnsureClosedPolygon(global_struct *all);
|
|
#ifdef EXT_APPL_SITES
|
|
int HandlePnt(global_struct *all, double xc1, double yc1, eas_type eas_data);
|
|
void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2,
|
|
eas_type eas_data);
|
|
void HandleArc(global_struct *all, double xc1, double yc1, double xc2, double yc2,
|
|
double xc3, double yc3, int attr, eas_type eas_data);
|
|
#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
|
|
|
|
|
|
void InitIOListDefaults(iolistdef *iolist)
|
|
{
|
|
|
|
iolist->new_pnts = 0;
|
|
iolist->first_pnt = NIL;
|
|
iolist->last_pnt = NIL;
|
|
iolist->curr_loop = NIL;
|
|
iolist->last_ind = NIL;
|
|
iolist->poly_vertex_number = NIL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void ResetIOListData(iolistdef *iolist)
|
|
{
|
|
|
|
iolist->new_pnts = 0;
|
|
iolist->first_pnt = NIL;
|
|
iolist->last_pnt = NIL;
|
|
iolist->last_ind = NIL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Read2DInputData(global_struct *all)
|
|
{
|
|
/* */
|
|
/* read 2D data from input file */
|
|
/* */
|
|
if (all->rt_opt.verbose) {
|
|
fprintf(stdout, "\n...reading the input data: ");
|
|
fflush(stdout);
|
|
}
|
|
if (all->rt_opt.read_input) {
|
|
ReadPolygon(all);
|
|
}
|
|
else if (all->rt_opt.read_poly) {
|
|
ReadPoly(all);
|
|
}
|
|
else if (all->rt_opt.read_dxf) {
|
|
ReadDXFFile(all);
|
|
}
|
|
else if (all->rt_opt.read_lines) {
|
|
ReadPolyLines(all);
|
|
}
|
|
else {
|
|
throw WRONG_INPUT_OPTION;
|
|
}
|
|
if (all->rt_opt.verbose) {
|
|
fprintf(stdout, "done!\n");
|
|
fflush(stdout);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void EnsureClosedPolygon(global_struct *all)
|
|
{
|
|
/* */
|
|
/* make sure that all polygons are closed even when my code is used not */
|
|
/* properly. */
|
|
/* */
|
|
if (all->c_iolist.curr_loop != NIL) CloseCurrentPoly(all);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void StartPoly(global_struct *all)
|
|
{
|
|
iolistdef *iolist = &all->c_iolist;
|
|
listdef *list = &all->c_list;
|
|
|
|
/* */
|
|
/* make sure that all polygons are closed even when my code is used not */
|
|
/* properly. */
|
|
/* */
|
|
if ((iolist->curr_loop != NIL)
|
|
&& (iolist->poly_vertex_number >= 1)) CloseCurrentPoly(all);
|
|
|
|
/* */
|
|
/* start a new polygon. */
|
|
/* */
|
|
if (iolist->curr_loop == NIL) iolist->curr_loop = MakeLoopHeader(list);
|
|
|
|
iolist->first_pnt = NIL;
|
|
iolist->last_pnt = NIL;
|
|
iolist->last_ind = NIL;
|
|
iolist->poly_vertex_number = NIL;
|
|
|
|
ExtApplFuncStartPoly;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void CloseCurrentPoly(global_struct *all)
|
|
{
|
|
iolistdef *iolist = &all->c_iolist;
|
|
listdef *list = &all->c_list;
|
|
#ifdef GRAPHICS
|
|
redrawdef *redraw = &all->c_redraw;
|
|
#endif
|
|
|
|
list_ind ind;
|
|
|
|
assert(iolist->curr_loop != NIL);
|
|
|
|
ExtApplFuncClosePoly_1;
|
|
|
|
if (iolist->poly_vertex_number < 1) {
|
|
/* */
|
|
/* polygon with no vertex? let's forget it! */
|
|
/* */
|
|
DecrementLoops(list);
|
|
}
|
|
else {
|
|
#ifdef GRAPHICS
|
|
if (all->rt_opt.graphics)
|
|
AddEdgeToBuffer(redraw, iolist->last_pnt, iolist->first_pnt, PolyColor);
|
|
#endif
|
|
if (iolist->poly_vertex_number == 1) {
|
|
/* */
|
|
/* polygon with only one vertex? we'll add one dummy vertex. */
|
|
/* */
|
|
iolist->last_ind = list->loops[iolist->curr_loop];
|
|
ind = MakeNode(list, iolist->first_pnt);
|
|
InsertAfter(list, iolist->last_ind, ind);
|
|
iolist->last_ind = ind;
|
|
iolist->last_pnt = iolist->first_pnt;
|
|
iolist->poly_vertex_number += 1;
|
|
}
|
|
if (iolist->poly_vertex_number == 2) {
|
|
/* */
|
|
/* polygon with only two vertices? we'll add one dummy vertex. */
|
|
/* */
|
|
ind = GetPrevNode(list, iolist->last_ind);
|
|
//i = GetIndex(list, ind);
|
|
SetAngle(list, ind, -2);
|
|
ind = MakeNode(list, iolist->last_pnt);
|
|
InsertAfter(list, iolist->last_ind, ind);
|
|
iolist->last_ind = ind;
|
|
SetAngle(list, ind, -2);
|
|
}
|
|
DeleteHook(list, iolist->curr_loop);
|
|
}
|
|
|
|
ExtApplFuncClosePoly_2;
|
|
|
|
iolist->curr_loop = NIL;
|
|
iolist->first_pnt = NIL;
|
|
iolist->last_pnt = NIL;
|
|
iolist->last_ind = NIL;
|
|
iolist->poly_vertex_number = NIL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
#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
|
|
{
|
|
iolistdef *iolist = &all->c_iolist;
|
|
listdef *list = &all->c_list;
|
|
datadef *data = &all->c_data;
|
|
#ifdef GRAPHICS
|
|
redrawdef *redraw = &all->c_redraw;
|
|
#endif
|
|
|
|
int j;
|
|
list_ind ind;
|
|
|
|
assert(iolist->curr_loop != NIL);
|
|
|
|
if (iolist->first_pnt == NIL) {
|
|
ExtApplFuncAddPolyVertex_1;
|
|
iolist->poly_vertex_number = 1;
|
|
#ifdef EXT_APPL_SITES
|
|
iolist->first_pnt = StorePnt(data, xc1, yc1, eas_data);
|
|
#else
|
|
iolist->first_pnt = StorePnt(data, xc1, yc1);
|
|
#endif
|
|
iolist->last_pnt = iolist->first_pnt;
|
|
#ifdef GRAPHICS
|
|
if (all->rt_opt.graphics) AddPntToBuffer(redraw, iolist->first_pnt,
|
|
PntsColor);
|
|
#endif
|
|
iolist->last_ind = list->loops[iolist->curr_loop];
|
|
ind = MakeNode(list, iolist->first_pnt);
|
|
InsertAfter(list, iolist->last_ind, ind);
|
|
iolist->last_ind = ind;
|
|
if (xc1 < all->bb_min.x) all->bb_min.x = xc1;
|
|
if (xc1 > all->bb_max.x) all->bb_max.x = xc1;
|
|
if (yc1 < all->bb_min.y) all->bb_min.y = yc1;
|
|
if (yc1 > all->bb_max.y) all->bb_max.y = yc1;
|
|
ExtApplFuncAddPolyVertex_2;
|
|
}
|
|
else {
|
|
ExtApplFuncAddPolyVertex_3;
|
|
iolist->poly_vertex_number += 1;
|
|
#ifdef EXT_APPL_SITES
|
|
j = StorePnt(data, xc1, yc1, eas_data);
|
|
#else
|
|
j = StorePnt(data, xc1, yc1);
|
|
#endif
|
|
#ifdef GRAPHICS
|
|
if (all->rt_opt.graphics) {
|
|
AddPntToBuffer(redraw, j, PntsColor);
|
|
AddEdgeToBuffer(redraw, iolist->last_pnt, j, PolyColor);
|
|
}
|
|
#endif
|
|
iolist->last_pnt = j;
|
|
ind = MakeNode(list, j);
|
|
InsertAfter(list, iolist->last_ind, ind);
|
|
iolist->last_ind = ind;
|
|
if (xc1 < all->bb_min.x) all->bb_min.x = xc1;
|
|
else if (xc1 > all->bb_max.x) all->bb_max.x = xc1;
|
|
if (yc1 < all->bb_min.y) all->bb_min.y = yc1;
|
|
else if (yc1 > all->bb_max.y) all->bb_max.y = yc1;
|
|
ExtApplFuncAddPolyVertex_4;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void DXFAddPolyVertex(global_struct *all, double xc1, double yc1, double bulge)
|
|
{
|
|
if (bulge != C_0_0)
|
|
FIST_Warning("DXFAddPolyVertex() - non-zero bulge ignored!\n");
|
|
|
|
#ifdef EXT_APPL_SITES
|
|
AddPolyVertex(all, xc1, yc1, eas_NIL);
|
|
#else
|
|
AddPolyVertex(all, xc1, yc1);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DXFCloseCurrentPoly(global_struct *all, double bulge)
|
|
{
|
|
if (bulge != C_0_0)
|
|
FIST_Warning("DXFCloseCurrentPoly() - non-zero bulge ignored!\n");
|
|
|
|
CloseCurrentPoly(all);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DXFStartPoly(global_struct *all)
|
|
{
|
|
StartPoly(all);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
#ifdef EXT_APPL_SITES
|
|
int HandlePnt(global_struct *all, double xc1, double yc1, eas_type eas_data)
|
|
#else
|
|
int HandlePnt(global_struct *all, double xc1, double yc1)
|
|
#endif
|
|
{
|
|
/* */
|
|
/* we convert the isolated point into a dummy triangle that consists of */
|
|
/* three zero-length edges. */
|
|
/* */
|
|
StartPoly(all);
|
|
#ifdef EXT_APPL_SITES
|
|
AddPolyVertex(all, xc1, yc1, eas_data);
|
|
#else
|
|
AddPolyVertex(all, xc1, yc1);
|
|
#endif
|
|
CloseCurrentPoly(all);
|
|
|
|
/* */
|
|
/* we don't have/use a return value within FIST, but need it for */
|
|
/* compatibility reasons with other codes of mine. */
|
|
/* */
|
|
return NIL;
|
|
}
|
|
|
|
|
|
|
|
#ifdef EXT_APPL_SITES
|
|
void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2,
|
|
eas_type eas_data)
|
|
#else
|
|
void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2)
|
|
#endif
|
|
{
|
|
/* */
|
|
/* we convert the line segment into a dummy triangle that consists of the */
|
|
/* line segment doubled plus one zero-length edge. */
|
|
/* */
|
|
StartPoly(all);
|
|
#ifdef EXT_APPL_SITES
|
|
AddPolyVertex(all, xc1, yc1, eas_data);
|
|
AddPolyVertex(all, xc2, yc2, eas_data);
|
|
#else
|
|
AddPolyVertex(all, xc1, yc1);
|
|
AddPolyVertex(all, xc2, yc2);
|
|
#endif
|
|
CloseCurrentPoly(all);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
#ifdef EXT_APPL_SITES
|
|
void HandleArc(global_struct *all,
|
|
double xc1, double yc1, double xc2, double yc2,
|
|
double xc3, double yc3, int attr, eas_type eas_data)
|
|
#else
|
|
void HandleArc(global_struct *all,
|
|
double xc1, double yc1, double xc2, double yc2,
|
|
double xc3, double yc3, int attr)
|
|
#endif
|
|
{
|
|
machine_double delta_x, delta_y, radius, angle_s, angle_e;
|
|
machine_double incr, alpha;
|
|
int number;
|
|
|
|
#ifdef EXT_APPL_SITES
|
|
AddPolyVertex(all, xc1, yc1, eas_data);
|
|
#else
|
|
AddPolyVertex(all, xc1, yc1);
|
|
#endif
|
|
|
|
delta_x = TO_MDOUBLE(xc1) - TO_MDOUBLE(xc3);
|
|
delta_y = TO_MDOUBLE(yc1) - TO_MDOUBLE(yc3);
|
|
radius = sqrt(delta_x * delta_x + delta_y * delta_y);
|
|
|
|
delta_x = TO_MDOUBLE(all->bb_max.x) - TO_MDOUBLE(all->bb_min.x);
|
|
delta_y = TO_MDOUBLE(all->bb_max.y) - TO_MDOUBLE(all->bb_min.y);
|
|
incr = MD_2PI * Max(delta_x, delta_y) / (150.0 * radius * sqrt(radius));
|
|
if (incr < (MD_2PI / 100.0)) incr = MD_2PI / 100.0;
|
|
if (incr > (MD_PI / 10.0)) incr = MD_PI / 10.0;
|
|
|
|
if (attr == 1) {
|
|
angle_s = atan2(TO_MDOUBLE(yc1) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc1) - TO_MDOUBLE(xc3));
|
|
angle_e = atan2(TO_MDOUBLE(yc2) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc2) - TO_MDOUBLE(xc3));
|
|
if (angle_s < 0.0) angle_s += MD_2PI;
|
|
if (angle_e < 0.0) angle_e += MD_2PI;
|
|
if (angle_e < angle_s) angle_e += MD_2PI;
|
|
number = (int) ((angle_e - angle_s) / incr);
|
|
++number;
|
|
incr = (angle_e - angle_s) / number;
|
|
angle_e -= incr / 2.0;
|
|
alpha = angle_s + incr;
|
|
|
|
while (alpha < angle_e) {
|
|
xc1 = xc3 + radius * cos(alpha);
|
|
yc1 = yc3 + radius * sin(alpha);
|
|
#ifdef EXT_APPL_SITES
|
|
AddPolyVertex(all, xc1, yc1, eas_data);
|
|
#else
|
|
AddPolyVertex(all, xc1, yc1);
|
|
#endif
|
|
alpha += incr;
|
|
}
|
|
}
|
|
else if (attr == -1) {
|
|
angle_s = atan2(TO_MDOUBLE(yc1) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc1) - TO_MDOUBLE(xc3));
|
|
angle_e = atan2(TO_MDOUBLE(yc2) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc2) - TO_MDOUBLE(xc3));
|
|
if (angle_s < 0.0) angle_s += MD_2PI;
|
|
if (angle_e < 0.0) angle_e += MD_2PI;
|
|
if (angle_s < angle_e) angle_s += MD_2PI;
|
|
number = (int) ((angle_s - angle_e) / incr);
|
|
++number;
|
|
incr = (angle_s - angle_e) / number;
|
|
angle_e += incr / 2.0;
|
|
alpha = angle_s - incr;
|
|
|
|
while (alpha > angle_e) {
|
|
xc1 = xc3 + radius * cos(alpha);
|
|
yc1 = yc3 + radius * sin(alpha);
|
|
#ifdef EXT_APPL_SITES
|
|
AddPolyVertex(all, xc1, yc1, eas_data);
|
|
#else
|
|
AddPolyVertex(all, xc1, yc1);
|
|
#endif
|
|
alpha -= incr;
|
|
}
|
|
}
|
|
else {
|
|
FIST_Warning("HandleArc() - unknown data format!\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|