Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: DXF Translator
4 : * Purpose: Definition of classes for OGR .dxf driver.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2009, Frank Warmerdam
9 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10 : * Copyright (c) 2017, Alan Thomas <alant@outlook.com.au>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #ifndef OGR_DXF_H_INCLUDED
16 : #define OGR_DXF_H_INCLUDED
17 :
18 : #include "ogrsf_frmts.h"
19 : #include "ogr_autocad_services.h"
20 : #include "cpl_conv.h"
21 : #include <vector>
22 : #include <map>
23 : #include <set>
24 : #include <queue>
25 : #include <memory>
26 :
27 : class OGRDXFDataSource;
28 : class OGRDXFFeature;
29 :
30 : /************************************************************************/
31 : /* DXFBlockDefinition */
32 : /* */
33 : /* Container for info about a block. */
34 : /************************************************************************/
35 :
36 : class DXFBlockDefinition
37 : {
38 : public:
39 75 : DXFBlockDefinition()
40 75 : {
41 75 : }
42 :
43 : ~DXFBlockDefinition();
44 :
45 : std::vector<OGRDXFFeature *> apoFeatures;
46 : };
47 :
48 : /************************************************************************/
49 : /* OGRDXFFeatureQueue */
50 : /************************************************************************/
51 :
52 : class OGRDXFFeatureQueue
53 : {
54 : std::queue<OGRDXFFeature *> apoFeatures;
55 :
56 : public:
57 571 : OGRDXFFeatureQueue()
58 571 : {
59 571 : }
60 :
61 : void push(OGRDXFFeature *poFeature);
62 :
63 1736 : OGRDXFFeature *front() const
64 : {
65 1736 : return apoFeatures.front();
66 : }
67 :
68 : void pop();
69 :
70 5977 : bool empty() const
71 : {
72 5977 : return apoFeatures.empty();
73 : }
74 :
75 : size_t size() const
76 : {
77 : return apoFeatures.size();
78 : }
79 : };
80 :
81 : /************************************************************************/
82 : /* OGRDXFBlocksLayer */
83 : /************************************************************************/
84 :
85 : class OGRDXFBlocksLayer final : public OGRLayer
86 : {
87 : OGRDXFDataSource *poDS;
88 :
89 : OGRFeatureDefn *poFeatureDefn;
90 :
91 : GIntBig iNextFID;
92 :
93 : std::map<CPLString, DXFBlockDefinition>::iterator oIt;
94 : CPLString osBlockName;
95 :
96 : OGRDXFFeatureQueue apoPendingFeatures;
97 :
98 : public:
99 : explicit OGRDXFBlocksLayer(OGRDXFDataSource *poDS);
100 : ~OGRDXFBlocksLayer();
101 :
102 : void ResetReading() override;
103 : OGRFeature *GetNextFeature() override;
104 :
105 14 : OGRFeatureDefn *GetLayerDefn() override
106 : {
107 14 : return poFeatureDefn;
108 : }
109 :
110 : int TestCapability(const char *) override;
111 :
112 : OGRDXFFeature *GetNextUnfilteredFeature();
113 : };
114 :
115 : /************************************************************************/
116 : /* OGRDXFInsertTransformer */
117 : /* */
118 : /* Stores the transformation needed to insert a block reference. */
119 : /************************************************************************/
120 :
121 : class OGRDXFInsertTransformer final : public OGRCoordinateTransformation
122 : {
123 : public:
124 370 : OGRDXFInsertTransformer() = default;
125 :
126 : double dfXOffset = 0.0;
127 : double dfYOffset = 0.0;
128 : double dfZOffset = 0.0;
129 : double dfXScale = 1.0;
130 : double dfYScale = 1.0;
131 : double dfZScale = 1.0;
132 : double dfAngle = 0.0;
133 :
134 696 : OGRDXFInsertTransformer GetOffsetTransformer()
135 : {
136 696 : OGRDXFInsertTransformer oResult;
137 696 : oResult.dfXOffset = this->dfXOffset;
138 696 : oResult.dfYOffset = this->dfYOffset;
139 696 : oResult.dfZOffset = this->dfZOffset;
140 696 : return oResult;
141 : }
142 :
143 696 : OGRDXFInsertTransformer GetRotateScaleTransformer()
144 : {
145 696 : OGRDXFInsertTransformer oResult;
146 696 : oResult.dfXScale = this->dfXScale;
147 696 : oResult.dfYScale = this->dfYScale;
148 696 : oResult.dfZScale = this->dfZScale;
149 696 : oResult.dfAngle = this->dfAngle;
150 696 : return oResult;
151 : }
152 :
153 0 : OGRCoordinateTransformation *Clone() const override
154 : {
155 0 : return new OGRDXFInsertTransformer(*this);
156 : }
157 :
158 0 : const OGRSpatialReference *GetSourceCS() const override
159 : {
160 0 : return nullptr;
161 : }
162 :
163 3410 : const OGRSpatialReference *GetTargetCS() const override
164 : {
165 3410 : return nullptr;
166 : }
167 :
168 3275 : int Transform(size_t nCount, double *x, double *y, double *z,
169 : double * /* t */, int *pabSuccess) override
170 : {
171 16649 : for (size_t i = 0; i < nCount; i++)
172 : {
173 13374 : x[i] *= dfXScale;
174 13374 : y[i] *= dfYScale;
175 13374 : if (z)
176 13374 : z[i] *= dfZScale;
177 :
178 13374 : const double dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
179 13374 : const double dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
180 :
181 13374 : x[i] = dfXNew;
182 13374 : y[i] = dfYNew;
183 :
184 13374 : x[i] += dfXOffset;
185 13374 : y[i] += dfYOffset;
186 13374 : if (z)
187 13374 : z[i] += dfZOffset;
188 :
189 13374 : if (pabSuccess)
190 13374 : pabSuccess[i] = TRUE;
191 : }
192 3275 : return TRUE;
193 : }
194 :
195 0 : OGRCoordinateTransformation *GetInverse() const override
196 : {
197 0 : return nullptr;
198 : }
199 : };
200 :
201 : /************************************************************************/
202 : /* OGRDXFAffineTransform */
203 : /* */
204 : /* A simple 3D affine transform used to keep track of the */
205 : /* transformation to be applied to an ASM entity. */
206 : /************************************************************************/
207 :
208 : class OGRDXFAffineTransform
209 : {
210 : public:
211 2 : OGRDXFAffineTransform()
212 2 : : adfData{1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}
213 : {
214 2 : }
215 :
216 : double adfData[12]; // Column-major: adfMatrix[5] is column 2, row 3
217 : // Last 3 elements are translation
218 :
219 : // Left composition (composes oOther o this), modifying this
220 6 : void ComposeWith(const OGRDXFInsertTransformer &oCT)
221 : {
222 : double adfNew[12];
223 :
224 6 : adfNew[0] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[0] -
225 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[1];
226 6 : adfNew[1] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[0] +
227 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[1];
228 6 : adfNew[2] = oCT.dfZScale * adfData[2];
229 :
230 6 : adfNew[3] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[3] -
231 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[4];
232 6 : adfNew[4] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[3] +
233 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[4];
234 6 : adfNew[5] = oCT.dfZScale * adfData[5];
235 :
236 6 : adfNew[6] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[6] -
237 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[7];
238 6 : adfNew[7] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[6] +
239 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[7];
240 6 : adfNew[8] = oCT.dfZScale * adfData[8];
241 :
242 6 : adfNew[9] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[9] -
243 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[10] +
244 6 : oCT.dfXOffset;
245 6 : adfNew[10] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[9] +
246 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[10] +
247 6 : oCT.dfYOffset;
248 6 : adfNew[11] = oCT.dfZScale * adfData[11] + oCT.dfZOffset;
249 :
250 6 : memcpy(adfData, adfNew, sizeof(adfNew));
251 6 : }
252 :
253 5 : void SetField(OGRFeature *poFeature, const char *pszFieldName) const
254 : {
255 5 : poFeature->SetField(pszFieldName, 12, adfData);
256 5 : }
257 : };
258 :
259 : /************************************************************************/
260 : /* OGRDXFOCSTransformer */
261 : /************************************************************************/
262 :
263 : class OGRDXFOCSTransformer final : public OGRCoordinateTransformation
264 : {
265 : private:
266 : double adfN[3];
267 : double adfAX[3];
268 : double adfAY[3];
269 :
270 : double dfDeterminant;
271 : double aadfInverse[4][4];
272 :
273 : public:
274 : explicit OGRDXFOCSTransformer(double adfNIn[3], bool bInverse = false);
275 :
276 0 : const OGRSpatialReference *GetSourceCS() const override
277 : {
278 0 : return nullptr;
279 : }
280 :
281 2078 : const OGRSpatialReference *GetTargetCS() const override
282 : {
283 2078 : return nullptr;
284 : }
285 :
286 : int Transform(size_t nCount, double *adfX, double *adfY, double *adfZ,
287 : double *adfT, int *pabSuccess) override;
288 :
289 : int InverseTransform(size_t nCount, double *adfX, double *adfY,
290 : double *adfZ);
291 :
292 : void ComposeOnto(OGRDXFAffineTransform &poCT) const;
293 :
294 0 : OGRCoordinateTransformation *Clone() const override
295 : {
296 0 : return new OGRDXFOCSTransformer(*this);
297 : }
298 :
299 0 : OGRCoordinateTransformation *GetInverse() const override
300 : {
301 0 : return nullptr;
302 : }
303 : };
304 :
305 : /************************************************************************/
306 : /* DXFTriple */
307 : /* */
308 : /* Represents a triple (X, Y, Z) used for various purposes in */
309 : /* DXF files. We do not use OGRPoint for this purpose, as the */
310 : /* triple does not always represent a point as such (for */
311 : /* example, it could contain a scale factor for each dimension). */
312 : /************************************************************************/
313 : struct DXFTriple
314 : {
315 : double dfX, dfY, dfZ;
316 :
317 27 : DXFTriple() : dfX(0.0), dfY(0.0), dfZ(0.0)
318 : {
319 27 : }
320 :
321 12587 : DXFTriple(double x, double y, double z) : dfX(x), dfY(y), dfZ(z)
322 : {
323 12587 : }
324 :
325 1956 : void ToArray(double adfOut[3]) const
326 : {
327 1956 : adfOut[0] = dfX;
328 1956 : adfOut[1] = dfY;
329 1956 : adfOut[2] = dfZ;
330 1956 : }
331 :
332 18 : DXFTriple &operator*=(const double dfValue)
333 : {
334 18 : dfX *= dfValue;
335 18 : dfY *= dfValue;
336 18 : dfZ *= dfValue;
337 18 : return *this;
338 : }
339 :
340 2 : DXFTriple &operator/=(const double dfValue)
341 : {
342 2 : dfX /= dfValue;
343 2 : dfY /= dfValue;
344 2 : dfZ /= dfValue;
345 2 : return *this;
346 : }
347 :
348 : bool operator==(const DXFTriple &oOther) const
349 : {
350 : return dfX == oOther.dfX && dfY == oOther.dfY && dfZ == oOther.dfZ;
351 : }
352 : };
353 :
354 : /************************************************************************/
355 : /* OGRDXFFeature */
356 : /* */
357 : /* Extends OGRFeature with some DXF-specific members. */
358 : /************************************************************************/
359 : class OGRDXFFeature final : public OGRFeature
360 : {
361 : friend class OGRDXFLayer;
362 :
363 : protected:
364 : // The feature's Object Coordinate System (OCS) unit normal vector
365 : DXFTriple oOCS;
366 :
367 : // A list of properties that are used to construct the style string
368 : std::map<CPLString, CPLString> oStyleProperties;
369 :
370 : // Additional data for INSERT entities
371 : bool bIsBlockReference;
372 : CPLString osBlockName;
373 : double dfBlockAngle;
374 : DXFTriple oBlockScale;
375 :
376 : // Used for INSERT entities when DXF_INLINE_BLOCKS is false, to store
377 : // the OCS insertion point
378 : DXFTriple oOriginalCoords;
379 :
380 : // Used in 3D mode to store transformation parameters for ASM entities
381 : std::unique_ptr<OGRDXFAffineTransform> poASMTransform;
382 :
383 : // Additional data for ATTRIB and ATTDEF entities
384 : CPLString osAttributeTag;
385 :
386 : // Store ATTRIB entities associated with an INSERT, for use when
387 : // DXF_INLINE_BLOCKS is true and a block with attributes is INSERTed
388 : // in another block
389 : std::vector<std::unique_ptr<OGRDXFFeature>> apoAttribFeatures;
390 :
391 : public:
392 : explicit OGRDXFFeature(OGRFeatureDefn *poFeatureDefn);
393 :
394 : OGRDXFFeature *CloneDXFFeature();
395 :
396 : DXFTriple GetOCS() const
397 : {
398 : return oOCS;
399 : }
400 :
401 2695 : bool IsBlockReference() const
402 : {
403 2695 : return bIsBlockReference;
404 : }
405 :
406 : CPLString GetBlockName() const
407 : {
408 : return osBlockName;
409 : }
410 :
411 : double GetBlockAngle() const
412 : {
413 : return dfBlockAngle;
414 : }
415 :
416 : DXFTriple GetBlockScale() const
417 : {
418 : return oBlockScale;
419 : }
420 :
421 793 : DXFTriple GetInsertOCSCoords() const
422 : {
423 793 : return oOriginalCoords;
424 : }
425 :
426 44 : CPLString GetAttributeTag() const
427 : {
428 44 : return osAttributeTag;
429 : }
430 :
431 : const std::vector<std::unique_ptr<OGRDXFFeature>> &GetAttribFeatures() const
432 : {
433 : return apoAttribFeatures;
434 : }
435 :
436 793 : void SetInsertOCSCoords(const DXFTriple &oTriple)
437 : {
438 793 : oOriginalCoords = oTriple;
439 793 : }
440 :
441 : void ApplyOCSTransformer(OGRGeometry *const poGeometry) const;
442 : void ApplyOCSTransformer(OGRDXFAffineTransform *const poCT) const;
443 : const CPLString GetColor(OGRDXFDataSource *const poDS,
444 : OGRDXFFeature *const poBlockFeature = nullptr);
445 : };
446 :
447 : /************************************************************************/
448 : /* OGRDXFLayer */
449 : /************************************************************************/
450 : class OGRDXFLayer final : public OGRLayer
451 : {
452 : friend class OGRDXFBlocksLayer;
453 :
454 : OGRDXFDataSource *poDS;
455 :
456 : OGRFeatureDefn *poFeatureDefn;
457 : GIntBig iNextFID;
458 :
459 : std::set<CPLString> oIgnoredEntities;
460 :
461 : OGRDXFFeatureQueue apoPendingFeatures;
462 :
463 : struct InsertState
464 : {
465 : OGRDXFInsertTransformer m_oTransformer{};
466 : CPLString m_osBlockName{};
467 : CPLStringList m_aosAttribs{};
468 : int m_nColumnCount = 0;
469 : int m_nRowCount = 0;
470 : int m_iCurCol = 0;
471 : int m_iCurRow = 0;
472 : double m_dfColumnSpacing = 0.0;
473 : double m_dfRowSpacing = 0.0;
474 : std::vector<std::unique_ptr<OGRDXFFeature>> m_apoAttribs{};
475 : std::unique_ptr<OGRDXFFeature> m_poTemplateFeature{};
476 : };
477 :
478 : InsertState m_oInsertState{};
479 :
480 : void ClearPendingFeatures();
481 :
482 : void TranslateGenericProperty(OGRDXFFeature *poFeature, int nCode,
483 : char *pszValue);
484 :
485 : void PrepareFeatureStyle(OGRDXFFeature *const poFeature,
486 : OGRDXFFeature *const poBlockFeature = nullptr);
487 : void PrepareBrushStyle(OGRDXFFeature *const poFeature,
488 : OGRDXFFeature *const poBlockFeature = nullptr);
489 : void PrepareLineStyle(OGRDXFFeature *const poFeature,
490 : OGRDXFFeature *const poBlockFeature = nullptr);
491 :
492 : OGRDXFFeature *TranslatePOINT();
493 : OGRDXFFeature *TranslateLINE();
494 : OGRDXFFeature *TranslatePOLYLINE();
495 : OGRDXFFeature *TranslateLWPOLYLINE();
496 : OGRDXFFeature *TranslateMLINE();
497 : OGRDXFFeature *TranslateCIRCLE();
498 : OGRDXFFeature *TranslateELLIPSE();
499 : OGRDXFFeature *TranslateARC();
500 : OGRDXFFeature *TranslateSPLINE();
501 : OGRDXFFeature *Translate3DFACE();
502 : bool TranslateINSERT();
503 : OGRDXFFeature *TranslateMTEXT();
504 : OGRDXFFeature *TranslateTEXT(const bool bIsAttribOrAttdef);
505 : OGRDXFFeature *TranslateDIMENSION();
506 : OGRDXFFeature *TranslateHATCH();
507 : OGRDXFFeature *TranslateSOLID();
508 : OGRDXFFeature *TranslateLEADER();
509 : OGRDXFFeature *TranslateMLEADER();
510 : OGRDXFFeature *TranslateASMEntity();
511 :
512 : static constexpr int FORTRAN_INDEXING = 1;
513 :
514 : bool GenerateINSERTFeatures();
515 : std::unique_ptr<OGRLineString>
516 : InsertSplineWithChecks(const int nDegree,
517 : std::vector<double> &adfControlPoints, bool bHasZ,
518 : int nControlPoints, std::vector<double> &adfKnots,
519 : int nKnots, std::vector<double> &adfWeights);
520 : static OGRGeometry *SimplifyBlockGeometry(OGRGeometryCollection *);
521 : OGRDXFFeature *InsertBlockInline(GUInt32 nInitialErrorCounter,
522 : const CPLString &osBlockName,
523 : OGRDXFInsertTransformer oTransformer,
524 : OGRDXFFeature *const poFeature,
525 : OGRDXFFeatureQueue &apoExtraFeatures,
526 : const bool bInlineNestedBlocks,
527 : const bool bMergeGeometry);
528 : static OGRDXFFeature *
529 : InsertBlockReference(const CPLString &osBlockName,
530 : const OGRDXFInsertTransformer &oTransformer,
531 : OGRDXFFeature *const poFeature);
532 : static void FormatDimension(CPLString &osText, const double dfValue,
533 : int nPrecision);
534 : void InsertArrowhead(OGRDXFFeature *const poFeature,
535 : const CPLString &osBlockName,
536 : OGRLineString *const poLine,
537 : const double dfArrowheadSize,
538 : const bool bReverse = false);
539 : OGRErr CollectBoundaryPath(OGRGeometryCollection *poGC,
540 : const double dfElevation);
541 : OGRErr CollectPolylinePath(OGRGeometryCollection *poGC,
542 : const double dfElevation);
543 :
544 : CPLString TextRecode(const char *);
545 : CPLString TextUnescape(const char *, bool);
546 :
547 : public:
548 : explicit OGRDXFLayer(OGRDXFDataSource *poDS);
549 : ~OGRDXFLayer();
550 :
551 : void ResetReading() override;
552 : OGRFeature *GetNextFeature() override;
553 :
554 323 : OGRFeatureDefn *GetLayerDefn() override
555 : {
556 323 : return poFeatureDefn;
557 : }
558 :
559 : int TestCapability(const char *) override;
560 :
561 : GDALDataset *GetDataset() override;
562 :
563 : OGRDXFFeature *GetNextUnfilteredFeature();
564 : };
565 :
566 : /************************************************************************/
567 : /* OGRDXFReader */
568 : /* */
569 : /* A class for very low level DXF reading without interpretation. */
570 : /************************************************************************/
571 :
572 : #define DXF_READER_ERROR() \
573 : do \
574 : { \
575 : CPLError(CE_Failure, CPLE_AppDefined, \
576 : "%s, %d: error at line %d of %s", __FILE__, __LINE__, \
577 : GetLineNumber(), GetDescription()); \
578 : } while (0)
579 : #define DXF_LAYER_READER_ERROR() \
580 : do \
581 : { \
582 : CPLError(CE_Failure, CPLE_AppDefined, \
583 : "%s, %d: error at line %d of %s", __FILE__, __LINE__, \
584 : poDS->GetLineNumber(), poDS->GetDescription()); \
585 : } while (0)
586 :
587 : class OGRDXFReader
588 : {
589 : int ReadValueRaw(char *pszValueBuffer, int nValueBufferSize);
590 :
591 : public:
592 : OGRDXFReader();
593 : ~OGRDXFReader();
594 :
595 : void Initialize(VSILFILE *fp);
596 :
597 : VSILFILE *fp;
598 :
599 : unsigned int iSrcBufferOffset;
600 : unsigned int nSrcBufferBytes;
601 : unsigned int iSrcBufferFileOffset;
602 : char achSrcBuffer[1025];
603 :
604 : unsigned int nLastValueSize;
605 : int nLineNumber;
606 :
607 : int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81);
608 : void UnreadValue();
609 : void LoadDiskChunk();
610 : void ResetReadPointer(unsigned int iNewOffset, int nNewLineNumber = 0);
611 : };
612 :
613 : /************************************************************************/
614 : /* OGRDXFFieldModes */
615 : /* */
616 : /* Represents which fields should be included in the data source. */
617 : /************************************************************************/
618 :
619 : enum OGRDXFFieldModes
620 : {
621 : ODFM_None = 0,
622 : ODFM_IncludeRawCodeValues = 0x1,
623 : ODFM_IncludeBlockFields = 0x2,
624 : ODFM_Include3DModeFields = 0x4
625 : };
626 :
627 : /************************************************************************/
628 : /* OGRDXFDataSource */
629 : /************************************************************************/
630 :
631 : class OGRDXFDataSource final : public GDALDataset
632 : {
633 : VSILFILE *fp;
634 :
635 : std::vector<OGRLayer *> apoLayers;
636 :
637 : unsigned int iEntitiesOffset;
638 : int iEntitiesLineNumber;
639 :
640 : std::map<CPLString, DXFBlockDefinition> oBlockMap;
641 : std::map<CPLString, CPLString> oBlockRecordHandles;
642 : std::map<CPLString, CPLString> oHeaderVariables;
643 :
644 : CPLString osEncoding;
645 :
646 : // indexed by layer name, then by property name.
647 : std::map<CPLString, std::map<CPLString, CPLString>> oLayerTable;
648 :
649 : // indexed by style name, then by property name.
650 : std::map<CPLString, std::map<CPLString, CPLString>> oTextStyleTable;
651 : std::map<CPLString, CPLString> oTextStyleHandles;
652 :
653 : // indexed by dimstyle name, then by DIM... variable name
654 : std::map<CPLString, std::map<CPLString, CPLString>> oDimStyleTable;
655 :
656 : std::map<CPLString, std::vector<double>> oLineTypeTable;
657 :
658 : bool bInlineBlocks;
659 : bool bMergeBlockGeometries;
660 : bool bTranslateEscapeSequences;
661 : bool bIncludeRawCodeValues;
662 : bool m_bClosedLineAsPolygon = false;
663 : double m_dfHatchTolerance = -1.0;
664 :
665 : bool b3DExtensibleMode;
666 : bool bHaveReadSolidData;
667 : std::map<CPLString, std::vector<GByte>> oSolidBinaryData;
668 :
669 : OGRDXFReader oReader;
670 :
671 : std::vector<CPLString> aosBlockInsertionStack;
672 :
673 : public:
674 : OGRDXFDataSource();
675 : ~OGRDXFDataSource();
676 :
677 : int Open(const char *pszFilename, bool bHeaderOnly,
678 : CSLConstList papszOptionsIn);
679 :
680 494 : int GetLayerCount() override
681 : {
682 494 : return static_cast<int>(apoLayers.size());
683 : }
684 :
685 : OGRLayer *GetLayer(int) override;
686 :
687 : int TestCapability(const char *) override;
688 :
689 : // The following is only used by OGRDXFLayer
690 :
691 1400 : bool InlineBlocks() const
692 : {
693 1400 : return bInlineBlocks;
694 : }
695 :
696 122 : bool ShouldMergeBlockGeometries() const
697 : {
698 122 : return bMergeBlockGeometries;
699 : }
700 :
701 148 : bool ShouldTranslateEscapes() const
702 : {
703 148 : return bTranslateEscapeSequences;
704 : }
705 :
706 2800 : bool ShouldIncludeRawCodeValues() const
707 : {
708 2800 : return bIncludeRawCodeValues;
709 : }
710 :
711 207 : bool In3DExtensibleMode() const
712 : {
713 207 : return b3DExtensibleMode;
714 : }
715 :
716 25 : bool ClosedLineAsPolygon() const
717 : {
718 25 : return m_bClosedLineAsPolygon;
719 : }
720 :
721 28 : double HatchTolerance() const
722 : {
723 28 : return m_dfHatchTolerance;
724 : }
725 :
726 : static void AddStandardFields(OGRFeatureDefn *poDef, const int nFieldModes);
727 :
728 : // Implemented in ogrdxf_blockmap.cpp
729 : bool ReadBlocksSection();
730 : DXFBlockDefinition *LookupBlock(const char *pszName);
731 : CPLString GetBlockNameByRecordHandle(const char *pszID);
732 :
733 42 : std::map<CPLString, DXFBlockDefinition> &GetBlockMap()
734 : {
735 42 : return oBlockMap;
736 : }
737 :
738 : bool PushBlockInsertion(const CPLString &osBlockName);
739 :
740 296 : void PopBlockInsertion()
741 : {
742 296 : aosBlockInsertionStack.pop_back();
743 296 : }
744 :
745 : // Layer and other Table Handling (ogrdatasource.cpp)
746 : bool ReadTablesSection();
747 : bool ReadLayerDefinition();
748 : bool ReadLineTypeDefinition();
749 : bool ReadTextStyleDefinition();
750 : bool ReadDimStyleDefinition();
751 : const char *LookupLayerProperty(const char *pszLayer,
752 : const char *pszProperty);
753 : const char *LookupTextStyleProperty(const char *pszTextStyle,
754 : const char *pszProperty,
755 : const char *pszDefault);
756 : bool LookupDimStyle(const char *pszDimstyle,
757 : std::map<CPLString, CPLString> &oDimStyleProperties);
758 :
759 4 : const std::map<CPLString, std::vector<double>> &GetLineTypeTable() const
760 : {
761 4 : return oLineTypeTable;
762 : }
763 :
764 : std::vector<double> LookupLineType(const char *pszName);
765 : bool TextStyleExists(const char *pszTextStyle);
766 : CPLString GetTextStyleNameByHandle(const char *pszID);
767 : static void PopulateDefaultDimStyleProperties(
768 : std::map<CPLString, CPLString> &oDimStyleProperties);
769 : size_t GetEntryFromAcDsDataSection(const char *pszEntityHandle,
770 : const GByte **pabyBuffer);
771 :
772 : // Header variables.
773 : bool ReadHeaderSection();
774 : const char *GetVariable(const char *pszName,
775 : const char *pszDefault = nullptr);
776 :
777 2918 : const char *GetEncoding()
778 : {
779 2918 : return osEncoding;
780 : }
781 :
782 : // reader related.
783 6 : int GetLineNumber()
784 : {
785 6 : return oReader.nLineNumber;
786 : }
787 :
788 134296 : int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81)
789 : {
790 134296 : return oReader.ReadValue(pszValueBuffer, nValueBufferSize);
791 : }
792 :
793 179 : void RestartEntities()
794 : {
795 179 : oReader.ResetReadPointer(iEntitiesOffset, iEntitiesLineNumber);
796 179 : }
797 :
798 2208 : void UnreadValue()
799 : {
800 2208 : oReader.UnreadValue();
801 2208 : }
802 :
803 56 : void ResetReadPointer(int iNewOffset)
804 : {
805 56 : oReader.ResetReadPointer(iNewOffset);
806 56 : }
807 : };
808 :
809 : /************************************************************************/
810 : /* OGRDXFWriterLayer */
811 : /************************************************************************/
812 :
813 : class OGRDXFWriterDS;
814 :
815 : class OGRDXFWriterLayer final : public OGRLayer
816 : {
817 : VSILFILE *fp;
818 : OGRFeatureDefn *poFeatureDefn;
819 :
820 : OGRDXFWriterDS *poDS;
821 :
822 : int WriteValue(int nCode, const char *pszValue);
823 : int WriteValue(int nCode, int nValue);
824 : int WriteValue(int nCode, double dfValue);
825 :
826 : OGRErr WriteCore(OGRFeature *);
827 : OGRErr WritePOINT(OGRFeature *);
828 : OGRErr WriteTEXT(OGRFeature *);
829 : OGRErr WritePOLYLINE(OGRFeature *, const OGRGeometry * = nullptr);
830 : OGRErr WriteHATCH(OGRFeature *, OGRGeometry * = nullptr);
831 : OGRErr WriteINSERT(OGRFeature *);
832 :
833 : static CPLString TextEscape(const char *);
834 : static int ColorStringToDXFColor(const char *);
835 : static std::vector<double> PrepareLineTypeDefinition(OGRStylePen *);
836 : static std::map<CPLString, CPLString>
837 : PrepareTextStyleDefinition(OGRStyleLabel *);
838 :
839 : std::map<CPLString, std::vector<double>> oNewLineTypes;
840 : std::map<CPLString, std::map<CPLString, CPLString>> oNewTextStyles;
841 : int nNextAutoID;
842 : int bWriteHatch;
843 :
844 : public:
845 : OGRDXFWriterLayer(OGRDXFWriterDS *poDS, VSILFILE *fp);
846 : ~OGRDXFWriterLayer();
847 :
848 16 : void ResetReading() override
849 : {
850 16 : }
851 :
852 16 : OGRFeature *GetNextFeature() override
853 : {
854 16 : return nullptr;
855 : }
856 :
857 494 : OGRFeatureDefn *GetLayerDefn() override
858 : {
859 494 : return poFeatureDefn;
860 : }
861 :
862 : int TestCapability(const char *) override;
863 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
864 : OGRErr CreateField(const OGRFieldDefn *poField,
865 : int bApproxOK = TRUE) override;
866 :
867 : GDALDataset *GetDataset() override;
868 :
869 : void ResetFP(VSILFILE *);
870 :
871 48 : std::map<CPLString, std::vector<double>> &GetNewLineTypeMap()
872 : {
873 48 : return oNewLineTypes;
874 : }
875 :
876 48 : std::map<CPLString, std::map<CPLString, CPLString>> &GetNewTextStyleMap()
877 : {
878 48 : return oNewTextStyles;
879 : }
880 : };
881 :
882 : /************************************************************************/
883 : /* OGRDXFBlocksWriterLayer */
884 : /************************************************************************/
885 :
886 : class OGRDXFBlocksWriterLayer final : public OGRLayer
887 : {
888 : OGRFeatureDefn *poFeatureDefn;
889 :
890 : public:
891 : explicit OGRDXFBlocksWriterLayer(OGRDXFWriterDS *poDS);
892 : ~OGRDXFBlocksWriterLayer();
893 :
894 0 : void ResetReading() override
895 : {
896 0 : }
897 :
898 0 : OGRFeature *GetNextFeature() override
899 : {
900 0 : return nullptr;
901 : }
902 :
903 10 : OGRFeatureDefn *GetLayerDefn() override
904 : {
905 10 : return poFeatureDefn;
906 : }
907 :
908 : int TestCapability(const char *) override;
909 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
910 : OGRErr CreateField(const OGRFieldDefn *poField,
911 : int bApproxOK = TRUE) override;
912 :
913 : std::vector<OGRFeature *> apoBlocks;
914 : OGRFeature *FindBlock(const char *);
915 : };
916 :
917 : /************************************************************************/
918 : /* OGRDXFWriterDS */
919 : /************************************************************************/
920 :
921 : class OGRDXFWriterDS final : public GDALDataset
922 : {
923 : friend class OGRDXFWriterLayer;
924 :
925 : int nNextFID;
926 :
927 : OGRDXFWriterLayer *poLayer;
928 : OGRDXFBlocksWriterLayer *poBlocksLayer;
929 : VSILFILE *fp;
930 : CPLString osTrailerFile;
931 :
932 : CPLString osTempFilename;
933 : VSILFILE *fpTemp;
934 :
935 : CPLString osHeaderFile;
936 : OGRDXFDataSource oHeaderDS;
937 : char **papszLayersToCreate;
938 :
939 : vsi_l_offset nHANDSEEDOffset;
940 :
941 : std::vector<int> anDefaultLayerCode;
942 : std::vector<CPLString> aosDefaultLayerText;
943 :
944 : std::set<CPLString> aosUsedEntities;
945 : void ScanForEntities(const char *pszFilename, const char *pszTarget);
946 :
947 : bool WriteNewLineTypeRecords(VSILFILE *fp);
948 : bool WriteNewTextStyleRecords(VSILFILE *fp);
949 : bool WriteNewBlockRecords(VSILFILE *);
950 : bool WriteNewBlockDefinitions(VSILFILE *);
951 : bool WriteNewLayerDefinitions(VSILFILE *);
952 : bool TransferUpdateHeader(VSILFILE *);
953 : bool TransferUpdateTrailer(VSILFILE *);
954 : bool FixupHANDSEED(VSILFILE *);
955 :
956 : OGREnvelope oGlobalEnvelope;
957 :
958 : bool m_bHeaderFileIsTemp = false;
959 : bool m_bTrailerFileIsTemp = false;
960 : OGRSpatialReference m_oSRS{};
961 : std::string m_osINSUNITS = "AUTO";
962 : std::string m_osMEASUREMENT = "HEADER_VALUE";
963 :
964 : public:
965 : OGRDXFWriterDS();
966 : ~OGRDXFWriterDS();
967 :
968 : int Open(const char *pszFilename, char **papszOptions);
969 :
970 : int GetLayerCount() override;
971 : OGRLayer *GetLayer(int) override;
972 :
973 : int TestCapability(const char *) override;
974 :
975 : OGRLayer *ICreateLayer(const char *pszName,
976 : const OGRGeomFieldDefn *poGeomFieldDefn,
977 : CSLConstList papszOptions) override;
978 :
979 : bool CheckEntityID(const char *pszEntityID);
980 : bool WriteEntityID(VSILFILE *fp, unsigned int &nAssignedFID,
981 : GIntBig nPreferredFID = OGRNullFID);
982 :
983 : void UpdateExtent(OGREnvelope *psEnvelope);
984 : };
985 :
986 : #endif /* ndef OGR_DXF_H_INCLUDED */
|