Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: DXF Translator
4 : * Purpose: Implements translation support for HATCH elements as part
5 : * of the OGRDXFLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
10 : * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
11 : * Copyright (c) 2017, Alan Thomas <alant@outlook.com.au>
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "ogr_dxf.h"
33 : #include "cpl_conv.h"
34 : #include "ogr_api.h"
35 :
36 : #include <algorithm>
37 : #include <cmath>
38 : #include "ogrdxf_polyline_smooth.h"
39 :
40 : /************************************************************************/
41 : /* TranslateHATCH() */
42 : /* */
43 : /* We mostly just try to convert hatch objects as polygons or */
44 : /* multipolygons representing the hatched area. It is hard to */
45 : /* preserve the actual details of the hatching. */
46 : /************************************************************************/
47 :
48 28 : OGRDXFFeature *OGRDXFLayer::TranslateHATCH()
49 :
50 : {
51 : char szLineBuf[257];
52 28 : int nCode = 0;
53 28 : OGRDXFFeature *poFeature = new OGRDXFFeature(poFeatureDefn);
54 :
55 56 : CPLString osHatchPattern;
56 28 : double dfElevation = 0.0; // Z value to be used for EVERY point
57 : /* int nFillFlag = 0; */
58 56 : OGRGeometryCollection oGC;
59 :
60 880 : while ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) > 0)
61 : {
62 852 : switch (nCode)
63 : {
64 28 : case 30:
65 : // Constant elevation.
66 28 : dfElevation = CPLAtof(szLineBuf);
67 28 : break;
68 :
69 28 : case 70:
70 : /* nFillFlag = atoi(szLineBuf); */
71 28 : break;
72 :
73 26 : case 2:
74 26 : osHatchPattern = szLineBuf;
75 26 : poFeature->SetField("Text", osHatchPattern.c_str());
76 26 : break;
77 :
78 28 : case 91:
79 : {
80 28 : int nBoundaryPathCount = atoi(szLineBuf);
81 :
82 65 : for (int iBoundary = 0; iBoundary < nBoundaryPathCount;
83 : iBoundary++)
84 : {
85 37 : if (CollectBoundaryPath(&oGC, dfElevation) != OGRERR_NONE)
86 0 : break;
87 : }
88 : }
89 28 : break;
90 :
91 742 : default:
92 742 : TranslateGenericProperty(poFeature, nCode, szLineBuf);
93 742 : break;
94 : }
95 : }
96 28 : if (nCode < 0)
97 : {
98 0 : DXF_LAYER_READER_ERROR();
99 0 : delete poFeature;
100 0 : return nullptr;
101 : }
102 :
103 28 : if (nCode == 0)
104 28 : poDS->UnreadValue();
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Obtain a tolerance value used when building the polygon. */
108 : /* -------------------------------------------------------------------- */
109 28 : double dfTolerance = atof(CPLGetConfigOption("DXF_HATCH_TOLERANCE", "-1"));
110 28 : if (dfTolerance < 0)
111 : {
112 : // If the configuration variable isn't set, compute the bounding box
113 : // and work out a tolerance from that
114 28 : OGREnvelope oEnvelope;
115 28 : oGC.getEnvelope(&oEnvelope);
116 56 : dfTolerance = std::max(oEnvelope.MaxX - oEnvelope.MinX,
117 28 : oEnvelope.MaxY - oEnvelope.MinY) *
118 : 1e-7;
119 : }
120 :
121 : /* -------------------------------------------------------------------- */
122 : /* Try to turn the set of lines into something useful. */
123 : /* -------------------------------------------------------------------- */
124 : OGRErr eErr;
125 :
126 28 : OGRGeometry *poFinalGeom = (OGRGeometry *)OGRBuildPolygonFromEdges(
127 : (OGRGeometryH)&oGC, TRUE, TRUE, dfTolerance, &eErr);
128 28 : if (eErr != OGRERR_NONE)
129 : {
130 0 : delete poFinalGeom;
131 0 : OGRMultiLineString *poMLS = new OGRMultiLineString();
132 0 : for (int i = 0; i < oGC.getNumGeometries(); i++)
133 0 : poMLS->addGeometry(oGC.getGeometryRef(i));
134 0 : poFinalGeom = poMLS;
135 : }
136 :
137 28 : poFeature->ApplyOCSTransformer(poFinalGeom);
138 28 : poFeature->SetGeometryDirectly(poFinalGeom);
139 :
140 28 : PrepareBrushStyle(poFeature);
141 :
142 28 : return poFeature;
143 : }
144 :
145 : /************************************************************************/
146 : /* CollectBoundaryPath() */
147 : /************************************************************************/
148 :
149 37 : OGRErr OGRDXFLayer::CollectBoundaryPath(OGRGeometryCollection *poGC,
150 : const double dfElevation)
151 :
152 : {
153 : char szLineBuf[257];
154 :
155 : /* -------------------------------------------------------------------- */
156 : /* Read the boundary path type. */
157 : /* -------------------------------------------------------------------- */
158 37 : int nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
159 37 : if (nCode != 92)
160 : {
161 0 : DXF_LAYER_READER_ERROR();
162 0 : return OGRERR_FAILURE;
163 : }
164 :
165 37 : const int nBoundaryPathType = atoi(szLineBuf);
166 :
167 : /* ==================================================================== */
168 : /* Handle polyline loops. */
169 : /* ==================================================================== */
170 37 : if (nBoundaryPathType & 0x02)
171 18 : return CollectPolylinePath(poGC, dfElevation);
172 :
173 : /* ==================================================================== */
174 : /* Handle non-polyline loops. */
175 : /* ==================================================================== */
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Read number of edges. */
179 : /* -------------------------------------------------------------------- */
180 19 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
181 19 : if (nCode != 93)
182 : {
183 0 : DXF_LAYER_READER_ERROR();
184 0 : return OGRERR_FAILURE;
185 : }
186 :
187 19 : const int nEdgeCount = atoi(szLineBuf);
188 :
189 : /* -------------------------------------------------------------------- */
190 : /* Loop reading edges. */
191 : /* -------------------------------------------------------------------- */
192 84 : for (int iEdge = 0; iEdge < nEdgeCount; iEdge++)
193 : {
194 : /* --------------------------------------------------------------------
195 : */
196 : /* Read the edge type. */
197 : /* --------------------------------------------------------------------
198 : */
199 65 : const int ET_LINE = 1;
200 65 : const int ET_CIRCULAR_ARC = 2;
201 65 : const int ET_ELLIPTIC_ARC = 3;
202 65 : const int ET_SPLINE = 4;
203 :
204 65 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
205 65 : if (nCode != 72)
206 : {
207 0 : DXF_LAYER_READER_ERROR();
208 0 : return OGRERR_FAILURE;
209 : }
210 :
211 65 : int nEdgeType = atoi(szLineBuf);
212 :
213 : /* --------------------------------------------------------------------
214 : */
215 : /* Process a line edge. */
216 : /* --------------------------------------------------------------------
217 : */
218 65 : if (nEdgeType == ET_LINE)
219 : {
220 45 : double dfStartX = 0.0;
221 :
222 45 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10)
223 45 : dfStartX = CPLAtof(szLineBuf);
224 : else
225 0 : break;
226 :
227 45 : double dfStartY = 0.0;
228 :
229 45 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20)
230 45 : dfStartY = CPLAtof(szLineBuf);
231 : else
232 0 : break;
233 :
234 45 : double dfEndX = 0.0;
235 :
236 45 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 11)
237 45 : dfEndX = CPLAtof(szLineBuf);
238 : else
239 0 : break;
240 :
241 45 : double dfEndY = 0.0;
242 :
243 45 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 21)
244 45 : dfEndY = CPLAtof(szLineBuf);
245 : else
246 0 : break;
247 :
248 45 : OGRLineString *poLS = new OGRLineString();
249 :
250 45 : poLS->addPoint(dfStartX, dfStartY, dfElevation);
251 45 : poLS->addPoint(dfEndX, dfEndY, dfElevation);
252 :
253 45 : poGC->addGeometryDirectly(poLS);
254 : }
255 : /* --------------------------------------------------------------------
256 : */
257 : /* Process a circular arc. */
258 : /* --------------------------------------------------------------------
259 : */
260 20 : else if (nEdgeType == ET_CIRCULAR_ARC)
261 : {
262 12 : double dfCenterX = 0.0;
263 :
264 12 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10)
265 12 : dfCenterX = CPLAtof(szLineBuf);
266 : else
267 0 : break;
268 :
269 12 : double dfCenterY = 0.0;
270 :
271 12 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20)
272 12 : dfCenterY = CPLAtof(szLineBuf);
273 : else
274 0 : break;
275 :
276 12 : double dfRadius = 0.0;
277 :
278 12 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 40)
279 12 : dfRadius = CPLAtof(szLineBuf);
280 : else
281 0 : break;
282 :
283 12 : double dfStartAngle = 0.0;
284 :
285 12 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 50)
286 12 : dfStartAngle = CPLAtof(szLineBuf);
287 : else
288 0 : break;
289 :
290 12 : double dfEndAngle = 0.0;
291 :
292 12 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 51)
293 12 : dfEndAngle = CPLAtof(szLineBuf);
294 : else
295 0 : break;
296 :
297 12 : bool bCounterClockwise = false;
298 :
299 12 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 73)
300 12 : bCounterClockwise = atoi(szLineBuf) != 0;
301 0 : else if (nCode >= 0)
302 0 : poDS->UnreadValue();
303 : else
304 0 : break;
305 :
306 12 : if (dfStartAngle > dfEndAngle)
307 4 : dfEndAngle += 360.0;
308 12 : if (bCounterClockwise)
309 : {
310 8 : dfStartAngle *= -1;
311 8 : dfEndAngle *= -1;
312 : }
313 :
314 12 : if (fabs(dfEndAngle - dfStartAngle) <= 361.0)
315 : {
316 12 : OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
317 : dfCenterX, dfCenterY, dfElevation, dfRadius, dfRadius, 0.0,
318 12 : dfStartAngle, dfEndAngle, 0.0, poDS->InlineBlocks());
319 :
320 : // If the input was 2D, we assume we want to keep it that way
321 12 : if (dfElevation == 0.0)
322 8 : poArc->flattenTo2D();
323 :
324 12 : poGC->addGeometryDirectly(poArc);
325 : }
326 : else
327 : {
328 : // TODO: emit error ?
329 : }
330 : }
331 :
332 : /* --------------------------------------------------------------------
333 : */
334 : /* Process an elliptical arc. */
335 : /* --------------------------------------------------------------------
336 : */
337 8 : else if (nEdgeType == ET_ELLIPTIC_ARC)
338 : {
339 6 : double dfCenterX = 0.0;
340 :
341 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10)
342 6 : dfCenterX = CPLAtof(szLineBuf);
343 : else
344 0 : break;
345 :
346 6 : double dfCenterY = 0.0;
347 :
348 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20)
349 6 : dfCenterY = CPLAtof(szLineBuf);
350 : else
351 0 : break;
352 :
353 6 : double dfMajorX = 0.0;
354 :
355 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 11)
356 6 : dfMajorX = CPLAtof(szLineBuf);
357 : else
358 0 : break;
359 :
360 6 : double dfMajorY = 0.0;
361 :
362 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 21)
363 6 : dfMajorY = CPLAtof(szLineBuf);
364 : else
365 0 : break;
366 :
367 6 : double dfRatio = 0.0;
368 :
369 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 40)
370 6 : dfRatio = CPLAtof(szLineBuf);
371 6 : if (dfRatio == 0.0)
372 0 : break;
373 :
374 6 : double dfStartAngle = 0.0;
375 :
376 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 50)
377 6 : dfStartAngle = CPLAtof(szLineBuf);
378 : else
379 0 : break;
380 :
381 6 : double dfEndAngle = 0.0;
382 :
383 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 51)
384 6 : dfEndAngle = CPLAtof(szLineBuf);
385 : else
386 0 : break;
387 :
388 6 : bool bCounterClockwise = false;
389 :
390 6 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 73)
391 6 : bCounterClockwise = atoi(szLineBuf) != 0;
392 0 : else if (nCode >= 0)
393 0 : poDS->UnreadValue();
394 : else
395 0 : break;
396 :
397 6 : if (dfStartAngle > dfEndAngle)
398 0 : dfEndAngle += 360.0;
399 6 : if (bCounterClockwise)
400 : {
401 5 : dfStartAngle *= -1;
402 5 : dfEndAngle *= -1;
403 : }
404 :
405 : const double dfMajorRadius =
406 6 : sqrt(dfMajorX * dfMajorX + dfMajorY * dfMajorY);
407 6 : const double dfMinorRadius = dfMajorRadius * dfRatio;
408 :
409 : const double dfRotation =
410 6 : -1 * atan2(dfMajorY, dfMajorX) * 180 / M_PI;
411 :
412 : // The start and end angles are stored as circular angles. However,
413 : // approximateArcAngles is expecting elliptical angles (what AutoCAD
414 : // calls "parameters"), so let's transform them.
415 6 : dfStartAngle =
416 6 : 180.0 * round(dfStartAngle / 180) +
417 6 : (fabs(fmod(dfStartAngle, 180)) == 90
418 4 : ? (std::signbit(dfStartAngle) ? 180 : -180)
419 : : 0) +
420 6 : atan((1.0 / dfRatio) * tan(dfStartAngle * M_PI / 180)) * 180 /
421 : M_PI;
422 6 : dfEndAngle = 180.0 * round(dfEndAngle / 180) +
423 6 : (fabs(fmod(dfEndAngle, 180)) == 90
424 1 : ? (std::signbit(dfEndAngle) ? 180 : -180)
425 : : 0) +
426 6 : atan((1.0 / dfRatio) * tan(dfEndAngle * M_PI / 180)) *
427 6 : 180 / M_PI;
428 :
429 6 : if (fabs(dfEndAngle - dfStartAngle) <= 361.0)
430 : {
431 6 : OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
432 : dfCenterX, dfCenterY, dfElevation, dfMajorRadius,
433 : dfMinorRadius, dfRotation, dfStartAngle, dfEndAngle, 0.0,
434 6 : poDS->InlineBlocks());
435 :
436 : // If the input was 2D, we assume we want to keep it that way
437 6 : if (dfElevation == 0.0)
438 2 : poArc->flattenTo2D();
439 :
440 6 : poGC->addGeometryDirectly(poArc);
441 : }
442 : else
443 : {
444 : // TODO: emit error ?
445 : }
446 : }
447 :
448 : /* --------------------------------------------------------------------
449 : */
450 : /* Process an elliptical arc. */
451 : /* --------------------------------------------------------------------
452 : */
453 2 : else if (nEdgeType == ET_SPLINE)
454 : {
455 2 : int nDegree = 3;
456 :
457 2 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 94)
458 2 : nDegree = atoi(szLineBuf);
459 : else
460 0 : break;
461 :
462 : // Skip a few things we don't care about
463 2 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) != 73)
464 0 : break;
465 2 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) != 74)
466 0 : break;
467 :
468 2 : int nKnots = 0;
469 :
470 2 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 95)
471 2 : nKnots = atoi(szLineBuf);
472 : else
473 0 : break;
474 :
475 2 : int nControlPoints = 0;
476 :
477 2 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 96)
478 2 : nControlPoints = atoi(szLineBuf);
479 : else
480 0 : break;
481 :
482 2 : std::vector<double> adfKnots(1, 0.0);
483 :
484 2 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
485 2 : if (nCode != 40)
486 0 : break;
487 :
488 23 : while (nCode == 40)
489 : {
490 21 : adfKnots.push_back(CPLAtof(szLineBuf));
491 21 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
492 : }
493 :
494 2 : std::vector<double> adfControlPoints(1, 0.0);
495 2 : std::vector<double> adfWeights(1, 0.0);
496 :
497 2 : if (nCode != 10)
498 0 : break;
499 :
500 15 : while (nCode == 10)
501 : {
502 13 : adfControlPoints.push_back(CPLAtof(szLineBuf));
503 :
504 13 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) ==
505 : 20)
506 : {
507 13 : adfControlPoints.push_back(CPLAtof(szLineBuf));
508 : }
509 : else
510 0 : break;
511 :
512 13 : adfControlPoints.push_back(0.0); // Z coordinate
513 :
514 : // 42 (weights) are optional
515 13 : if ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) ==
516 : 42)
517 : {
518 7 : adfWeights.push_back(CPLAtof(szLineBuf));
519 7 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
520 : }
521 : }
522 :
523 : // Skip past the number of fit points
524 2 : if (nCode != 97)
525 0 : break;
526 :
527 : // Eat the rest of this section, if present, until the next
528 : // boundary segment (72) or the conclusion of the boundary data (97)
529 2 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
530 14 : while (nCode > 0 && nCode != 72 && nCode != 97)
531 12 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
532 2 : if (nCode > 0)
533 2 : poDS->UnreadValue();
534 :
535 : auto poLS = InsertSplineWithChecks(nDegree, adfControlPoints,
536 : nControlPoints, adfKnots, nKnots,
537 2 : adfWeights);
538 :
539 2 : if (!poLS)
540 : {
541 0 : DXF_LAYER_READER_ERROR();
542 0 : return OGRERR_FAILURE;
543 : }
544 :
545 2 : poGC->addGeometryDirectly(poLS.release());
546 : }
547 :
548 : else
549 : {
550 0 : CPLDebug("DXF", "Unsupported HATCH boundary line type:%d",
551 : nEdgeType);
552 0 : return OGRERR_UNSUPPORTED_OPERATION;
553 : }
554 : }
555 :
556 19 : if (nCode < 0)
557 : {
558 0 : DXF_LAYER_READER_ERROR();
559 0 : return OGRERR_FAILURE;
560 : }
561 :
562 : /* -------------------------------------------------------------------- */
563 : /* Skip through source boundary objects if present. */
564 : /* -------------------------------------------------------------------- */
565 19 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
566 19 : if (nCode != 97)
567 : {
568 0 : if (nCode < 0)
569 0 : return OGRERR_FAILURE;
570 0 : poDS->UnreadValue();
571 : }
572 : else
573 : {
574 19 : int iObj, nObjCount = atoi(szLineBuf);
575 :
576 21 : for (iObj = 0; iObj < nObjCount; iObj++)
577 : {
578 2 : if (poDS->ReadValue(szLineBuf, sizeof(szLineBuf)) < 0)
579 0 : return OGRERR_FAILURE;
580 : }
581 : }
582 :
583 19 : return OGRERR_NONE;
584 : }
585 :
586 : /************************************************************************/
587 : /* CollectPolylinePath() */
588 : /************************************************************************/
589 :
590 18 : OGRErr OGRDXFLayer::CollectPolylinePath(OGRGeometryCollection *poGC,
591 : const double dfElevation)
592 :
593 : {
594 18 : int nCode = 0;
595 : char szLineBuf[257];
596 36 : DXFSmoothPolyline oSmoothPolyline;
597 18 : double dfBulge = 0.0;
598 18 : double dfX = 0.0;
599 18 : double dfY = 0.0;
600 18 : bool bHaveX = false;
601 18 : bool bHaveY = false;
602 18 : bool bIsClosed = false;
603 18 : int nVertexCount = -1;
604 18 : bool bHaveBulges = false;
605 :
606 18 : if (dfElevation != 0)
607 1 : oSmoothPolyline.setCoordinateDimension(3);
608 :
609 : /* -------------------------------------------------------------------- */
610 : /* Read the boundary path type. */
611 : /* -------------------------------------------------------------------- */
612 224 : while ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) > 0)
613 : {
614 224 : if (nVertexCount > 0 && (int)oSmoothPolyline.size() == nVertexCount)
615 18 : break;
616 :
617 206 : switch (nCode)
618 : {
619 18 : case 93:
620 18 : nVertexCount = atoi(szLineBuf);
621 18 : break;
622 :
623 18 : case 72:
624 18 : bHaveBulges = CPL_TO_BOOL(atoi(szLineBuf));
625 18 : break;
626 :
627 18 : case 73:
628 18 : bIsClosed = CPL_TO_BOOL(atoi(szLineBuf));
629 18 : break;
630 :
631 76 : case 10:
632 76 : if (bHaveX && bHaveY)
633 : {
634 0 : oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
635 0 : dfBulge = 0.0;
636 0 : bHaveY = false;
637 : }
638 76 : dfX = CPLAtof(szLineBuf);
639 76 : bHaveX = true;
640 76 : break;
641 :
642 76 : case 20:
643 76 : if (bHaveX && bHaveY)
644 : {
645 0 : oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
646 0 : dfBulge = 0.0;
647 0 : bHaveX = false;
648 : }
649 76 : dfY = CPLAtof(szLineBuf);
650 76 : bHaveY = true;
651 76 : if (bHaveX /* && bHaveY */ && !bHaveBulges)
652 : {
653 76 : oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
654 76 : dfBulge = 0.0;
655 76 : bHaveX = false;
656 76 : bHaveY = false;
657 : }
658 76 : break;
659 :
660 0 : case 42:
661 0 : dfBulge = CPLAtof(szLineBuf);
662 0 : if (bHaveX && bHaveY)
663 : {
664 0 : oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
665 0 : dfBulge = 0.0;
666 0 : bHaveX = false;
667 0 : bHaveY = false;
668 : }
669 0 : break;
670 :
671 0 : default:
672 0 : break;
673 : }
674 : }
675 18 : if (nCode < 0)
676 : {
677 0 : DXF_LAYER_READER_ERROR();
678 0 : return OGRERR_FAILURE;
679 : }
680 :
681 18 : if (nCode != 10 && nCode != 20 && nCode != 42)
682 18 : poDS->UnreadValue();
683 :
684 18 : if (bHaveX && bHaveY)
685 0 : oSmoothPolyline.AddPoint(dfX, dfY, dfElevation, dfBulge);
686 :
687 18 : if (bIsClosed)
688 18 : oSmoothPolyline.Close();
689 :
690 18 : if (oSmoothPolyline.IsEmpty())
691 : {
692 0 : return OGRERR_FAILURE;
693 : }
694 :
695 : // Only process polylines with at least 2 vertices
696 18 : if (nVertexCount >= 2)
697 : {
698 18 : oSmoothPolyline.SetUseMaxGapWhenTessellatingArcs(poDS->InlineBlocks());
699 18 : poGC->addGeometryDirectly(oSmoothPolyline.Tessellate());
700 : }
701 :
702 : /* -------------------------------------------------------------------- */
703 : /* Skip through source boundary objects if present. */
704 : /* -------------------------------------------------------------------- */
705 18 : nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf));
706 18 : if (nCode != 97)
707 : {
708 0 : if (nCode < 0)
709 0 : return OGRERR_FAILURE;
710 0 : poDS->UnreadValue();
711 : }
712 : else
713 : {
714 18 : int iObj, nObjCount = atoi(szLineBuf);
715 :
716 18 : for (iObj = 0; iObj < nObjCount; iObj++)
717 : {
718 0 : if (poDS->ReadValue(szLineBuf, sizeof(szLineBuf)) < 0)
719 0 : return OGRERR_FAILURE;
720 : }
721 : }
722 18 : return OGRERR_NONE;
723 : }
|