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 82 : DXFBlockDefinition()
40 82 : {
41 82 : }
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 608 : OGRDXFFeatureQueue()
58 608 : {
59 608 : }
60 :
61 : void push(OGRDXFFeature *poFeature);
62 :
63 2023 : OGRDXFFeature *front() const
64 : {
65 2023 : return apoFeatures.front();
66 : }
67 :
68 : void pop();
69 :
70 6510 : bool empty() const
71 : {
72 6510 : 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 17 : OGRFeatureDefn *GetLayerDefn() override
106 : {
107 17 : 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 387 : 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 888 : OGRDXFInsertTransformer GetOffsetTransformer()
135 : {
136 888 : OGRDXFInsertTransformer oResult;
137 888 : oResult.dfXOffset = this->dfXOffset;
138 888 : oResult.dfYOffset = this->dfYOffset;
139 888 : oResult.dfZOffset = this->dfZOffset;
140 888 : return oResult;
141 : }
142 :
143 888 : OGRDXFInsertTransformer GetRotateScaleTransformer()
144 : {
145 888 : OGRDXFInsertTransformer oResult;
146 888 : oResult.dfXScale = this->dfXScale;
147 888 : oResult.dfYScale = this->dfYScale;
148 888 : oResult.dfZScale = this->dfZScale;
149 888 : oResult.dfAngle = this->dfAngle;
150 888 : 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 3833 : const OGRSpatialReference *GetTargetCS() const override
164 : {
165 3833 : return nullptr;
166 : }
167 :
168 3692 : int Transform(size_t nCount, double *x, double *y, double *z,
169 : double * /* t */, int *pabSuccess) override
170 : {
171 19045 : for (size_t i = 0; i < nCount; i++)
172 : {
173 15353 : x[i] *= dfXScale;
174 15353 : y[i] *= dfYScale;
175 15353 : if (z)
176 15353 : z[i] *= dfZScale;
177 :
178 15353 : const double dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
179 15353 : const double dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
180 :
181 15353 : x[i] = dfXNew;
182 15353 : y[i] = dfYNew;
183 :
184 15353 : x[i] += dfXOffset;
185 15353 : y[i] += dfYOffset;
186 15353 : if (z)
187 15353 : z[i] += dfZOffset;
188 :
189 15353 : if (pabSuccess)
190 15353 : pabSuccess[i] = TRUE;
191 : }
192 3692 : 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 2302 : const OGRSpatialReference *GetTargetCS() const override
282 : {
283 2302 : 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 13145 : DXFTriple(double x, double y, double z) : dfX(x), dfY(y), dfZ(z)
322 : {
323 13145 : }
324 :
325 2178 : void ToArray(double adfOut[3]) const
326 : {
327 2178 : adfOut[0] = dfX;
328 2178 : adfOut[1] = dfY;
329 2178 : adfOut[2] = dfZ;
330 2178 : }
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 2859 : bool IsBlockReference() const
402 : {
403 2859 : 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 797 : DXFTriple GetInsertOCSCoords() const
422 : {
423 797 : return oOriginalCoords;
424 : }
425 :
426 45 : CPLString GetAttributeTag() const
427 : {
428 45 : return osAttributeTag;
429 : }
430 :
431 : const std::vector<std::unique_ptr<OGRDXFFeature>> &GetAttribFeatures() const
432 : {
433 : return apoAttribFeatures;
434 : }
435 :
436 797 : void SetInsertOCSCoords(const DXFTriple &oTriple)
437 : {
438 797 : oOriginalCoords = oTriple;
439 797 : }
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 *TranslateWIPEOUT();
511 : OGRDXFFeature *TranslateASMEntity();
512 :
513 : static constexpr int FORTRAN_INDEXING = 1;
514 :
515 : bool GenerateINSERTFeatures();
516 : std::unique_ptr<OGRLineString>
517 : InsertSplineWithChecks(const int nDegree,
518 : std::vector<double> &adfControlPoints, bool bHasZ,
519 : int nControlPoints, std::vector<double> &adfKnots,
520 : int nKnots, std::vector<double> &adfWeights);
521 : static OGRGeometry *SimplifyBlockGeometry(OGRGeometryCollection *);
522 : OGRDXFFeature *InsertBlockInline(GUInt32 nInitialErrorCounter,
523 : const CPLString &osBlockName,
524 : OGRDXFInsertTransformer oTransformer,
525 : OGRDXFFeature *const poFeature,
526 : OGRDXFFeatureQueue &apoExtraFeatures,
527 : const bool bInlineNestedBlocks,
528 : const bool bMergeGeometry);
529 : static OGRDXFFeature *
530 : InsertBlockReference(const CPLString &osBlockName,
531 : const OGRDXFInsertTransformer &oTransformer,
532 : OGRDXFFeature *const poFeature);
533 : static void FormatDimension(CPLString &osText, const double dfValue,
534 : int nPrecision);
535 : void InsertArrowhead(OGRDXFFeature *const poFeature,
536 : const CPLString &osBlockName,
537 : OGRLineString *const poLine,
538 : const double dfArrowheadSize,
539 : const bool bReverse = false);
540 : OGRErr CollectBoundaryPath(OGRGeometryCollection *poGC,
541 : const double dfElevation);
542 : OGRErr CollectPolylinePath(OGRGeometryCollection *poGC,
543 : const double dfElevation);
544 :
545 : CPLString TextRecode(const char *);
546 : CPLString TextUnescape(const char *, bool);
547 :
548 : public:
549 : explicit OGRDXFLayer(OGRDXFDataSource *poDS);
550 : ~OGRDXFLayer();
551 :
552 : void ResetReading() override;
553 : OGRFeature *GetNextFeature() override;
554 :
555 331 : OGRFeatureDefn *GetLayerDefn() override
556 : {
557 331 : return poFeatureDefn;
558 : }
559 :
560 : int TestCapability(const char *) override;
561 :
562 : GDALDataset *GetDataset() override;
563 :
564 : OGRDXFFeature *GetNextUnfilteredFeature();
565 : };
566 :
567 : /************************************************************************/
568 : /* OGRDXFReader */
569 : /* */
570 : /* A class for very low level DXF reading without interpretation. */
571 : /************************************************************************/
572 :
573 : #define DXF_READER_ERROR() \
574 : do \
575 : { \
576 : CPLError(CE_Failure, CPLE_AppDefined, \
577 : "%s, %d: error at line %d of %s", __FILE__, __LINE__, \
578 : GetLineNumber(), GetDescription()); \
579 : } while (0)
580 : #define DXF_LAYER_READER_ERROR() \
581 : do \
582 : { \
583 : CPLError(CE_Failure, CPLE_AppDefined, \
584 : "%s, %d: error at line %d of %s", __FILE__, __LINE__, \
585 : poDS->GetLineNumber(), poDS->GetDescription()); \
586 : } while (0)
587 :
588 : class OGRDXFReader
589 : {
590 : int ReadValueRaw(char *pszValueBuffer, int nValueBufferSize);
591 :
592 : public:
593 : OGRDXFReader();
594 : ~OGRDXFReader();
595 :
596 : void Initialize(VSILFILE *fp);
597 :
598 : VSILFILE *fp;
599 :
600 : unsigned int iSrcBufferOffset;
601 : unsigned int nSrcBufferBytes;
602 : unsigned int iSrcBufferFileOffset;
603 : char achSrcBuffer[1025];
604 :
605 : unsigned int nLastValueSize;
606 : int nLineNumber;
607 :
608 : int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81);
609 : void UnreadValue();
610 : void LoadDiskChunk();
611 : void ResetReadPointer(unsigned int iNewOffset, int nNewLineNumber = 0);
612 : };
613 :
614 : /************************************************************************/
615 : /* OGRDXFFieldModes */
616 : /* */
617 : /* Represents which fields should be included in the data source. */
618 : /************************************************************************/
619 :
620 : enum OGRDXFFieldModes
621 : {
622 : ODFM_None = 0,
623 : ODFM_IncludeRawCodeValues = 0x1,
624 : ODFM_IncludeBlockFields = 0x2,
625 : ODFM_Include3DModeFields = 0x4
626 : };
627 :
628 : /************************************************************************/
629 : /* OGRDXFDataSource */
630 : /************************************************************************/
631 :
632 : class OGRDXFDataSource final : public GDALDataset
633 : {
634 : VSILFILE *fp;
635 :
636 : std::vector<OGRLayer *> apoLayers;
637 :
638 : unsigned int iEntitiesOffset;
639 : int iEntitiesLineNumber;
640 :
641 : std::map<CPLString, DXFBlockDefinition> oBlockMap;
642 : std::map<CPLString, CPLString> oBlockRecordHandles;
643 : std::map<CPLString, CPLString> oHeaderVariables;
644 :
645 : CPLString osEncoding;
646 :
647 : // indexed by layer name, then by property name.
648 : std::map<CPLString, std::map<CPLString, CPLString>> oLayerTable;
649 :
650 : // indexed by style name, then by property name.
651 : std::map<CPLString, std::map<CPLString, CPLString>> oTextStyleTable;
652 : std::map<CPLString, CPLString> oTextStyleHandles;
653 :
654 : // indexed by dimstyle name, then by DIM... variable name
655 : std::map<CPLString, std::map<CPLString, CPLString>> oDimStyleTable;
656 :
657 : std::map<CPLString, std::vector<double>> oLineTypeTable;
658 :
659 : bool bInlineBlocks;
660 : bool bMergeBlockGeometries;
661 : bool bTranslateEscapeSequences;
662 : bool bIncludeRawCodeValues;
663 : bool m_bClosedLineAsPolygon = false;
664 : double m_dfHatchTolerance = -1.0;
665 :
666 : bool b3DExtensibleMode;
667 : bool bHaveReadSolidData;
668 : std::map<CPLString, std::vector<GByte>> oSolidBinaryData;
669 :
670 : OGRDXFReader oReader;
671 :
672 : std::vector<CPLString> aosBlockInsertionStack;
673 :
674 : public:
675 : OGRDXFDataSource();
676 : ~OGRDXFDataSource();
677 :
678 : int Open(const char *pszFilename, bool bHeaderOnly,
679 : CSLConstList papszOptionsIn);
680 :
681 509 : int GetLayerCount() override
682 : {
683 509 : return static_cast<int>(apoLayers.size());
684 : }
685 :
686 : OGRLayer *GetLayer(int) override;
687 :
688 : int TestCapability(const char *) override;
689 :
690 : // The following is only used by OGRDXFLayer
691 :
692 1430 : bool InlineBlocks() const
693 : {
694 1430 : return bInlineBlocks;
695 : }
696 :
697 130 : bool ShouldMergeBlockGeometries() const
698 : {
699 130 : return bMergeBlockGeometries;
700 : }
701 :
702 148 : bool ShouldTranslateEscapes() const
703 : {
704 148 : return bTranslateEscapeSequences;
705 : }
706 :
707 2860 : bool ShouldIncludeRawCodeValues() const
708 : {
709 2860 : return bIncludeRawCodeValues;
710 : }
711 :
712 213 : bool In3DExtensibleMode() const
713 : {
714 213 : return b3DExtensibleMode;
715 : }
716 :
717 26 : bool ClosedLineAsPolygon() const
718 : {
719 26 : return m_bClosedLineAsPolygon;
720 : }
721 :
722 28 : double HatchTolerance() const
723 : {
724 28 : return m_dfHatchTolerance;
725 : }
726 :
727 : static void AddStandardFields(OGRFeatureDefn *poDef, const int nFieldModes);
728 :
729 : // Implemented in ogrdxf_blockmap.cpp
730 : bool ReadBlocksSection();
731 : DXFBlockDefinition *LookupBlock(const char *pszName);
732 : CPLString GetBlockNameByRecordHandle(const char *pszID);
733 :
734 48 : std::map<CPLString, DXFBlockDefinition> &GetBlockMap()
735 : {
736 48 : return oBlockMap;
737 : }
738 :
739 : bool PushBlockInsertion(const CPLString &osBlockName);
740 :
741 327 : void PopBlockInsertion()
742 : {
743 327 : aosBlockInsertionStack.pop_back();
744 327 : }
745 :
746 : // Layer and other Table Handling (ogrdatasource.cpp)
747 : bool ReadTablesSection();
748 : bool ReadLayerDefinition();
749 : bool ReadLineTypeDefinition();
750 : bool ReadTextStyleDefinition();
751 : bool ReadDimStyleDefinition();
752 : const char *LookupLayerProperty(const char *pszLayer,
753 : const char *pszProperty);
754 : const char *LookupTextStyleProperty(const char *pszTextStyle,
755 : const char *pszProperty,
756 : const char *pszDefault);
757 : bool LookupDimStyle(const char *pszDimstyle,
758 : std::map<CPLString, CPLString> &oDimStyleProperties);
759 :
760 4 : const std::map<CPLString, std::vector<double>> &GetLineTypeTable() const
761 : {
762 4 : return oLineTypeTable;
763 : }
764 :
765 : std::vector<double> LookupLineType(const char *pszName);
766 : bool TextStyleExists(const char *pszTextStyle);
767 : CPLString GetTextStyleNameByHandle(const char *pszID);
768 : static void PopulateDefaultDimStyleProperties(
769 : std::map<CPLString, CPLString> &oDimStyleProperties);
770 : size_t GetEntryFromAcDsDataSection(const char *pszEntityHandle,
771 : const GByte **pabyBuffer);
772 :
773 : // Header variables.
774 : bool ReadHeaderSection();
775 : const char *GetVariable(const char *pszName,
776 : const char *pszDefault = nullptr);
777 :
778 2988 : const char *GetEncoding()
779 : {
780 2988 : return osEncoding;
781 : }
782 :
783 : // reader related.
784 6 : int GetLineNumber()
785 : {
786 6 : return oReader.nLineNumber;
787 : }
788 :
789 136282 : int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81)
790 : {
791 136282 : return oReader.ReadValue(pszValueBuffer, nValueBufferSize);
792 : }
793 :
794 184 : void RestartEntities()
795 : {
796 184 : oReader.ResetReadPointer(iEntitiesOffset, iEntitiesLineNumber);
797 184 : }
798 :
799 2281 : void UnreadValue()
800 : {
801 2281 : oReader.UnreadValue();
802 2281 : }
803 :
804 56 : void ResetReadPointer(int iNewOffset)
805 : {
806 56 : oReader.ResetReadPointer(iNewOffset);
807 56 : }
808 : };
809 :
810 : /************************************************************************/
811 : /* OGRDXFWriterLayer */
812 : /************************************************************************/
813 :
814 : class OGRDXFWriterDS;
815 :
816 : class OGRDXFWriterLayer final : public OGRLayer
817 : {
818 : VSILFILE *fp;
819 : OGRFeatureDefn *poFeatureDefn;
820 :
821 : OGRDXFWriterDS *poDS;
822 :
823 : int WriteValue(int nCode, const char *pszValue);
824 : int WriteValue(int nCode, int nValue);
825 : int WriteValue(int nCode, double dfValue);
826 :
827 : OGRErr WriteCore(OGRFeature *);
828 : OGRErr WritePOINT(OGRFeature *);
829 : OGRErr WriteTEXT(OGRFeature *);
830 : OGRErr WritePOLYLINE(OGRFeature *, const OGRGeometry * = nullptr);
831 : OGRErr WriteHATCH(OGRFeature *, OGRGeometry * = nullptr);
832 : OGRErr WriteINSERT(OGRFeature *);
833 :
834 : static CPLString TextEscape(const char *);
835 : static int ColorStringToDXFColor(const char *);
836 : static std::vector<double> PrepareLineTypeDefinition(OGRStylePen *);
837 : static std::map<CPLString, CPLString>
838 : PrepareTextStyleDefinition(OGRStyleLabel *);
839 :
840 : std::map<CPLString, std::vector<double>> oNewLineTypes;
841 : std::map<CPLString, std::map<CPLString, CPLString>> oNewTextStyles;
842 : int nNextAutoID;
843 : int bWriteHatch;
844 :
845 : public:
846 : OGRDXFWriterLayer(OGRDXFWriterDS *poDS, VSILFILE *fp);
847 : ~OGRDXFWriterLayer();
848 :
849 16 : void ResetReading() override
850 : {
851 16 : }
852 :
853 16 : OGRFeature *GetNextFeature() override
854 : {
855 16 : return nullptr;
856 : }
857 :
858 502 : OGRFeatureDefn *GetLayerDefn() override
859 : {
860 502 : return poFeatureDefn;
861 : }
862 :
863 : int TestCapability(const char *) override;
864 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
865 : OGRErr CreateField(const OGRFieldDefn *poField,
866 : int bApproxOK = TRUE) override;
867 :
868 : GDALDataset *GetDataset() override;
869 :
870 : void ResetFP(VSILFILE *);
871 :
872 48 : std::map<CPLString, std::vector<double>> &GetNewLineTypeMap()
873 : {
874 48 : return oNewLineTypes;
875 : }
876 :
877 48 : std::map<CPLString, std::map<CPLString, CPLString>> &GetNewTextStyleMap()
878 : {
879 48 : return oNewTextStyles;
880 : }
881 : };
882 :
883 : /************************************************************************/
884 : /* OGRDXFBlocksWriterLayer */
885 : /************************************************************************/
886 :
887 : class OGRDXFBlocksWriterLayer final : public OGRLayer
888 : {
889 : OGRFeatureDefn *poFeatureDefn;
890 :
891 : public:
892 : explicit OGRDXFBlocksWriterLayer(OGRDXFWriterDS *poDS);
893 : ~OGRDXFBlocksWriterLayer();
894 :
895 0 : void ResetReading() override
896 : {
897 0 : }
898 :
899 0 : OGRFeature *GetNextFeature() override
900 : {
901 0 : return nullptr;
902 : }
903 :
904 10 : OGRFeatureDefn *GetLayerDefn() override
905 : {
906 10 : return poFeatureDefn;
907 : }
908 :
909 : int TestCapability(const char *) override;
910 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
911 : OGRErr CreateField(const OGRFieldDefn *poField,
912 : int bApproxOK = TRUE) override;
913 :
914 : std::vector<OGRFeature *> apoBlocks;
915 : OGRFeature *FindBlock(const char *);
916 : };
917 :
918 : /************************************************************************/
919 : /* OGRDXFWriterDS */
920 : /************************************************************************/
921 :
922 : class OGRDXFWriterDS final : public GDALDataset
923 : {
924 : friend class OGRDXFWriterLayer;
925 :
926 : int nNextFID;
927 :
928 : OGRDXFWriterLayer *poLayer;
929 : OGRDXFBlocksWriterLayer *poBlocksLayer;
930 : VSILFILE *fp;
931 : CPLString osTrailerFile;
932 :
933 : CPLString osTempFilename;
934 : VSILFILE *fpTemp;
935 :
936 : CPLString osHeaderFile;
937 : OGRDXFDataSource oHeaderDS;
938 : char **papszLayersToCreate;
939 :
940 : vsi_l_offset nHANDSEEDOffset;
941 :
942 : std::vector<int> anDefaultLayerCode;
943 : std::vector<CPLString> aosDefaultLayerText;
944 :
945 : std::set<CPLString> aosUsedEntities;
946 : void ScanForEntities(const char *pszFilename, const char *pszTarget);
947 :
948 : bool WriteNewLineTypeRecords(VSILFILE *fp);
949 : bool WriteNewTextStyleRecords(VSILFILE *fp);
950 : bool WriteNewBlockRecords(VSILFILE *);
951 : bool WriteNewBlockDefinitions(VSILFILE *);
952 : bool WriteNewLayerDefinitions(VSILFILE *);
953 : bool TransferUpdateHeader(VSILFILE *);
954 : bool TransferUpdateTrailer(VSILFILE *);
955 : bool FixupHANDSEED(VSILFILE *);
956 :
957 : OGREnvelope oGlobalEnvelope;
958 :
959 : bool m_bHeaderFileIsTemp = false;
960 : bool m_bTrailerFileIsTemp = false;
961 : OGRSpatialReference m_oSRS{};
962 : std::string m_osINSUNITS = "AUTO";
963 : std::string m_osMEASUREMENT = "HEADER_VALUE";
964 :
965 : public:
966 : OGRDXFWriterDS();
967 : ~OGRDXFWriterDS();
968 :
969 : int Open(const char *pszFilename, char **papszOptions);
970 :
971 : int GetLayerCount() override;
972 : OGRLayer *GetLayer(int) override;
973 :
974 : int TestCapability(const char *) override;
975 :
976 : OGRLayer *ICreateLayer(const char *pszName,
977 : const OGRGeomFieldDefn *poGeomFieldDefn,
978 : CSLConstList papszOptions) override;
979 :
980 : bool CheckEntityID(const char *pszEntityID);
981 : bool WriteEntityID(VSILFILE *fp, unsigned int &nAssignedFID,
982 : GIntBig nPreferredFID = OGRNullFID);
983 :
984 : void UpdateExtent(OGREnvelope *psEnvelope);
985 : };
986 :
987 : #endif /* ndef OGR_DXF_H_INCLUDED */
|