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