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