Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: DXF Translator
5 : * Purpose: Definition of classes for OGR .dxf driver.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Frank Warmerdam
10 : * Copyright (c) 2010-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 : #ifndef OGR_DXF_H_INCLUDED
17 : #define OGR_DXF_H_INCLUDED
18 :
19 : #include "ogrsf_frmts.h"
20 : #include "ogr_autocad_services.h"
21 : #include "cpl_conv.h"
22 : #include <vector>
23 : #include <map>
24 : #include <set>
25 : #include <queue>
26 : #include <memory>
27 :
28 : class OGRDXFDataSource;
29 : class OGRDXFFeature;
30 :
31 : /************************************************************************/
32 : /* DXFBlockDefinition */
33 : /* */
34 : /* Container for info about a block. */
35 : /************************************************************************/
36 :
37 : class DXFBlockDefinition
38 : {
39 : public:
40 75 : DXFBlockDefinition()
41 75 : {
42 75 : }
43 :
44 : ~DXFBlockDefinition();
45 :
46 : std::vector<OGRDXFFeature *> apoFeatures;
47 : };
48 :
49 : /************************************************************************/
50 : /* OGRDXFFeatureQueue */
51 : /************************************************************************/
52 :
53 : class OGRDXFFeatureQueue
54 : {
55 : std::queue<OGRDXFFeature *> apoFeatures;
56 :
57 : public:
58 537 : OGRDXFFeatureQueue()
59 537 : {
60 537 : }
61 :
62 : void push(OGRDXFFeature *poFeature);
63 :
64 1736 : OGRDXFFeature *front() const
65 : {
66 1736 : return apoFeatures.front();
67 : }
68 :
69 : void pop();
70 :
71 5921 : bool empty() const
72 : {
73 5921 : return apoFeatures.empty();
74 : }
75 :
76 : size_t size() const
77 : {
78 : return apoFeatures.size();
79 : }
80 : };
81 :
82 : /************************************************************************/
83 : /* OGRDXFBlocksLayer */
84 : /************************************************************************/
85 :
86 : class OGRDXFBlocksLayer final : public OGRLayer
87 : {
88 : OGRDXFDataSource *poDS;
89 :
90 : OGRFeatureDefn *poFeatureDefn;
91 :
92 : GIntBig iNextFID;
93 :
94 : std::map<CPLString, DXFBlockDefinition>::iterator oIt;
95 : CPLString osBlockName;
96 :
97 : OGRDXFFeatureQueue apoPendingFeatures;
98 :
99 : public:
100 : explicit OGRDXFBlocksLayer(OGRDXFDataSource *poDS);
101 : ~OGRDXFBlocksLayer();
102 :
103 : void ResetReading() override;
104 : OGRFeature *GetNextFeature() override;
105 :
106 14 : OGRFeatureDefn *GetLayerDefn() override
107 : {
108 14 : return poFeatureDefn;
109 : }
110 :
111 : int TestCapability(const char *) override;
112 :
113 : OGRDXFFeature *GetNextUnfilteredFeature();
114 : };
115 :
116 : /************************************************************************/
117 : /* OGRDXFInsertTransformer */
118 : /* */
119 : /* Stores the transformation needed to insert a block reference. */
120 : /************************************************************************/
121 :
122 : class OGRDXFInsertTransformer final : public OGRCoordinateTransformation
123 : {
124 : public:
125 336 : OGRDXFInsertTransformer() = default;
126 :
127 : double dfXOffset = 0.0;
128 : double dfYOffset = 0.0;
129 : double dfZOffset = 0.0;
130 : double dfXScale = 1.0;
131 : double dfYScale = 1.0;
132 : double dfZScale = 1.0;
133 : double dfAngle = 0.0;
134 :
135 696 : OGRDXFInsertTransformer GetOffsetTransformer()
136 : {
137 696 : OGRDXFInsertTransformer oResult;
138 696 : oResult.dfXOffset = this->dfXOffset;
139 696 : oResult.dfYOffset = this->dfYOffset;
140 696 : oResult.dfZOffset = this->dfZOffset;
141 696 : return oResult;
142 : }
143 :
144 696 : OGRDXFInsertTransformer GetRotateScaleTransformer()
145 : {
146 696 : OGRDXFInsertTransformer oResult;
147 696 : oResult.dfXScale = this->dfXScale;
148 696 : oResult.dfYScale = this->dfYScale;
149 696 : oResult.dfZScale = this->dfZScale;
150 696 : oResult.dfAngle = this->dfAngle;
151 696 : return oResult;
152 : }
153 :
154 0 : OGRCoordinateTransformation *Clone() const override
155 : {
156 0 : return new OGRDXFInsertTransformer(*this);
157 : }
158 :
159 0 : const OGRSpatialReference *GetSourceCS() const override
160 : {
161 0 : return nullptr;
162 : }
163 :
164 3410 : const OGRSpatialReference *GetTargetCS() const override
165 : {
166 3410 : return nullptr;
167 : }
168 :
169 3275 : int Transform(size_t nCount, double *x, double *y, double *z,
170 : double * /* t */, int *pabSuccess) override
171 : {
172 16649 : for (size_t i = 0; i < nCount; i++)
173 : {
174 13374 : x[i] *= dfXScale;
175 13374 : y[i] *= dfYScale;
176 13374 : if (z)
177 13374 : z[i] *= dfZScale;
178 :
179 13374 : const double dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
180 13374 : const double dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
181 :
182 13374 : x[i] = dfXNew;
183 13374 : y[i] = dfYNew;
184 :
185 13374 : x[i] += dfXOffset;
186 13374 : y[i] += dfYOffset;
187 13374 : if (z)
188 13374 : z[i] += dfZOffset;
189 :
190 13374 : if (pabSuccess)
191 13374 : pabSuccess[i] = TRUE;
192 : }
193 3275 : return TRUE;
194 : }
195 :
196 0 : OGRCoordinateTransformation *GetInverse() const override
197 : {
198 0 : return nullptr;
199 : }
200 : };
201 :
202 : /************************************************************************/
203 : /* OGRDXFAffineTransform */
204 : /* */
205 : /* A simple 3D affine transform used to keep track of the */
206 : /* transformation to be applied to an ASM entity. */
207 : /************************************************************************/
208 :
209 : class OGRDXFAffineTransform
210 : {
211 : public:
212 2 : OGRDXFAffineTransform()
213 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}
214 : {
215 2 : }
216 :
217 : double adfData[12]; // Column-major: adfMatrix[5] is column 2, row 3
218 : // Last 3 elements are translation
219 :
220 : // Left composition (composes oOther o this), modifying this
221 6 : void ComposeWith(const OGRDXFInsertTransformer &oCT)
222 : {
223 : double adfNew[12];
224 :
225 6 : adfNew[0] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[0] -
226 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[1];
227 6 : adfNew[1] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[0] +
228 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[1];
229 6 : adfNew[2] = oCT.dfZScale * adfData[2];
230 :
231 6 : adfNew[3] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[3] -
232 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[4];
233 6 : adfNew[4] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[3] +
234 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[4];
235 6 : adfNew[5] = oCT.dfZScale * adfData[5];
236 :
237 6 : adfNew[6] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[6] -
238 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[7];
239 6 : adfNew[7] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[6] +
240 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[7];
241 6 : adfNew[8] = oCT.dfZScale * adfData[8];
242 :
243 6 : adfNew[9] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[9] -
244 6 : oCT.dfYScale * sin(oCT.dfAngle) * adfData[10] +
245 6 : oCT.dfXOffset;
246 6 : adfNew[10] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[9] +
247 6 : oCT.dfYScale * cos(oCT.dfAngle) * adfData[10] +
248 6 : oCT.dfYOffset;
249 6 : adfNew[11] = oCT.dfZScale * adfData[11] + oCT.dfZOffset;
250 :
251 6 : memcpy(adfData, adfNew, sizeof(adfNew));
252 6 : }
253 :
254 5 : void SetField(OGRFeature *poFeature, const char *pszFieldName) const
255 : {
256 5 : poFeature->SetField(pszFieldName, 12, adfData);
257 5 : }
258 : };
259 :
260 : /************************************************************************/
261 : /* OGRDXFOCSTransformer */
262 : /************************************************************************/
263 :
264 : class OGRDXFOCSTransformer final : public OGRCoordinateTransformation
265 : {
266 : private:
267 : double adfN[3];
268 : double adfAX[3];
269 : double adfAY[3];
270 :
271 : double dfDeterminant;
272 : double aadfInverse[4][4];
273 :
274 : public:
275 : explicit OGRDXFOCSTransformer(double adfNIn[3], bool bInverse = false);
276 :
277 0 : const OGRSpatialReference *GetSourceCS() const override
278 : {
279 0 : return nullptr;
280 : }
281 :
282 2078 : const OGRSpatialReference *GetTargetCS() const override
283 : {
284 2078 : return nullptr;
285 : }
286 :
287 : int Transform(size_t nCount, double *adfX, double *adfY, double *adfZ,
288 : double *adfT, int *pabSuccess) override;
289 :
290 : int InverseTransform(size_t nCount, double *adfX, double *adfY,
291 : double *adfZ);
292 :
293 : void ComposeOnto(OGRDXFAffineTransform &poCT) const;
294 :
295 0 : OGRCoordinateTransformation *Clone() const override
296 : {
297 0 : return new OGRDXFOCSTransformer(*this);
298 : }
299 :
300 0 : OGRCoordinateTransformation *GetInverse() const override
301 : {
302 0 : return nullptr;
303 : }
304 : };
305 :
306 : /************************************************************************/
307 : /* DXFTriple */
308 : /* */
309 : /* Represents a triple (X, Y, Z) used for various purposes in */
310 : /* DXF files. We do not use OGRPoint for this purpose, as the */
311 : /* triple does not always represent a point as such (for */
312 : /* example, it could contain a scale factor for each dimension). */
313 : /************************************************************************/
314 : struct DXFTriple
315 : {
316 : double dfX, dfY, dfZ;
317 :
318 27 : DXFTriple() : dfX(0.0), dfY(0.0), dfZ(0.0)
319 : {
320 27 : }
321 :
322 12587 : DXFTriple(double x, double y, double z) : dfX(x), dfY(y), dfZ(z)
323 : {
324 12587 : }
325 :
326 1956 : void ToArray(double adfOut[3]) const
327 : {
328 1956 : adfOut[0] = dfX;
329 1956 : adfOut[1] = dfY;
330 1956 : adfOut[2] = dfZ;
331 1956 : }
332 :
333 18 : DXFTriple &operator*=(const double dfValue)
334 : {
335 18 : dfX *= dfValue;
336 18 : dfY *= dfValue;
337 18 : dfZ *= dfValue;
338 18 : return *this;
339 : }
340 :
341 2 : DXFTriple &operator/=(const double dfValue)
342 : {
343 2 : dfX /= dfValue;
344 2 : dfY /= dfValue;
345 2 : dfZ /= dfValue;
346 2 : return *this;
347 : }
348 :
349 : bool operator==(const DXFTriple &oOther) const
350 : {
351 : return dfX == oOther.dfX && dfY == oOther.dfY && dfZ == oOther.dfZ;
352 : }
353 : };
354 :
355 : /************************************************************************/
356 : /* OGRDXFFeature */
357 : /* */
358 : /* Extends OGRFeature with some DXF-specific members. */
359 : /************************************************************************/
360 : class OGRDXFFeature final : public OGRFeature
361 : {
362 : friend class OGRDXFLayer;
363 :
364 : protected:
365 : // The feature's Object Coordinate System (OCS) unit normal vector
366 : DXFTriple oOCS;
367 :
368 : // A list of properties that are used to construct the style string
369 : std::map<CPLString, CPLString> oStyleProperties;
370 :
371 : // Additional data for INSERT entities
372 : bool bIsBlockReference;
373 : CPLString osBlockName;
374 : double dfBlockAngle;
375 : DXFTriple oBlockScale;
376 :
377 : // Used for INSERT entities when DXF_INLINE_BLOCKS is false, to store
378 : // the OCS insertion point
379 : DXFTriple oOriginalCoords;
380 :
381 : // Used in 3D mode to store transformation parameters for ASM entities
382 : std::unique_ptr<OGRDXFAffineTransform> poASMTransform;
383 :
384 : // Additional data for ATTRIB and ATTDEF entities
385 : CPLString osAttributeTag;
386 :
387 : // Store ATTRIB entities associated with an INSERT, for use when
388 : // DXF_INLINE_BLOCKS is true and a block with attributes is INSERTed
389 : // in another block
390 : std::vector<std::unique_ptr<OGRDXFFeature>> apoAttribFeatures;
391 :
392 : public:
393 : explicit OGRDXFFeature(OGRFeatureDefn *poFeatureDefn);
394 :
395 : OGRDXFFeature *CloneDXFFeature();
396 :
397 : DXFTriple GetOCS() const
398 : {
399 : return oOCS;
400 : }
401 :
402 2695 : bool IsBlockReference() const
403 : {
404 2695 : return bIsBlockReference;
405 : }
406 :
407 : CPLString GetBlockName() const
408 : {
409 : return osBlockName;
410 : }
411 :
412 : double GetBlockAngle() const
413 : {
414 : return dfBlockAngle;
415 : }
416 :
417 : DXFTriple GetBlockScale() const
418 : {
419 : return oBlockScale;
420 : }
421 :
422 793 : DXFTriple GetInsertOCSCoords() const
423 : {
424 793 : return oOriginalCoords;
425 : }
426 :
427 44 : CPLString GetAttributeTag() const
428 : {
429 44 : return osAttributeTag;
430 : }
431 :
432 : const std::vector<std::unique_ptr<OGRDXFFeature>> &GetAttribFeatures() const
433 : {
434 : return apoAttribFeatures;
435 : }
436 :
437 793 : void SetInsertOCSCoords(const DXFTriple &oTriple)
438 : {
439 793 : oOriginalCoords = oTriple;
440 793 : }
441 :
442 : void ApplyOCSTransformer(OGRGeometry *const poGeometry) const;
443 : void ApplyOCSTransformer(OGRDXFAffineTransform *const poCT) const;
444 : const CPLString GetColor(OGRDXFDataSource *const poDS,
445 : OGRDXFFeature *const poBlockFeature = nullptr);
446 : };
447 :
448 : /************************************************************************/
449 : /* OGRDXFLayer */
450 : /************************************************************************/
451 : class OGRDXFLayer final : public OGRLayer
452 : {
453 : friend class OGRDXFBlocksLayer;
454 :
455 : OGRDXFDataSource *poDS;
456 :
457 : OGRFeatureDefn *poFeatureDefn;
458 : GIntBig iNextFID;
459 :
460 : std::set<CPLString> oIgnoredEntities;
461 :
462 : OGRDXFFeatureQueue apoPendingFeatures;
463 :
464 : struct InsertState
465 : {
466 : OGRDXFInsertTransformer m_oTransformer{};
467 : CPLString m_osBlockName{};
468 : CPLStringList m_aosAttribs{};
469 : int m_nColumnCount = 0;
470 : int m_nRowCount = 0;
471 : int m_iCurCol = 0;
472 : int m_iCurRow = 0;
473 : double m_dfColumnSpacing = 0.0;
474 : double m_dfRowSpacing = 0.0;
475 : std::vector<std::unique_ptr<OGRDXFFeature>> m_apoAttribs{};
476 : std::unique_ptr<OGRDXFFeature> m_poTemplateFeature{};
477 : };
478 :
479 : InsertState m_oInsertState{};
480 :
481 : void ClearPendingFeatures();
482 :
483 : void TranslateGenericProperty(OGRDXFFeature *poFeature, int nCode,
484 : char *pszValue);
485 :
486 : void PrepareFeatureStyle(OGRDXFFeature *const poFeature,
487 : OGRDXFFeature *const poBlockFeature = nullptr);
488 : void PrepareBrushStyle(OGRDXFFeature *const poFeature,
489 : OGRDXFFeature *const poBlockFeature = nullptr);
490 : void PrepareLineStyle(OGRDXFFeature *const poFeature,
491 : OGRDXFFeature *const poBlockFeature = nullptr);
492 :
493 : OGRDXFFeature *TranslatePOINT();
494 : OGRDXFFeature *TranslateLINE();
495 : OGRDXFFeature *TranslatePOLYLINE();
496 : OGRDXFFeature *TranslateLWPOLYLINE();
497 : OGRDXFFeature *TranslateMLINE();
498 : OGRDXFFeature *TranslateCIRCLE();
499 : OGRDXFFeature *TranslateELLIPSE();
500 : OGRDXFFeature *TranslateARC();
501 : OGRDXFFeature *TranslateSPLINE();
502 : OGRDXFFeature *Translate3DFACE();
503 : bool TranslateINSERT();
504 : OGRDXFFeature *TranslateMTEXT();
505 : OGRDXFFeature *TranslateTEXT(const bool bIsAttribOrAttdef);
506 : OGRDXFFeature *TranslateDIMENSION();
507 : OGRDXFFeature *TranslateHATCH();
508 : OGRDXFFeature *TranslateSOLID();
509 : OGRDXFFeature *TranslateLEADER();
510 : OGRDXFFeature *TranslateMLEADER();
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 255 : OGRFeatureDefn *GetLayerDefn() override
556 : {
557 255 : 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 392 : int GetLayerCount() override
682 : {
683 392 : 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 1366 : bool InlineBlocks() const
693 : {
694 1366 : return bInlineBlocks;
695 : }
696 :
697 122 : bool ShouldMergeBlockGeometries() const
698 : {
699 122 : return bMergeBlockGeometries;
700 : }
701 :
702 148 : bool ShouldTranslateEscapes() const
703 : {
704 148 : return bTranslateEscapeSequences;
705 : }
706 :
707 2766 : bool ShouldIncludeRawCodeValues() const
708 : {
709 2766 : return bIncludeRawCodeValues;
710 : }
711 :
712 173 : bool In3DExtensibleMode() const
713 : {
714 173 : return b3DExtensibleMode;
715 : }
716 :
717 25 : bool ClosedLineAsPolygon() const
718 : {
719 25 : 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 42 : std::map<CPLString, DXFBlockDefinition> &GetBlockMap()
735 : {
736 42 : return oBlockMap;
737 : }
738 :
739 : bool PushBlockInsertion(const CPLString &osBlockName);
740 :
741 296 : void PopBlockInsertion()
742 : {
743 296 : aosBlockInsertionStack.pop_back();
744 296 : }
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 2680 : const char *GetEncoding()
779 : {
780 2680 : return osEncoding;
781 : }
782 :
783 : // reader related.
784 6 : int GetLineNumber()
785 : {
786 6 : return oReader.nLineNumber;
787 : }
788 :
789 108194 : int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81)
790 : {
791 108194 : return oReader.ReadValue(pszValueBuffer, nValueBufferSize);
792 : }
793 :
794 157 : void RestartEntities()
795 : {
796 157 : oReader.ResetReadPointer(iEntitiesOffset, iEntitiesLineNumber);
797 157 : }
798 :
799 1958 : void UnreadValue()
800 : {
801 1958 : oReader.UnreadValue();
802 1958 : }
803 :
804 44 : void ResetReadPointer(int iNewOffset)
805 : {
806 44 : oReader.ResetReadPointer(iNewOffset);
807 44 : }
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 489 : OGRFeatureDefn *GetLayerDefn() override
859 : {
860 489 : 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 43 : std::map<CPLString, std::vector<double>> &GetNewLineTypeMap()
873 : {
874 43 : return oNewLineTypes;
875 : }
876 :
877 43 : std::map<CPLString, std::map<CPLString, CPLString>> &GetNewTextStyleMap()
878 : {
879 43 : 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 :
962 : public:
963 : OGRDXFWriterDS();
964 : ~OGRDXFWriterDS();
965 :
966 : int Open(const char *pszFilename, char **papszOptions);
967 :
968 : int GetLayerCount() override;
969 : OGRLayer *GetLayer(int) override;
970 :
971 : int TestCapability(const char *) override;
972 :
973 : OGRLayer *ICreateLayer(const char *pszName,
974 : const OGRGeomFieldDefn *poGeomFieldDefn,
975 : CSLConstList papszOptions) override;
976 :
977 : bool CheckEntityID(const char *pszEntityID);
978 : bool WriteEntityID(VSILFILE *fp, unsigned int &nAssignedFID,
979 : GIntBig nPreferredFID = OGRNullFID);
980 :
981 : void UpdateExtent(OGREnvelope *psEnvelope);
982 : };
983 :
984 : #endif /* ndef OGR_DXF_H_INCLUDED */
|