1 /*
2
3 dxf_parser.c -- implements DXF support [parsing]
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 -----------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29
30 Contributor(s):
31
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43
44 */
45
46 /*
47
48 CREDITS:
49
50 inital development of the DXF module has been funded by:
51 Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
52
53 */
54
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <math.h>
59
60 #if defined(_WIN32) && !defined(__MINGW32__)
61 #include "config-msvc.h"
62 #else
63 #include "config.h"
64 #endif
65
66 #include <spatialite/sqlite.h>
67 #include <spatialite/debug.h>
68
69 #include <spatialite/gaiageo.h>
70 #include <spatialite/gg_dxf.h>
71 #include <spatialite.h>
72
73 #include "dxf_private.h"
74
75 #ifndef OMIT_GEOS /* only if GEOS is enabled */
76
77 typedef struct dxf_segment
78 {
79 /* a DXF segment */
80 int valid;
81 double ax;
82 double ay;
83 double az;
84 double bx;
85 double by;
86 double bz;
87 } dxfSegment;
88 typedef dxfSegment *dxfSegmentPtr;
89
90 typedef struct dxf_linked_segments
91 {
92 /* a collection of DXF segments */
93 int count;
94 dxfSegmentPtr segments;
95 } dxfLinkedSegments;
96 typedef dxfLinkedSegments *dxfLinkedSegmentsPtr;
97
98 typedef struct dxf_rings_collection
99 {
100 /* a collection of rings */
101 gaiaDxfPolylinePtr first;
102 gaiaDxfPolylinePtr last;
103 } dxfRingsCollection;
104 typedef dxfRingsCollection *dxfRingsCollectionPtr;
105
106 static gaiaDxfHatchSegmPtr
alloc_dxf_hatch_segm(double x0,double y0,double x1,double y1)107 alloc_dxf_hatch_segm (double x0, double y0, double x1, double y1)
108 {
109 /* allocating and initializing a DXF Hatch Segment object */
110 gaiaDxfHatchSegmPtr segm = malloc (sizeof (gaiaDxfHatchSegm));
111 segm->x0 = x0;
112 segm->y0 = y0;
113 segm->x1 = x1;
114 segm->y1 = y1;
115 segm->next = NULL;
116 return segm;
117 }
118
119 static void
destroy_dxf_hatch_segm(gaiaDxfHatchSegmPtr segm)120 destroy_dxf_hatch_segm (gaiaDxfHatchSegmPtr segm)
121 {
122 /* memory cleanup - destroying a DXF Hatch Segment object */
123 if (segm == NULL)
124 return;
125 free (segm);
126 }
127
128 static gaiaDxfBoundaryPathPtr
alloc_dxf_boundary_path()129 alloc_dxf_boundary_path ()
130 {
131 /* allocating and initializing a DXF Boundary Path object */
132 gaiaDxfBoundaryPathPtr path = malloc (sizeof (gaiaDxfBoundaryPath));
133 path->first = NULL;
134 path->last = NULL;
135 path->next = NULL;
136 return path;
137 }
138
139 static void
insert_dxf_boundary_segm(gaiaDxfBoundaryPathPtr path,gaiaDxfHatchSegmPtr segm)140 insert_dxf_boundary_segm (gaiaDxfBoundaryPathPtr path, gaiaDxfHatchSegmPtr segm)
141 {
142 /* inserting a Segment into a Boundary Path */
143 if (path->first == NULL)
144 path->first = segm;
145 if (path->last != NULL)
146 path->last->next = segm;
147 path->last = segm;
148 }
149
150 static void
destroy_dxf_boundary_path(gaiaDxfBoundaryPathPtr path)151 destroy_dxf_boundary_path (gaiaDxfBoundaryPathPtr path)
152 {
153 /* memory cleanup - destroying a DXF Boundary Path object */
154 gaiaDxfHatchSegmPtr segm;
155 gaiaDxfHatchSegmPtr n_segm;
156 if (path == NULL)
157 return;
158 segm = path->first;
159 while (segm != NULL)
160 {
161 n_segm = segm->next;
162 destroy_dxf_hatch_segm (segm);
163 segm = n_segm;
164 }
165 free (path);
166 }
167
168 static gaiaDxfHatchPtr
alloc_dxf_hatch()169 alloc_dxf_hatch ()
170 {
171 /* allocating and initializing a DXF Pattern Hatch object */
172 gaiaDxfHatchPtr hatch = malloc (sizeof (gaiaDxfHatch));
173 hatch->spacing = 0.0;
174 hatch->angle = 0.0;
175 hatch->base_x = 0.0;
176 hatch->base_y = 0.0;
177 hatch->offset_x = 0.0;
178 hatch->offset_y = 0.0;
179 hatch->first = NULL;
180 hatch->last = NULL;
181 hatch->boundary = NULL;
182 hatch->first_out = NULL;
183 hatch->last_out = NULL;
184 hatch->next = NULL;
185 return hatch;
186 }
187
188 static void
insert_dxf_boundary_path(gaiaDxfHatchPtr hatch,gaiaDxfBoundaryPathPtr path)189 insert_dxf_boundary_path (gaiaDxfHatchPtr hatch, gaiaDxfBoundaryPathPtr path)
190 {
191 /* inserting a Boundary Path into a Hatch */
192 if (hatch->first == NULL)
193 hatch->first = path;
194 if (hatch->last != NULL)
195 hatch->last->next = path;
196 hatch->last = path;
197 }
198
199 static void
insert_dxf_hatch_out(gaiaDxfHatchPtr hatch,gaiaDxfHatchSegmPtr segm)200 insert_dxf_hatch_out (gaiaDxfHatchPtr hatch, gaiaDxfHatchSegmPtr segm)
201 {
202 /* inserting a Segment into a Hatch */
203 if (hatch->first_out == NULL)
204 hatch->first_out = segm;
205 if (hatch->last_out != NULL)
206 hatch->last_out->next = segm;
207 hatch->last_out = segm;
208 }
209
210 static void
destroy_dxf_hatch(gaiaDxfHatchPtr hatch)211 destroy_dxf_hatch (gaiaDxfHatchPtr hatch)
212 {
213 /* memory cleanup - destroying a DXF Pattern Hatch object */
214 gaiaDxfBoundaryPathPtr path;
215 gaiaDxfBoundaryPathPtr n_path;
216 gaiaDxfHatchSegmPtr out;
217 gaiaDxfHatchSegmPtr n_out;
218 if (hatch == NULL)
219 return;
220 path = hatch->first;
221 while (path != NULL)
222 {
223 n_path = path->next;
224 destroy_dxf_boundary_path (path);
225 path = n_path;
226 }
227 if (hatch->boundary != NULL)
228 gaiaFreeGeomColl (hatch->boundary);
229 out = hatch->first_out;
230 while (out != NULL)
231 {
232 n_out = out->next;
233 destroy_dxf_hatch_segm (out);
234 out = n_out;
235 }
236 free (hatch);
237 }
238
239 static int
is_valid_dxf_hatch(gaiaDxfHatchPtr hatch)240 is_valid_dxf_hatch (gaiaDxfHatchPtr hatch)
241 {
242 /* testing for a valid Pattern Hatch */
243 if (hatch->first == NULL)
244 return 0;
245 return 1;
246 }
247
248 static void
apply_vertical_hatch(gaiaGeomCollPtr boundary,gaiaGeomCollPtr geom,double spacing,double base_x)249 apply_vertical_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom,
250 double spacing, double base_x)
251 {
252 /* vertical Pattern Hatch Lines */
253 double min_x = boundary->MinX;
254 double max_x = boundary->MaxX;
255 double min_y = boundary->MinY;
256 double max_y = boundary->MaxY;
257 double x;
258 gaiaLinestringPtr ln;
259 /* inserting all Hatch Lines into the collection */
260 x = base_x + boundary->MinX;
261 while (x < max_x)
262 {
263 ln = gaiaAddLinestringToGeomColl (geom, 2);
264 gaiaSetPoint (ln->Coords, 0, x, min_y);
265 gaiaSetPoint (ln->Coords, 1, x, max_y);
266 x += spacing;
267 }
268 x = base_x + boundary->MinX - spacing;
269 while (x > min_x)
270 {
271 ln = gaiaAddLinestringToGeomColl (geom, 2);
272 gaiaSetPoint (ln->Coords, 0, x, min_y);
273 gaiaSetPoint (ln->Coords, 1, x, max_y);
274 x -= spacing;
275 }
276 }
277
278 static void
apply_horizontal_hatch(gaiaGeomCollPtr boundary,gaiaGeomCollPtr geom,double spacing,double base_y)279 apply_horizontal_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom,
280 double spacing, double base_y)
281 {
282 /* horizontal Pattern Hatch Lines */
283 double min_x = boundary->MinX;
284 double max_x = boundary->MaxX;
285 double min_y = boundary->MinY;
286 double max_y = boundary->MaxY;
287 double y;
288 gaiaLinestringPtr ln;
289 /* inserting all Hatch Lines into the collection */
290 y = base_y + boundary->MinY;
291 while (y < max_y)
292 {
293 ln = gaiaAddLinestringToGeomColl (geom, 2);
294 gaiaSetPoint (ln->Coords, 0, min_x, y);
295 gaiaSetPoint (ln->Coords, 1, max_x, y);
296 y += spacing;
297 }
298 y = base_y + boundary->MinY - spacing;
299 while (y > min_y)
300 {
301 ln = gaiaAddLinestringToGeomColl (geom, 2);
302 gaiaSetPoint (ln->Coords, 0, min_x, y);
303 gaiaSetPoint (ln->Coords, 1, max_x, y);
304 y -= spacing;
305 }
306 }
307
308 static void
apply_hatch(gaiaGeomCollPtr boundary,gaiaGeomCollPtr geom,double angle,double spacing,double base_x,double base_y)309 apply_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom, double angle,
310 double spacing, double base_x, double base_y)
311 {
312 /* ordinary (slant) Pattern Hatch Lines */
313 double min_x = boundary->MinX;
314 double max_x = boundary->MaxX;
315 double min_y = boundary->MinY;
316 double max_y = boundary->MaxY;
317 double ext_x = max_x - min_x;
318 double ext_y = max_y - min_y;
319 double ext = (ext_x > ext_y) ? ext_x : ext_y;
320 double mnx = (ext * 2.0) * -1.0;
321 double mxx = ext * 3.0;
322 double mny = (ext * 2.0) * -1.0;
323 double mxy = ext * 3.0;
324 gaiaLinestringPtr ln;
325 double y;
326 /* inserting all horizontal Hatch Lines into the collection */
327 y = 0.0;
328 while (y < mxy)
329 {
330 ln = gaiaAddLinestringToGeomColl (geom, 2);
331 gaiaSetPoint (ln->Coords, 0, mnx, y);
332 gaiaSetPoint (ln->Coords, 1, mxx, y);
333 y += spacing;
334 }
335 y = 0.0 - spacing;
336 while (y > mny)
337 {
338 ln = gaiaAddLinestringToGeomColl (geom, 2);
339 gaiaSetPoint (ln->Coords, 0, mnx, y);
340 gaiaSetPoint (ln->Coords, 1, mxx, y);
341 y -= spacing;
342 }
343 /* applying the required rotation */
344 gaiaRotateCoords (geom, angle * -1.0);
345 /* translating into base position */
346 gaiaShiftCoords (geom, base_x + min_x, base_y + min_y);
347 }
348
349 static void
create_dxf_hatch_lines(const void * p_cache,gaiaDxfHatchPtr hatch,int srid)350 create_dxf_hatch_lines (const void *p_cache, gaiaDxfHatchPtr hatch, int srid)
351 {
352 /* creating Pattern Hatch lines */
353 gaiaDxfBoundaryPathPtr path;
354 gaiaDxfHatchSegmPtr out;
355 gaiaDxfHatchSegmPtr n_out;
356 gaiaGeomCollPtr geom;
357 gaiaGeomCollPtr result;
358 gaiaGeomCollPtr clipped;
359 double angle;
360 double x0;
361 double y0;
362 double x1;
363 double y1;
364 gaiaLinestringPtr ln;
365
366 if (hatch == NULL)
367 return;
368 if (hatch->boundary != NULL)
369 gaiaFreeGeomColl (hatch->boundary);
370 out = hatch->first_out;
371 while (out != NULL)
372 {
373 /* cleaning all Pattern Hatch lines */
374 n_out = out->next;
375 destroy_dxf_hatch_segm (out);
376 out = n_out;
377 }
378 hatch->boundary = NULL;
379 hatch->first_out = NULL;
380 hatch->last_out = NULL;
381
382 /* creating the Pattern Boundary */
383 geom = gaiaAllocGeomColl ();
384 path = hatch->first;
385 while (path != NULL)
386 {
387 /* inserting Boundary lines */
388 out = path->first;
389 while (out != NULL)
390 {
391 /* inserting all Boundary segments into the collection */
392 ln = gaiaAddLinestringToGeomColl (geom, 2);
393 gaiaSetPoint (ln->Coords, 0, out->x0, out->y0);
394 gaiaSetPoint (ln->Coords, 1, out->x1, out->y1);
395 out = out->next;
396 }
397 path = path->next;
398 }
399 /* attempting to reassemble the Boundary */
400 if (p_cache != NULL)
401 result = gaiaPolygonize_r (p_cache, geom, 0);
402 else
403 result = gaiaPolygonize (geom, 0);
404 gaiaFreeGeomColl (geom);
405 if (result == NULL)
406 return;
407 gaiaMbrGeometry (result);
408 result->Srid = srid;
409 result->DeclaredType = GAIA_MULTIPOLYGON;
410 hatch->boundary = result;
411 if (hatch->spacing == 0.0)
412 {
413 /* no pattern filling, just the boundary */
414 return;
415 }
416 /* normalizing the angle */
417 angle = hatch->angle;
418 while (angle >= 360.0)
419 angle -= 360.0;
420 while (angle <= -360.0)
421 angle += 360;
422 /* preparing the Hatch filling lines */
423 geom = gaiaAllocGeomColl ();
424 if (angle == 90.0 || angle == -90.0 || angle == 270.0 || angle == -270.0)
425 apply_vertical_hatch (result, geom, hatch->spacing, hatch->base_x);
426 else if (angle == 0.0 || angle == 180 || angle == -180)
427 apply_horizontal_hatch (result, geom, hatch->spacing, hatch->base_y);
428 else
429 apply_hatch (result, geom, angle, hatch->spacing, hatch->base_x,
430 hatch->base_y);
431 gaiaMbrGeometry (geom);
432 if (p_cache != NULL)
433 clipped = gaiaGeometryIntersection_r (p_cache, geom, result);
434 else
435 clipped = gaiaGeometryIntersection (geom, result);
436 gaiaFreeGeomColl (geom);
437 if (clipped == NULL)
438 return;
439 ln = clipped->FirstLinestring;
440 while (ln != NULL)
441 {
442 if (ln->Points == 2)
443 {
444 gaiaGetPoint (ln->Coords, 0, &x0, &y0);
445 gaiaGetPoint (ln->Coords, 1, &x1, &y1);
446 n_out = alloc_dxf_hatch_segm (x0, y0, x1, y1);
447 insert_dxf_hatch_out (hatch, n_out);
448 }
449 ln = ln->Next;
450 }
451 gaiaFreeGeomColl (clipped);
452 }
453
454 static gaiaDxfHolePtr
alloc_dxf_hole(int points)455 alloc_dxf_hole (int points)
456 {
457 /* allocating and initializing a DXF Polygon Hole object */
458 int i;
459 gaiaDxfHolePtr hole = malloc (sizeof (gaiaDxfHole));
460 hole->points = points;
461 hole->x = malloc (sizeof (double) * points);
462 hole->y = malloc (sizeof (double) * points);
463 hole->z = malloc (sizeof (double) * points);
464 for (i = 0; i < points; i++)
465 {
466 *(hole->x + i) = 0.0;
467 *(hole->y + i) = 0.0;
468 *(hole->z + i) = 0.0;
469 }
470 hole->next = NULL;
471 return hole;
472 }
473
474 static void
insert_dxf_hole(gaiaDxfPolylinePtr line,gaiaDxfHolePtr hole)475 insert_dxf_hole (gaiaDxfPolylinePtr line, gaiaDxfHolePtr hole)
476 {
477 /* inserting an Hole into a Polygon */
478 if (line->first_hole == NULL)
479 line->first_hole = hole;
480 if (line->last_hole != NULL)
481 line->last_hole->next = hole;
482 line->last_hole = hole;
483 }
484
485 static void
destroy_dxf_hole(gaiaDxfHolePtr hole)486 destroy_dxf_hole (gaiaDxfHolePtr hole)
487 {
488 /* memory cleanup - destroying a DXF Hole object */
489 if (hole == NULL)
490 return;
491 if (hole->x != NULL)
492 free (hole->x);
493 if (hole->y != NULL)
494 free (hole->y);
495 if (hole->z != NULL)
496 free (hole->z);
497 free (hole);
498 }
499
500 static int
force_closure(gaiaDxfPolylinePtr line)501 force_closure (gaiaDxfPolylinePtr line)
502 {
503 /* checking (and eventually forcing) first/last vertex coherency */
504 if (check_unclosed_polyg (line, 1))
505 {
506 /* not properly closed: forcing the last vertex */
507 double *ptr_x;
508 double *ptr_y;
509 double *ptr_z;
510 ptr_x = realloc (line->x, sizeof (double) * (line->points + 1));
511 ptr_y = realloc (line->y, sizeof (double) * (line->points + 1));
512 ptr_z = realloc (line->z, sizeof (double) * (line->points + 1));
513 if (ptr_x == NULL || ptr_y == NULL || ptr_z == NULL)
514 {
515 /* some unexpected error happened - giving up */
516 if (ptr_x == NULL)
517 free (ptr_x);
518 if (ptr_y == NULL)
519 free (ptr_y);
520 if (ptr_z == NULL)
521 free (ptr_z);
522 return 0;
523 }
524 line->x = ptr_x;
525 line->y = ptr_y;
526 line->z = ptr_z;
527 *(line->x + line->points) = *(line->x + 0);
528 *(line->y + line->points) = *(line->y + 0);
529 *(line->z + line->points) = *(line->z + 0);
530 line->points += 1;
531 }
532 return 1;
533 }
534
535 static void
linked_rings(const void * p_cache,gaiaDxfPolylinePtr line)536 linked_rings (const void *p_cache, gaiaDxfPolylinePtr line)
537 {
538 /* attempt to identify linked Polygon rings */
539 int i;
540 int i2;
541 int match = 0;
542 double x;
543 double y;
544 double z;
545 gaiaDxfHolePtr hole;
546 dxfLinkedSegmentsPtr coll;
547 dxfSegmentPtr seg;
548 dxfSegmentPtr seg2;
549 gaiaGeomCollPtr geom;
550 gaiaGeomCollPtr result;
551 gaiaPolygonPtr pg;
552 gaiaRingPtr rng;
553 int pgs;
554 int ok;
555
556 if (line == NULL)
557 return;
558 if (line->points <= 0)
559 return;
560 if (line->is_closed == 0)
561 return;
562
563 if (!force_closure (line))
564 return;
565
566 coll = malloc (sizeof (dxfLinkedSegments));
567 coll->count = line->points - 1;
568 coll->segments = malloc (sizeof (dxfSegment) * coll->count);
569 x = *(line->x + 0);
570 y = *(line->y + 0);
571 z = *(line->z + 0);
572 for (i2 = 0, i = 1; i < line->points; i++, i2++)
573 {
574 /* initializing all segments */
575 seg = &(coll->segments[i2]);
576 seg->valid = 1;
577 seg->ax = x;
578 seg->ay = y;
579 seg->az = z;
580 x = *(line->x + i);
581 y = *(line->y + i);
582 z = *(line->z + i);
583 seg->bx = x;
584 seg->by = y;
585 seg->bz = z;
586 }
587
588 for (i = 0; i < coll->count - 1; i++)
589 {
590 /* testing for linked polygon holes */
591 seg = &(coll->segments[i]);
592 if (seg->valid == 0)
593 continue;
594 for (i2 = i + 1; i2 < coll->count; i2++)
595 {
596 seg2 = &(coll->segments[i2]);
597 if (seg2->valid == 0)
598 continue;
599 if ((seg->ax == seg2->ax && seg->ay == seg2->ay
600 && seg->az == seg2->az && seg->bx == seg2->bx
601 && seg->by == seg2->by && seg->bz == seg2->bz)
602 || (seg->ax == seg2->bx && seg->ay == seg2->by
603 && seg->az == seg2->bz && seg->bx == seg2->ax
604 && seg->by == seg2->ay && seg->bz == seg2->az))
605 {
606 /* found a linked segment */
607 seg->valid = 0;
608 seg2->valid = 0;
609 match = 1;
610 }
611 }
612 }
613
614 if (match == 0)
615 {
616 /* no link segment was found - quitting */
617 free (coll->segments);
618 free (coll);
619 return;
620 }
621
622 /* building a candidate geometry (multilinestring) */
623 geom = gaiaAllocGeomCollXYZ ();
624 for (i = 0; i < coll->count; i++)
625 {
626 seg = &(coll->segments[i]);
627 if (seg->valid)
628 {
629 /* inserting a valid segment into the collection */
630 gaiaLinestringPtr ln = gaiaAddLinestringToGeomColl (geom, 2);
631 gaiaSetPointXYZ (ln->Coords, 0, seg->ax, seg->ay, seg->az);
632 gaiaSetPointXYZ (ln->Coords, 1, seg->bx, seg->by, seg->bz);
633 }
634 }
635 /* freeing the linked segments list */
636 free (coll->segments);
637 free (coll);
638
639 /* attempting to reassemble a polygon */
640 if (p_cache != NULL)
641 result = gaiaPolygonize_r (p_cache, geom, 0);
642 else
643 result = gaiaPolygonize (geom, 0);
644 gaiaFreeGeomColl (geom);
645 if (result == NULL)
646 return;
647
648 /* checking the returned polygon for validity */
649 pgs = 0;
650 ok = 1;
651 pg = result->FirstPolygon;
652 while (pg != NULL)
653 {
654 pgs++;
655 if (pg->NumInteriors == 0)
656 ok = 0;
657 pg = pg->Next;
658 }
659 if (ok == 1 && pgs == 1)
660 {
661 /* found a valid Polygon with internal holes(s) */
662 pg = result->FirstPolygon;
663 rng = pg->Exterior;
664 /* rebuilding the exterior ring */
665 free (line->x);
666 free (line->y);
667 free (line->z);
668 line->points = rng->Points;
669 line->x = malloc (sizeof (double) * line->points);
670 line->y = malloc (sizeof (double) * line->points);
671 line->z = malloc (sizeof (double) * line->points);
672 for (i = 0; i < line->points; i++)
673 {
674 /* setting the exterior ring points */
675 gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
676 *(line->x + i) = x;
677 *(line->y + i) = y;
678 *(line->z + i) = z;
679 }
680 for (i2 = 0; i2 < pg->NumInteriors; i2++)
681 {
682 /* saving the Holes */
683 rng = pg->Interiors + i2;
684 hole = alloc_dxf_hole (rng->Points);
685 insert_dxf_hole (line, hole);
686 for (i = 0; i < hole->points; i++)
687 {
688 /* setting the interior ring points */
689 gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
690 *(hole->x + i) = x;
691 *(hole->y + i) = y;
692 *(hole->z + i) = z;
693 }
694 }
695 }
696 gaiaFreeGeomColl (result);
697 /* forcing the closure flag */
698 line->is_closed = 1;
699 }
700
701 static void
insert_dxf_hatch(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfHatchPtr hatch)702 insert_dxf_hatch (gaiaDxfParserPtr dxf, const char *layer_name,
703 gaiaDxfHatchPtr hatch)
704 {
705 /* inserting a HATCH object into the appropriate Layer */
706 gaiaDxfLayerPtr lyr = dxf->first_layer;
707 while (lyr != NULL)
708 {
709 if (strcmp (lyr->layer_name, layer_name) == 0)
710 {
711 /* found the matching Layer */
712 if (lyr->first_hatch == NULL)
713 lyr->first_hatch = hatch;
714 if (lyr->last_hatch != NULL)
715 lyr->last_hatch->next = hatch;
716 lyr->last_hatch = hatch;
717 return;
718 }
719 lyr = lyr->next;
720 }
721 destroy_dxf_hatch (hatch);
722 }
723
724 static void
insert_dxf_block_hatch(gaiaDxfParserPtr dxf,gaiaDxfHatchPtr hatch)725 insert_dxf_block_hatch (gaiaDxfParserPtr dxf, gaiaDxfHatchPtr hatch)
726 {
727 /* inserting a HATCH object into the current Block */
728 if (dxf->curr_block.first_hatch == NULL)
729 dxf->curr_block.first_hatch = hatch;
730 if (dxf->curr_block.last_hatch != NULL)
731 dxf->curr_block.last_hatch->next = hatch;
732 dxf->curr_block.last_hatch = hatch;
733 }
734
735 static gaiaDxfExtraAttrPtr
alloc_dxf_extra()736 alloc_dxf_extra ()
737 {
738 /* allocating and initializing a DXF Extra Attribute object */
739 gaiaDxfExtraAttrPtr ext = malloc (sizeof (gaiaDxfExtraAttr));
740 ext->key = NULL;
741 ext->value = NULL;
742 ext->next = NULL;
743 return ext;
744 }
745
746 static gaiaDxfExtraAttrPtr
clone_dxf_extra(gaiaDxfExtraAttrPtr org)747 clone_dxf_extra (gaiaDxfExtraAttrPtr org)
748 {
749 /* cloning a DXF Extra Attribute object */
750 int len;
751 gaiaDxfExtraAttrPtr ext = malloc (sizeof (gaiaDxfExtraAttr));
752 len = strlen (org->key);
753 ext->key = malloc (len + 1);
754 strcpy (ext->key, org->key);
755 len = strlen (org->value);
756 ext->value = malloc (len + 1);
757 strcpy (ext->value, org->value);
758 ext->next = NULL;
759 return ext;
760 }
761
762 static void
destroy_dxf_extra(gaiaDxfExtraAttrPtr ext)763 destroy_dxf_extra (gaiaDxfExtraAttrPtr ext)
764 {
765 /* memory cleanup - destroying a DXF Extra Attribute object */
766 if (ext == NULL)
767 return;
768 if (ext->key != NULL)
769 free (ext->key);
770 if (ext->value != NULL)
771 free (ext->value);
772 free (ext);
773 }
774
775 static gaiaDxfTextPtr
alloc_dxf_text(const char * label,double x,double y,double z,double angle)776 alloc_dxf_text (const char *label, double x, double y, double z, double angle)
777 {
778 /* allocating and initializing a DXF Text object */
779 int len;
780 gaiaDxfTextPtr txt = malloc (sizeof (gaiaDxfText));
781 len = strlen (label);
782 txt->label = malloc (len + 1);
783 strcpy (txt->label, label);
784 txt->x = x;
785 txt->y = y;
786 txt->z = z;
787 txt->angle = angle;
788 txt->first = NULL;
789 txt->last = NULL;
790 txt->next = NULL;
791 return txt;
792 }
793
794 static void
destroy_dxf_text(gaiaDxfTextPtr txt)795 destroy_dxf_text (gaiaDxfTextPtr txt)
796 {
797 /* memory cleanup - destroying a DXF Text object */
798 gaiaDxfExtraAttrPtr ext;
799 gaiaDxfExtraAttrPtr n_ext;
800 if (txt == NULL)
801 return;
802 if (txt->label != NULL)
803 free (txt->label);
804 ext = txt->first;
805 while (ext != NULL)
806 {
807 n_ext = ext->next;
808 destroy_dxf_extra (ext);
809 ext = n_ext;
810 }
811 free (txt);
812 }
813
814 static int
is_3d_text(gaiaDxfTextPtr txt)815 is_3d_text (gaiaDxfTextPtr txt)
816 {
817 /* testing if it's really a 3D Text */
818 if (txt->z == 0.0)
819 return 0;
820 return 1;
821 }
822
823 static void
insert_dxf_text(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfTextPtr txt)824 insert_dxf_text (gaiaDxfParserPtr dxf, const char *layer_name,
825 gaiaDxfTextPtr txt)
826 {
827 /* inserting a TEXT object into the appropriate Layer */
828 gaiaDxfLayerPtr lyr = dxf->first_layer;
829 while (lyr != NULL)
830 {
831 if (strcmp (lyr->layer_name, layer_name) == 0)
832 {
833 /* found the matching Layer */
834 if (lyr->first_text == NULL)
835 lyr->first_text = txt;
836 if (lyr->last_text != NULL)
837 lyr->last_text->next = txt;
838 lyr->last_text = txt;
839 if (dxf->force_dims == GAIA_DXF_FORCE_2D
840 || dxf->force_dims == GAIA_DXF_FORCE_3D)
841 ;
842 else
843 {
844 if (is_3d_text (txt))
845 lyr->is3Dtext = 1;
846 }
847 txt->first = dxf->first_ext;
848 txt->last = dxf->last_ext;
849 dxf->first_ext = NULL;
850 dxf->last_ext = NULL;
851 if (txt->first != NULL)
852 lyr->hasExtraText = 1;
853 return;
854 }
855 lyr = lyr->next;
856 }
857 destroy_dxf_text (txt);
858 }
859
860 static void
insert_dxf_block_text(gaiaDxfParserPtr dxf,gaiaDxfTextPtr txt)861 insert_dxf_block_text (gaiaDxfParserPtr dxf, gaiaDxfTextPtr txt)
862 {
863 /* inserting a TEXT object into the current Block */
864 if (dxf->curr_block.first_text == NULL)
865 dxf->curr_block.first_text = txt;
866 if (dxf->curr_block.last_text != NULL)
867 dxf->curr_block.last_text->next = txt;
868 dxf->curr_block.last_text = txt;
869 if (dxf->force_dims == GAIA_DXF_FORCE_2D
870 || dxf->force_dims == GAIA_DXF_FORCE_3D)
871 ;
872 else
873 {
874 if (is_3d_text (txt))
875 dxf->curr_block.is3Dtext = 1;
876 }
877 }
878
879 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)880 alloc_dxf_insert (const char *block_id, double x, double y, double z,
881 double scale_x, double scale_y, double scale_z, double angle)
882 {
883 /* allocating and initializing a DXF Insertt object */
884 int len;
885 gaiaDxfInsertPtr ins = malloc (sizeof (gaiaDxfInsert));
886 len = strlen (block_id);
887 ins->block_id = malloc (len + 1);
888 strcpy (ins->block_id, block_id);
889 ins->x = x;
890 ins->y = y;
891 ins->z = z;
892 ins->scale_x = scale_x;
893 ins->scale_y = scale_y;
894 ins->scale_z = scale_z;
895 ins->angle = angle;
896 ins->hasText = 0;
897 ins->hasPoint = 0;
898 ins->hasLine = 0;
899 ins->hasPolyg = 0;
900 ins->hasHatch = 0;
901 ins->is3Dtext = 0;
902 ins->is3Dpoint = 0;
903 ins->is3Dline = 0;
904 ins->is3Dpolyg = 0;
905 ins->first = NULL;
906 ins->last = NULL;
907 ins->next = NULL;
908 return ins;
909 }
910
911 static gaiaDxfInsertPtr
clone_dxf_insert(gaiaDxfInsertPtr org)912 clone_dxf_insert (gaiaDxfInsertPtr org)
913 {
914 /* cloning a DXF Insertt object */
915 gaiaDxfExtraAttrPtr ext_org;
916 gaiaDxfExtraAttrPtr ext;
917 int len;
918 gaiaDxfInsertPtr ins = malloc (sizeof (gaiaDxfInsert));
919 len = strlen (org->block_id);
920 ins->block_id = malloc (len + 1);
921 strcpy (ins->block_id, org->block_id);
922 ins->x = org->x;
923 ins->y = org->y;
924 ins->z = org->z;
925 ins->scale_x = org->scale_x;
926 ins->scale_y = org->scale_y;
927 ins->scale_z = org->scale_z;
928 ins->angle = org->angle;
929 ins->hasText = org->hasText;
930 ins->hasPoint = org->hasPoint;
931 ins->hasLine = org->hasLine;
932 ins->hasPolyg = org->hasPolyg;
933 ins->hasHatch = org->hasHatch;
934 ins->is3Dtext = org->is3Dtext;
935 ins->is3Dpoint = org->is3Dpoint;
936 ins->is3Dline = org->is3Dline;
937 ins->is3Dpolyg = org->is3Dpolyg;
938 ins->first = NULL;
939 ins->last = NULL;
940 ext_org = org->first;
941 while (ext_org != NULL)
942 {
943 ext = clone_dxf_extra (ext_org);
944 if (ins->first == NULL)
945 ins->first = ext;
946 if (ins->last != NULL)
947 ins->last->next = ext;
948 ins->last = ext;
949 ext_org = ext_org->next;
950 }
951 ins->next = NULL;
952 return ins;
953 }
954
955 static void
destroy_dxf_insert(gaiaDxfInsertPtr ins)956 destroy_dxf_insert (gaiaDxfInsertPtr ins)
957 {
958 /* memory cleanup - destroying a DXF Insert object */
959 gaiaDxfExtraAttrPtr ext;
960 gaiaDxfExtraAttrPtr n_ext;
961 if (ins == NULL)
962 return;
963 if (ins->block_id != NULL)
964 free (ins->block_id);
965 ext = ins->first;
966 while (ext != NULL)
967 {
968 n_ext = ext->next;
969 destroy_dxf_extra (ext);
970 ext = n_ext;
971 }
972 free (ins);
973 }
974
975 static void
insert_dxf_insert(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfInsertPtr ins)976 insert_dxf_insert (gaiaDxfParserPtr dxf, const char *layer_name,
977 gaiaDxfInsertPtr ins)
978 {
979 /* inserting an INSERT object into the appropriate Layer */
980 gaiaDxfLayerPtr lyr = dxf->first_layer;
981 while (lyr != NULL)
982 {
983 if (strcmp (lyr->layer_name, layer_name) == 0)
984 {
985 /* found the matching Layer */
986 ins->first = dxf->first_ext;
987 ins->last = dxf->last_ext;
988 dxf->first_ext = NULL;
989 dxf->last_ext = NULL;
990 if (ins->hasText)
991 {
992 /* indirect Text reference */
993 gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
994 if (lyr->first_ins_text == NULL)
995 lyr->first_ins_text = ins2;
996 if (lyr->last_ins_text != NULL)
997 lyr->last_ins_text->next = ins2;
998 lyr->last_ins_text = ins2;
999 if (ins2->is3Dtext)
1000 lyr->is3DinsText = 1;
1001 if (ins2->first != NULL)
1002 lyr->hasExtraInsText = 1;
1003 }
1004 if (ins->hasPoint)
1005 {
1006 /* indirect Point reference */
1007 gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
1008 if (lyr->first_ins_point == NULL)
1009 lyr->first_ins_point = ins2;
1010 if (lyr->last_ins_point != NULL)
1011 lyr->last_ins_point->next = ins2;
1012 lyr->last_ins_point = ins2;
1013 if (ins2->is3Dpoint)
1014 lyr->is3DinsPoint = 1;
1015 if (ins2->first != NULL)
1016 lyr->hasExtraInsPoint = 1;
1017 }
1018 if (ins->hasLine)
1019 {
1020 /* indirect Polyline (Linestring) reference */
1021 gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
1022 if (lyr->first_ins_line == NULL)
1023 lyr->first_ins_line = ins2;
1024 if (lyr->last_ins_line != NULL)
1025 lyr->last_ins_line->next = ins2;
1026 lyr->last_ins_line = ins2;
1027 if (ins2->is3Dline)
1028 lyr->is3DinsLine = 1;
1029 if (ins2->first != NULL)
1030 lyr->hasExtraInsLine = 1;
1031 }
1032 if (ins->hasPolyg)
1033 {
1034 /* indirect Polyline (Polygon) reference */
1035 gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
1036 if (lyr->first_ins_polyg == NULL)
1037 lyr->first_ins_polyg = ins2;
1038 if (lyr->last_ins_polyg != NULL)
1039 lyr->last_ins_polyg->next = ins2;
1040 lyr->last_ins_polyg = ins2;
1041 if (ins2->is3Dpolyg)
1042 lyr->is3DinsPolyg = 1;
1043 if (ins2->first != NULL)
1044 lyr->hasExtraInsPolyg = 1;
1045 }
1046 destroy_dxf_insert (ins);
1047 return;
1048 }
1049 lyr = lyr->next;
1050 }
1051 destroy_dxf_insert (ins);
1052 }
1053
1054 static gaiaDxfPointPtr
alloc_dxf_point(double x,double y,double z)1055 alloc_dxf_point (double x, double y, double z)
1056 {
1057 /* allocating and initializing a DXF Point object */
1058 gaiaDxfPointPtr pt = malloc (sizeof (gaiaDxfPoint));
1059 pt->x = x;
1060 pt->y = y;
1061 pt->z = z;
1062 pt->next = NULL;
1063 pt->first = NULL;
1064 pt->last = NULL;
1065 return pt;
1066 }
1067
1068 static void
destroy_dxf_point(gaiaDxfPointPtr pt)1069 destroy_dxf_point (gaiaDxfPointPtr pt)
1070 {
1071 /* memory cleanup - destroying a DXF Point object */
1072 gaiaDxfExtraAttrPtr ext;
1073 gaiaDxfExtraAttrPtr n_ext;
1074 if (pt == NULL)
1075 return;
1076 ext = pt->first;
1077 while (ext != NULL)
1078 {
1079 n_ext = ext->next;
1080 destroy_dxf_extra (ext);
1081 ext = n_ext;
1082 }
1083 free (pt);
1084 }
1085
1086 static int
is_3d_point(gaiaDxfPointPtr pt)1087 is_3d_point (gaiaDxfPointPtr pt)
1088 {
1089 /* testing if it's really a 3D Point */
1090 if (pt->z == 0.0)
1091 return 0;
1092 return 1;
1093 }
1094
1095 static void
insert_dxf_point(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfPointPtr pt)1096 insert_dxf_point (gaiaDxfParserPtr dxf, const char *layer_name,
1097 gaiaDxfPointPtr pt)
1098 {
1099 /* inserting a POINT object into the appropriate Layer */
1100 gaiaDxfLayerPtr lyr = dxf->first_layer;
1101 while (lyr != NULL)
1102 {
1103 if (strcmp (lyr->layer_name, layer_name) == 0)
1104 {
1105 /* found the matching Layer */
1106 if (lyr->first_point == NULL)
1107 lyr->first_point = pt;
1108 if (lyr->last_point != NULL)
1109 lyr->last_point->next = pt;
1110 lyr->last_point = pt;
1111 if (dxf->force_dims == GAIA_DXF_FORCE_2D
1112 || dxf->force_dims == GAIA_DXF_FORCE_3D)
1113 ;
1114 else
1115 {
1116 if (is_3d_point (pt))
1117 lyr->is3Dpoint = 1;
1118 }
1119 pt->first = dxf->first_ext;
1120 pt->last = dxf->last_ext;
1121 dxf->first_ext = NULL;
1122 dxf->last_ext = NULL;
1123 if (pt->first != NULL)
1124 lyr->hasExtraPoint = 1;
1125 return;
1126 }
1127 lyr = lyr->next;
1128 }
1129 destroy_dxf_point (pt);
1130 }
1131
1132 static void
insert_dxf_block_point(gaiaDxfParserPtr dxf,gaiaDxfPointPtr pt)1133 insert_dxf_block_point (gaiaDxfParserPtr dxf, gaiaDxfPointPtr pt)
1134 {
1135 /* inserting a POINT object into the current Block */
1136 if (dxf->curr_block.first_point == NULL)
1137 dxf->curr_block.first_point = pt;
1138 if (dxf->curr_block.last_point != NULL)
1139 dxf->curr_block.last_point->next = pt;
1140 dxf->curr_block.last_point = pt;
1141 if (dxf->force_dims == GAIA_DXF_FORCE_2D
1142 || dxf->force_dims == GAIA_DXF_FORCE_3D)
1143 ;
1144 else
1145 {
1146 if (is_3d_point (pt))
1147 dxf->curr_block.is3Dpoint = 1;
1148 }
1149 }
1150
1151 static gaiaDxfPolylinePtr
alloc_dxf_polyline(int is_closed,int points)1152 alloc_dxf_polyline (int is_closed, int points)
1153 {
1154 /* allocating and initializing a DXF Polyline object */
1155 int i;
1156 gaiaDxfPolylinePtr ln = malloc (sizeof (gaiaDxfPolyline));
1157 ln->is_closed = is_closed;
1158 ln->points = points;
1159 ln->x = malloc (sizeof (double) * points);
1160 ln->y = malloc (sizeof (double) * points);
1161 ln->z = malloc (sizeof (double) * points);
1162 for (i = 0; i < points; i++)
1163 {
1164 *(ln->x + i) = 0.0;
1165 *(ln->y + i) = 0.0;
1166 *(ln->z + i) = 0.0;
1167 }
1168 ln->first_hole = NULL;
1169 ln->last_hole = NULL;
1170 ln->first = NULL;
1171 ln->last = NULL;
1172 ln->next = NULL;
1173 return ln;
1174 }
1175
1176 static gaiaDxfPolylinePtr
alloc_dxf_line(double x0,double y0,double z0,double x1,double y1,double z1)1177 alloc_dxf_line (double x0, double y0, double z0, double x1, double y1,
1178 double z1)
1179 {
1180 /* allocating and initializing a DXF Line object */
1181 gaiaDxfPolylinePtr ln = malloc (sizeof (gaiaDxfPolyline));
1182 ln->is_closed = 0;
1183 ln->points = 2;
1184 ln->x = malloc (sizeof (double) * 2);
1185 ln->y = malloc (sizeof (double) * 2);
1186 ln->z = malloc (sizeof (double) * 2);
1187 *(ln->x + 0) = x0;
1188 *(ln->y + 0) = y0;
1189 *(ln->z + 0) = z0;
1190 *(ln->x + 1) = x1;
1191 *(ln->y + 1) = y1;
1192 *(ln->z + 1) = z1;
1193 ln->first_hole = NULL;
1194 ln->last_hole = NULL;
1195 ln->first = NULL;
1196 ln->last = NULL;
1197 ln->next = NULL;
1198 return ln;
1199 }
1200
1201 static void
destroy_dxf_polyline(gaiaDxfPolylinePtr ln)1202 destroy_dxf_polyline (gaiaDxfPolylinePtr ln)
1203 {
1204 /* memory cleanup - destroying a DXF Polyline object */
1205 gaiaDxfExtraAttrPtr ext;
1206 gaiaDxfExtraAttrPtr n_ext;
1207 gaiaDxfHolePtr hole;
1208 gaiaDxfHolePtr n_hole;
1209 if (ln == NULL)
1210 return;
1211 if (ln->x != NULL)
1212 free (ln->x);
1213 if (ln->y != NULL)
1214 free (ln->y);
1215 if (ln->z != NULL)
1216 free (ln->z);
1217 ext = ln->first;
1218 while (ext != NULL)
1219 {
1220 n_ext = ext->next;
1221 destroy_dxf_extra (ext);
1222 ext = n_ext;
1223 }
1224 hole = ln->first_hole;
1225 while (hole != NULL)
1226 {
1227 n_hole = hole->next;
1228 destroy_dxf_hole (hole);
1229 hole = n_hole;
1230 }
1231 free (ln);
1232 }
1233
1234 static int
is_3d_line(gaiaDxfPolylinePtr ln)1235 is_3d_line (gaiaDxfPolylinePtr ln)
1236 {
1237 /* testing if it's really a 3D Polyline */
1238 gaiaDxfHolePtr hole;
1239 int i;
1240 for (i = 0; i < ln->points; i++)
1241 {
1242 if (*(ln->z + i) != 0.0)
1243 return 1;
1244 }
1245 hole = ln->first_hole;
1246 while (hole != NULL)
1247 {
1248 for (i = 0; i < hole->points; i++)
1249 {
1250 if (*(hole->z + i) != 0.0)
1251 return 1;
1252 }
1253 }
1254 return 0;
1255 }
1256
1257 static dxfRingsCollectionPtr
alloc_dxf_rings()1258 alloc_dxf_rings ()
1259 {
1260 /* allocating an empty Rings Collection */
1261 dxfRingsCollectionPtr coll = malloc (sizeof (dxfRingsCollection));
1262 coll->first = NULL;
1263 coll->last = NULL;
1264 return coll;
1265 }
1266
1267 static void
destroy_dxf_rings(dxfRingsCollectionPtr coll)1268 destroy_dxf_rings (dxfRingsCollectionPtr coll)
1269 {
1270 /* memory cleanup - destroying a Rings Collection */
1271 gaiaDxfPolylinePtr ln;
1272 gaiaDxfPolylinePtr n_ln;
1273 if (coll == NULL)
1274 return;
1275 ln = coll->first;
1276 while (ln != NULL)
1277 {
1278 n_ln = ln->next;
1279 destroy_dxf_polyline (ln);
1280 ln = n_ln;
1281 }
1282 free (coll);
1283 }
1284
1285 static void
insert_dxf_ring(dxfRingsCollectionPtr coll,gaiaDxfPolylinePtr line,int start,int end)1286 insert_dxf_ring (dxfRingsCollectionPtr coll, gaiaDxfPolylinePtr line, int start,
1287 int end)
1288 {
1289 /* inserting a Ring into the collection */
1290 int i;
1291 int i2;
1292 int points = end - start + 1;
1293 gaiaDxfPolylinePtr out = alloc_dxf_polyline (1, points);
1294 for (i2 = 0, i = start; i <= end; i++, i2++)
1295 {
1296 *(out->x + i2) = *(line->x + i);
1297 *(out->y + i2) = *(line->y + i);
1298 *(out->z + i2) = *(line->z + i);
1299 }
1300 if (coll->first == NULL)
1301 coll->first = out;
1302 if (coll->last != NULL)
1303 coll->last->next = out;
1304 coll->last = out;
1305 }
1306
1307 static void
unlinked_rings(const void * p_cache,gaiaDxfPolylinePtr line)1308 unlinked_rings (const void *p_cache, gaiaDxfPolylinePtr line)
1309 {
1310 /* attempt to identify unlinked Polygon rings */
1311 int invalid = 0;
1312 int start;
1313 int count;
1314 double x;
1315 double y;
1316 double z;
1317 int i;
1318 int i2;
1319 gaiaDxfHolePtr hole;
1320 dxfRingsCollectionPtr coll;
1321 gaiaDxfPolylinePtr ring;
1322 gaiaGeomCollPtr geom;
1323 gaiaGeomCollPtr result;
1324 gaiaPolygonPtr pg;
1325 gaiaRingPtr rng;
1326 int pgs;
1327 int ok;
1328
1329 if (line == NULL)
1330 return;
1331 if (line->points <= 0)
1332 return;
1333 if (line->is_closed == 0)
1334 return;
1335
1336 if (!force_closure (line))
1337 return;
1338
1339 coll = alloc_dxf_rings ();
1340 start = 0;
1341 while (start < line->points - 1)
1342 {
1343 /* looping on candidate rings */
1344 x = *(line->x + start);
1345 y = *(line->y + start);
1346 z = *(line->z + start);
1347 invalid = 1;
1348 for (i = start + 1; i < line->points; i++)
1349 {
1350 if (*(line->x + i) == x && *(line->y + i) == y
1351 && *(line->z + i) == z)
1352 {
1353 insert_dxf_ring (coll, line, start, i);
1354 start = i + 1;
1355 invalid = 0;
1356 break;
1357 }
1358 }
1359 if (invalid)
1360 break;
1361 }
1362
1363 count = 0;
1364 ring = coll->first;
1365 while (ring != NULL)
1366 {
1367 count++;
1368 ring = ring->next;
1369 }
1370 if (count < 2)
1371 invalid = 1;
1372 if (invalid)
1373 {
1374 /* no unlinked rings were found - quitting */
1375 destroy_dxf_rings (coll);
1376 return;
1377 }
1378
1379 /* building a candidate geometry (multilinestring) */
1380 geom = gaiaAllocGeomCollXYZ ();
1381 ring = coll->first;
1382 while (ring != NULL)
1383 {
1384 /* inserting a ring into the collection */
1385 gaiaLinestringPtr ln =
1386 gaiaAddLinestringToGeomColl (geom, ring->points);
1387 for (i = 0; i < ring->points; i++)
1388 {
1389 gaiaSetPointXYZ (ln->Coords, i, *(ring->x + i), *(ring->y + i),
1390 *(ring->z + i));
1391 }
1392 ring = ring->next;
1393 }
1394 /* freeing the rings list */
1395 destroy_dxf_rings (coll);
1396
1397 /* attempting to reassemble a polygon */
1398 if (p_cache != NULL)
1399 result = gaiaPolygonize_r (p_cache, geom, 0);
1400 else
1401 result = gaiaPolygonize (geom, 0);
1402 gaiaFreeGeomColl (geom);
1403 if (result == NULL)
1404 return;
1405
1406 /* checking the returned polygon for validity */
1407 pgs = 0;
1408 ok = 1;
1409 pg = result->FirstPolygon;
1410 while (pg != NULL)
1411 {
1412 pgs++;
1413 if (pg->NumInteriors == 0)
1414 ok = 0;
1415 pg = pg->Next;
1416 }
1417 if (ok == 1 && pgs == 1)
1418 {
1419 /* found a valid Polygon with internal holes(s) */
1420 pg = result->FirstPolygon;
1421 rng = pg->Exterior;
1422 /* rebuilding the exterior ring */
1423 free (line->x);
1424 free (line->y);
1425 free (line->z);
1426 line->points = rng->Points;
1427 line->x = malloc (sizeof (double) * line->points);
1428 line->y = malloc (sizeof (double) * line->points);
1429 line->z = malloc (sizeof (double) * line->points);
1430 for (i = 0; i < line->points; i++)
1431 {
1432 /* setting the exterior ring points */
1433 gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
1434 *(line->x + i) = x;
1435 *(line->y + i) = y;
1436 *(line->z + i) = z;
1437 }
1438 for (i2 = 0; i2 < pg->NumInteriors; i2++)
1439 {
1440 /* saving the Holes */
1441 rng = pg->Interiors + i2;
1442 hole = alloc_dxf_hole (rng->Points);
1443 insert_dxf_hole (line, hole);
1444 for (i = 0; i < hole->points; i++)
1445 {
1446 /* setting the interior ring points */
1447 gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
1448 *(hole->x + i) = x;
1449 *(hole->y + i) = y;
1450 *(hole->z + i) = z;
1451 }
1452 }
1453 }
1454 gaiaFreeGeomColl (result);
1455 /* forcing the closure flag */
1456 line->is_closed = 1;
1457 }
1458
1459 static void
insert_dxf_polyline(const void * p_cache,gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfPolylinePtr ln)1460 insert_dxf_polyline (const void *p_cache, gaiaDxfParserPtr dxf,
1461 const char *layer_name, gaiaDxfPolylinePtr ln)
1462 {
1463 /* inserting a POLYLINE object into the appropriate Layer */
1464 gaiaDxfLayerPtr lyr = dxf->first_layer;
1465 while (lyr != NULL)
1466 {
1467 if (strcmp (lyr->layer_name, layer_name) == 0)
1468 {
1469 /* found the matching Layer */
1470 if (dxf->linked_rings)
1471 linked_rings (p_cache, ln);
1472 if (dxf->unlinked_rings)
1473 unlinked_rings (p_cache, ln);
1474 if (ln->is_closed)
1475 {
1476 /* it's a Ring */
1477 if (lyr->first_polyg == NULL)
1478 lyr->first_polyg = ln;
1479 if (lyr->last_polyg != NULL)
1480 lyr->last_polyg->next = ln;
1481 lyr->last_polyg = ln;
1482 if (dxf->force_dims == GAIA_DXF_FORCE_2D
1483 || dxf->force_dims == GAIA_DXF_FORCE_3D)
1484 ;
1485 else
1486 {
1487 if (is_3d_line (ln))
1488 lyr->is3Dpolyg = 1;
1489 }
1490 }
1491 else
1492 {
1493 /* it's a Linestring */
1494 if (lyr->first_line == NULL)
1495 lyr->first_line = ln;
1496 if (lyr->last_line != NULL)
1497 lyr->last_line->next = ln;
1498 lyr->last_line = ln;
1499 if (dxf->force_dims == GAIA_DXF_FORCE_2D
1500 || dxf->force_dims == GAIA_DXF_FORCE_3D)
1501 ;
1502 else
1503 {
1504 if (is_3d_line (ln))
1505 lyr->is3Dline = 1;
1506 }
1507 }
1508 ln->first = dxf->first_ext;
1509 ln->last = dxf->last_ext;
1510 dxf->first_ext = NULL;
1511 dxf->last_ext = NULL;
1512 if (ln->is_closed && ln->first != NULL)
1513 lyr->hasExtraPolyg = 1;
1514 if (ln->is_closed == 0 && ln->first != NULL)
1515 lyr->hasExtraLine = 1;
1516 return;
1517 }
1518 lyr = lyr->next;
1519 }
1520 destroy_dxf_polyline (ln);
1521 }
1522
1523 static void
insert_dxf_block_polyline(const void * p_cache,gaiaDxfParserPtr dxf,gaiaDxfPolylinePtr ln)1524 insert_dxf_block_polyline (const void *p_cache, gaiaDxfParserPtr dxf,
1525 gaiaDxfPolylinePtr ln)
1526 {
1527 /* inserting a POLYLINE object into the current Block */
1528 if (dxf->linked_rings)
1529 linked_rings (p_cache, ln);
1530 if (dxf->unlinked_rings)
1531 unlinked_rings (p_cache, ln);
1532 if (ln->is_closed)
1533 {
1534 /* it's a Ring */
1535 if (dxf->curr_block.first_polyg == NULL)
1536 dxf->curr_block.first_polyg = ln;
1537 if (dxf->curr_block.last_polyg != NULL)
1538 dxf->curr_block.last_polyg->next = ln;
1539 dxf->curr_block.last_polyg = ln;
1540 if (dxf->force_dims == GAIA_DXF_FORCE_2D
1541 || dxf->force_dims == GAIA_DXF_FORCE_3D)
1542 ;
1543 else
1544 {
1545 if (is_3d_line (ln))
1546 dxf->curr_block.is3Dpolyg = 1;
1547 }
1548 }
1549 else
1550 {
1551 /* it's a Linestring */
1552 if (dxf->curr_block.first_line == NULL)
1553 dxf->curr_block.first_line = ln;
1554 if (dxf->curr_block.last_line != NULL)
1555 dxf->curr_block.last_line->next = ln;
1556 dxf->curr_block.last_line = ln;
1557 if (dxf->force_dims == GAIA_DXF_FORCE_2D
1558 || dxf->force_dims == GAIA_DXF_FORCE_3D)
1559 ;
1560 else
1561 {
1562 if (is_3d_line (ln))
1563 dxf->curr_block.is3Dline = 1;
1564 }
1565 }
1566 ln->first = dxf->first_ext;
1567 ln->last = dxf->last_ext;
1568 dxf->first_ext = NULL;
1569 dxf->last_ext = NULL;
1570 }
1571
1572 static gaiaDxfBlockPtr
alloc_dxf_block(const char * layer,const char * id)1573 alloc_dxf_block (const char *layer, const char *id)
1574 {
1575 /* allocating and initializing a DXF Block object */
1576 int len;
1577 gaiaDxfBlockPtr blk = malloc (sizeof (gaiaDxfBlock));
1578 blk->hasInsert = 0;
1579 len = strlen (layer);
1580 blk->layer_name = malloc (len + 1);
1581 strcpy (blk->layer_name, layer);
1582 len = strlen (id);
1583 blk->block_id = malloc (len + 1);
1584 strcpy (blk->block_id, id);
1585 blk->first_text = NULL;
1586 blk->last_text = NULL;
1587 blk->first_point = NULL;
1588 blk->last_point = NULL;
1589 blk->first_line = NULL;
1590 blk->last_line = NULL;
1591 blk->first_polyg = NULL;
1592 blk->last_polyg = NULL;
1593 blk->first_hatch = NULL;
1594 blk->last_hatch = NULL;
1595 blk->is3Dtext = 0;
1596 blk->is3Dpoint = 0;
1597 blk->is3Dline = 0;
1598 blk->is3Dpolyg = 0;
1599 blk->next = NULL;
1600 return blk;
1601 }
1602
1603 static void
destroy_dxf_block(gaiaDxfBlockPtr blk)1604 destroy_dxf_block (gaiaDxfBlockPtr blk)
1605 {
1606 /* memory cleanup - destroying a DXF Block object */
1607 gaiaDxfTextPtr txt;
1608 gaiaDxfTextPtr n_txt;
1609 gaiaDxfPointPtr pt;
1610 gaiaDxfPointPtr n_pt;
1611 gaiaDxfPolylinePtr ln;
1612 gaiaDxfPolylinePtr n_ln;
1613 gaiaDxfHatchPtr htc;
1614 gaiaDxfHatchPtr n_htc;
1615 if (blk == NULL)
1616 return;
1617 if (blk->layer_name != NULL)
1618 free (blk->layer_name);
1619 if (blk->block_id != NULL)
1620 free (blk->block_id);
1621 txt = blk->first_text;
1622 while (txt != NULL)
1623 {
1624 n_txt = txt->next;
1625 destroy_dxf_text (txt);
1626 txt = n_txt;
1627 }
1628 pt = blk->first_point;
1629 while (pt != NULL)
1630 {
1631 n_pt = pt->next;
1632 destroy_dxf_point (pt);
1633 pt = n_pt;
1634 }
1635 ln = blk->first_line;
1636 while (ln != NULL)
1637 {
1638 n_ln = ln->next;
1639 destroy_dxf_polyline (ln);
1640 ln = n_ln;
1641 }
1642 ln = blk->first_polyg;
1643 while (ln != NULL)
1644 {
1645 n_ln = ln->next;
1646 destroy_dxf_polyline (ln);
1647 ln = n_ln;
1648 }
1649 htc = blk->first_hatch;
1650 while (htc != NULL)
1651 {
1652 n_htc = htc->next;
1653 destroy_dxf_hatch (htc);
1654 htc = n_htc;
1655 }
1656 free (blk);
1657 }
1658
1659 static void
insert_dxf_block(gaiaDxfParserPtr dxf)1660 insert_dxf_block (gaiaDxfParserPtr dxf)
1661 {
1662 /* inserting a DXF Block object */
1663 gaiaDxfBlockPtr blk;
1664 int ok = 0;
1665 if (dxf->curr_block.layer_name == NULL)
1666 return;
1667 if (dxf->curr_block.block_id == NULL)
1668 return;
1669 if (dxf->curr_block.first_text != NULL)
1670 ok++;
1671 if (dxf->curr_block.first_point != NULL)
1672 ok++;
1673 if (dxf->curr_block.first_line != NULL)
1674 ok++;
1675 if (dxf->curr_block.first_polyg != NULL)
1676 ok++;
1677 if (dxf->curr_block.first_hatch != NULL)
1678 ok++;
1679 if (ok == 0)
1680 return;
1681 blk =
1682 alloc_dxf_block (dxf->curr_block.layer_name, dxf->curr_block.block_id);
1683 blk->first_text = dxf->curr_block.first_text;
1684 blk->last_text = dxf->curr_block.last_text;
1685 dxf->curr_block.first_text = NULL;
1686 dxf->curr_block.last_text = NULL;
1687 blk->first_point = dxf->curr_block.first_point;
1688 blk->last_point = dxf->curr_block.last_point;
1689 dxf->curr_block.first_point = NULL;
1690 dxf->curr_block.last_point = NULL;
1691 blk->first_line = dxf->curr_block.first_line;
1692 blk->last_line = dxf->curr_block.last_line;
1693 dxf->curr_block.first_line = NULL;
1694 dxf->curr_block.last_line = NULL;
1695 blk->first_polyg = dxf->curr_block.first_polyg;
1696 blk->last_polyg = dxf->curr_block.last_polyg;
1697 dxf->curr_block.first_polyg = NULL;
1698 dxf->curr_block.last_polyg = NULL;
1699 blk->first_hatch = dxf->curr_block.first_hatch;
1700 blk->last_hatch = dxf->curr_block.last_hatch;
1701 dxf->curr_block.first_hatch = NULL;
1702 dxf->curr_block.last_hatch = NULL;
1703
1704 if (dxf->first_block == NULL)
1705 dxf->first_block = blk;
1706 if (dxf->last_block != NULL)
1707 dxf->last_block->next = blk;
1708 dxf->last_block = blk;
1709 }
1710
1711 static gaiaDxfLayerPtr
alloc_dxf_layer(const char * name,int force_dims)1712 alloc_dxf_layer (const char *name, int force_dims)
1713 {
1714 /* allocating and initializing a DXF Layer object */
1715 int len;
1716 gaiaDxfLayerPtr lyr = malloc (sizeof (gaiaDxfLayer));
1717 len = strlen (name);
1718 lyr->layer_name = malloc (len + 1);
1719 strcpy (lyr->layer_name, name);
1720 lyr->first_text = NULL;
1721 lyr->last_text = NULL;
1722 lyr->first_point = NULL;
1723 lyr->last_point = NULL;
1724 lyr->first_line = NULL;
1725 lyr->last_line = NULL;
1726 lyr->first_polyg = NULL;
1727 lyr->last_polyg = NULL;
1728 lyr->first_hatch = NULL;
1729 lyr->last_hatch = NULL;
1730 lyr->first_ins_text = NULL;
1731 lyr->last_ins_text = NULL;
1732 lyr->first_ins_point = NULL;
1733 lyr->last_ins_point = NULL;
1734 lyr->first_ins_line = NULL;
1735 lyr->last_ins_line = NULL;
1736 lyr->first_ins_polyg = NULL;
1737 lyr->last_ins_polyg = NULL;
1738 lyr->first_ins_hatch = NULL;
1739 lyr->last_ins_hatch = NULL;
1740 if (force_dims == GAIA_DXF_FORCE_3D)
1741 {
1742 lyr->is3Dtext = 1;
1743 lyr->is3Dpoint = 1;
1744 lyr->is3Dline = 1;
1745 lyr->is3Dpolyg = 1;
1746 lyr->is3DinsText = 1;
1747 lyr->is3DinsPoint = 1;
1748 lyr->is3DinsLine = 1;
1749 lyr->is3DinsPolyg = 1;
1750 }
1751 else
1752 {
1753 lyr->is3Dtext = 0;
1754 lyr->is3Dpoint = 0;
1755 lyr->is3Dline = 0;
1756 lyr->is3Dpolyg = 0;
1757 lyr->is3DinsText = 0;
1758 lyr->is3DinsPoint = 0;
1759 lyr->is3DinsLine = 0;
1760 lyr->is3DinsPolyg = 0;
1761 }
1762 lyr->hasExtraText = 0;
1763 lyr->hasExtraPoint = 0;
1764 lyr->hasExtraLine = 0;
1765 lyr->hasExtraPolyg = 0;
1766 lyr->hasExtraInsText = 0;
1767 lyr->hasExtraInsPoint = 0;
1768 lyr->hasExtraInsLine = 0;
1769 lyr->hasExtraInsPolyg = 0;
1770 lyr->next = NULL;
1771 return lyr;
1772 }
1773
1774 static void
destroy_dxf_layer(gaiaDxfLayerPtr lyr)1775 destroy_dxf_layer (gaiaDxfLayerPtr lyr)
1776 {
1777 /* memory cleanup - destroying a DXF Layer object */
1778 gaiaDxfTextPtr txt;
1779 gaiaDxfTextPtr n_txt;
1780 gaiaDxfPointPtr pt;
1781 gaiaDxfPointPtr n_pt;
1782 gaiaDxfPolylinePtr ln;
1783 gaiaDxfPolylinePtr n_ln;
1784 gaiaDxfHatchPtr ht;
1785 gaiaDxfHatchPtr n_ht;
1786 gaiaDxfInsertPtr ins;
1787 gaiaDxfInsertPtr n_ins;
1788 if (lyr == NULL)
1789 return;
1790 txt = lyr->first_text;
1791 while (txt != NULL)
1792 {
1793 n_txt = txt->next;
1794 destroy_dxf_text (txt);
1795 txt = n_txt;
1796 }
1797 pt = lyr->first_point;
1798 while (pt != NULL)
1799 {
1800 n_pt = pt->next;
1801 destroy_dxf_point (pt);
1802 pt = n_pt;
1803 }
1804 ln = lyr->first_line;
1805 while (ln != NULL)
1806 {
1807 n_ln = ln->next;
1808 destroy_dxf_polyline (ln);
1809 ln = n_ln;
1810 }
1811 ln = lyr->first_polyg;
1812 while (ln != NULL)
1813 {
1814 n_ln = ln->next;
1815 destroy_dxf_polyline (ln);
1816 ln = n_ln;
1817 }
1818 ht = lyr->first_hatch;
1819 while (ht != NULL)
1820 {
1821 n_ht = ht->next;
1822 destroy_dxf_hatch (ht);
1823 ht = n_ht;
1824 }
1825 ins = lyr->first_ins_text;
1826 while (ins != NULL)
1827 {
1828 n_ins = ins->next;
1829 destroy_dxf_insert (ins);
1830 ins = n_ins;
1831 }
1832 ins = lyr->first_ins_point;
1833 while (ins != NULL)
1834 {
1835 n_ins = ins->next;
1836 destroy_dxf_insert (ins);
1837 ins = n_ins;
1838 }
1839 ins = lyr->first_ins_line;
1840 while (ins != NULL)
1841 {
1842 n_ins = ins->next;
1843 destroy_dxf_insert (ins);
1844 ins = n_ins;
1845 }
1846 ins = lyr->first_ins_polyg;
1847 while (ins != NULL)
1848 {
1849 n_ins = ins->next;
1850 destroy_dxf_insert (ins);
1851 ins = n_ins;
1852 }
1853 ins = lyr->first_ins_hatch;
1854 while (ins != NULL)
1855 {
1856 n_ins = ins->next;
1857 destroy_dxf_insert (ins);
1858 ins = n_ins;
1859 }
1860 if (lyr->layer_name != NULL)
1861 free (lyr->layer_name);
1862 free (lyr);
1863 }
1864
1865 static void
insert_dxf_layer(gaiaDxfParserPtr dxf,gaiaDxfLayerPtr lyr)1866 insert_dxf_layer (gaiaDxfParserPtr dxf, gaiaDxfLayerPtr lyr)
1867 {
1868 /* inserting a Layer object into the DXF struct */
1869 if (dxf->first_layer == NULL)
1870 dxf->first_layer = lyr;
1871 if (dxf->last_layer != NULL)
1872 dxf->last_layer->next = lyr;
1873 dxf->last_layer = lyr;
1874 }
1875
1876 static void
force_missing_layer(gaiaDxfParserPtr dxf)1877 force_missing_layer (gaiaDxfParserPtr dxf)
1878 {
1879 /* forcing undeclared layers [missing TABLES section] */
1880 int ok_layer = 1;
1881 if (dxf->undeclared_layers == 0)
1882 return;
1883 if (dxf->selected_layer != NULL)
1884 {
1885 ok_layer = 0;
1886 if (strcmp (dxf->selected_layer, dxf->curr_layer_name) == 0)
1887 ok_layer = 1;
1888 }
1889 if (ok_layer)
1890 {
1891 int already_defined = 0;
1892 gaiaDxfLayerPtr lyr = dxf->first_layer;
1893 while (lyr != NULL)
1894 {
1895 if (strcmp (lyr->layer_name, dxf->curr_layer_name) == 0)
1896 {
1897 already_defined = 1;
1898 break;
1899 }
1900 lyr = lyr->next;
1901 }
1902 if (already_defined)
1903 return;
1904 lyr = alloc_dxf_layer (dxf->curr_layer_name, dxf->force_dims);
1905 insert_dxf_layer (dxf, lyr);
1906 }
1907 }
1908
1909 static void
set_dxf_vertex(gaiaDxfParserPtr dxf)1910 set_dxf_vertex (gaiaDxfParserPtr dxf)
1911 {
1912 /* saving the current Polyline Vertex */
1913 gaiaDxfPointPtr pt = malloc (sizeof (gaiaDxfPoint));
1914 pt->x = dxf->curr_point.x;
1915 pt->y = dxf->curr_point.y;
1916 pt->z = dxf->curr_point.z;
1917 pt->first = NULL;
1918 pt->last = NULL;
1919 pt->next = NULL;
1920 if (dxf->first_pt == NULL)
1921 dxf->first_pt = pt;
1922 if (dxf->last_pt != NULL)
1923 dxf->last_pt->next = pt;
1924 dxf->last_pt = pt;
1925 dxf->curr_point.x = 0.0;
1926 dxf->curr_point.y = 0.0;
1927 dxf->curr_point.z = 0.0;
1928 }
1929
1930 static void
save_current_polyline(const void * p_cache,gaiaDxfParserPtr dxf)1931 save_current_polyline (const void *p_cache, gaiaDxfParserPtr dxf)
1932 {
1933 /* saving the current Polyline */
1934 int points = 0;
1935 gaiaDxfPolylinePtr ln;
1936 gaiaDxfPointPtr n_pt;
1937 gaiaDxfPointPtr pt;
1938 if (dxf->curr_layer_name == NULL)
1939 goto clear;
1940 pt = dxf->first_pt;
1941 while (pt != NULL)
1942 {
1943 /* counting how many vertices are into the polyline */
1944 points++;
1945 pt = pt->next;
1946 }
1947 ln = alloc_dxf_polyline (dxf->is_closed_polyline, points);
1948 points = 0;
1949 pt = dxf->first_pt;
1950 while (pt != NULL)
1951 {
1952 /* setting vertices into the polyline */
1953 *(ln->x + points) = pt->x;
1954 *(ln->y + points) = pt->y;
1955 *(ln->z + points) = pt->z;
1956 points++;
1957 pt = pt->next;
1958 }
1959 if (dxf->is_block)
1960 insert_dxf_block_polyline (p_cache, dxf, ln);
1961 else
1962 {
1963 force_missing_layer (dxf);
1964 insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
1965 }
1966 /* resetting the current polyline */
1967 clear:
1968 pt = dxf->first_pt;
1969 while (pt != NULL)
1970 {
1971 n_pt = pt->next;
1972 destroy_dxf_point (pt);
1973 pt = n_pt;
1974 }
1975 /* resetting curr_layer */
1976 if (dxf->curr_layer_name != NULL)
1977 free (dxf->curr_layer_name);
1978 dxf->curr_layer_name = NULL;
1979 dxf->first_pt = NULL;
1980 dxf->last_pt = NULL;
1981 }
1982
1983 static void
reset_dxf_polyline(const void * p_cache,gaiaDxfParserPtr dxf)1984 reset_dxf_polyline (const void *p_cache, gaiaDxfParserPtr dxf)
1985 {
1986 /* resetting the current DXF polyline */
1987 if (dxf->is_polyline)
1988 {
1989 if (dxf->first_pt != NULL)
1990 save_current_polyline (p_cache, dxf);
1991 dxf->is_polyline = 0;
1992 }
1993 }
1994
1995 static void
reset_dxf_block(gaiaDxfParserPtr dxf)1996 reset_dxf_block (gaiaDxfParserPtr dxf)
1997 {
1998 /* memory cleanup - resetting the current DXF Block */
1999 gaiaDxfTextPtr txt;
2000 gaiaDxfTextPtr n_txt;
2001 gaiaDxfPointPtr pt;
2002 gaiaDxfPointPtr n_pt;
2003 gaiaDxfPolylinePtr ln;
2004 gaiaDxfPolylinePtr n_ln;
2005 gaiaDxfHatchPtr htc;
2006 gaiaDxfHatchPtr n_htc;
2007 if (dxf->curr_block.layer_name != NULL)
2008 free (dxf->curr_block.layer_name);
2009 if (dxf->curr_block.block_id != NULL)
2010 free (dxf->curr_block.block_id);
2011 txt = dxf->curr_block.first_text;
2012 while (txt != NULL)
2013 {
2014 n_txt = txt->next;
2015 destroy_dxf_text (txt);
2016 txt = n_txt;
2017 }
2018 pt = dxf->curr_block.first_point;
2019 while (pt != NULL)
2020 {
2021 n_pt = pt->next;
2022 destroy_dxf_point (pt);
2023 pt = n_pt;
2024 }
2025 ln = dxf->curr_block.first_line;
2026 while (ln != NULL)
2027 {
2028 n_ln = ln->next;
2029 destroy_dxf_polyline (ln);
2030 ln = n_ln;
2031 }
2032 ln = dxf->curr_block.first_polyg;
2033 while (ln != NULL)
2034 {
2035 n_ln = ln->next;
2036 destroy_dxf_polyline (ln);
2037 ln = n_ln;
2038 }
2039 htc = dxf->curr_block.first_hatch;
2040 while (htc != NULL)
2041 {
2042 n_htc = htc->next;
2043 destroy_dxf_hatch (htc);
2044 htc = n_htc;
2045 }
2046 dxf->curr_block.layer_name = NULL;
2047 dxf->curr_block.block_id = NULL;
2048 dxf->curr_block.first_text = NULL;
2049 dxf->curr_block.last_text = NULL;
2050 dxf->curr_block.first_point = NULL;
2051 dxf->curr_block.last_point = NULL;
2052 dxf->curr_block.first_line = NULL;
2053 dxf->curr_block.last_line = NULL;
2054 dxf->curr_block.first_polyg = NULL;
2055 dxf->curr_block.last_polyg = NULL;
2056 dxf->curr_block.first_hatch = NULL;
2057 dxf->curr_block.last_hatch = NULL;
2058 dxf->curr_block.is3Dtext = 0;
2059 dxf->curr_block.is3Dpoint = 0;
2060 dxf->curr_block.is3Dline = 0;
2061 dxf->curr_block.is3Dpolyg = 0;
2062 }
2063
2064 static gaiaDxfBlockPtr
find_dxf_block(gaiaDxfParserPtr dxf,const char * layer_name,const char * block_id)2065 find_dxf_block (gaiaDxfParserPtr dxf, const char *layer_name,
2066 const char *block_id)
2067 {
2068 /* attempting to find a Block object by its Id */
2069 gaiaDxfBlockPtr blk = dxf->first_block;
2070 while (blk != NULL)
2071 {
2072 if (layer_name != NULL && block_id != NULL)
2073 {
2074 if (strcmp (blk->layer_name, layer_name) == 0
2075 && strcmp (blk->block_id, block_id) == 0)
2076 {
2077 /* ok, matching item found */
2078 return blk;
2079 }
2080 }
2081 blk = blk->next;
2082 }
2083 return NULL;
2084 }
2085
2086 static void
save_current_circle(const void * p_cache,gaiaDxfParserPtr dxf)2087 save_current_circle (const void *p_cache, gaiaDxfParserPtr dxf)
2088 {
2089 /* saving the current Circle */
2090 int iv;
2091 double x;
2092 double y;
2093 gaiaGeomCollPtr geom = NULL;
2094 gaiaLinestringPtr circle;
2095 gaiaDxfPolylinePtr ln;
2096 if (dxf->curr_layer_name == NULL)
2097 return;
2098 geom =
2099 gaiaMakeCircle (dxf->curr_circle.cx, dxf->curr_circle.cy,
2100 dxf->curr_circle.radius, 2.5);
2101 if (geom == NULL)
2102 goto stop;
2103 circle = geom->FirstLinestring;
2104 if (circle == NULL)
2105 goto stop;
2106 ln = alloc_dxf_polyline (0, circle->Points);
2107 for (iv = 0; iv < circle->Points; iv++)
2108 {
2109 /* setting vertices into the polyline */
2110 gaiaGetPoint (circle->Coords, iv, &x, &y);
2111 *(ln->x + iv) = x;
2112 *(ln->y + iv) = y;
2113 *(ln->z + iv) = dxf->curr_circle.cz;
2114 }
2115 if (dxf->is_block)
2116 insert_dxf_block_polyline (p_cache, dxf, ln);
2117 else
2118 {
2119 force_missing_layer (dxf);
2120 insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
2121 }
2122 stop:
2123 /* resetting curr_layer */
2124 if (dxf->curr_layer_name != NULL)
2125 free (dxf->curr_layer_name);
2126 dxf->curr_layer_name = NULL;
2127 if (geom != NULL)
2128 gaiaFreeGeomColl (geom);
2129 }
2130
2131 static void
save_current_arc(const void * p_cache,gaiaDxfParserPtr dxf)2132 save_current_arc (const void *p_cache, gaiaDxfParserPtr dxf)
2133 {
2134 /* saving the current Arc */
2135 int iv;
2136 double x;
2137 double y;
2138 gaiaGeomCollPtr geom;
2139 gaiaLinestringPtr arc;
2140 gaiaDxfPolylinePtr ln;
2141 if (dxf->curr_layer_name == NULL)
2142 return;
2143 geom =
2144 gaiaMakeArc (dxf->curr_arc.cx, dxf->curr_arc.cy, dxf->curr_arc.radius,
2145 dxf->curr_arc.start, dxf->curr_arc.stop, 2.5);
2146 if (geom == NULL)
2147 goto stop;
2148 arc = geom->FirstLinestring;
2149 if (arc == NULL)
2150 goto stop;
2151 ln = alloc_dxf_polyline (0, arc->Points);
2152 for (iv = 0; iv < arc->Points; iv++)
2153 {
2154 /* setting vertices into the polyline */
2155 gaiaGetPoint (arc->Coords, iv, &x, &y);
2156 *(ln->x + iv) = x;
2157 *(ln->y + iv) = y;
2158 *(ln->z + iv) = dxf->curr_arc.cz;
2159 }
2160 if (dxf->is_block)
2161 insert_dxf_block_polyline (p_cache, dxf, ln);
2162 else
2163 {
2164 force_missing_layer (dxf);
2165 insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
2166 }
2167 stop:
2168 /* resetting curr_layer */
2169 if (dxf->curr_layer_name != NULL)
2170 free (dxf->curr_layer_name);
2171 dxf->curr_layer_name = NULL;
2172 if (geom != NULL)
2173 gaiaFreeGeomColl (geom);
2174 }
2175
2176 static void
reset_dxf_entity(const void * p_cache,gaiaDxfParserPtr dxf)2177 reset_dxf_entity (const void *p_cache, gaiaDxfParserPtr dxf)
2178 {
2179 /* resetting the current DXF entity */
2180 gaiaDxfExtraAttrPtr ext;
2181 gaiaDxfExtraAttrPtr n_ext;
2182 if (dxf->is_vertex)
2183 {
2184 /* saving the current Vertex */
2185 set_dxf_vertex (dxf);
2186 dxf->is_vertex = 0;
2187 return;
2188 }
2189 if (dxf->is_polyline)
2190 return;
2191 if (dxf->is_layer)
2192 {
2193 /* saving the current Table aka Layer */
2194 int ok_layer = 1;
2195 if (dxf->selected_layer != NULL)
2196 {
2197 ok_layer = 0;
2198 if (strcmp (dxf->selected_layer, dxf->curr_layer_name) == 0)
2199 ok_layer = 1;
2200 }
2201 if (ok_layer)
2202 {
2203 gaiaDxfLayerPtr lyr =
2204 alloc_dxf_layer (dxf->curr_layer_name, dxf->force_dims);
2205 insert_dxf_layer (dxf, lyr);
2206 dxf->undeclared_layers = 0;
2207 }
2208 /* resetting curr_layer */
2209 if (dxf->curr_layer_name != NULL)
2210 free (dxf->curr_layer_name);
2211 dxf->curr_layer_name = NULL;
2212 dxf->is_layer = 0;
2213 }
2214 if (dxf->is_insert)
2215 {
2216 gaiaDxfBlockPtr blk = find_dxf_block (dxf, dxf->curr_layer_name,
2217 dxf->curr_insert.block_id);
2218 if (blk != NULL)
2219 {
2220 /* saving the current Insert */
2221 gaiaDxfInsertPtr ins =
2222 alloc_dxf_insert (dxf->curr_insert.block_id,
2223 dxf->curr_insert.x,
2224 dxf->curr_insert.y, dxf->curr_insert.z,
2225 dxf->curr_insert.scale_x,
2226 dxf->curr_insert.scale_y,
2227 dxf->curr_insert.scale_z,
2228 dxf->curr_insert.angle);
2229 blk->hasInsert = 1;
2230 if (blk->first_text != NULL)
2231 {
2232 ins->hasText = 1;
2233 if (blk->is3Dtext)
2234 ins->is3Dtext = 1;
2235 }
2236 if (blk->first_point != NULL)
2237 {
2238 ins->hasPoint = 1;
2239 if (blk->is3Dpoint)
2240 ins->is3Dpoint = 1;
2241 }
2242 if (blk->first_line != NULL)
2243 {
2244 ins->hasLine = 1;
2245 if (blk->is3Dline)
2246 ins->is3Dline = 1;
2247 }
2248 if (blk->first_polyg != NULL)
2249 {
2250 ins->hasPolyg = 1;
2251 if (blk->is3Dpolyg)
2252 ins->is3Dpolyg = 1;
2253 }
2254 if (blk->first_hatch != NULL)
2255 ins->hasHatch = 1;
2256 force_missing_layer (dxf);
2257 insert_dxf_insert (dxf, dxf->curr_layer_name, ins);
2258 }
2259 /* resetting curr_insert */
2260 dxf->curr_insert.x = 0.0;
2261 dxf->curr_insert.y = 0.0;
2262 dxf->curr_insert.z = 0.0;
2263 dxf->curr_insert.scale_x = 0.0;
2264 dxf->curr_insert.scale_y = 0.0;
2265 dxf->curr_insert.scale_z = 0.0;
2266 dxf->curr_insert.angle = 0.0;
2267 dxf->curr_insert.is3Dtext = 0;
2268 dxf->curr_insert.is3Dpoint = 0;
2269 dxf->curr_insert.is3Dline = 0;
2270 dxf->curr_insert.is3Dpolyg = 0;
2271 if (dxf->curr_insert.block_id != NULL)
2272 free (dxf->curr_insert.block_id);
2273 dxf->curr_insert.block_id = NULL;
2274 dxf->is_insert = 0;
2275 /* resetting curr_layer */
2276 if (dxf->curr_layer_name != NULL)
2277 free (dxf->curr_layer_name);
2278 dxf->curr_layer_name = NULL;
2279 }
2280 if (dxf->is_line)
2281 {
2282 /* saving the current Line */
2283 gaiaDxfPolylinePtr ln =
2284 alloc_dxf_line (dxf->curr_point.x, dxf->curr_point.y,
2285 dxf->curr_point.z,
2286 dxf->curr_end_point.x, dxf->curr_end_point.y,
2287 dxf->curr_end_point.z);
2288 if (dxf->is_block)
2289 insert_dxf_block_polyline (p_cache, dxf, ln);
2290 else
2291 {
2292 force_missing_layer (dxf);
2293 insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
2294 }
2295 /* resetting curr_line */
2296 dxf->curr_point.x = 0.0;
2297 dxf->curr_point.y = 0.0;
2298 dxf->curr_point.z = 0.0;
2299 dxf->curr_end_point.x = 0.0;
2300 dxf->curr_end_point.y = 0.0;
2301 dxf->curr_end_point.z = 0.0;
2302 dxf->is_line = 0;
2303 /* resetting curr_layer */
2304 if (dxf->curr_layer_name != NULL)
2305 free (dxf->curr_layer_name);
2306 dxf->curr_layer_name = NULL;
2307 }
2308 if (dxf->is_hatch)
2309 {
2310 /* saving the current hatch */
2311 if (dxf->curr_hatch != NULL)
2312 {
2313 if (is_valid_dxf_hatch (dxf->curr_hatch))
2314 {
2315 create_dxf_hatch_lines (p_cache, dxf->curr_hatch,
2316 dxf->srid);
2317 if (dxf->is_block)
2318 insert_dxf_block_hatch (dxf, dxf->curr_hatch);
2319 else
2320 {
2321 force_missing_layer (dxf);
2322 insert_dxf_hatch (dxf, dxf->curr_layer_name,
2323 dxf->curr_hatch);
2324 }
2325 dxf->curr_hatch = NULL;
2326 }
2327 }
2328 dxf->is_hatch = 0;
2329 /* resetting curr_layer */
2330 if (dxf->curr_layer_name != NULL)
2331 free (dxf->curr_layer_name);
2332 dxf->curr_layer_name = NULL;
2333 }
2334 if (dxf->is_text)
2335 {
2336 /* saving the current Text */
2337 gaiaDxfTextPtr txt =
2338 alloc_dxf_text (dxf->curr_text.label, dxf->curr_text.x,
2339 dxf->curr_text.y, dxf->curr_text.z,
2340 dxf->curr_text.angle);
2341 if (dxf->is_block)
2342 insert_dxf_block_text (dxf, txt);
2343 else
2344 {
2345 force_missing_layer (dxf);
2346 insert_dxf_text (dxf, dxf->curr_layer_name, txt);
2347 }
2348 /* resetting curr_text */
2349 dxf->curr_text.x = 0.0;
2350 dxf->curr_text.y = 0.0;
2351 dxf->curr_text.z = 0.0;
2352 dxf->curr_text.angle = 0.0;
2353 if (dxf->curr_text.label != NULL)
2354 free (dxf->curr_text.label);
2355 dxf->curr_text.label = NULL;
2356 dxf->is_text = 0;
2357 /* resetting curr_layer */
2358 if (dxf->curr_layer_name != NULL)
2359 free (dxf->curr_layer_name);
2360 dxf->curr_layer_name = NULL;
2361 }
2362 if (dxf->is_point)
2363 {
2364 /* saving the current Point */
2365 gaiaDxfPointPtr pt =
2366 alloc_dxf_point (dxf->curr_point.x, dxf->curr_point.y,
2367 dxf->curr_point.z);
2368 if (dxf->is_block)
2369 insert_dxf_block_point (dxf, pt);
2370 else
2371 {
2372 force_missing_layer (dxf);
2373 insert_dxf_point (dxf, dxf->curr_layer_name, pt);
2374 }
2375 /* resetting curr_point */
2376 dxf->curr_point.x = 0.0;
2377 dxf->curr_point.y = 0.0;
2378 dxf->curr_point.z = 0.0;
2379 dxf->is_point = 0;
2380 /* resetting curr_layer */
2381 if (dxf->curr_layer_name != NULL)
2382 free (dxf->curr_layer_name);
2383 dxf->curr_layer_name = NULL;
2384 }
2385 if (dxf->is_lwpolyline)
2386 {
2387 /* saving the current Polyline */
2388 save_current_polyline (p_cache, dxf);
2389 dxf->is_lwpolyline = 0;
2390 }
2391 if (dxf->is_circle)
2392 {
2393 /* saving the current Circle */
2394 save_current_circle (p_cache, dxf);
2395 /* resetting curr_circle */
2396 dxf->curr_circle.cx = 0.0;
2397 dxf->curr_circle.cy = 0.0;
2398 dxf->curr_circle.cz = 0.0;
2399 dxf->curr_circle.radius = 0.0;
2400 dxf->is_circle = 0;
2401 /* resetting curr_layer */
2402 if (dxf->curr_layer_name != NULL)
2403 free (dxf->curr_layer_name);
2404 dxf->curr_layer_name = NULL;
2405 }
2406 if (dxf->is_arc)
2407 {
2408 /* saving the current Arc */
2409 save_current_arc (p_cache, dxf);
2410 /* resetting curr_arc */
2411 dxf->curr_arc.cx = 0.0;
2412 dxf->curr_arc.cy = 0.0;
2413 dxf->curr_arc.cz = 0.0;
2414 dxf->curr_arc.radius = 0.0;
2415 dxf->curr_arc.start = 0.0;
2416 dxf->curr_arc.stop = 0.0;
2417 dxf->is_arc = 0;
2418 /* resetting curr_layer */
2419 if (dxf->curr_layer_name != NULL)
2420 free (dxf->curr_layer_name);
2421 dxf->curr_layer_name = NULL;
2422 }
2423 if (dxf->extra_key != NULL)
2424 {
2425 free (dxf->extra_key);
2426 dxf->extra_key = NULL;
2427 }
2428 if (dxf->extra_value != NULL)
2429 {
2430 free (dxf->extra_value);
2431 dxf->extra_value = NULL;
2432 }
2433 ext = dxf->first_ext;
2434 while (ext != NULL)
2435 {
2436 n_ext = ext->next;
2437 destroy_dxf_extra (ext);
2438 ext = n_ext;
2439 }
2440 dxf->first_ext = NULL;
2441 dxf->last_ext = NULL;
2442 if (dxf->curr_hatch != NULL)
2443 destroy_dxf_hatch (dxf->curr_hatch);
2444 dxf->curr_hatch = NULL;
2445 }
2446
2447 static void
set_dxf_layer_name(gaiaDxfParserPtr dxf,const char * name)2448 set_dxf_layer_name (gaiaDxfParserPtr dxf, const char *name)
2449 {
2450 /* saving the current Layer Name */
2451 int len;
2452 if (dxf->curr_layer_name != NULL)
2453 free (dxf->curr_layer_name);
2454 len = strlen (name);
2455 dxf->curr_layer_name = malloc (len + 1);
2456 strcpy (dxf->curr_layer_name, name);
2457 }
2458
2459 static void
set_dxf_block_layer_name(gaiaDxfParserPtr dxf,const char * name)2460 set_dxf_block_layer_name (gaiaDxfParserPtr dxf, const char *name)
2461 {
2462 /* saving the current Block Layer Name */
2463 int len;
2464 if (dxf->curr_block.layer_name != NULL)
2465 free (dxf->curr_block.layer_name);
2466 len = strlen (name);
2467 dxf->curr_block.layer_name = malloc (len + 1);
2468 strcpy (dxf->curr_block.layer_name, name);
2469 }
2470
2471 static void
set_dxf_block_id(gaiaDxfParserPtr dxf,const char * id)2472 set_dxf_block_id (gaiaDxfParserPtr dxf, const char *id)
2473 {
2474 /* saving the current Block Id */
2475 int len;
2476 if (dxf->curr_block.block_id != NULL)
2477 free (dxf->curr_block.block_id);
2478 len = strlen (id);
2479 dxf->curr_block.block_id = malloc (len + 1);
2480 strcpy (dxf->curr_block.block_id, id);
2481 }
2482
2483 static void
set_dxf_insert_block_id(gaiaDxfParserPtr dxf,const char * id)2484 set_dxf_insert_block_id (gaiaDxfParserPtr dxf, const char *id)
2485 {
2486 /* saving the current Block Id */
2487 int len;
2488 if (dxf->curr_insert.block_id != NULL)
2489 free (dxf->curr_insert.block_id);
2490 len = strlen (id);
2491 dxf->curr_insert.block_id = malloc (len + 1);
2492 strcpy (dxf->curr_insert.block_id, id);
2493 }
2494
2495 static void
set_dxf_label(gaiaDxfParserPtr dxf,const char * label)2496 set_dxf_label (gaiaDxfParserPtr dxf, const char *label)
2497 {
2498 /* saving the current Text Label */
2499 int len;
2500 if (dxf->curr_text.label != NULL)
2501 free (dxf->curr_text.label);
2502 len = strlen (label);
2503 dxf->curr_text.label = malloc (len + 1);
2504 strcpy (dxf->curr_text.label, label);
2505 }
2506
2507 static void
set_dxf_extra_attr(gaiaDxfParserPtr dxf)2508 set_dxf_extra_attr (gaiaDxfParserPtr dxf)
2509 {
2510 /* saving the current Extra Attribute */
2511 gaiaDxfExtraAttrPtr ext = alloc_dxf_extra ();
2512 ext->key = dxf->extra_key;
2513 ext->value = dxf->extra_value;
2514 if (dxf->first_ext == NULL)
2515 dxf->first_ext = ext;
2516 if (dxf->last_ext != NULL)
2517 dxf->last_ext->next = ext;
2518 dxf->last_ext = ext;
2519 dxf->extra_key = NULL;
2520 dxf->extra_value = NULL;
2521 }
2522
2523 static void
set_dxf_extra_key(gaiaDxfParserPtr dxf,const char * key)2524 set_dxf_extra_key (gaiaDxfParserPtr dxf, const char *key)
2525 {
2526 /* saving the current Extra Attribute Key */
2527 int len;
2528 if (dxf->extra_key != NULL)
2529 free (dxf->extra_key);
2530 len = strlen (key);
2531 dxf->extra_key = malloc (len + 1);
2532 strcpy (dxf->extra_key, key);
2533 if (dxf->extra_key != NULL && dxf->extra_value != NULL)
2534 set_dxf_extra_attr (dxf);
2535 }
2536
2537 static void
set_dxf_extra_value(gaiaDxfParserPtr dxf,const char * value)2538 set_dxf_extra_value (gaiaDxfParserPtr dxf, const char *value)
2539 {
2540 /* saving the current Extra Attribute Value */
2541 int len;
2542 if (dxf->extra_value != NULL)
2543 free (dxf->extra_value);
2544 len = strlen (value);
2545 dxf->extra_value = malloc (len + 1);
2546 strcpy (dxf->extra_value, value);
2547 if (dxf->extra_key != NULL && dxf->extra_value != NULL)
2548 set_dxf_extra_attr (dxf);
2549 }
2550
2551 static void
create_dxf_curr_hatch(gaiaDxfParserPtr dxf)2552 create_dxf_curr_hatch (gaiaDxfParserPtr dxf)
2553 {
2554 /* creating the current Hatch being parsed */
2555 if (dxf->curr_hatch != NULL)
2556 destroy_dxf_hatch (dxf->curr_hatch);
2557 dxf->curr_hatch = alloc_dxf_hatch ();
2558 }
2559
2560 static void
start_dxf_hatch_boundary(gaiaDxfParserPtr dxf)2561 start_dxf_hatch_boundary (gaiaDxfParserPtr dxf)
2562 {
2563 /* starting a new Hatch Boundary Path */
2564 if (dxf->curr_hatch != NULL)
2565 {
2566 gaiaDxfBoundaryPathPtr path = alloc_dxf_boundary_path ();
2567 insert_dxf_boundary_path (dxf->curr_hatch, path);
2568 dxf->is_hatch_boundary = 1;
2569 }
2570 }
2571
2572 static void
insert_dxf_hatch_boundary_segm(gaiaDxfParserPtr dxf)2573 insert_dxf_hatch_boundary_segm (gaiaDxfParserPtr dxf)
2574 {
2575 if (dxf->curr_hatch != NULL)
2576 {
2577 gaiaDxfBoundaryPathPtr path = dxf->curr_hatch->last;
2578 if (path != NULL)
2579 {
2580 gaiaDxfHatchSegmPtr segm =
2581 alloc_dxf_hatch_segm (dxf->curr_point.x, dxf->curr_point.y,
2582 dxf->curr_end_point.x,
2583 dxf->curr_end_point.y);
2584 insert_dxf_boundary_segm (path, segm);
2585 }
2586 }
2587 dxf->curr_point.x = 0.0;
2588 dxf->curr_point.y = 0.0;
2589 dxf->curr_point.z = 0.0;
2590 dxf->curr_end_point.x = 0.0;
2591 dxf->curr_end_point.y = 0.0;
2592 dxf->curr_end_point.z = 0.0;
2593 }
2594
2595 static void
set_dxf_hatch_spacing(gaiaDxfParserPtr dxf,double spacing)2596 set_dxf_hatch_spacing (gaiaDxfParserPtr dxf, double spacing)
2597 {
2598 /* saving the current Hatch spacing */
2599 if (dxf->curr_hatch != NULL)
2600 dxf->curr_hatch->spacing = spacing;
2601 }
2602
2603 static void
set_dxf_hatch_angle(gaiaDxfParserPtr dxf,double angle)2604 set_dxf_hatch_angle (gaiaDxfParserPtr dxf, double angle)
2605 {
2606 /* saving the current Hatch angle */
2607 if (dxf->curr_hatch != NULL)
2608 dxf->curr_hatch->angle = angle;
2609 }
2610
2611 static void
set_dxf_hatch_base_x(gaiaDxfParserPtr dxf,double x)2612 set_dxf_hatch_base_x (gaiaDxfParserPtr dxf, double x)
2613 {
2614 /* saving the current Hatch base X */
2615 if (dxf->curr_hatch != NULL)
2616 dxf->curr_hatch->base_x = x;
2617 }
2618
2619 static void
set_dxf_hatch_base_y(gaiaDxfParserPtr dxf,double y)2620 set_dxf_hatch_base_y (gaiaDxfParserPtr dxf, double y)
2621 {
2622 /* saving the current Hatch base Y */
2623 if (dxf->curr_hatch != NULL)
2624 dxf->curr_hatch->base_y = y;
2625 }
2626
2627 static void
set_dxf_hatch_offset_x(gaiaDxfParserPtr dxf,double x)2628 set_dxf_hatch_offset_x (gaiaDxfParserPtr dxf, double x)
2629 {
2630 /* saving the current Hatch offset X */
2631 if (dxf->curr_hatch != NULL)
2632 dxf->curr_hatch->offset_x = x;
2633 }
2634
2635 static void
set_dxf_hatch_offset_y(gaiaDxfParserPtr dxf,double y)2636 set_dxf_hatch_offset_y (gaiaDxfParserPtr dxf, double y)
2637 {
2638 /* saving the current Hatch offset Y */
2639 if (dxf->curr_hatch != NULL)
2640 dxf->curr_hatch->offset_y = y;
2641 }
2642
2643 static int
op_code_line(const char * line)2644 op_code_line (const char *line)
2645 {
2646 /* checking for a valid op-code */
2647 int numdigit = 0;
2648 int invalid = 0;
2649 const char *p = line;
2650 while (*p != '\0')
2651 {
2652 /* skipping leading white-spaces */
2653 if (*p == ' ' || *p == '\t')
2654 {
2655 p++;
2656 continue;
2657 }
2658 else
2659 break;
2660 }
2661 while (*p != '\0')
2662 {
2663 /* evaluating each character */
2664 if (*p >= '0' && *p <= '9')
2665 {
2666 numdigit++;
2667 p++;
2668 continue;
2669 }
2670 else
2671 {
2672 invalid = 1;
2673 break;
2674 }
2675 }
2676 if (numdigit > 0 && invalid == 0)
2677 return 1;
2678 return 0;
2679 }
2680
2681 static int
parse_dxf_line(const void * p_cache,gaiaDxfParserPtr dxf,const char * line)2682 parse_dxf_line (const void *p_cache, gaiaDxfParserPtr dxf, const char *line)
2683 {
2684 /* parsing a DXF line */
2685 dxf->line_no += 1;
2686
2687 if (dxf->tables || dxf->entities || dxf->blocks)
2688 {
2689 /* handling OP-CODE lines */
2690 if (dxf->op_code_line)
2691 {
2692 if (!op_code_line (line))
2693 {
2694 /* unexpected value */
2695 spatialite_e
2696 ("ERROR on line %d: expected on OP-CODE to be found\n",
2697 dxf->line_no);
2698 return 0;
2699 }
2700 dxf->op_code = atoi (line);
2701 if (dxf->op_code == 0)
2702 reset_dxf_entity (p_cache, dxf);
2703 dxf->op_code_line = 0;
2704 return 1;
2705 }
2706 dxf->op_code_line = 1;
2707 }
2708 if (dxf->eof)
2709 {
2710 /* reading past the end */
2711 spatialite_e ("ERROR on line %d: attempting to read past EOF\n",
2712 dxf->line_no);
2713 return 0;
2714 }
2715 if (strcmp (line, "SECTION") == 0)
2716 {
2717 /* start SECTION tag */
2718 reset_dxf_polyline (p_cache, dxf);
2719 if (dxf->section)
2720 {
2721 spatialite_e ("ERROR on line %d: unexpected SECTION\n",
2722 dxf->line_no);
2723 dxf->error = 1;
2724 return 0;
2725 }
2726 dxf->section = 1;
2727 return 1;
2728 }
2729 if (strcmp (line, "ENDSEC") == 0)
2730 {
2731 /* end SECTION tag */
2732 reset_dxf_polyline (p_cache, dxf);
2733 if (!dxf->section)
2734 {
2735 spatialite_e ("ERROR on line %d: unexpected ENDSEC\n",
2736 dxf->line_no);
2737 dxf->error = 1;
2738 return 0;
2739 }
2740 dxf->section = 0;
2741 dxf->tables = 0;
2742 dxf->blocks = 0;
2743 dxf->is_block = 0;
2744 dxf->entities = 0;
2745 return 1;
2746 }
2747 if (strcmp (line, "TABLES") == 0)
2748 {
2749 /* start TABLES tag */
2750 reset_dxf_polyline (p_cache, dxf);
2751 if (dxf->section)
2752 {
2753 dxf->tables = 1;
2754 dxf->op_code_line = 1;
2755 return 1;
2756 }
2757 }
2758 if (strcmp (line, "BLOCKS") == 0)
2759 {
2760 /* start BLOCKS tag */
2761 reset_dxf_polyline (p_cache, dxf);
2762 if (dxf->section)
2763 {
2764 dxf->blocks = 1;
2765 dxf->op_code_line = 1;
2766 return 1;
2767 }
2768 }
2769 if (strcmp (line, "BLOCK") == 0)
2770 {
2771 /* start BLOCK tag */
2772 reset_dxf_polyline (p_cache, dxf);
2773 if (dxf->blocks)
2774 {
2775 dxf->is_block = 1;
2776 dxf->op_code_line = 1;
2777 return 1;
2778 }
2779 }
2780 if (strcmp (line, "ENDBLK") == 0)
2781 {
2782 /* end BLOCK tag */
2783 reset_dxf_polyline (p_cache, dxf);
2784 if (dxf->is_block)
2785 {
2786 insert_dxf_block (dxf);
2787 dxf->is_block = 0;
2788 dxf->op_code_line = 1;
2789 return 1;
2790 }
2791 }
2792 if (strcmp (line, "ENTITIES") == 0)
2793 {
2794 /* start ENTITIES tag */
2795 reset_dxf_polyline (p_cache, dxf);
2796 if (dxf->section)
2797 {
2798 dxf->entities = 1;
2799 dxf->op_code_line = 1;
2800 return 1;
2801 }
2802 }
2803 if (strcmp (line, "LAYER") == 0)
2804 {
2805 /* start LAYER tag */
2806 reset_dxf_polyline (p_cache, dxf);
2807 if (dxf->tables && dxf->op_code == 0)
2808 {
2809 dxf->is_layer = 1;
2810 return 1;
2811 }
2812 }
2813 if (strcmp (line, "INSERT") == 0)
2814 {
2815 /* start INSERT tag */
2816 reset_dxf_polyline (p_cache, dxf);
2817 if (dxf->entities && dxf->op_code == 0)
2818 {
2819 dxf->is_insert = 1;
2820 return 1;
2821 }
2822 }
2823 if (strcmp (line, "INSERT") == 0)
2824 {
2825 /* start INSERT tag */
2826 reset_dxf_polyline (p_cache, dxf);
2827 if (dxf->entities && dxf->op_code == 0)
2828 {
2829 dxf->is_insert = 1;
2830 return 1;
2831 }
2832 }
2833 if (strcmp (line, "TEXT") == 0)
2834 {
2835 /* start TEXT tag */
2836 reset_dxf_polyline (p_cache, dxf);
2837 if (dxf->entities && dxf->op_code == 0)
2838 {
2839 dxf->is_text = 1;
2840 return 1;
2841 }
2842 if (dxf->is_block && dxf->op_code == 0)
2843 {
2844 dxf->is_text = 1;
2845 return 1;
2846 }
2847 }
2848 if (strcmp (line, "POINT") == 0)
2849 {
2850 /* start POINT tag */
2851 reset_dxf_polyline (p_cache, dxf);
2852 if (dxf->entities && dxf->op_code == 0)
2853 {
2854 dxf->is_point = 1;
2855 return 1;
2856 }
2857 if (dxf->is_block && dxf->op_code == 0)
2858 {
2859 dxf->is_point = 1;
2860 return 1;
2861 }
2862 }
2863 if (strcmp (line, "POLYLINE") == 0)
2864 {
2865 /* start POLYLINE tag */
2866 reset_dxf_polyline (p_cache, dxf);
2867 if (dxf->entities && dxf->op_code == 0)
2868 {
2869 dxf->is_polyline = 1;
2870 return 1;
2871 }
2872 if (dxf->is_block && dxf->op_code == 0)
2873 {
2874 dxf->is_polyline = 1;
2875 return 1;
2876 }
2877 }
2878 if (strcmp (line, "LWPOLYLINE") == 0)
2879 {
2880 /* start LWPOLYLINE tag */
2881 reset_dxf_polyline (p_cache, dxf);
2882 if (dxf->entities && dxf->op_code == 0)
2883 {
2884 dxf->is_lwpolyline = 1;
2885 return 1;
2886 }
2887 if (dxf->is_block && dxf->op_code == 0)
2888 {
2889 dxf->is_lwpolyline = 1;
2890 return 1;
2891 }
2892 }
2893 if (strcmp (line, "LINE") == 0)
2894 {
2895 /* start LINE tag */
2896 reset_dxf_polyline (p_cache, dxf);
2897 if (dxf->entities && dxf->op_code == 0)
2898 {
2899 dxf->is_line = 1;
2900 return 1;
2901 }
2902 if (dxf->is_block && dxf->op_code == 0)
2903 {
2904 dxf->is_line = 1;
2905 return 1;
2906 }
2907 }
2908 if (strcmp (line, "CIRCLE") == 0)
2909 {
2910 /* start CIRCLE tag */
2911 reset_dxf_polyline (p_cache, dxf);
2912 if (dxf->entities && dxf->op_code == 0)
2913 {
2914 dxf->is_circle = 1;
2915 return 1;
2916 }
2917 if (dxf->is_block && dxf->op_code == 0)
2918 {
2919 dxf->is_circle = 1;
2920 return 1;
2921 }
2922 }
2923 if (strcmp (line, "ARC") == 0)
2924 {
2925 /* start ARC tag */
2926 reset_dxf_polyline (p_cache, dxf);
2927 if (dxf->entities && dxf->op_code == 0)
2928 {
2929 dxf->is_arc = 1;
2930 return 1;
2931 }
2932 if (dxf->is_block && dxf->op_code == 0)
2933 {
2934 dxf->is_arc = 1;
2935 return 1;
2936 }
2937 }
2938 if (strcmp (line, "VERTEX") == 0)
2939 {
2940 /* start VERTEX tag */
2941 if (dxf->is_polyline && dxf->op_code == 0)
2942 {
2943 dxf->is_vertex = 1;
2944 return 1;
2945 }
2946 }
2947 if (strcmp (line, "HATCH") == 0)
2948 {
2949 /* start HATCH tag */
2950 if (dxf->entities && dxf->op_code == 0)
2951 {
2952 dxf->is_hatch = 1;
2953 return 1;
2954 }
2955 if (dxf->is_block && dxf->op_code == 0)
2956 {
2957 dxf->is_hatch = 1;
2958 return 1;
2959 }
2960 }
2961 if (strcmp (line, "EOF") == 0)
2962 {
2963 /* end of file marker tag */
2964 reset_dxf_polyline (p_cache, dxf);
2965 dxf->eof = 1;
2966 return 1;
2967 }
2968 if (dxf->is_layer)
2969 {
2970 /* parsing Table attributes */
2971 switch (dxf->op_code)
2972 {
2973 case 2:
2974 set_dxf_layer_name (dxf, line);
2975 break;
2976 };
2977 }
2978 if (dxf->is_block)
2979 {
2980 /* parsing Block attributes */
2981 switch (dxf->op_code)
2982 {
2983 case 2:
2984 set_dxf_block_id (dxf, line);
2985 break;
2986 case 8:
2987 set_dxf_block_layer_name (dxf, line);
2988 break;
2989 };
2990 }
2991 if (dxf->is_line)
2992 {
2993 /* parsing Line attributes */
2994 switch (dxf->op_code)
2995 {
2996 case 8:
2997 set_dxf_layer_name (dxf, line);
2998 break;
2999 case 10:
3000 dxf->curr_point.x = atof (line);
3001 break;
3002 case 20:
3003 dxf->curr_point.y = atof (line);
3004 break;
3005 case 30:
3006 dxf->curr_point.z = atof (line);
3007 break;
3008 case 11:
3009 dxf->curr_end_point.x = atof (line);
3010 break;
3011 case 21:
3012 dxf->curr_end_point.y = atof (line);
3013 break;
3014 case 31:
3015 dxf->curr_end_point.z = atof (line);
3016 break;
3017 };
3018 }
3019 if (dxf->is_circle)
3020 {
3021 /* parsing Circle attributes */
3022 switch (dxf->op_code)
3023 {
3024 case 8:
3025 set_dxf_layer_name (dxf, line);
3026 break;
3027 case 10:
3028 dxf->curr_circle.cx = atof (line);
3029 break;
3030 case 20:
3031 dxf->curr_circle.cy = atof (line);
3032 break;
3033 case 30:
3034 dxf->curr_circle.cz = atof (line);
3035 break;
3036 case 40:
3037 dxf->curr_circle.radius = atof (line);
3038 break;
3039 };
3040 }
3041 if (dxf->is_arc)
3042 {
3043 /* parsing Arc attributes */
3044 switch (dxf->op_code)
3045 {
3046 case 8:
3047 set_dxf_layer_name (dxf, line);
3048 break;
3049 case 10:
3050 dxf->curr_arc.cx = atof (line);
3051 break;
3052 case 20:
3053 dxf->curr_arc.cy = atof (line);
3054 break;
3055 case 30:
3056 dxf->curr_arc.cz = atof (line);
3057 break;
3058 case 40:
3059 dxf->curr_arc.radius = atof (line);
3060 break;
3061 case 50:
3062 dxf->curr_arc.start = atof (line);
3063 break;
3064 case 51:
3065 dxf->curr_arc.stop = atof (line);
3066 break;
3067 };
3068 }
3069 if (dxf->is_insert)
3070 {
3071 /* parsing Insert attributes */
3072 switch (dxf->op_code)
3073 {
3074 case 2:
3075 set_dxf_insert_block_id (dxf, line);
3076 break;
3077 case 8:
3078 set_dxf_layer_name (dxf, line);
3079 break;
3080 case 10:
3081 dxf->curr_insert.x = atof (line);
3082 break;
3083 case 20:
3084 dxf->curr_insert.y = atof (line);
3085 break;
3086 case 30:
3087 dxf->curr_insert.z = atof (line);
3088 break;
3089 case 41:
3090 dxf->curr_insert.scale_x = atof (line);
3091 break;
3092 case 42:
3093 dxf->curr_insert.scale_y = atof (line);
3094 break;
3095 case 43:
3096 dxf->curr_insert.scale_z = atof (line);
3097 break;
3098 case 50:
3099 dxf->curr_insert.angle = atof (line);
3100 break;
3101 case 1000:
3102 set_dxf_extra_value (dxf, line);
3103 break;
3104 case 1001:
3105 set_dxf_extra_key (dxf, line);
3106 break;
3107 };
3108 }
3109 if (dxf->is_text)
3110 {
3111 /* parsing Text attributes */
3112 switch (dxf->op_code)
3113 {
3114 case 1:
3115 set_dxf_label (dxf, line);
3116 break;
3117 case 8:
3118 set_dxf_layer_name (dxf, line);
3119 break;
3120 case 10:
3121 dxf->curr_text.x = atof (line);
3122 break;
3123 case 20:
3124 dxf->curr_text.y = atof (line);
3125 break;
3126 case 30:
3127 dxf->curr_text.z = atof (line);
3128 break;
3129 case 50:
3130 dxf->curr_text.angle = atof (line);
3131 break;
3132 case 1000:
3133 set_dxf_extra_value (dxf, line);
3134 break;
3135 case 1001:
3136 set_dxf_extra_key (dxf, line);
3137 break;
3138 };
3139 }
3140 if (dxf->is_point)
3141 {
3142 /* parsing Point attributes */
3143 switch (dxf->op_code)
3144 {
3145 case 8:
3146 set_dxf_layer_name (dxf, line);
3147 break;
3148 case 10:
3149 dxf->curr_point.x = atof (line);
3150 break;
3151 case 20:
3152 dxf->curr_point.y = atof (line);
3153 break;
3154 case 30:
3155 dxf->curr_point.z = atof (line);
3156 break;
3157 case 1000:
3158 set_dxf_extra_value (dxf, line);
3159 break;
3160 case 1001:
3161 set_dxf_extra_key (dxf, line);
3162 break;
3163 };
3164 }
3165 if (dxf->is_lwpolyline)
3166 {
3167 /* parsing LwPolyline attributes */
3168 switch (dxf->op_code)
3169 {
3170 case 8:
3171 set_dxf_layer_name (dxf, line);
3172 break;
3173 case 10:
3174 dxf->curr_point.x = atof (line);
3175 break;
3176 case 20:
3177 dxf->curr_point.y = atof (line);
3178 set_dxf_vertex (dxf);
3179 break;
3180 case 70:
3181 if ((atoi (line) & 0x01) == 0x01)
3182 dxf->is_closed_polyline = 1;
3183 else
3184 dxf->is_closed_polyline = 0;
3185 break;
3186 case 1000:
3187 set_dxf_extra_value (dxf, line);
3188 break;
3189 case 1001:
3190 set_dxf_extra_key (dxf, line);
3191 break;
3192 };
3193 }
3194 if (dxf->is_polyline && dxf->is_vertex != 1)
3195 {
3196 /* parsing Polyline attributes */
3197 switch (dxf->op_code)
3198 {
3199 case 8:
3200 set_dxf_layer_name (dxf, line);
3201 break;
3202 case 70:
3203 if ((atoi (line) & 0x01) == 0x01)
3204 dxf->is_closed_polyline = 1;
3205 else
3206 dxf->is_closed_polyline = 0;
3207 break;
3208 case 1000:
3209 set_dxf_extra_value (dxf, line);
3210 break;
3211 case 1001:
3212 set_dxf_extra_key (dxf, line);
3213 break;
3214 };
3215 }
3216 if (dxf->is_vertex)
3217 {
3218 /* parsing Vertex attributes */
3219 switch (dxf->op_code)
3220 {
3221 case 10:
3222 dxf->curr_point.x = atof (line);
3223 break;
3224 case 20:
3225 dxf->curr_point.y = atof (line);
3226 break;
3227 case 30:
3228 dxf->curr_point.z = atof (line);
3229 break;
3230 };
3231 }
3232 if (dxf->is_hatch)
3233 {
3234 /* parsing Hatch attributes */
3235 switch (dxf->op_code)
3236 {
3237 case 8:
3238 set_dxf_layer_name (dxf, line);
3239 create_dxf_curr_hatch (dxf);
3240 break;
3241 case 10:
3242 if (dxf->is_hatch_boundary)
3243 dxf->curr_point.x = atof (line);
3244 break;
3245 case 20:
3246 if (dxf->is_hatch_boundary)
3247 dxf->curr_point.y = atof (line);
3248 break;
3249 case 11:
3250 if (dxf->is_hatch_boundary)
3251 dxf->curr_end_point.x = atof (line);
3252 break;
3253 case 21:
3254 dxf->curr_end_point.y = atof (line);
3255 insert_dxf_hatch_boundary_segm (dxf);
3256 break;
3257 case 41:
3258 set_dxf_hatch_spacing (dxf, atof (line));
3259 break;
3260 case 43:
3261 set_dxf_hatch_base_x (dxf, atof (line));
3262 break;
3263 case 44:
3264 set_dxf_hatch_base_y (dxf, atof (line));
3265 break;
3266 case 45:
3267 set_dxf_hatch_offset_x (dxf, atof (line));
3268 break;
3269 case 46:
3270 set_dxf_hatch_offset_y (dxf, atof (line));
3271 break;
3272 case 53:
3273 set_dxf_hatch_angle (dxf, atof (line));
3274 break;
3275 case 92:
3276 start_dxf_hatch_boundary (dxf);
3277 break;
3278 case 97:
3279 dxf->is_hatch_boundary = 0;
3280 break;
3281 };
3282 }
3283 return 1;
3284 }
3285
3286 GAIAGEO_DECLARE gaiaDxfParserPtr
gaiaCreateDxfParser(int srid,int force_dims,const char * prefix,const char * selected_layer,int special_rings)3287 gaiaCreateDxfParser (int srid,
3288 int force_dims,
3289 const char *prefix,
3290 const char *selected_layer, int special_rings)
3291 {
3292 /* allocating and initializing a DXF parser object */
3293 gaiaDxfParserPtr dxf = malloc (sizeof (gaiaDxfParser));
3294 dxf->line_no = 0;
3295 dxf->op_code_line = 0;
3296 dxf->op_code = -1;
3297 dxf->section = 0;
3298 dxf->tables = 0;
3299 dxf->blocks = 0;
3300 dxf->entities = 0;
3301 dxf->is_layer = 0;
3302 dxf->is_block = 0;
3303 dxf->is_text = 0;
3304 dxf->is_point = 0;
3305 dxf->is_polyline = 0;
3306 dxf->is_lwpolyline = 0;
3307 dxf->is_line = 0;
3308 dxf->is_circle = 0;
3309 dxf->is_arc = 0;
3310 dxf->is_vertex = 0;
3311 dxf->is_hatch = 0;
3312 dxf->is_hatch_boundary = 0;
3313 dxf->is_insert = 0;
3314 dxf->eof = 0;
3315 dxf->error = 0;
3316 dxf->curr_layer_name = NULL;
3317 dxf->curr_insert.x = 0.0;
3318 dxf->curr_insert.y = 0.0;
3319 dxf->curr_insert.z = 0.0;
3320 dxf->curr_insert.scale_x = 0.0;
3321 dxf->curr_insert.scale_y = 0.0;
3322 dxf->curr_insert.scale_z = 0.0;
3323 dxf->curr_insert.angle = 0.0;
3324 dxf->curr_insert.block_id = NULL;
3325 dxf->curr_insert.is3Dtext = 0;
3326 dxf->curr_insert.is3Dpoint = 0;
3327 dxf->curr_insert.is3Dline = 0;
3328 dxf->curr_insert.is3Dpolyg = 0;
3329 dxf->curr_text.x = 0.0;
3330 dxf->curr_text.y = 0.0;
3331 dxf->curr_text.z = 0.0;
3332 dxf->curr_text.angle = 0.0;
3333 dxf->curr_text.label = NULL;
3334 dxf->curr_point.x = 0.0;
3335 dxf->curr_point.y = 0.0;
3336 dxf->curr_point.z = 0.0;
3337 dxf->curr_block.layer_name = NULL;
3338 dxf->curr_block.block_id = NULL;
3339 dxf->curr_block.first_text = NULL;
3340 dxf->curr_block.last_text = NULL;
3341 dxf->curr_block.first_point = NULL;
3342 dxf->curr_block.last_point = NULL;
3343 dxf->curr_block.first_line = NULL;
3344 dxf->curr_block.last_line = NULL;
3345 dxf->curr_block.first_polyg = NULL;
3346 dxf->curr_block.last_polyg = NULL;
3347 dxf->curr_block.first_hatch = NULL;
3348 dxf->curr_block.last_hatch = NULL;
3349 dxf->curr_block.is3Dtext = 0;
3350 dxf->curr_block.is3Dpoint = 0;
3351 dxf->curr_block.is3Dline = 0;
3352 dxf->curr_block.is3Dpolyg = 0;
3353 dxf->curr_end_point.x = 0.0;
3354 dxf->curr_end_point.y = 0.0;
3355 dxf->curr_end_point.z = 0.0;
3356 dxf->curr_circle.cx = 0.0;
3357 dxf->curr_circle.cy = 0.0;
3358 dxf->curr_circle.cz = 0.0;
3359 dxf->curr_circle.radius = 0.0;
3360 dxf->curr_arc.cx = 0.0;
3361 dxf->curr_arc.cy = 0.0;
3362 dxf->curr_arc.cz = 0.0;
3363 dxf->curr_arc.radius = 0.0;
3364 dxf->curr_arc.start = 0.0;
3365 dxf->curr_arc.stop = 0.0;
3366 dxf->is_closed_polyline = 0;
3367 dxf->extra_key = NULL;
3368 dxf->extra_value = NULL;
3369 dxf->first_pt = NULL;
3370 dxf->last_pt = NULL;
3371 dxf->first_ext = NULL;
3372 dxf->last_ext = NULL;
3373 dxf->filename = NULL;
3374 dxf->first_layer = NULL;
3375 dxf->last_layer = NULL;
3376 dxf->first_block = NULL;
3377 dxf->last_block = NULL;
3378 dxf->curr_hatch = NULL;
3379 dxf->force_dims = force_dims;
3380 if (srid <= 0)
3381 srid = -1;
3382 dxf->srid = srid;
3383 dxf->prefix = prefix;
3384 dxf->selected_layer = selected_layer;
3385 dxf->linked_rings = 0;
3386 dxf->unlinked_rings = 0;
3387 if (special_rings == GAIA_DXF_RING_LINKED)
3388 dxf->linked_rings = 1;
3389 if (special_rings == GAIA_DXF_RING_UNLINKED)
3390 dxf->unlinked_rings = 1;
3391 dxf->undeclared_layers = 1;
3392 return dxf;
3393 }
3394
3395 GAIAGEO_DECLARE void
gaiaDestroyDxfParser(gaiaDxfParserPtr dxf)3396 gaiaDestroyDxfParser (gaiaDxfParserPtr dxf)
3397 {
3398 /* memory cleanup: destroying a DXF parser object */
3399 gaiaDxfLayerPtr lyr;
3400 gaiaDxfLayerPtr n_lyr;
3401 gaiaDxfPointPtr pt;
3402 gaiaDxfPointPtr n_pt;
3403 gaiaDxfExtraAttrPtr ext;
3404 gaiaDxfExtraAttrPtr n_ext;
3405 gaiaDxfBlockPtr blk;
3406 gaiaDxfBlockPtr n_blk;
3407 if (dxf == NULL)
3408 return;
3409 if (dxf->curr_text.label != NULL)
3410 free (dxf->curr_text.label);
3411 if (dxf->curr_layer_name != NULL)
3412 free (dxf->curr_layer_name);
3413 if (dxf->filename != NULL)
3414 free (dxf->filename);
3415 lyr = dxf->first_layer;
3416 while (lyr != NULL)
3417 {
3418 n_lyr = lyr->next;
3419 destroy_dxf_layer (lyr);
3420 lyr = n_lyr;
3421 }
3422 pt = dxf->first_pt;
3423 while (pt != NULL)
3424 {
3425 n_pt = pt->next;
3426 destroy_dxf_point (pt);
3427 pt = n_pt;
3428 }
3429 if (dxf->extra_key != NULL)
3430 free (dxf->extra_key);
3431 if (dxf->extra_value != NULL)
3432 free (dxf->extra_value);
3433 ext = dxf->first_ext;
3434 while (ext != NULL)
3435 {
3436 n_ext = ext->next;
3437 destroy_dxf_extra (ext);
3438 ext = n_ext;
3439 }
3440 blk = dxf->first_block;
3441 while (blk != NULL)
3442 {
3443 n_blk = blk->next;
3444 destroy_dxf_block (blk);
3445 blk = n_blk;
3446 }
3447 if (dxf->curr_hatch != NULL)
3448 destroy_dxf_hatch (dxf->curr_hatch);
3449 reset_dxf_block (dxf);
3450 free (dxf);
3451 }
3452
3453 static void
save_dxf_filename(gaiaDxfParserPtr dxf,const char * path)3454 save_dxf_filename (gaiaDxfParserPtr dxf, const char *path)
3455 {
3456 /* saving the input/origin filename */
3457 int len = strlen (path);
3458 const char *start = path;
3459 const char *stop = path + len - 1;
3460 const char *p = path;
3461 if (dxf->filename != NULL)
3462 free (dxf->filename);
3463 dxf->filename = NULL;
3464 if (path == NULL)
3465 return;
3466
3467 while (*p != '\0')
3468 {
3469 if (*p == '/' || *p == '\\')
3470 start = p + 1;
3471 p++;
3472 }
3473 p = stop;
3474 while (p > path)
3475 {
3476 if (*p == '.')
3477 {
3478 stop = p - 1;
3479 break;
3480 }
3481 p--;
3482 }
3483 if (stop > start)
3484 {
3485 len = stop - start + 1;
3486 dxf->filename = malloc (len + 1);
3487 memset (dxf->filename, '\0', len + 1);
3488 memcpy (dxf->filename, start, len);
3489 }
3490 else
3491 {
3492 dxf->filename = malloc (len + 1);
3493 strcpy (dxf->filename, path);
3494 }
3495 }
3496
3497 static int
gaiaParseDxfFileCommon(const void * p_cache,gaiaDxfParserPtr dxf,const char * path)3498 gaiaParseDxfFileCommon (const void *p_cache, gaiaDxfParserPtr dxf,
3499 const char *path)
3500 {
3501 /* parsing the whole DXF file */
3502 int c;
3503 char line[4192];
3504 char *p = line;
3505 FILE *fl;
3506
3507 if (dxf == NULL)
3508 return 0;
3509 save_dxf_filename (dxf, path);
3510 if (dxf->first_layer != NULL || dxf->first_block != NULL)
3511 return 0;
3512
3513 /* attempting to open the input file */
3514 #ifdef _WIN32
3515 fl = gaia_win_fopen (path, "rb");
3516 #else
3517 fl = fopen (path, "rb");
3518 #endif
3519 if (fl == NULL)
3520 return 0;
3521
3522 /* scanning the DXF file */
3523 while ((c = getc (fl)) != EOF)
3524 {
3525 if (c == '\r')
3526 {
3527 /* ignoring any CR */
3528 continue;
3529 }
3530 if (c == '\n')
3531 {
3532 /* end line found */
3533 *p = '\0';
3534 if (!parse_dxf_line (p_cache, dxf, line))
3535 goto stop;
3536 if (dxf->eof)
3537 {
3538 /* EOF marker found - quitting */
3539 break;
3540 }
3541 p = line;
3542 continue;
3543 }
3544 *p++ = (char) c;
3545 /* Even Rouault 2013-06-02 - avoiding a potential buffer overflow */
3546 if (p - line == sizeof (line) - 1)
3547 goto stop;
3548 /* END - Even Rouault 2013-06-02 */
3549 }
3550
3551 fclose (fl);
3552 return 1;
3553 stop:
3554 fclose (fl);
3555 return 0;
3556 }
3557
3558 GAIAGEO_DECLARE int
gaiaParseDxfFile(gaiaDxfParserPtr dxf,const char * path)3559 gaiaParseDxfFile (gaiaDxfParserPtr dxf, const char *path)
3560 {
3561 return gaiaParseDxfFileCommon (NULL, dxf, path);
3562 }
3563
3564 GAIAGEO_DECLARE int
gaiaParseDxfFile_r(const void * p_cache,gaiaDxfParserPtr dxf,const char * path)3565 gaiaParseDxfFile_r (const void *p_cache, gaiaDxfParserPtr dxf, const char *path)
3566 {
3567 return gaiaParseDxfFileCommon (p_cache, dxf, path);
3568 }
3569
3570 #endif /* GEOS enabled */
3571