cbec90699f
- creato il progetto in Visual Studio per compilare come libreria statica - modifiche al codice originale per integrarlo nelle nostre librerie.
646 lines
22 KiB
C++
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;
|
|
}
|