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