#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#if defined(_WIN32) && !defined(__MINGW32__)
#include "config-msvc.h"
#else
#include "config.h"
#endif
#include <spatialite/sqlite.h>
#include <spatialite/debug.h>
#include <spatialite/gaiageo.h>
#include <spatialite/gg_dxf.h>
#include <spatialite.h>
#include "dxf_private.h"
#ifndef OMIT_GEOS
typedef struct dxf_segment
{
int valid;
double ax;
double ay;
double az;
double bx;
double by;
double bz;
} dxfSegment;
typedef dxfSegment *dxfSegmentPtr;
typedef struct dxf_linked_segments
{
int count;
dxfSegmentPtr segments;
} dxfLinkedSegments;
typedef dxfLinkedSegments *dxfLinkedSegmentsPtr;
typedef struct dxf_rings_collection
{
gaiaDxfPolylinePtr first;
gaiaDxfPolylinePtr last;
} dxfRingsCollection;
typedef dxfRingsCollection *dxfRingsCollectionPtr;
static gaiaDxfHatchSegmPtr
alloc_dxf_hatch_segm (double x0, double y0, double x1, double y1)
{
gaiaDxfHatchSegmPtr segm = malloc (sizeof (gaiaDxfHatchSegm));
segm->x0 = x0;
segm->y0 = y0;
segm->x1 = x1;
segm->y1 = y1;
segm->next = NULL;
return segm;
}
static void
destroy_dxf_hatch_segm (gaiaDxfHatchSegmPtr segm)
{
if (segm == NULL)
return;
free (segm);
}
static gaiaDxfBoundaryPathPtr
alloc_dxf_boundary_path ()
{
gaiaDxfBoundaryPathPtr path = malloc (sizeof (gaiaDxfBoundaryPath));
path->first = NULL;
path->last = NULL;
path->next = NULL;
return path;
}
static void
insert_dxf_boundary_segm (gaiaDxfBoundaryPathPtr path, gaiaDxfHatchSegmPtr segm)
{
if (path->first == NULL)
path->first = segm;
if (path->last != NULL)
path->last->next = segm;
path->last = segm;
}
static void
destroy_dxf_boundary_path (gaiaDxfBoundaryPathPtr path)
{
gaiaDxfHatchSegmPtr segm;
gaiaDxfHatchSegmPtr n_segm;
if (path == NULL)
return;
segm = path->first;
while (segm != NULL)
{
n_segm = segm->next;
destroy_dxf_hatch_segm (segm);
segm = n_segm;
}
free (path);
}
static gaiaDxfHatchPtr
alloc_dxf_hatch ()
{
gaiaDxfHatchPtr hatch = malloc (sizeof (gaiaDxfHatch));
hatch->spacing = 0.0;
hatch->angle = 0.0;
hatch->base_x = 0.0;
hatch->base_y = 0.0;
hatch->offset_x = 0.0;
hatch->offset_y = 0.0;
hatch->first = NULL;
hatch->last = NULL;
hatch->boundary = NULL;
hatch->first_out = NULL;
hatch->last_out = NULL;
hatch->next = NULL;
return hatch;
}
static void
insert_dxf_boundary_path (gaiaDxfHatchPtr hatch, gaiaDxfBoundaryPathPtr path)
{
if (hatch->first == NULL)
hatch->first = path;
if (hatch->last != NULL)
hatch->last->next = path;
hatch->last = path;
}
static void
insert_dxf_hatch_out (gaiaDxfHatchPtr hatch, gaiaDxfHatchSegmPtr segm)
{
if (hatch->first_out == NULL)
hatch->first_out = segm;
if (hatch->last_out != NULL)
hatch->last_out->next = segm;
hatch->last_out = segm;
}
static void
destroy_dxf_hatch (gaiaDxfHatchPtr hatch)
{
gaiaDxfBoundaryPathPtr path;
gaiaDxfBoundaryPathPtr n_path;
gaiaDxfHatchSegmPtr out;
gaiaDxfHatchSegmPtr n_out;
if (hatch == NULL)
return;
path = hatch->first;
while (path != NULL)
{
n_path = path->next;
destroy_dxf_boundary_path (path);
path = n_path;
}
if (hatch->boundary != NULL)
gaiaFreeGeomColl (hatch->boundary);
out = hatch->first_out;
while (out != NULL)
{
n_out = out->next;
destroy_dxf_hatch_segm (out);
out = n_out;
}
free (hatch);
}
static int
is_valid_dxf_hatch (gaiaDxfHatchPtr hatch)
{
if (hatch->first == NULL)
return 0;
return 1;
}
static void
apply_vertical_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom,
double spacing, double base_x)
{
double min_x = boundary->MinX;
double max_x = boundary->MaxX;
double min_y = boundary->MinY;
double max_y = boundary->MaxY;
double x;
gaiaLinestringPtr ln;
x = base_x + boundary->MinX;
while (x < max_x)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, x, min_y);
gaiaSetPoint (ln->Coords, 1, x, max_y);
x += spacing;
}
x = base_x + boundary->MinX - spacing;
while (x > min_x)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, x, min_y);
gaiaSetPoint (ln->Coords, 1, x, max_y);
x -= spacing;
}
}
static void
apply_horizontal_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom,
double spacing, double base_y)
{
double min_x = boundary->MinX;
double max_x = boundary->MaxX;
double min_y = boundary->MinY;
double max_y = boundary->MaxY;
double y;
gaiaLinestringPtr ln;
y = base_y + boundary->MinY;
while (y < max_y)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, min_x, y);
gaiaSetPoint (ln->Coords, 1, max_x, y);
y += spacing;
}
y = base_y + boundary->MinY - spacing;
while (y > min_y)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, min_x, y);
gaiaSetPoint (ln->Coords, 1, max_x, y);
y -= spacing;
}
}
static void
apply_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom, double angle,
double spacing, double base_x, double base_y)
{
double min_x = boundary->MinX;
double max_x = boundary->MaxX;
double min_y = boundary->MinY;
double max_y = boundary->MaxY;
double ext_x = max_x - min_x;
double ext_y = max_y - min_y;
double ext = (ext_x > ext_y) ? ext_x : ext_y;
double mnx = (ext * 2.0) * -1.0;
double mxx = ext * 3.0;
double mny = (ext * 2.0) * -1.0;
double mxy = ext * 3.0;
gaiaLinestringPtr ln;
double y;
y = 0.0;
while (y < mxy)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, mnx, y);
gaiaSetPoint (ln->Coords, 1, mxx, y);
y += spacing;
}
y = 0.0 - spacing;
while (y > mny)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, mnx, y);
gaiaSetPoint (ln->Coords, 1, mxx, y);
y -= spacing;
}
gaiaRotateCoords (geom, angle * -1.0);
gaiaShiftCoords (geom, base_x + min_x, base_y + min_y);
}
static void
create_dxf_hatch_lines (const void *p_cache, gaiaDxfHatchPtr hatch, int srid)
{
gaiaDxfBoundaryPathPtr path;
gaiaDxfHatchSegmPtr out;
gaiaDxfHatchSegmPtr n_out;
gaiaGeomCollPtr geom;
gaiaGeomCollPtr result;
gaiaGeomCollPtr clipped;
double angle;
double x0;
double y0;
double x1;
double y1;
gaiaLinestringPtr ln;
if (hatch == NULL)
return;
if (hatch->boundary != NULL)
gaiaFreeGeomColl (hatch->boundary);
out = hatch->first_out;
while (out != NULL)
{
n_out = out->next;
destroy_dxf_hatch_segm (out);
out = n_out;
}
hatch->boundary = NULL;
hatch->first_out = NULL;
hatch->last_out = NULL;
geom = gaiaAllocGeomColl ();
path = hatch->first;
while (path != NULL)
{
out = path->first;
while (out != NULL)
{
ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPoint (ln->Coords, 0, out->x0, out->y0);
gaiaSetPoint (ln->Coords, 1, out->x1, out->y1);
out = out->next;
}
path = path->next;
}
if (p_cache != NULL)
result = gaiaPolygonize_r (p_cache, geom, 0);
else
result = gaiaPolygonize (geom, 0);
gaiaFreeGeomColl (geom);
if (result == NULL)
return;
gaiaMbrGeometry (result);
result->Srid = srid;
result->DeclaredType = GAIA_MULTIPOLYGON;
hatch->boundary = result;
if (hatch->spacing == 0.0)
{
return;
}
angle = hatch->angle;
while (angle >= 360.0)
angle -= 360.0;
while (angle <= -360.0)
angle += 360;
geom = gaiaAllocGeomColl ();
if (angle == 90.0 || angle == -90.0 || angle == 270.0 || angle == -270.0)
apply_vertical_hatch (result, geom, hatch->spacing, hatch->base_x);
else if (angle == 0.0 || angle == 180 || angle == -180)
apply_horizontal_hatch (result, geom, hatch->spacing, hatch->base_y);
else
apply_hatch (result, geom, angle, hatch->spacing, hatch->base_x,
hatch->base_y);
gaiaMbrGeometry (geom);
if (p_cache != NULL)
clipped = gaiaGeometryIntersection_r (p_cache, geom, result);
else
clipped = gaiaGeometryIntersection (geom, result);
gaiaFreeGeomColl (geom);
if (clipped == NULL)
return;
ln = clipped->FirstLinestring;
while (ln != NULL)
{
if (ln->Points == 2)
{
gaiaGetPoint (ln->Coords, 0, &x0, &y0);
gaiaGetPoint (ln->Coords, 1, &x1, &y1);
n_out = alloc_dxf_hatch_segm (x0, y0, x1, y1);
insert_dxf_hatch_out (hatch, n_out);
}
ln = ln->Next;
}
gaiaFreeGeomColl (clipped);
}
static gaiaDxfHolePtr
alloc_dxf_hole (int points)
{
int i;
gaiaDxfHolePtr hole = malloc (sizeof (gaiaDxfHole));
hole->points = points;
hole->x = malloc (sizeof (double) * points);
hole->y = malloc (sizeof (double) * points);
hole->z = malloc (sizeof (double) * points);
for (i = 0; i < points; i++)
{
*(hole->x + i) = 0.0;
*(hole->y + i) = 0.0;
*(hole->z + i) = 0.0;
}
hole->next = NULL;
return hole;
}
static void
insert_dxf_hole (gaiaDxfPolylinePtr line, gaiaDxfHolePtr hole)
{
if (line->first_hole == NULL)
line->first_hole = hole;
if (line->last_hole != NULL)
line->last_hole->next = hole;
line->last_hole = hole;
}
static void
destroy_dxf_hole (gaiaDxfHolePtr hole)
{
if (hole == NULL)
return;
if (hole->x != NULL)
free (hole->x);
if (hole->y != NULL)
free (hole->y);
if (hole->z != NULL)
free (hole->z);
free (hole);
}
static int
force_closure (gaiaDxfPolylinePtr line)
{
if (check_unclosed_polyg (line, 1))
{
double *ptr_x;
double *ptr_y;
double *ptr_z;
ptr_x = realloc (line->x, sizeof (double) * (line->points + 1));
ptr_y = realloc (line->y, sizeof (double) * (line->points + 1));
ptr_z = realloc (line->z, sizeof (double) * (line->points + 1));
if (ptr_x == NULL || ptr_y == NULL || ptr_z == NULL)
{
if (ptr_x == NULL)
free (ptr_x);
if (ptr_y == NULL)
free (ptr_y);
if (ptr_z == NULL)
free (ptr_z);
return 0;
}
line->x = ptr_x;
line->y = ptr_y;
line->z = ptr_z;
*(line->x + line->points) = *(line->x + 0);
*(line->y + line->points) = *(line->y + 0);
*(line->z + line->points) = *(line->z + 0);
line->points += 1;
}
return 1;
}
static void
linked_rings (const void *p_cache, gaiaDxfPolylinePtr line)
{
int i;
int i2;
int match = 0;
double x;
double y;
double z;
gaiaDxfHolePtr hole;
dxfLinkedSegmentsPtr coll;
dxfSegmentPtr seg;
dxfSegmentPtr seg2;
gaiaGeomCollPtr geom;
gaiaGeomCollPtr result;
gaiaPolygonPtr pg;
gaiaRingPtr rng;
int pgs;
int ok;
if (line == NULL)
return;
if (line->points <= 0)
return;
if (line->is_closed == 0)
return;
if (!force_closure (line))
return;
coll = malloc (sizeof (dxfLinkedSegments));
coll->count = line->points - 1;
coll->segments = malloc (sizeof (dxfSegment) * coll->count);
x = *(line->x + 0);
y = *(line->y + 0);
z = *(line->z + 0);
for (i2 = 0, i = 1; i < line->points; i++, i2++)
{
seg = &(coll->segments[i2]);
seg->valid = 1;
seg->ax = x;
seg->ay = y;
seg->az = z;
x = *(line->x + i);
y = *(line->y + i);
z = *(line->z + i);
seg->bx = x;
seg->by = y;
seg->bz = z;
}
for (i = 0; i < coll->count - 1; i++)
{
seg = &(coll->segments[i]);
if (seg->valid == 0)
continue;
for (i2 = i + 1; i2 < coll->count; i2++)
{
seg2 = &(coll->segments[i2]);
if (seg2->valid == 0)
continue;
if ((seg->ax == seg2->ax && seg->ay == seg2->ay
&& seg->az == seg2->az && seg->bx == seg2->bx
&& seg->by == seg2->by && seg->bz == seg2->bz)
|| (seg->ax == seg2->bx && seg->ay == seg2->by
&& seg->az == seg2->bz && seg->bx == seg2->ax
&& seg->by == seg2->ay && seg->bz == seg2->az))
{
seg->valid = 0;
seg2->valid = 0;
match = 1;
}
}
}
if (match == 0)
{
free (coll->segments);
free (coll);
return;
}
geom = gaiaAllocGeomCollXYZ ();
for (i = 0; i < coll->count; i++)
{
seg = &(coll->segments[i]);
if (seg->valid)
{
gaiaLinestringPtr ln = gaiaAddLinestringToGeomColl (geom, 2);
gaiaSetPointXYZ (ln->Coords, 0, seg->ax, seg->ay, seg->az);
gaiaSetPointXYZ (ln->Coords, 1, seg->bx, seg->by, seg->bz);
}
}
free (coll->segments);
free (coll);
if (p_cache != NULL)
result = gaiaPolygonize_r (p_cache, geom, 0);
else
result = gaiaPolygonize (geom, 0);
gaiaFreeGeomColl (geom);
if (result == NULL)
return;
pgs = 0;
ok = 1;
pg = result->FirstPolygon;
while (pg != NULL)
{
pgs++;
if (pg->NumInteriors == 0)
ok = 0;
pg = pg->Next;
}
if (ok == 1 && pgs == 1)
{
pg = result->FirstPolygon;
rng = pg->Exterior;
free (line->x);
free (line->y);
free (line->z);
line->points = rng->Points;
line->x = malloc (sizeof (double) * line->points);
line->y = malloc (sizeof (double) * line->points);
line->z = malloc (sizeof (double) * line->points);
for (i = 0; i < line->points; i++)
{
gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
*(line->x + i) = x;
*(line->y + i) = y;
*(line->z + i) = z;
}
for (i2 = 0; i2 < pg->NumInteriors; i2++)
{
rng = pg->Interiors + i2;
hole = alloc_dxf_hole (rng->Points);
insert_dxf_hole (line, hole);
for (i = 0; i < hole->points; i++)
{
gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
*(hole->x + i) = x;
*(hole->y + i) = y;
*(hole->z + i) = z;
}
}
}
gaiaFreeGeomColl (result);
line->is_closed = 1;
}
static void
insert_dxf_hatch (gaiaDxfParserPtr dxf, const char *layer_name,
gaiaDxfHatchPtr hatch)
{
gaiaDxfLayerPtr lyr = dxf->first_layer;
while (lyr != NULL)
{
if (strcmp (lyr->layer_name, layer_name) == 0)
{
if (lyr->first_hatch == NULL)
lyr->first_hatch = hatch;
if (lyr->last_hatch != NULL)
lyr->last_hatch->next = hatch;
lyr->last_hatch = hatch;
return;
}
lyr = lyr->next;
}
destroy_dxf_hatch (hatch);
}
static void
insert_dxf_block_hatch (gaiaDxfParserPtr dxf, gaiaDxfHatchPtr hatch)
{
if (dxf->curr_block.first_hatch == NULL)
dxf->curr_block.first_hatch = hatch;
if (dxf->curr_block.last_hatch != NULL)
dxf->curr_block.last_hatch->next = hatch;
dxf->curr_block.last_hatch = hatch;
}
static gaiaDxfExtraAttrPtr
alloc_dxf_extra ()
{
gaiaDxfExtraAttrPtr ext = malloc (sizeof (gaiaDxfExtraAttr));
ext->key = NULL;
ext->value = NULL;
ext->next = NULL;
return ext;
}
static gaiaDxfExtraAttrPtr
clone_dxf_extra (gaiaDxfExtraAttrPtr org)
{
int len;
gaiaDxfExtraAttrPtr ext = malloc (sizeof (gaiaDxfExtraAttr));
len = strlen (org->key);
ext->key = malloc (len + 1);
strcpy (ext->key, org->key);
len = strlen (org->value);
ext->value = malloc (len + 1);
strcpy (ext->value, org->value);
ext->next = NULL;
return ext;
}
static void
destroy_dxf_extra (gaiaDxfExtraAttrPtr ext)
{
if (ext == NULL)
return;
if (ext->key != NULL)
free (ext->key);
if (ext->value != NULL)
free (ext->value);
free (ext);
}
static gaiaDxfTextPtr
alloc_dxf_text (const char *label, double x, double y, double z, double angle)
{
int len;
gaiaDxfTextPtr txt = malloc (sizeof (gaiaDxfText));
len = strlen (label);
txt->label = malloc (len + 1);
strcpy (txt->label, label);
txt->x = x;
txt->y = y;
txt->z = z;
txt->angle = angle;
txt->first = NULL;
txt->last = NULL;
txt->next = NULL;
return txt;
}
static void
destroy_dxf_text (gaiaDxfTextPtr txt)
{
gaiaDxfExtraAttrPtr ext;
gaiaDxfExtraAttrPtr n_ext;
if (txt == NULL)
return;
if (txt->label != NULL)
free (txt->label);
ext = txt->first;
while (ext != NULL)
{
n_ext = ext->next;
destroy_dxf_extra (ext);
ext = n_ext;
}
free (txt);
}
static int
is_3d_text (gaiaDxfTextPtr txt)
{
if (txt->z == 0.0)
return 0;
return 1;
}
static void
insert_dxf_text (gaiaDxfParserPtr dxf, const char *layer_name,
gaiaDxfTextPtr txt)
{
gaiaDxfLayerPtr lyr = dxf->first_layer;
while (lyr != NULL)
{
if (strcmp (lyr->layer_name, layer_name) == 0)
{
if (lyr->first_text == NULL)
lyr->first_text = txt;
if (lyr->last_text != NULL)
lyr->last_text->next = txt;
lyr->last_text = txt;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_text (txt))
lyr->is3Dtext = 1;
}
txt->first = dxf->first_ext;
txt->last = dxf->last_ext;
dxf->first_ext = NULL;
dxf->last_ext = NULL;
if (txt->first != NULL)
lyr->hasExtraText = 1;
return;
}
lyr = lyr->next;
}
destroy_dxf_text (txt);
}
static void
insert_dxf_block_text (gaiaDxfParserPtr dxf, gaiaDxfTextPtr txt)
{
if (dxf->curr_block.first_text == NULL)
dxf->curr_block.first_text = txt;
if (dxf->curr_block.last_text != NULL)
dxf->curr_block.last_text->next = txt;
dxf->curr_block.last_text = txt;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_text (txt))
dxf->curr_block.is3Dtext = 1;
}
}
static gaiaDxfInsertPtr
alloc_dxf_insert (const char *block_id, double x, double y, double z,
double scale_x, double scale_y, double scale_z, double angle)
{
int len;
gaiaDxfInsertPtr ins = malloc (sizeof (gaiaDxfInsert));
len = strlen (block_id);
ins->block_id = malloc (len + 1);
strcpy (ins->block_id, block_id);
ins->x = x;
ins->y = y;
ins->z = z;
ins->scale_x = scale_x;
ins->scale_y = scale_y;
ins->scale_z = scale_z;
ins->angle = angle;
ins->hasText = 0;
ins->hasPoint = 0;
ins->hasLine = 0;
ins->hasPolyg = 0;
ins->hasHatch = 0;
ins->is3Dtext = 0;
ins->is3Dpoint = 0;
ins->is3Dline = 0;
ins->is3Dpolyg = 0;
ins->first = NULL;
ins->last = NULL;
ins->next = NULL;
return ins;
}
static gaiaDxfInsertPtr
clone_dxf_insert (gaiaDxfInsertPtr org)
{
gaiaDxfExtraAttrPtr ext_org;
gaiaDxfExtraAttrPtr ext;
int len;
gaiaDxfInsertPtr ins = malloc (sizeof (gaiaDxfInsert));
len = strlen (org->block_id);
ins->block_id = malloc (len + 1);
strcpy (ins->block_id, org->block_id);
ins->x = org->x;
ins->y = org->y;
ins->z = org->z;
ins->scale_x = org->scale_x;
ins->scale_y = org->scale_y;
ins->scale_z = org->scale_z;
ins->angle = org->angle;
ins->hasText = org->hasText;
ins->hasPoint = org->hasPoint;
ins->hasLine = org->hasLine;
ins->hasPolyg = org->hasPolyg;
ins->hasHatch = org->hasHatch;
ins->is3Dtext = org->is3Dtext;
ins->is3Dpoint = org->is3Dpoint;
ins->is3Dline = org->is3Dline;
ins->is3Dpolyg = org->is3Dpolyg;
ins->first = NULL;
ins->last = NULL;
ext_org = org->first;
while (ext_org != NULL)
{
ext = clone_dxf_extra (ext_org);
if (ins->first == NULL)
ins->first = ext;
if (ins->last != NULL)
ins->last->next = ext;
ins->last = ext;
ext_org = ext_org->next;
}
ins->next = NULL;
return ins;
}
static void
destroy_dxf_insert (gaiaDxfInsertPtr ins)
{
gaiaDxfExtraAttrPtr ext;
gaiaDxfExtraAttrPtr n_ext;
if (ins == NULL)
return;
if (ins->block_id != NULL)
free (ins->block_id);
ext = ins->first;
while (ext != NULL)
{
n_ext = ext->next;
destroy_dxf_extra (ext);
ext = n_ext;
}
free (ins);
}
static void
insert_dxf_insert (gaiaDxfParserPtr dxf, const char *layer_name,
gaiaDxfInsertPtr ins)
{
gaiaDxfLayerPtr lyr = dxf->first_layer;
while (lyr != NULL)
{
if (strcmp (lyr->layer_name, layer_name) == 0)
{
ins->first = dxf->first_ext;
ins->last = dxf->last_ext;
dxf->first_ext = NULL;
dxf->last_ext = NULL;
if (ins->hasText)
{
gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
if (lyr->first_ins_text == NULL)
lyr->first_ins_text = ins2;
if (lyr->last_ins_text != NULL)
lyr->last_ins_text->next = ins2;
lyr->last_ins_text = ins2;
if (ins2->is3Dtext)
lyr->is3DinsText = 1;
if (ins2->first != NULL)
lyr->hasExtraInsText = 1;
}
if (ins->hasPoint)
{
gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
if (lyr->first_ins_point == NULL)
lyr->first_ins_point = ins2;
if (lyr->last_ins_point != NULL)
lyr->last_ins_point->next = ins2;
lyr->last_ins_point = ins2;
if (ins2->is3Dpoint)
lyr->is3DinsPoint = 1;
if (ins2->first != NULL)
lyr->hasExtraInsPoint = 1;
}
if (ins->hasLine)
{
gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
if (lyr->first_ins_line == NULL)
lyr->first_ins_line = ins2;
if (lyr->last_ins_line != NULL)
lyr->last_ins_line->next = ins2;
lyr->last_ins_line = ins2;
if (ins2->is3Dline)
lyr->is3DinsLine = 1;
if (ins2->first != NULL)
lyr->hasExtraInsLine = 1;
}
if (ins->hasPolyg)
{
gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
if (lyr->first_ins_polyg == NULL)
lyr->first_ins_polyg = ins2;
if (lyr->last_ins_polyg != NULL)
lyr->last_ins_polyg->next = ins2;
lyr->last_ins_polyg = ins2;
if (ins2->is3Dpolyg)
lyr->is3DinsPolyg = 1;
if (ins2->first != NULL)
lyr->hasExtraInsPolyg = 1;
}
destroy_dxf_insert (ins);
return;
}
lyr = lyr->next;
}
destroy_dxf_insert (ins);
}
static gaiaDxfPointPtr
alloc_dxf_point (double x, double y, double z)
{
gaiaDxfPointPtr pt = malloc (sizeof (gaiaDxfPoint));
pt->x = x;
pt->y = y;
pt->z = z;
pt->next = NULL;
pt->first = NULL;
pt->last = NULL;
return pt;
}
static void
destroy_dxf_point (gaiaDxfPointPtr pt)
{
gaiaDxfExtraAttrPtr ext;
gaiaDxfExtraAttrPtr n_ext;
if (pt == NULL)
return;
ext = pt->first;
while (ext != NULL)
{
n_ext = ext->next;
destroy_dxf_extra (ext);
ext = n_ext;
}
free (pt);
}
static int
is_3d_point (gaiaDxfPointPtr pt)
{
if (pt->z == 0.0)
return 0;
return 1;
}
static void
insert_dxf_point (gaiaDxfParserPtr dxf, const char *layer_name,
gaiaDxfPointPtr pt)
{
gaiaDxfLayerPtr lyr = dxf->first_layer;
while (lyr != NULL)
{
if (strcmp (lyr->layer_name, layer_name) == 0)
{
if (lyr->first_point == NULL)
lyr->first_point = pt;
if (lyr->last_point != NULL)
lyr->last_point->next = pt;
lyr->last_point = pt;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_point (pt))
lyr->is3Dpoint = 1;
}
pt->first = dxf->first_ext;
pt->last = dxf->last_ext;
dxf->first_ext = NULL;
dxf->last_ext = NULL;
if (pt->first != NULL)
lyr->hasExtraPoint = 1;
return;
}
lyr = lyr->next;
}
destroy_dxf_point (pt);
}
static void
insert_dxf_block_point (gaiaDxfParserPtr dxf, gaiaDxfPointPtr pt)
{
if (dxf->curr_block.first_point == NULL)
dxf->curr_block.first_point = pt;
if (dxf->curr_block.last_point != NULL)
dxf->curr_block.last_point->next = pt;
dxf->curr_block.last_point = pt;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_point (pt))
dxf->curr_block.is3Dpoint = 1;
}
}
static gaiaDxfPolylinePtr
alloc_dxf_polyline (int is_closed, int points)
{
int i;
gaiaDxfPolylinePtr ln = malloc (sizeof (gaiaDxfPolyline));
ln->is_closed = is_closed;
ln->points = points;
ln->x = malloc (sizeof (double) * points);
ln->y = malloc (sizeof (double) * points);
ln->z = malloc (sizeof (double) * points);
for (i = 0; i < points; i++)
{
*(ln->x + i) = 0.0;
*(ln->y + i) = 0.0;
*(ln->z + i) = 0.0;
}
ln->first_hole = NULL;
ln->last_hole = NULL;
ln->first = NULL;
ln->last = NULL;
ln->next = NULL;
return ln;
}
static gaiaDxfPolylinePtr
alloc_dxf_line (double x0, double y0, double z0, double x1, double y1,
double z1)
{
gaiaDxfPolylinePtr ln = malloc (sizeof (gaiaDxfPolyline));
ln->is_closed = 0;
ln->points = 2;
ln->x = malloc (sizeof (double) * 2);
ln->y = malloc (sizeof (double) * 2);
ln->z = malloc (sizeof (double) * 2);
*(ln->x + 0) = x0;
*(ln->y + 0) = y0;
*(ln->z + 0) = z0;
*(ln->x + 1) = x1;
*(ln->y + 1) = y1;
*(ln->z + 1) = z1;
ln->first_hole = NULL;
ln->last_hole = NULL;
ln->first = NULL;
ln->last = NULL;
ln->next = NULL;
return ln;
}
static void
destroy_dxf_polyline (gaiaDxfPolylinePtr ln)
{
gaiaDxfExtraAttrPtr ext;
gaiaDxfExtraAttrPtr n_ext;
gaiaDxfHolePtr hole;
gaiaDxfHolePtr n_hole;
if (ln == NULL)
return;
if (ln->x != NULL)
free (ln->x);
if (ln->y != NULL)
free (ln->y);
if (ln->z != NULL)
free (ln->z);
ext = ln->first;
while (ext != NULL)
{
n_ext = ext->next;
destroy_dxf_extra (ext);
ext = n_ext;
}
hole = ln->first_hole;
while (hole != NULL)
{
n_hole = hole->next;
destroy_dxf_hole (hole);
hole = n_hole;
}
free (ln);
}
static int
is_3d_line (gaiaDxfPolylinePtr ln)
{
gaiaDxfHolePtr hole;
int i;
for (i = 0; i < ln->points; i++)
{
if (*(ln->z + i) != 0.0)
return 1;
}
hole = ln->first_hole;
while (hole != NULL)
{
for (i = 0; i < hole->points; i++)
{
if (*(hole->z + i) != 0.0)
return 1;
}
}
return 0;
}
static dxfRingsCollectionPtr
alloc_dxf_rings ()
{
dxfRingsCollectionPtr coll = malloc (sizeof (dxfRingsCollection));
coll->first = NULL;
coll->last = NULL;
return coll;
}
static void
destroy_dxf_rings (dxfRingsCollectionPtr coll)
{
gaiaDxfPolylinePtr ln;
gaiaDxfPolylinePtr n_ln;
if (coll == NULL)
return;
ln = coll->first;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
free (coll);
}
static void
insert_dxf_ring (dxfRingsCollectionPtr coll, gaiaDxfPolylinePtr line, int start,
int end)
{
int i;
int i2;
int points = end - start + 1;
gaiaDxfPolylinePtr out = alloc_dxf_polyline (1, points);
for (i2 = 0, i = start; i <= end; i++, i2++)
{
*(out->x + i2) = *(line->x + i);
*(out->y + i2) = *(line->y + i);
*(out->z + i2) = *(line->z + i);
}
if (coll->first == NULL)
coll->first = out;
if (coll->last != NULL)
coll->last->next = out;
coll->last = out;
}
static void
unlinked_rings (const void *p_cache, gaiaDxfPolylinePtr line)
{
int invalid;
int start;
int count;
double x;
double y;
double z;
int i;
int i2;
gaiaDxfHolePtr hole;
dxfRingsCollectionPtr coll;
gaiaDxfPolylinePtr ring;
gaiaGeomCollPtr geom;
gaiaGeomCollPtr result;
gaiaPolygonPtr pg;
gaiaRingPtr rng;
int pgs;
int ok;
if (line == NULL)
return;
if (line->points <= 0)
return;
if (line->is_closed == 0)
return;
if (!force_closure (line))
return;
coll = alloc_dxf_rings ();
start = 0;
while (start < line->points - 1)
{
x = *(line->x + start);
y = *(line->y + start);
z = *(line->z + start);
invalid = 1;
for (i = start + 1; i < line->points; i++)
{
if (*(line->x + i) == x && *(line->y + i) == y
&& *(line->z + i) == z)
{
insert_dxf_ring (coll, line, start, i);
start = i + 1;
invalid = 0;
break;
}
}
if (invalid)
break;
}
count = 0;
ring = coll->first;
while (ring != NULL)
{
count++;
ring = ring->next;
}
if (count < 2)
invalid = 1;
if (invalid)
{
destroy_dxf_rings (coll);
return;
}
geom = gaiaAllocGeomCollXYZ ();
ring = coll->first;
while (ring != NULL)
{
gaiaLinestringPtr ln =
gaiaAddLinestringToGeomColl (geom, ring->points);
for (i = 0; i < ring->points; i++)
{
gaiaSetPointXYZ (ln->Coords, i, *(ring->x + i), *(ring->y + i),
*(ring->z + i));
}
ring = ring->next;
}
destroy_dxf_rings (coll);
if (p_cache != NULL)
result = gaiaPolygonize_r (p_cache, geom, 0);
else
result = gaiaPolygonize (geom, 0);
gaiaFreeGeomColl (geom);
if (result == NULL)
return;
pgs = 0;
ok = 1;
pg = result->FirstPolygon;
while (pg != NULL)
{
pgs++;
if (pg->NumInteriors == 0)
ok = 0;
pg = pg->Next;
}
if (ok == 1 && pgs == 1)
{
pg = result->FirstPolygon;
rng = pg->Exterior;
free (line->x);
free (line->y);
free (line->z);
line->points = rng->Points;
line->x = malloc (sizeof (double) * line->points);
line->y = malloc (sizeof (double) * line->points);
line->z = malloc (sizeof (double) * line->points);
for (i = 0; i < line->points; i++)
{
gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
*(line->x + i) = x;
*(line->y + i) = y;
*(line->z + i) = z;
}
for (i2 = 0; i2 < pg->NumInteriors; i2++)
{
rng = pg->Interiors + i2;
hole = alloc_dxf_hole (rng->Points);
insert_dxf_hole (line, hole);
for (i = 0; i < hole->points; i++)
{
gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
*(hole->x + i) = x;
*(hole->y + i) = y;
*(hole->z + i) = z;
}
}
}
gaiaFreeGeomColl (result);
line->is_closed = 1;
}
static void
insert_dxf_polyline (const void *p_cache, gaiaDxfParserPtr dxf,
const char *layer_name, gaiaDxfPolylinePtr ln)
{
gaiaDxfLayerPtr lyr = dxf->first_layer;
while (lyr != NULL)
{
if (strcmp (lyr->layer_name, layer_name) == 0)
{
if (dxf->linked_rings)
linked_rings (p_cache, ln);
if (dxf->unlinked_rings)
unlinked_rings (p_cache, ln);
if (ln->is_closed)
{
if (lyr->first_polyg == NULL)
lyr->first_polyg = ln;
if (lyr->last_polyg != NULL)
lyr->last_polyg->next = ln;
lyr->last_polyg = ln;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_line (ln))
lyr->is3Dpolyg = 1;
}
}
else
{
if (lyr->first_line == NULL)
lyr->first_line = ln;
if (lyr->last_line != NULL)
lyr->last_line->next = ln;
lyr->last_line = ln;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_line (ln))
lyr->is3Dline = 1;
}
}
ln->first = dxf->first_ext;
ln->last = dxf->last_ext;
dxf->first_ext = NULL;
dxf->last_ext = NULL;
if (ln->is_closed && ln->first != NULL)
lyr->hasExtraPolyg = 1;
if (ln->is_closed == 0 && ln->first != NULL)
lyr->hasExtraLine = 1;
return;
}
lyr = lyr->next;
}
destroy_dxf_polyline (ln);
}
static void
insert_dxf_block_polyline (const void *p_cache, gaiaDxfParserPtr dxf,
gaiaDxfPolylinePtr ln)
{
if (dxf->linked_rings)
linked_rings (p_cache, ln);
if (dxf->unlinked_rings)
unlinked_rings (p_cache, ln);
if (ln->is_closed)
{
if (dxf->curr_block.first_polyg == NULL)
dxf->curr_block.first_polyg = ln;
if (dxf->curr_block.last_polyg != NULL)
dxf->curr_block.last_polyg->next = ln;
dxf->curr_block.last_polyg = ln;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_line (ln))
dxf->curr_block.is3Dpolyg = 1;
}
}
else
{
if (dxf->curr_block.first_line == NULL)
dxf->curr_block.first_line = ln;
if (dxf->curr_block.last_line != NULL)
dxf->curr_block.last_line->next = ln;
dxf->curr_block.last_line = ln;
if (dxf->force_dims == GAIA_DXF_FORCE_2D
|| dxf->force_dims == GAIA_DXF_FORCE_3D)
;
else
{
if (is_3d_line (ln))
dxf->curr_block.is3Dline = 1;
}
}
ln->first = dxf->first_ext;
ln->last = dxf->last_ext;
dxf->first_ext = NULL;
dxf->last_ext = NULL;
}
static gaiaDxfBlockPtr
alloc_dxf_block (const char *layer, const char *id)
{
int len;
gaiaDxfBlockPtr blk = malloc (sizeof (gaiaDxfBlock));
blk->hasInsert = 0;
len = strlen (layer);
blk->layer_name = malloc (len + 1);
strcpy (blk->layer_name, layer);
len = strlen (id);
blk->block_id = malloc (len + 1);
strcpy (blk->block_id, id);
blk->first_text = NULL;
blk->last_text = NULL;
blk->first_point = NULL;
blk->last_point = NULL;
blk->first_line = NULL;
blk->last_line = NULL;
blk->first_polyg = NULL;
blk->last_polyg = NULL;
blk->first_hatch = NULL;
blk->last_hatch = NULL;
blk->is3Dtext = 0;
blk->is3Dpoint = 0;
blk->is3Dline = 0;
blk->is3Dpolyg = 0;
blk->next = NULL;
return blk;
}
static void
destroy_dxf_block (gaiaDxfBlockPtr blk)
{
gaiaDxfTextPtr txt;
gaiaDxfTextPtr n_txt;
gaiaDxfPointPtr pt;
gaiaDxfPointPtr n_pt;
gaiaDxfPolylinePtr ln;
gaiaDxfPolylinePtr n_ln;
gaiaDxfHatchPtr htc;
gaiaDxfHatchPtr n_htc;
if (blk == NULL)
return;
if (blk->layer_name != NULL)
free (blk->layer_name);
if (blk->block_id != NULL)
free (blk->block_id);
txt = blk->first_text;
while (txt != NULL)
{
n_txt = txt->next;
destroy_dxf_text (txt);
txt = n_txt;
}
pt = blk->first_point;
while (pt != NULL)
{
n_pt = pt->next;
destroy_dxf_point (pt);
pt = n_pt;
}
ln = blk->first_line;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
ln = blk->first_polyg;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
htc = blk->first_hatch;
while (htc != NULL)
{
n_htc = htc->next;
destroy_dxf_hatch (htc);
htc = n_htc;
}
free (blk);
}
static void
insert_dxf_block (gaiaDxfParserPtr dxf)
{
gaiaDxfBlockPtr blk;
int ok = 0;
if (dxf->curr_block.layer_name == NULL)
return;
if (dxf->curr_block.block_id == NULL)
return;
if (dxf->curr_block.first_text != NULL)
ok++;
if (dxf->curr_block.first_point != NULL)
ok++;
if (dxf->curr_block.first_line != NULL)
ok++;
if (dxf->curr_block.first_polyg != NULL)
ok++;
if (dxf->curr_block.first_hatch != NULL)
ok++;
if (ok == 0)
return;
blk =
alloc_dxf_block (dxf->curr_block.layer_name, dxf->curr_block.block_id);
blk->first_text = dxf->curr_block.first_text;
blk->last_text = dxf->curr_block.last_text;
dxf->curr_block.first_text = NULL;
dxf->curr_block.last_text = NULL;
blk->first_point = dxf->curr_block.first_point;
blk->last_point = dxf->curr_block.last_point;
dxf->curr_block.first_point = NULL;
dxf->curr_block.last_point = NULL;
blk->first_line = dxf->curr_block.first_line;
blk->last_line = dxf->curr_block.last_line;
dxf->curr_block.first_line = NULL;
dxf->curr_block.last_line = NULL;
blk->first_polyg = dxf->curr_block.first_polyg;
blk->last_polyg = dxf->curr_block.last_polyg;
dxf->curr_block.first_polyg = NULL;
dxf->curr_block.last_polyg = NULL;
blk->first_hatch = dxf->curr_block.first_hatch;
blk->last_hatch = dxf->curr_block.last_hatch;
dxf->curr_block.first_hatch = NULL;
dxf->curr_block.last_hatch = NULL;
if (dxf->first_block == NULL)
dxf->first_block = blk;
if (dxf->last_block != NULL)
dxf->last_block->next = blk;
dxf->last_block = blk;
}
static gaiaDxfLayerPtr
alloc_dxf_layer (const char *name, int force_dims)
{
int len;
gaiaDxfLayerPtr lyr = malloc (sizeof (gaiaDxfLayer));
len = strlen (name);
lyr->layer_name = malloc (len + 1);
strcpy (lyr->layer_name, name);
lyr->first_text = NULL;
lyr->last_text = NULL;
lyr->first_point = NULL;
lyr->last_point = NULL;
lyr->first_line = NULL;
lyr->last_line = NULL;
lyr->first_polyg = NULL;
lyr->last_polyg = NULL;
lyr->first_hatch = NULL;
lyr->last_hatch = NULL;
lyr->first_ins_text = NULL;
lyr->last_ins_text = NULL;
lyr->first_ins_point = NULL;
lyr->last_ins_point = NULL;
lyr->first_ins_line = NULL;
lyr->last_ins_line = NULL;
lyr->first_ins_polyg = NULL;
lyr->last_ins_polyg = NULL;
lyr->first_ins_hatch = NULL;
lyr->last_ins_hatch = NULL;
if (force_dims == GAIA_DXF_FORCE_3D)
{
lyr->is3Dtext = 1;
lyr->is3Dpoint = 1;
lyr->is3Dline = 1;
lyr->is3Dpolyg = 1;
lyr->is3DinsText = 1;
lyr->is3DinsPoint = 1;
lyr->is3DinsLine = 1;
lyr->is3DinsPolyg = 1;
}
else
{
lyr->is3Dtext = 0;
lyr->is3Dpoint = 0;
lyr->is3Dline = 0;
lyr->is3Dpolyg = 0;
lyr->is3DinsText = 0;
lyr->is3DinsPoint = 0;
lyr->is3DinsLine = 0;
lyr->is3DinsPolyg = 0;
}
lyr->hasExtraText = 0;
lyr->hasExtraPoint = 0;
lyr->hasExtraLine = 0;
lyr->hasExtraPolyg = 0;
lyr->hasExtraInsText = 0;
lyr->hasExtraInsPoint = 0;
lyr->hasExtraInsLine = 0;
lyr->hasExtraInsPolyg = 0;
lyr->next = NULL;
return lyr;
}
static void
destroy_dxf_layer (gaiaDxfLayerPtr lyr)
{
gaiaDxfTextPtr txt;
gaiaDxfTextPtr n_txt;
gaiaDxfPointPtr pt;
gaiaDxfPointPtr n_pt;
gaiaDxfPolylinePtr ln;
gaiaDxfPolylinePtr n_ln;
gaiaDxfHatchPtr ht;
gaiaDxfHatchPtr n_ht;
gaiaDxfInsertPtr ins;
gaiaDxfInsertPtr n_ins;
if (lyr == NULL)
return;
txt = lyr->first_text;
while (txt != NULL)
{
n_txt = txt->next;
destroy_dxf_text (txt);
txt = n_txt;
}
pt = lyr->first_point;
while (pt != NULL)
{
n_pt = pt->next;
destroy_dxf_point (pt);
pt = n_pt;
}
ln = lyr->first_line;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
ln = lyr->first_polyg;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
ht = lyr->first_hatch;
while (ht != NULL)
{
n_ht = ht->next;
destroy_dxf_hatch (ht);
ht = n_ht;
}
ins = lyr->first_ins_text;
while (ins != NULL)
{
n_ins = ins->next;
destroy_dxf_insert (ins);
ins = n_ins;
}
ins = lyr->first_ins_point;
while (ins != NULL)
{
n_ins = ins->next;
destroy_dxf_insert (ins);
ins = n_ins;
}
ins = lyr->first_ins_line;
while (ins != NULL)
{
n_ins = ins->next;
destroy_dxf_insert (ins);
ins = n_ins;
}
ins = lyr->first_ins_polyg;
while (ins != NULL)
{
n_ins = ins->next;
destroy_dxf_insert (ins);
ins = n_ins;
}
ins = lyr->first_ins_hatch;
while (ins != NULL)
{
n_ins = ins->next;
destroy_dxf_insert (ins);
ins = n_ins;
}
if (lyr->layer_name != NULL)
free (lyr->layer_name);
free (lyr);
}
static void
insert_dxf_layer (gaiaDxfParserPtr dxf, gaiaDxfLayerPtr lyr)
{
if (dxf->first_layer == NULL)
dxf->first_layer = lyr;
if (dxf->last_layer != NULL)
dxf->last_layer->next = lyr;
dxf->last_layer = lyr;
}
static void
force_missing_layer (gaiaDxfParserPtr dxf)
{
int ok_layer = 1;
if (dxf->undeclared_layers == 0)
return;
if (dxf->selected_layer != NULL)
{
ok_layer = 0;
if (strcmp (dxf->selected_layer, dxf->curr_layer_name) == 0)
ok_layer = 1;
}
if (ok_layer)
{
int already_defined = 0;
gaiaDxfLayerPtr lyr = dxf->first_layer;
while (lyr != NULL)
{
if (strcmp (lyr->layer_name, dxf->curr_layer_name) == 0)
{
already_defined = 1;
break;
}
lyr = lyr->next;
}
if (already_defined)
return;
lyr = alloc_dxf_layer (dxf->curr_layer_name, dxf->force_dims);
insert_dxf_layer (dxf, lyr);
}
}
static void
set_dxf_vertex (gaiaDxfParserPtr dxf)
{
gaiaDxfPointPtr pt = malloc (sizeof (gaiaDxfPoint));
pt->x = dxf->curr_point.x;
pt->y = dxf->curr_point.y;
pt->z = dxf->curr_point.z;
pt->first = NULL;
pt->last = NULL;
pt->next = NULL;
if (dxf->first_pt == NULL)
dxf->first_pt = pt;
if (dxf->last_pt != NULL)
dxf->last_pt->next = pt;
dxf->last_pt = pt;
dxf->curr_point.x = 0.0;
dxf->curr_point.y = 0.0;
dxf->curr_point.z = 0.0;
}
static void
save_current_polyline (const void *p_cache, gaiaDxfParserPtr dxf)
{
int points = 0;
gaiaDxfPolylinePtr ln;
gaiaDxfPointPtr n_pt;
gaiaDxfPointPtr pt;
if (dxf->curr_layer_name == NULL)
goto clear;
pt = dxf->first_pt;
while (pt != NULL)
{
points++;
pt = pt->next;
}
ln = alloc_dxf_polyline (dxf->is_closed_polyline, points);
points = 0;
pt = dxf->first_pt;
while (pt != NULL)
{
*(ln->x + points) = pt->x;
*(ln->y + points) = pt->y;
*(ln->z + points) = pt->z;
points++;
pt = pt->next;
}
if (dxf->is_block)
insert_dxf_block_polyline (p_cache, dxf, ln);
else
{
force_missing_layer (dxf);
insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
}
clear:
pt = dxf->first_pt;
while (pt != NULL)
{
n_pt = pt->next;
destroy_dxf_point (pt);
pt = n_pt;
}
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
dxf->first_pt = NULL;
dxf->last_pt = NULL;
}
static void
reset_dxf_polyline (const void *p_cache, gaiaDxfParserPtr dxf)
{
if (dxf->is_polyline)
{
if (dxf->first_pt != NULL)
save_current_polyline (p_cache, dxf);
dxf->is_polyline = 0;
}
}
static void
reset_dxf_block (gaiaDxfParserPtr dxf)
{
gaiaDxfTextPtr txt;
gaiaDxfTextPtr n_txt;
gaiaDxfPointPtr pt;
gaiaDxfPointPtr n_pt;
gaiaDxfPolylinePtr ln;
gaiaDxfPolylinePtr n_ln;
gaiaDxfHatchPtr htc;
gaiaDxfHatchPtr n_htc;
if (dxf->curr_block.layer_name != NULL)
free (dxf->curr_block.layer_name);
if (dxf->curr_block.block_id != NULL)
free (dxf->curr_block.block_id);
txt = dxf->curr_block.first_text;
while (txt != NULL)
{
n_txt = txt->next;
destroy_dxf_text (txt);
txt = n_txt;
}
pt = dxf->curr_block.first_point;
while (pt != NULL)
{
n_pt = pt->next;
destroy_dxf_point (pt);
pt = n_pt;
}
ln = dxf->curr_block.first_line;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
ln = dxf->curr_block.first_polyg;
while (ln != NULL)
{
n_ln = ln->next;
destroy_dxf_polyline (ln);
ln = n_ln;
}
htc = dxf->curr_block.first_hatch;
while (htc != NULL)
{
n_htc = htc->next;
destroy_dxf_hatch (htc);
htc = n_htc;
}
dxf->curr_block.layer_name = NULL;
dxf->curr_block.block_id = NULL;
dxf->curr_block.first_text = NULL;
dxf->curr_block.last_text = NULL;
dxf->curr_block.first_point = NULL;
dxf->curr_block.last_point = NULL;
dxf->curr_block.first_line = NULL;
dxf->curr_block.last_line = NULL;
dxf->curr_block.first_polyg = NULL;
dxf->curr_block.last_polyg = NULL;
dxf->curr_block.first_hatch = NULL;
dxf->curr_block.last_hatch = NULL;
dxf->curr_block.is3Dtext = 0;
dxf->curr_block.is3Dpoint = 0;
dxf->curr_block.is3Dline = 0;
dxf->curr_block.is3Dpolyg = 0;
}
static gaiaDxfBlockPtr
find_dxf_block (gaiaDxfParserPtr dxf, const char *layer_name,
const char *block_id)
{
gaiaDxfBlockPtr blk = dxf->first_block;
while (blk != NULL)
{
if (layer_name != NULL && block_id != NULL)
{
if (strcmp (blk->layer_name, layer_name) == 0
&& strcmp (blk->block_id, block_id) == 0)
{
return blk;
}
}
blk = blk->next;
}
return NULL;
}
static void
save_current_circle (const void *p_cache, gaiaDxfParserPtr dxf)
{
int iv;
double x;
double y;
gaiaGeomCollPtr geom = NULL;
gaiaLinestringPtr circle;
gaiaDxfPolylinePtr ln;
if (dxf->curr_layer_name == NULL)
return;
geom =
gaiaMakeCircle (dxf->curr_circle.cx, dxf->curr_circle.cy,
dxf->curr_circle.radius, 2.5);
if (geom == NULL)
goto stop;
circle = geom->FirstLinestring;
if (circle == NULL)
goto stop;
ln = alloc_dxf_polyline (0, circle->Points);
for (iv = 0; iv < circle->Points; iv++)
{
gaiaGetPoint (circle->Coords, iv, &x, &y);
*(ln->x + iv) = x;
*(ln->y + iv) = y;
*(ln->z + iv) = dxf->curr_circle.cz;
}
if (dxf->is_block)
insert_dxf_block_polyline (p_cache, dxf, ln);
else
{
force_missing_layer (dxf);
insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
}
stop:
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
if (geom != NULL)
gaiaFreeGeomColl (geom);
}
static void
save_current_arc (const void *p_cache, gaiaDxfParserPtr dxf)
{
int iv;
double x;
double y;
gaiaGeomCollPtr geom;
gaiaLinestringPtr arc;
gaiaDxfPolylinePtr ln;
if (dxf->curr_layer_name == NULL)
return;
geom =
gaiaMakeArc (dxf->curr_arc.cx, dxf->curr_arc.cy, dxf->curr_arc.radius,
dxf->curr_arc.start, dxf->curr_arc.stop, 2.5);
if (geom == NULL)
goto stop;
arc = geom->FirstLinestring;
if (arc == NULL)
goto stop;
ln = alloc_dxf_polyline (0, arc->Points);
for (iv = 0; iv < arc->Points; iv++)
{
gaiaGetPoint (arc->Coords, iv, &x, &y);
*(ln->x + iv) = x;
*(ln->y + iv) = y;
*(ln->z + iv) = dxf->curr_arc.cz;
}
if (dxf->is_block)
insert_dxf_block_polyline (p_cache, dxf, ln);
else
{
force_missing_layer (dxf);
insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
}
stop:
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
if (geom != NULL)
gaiaFreeGeomColl (geom);
}
static void
reset_dxf_entity (const void *p_cache, gaiaDxfParserPtr dxf)
{
gaiaDxfExtraAttrPtr ext;
gaiaDxfExtraAttrPtr n_ext;
if (dxf->is_vertex)
{
set_dxf_vertex (dxf);
dxf->is_vertex = 0;
return;
}
if (dxf->is_polyline)
return;
if (dxf->is_layer)
{
int ok_layer = 1;
if (dxf->selected_layer != NULL)
{
ok_layer = 0;
if (strcmp (dxf->selected_layer, dxf->curr_layer_name) == 0)
ok_layer = 1;
}
if (ok_layer)
{
gaiaDxfLayerPtr lyr =
alloc_dxf_layer (dxf->curr_layer_name, dxf->force_dims);
insert_dxf_layer (dxf, lyr);
dxf->undeclared_layers = 0;
}
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
dxf->is_layer = 0;
}
if (dxf->is_insert)
{
gaiaDxfBlockPtr blk = find_dxf_block (dxf, dxf->curr_layer_name,
dxf->curr_insert.block_id);
if (blk != NULL)
{
gaiaDxfInsertPtr ins =
alloc_dxf_insert (dxf->curr_insert.block_id,
dxf->curr_insert.x,
dxf->curr_insert.y, dxf->curr_insert.z,
dxf->curr_insert.scale_x,
dxf->curr_insert.scale_y,
dxf->curr_insert.scale_z,
dxf->curr_insert.angle);
blk->hasInsert = 1;
if (blk->first_text != NULL)
{
ins->hasText = 1;
if (blk->is3Dtext)
ins->is3Dtext = 1;
}
if (blk->first_point != NULL)
{
ins->hasPoint = 1;
if (blk->is3Dpoint)
ins->is3Dpoint = 1;
}
if (blk->first_line != NULL)
{
ins->hasLine = 1;
if (blk->is3Dline)
ins->is3Dline = 1;
}
if (blk->first_polyg != NULL)
{
ins->hasPolyg = 1;
if (blk->is3Dpolyg)
ins->is3Dpolyg = 1;
}
if (blk->first_hatch != NULL)
ins->hasHatch = 1;
force_missing_layer (dxf);
insert_dxf_insert (dxf, dxf->curr_layer_name, ins);
}
dxf->curr_insert.x = 0.0;
dxf->curr_insert.y = 0.0;
dxf->curr_insert.z = 0.0;
dxf->curr_insert.scale_x = 0.0;
dxf->curr_insert.scale_y = 0.0;
dxf->curr_insert.scale_z = 0.0;
dxf->curr_insert.angle = 0.0;
dxf->curr_insert.is3Dtext = 0;
dxf->curr_insert.is3Dpoint = 0;
dxf->curr_insert.is3Dline = 0;
dxf->curr_insert.is3Dpolyg = 0;
if (dxf->curr_insert.block_id != NULL)
free (dxf->curr_insert.block_id);
dxf->curr_insert.block_id = NULL;
dxf->is_insert = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->is_line)
{
gaiaDxfPolylinePtr ln =
alloc_dxf_line (dxf->curr_point.x, dxf->curr_point.y,
dxf->curr_point.z,
dxf->curr_end_point.x, dxf->curr_end_point.y,
dxf->curr_end_point.z);
if (dxf->is_block)
insert_dxf_block_polyline (p_cache, dxf, ln);
else
{
force_missing_layer (dxf);
insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
}
dxf->curr_point.x = 0.0;
dxf->curr_point.y = 0.0;
dxf->curr_point.z = 0.0;
dxf->curr_end_point.x = 0.0;
dxf->curr_end_point.y = 0.0;
dxf->curr_end_point.z = 0.0;
dxf->is_line = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->is_hatch)
{
if (dxf->curr_hatch != NULL)
{
if (is_valid_dxf_hatch (dxf->curr_hatch))
{
create_dxf_hatch_lines (p_cache, dxf->curr_hatch,
dxf->srid);
if (dxf->is_block)
insert_dxf_block_hatch (dxf, dxf->curr_hatch);
else
{
force_missing_layer (dxf);
insert_dxf_hatch (dxf, dxf->curr_layer_name,
dxf->curr_hatch);
}
dxf->curr_hatch = NULL;
}
}
dxf->is_hatch = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->is_text)
{
gaiaDxfTextPtr txt =
alloc_dxf_text (dxf->curr_text.label, dxf->curr_text.x,
dxf->curr_text.y, dxf->curr_text.z,
dxf->curr_text.angle);
if (dxf->is_block)
insert_dxf_block_text (dxf, txt);
else
{
force_missing_layer (dxf);
insert_dxf_text (dxf, dxf->curr_layer_name, txt);
}
dxf->curr_text.x = 0.0;
dxf->curr_text.y = 0.0;
dxf->curr_text.z = 0.0;
dxf->curr_text.angle = 0.0;
if (dxf->curr_text.label != NULL)
free (dxf->curr_text.label);
dxf->curr_text.label = NULL;
dxf->is_text = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->is_point)
{
gaiaDxfPointPtr pt =
alloc_dxf_point (dxf->curr_point.x, dxf->curr_point.y,
dxf->curr_point.z);
if (dxf->is_block)
insert_dxf_block_point (dxf, pt);
else
{
force_missing_layer (dxf);
insert_dxf_point (dxf, dxf->curr_layer_name, pt);
}
dxf->curr_point.x = 0.0;
dxf->curr_point.y = 0.0;
dxf->curr_point.z = 0.0;
dxf->is_point = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->is_lwpolyline)
{
save_current_polyline (p_cache, dxf);
dxf->is_lwpolyline = 0;
}
if (dxf->is_circle)
{
save_current_circle (p_cache, dxf);
dxf->curr_circle.cx = 0.0;
dxf->curr_circle.cy = 0.0;
dxf->curr_circle.cz = 0.0;
dxf->curr_circle.radius = 0.0;
dxf->is_circle = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->is_arc)
{
save_current_arc (p_cache, dxf);
dxf->curr_arc.cx = 0.0;
dxf->curr_arc.cy = 0.0;
dxf->curr_arc.cz = 0.0;
dxf->curr_arc.radius = 0.0;
dxf->curr_arc.start = 0.0;
dxf->curr_arc.stop = 0.0;
dxf->is_arc = 0;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
dxf->curr_layer_name = NULL;
}
if (dxf->extra_key != NULL)
{
free (dxf->extra_key);
dxf->extra_key = NULL;
}
if (dxf->extra_value != NULL)
{
free (dxf->extra_value);
dxf->extra_value = NULL;
}
ext = dxf->first_ext;
while (ext != NULL)
{
n_ext = ext->next;
destroy_dxf_extra (ext);
ext = n_ext;
}
dxf->first_ext = NULL;
dxf->last_ext = NULL;
if (dxf->curr_hatch != NULL)
destroy_dxf_hatch (dxf->curr_hatch);
dxf->curr_hatch = NULL;
}
static void
set_dxf_layer_name (gaiaDxfParserPtr dxf, const char *name)
{
int len;
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
len = strlen (name);
dxf->curr_layer_name = malloc (len + 1);
strcpy (dxf->curr_layer_name, name);
}
static void
set_dxf_block_layer_name (gaiaDxfParserPtr dxf, const char *name)
{
int len;
if (dxf->curr_block.layer_name != NULL)
free (dxf->curr_block.layer_name);
len = strlen (name);
dxf->curr_block.layer_name = malloc (len + 1);
strcpy (dxf->curr_block.layer_name, name);
}
static void
set_dxf_block_id (gaiaDxfParserPtr dxf, const char *id)
{
int len;
if (dxf->curr_block.block_id != NULL)
free (dxf->curr_block.block_id);
len = strlen (id);
dxf->curr_block.block_id = malloc (len + 1);
strcpy (dxf->curr_block.block_id, id);
}
static void
set_dxf_insert_block_id (gaiaDxfParserPtr dxf, const char *id)
{
int len;
if (dxf->curr_insert.block_id != NULL)
free (dxf->curr_insert.block_id);
len = strlen (id);
dxf->curr_insert.block_id = malloc (len + 1);
strcpy (dxf->curr_insert.block_id, id);
}
static void
set_dxf_label (gaiaDxfParserPtr dxf, const char *label)
{
int len;
if (dxf->curr_text.label != NULL)
free (dxf->curr_text.label);
len = strlen (label);
dxf->curr_text.label = malloc (len + 1);
strcpy (dxf->curr_text.label, label);
}
static void
set_dxf_extra_attr (gaiaDxfParserPtr dxf)
{
gaiaDxfExtraAttrPtr ext = alloc_dxf_extra ();
ext->key = dxf->extra_key;
ext->value = dxf->extra_value;
if (dxf->first_ext == NULL)
dxf->first_ext = ext;
if (dxf->last_ext != NULL)
dxf->last_ext->next = ext;
dxf->last_ext = ext;
dxf->extra_key = NULL;
dxf->extra_value = NULL;
}
static void
set_dxf_extra_key (gaiaDxfParserPtr dxf, const char *key)
{
int len;
if (dxf->extra_key != NULL)
free (dxf->extra_key);
len = strlen (key);
dxf->extra_key = malloc (len + 1);
strcpy (dxf->extra_key, key);
if (dxf->extra_key != NULL && dxf->extra_value != NULL)
set_dxf_extra_attr (dxf);
}
static void
set_dxf_extra_value (gaiaDxfParserPtr dxf, const char *value)
{
int len;
if (dxf->extra_value != NULL)
free (dxf->extra_value);
len = strlen (value);
dxf->extra_value = malloc (len + 1);
strcpy (dxf->extra_value, value);
if (dxf->extra_key != NULL && dxf->extra_value != NULL)
set_dxf_extra_attr (dxf);
}
static void
create_dxf_curr_hatch (gaiaDxfParserPtr dxf)
{
if (dxf->curr_hatch != NULL)
destroy_dxf_hatch (dxf->curr_hatch);
dxf->curr_hatch = alloc_dxf_hatch ();
}
static void
start_dxf_hatch_boundary (gaiaDxfParserPtr dxf)
{
if (dxf->curr_hatch != NULL)
{
gaiaDxfBoundaryPathPtr path = alloc_dxf_boundary_path ();
insert_dxf_boundary_path (dxf->curr_hatch, path);
dxf->is_hatch_boundary = 1;
}
}
static void
insert_dxf_hatch_boundary_segm (gaiaDxfParserPtr dxf)
{
if (dxf->curr_hatch != NULL)
{
gaiaDxfBoundaryPathPtr path = dxf->curr_hatch->last;
if (path != NULL)
{
gaiaDxfHatchSegmPtr segm =
alloc_dxf_hatch_segm (dxf->curr_point.x, dxf->curr_point.y,
dxf->curr_end_point.x,
dxf->curr_end_point.y);
insert_dxf_boundary_segm (path, segm);
}
}
dxf->curr_point.x = 0.0;
dxf->curr_point.y = 0.0;
dxf->curr_point.z = 0.0;
dxf->curr_end_point.x = 0.0;
dxf->curr_end_point.y = 0.0;
dxf->curr_end_point.z = 0.0;
}
static void
set_dxf_hatch_spacing (gaiaDxfParserPtr dxf, double spacing)
{
if (dxf->curr_hatch != NULL)
dxf->curr_hatch->spacing = spacing;
}
static void
set_dxf_hatch_angle (gaiaDxfParserPtr dxf, double angle)
{
if (dxf->curr_hatch != NULL)
dxf->curr_hatch->angle = angle;
}
static void
set_dxf_hatch_base_x (gaiaDxfParserPtr dxf, double x)
{
if (dxf->curr_hatch != NULL)
dxf->curr_hatch->base_x = x;
}
static void
set_dxf_hatch_base_y (gaiaDxfParserPtr dxf, double y)
{
if (dxf->curr_hatch != NULL)
dxf->curr_hatch->base_y = y;
}
static void
set_dxf_hatch_offset_x (gaiaDxfParserPtr dxf, double x)
{
if (dxf->curr_hatch != NULL)
dxf->curr_hatch->offset_x = x;
}
static void
set_dxf_hatch_offset_y (gaiaDxfParserPtr dxf, double y)
{
if (dxf->curr_hatch != NULL)
dxf->curr_hatch->offset_y = y;
}
static int
op_code_line (const char *line)
{
int numdigit = 0;
int invalid = 0;
const char *p = line;
while (*p != '\0')
{
if (*p == ' ' || *p == '\t')
{
p++;
continue;
}
else
break;
}
while (*p != '\0')
{
if (*p >= '0' && *p <= '9')
{
numdigit++;
p++;
continue;
}
else
{
invalid = 1;
break;
}
}
if (numdigit > 0 && invalid == 0)
return 1;
return 0;
}
static int
parse_dxf_line (const void *p_cache, gaiaDxfParserPtr dxf, const char *line)
{
dxf->line_no += 1;
if (dxf->tables || dxf->entities || dxf->blocks)
{
if (dxf->op_code_line)
{
if (!op_code_line (line))
{
spatialite_e
("ERROR on line %d: expected on OP-CODE to be found\n",
dxf->line_no);
return 0;
}
dxf->op_code = atoi (line);
if (dxf->op_code == 0)
reset_dxf_entity (p_cache, dxf);
dxf->op_code_line = 0;
return 1;
}
dxf->op_code_line = 1;
}
if (dxf->eof)
{
spatialite_e ("ERROR on line %d: attempting to read past EOF\n",
dxf->line_no);
return 0;
}
if (strcmp (line, "SECTION") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->section)
{
spatialite_e ("ERROR on line %d: unexpected SECTION\n",
dxf->line_no);
dxf->error = 1;
return 0;
}
dxf->section = 1;
return 1;
}
if (strcmp (line, "ENDSEC") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (!dxf->section)
{
spatialite_e ("ERROR on line %d: unexpected ENDSEC\n",
dxf->line_no);
dxf->error = 1;
return 0;
}
dxf->section = 0;
dxf->tables = 0;
dxf->blocks = 0;
dxf->is_block = 0;
dxf->entities = 0;
return 1;
}
if (strcmp (line, "TABLES") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->section)
{
dxf->tables = 1;
dxf->op_code_line = 1;
return 1;
}
}
if (strcmp (line, "BLOCKS") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->section)
{
dxf->blocks = 1;
dxf->op_code_line = 1;
return 1;
}
}
if (strcmp (line, "BLOCK") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->blocks)
{
dxf->is_block = 1;
dxf->op_code_line = 1;
return 1;
}
}
if (strcmp (line, "ENDBLK") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->is_block)
{
insert_dxf_block (dxf);
dxf->is_block = 0;
dxf->op_code_line = 1;
return 1;
}
}
if (strcmp (line, "ENTITIES") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->section)
{
dxf->entities = 1;
dxf->op_code_line = 1;
return 1;
}
}
if (strcmp (line, "LAYER") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->tables && dxf->op_code == 0)
{
dxf->is_layer = 1;
return 1;
}
}
if (strcmp (line, "INSERT") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_insert = 1;
return 1;
}
}
if (strcmp (line, "INSERT") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_insert = 1;
return 1;
}
}
if (strcmp (line, "TEXT") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_text = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_text = 1;
return 1;
}
}
if (strcmp (line, "POINT") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_point = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_point = 1;
return 1;
}
}
if (strcmp (line, "POLYLINE") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_polyline = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_polyline = 1;
return 1;
}
}
if (strcmp (line, "LWPOLYLINE") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_lwpolyline = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_lwpolyline = 1;
return 1;
}
}
if (strcmp (line, "LINE") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_line = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_line = 1;
return 1;
}
}
if (strcmp (line, "CIRCLE") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_circle = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_circle = 1;
return 1;
}
}
if (strcmp (line, "ARC") == 0)
{
reset_dxf_polyline (p_cache, dxf);
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_arc = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_arc = 1;
return 1;
}
}
if (strcmp (line, "VERTEX") == 0)
{
if (dxf->is_polyline && dxf->op_code == 0)
{
dxf->is_vertex = 1;
return 1;
}
}
if (strcmp (line, "HATCH") == 0)
{
if (dxf->entities && dxf->op_code == 0)
{
dxf->is_hatch = 1;
return 1;
}
if (dxf->is_block && dxf->op_code == 0)
{
dxf->is_hatch = 1;
return 1;
}
}
if (strcmp (line, "EOF") == 0)
{
reset_dxf_polyline (p_cache, dxf);
dxf->eof = 1;
return 1;
}
if (dxf->is_layer)
{
switch (dxf->op_code)
{
case 2:
set_dxf_layer_name (dxf, line);
break;
};
}
if (dxf->is_block)
{
switch (dxf->op_code)
{
case 2:
set_dxf_block_id (dxf, line);
break;
case 8:
set_dxf_block_layer_name (dxf, line);
break;
};
}
if (dxf->is_line)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_point.x = atof (line);
break;
case 20:
dxf->curr_point.y = atof (line);
break;
case 30:
dxf->curr_point.z = atof (line);
break;
case 11:
dxf->curr_end_point.x = atof (line);
break;
case 21:
dxf->curr_end_point.y = atof (line);
break;
case 31:
dxf->curr_end_point.z = atof (line);
break;
};
}
if (dxf->is_circle)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_circle.cx = atof (line);
break;
case 20:
dxf->curr_circle.cy = atof (line);
break;
case 30:
dxf->curr_circle.cz = atof (line);
break;
case 40:
dxf->curr_circle.radius = atof (line);
break;
};
}
if (dxf->is_arc)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_arc.cx = atof (line);
break;
case 20:
dxf->curr_arc.cy = atof (line);
break;
case 30:
dxf->curr_arc.cz = atof (line);
break;
case 40:
dxf->curr_arc.radius = atof (line);
break;
case 50:
dxf->curr_arc.start = atof (line);
break;
case 51:
dxf->curr_arc.stop = atof (line);
break;
};
}
if (dxf->is_insert)
{
switch (dxf->op_code)
{
case 2:
set_dxf_insert_block_id (dxf, line);
break;
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_insert.x = atof (line);
break;
case 20:
dxf->curr_insert.y = atof (line);
break;
case 30:
dxf->curr_insert.z = atof (line);
break;
case 41:
dxf->curr_insert.scale_x = atof (line);
break;
case 42:
dxf->curr_insert.scale_y = atof (line);
break;
case 43:
dxf->curr_insert.scale_z = atof (line);
break;
case 50:
dxf->curr_insert.angle = atof (line);
break;
case 1000:
set_dxf_extra_value (dxf, line);
break;
case 1001:
set_dxf_extra_key (dxf, line);
break;
};
}
if (dxf->is_text)
{
switch (dxf->op_code)
{
case 1:
set_dxf_label (dxf, line);
break;
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_text.x = atof (line);
break;
case 20:
dxf->curr_text.y = atof (line);
break;
case 30:
dxf->curr_text.z = atof (line);
break;
case 50:
dxf->curr_text.angle = atof (line);
break;
case 1000:
set_dxf_extra_value (dxf, line);
break;
case 1001:
set_dxf_extra_key (dxf, line);
break;
};
}
if (dxf->is_point)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_point.x = atof (line);
break;
case 20:
dxf->curr_point.y = atof (line);
break;
case 30:
dxf->curr_point.z = atof (line);
break;
case 1000:
set_dxf_extra_value (dxf, line);
break;
case 1001:
set_dxf_extra_key (dxf, line);
break;
};
}
if (dxf->is_lwpolyline)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
break;
case 10:
dxf->curr_point.x = atof (line);
break;
case 20:
dxf->curr_point.y = atof (line);
set_dxf_vertex (dxf);
break;
case 70:
if ((atoi (line) & 0x01) == 0x01)
dxf->is_closed_polyline = 1;
else
dxf->is_closed_polyline = 0;
break;
case 1000:
set_dxf_extra_value (dxf, line);
break;
case 1001:
set_dxf_extra_key (dxf, line);
break;
};
}
if (dxf->is_polyline && dxf->is_vertex != 1)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
break;
case 70:
if ((atoi (line) & 0x01) == 0x01)
dxf->is_closed_polyline = 1;
else
dxf->is_closed_polyline = 0;
break;
case 1000:
set_dxf_extra_value (dxf, line);
break;
case 1001:
set_dxf_extra_key (dxf, line);
break;
};
}
if (dxf->is_vertex)
{
switch (dxf->op_code)
{
case 10:
dxf->curr_point.x = atof (line);
break;
case 20:
dxf->curr_point.y = atof (line);
break;
case 30:
dxf->curr_point.z = atof (line);
break;
};
}
if (dxf->is_hatch)
{
switch (dxf->op_code)
{
case 8:
set_dxf_layer_name (dxf, line);
create_dxf_curr_hatch (dxf);
break;
case 10:
if (dxf->is_hatch_boundary)
dxf->curr_point.x = atof (line);
break;
case 20:
if (dxf->is_hatch_boundary)
dxf->curr_point.y = atof (line);
break;
case 11:
if (dxf->is_hatch_boundary)
dxf->curr_end_point.x = atof (line);
break;
case 21:
dxf->curr_end_point.y = atof (line);
insert_dxf_hatch_boundary_segm (dxf);
break;
case 41:
set_dxf_hatch_spacing (dxf, atof (line));
break;
case 43:
set_dxf_hatch_base_x (dxf, atof (line));
break;
case 44:
set_dxf_hatch_base_y (dxf, atof (line));
break;
case 45:
set_dxf_hatch_offset_x (dxf, atof (line));
break;
case 46:
set_dxf_hatch_offset_y (dxf, atof (line));
break;
case 53:
set_dxf_hatch_angle (dxf, atof (line));
break;
case 92:
start_dxf_hatch_boundary (dxf);
break;
case 97:
dxf->is_hatch_boundary = 0;
break;
};
}
return 1;
}
GAIAGEO_DECLARE gaiaDxfParserPtr
gaiaCreateDxfParser (int srid,
int force_dims,
const char *prefix,
const char *selected_layer, int special_rings)
{
gaiaDxfParserPtr dxf = malloc (sizeof (gaiaDxfParser));
dxf->line_no = 0;
dxf->op_code_line = 0;
dxf->op_code = -1;
dxf->section = 0;
dxf->tables = 0;
dxf->blocks = 0;
dxf->entities = 0;
dxf->is_layer = 0;
dxf->is_block = 0;
dxf->is_text = 0;
dxf->is_point = 0;
dxf->is_polyline = 0;
dxf->is_lwpolyline = 0;
dxf->is_line = 0;
dxf->is_circle = 0;
dxf->is_arc = 0;
dxf->is_vertex = 0;
dxf->is_hatch = 0;
dxf->is_hatch_boundary = 0;
dxf->is_insert = 0;
dxf->eof = 0;
dxf->error = 0;
dxf->curr_layer_name = NULL;
dxf->curr_insert.x = 0.0;
dxf->curr_insert.y = 0.0;
dxf->curr_insert.z = 0.0;
dxf->curr_insert.scale_x = 0.0;
dxf->curr_insert.scale_y = 0.0;
dxf->curr_insert.scale_z = 0.0;
dxf->curr_insert.angle = 0.0;
dxf->curr_insert.block_id = NULL;
dxf->curr_insert.is3Dtext = 0;
dxf->curr_insert.is3Dpoint = 0;
dxf->curr_insert.is3Dline = 0;
dxf->curr_insert.is3Dpolyg = 0;
dxf->curr_text.x = 0.0;
dxf->curr_text.y = 0.0;
dxf->curr_text.z = 0.0;
dxf->curr_text.angle = 0.0;
dxf->curr_text.label = NULL;
dxf->curr_point.x = 0.0;
dxf->curr_point.y = 0.0;
dxf->curr_point.z = 0.0;
dxf->curr_block.layer_name = NULL;
dxf->curr_block.block_id = NULL;
dxf->curr_block.first_text = NULL;
dxf->curr_block.last_text = NULL;
dxf->curr_block.first_point = NULL;
dxf->curr_block.last_point = NULL;
dxf->curr_block.first_line = NULL;
dxf->curr_block.last_line = NULL;
dxf->curr_block.first_polyg = NULL;
dxf->curr_block.last_polyg = NULL;
dxf->curr_block.first_hatch = NULL;
dxf->curr_block.last_hatch = NULL;
dxf->curr_block.is3Dtext = 0;
dxf->curr_block.is3Dpoint = 0;
dxf->curr_block.is3Dline = 0;
dxf->curr_block.is3Dpolyg = 0;
dxf->curr_end_point.x = 0.0;
dxf->curr_end_point.y = 0.0;
dxf->curr_end_point.z = 0.0;
dxf->curr_circle.cx = 0.0;
dxf->curr_circle.cy = 0.0;
dxf->curr_circle.cz = 0.0;
dxf->curr_circle.radius = 0.0;
dxf->curr_arc.cx = 0.0;
dxf->curr_arc.cy = 0.0;
dxf->curr_arc.cz = 0.0;
dxf->curr_arc.radius = 0.0;
dxf->curr_arc.start = 0.0;
dxf->curr_arc.stop = 0.0;
dxf->is_closed_polyline = 0;
dxf->extra_key = NULL;
dxf->extra_value = NULL;
dxf->first_pt = NULL;
dxf->last_pt = NULL;
dxf->first_ext = NULL;
dxf->last_ext = NULL;
dxf->filename = NULL;
dxf->first_layer = NULL;
dxf->last_layer = NULL;
dxf->first_block = NULL;
dxf->last_block = NULL;
dxf->curr_hatch = NULL;
dxf->force_dims = force_dims;
if (srid <= 0)
srid = -1;
dxf->srid = srid;
dxf->prefix = prefix;
dxf->selected_layer = selected_layer;
dxf->linked_rings = 0;
dxf->unlinked_rings = 0;
if (special_rings == GAIA_DXF_RING_LINKED)
dxf->linked_rings = 1;
if (special_rings == GAIA_DXF_RING_UNLINKED)
dxf->unlinked_rings = 1;
dxf->undeclared_layers = 1;
return dxf;
}
GAIAGEO_DECLARE void
gaiaDestroyDxfParser (gaiaDxfParserPtr dxf)
{
gaiaDxfLayerPtr lyr;
gaiaDxfLayerPtr n_lyr;
gaiaDxfPointPtr pt;
gaiaDxfPointPtr n_pt;
gaiaDxfExtraAttrPtr ext;
gaiaDxfExtraAttrPtr n_ext;
gaiaDxfBlockPtr blk;
gaiaDxfBlockPtr n_blk;
if (dxf == NULL)
return;
if (dxf->curr_text.label != NULL)
free (dxf->curr_text.label);
if (dxf->curr_layer_name != NULL)
free (dxf->curr_layer_name);
if (dxf->filename != NULL)
free (dxf->filename);
lyr = dxf->first_layer;
while (lyr != NULL)
{
n_lyr = lyr->next;
destroy_dxf_layer (lyr);
lyr = n_lyr;
}
pt = dxf->first_pt;
while (pt != NULL)
{
n_pt = pt->next;
destroy_dxf_point (pt);
pt = n_pt;
}
if (dxf->extra_key != NULL)
free (dxf->extra_key);
if (dxf->extra_value != NULL)
free (dxf->extra_value);
ext = dxf->first_ext;
while (ext != NULL)
{
n_ext = ext->next;
destroy_dxf_extra (ext);
ext = n_ext;
}
blk = dxf->first_block;
while (blk != NULL)
{
n_blk = blk->next;
destroy_dxf_block (blk);
blk = n_blk;
}
if (dxf->curr_hatch != NULL)
destroy_dxf_hatch (dxf->curr_hatch);
reset_dxf_block (dxf);
free (dxf);
}
static void
save_dxf_filename (gaiaDxfParserPtr dxf, const char *path)
{
int len = strlen (path);
const char *start = path;
const char *stop = path + len - 1;
const char *p = path;
if (dxf->filename != NULL)
free (dxf->filename);
dxf->filename = NULL;
if (path == NULL)
return;
while (*p != '\0')
{
if (*p == '/' || *p == '\\')
start = p + 1;
p++;
}
p = stop;
while (p > path)
{
if (*p == '.')
{
stop = p - 1;
break;
}
p--;
}
if (stop > start)
{
len = stop - start + 1;
dxf->filename = malloc (len + 1);
memset (dxf->filename, '\0', len + 1);
memcpy (dxf->filename, start, len);
}
else
{
dxf->filename = malloc (len + 1);
strcpy (dxf->filename, path);
}
}
static int
gaiaParseDxfFileCommon (const void *p_cache, gaiaDxfParserPtr dxf,
const char *path)
{
int c;
char line[4192];
char *p = line;
FILE *fl;
if (dxf == NULL)
return 0;
save_dxf_filename (dxf, path);
if (dxf->first_layer != NULL || dxf->first_block != NULL)
return 0;
fl = fopen (path, "rb");
if (fl == NULL)
return 0;
while ((c = getc (fl)) != EOF)
{
if (c == '\r')
{
continue;
}
if (c == '\n')
{
*p = '\0';
if (!parse_dxf_line (p_cache, dxf, line))
goto stop;
if (dxf->eof)
{
break;
}
p = line;
continue;
}
*p++ = c;
if (p - line == sizeof (line) - 1)
goto stop;
}
fclose (fl);
return 1;
stop:
fclose (fl);
return 0;
}
GAIAGEO_DECLARE int
gaiaParseDxfFile (gaiaDxfParserPtr dxf, const char *path)
{
return gaiaParseDxfFileCommon (NULL, dxf, path);
}
GAIAGEO_DECLARE int
gaiaParseDxfFile_r (const void *p_cache, gaiaDxfParserPtr dxf, const char *path)
{
return gaiaParseDxfFileCommon (p_cache, dxf, path);
}
#endif