Files
SaraP 739088af9f Vroni 7.8 :
- aggiornamento versione.
2025-01-29 16:24:30 +01:00

710 lines
26 KiB
C++

/*****************************************************************************/
/* */
/* Copyright (C) 2003--2025 M. Held */
/* */
/* This code is not in the public domain. All rights reserved! Please make */
/* sure to read the full copyright statement contained in "README.txt" or in */
/* the "main" file of this code, such as "main.cc". */
/* */
/*****************************************************************************/
/* */
/* Written by: Martin Held */
/* */
/* E-Mail: held@cs.sbg.ac.at */
/* Fax Mail: (+43 662) 8044-611 */
/* Voice Mail: (+43 662) 8044-6304 */
/* Snail Mail: Martin Held */
/* FB Informatik */
/* Universitaet Salzburg */
/* A-5020 Salzburg, Austria */
/* */
/*****************************************************************************/
/* */
/* get standard libraries */
/* */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
/* */
/* get my header files */
/* */
#include "vronivector.h"
#include "vroni_object.h"
#include "fpkernel.h"
#include "defs.h"
#include "ext_appl_defs.h"
#include "io_dxf.h"
#define LINE_LENGTH 1024
#define NEWLINE '\n'
#define CARRIAGE '\r'
#define InitBBox \
{\
bb_min.x = bb_min.y = DBL_MAX; \
bb_max.x = bb_max.y = - DBL_MAX; \
}
#define IsSpace(x)\
((x == ' ') || (x == '\t') || (x == '\r') || (x == '\n') || (x == '\f'))
#define SkipUntilDXFCode(input, code, string, dxf_code) \
{ \
do { \
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH)) \
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!"); \
} while (atoi(code) != dxf_code); \
}
#define SkipUntilDXFString(input, code, string, dxf_string) \
{ \
do { \
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH)) \
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!"); \
} while (strcmp(string, dxf_string)); \
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH)) \
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!"); \
}
vr_bool ReadNewLine(FILE *input, char *line, int size, vr_bool read_string)
{
char *s;
int i;
do {
s = fgets(line, size, input);
if (s == (char*)NULL) return false;
i = ((int) strlen(s)) - 1;
while((i >= 0) && IsSpace(s[i])) {
s[i]='\0';
i--;
}
if (i >= 0) {
while (IsSpace(s[0])) ++s;
line = strcpy(line, s);
}
else if (read_string) {
i = 0;
}
} while (i < 0);
if (i < 0) return false;
else return true;
}
vr_bool ReadNewDXFPair(FILE *input, char *code, char *string, int size)
{
if (!ReadNewLine(input, code, size, false)) return false;
if (!ReadNewLine(input, string, size, true)) return false;
return true;
}
/* */
/* This is a >>VERY<< rudimentary interface for reading AutoCAD DXF files. */
/* Note that this interface is not as general as it ought to be. That is, */
/* likely it will cough on lots of DXF files. Currently, it supports POINT, */
/* LINE, ARC, CIRCLE, POLYLINE and LWPOLYLINE entities, including "closed" */
/* flags and bulge factors for the latter two entities. It does not handle */
/* BLOCKs or INSERTs or LAYERs, or any other codes that turn objects on or */
/* off, or that move or resize them. Also, this routine does not care about */
/* z-coordinates, and it does not support binary files. */
/* */
void vroniObject::ReadDXFFile(char input_file[], vr_bool *new_input)
{
FILE *input;
char code[LINE_LENGTH+1];
char string[LINE_LENGTH+1];
int dxf_code, i;
double xc1 = 0.0, yc1 = 0.0, xc2 = 0.0, yc2 = 0.0;
double rad = 0.0, bulge = 0.0, old_bulge = 0.0, s_a = 0.0, e_a = 0.0;
vr_bool xc1_set, yc1_set, xc2_set, yc2_set;
vr_bool rad_set, s_a_set, e_a_set;
vr_bool pnt_read, seg_read, arc_read, cir_read, poly_closed = false;
vr_bool poly_started = false;;
*new_input = false;
isolated_pnts = false;
InitBBox;
input = OpenFileVD(input_file, "r");
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH)) return;
while (strcmp(string, "EOF")) {
if ((!strcmp(string, "POINT")) ||
(!strcmp(string, "LINE")) ||
(!strcmp(string, "CIRCLE")) ||
(!strcmp(string, "ARC"))) {
/* */
/* input point, line segment, circle or circular arc. */
/* */
xc1_set = yc1_set = false;
xc2_set = yc2_set = false;
rad_set = s_a_set = e_a_set = false;
pnt_read = seg_read = arc_read = cir_read = false;
if (!strcmp(string, "POINT")) pnt_read = true;
if (!strcmp(string, "LINE")) seg_read = true;
if (!strcmp(string, "ARC")) arc_read = true;
if (!strcmp(string, "CIRCLE")) cir_read = true;
do {
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
dxf_code = atoi(code);
switch(dxf_code) {
case 10:
xc1 = atof(string);
xc1_set = true;
break;
case 20:
yc1 = atof(string);
yc1_set = true;
break;
case 11:
xc2 = atof(string);
xc2_set = true;
break;
case 21:
yc2 = atof(string);
yc2_set = true;
break;
case 40:
rad = atof(string);
rad_set = true;
break;
case 50:
s_a = atof(string);
s_a_set = true;
break;
case 51:
e_a = atof(string);
e_a_set = true;
break;
default:
break;
}
} while (dxf_code != 0);
if (xc1_set && yc1_set) {
*new_input = true;
if (seg_read && xc2_set && yc2_set) {
#ifdef EXT_APPL_SITES
HandleSeg(xc1, yc1, xc2, yc2, eas_NIL);
#else
HandleSeg(xc1, yc1, xc2, yc2);
#endif
}
else if (arc_read && rad_set && s_a_set && e_a_set){
s_a *= M_PI_180;
e_a *= M_PI_180;
#ifdef EXT_APPL_SITES
HandleArc(xc1 + rad * cos(s_a), yc1 + rad * sin(s_a),
xc1 + rad * cos(e_a), yc1 + rad * sin(e_a),
xc1, yc1, ARC, eas_NIL);
#else
HandleArc(xc1 + rad * cos(s_a), yc1 + rad * sin(s_a),
xc1 + rad * cos(e_a), yc1 + rad * sin(e_a),
xc1, yc1, ARC);
#endif
}
else if (cir_read && rad_set) {
#ifdef EXT_APPL_SITES
HandleArc(xc1 + rad, yc1, xc1 - rad, yc1, xc1, yc1,
ARC, eas_NIL);
HandleArc(xc1 - rad, yc1, xc1 + rad, yc1, xc1, yc1,
ARC, eas_NIL);
#else
HandleArc(xc1 + rad, yc1, xc1 - rad, yc1, xc1, yc1,
ARC);
HandleArc(xc1 - rad, yc1, xc1 + rad, yc1, xc1, yc1,
ARC);
#endif
}
else if (pnt_read) {
#ifdef EXT_APPL_PNTS
(void) HandlePnt(xc1, yc1, eap_NIL);
#else
(void) HandlePnt(xc1, yc1);
#endif
isolated_pnts = true;
}
}
}
else if (!strcmp(string, "LWPOLYLINE")) {
/* */
/* "light-weight" polygonal curve. */
/* */
DXFStartPoly();
xc1_set = false;
yc1_set = false;
bulge = 0.0;
poly_closed = false;
do {
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
dxf_code = atoi(code);
switch(dxf_code) {
case 10:
case 20:
if (dxf_code == 10) {
xc1 = atof(string);
xc1_set = true;
}
else {
yc1 = atof(string);
yc1_set = true;
}
if (xc1_set && yc1_set) {
*new_input = true;
DXFAddPolyVertex(xc1, yc1, bulge);
xc1_set = false;
yc1_set = false;
bulge = 0.0;
}
break;
case 42:
bulge = atof(string);
break;
case 70:
poly_closed = (vr_bool) (1&atoi(string));
break;
default:
break;
}
} while (dxf_code != 0);
if (poly_closed) {
DXFClosePoly(bulge);
bulge = 0.0;
}
}
else if (!strcmp(string, "POLYLINE")) {
/* */
/* polygonal curve. */
/* */
poly_closed = false;
do {
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
dxf_code = atoi(code);
switch(dxf_code) {
case 70:
poly_closed = (vr_bool) (1&atoi(string));
break;
default:
break;
}
} while (dxf_code != 0);
if (strcmp(string, "VERTEX"))
SkipUntilDXFString(input, code, string, "VERTEX");
DXFStartPoly();
poly_started = true;
old_bulge = 0.0;
}
else if (!strcmp(string, "VERTEX")) {
/* */
/* vertex of a polygon. */
/* */
xc1_set = false;
yc1_set = false;
bulge = 0.0;
do {
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
dxf_code = atoi(code);
switch(dxf_code) {
case 10:
xc1 = atof(string);
xc1_set = true;
break;
case 20:
yc1 = atof(string);
yc1_set = true;
break;
case 42:
bulge = atof(string);
break;
default:
break;
}
} while (dxf_code != 0);
if (poly_started && xc1_set && yc1_set) {
*new_input = true;
DXFAddPolyVertex(xc1, yc1, old_bulge);
old_bulge = bulge;
}
xc1_set = false;
yc1_set = false;
}
else if (!strcmp(string, "SEQEND")) {
if (poly_closed) DXFClosePoly(old_bulge);
poly_started = false;
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
}
else if (string[0] == '$') {
/* */
/* some initialization stuff. we don't care about it. */
/* */
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
}
else if (string[0] == '{') {
/* */
/* some application-specific stuff. we don't care about it. */
/* */
i = ((int) strlen(string)) - 1;
if (string[i] != '}') {
SkipUntilDXFString(input, code, string, "}");
}
else {
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
}
}
else if (!strcmp(string, "LAYER")) {
/* */
/* information on a layer. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else if (!strcmp(string, "BLOCK")) {
/* */
/* information on a block. we skip it. */
/* */
SkipUntilDXFString(input, code, string, "ENDBLK");
}
else if (!strcmp(string, "INSERT")) {
/* */
/* information on inserting a block. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else if (!strcmp(string, "SPLINE")) {
/* */
/* information on a spline. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else if (!strcmp(string, "ELLIPSE")) {
/* */
/* information on an ellipse. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else if (!strcmp(string, "TEXT")) {
/* */
/* text. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else if (!strcmp(string, "DIMENSION")) {
/* */
/* dimensons. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else if (!strcmp(string, "HATCH")) {
/* */
/* information on hatching. we skip it. */
/* */
SkipUntilDXFCode(input, code, string, 0);
}
else {
/* */
/* some dxf code that we don't care about. */
/* */
if (!ReadNewDXFPair(input, code, string, LINE_LENGTH))
throw std::runtime_error("VRONI error: ReadDXFFile() - premature end of file!");
}
}
fclose(input);
return;
}
/* */
/* this routines writes the standard start-up DXF lines. */
/* */
void vroniObject::StartDXFFile(FILE *dxf_file)
{
fprintf(dxf_file, " 0\nSECTION\n 2\nHEADER\n" );
fprintf(dxf_file, " 0\nENDSEC\n" );
fprintf(dxf_file, " 0\nSECTION\n 2\nENTITIES\n" );
return;
}
/* */
/* this routines writes the standard finishing DXF lines. */
/* */
void vroniObject::FinishDXFFile(FILE *dxf_file)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nENDSEC\n 0\nEOF\n");
}
return;
}
void vroniObject::WriteDXFEntity(FILE *dxf_file, int color)
{
// write Handle
fprintf(dxf_file, " 5\n%d\n", dxf_handle);
dxf_handle++;
// write subclass marker (AcDbEntity)
fprintf(dxf_file, "100\nAcDbEntity\n");
// write layer name
fprintf(dxf_file, " 8\nVRONI\n");
// write color number
if (color >= 0) fprintf(dxf_file, " 62\n%3d\n", color);
return;
}
/* */
/* output a 2D line segment in DXF format. */
/* */
void vroniObject::WriteDXFLine(FILE *dxf_file, double_arg xc1, double_arg yc1,
double_arg xc2, double_arg yc2, int color)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nLINE\n" );
WriteDXFEntity(dxf_file, color);
fprintf(dxf_file, "100\nAcDbLine\n" );
FP_fprintf(dxf_file, " 10\n%f\n 20\n%f\n 30\n0.0\n", FP_PRNTARG(xc1), FP_PRNTARG(yc1) );
FP_fprintf(dxf_file, " 11\n%f\n 21\n%f\n 31\n0.0\n", FP_PRNTARG(xc2), FP_PRNTARG(yc2) );
}
else {
throw std::runtime_error("VRONI error: WriteDXFLine() - DXF output file not opened properly!");
}
return;
}
/* */
/* output a 2D point in DXF format. */
/* */
void vroniObject::WriteDXFPoint(FILE *dxf_file, double_arg xc1, double_arg yc1,
int color)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nPOINT\n" );
WriteDXFEntity(dxf_file, color);
fprintf(dxf_file, "100\nAcDbPoint\n" );
FP_fprintf(dxf_file, " 10\n%f\n 20\n%f\n 30\n0.0\n", FP_PRNTARG(xc1), FP_PRNTARG(yc1) );
}
else {
throw std::runtime_error("VRONI error: WriteDXFPoint() - DXF output file not opened properly!");
}
return;
}
/* */
/* output a 2D circle in DXF format. */
/* */
void vroniObject::WriteDXFCircle(FILE *dxf_file, double_arg xc1, double_arg yc1,
double_arg radius, int color)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nCIRCLE\n" );
WriteDXFEntity(dxf_file, color);
fprintf(dxf_file, "100\nAcDbCircle\n" );
FP_fprintf(dxf_file, " 10\n%f\n 20\n%f\n 30\n0.0\n", FP_PRNTARG(xc1), FP_PRNTARG(yc1) );
FP_fprintf(dxf_file, " 40\n%f\n", FP_PRNTARG(radius) );
}
else {
throw std::runtime_error("VRONI error: WriteDXFCircle() - DXF output file not properly opened!");
}
return;
}
/* */
/* output a 2D circular arc in DXF format. */
/* */
void vroniObject::WriteDXFArc(FILE *dxf_file, double_arg xc1, double_arg yc1,
double_arg xc2, double_arg yc2,
double_arg xc3, double_arg yc3, vr_bool ccw_flag, int color)
{
double s_a, s_e;
double dx, dy, r;
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nARC\n" );
WriteDXFEntity(dxf_file, color);
fprintf(dxf_file, "100\nAcDbCircle\n" );
FP_fprintf(dxf_file, " 10\n%f\n 20\n%f\n 30\n0.0\n", FP_PRNTARG(xc3), FP_PRNTARG(yc3) );
dx = xc1 - xc3;
dy = yc1 - yc3;
r = sqrt( dx*dx + dy*dy );
FP_fprintf(dxf_file, " 40\n%f\n", FP_PRNTARG(r) );
s_a = atan2( dy, dx );
s_e = atan2( yc2 - yc3, xc2 - xc3 );
if ( s_a < 0.0 ) s_a += 2*M_PI;
if ( s_e < 0.0 ) s_e += 2*M_PI;
s_a *= M_180_PI;
s_e *= M_180_PI;
fprintf(dxf_file, "100\nAcDbArc\n" );
if ( ccw_flag )
FP_fprintf(dxf_file, " 50\n%f\n 51\n%f\n", FP_PRNTARG(s_a), FP_PRNTARG(s_e) );
else
FP_fprintf(dxf_file, " 50\n%f\n 51\n%f\n", FP_PRNTARG(s_e), FP_PRNTARG(s_a) );
}
else {
throw std::runtime_error("VRONI error: WriteDXFArc() - DXF output file not properly opened!");
}
return;
}
/* */
/* output the start code for "LWPOLYLINE" in DXF format. */
/* */
void vroniObject::WriteDXFLWPoly_Start(FILE *dxf_file, vr_bool closed,
int color)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nLWPOLYLINE\n" );
WriteDXFEntity(dxf_file, color);
fprintf(dxf_file, "100\nAcDbPolyline\n" );
if (closed) fprintf(dxf_file, " 70\n 1\n" );
else fprintf(dxf_file, " 70\n 0\n" );
fprintf(dxf_file, " 6\nCONTINUOUS\n");
}
else {
throw std::runtime_error("VRONI error: WriteDXFLWPoly_Start() - DXF output file not properly opened!");
}
return;
}
/* */
/* output the start code for "POLYLINE" in DXF format. */
/* */
void vroniObject::WriteDXFPoly_Start(FILE *dxf_file, vr_bool closed, int color)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nPOLYLINE\n" );
WriteDXFEntity(dxf_file, color );
fprintf(dxf_file, "100\nAcDb2dPolyline\n" );
if (closed) fprintf(dxf_file, " 70\n 1\n" );
else fprintf(dxf_file, " 70\n 0\n" );
fprintf(dxf_file, " 6\nCONTINUOUS\n");
}
else {
throw std::runtime_error("VRONI error: WriteDXFPoly_Start() - DXF output file not properly opened!");
}
return;
}
/* */
/* output the end code for "POLYLINE" in DXF format. */
/* */
void vroniObject::WriteDXFPoly_End(FILE *dxf_file)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nSEQEND\n");
}
else {
throw std::runtime_error("VRONI error: WriteDXFPoly_End() - DXF output file not properly opened!");
}
return;
}
/* */
/* output one vertex of a "LWPOLYLINE" in DXF format. */
/* */
void vroniObject::WriteDXFLWPoly_Vertex(FILE *dxf_file, double_arg xc1, double_arg yc1,
double_arg bulge)
{
if (dxf_file != (FILE*)NULL) {
FP_fprintf(dxf_file, " 10\n%f\n 20\n%f\n 30\n0.0\n", FP_PRNTARG(xc1), FP_PRNTARG(yc1));
if (bulge != 0.0) FP_fprintf(dxf_file, " 42\n%f\n", FP_PRNTARG(bulge));
}
else {
throw std::runtime_error("VRONI error: WriteDXFLWPoly_Vertex() - DXF output file not properly opened!");
}
return;
}
/* */
/* output one vertex of a "POLYLINE" in DXF format. */
/* */
void vroniObject::WriteDXFPoly_Vertex(FILE *dxf_file, double_arg xc1, double_arg yc1,
double_arg bulge)
{
if (dxf_file != (FILE*)NULL) {
fprintf(dxf_file, " 0\nVERTEX\n");
FP_fprintf(dxf_file, " 10\n%f\n 20\n%f\n 30\n0.0\n", FP_PRNTARG(xc1), FP_PRNTARG(yc1));
if (bulge != 0.0) FP_fprintf(dxf_file, " 42\n%f\n", FP_PRNTARG(bulge));
}
else {
throw std::runtime_error("VRONI error: WriteDXFPoly_Vertex() - DXF output file not properly opened!");
}
return;
}