Files
SaraP cbec90699f FIST 6.8 :
- creato il progetto in Visual Studio per compilare come libreria statica
- modifiche al codice originale per integrarlo nelle nostre librerie.
2025-03-04 16:19:35 +01:00

646 lines
22 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>
/* */
/* get my header files */
/* */
#include "fpkernel.h"
#include "martin.h"
#include "defs.h"
#include "list.h"
#include "basic.h"
#include "header.h"
#include "ipe_io.h"
#include "io_dxf.h"
/* */
/* function prototypes of functions provided in this file */
/* */
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[]);
/* Writes into Triangle's .poly file format or also Qi Meng's GPU-DT format */
/* switched can be using hard-coded ifdefs */
/* ONLY FOR Qi Meng's GPU-DT Code: (needs POLYSTARTINDEX 0) */
#define QiMeng
//#undef QiMeng
#define POLYSTARTINDEX 0
void WritePolyFormat(global_struct *all);
void ReadContour(global_struct *all, FILE *input)
{
int i, number, orientation, attr = 0, last_attr = 0;
double xc0, yc0, xc1, yc1, xc2, yc2;
double start_x, start_y, center_x, center_y;
#ifdef EXT_APPL_SITES
eas_type eas_data;
#endif
xc0 = yc0 = start_x = start_y = center_x = center_y = C_0_0;
/* */
/* get the number of contour elements */
/* */
if (!ReadNumber(input, &number)) throw EOF_ENCOUNTERED;
StartPoly(all);
InitStoragePnts(&all->c_data, number);
InitStorageList(&all->c_list, number+1);
if (number < 0) number = - number;
if (number < 2) {
FIST_Warning("ReadContour() - less than two vertices!\n");
throw INSUFFICENT_INPUT;
}
/* */
/* read the orientation of the contour (we don't trust it, though) */
/* */
if (!ReadOptionalNumber(input, &orientation)) throw EOF_ENCOUNTERED;
for (i = 1; i <= number; ++i) {
/* */
/* read next vertex of polygon */
/* */
if (!ReadOptionalNumber(input, &attr)) throw EOF_ENCOUNTERED;
#ifdef EXT_APPL_SITES
if (!ReadPntData(input, &xc1, &yc1, &eas_data))
#else
if (!ReadPntData(input, &xc1, &yc1))
#endif
throw EOF_ENCOUNTERED;
if (i == 1) {
xc0 = xc1;
yc0 = yc1;
}
if (last_attr != 0) {
#ifdef EXT_APPL_SITES
HandleArc(all, start_x, start_y, xc1, yc1, center_x, center_y,
last_attr, eas_NIL);
#else
HandleArc(all, start_x, start_y, xc1, yc1, center_x, center_y,
last_attr);
#endif
last_attr = 0;
}
if (!ReadOptionalCoord(input, &xc2)) throw EOF_ENCOUNTERED;
if (!ReadOptionalCoord(input, &yc2)) throw EOF_ENCOUNTERED;
if (attr == 0) {
#ifdef EXT_APPL_SITES
AddPolyVertex(all, xc1, yc1, eas_data);
#else
AddPolyVertex(all, xc1, yc1);
#endif
last_attr = 0;
}
else {
last_attr = attr;
start_x = xc1;
start_y = yc1;
center_x = xc2;
center_y = yc2;
}
}
if (last_attr != 0) {
#ifdef EXT_APPL_SITES
HandleArc(all, start_x, start_y, xc0, yc0, center_x, center_y,
last_attr, eas_NIL);
#else
HandleArc(all, start_x, start_y, xc0, yc0, center_x, center_y,
last_attr);
#endif
}
CloseCurrentPoly(all);
return;
}
/* */
/* this function reads a simply-connected or multiply-connected polygon */
/* specified in my .dat format for curvilinear data. if EXT_APPL_SITES is */
/* defined at compile-time, and if the functions for parsing the file are */
/* properly redefined in io_parse.c, then the same routine can be used to */
/* parse .dat data with application-specific data added in the file. */
/* */
void ReadPolygon(global_struct *all)
{
double xc1, yc1, xc2, yc2;
int i, number;
FILE *input;
input = OpenFile(all->rt_opt.input_file, "r");
/* */
/* read enclosing bounding box (we don't trust it, though) */
/* */
if (!ReadOptionalCoord(input, &xc1)) throw EOF_ENCOUNTERED;
if (!ReadOptionalCoord(input, &yc1)) throw EOF_ENCOUNTERED;
if (!ReadOptionalCoord(input, &xc2)) throw EOF_ENCOUNTERED;
if (!ReadOptionalCoord(input, &yc2)) throw EOF_ENCOUNTERED;
all->bb_min.x = all->bb_min.y = fpkernel_DBL_MAX;
all->bb_max.x = all->bb_max.y = - fpkernel_DBL_MAX;
/* */
/* get the number of contours */
/* */
if (!ReadNumber(input, &number)) throw EOF_ENCOUNTERED;
InitStorageLoops(&all->c_list, number);
for (i = 0; i < number; ++i) {
ReadContour(all, input);\
}
fclose(input);
all->new_input = true;
return;
}
/* */
/* this function reads a simply-connected polygon specified in my simplified */
/* format for polygons. similar to ReadPolygon(), if EXT_APPL_SITES is */
/* defined at compile-time, and if the functions for parsing the file are */
/* properly redefined in io_parse.c, then the same routine can be used to */
/* parse .poly data with application-specific data added in the file. */
/* */
void ReadPoly(global_struct *all)
{
double xc1, yc1;
int i, number;
FILE *input;
#ifdef EXT_APPL_SITES
eas_type eas_data;
#endif
input = OpenFile(all->rt_opt.input_file, "r");
all->bb_min.x = all->bb_min.y = fpkernel_DBL_MAX;
all->bb_max.x = all->bb_max.y = - fpkernel_DBL_MAX;
InitStorageLoops(&all->c_list, 1);
StartPoly(all);
/* */
/* get the number of contour elements */
/* */
if (!ReadNumber(input, &number)) throw EOF_ENCOUNTERED;
InitStoragePnts(&all->c_data, number);
InitStorageList(&all->c_list, number+1);
if (number < 3) throw INSUFFICENT_INPUT;
all->new_input = true;
for (i = 1; i <= number; ++i) {
/* */
/* read next vertex of polygon */
/* */
#ifdef EXT_APPL_SITES
if (!ReadPntData(input, &xc1, &yc1, &eas_data))
#else
if (!ReadPntData(input, &xc1, &yc1))
#endif
throw EOF_ENCOUNTERED;
#ifdef EXT_APPL_SITES
AddPolyVertex(all, xc1, yc1, eas_data);
#else
AddPolyVertex(all, xc1, yc1);
#endif
}
CloseCurrentPoly(all);
fclose(input);
return;
}
/* */
/* this function reads several polygons specified in my .lines format for */
/* polygons. note that the .lines format requires the first and last point */
/* of every polygon to be identical! */
/* similar to ReadPolygon(), if EXT_APPL_SITES is defined at compile-time, */
/* and if the functions for parsing the file are properly redefined in */
/* io_parse.c, then the same routine can be used to parse .lines data with */
/* application-specific data added in the file. */
/* */
void ReadPolyLines(global_struct *all)
{
double xc1, yc1, xc0, yc0;
int i, number;
FILE *input;
#ifdef EXT_APPL_SITES
eas_type eas_data;
#endif
input = OpenFile(all->rt_opt.input_file, "r");
all->bb_min.x = all->bb_min.y = fpkernel_DBL_MAX;
all->bb_max.x = all->bb_max.y = - fpkernel_DBL_MAX;
/* */
/* get the number of contour elements for this polygon */
/* */
while (ReadNumber(input, &number)) {
StartPoly(all);
if (number < 4) throw INSUFFICENT_INPUT;
all->new_input = true;
/* */
/* read first vertex of polygon */
/* */
#ifdef EXT_APPL_SITES
if (!ReadPntData(input, &xc0, &yc0, &eas_data))
#else
if (!ReadPntData(input, &xc0, &yc0))
#endif
throw EOF_ENCOUNTERED;
#ifdef EXT_APPL_SITES
AddPolyVertex(all, xc0, yc0, eas_data);
#else
AddPolyVertex(all, xc0, yc0);
#endif
for (i = 2; i < number; ++i) {
/* */
/* read next vertex of polygon */
/* */
#ifdef EXT_APPL_SITES
if (!ReadPntData(input, &xc1, &yc1, &eas_data))
#else
if (!ReadPntData(input, &xc1, &yc1))
#endif
throw EOF_ENCOUNTERED;
#ifdef EXT_APPL_SITES
AddPolyVertex(all, xc1, yc1, eas_data);
#else
AddPolyVertex(all, xc1, yc1);
#endif
}
/* */
/* check whether the first vertex equals the last vertex */
/* */
#ifdef EXT_APPL_SITES
if (!ReadPntData(input, &xc1, &yc1, &eas_data))
#else
if (!ReadPntData(input, &xc1, &yc1))
#endif
throw EOF_ENCOUNTERED;
if ((xc0 != xc1) || (yc0 != yc1)) {
FIST_Warning("ReadPolyLines() - input does not conform to .line standard!\n");
#ifdef EXT_APPL_SITES
AddPolyVertex(all, xc1, yc1, eas_data);
#else
AddPolyVertex(all, xc1, yc1);
#endif
}
CloseCurrentPoly(all);
}
fclose(input);
return;
}
#undef WRITE_MY_POLYGONS
#undef WRITE_MY_POLY_LINES
/* #define WRITE_MY_POLYGONS */
#define WRITE_MY_POLY_LINES
/* */
/* this function writes a simply-connected or multiply-connected polygon */
/* specified in my format for curvilinear data. */
/* */
#ifndef WRITE_MY_POLY_LINES
#ifndef WRITE_MY_POLYGONS
void WritePolygon(global_struct *all, char output_file[])
{
int i;
FILE *output;
void WriteContour(FILE *output, list_ind ind1);
output = OpenFile(output_file, "w");
WriteVectorData(output, all->bb_min.x, all->bb_min.y);
WriteVectorData(output, all->bb_max.x, all->bb_max.y);
WriteNumber(output, list->num_loops);
for (i = 0; i < list->num_loops; ++i) {
WriteContour(all, output, list->loops[i]);
}
fclose(output);
return;
}
#else
void WritePolygon(global_struct *all, char output_file[])
{
int i, j, index, num_ele, ind1;
FILE *output;
double delta_x, delta_y, scale_factor;
double x, y;
char number[5];
char name[1000];
for (j = 0; j < list->num_loops; ++j) {
number[0] = '\0';
sprintf(number, "%05d", j);
name[0] = '\0';
strcat(name, output_file);
strcat(name, number);
strcat(name, ".poly");
output = OpenFile(name, "w");
ind1 = list->loops[j];
num_ele = CountListElements(ind1);
WriteNumber(output, num_ele);
for (i = 0; i < num_ele; ++i) {
ind1 = GetNextNode(list,ind1);
index = GetIndex(list,ind1);
x = data->points[index].x;
y = data->points[index].y;
WriteVectorData(output, TO_MDOUBLE(x), TO_MDOUBLE(y));
}
fclose(output);
}
return;
}
#endif
#else
void WritePolygon(global_struct *all, char output_file[])
{
listdef *list = &all->c_list;
datadef *data = &all->c_data;
int i, j, index, num_ele, ind1;
FILE *output;
double x, y;
if (!data->data_scaled) {
data->shift.x = C_0_0;
data->shift.y = C_0_0;
data->scale_factor = C_1_0;
}
output = OpenFile(output_file, "w");
for (j = 0; j < list->num_loops; ++j) {
ind1 = list->loops[j];
num_ele = CountListElements(list, ind1);
WriteNumber(output, num_ele + 1);
for (i = 0; i < num_ele; ++i) {
ind1 = GetNextNode(list, ind1);
index = GetIndex(list, ind1);
x = UnscaleX(data,data->points[index].x);
y = UnscaleY(data,data->points[index].y);
WriteVectorData(output, TO_MDOUBLE(x), TO_MDOUBLE(y));
}
ind1 = list->loops[j];
ind1 = GetNextNode(list, ind1);
index = GetIndex(list, ind1);
x = UnscaleX(data, data->points[index].x);
y = UnscaleY(data, data->points[index].y);
WriteVectorData(output, TO_MDOUBLE(x), TO_MDOUBLE(y));
}
fclose(output);
return;
}
#endif
/* WritePolyFormat() writes the cleaned contour into triangle's
* .poly format:
* First line: <# of vertices> <dimension (must be 2)>
* <# of attributes> <# of boundary markers (0 or 1)>
* Following lines: <vertex #> <x> <y> [attributes] [boundary marker]
* One line: <# of segments> <# of boundary markers (0 or 1)>
* Following lines: <segment #> <endpoint> <endpoint> [boundary marker]
* One line: <# of holes>
* Following lines: <hole #> <x> <y>
* Optional line: <# of regional attributes and/or area constraints>
* Optional following lines: <region #> <x> <y> <attribute> <maximum area> */
void WritePolyFormat(global_struct *all)
{
listdef *list = &all->c_list;
datadef *data = &all->c_data;
rt_options *rt_opt = &all->rt_opt;
FILE *output;
list_ind ind1, ind_start;
int index, cnt, loop_cnt;
double x, y;
output = OpenFile(rt_opt->c2p_file, "w");
if (output != NULL) {
if (!data->data_scaled) {
data->shift.x = C_0_0;
data->shift.y = C_0_0;
data->scale_factor = C_1_0;
}
loop_cnt = index = cnt = 0;
for (int j = 0; j < list->num_loops; ++j) {
ind1 = list->loops[j];
cnt += CountListElements(list, ind1);
}
/* First line: <# of vertices> <dimension (must be 2)> *
* <# of attributes> <# of boundary markers (0 or 1)> */
#ifdef QiMeng
fprintf(output, "%d\n", cnt);
#else
fprintf(output, "%d 2 1 0\n", cnt);
#endif
/* Following lines: <vertex #> <x> <y> [attributes] [boundary marker] */
loop_cnt = POLYSTARTINDEX;
for (int j = 0; j < list->num_loops; ++j) {
ind_start = ind1 = list->loops[j];
do {
index = GetIndex(list, ind1);
x = UnscaleX(data,data->points[index].x);
y = UnscaleY(data,data->points[index].y);
fprintf(output, "%d ", loop_cnt);
WriteVectorData(output, TO_MDOUBLE(x), TO_MDOUBLE(y));
++loop_cnt;
ind1 = GetNextNode(list, ind1);
} while(ind1 != ind_start);
}
#ifdef QiMeng
fclose(output);
rt_opt->c2p_file[strlen(rt_opt->c2p_file)+1] = rt_opt->c2p_file[strlen(rt_opt->c2p_file)];
rt_opt->c2p_file[strlen(rt_opt->c2p_file)] = 'c';
output = OpenFile(rt_opt->c2p_file, "w");
fprintf(output, "%d\n", cnt);
#else
/* One line: <# of segments> <# of boundary markers (0 or 1)> */
fprintf(output, "%d 0\n", cnt);
#endif
/* Following lines: <segment #> <endpoint> <endpoint> [boundary marker] */
loop_cnt = POLYSTARTINDEX;
for (int j = 0; j < list->num_loops; ++j) {
ind_start = ind1 = list->loops[j];
cnt = loop_cnt;
do {
index = GetIndex(list, ind1);
x = UnscaleX(data,data->points[index].x);
y = UnscaleY(data,data->points[index].y);
if(GetNextNode(list,ind1) != ind_start) {
fprintf(output, "%d %d %d\n", loop_cnt, loop_cnt, loop_cnt+1);
} else {
fprintf(output, "%d %d %d\n", loop_cnt, loop_cnt, cnt);
}
++loop_cnt;
ind1 = GetNextNode(list, ind1);
} while(ind1 != ind_start);
}
#ifdef QiMeng
fprintf(output, "\n");
#else
/* One line: <# of holes> */
fprintf(output, "0\n");
#endif
fclose(output);
} else {
if (rt_opt->verbose) {
fprintf(stdout, "The file %s could not be opened!\n", rt_opt->c2p_file);
fflush(stdout);
}
}
}
void WriteContour(global_struct *all, FILE *output, list_ind ind1)
{
datadef *data = &all->c_data;
listdef *list = &all->c_list;
int i, index, num_ele;
int orientation = 1;
int attr = 0;
double xc2 = 0.0, yc2 = 0.0;
num_ele = CountListElements(list, ind1);
WriteNumber(output, num_ele);
WriteNumber(output, orientation);
for (i = 0; i < num_ele; ++i) {
ind1 = GetNextNode(list,ind1);
index = GetIndex(list,ind1);
WriteNumber(output, attr);
WriteVectorData(output, TO_MDOUBLE(data->points[index].x),
TO_MDOUBLE(data->points[index].y));
#ifdef EXT_APPL_SITES
WritePntData(output, TO_MDOUBLE(xc2), TO_MDOUBLE(yc2),
&data->points[index].ext_appl);
#else
WritePntData(output, TO_MDOUBLE(xc2), TO_MDOUBLE(yc2));
#endif
}
return;
}
void WriteFacesDXF(global_struct *all, char output_file[])
{
vertexdef *vert = &all->c_vertex;
int i;
/* */
/* open output file and write .dxf start-up commands */
/* */
StartDXFFile(all, output_file);
/* */
/* output all triangles */
/* */
for (i = 0; i < vert->num_triangles; ++i) {
#ifdef PARTITION_FIST
if(vert->triangles[i].disabled) continue;
#endif
assert(InVertexList(vert, vert->triangles[i].v1));
assert(InVertexList(vert, vert->triangles[i].v2));
assert(InVertexList(vert, vert->triangles[i].v3));
WriteDXFPoly_Start(all, true, DXF_RED);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->triangles[i].v1].x),
TO_MDOUBLE(vert->vertices[vert->triangles[i].v1].y), 0.0);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->triangles[i].v2].x),
TO_MDOUBLE(vert->vertices[vert->triangles[i].v2].y), 0.0);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->triangles[i].v3].x),
TO_MDOUBLE(vert->vertices[vert->triangles[i].v3].y), 0.0);
WriteDXFPoly_End(all);
}
/* */
/* output all quads (if there are any) */
/* */
for (i = 0; i < vert->num_quads; ++i) {
assert(InVertexList(vert, vert->quads[i].v1));
assert(InVertexList(vert, vert->quads[i].v2));
assert(InVertexList(vert, vert->quads[i].v3));
assert(InVertexList(vert, vert->quads[i].v4));
WriteDXFPoly_Start(all, true, DXF_RED);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->quads[i].v1].x),
TO_MDOUBLE(vert->vertices[vert->quads[i].v1].y), 0.0);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->quads[i].v2].x),
TO_MDOUBLE(vert->vertices[vert->quads[i].v2].y), 0.0);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->quads[i].v3].x),
TO_MDOUBLE(vert->vertices[vert->quads[i].v3].y), 0.0);
WriteDXFPoly_Vertex(all, TO_MDOUBLE(vert->vertices[vert->quads[i].v4].x),
TO_MDOUBLE(vert->vertices[vert->quads[i].v4].y), 0.0);
WriteDXFPoly_End(all);
}
/* */
/* write .dxf end commands */
/* */
FinishDXFFile(all);
return;
}