QGIS API Documentation  2.99.0-Master (6c64c5a)
qgsdxfexport.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdxfexport.cpp
3  ----------------
4  begin : September 2013
5  copyright : (C) 2013 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 // Specs:
19 // AutoCAD 2000: http://www.autodesk.com/techpubs/autocad/acad2000/dxf/
20 // AutoCAD 2002: http://www.autodesk.com/techpubs/autocad/dxf/dxf2002.pdf
21 // AutoCAD 2004: http://atrey.karlin.mff.cuni.cz/projekty/vrr/doc/dxf14.pdf
22 // AutoCAD 2006: http://images.autodesk.com/adsk/files/dxf_format.pdf
23 // AutoCAD 2008: http://images.autodesk.com/adsk/files/acad_dxf0.pdf
24 // AutoCAD 2009: http://images.autodesk.com/adsk/files/acad_dxf.pdf
25 // AutoCAD 2011: http://images.autodesk.com/adsk/files/acad_dxf2.pdf
26 // AutoCAD 2012: http://images.autodesk.com/adsk/files/autocad_2012_pdf_dxf-reference_enu.pdf
27 // AutoCAD 2014: http://images.autodesk.com/adsk/files/autocad_2014_pdf_dxf_reference_enu.pdf
28 
29 #include "qgsdxfexport.h"
30 #include "qgsdxfpallabeling.h"
31 #include "qgsvectordataprovider.h"
32 #include "qgspointxy.h"
33 #include "qgsproject.h"
34 #include "qgsrenderer.h"
35 #include "qgssymbollayer.h"
36 #include "qgsfillsymbollayer.h"
37 #include "qgsfeatureiterator.h"
38 #include "qgslinesymbollayer.h"
39 #include "qgsvectorlayer.h"
40 #include "qgsunittypes.h"
41 #include "qgstextlabelfeature.h"
42 #include "qgslogger.h"
44 
45 #include "qgswkbtypes.h"
46 #include "qgspoint.h"
47 #include "qgsgeos.h"
48 
49 #include "pal/feature.h"
50 #include "pal/pointset.h"
51 #include "pal/labelposition.h"
52 
53 #include <QIODevice>
54 
55 // dxf color palette
56 int QgsDxfExport::sDxfColors[][3] =
57 {
58  { 255, 255, 255 },
59  { 255, 0, 0 },
60  { 255, 255, 0 },
61  { 0, 255, 0 },
62  { 0, 255, 255 },
63  { 0, 0, 255 },
64  { 255, 0, 255 },
65  { 0, 0, 0 },
66  { 128, 128, 128 },
67  { 192, 192, 192 },
68  { 255, 0, 0 },
69  { 255, 127, 127 },
70  { 204, 0, 0 },
71  { 204, 102, 102 },
72  { 153, 0, 0 },
73  { 153, 76, 76 },
74  { 127, 0, 0 },
75  { 127, 63, 63 },
76  { 76, 0, 0 },
77  { 76, 38, 38 },
78  { 255, 63, 0 },
79  { 255, 159, 127 },
80  { 204, 51, 0 },
81  { 204, 127, 102 },
82  { 153, 38, 0 },
83  { 153, 95, 76 },
84  { 127, 31, 0 },
85  { 127, 79, 63 },
86  { 76, 19, 0 },
87  { 76, 47, 38 },
88  { 255, 127, 0 },
89  { 255, 191, 127 },
90  { 204, 102, 0 },
91  { 204, 153, 102 },
92  { 153, 76, 0 },
93  { 153, 114, 76 },
94  { 127, 63, 0 },
95  { 127, 95, 63 },
96  { 76, 38, 0 },
97  { 76, 57, 38 },
98  { 255, 191, 0 },
99  { 255, 223, 127 },
100  { 204, 153, 0 },
101  { 204, 178, 102 },
102  { 153, 114, 0 },
103  { 153, 133, 76 },
104  { 127, 95, 0 },
105  { 127, 111, 63 },
106  { 76, 57, 0 },
107  { 76, 66, 38 },
108  { 255, 255, 0 },
109  { 255, 255, 127 },
110  { 204, 204, 0 },
111  { 204, 204, 102 },
112  { 153, 153, 0 },
113  { 153, 153, 76 },
114  { 127, 127, 0 },
115  { 127, 127, 63 },
116  { 76, 76, 0 },
117  { 76, 76, 38 },
118  { 191, 255, 0 },
119  { 223, 255, 127 },
120  { 153, 204, 0 },
121  { 178, 204, 102 },
122  { 114, 153, 0 },
123  { 133, 153, 76 },
124  { 95, 127, 0 },
125  { 111, 127, 63 },
126  { 57, 76, 0 },
127  { 66, 76, 38 },
128  { 127, 255, 0 },
129  { 191, 255, 127 },
130  { 102, 204, 0 },
131  { 153, 204, 102 },
132  { 76, 153, 0 },
133  { 114, 153, 76 },
134  { 63, 127, 0 },
135  { 95, 127, 63 },
136  { 38, 76, 0 },
137  { 57, 76, 38 },
138  { 63, 255, 0 },
139  { 159, 255, 127 },
140  { 51, 204, 0 },
141  { 127, 204, 102 },
142  { 38, 153, 0 },
143  { 95, 153, 76 },
144  { 31, 127, 0 },
145  { 79, 127, 63 },
146  { 19, 76, 0 },
147  { 47, 76, 38 },
148  { 0, 255, 0 },
149  { 127, 255, 127 },
150  { 0, 204, 0 },
151  { 102, 204, 102 },
152  { 0, 153, 0 },
153  { 76, 153, 76 },
154  { 0, 127, 0 },
155  { 63, 127, 63 },
156  { 0, 76, 0 },
157  { 38, 76, 38 },
158  { 0, 255, 63 },
159  { 127, 255, 159 },
160  { 0, 204, 51 },
161  { 102, 204, 127 },
162  { 0, 153, 38 },
163  { 76, 153, 95 },
164  { 0, 127, 31 },
165  { 63, 127, 79 },
166  { 0, 76, 19 },
167  { 38, 76, 47 },
168  { 0, 255, 127 },
169  { 127, 255, 191 },
170  { 0, 204, 102 },
171  { 102, 204, 153 },
172  { 0, 153, 76 },
173  { 76, 153, 114 },
174  { 0, 127, 63 },
175  { 63, 127, 95 },
176  { 0, 76, 38 },
177  { 38, 76, 57 },
178  { 0, 255, 191 },
179  { 127, 255, 223 },
180  { 0, 204, 153 },
181  { 102, 204, 178 },
182  { 0, 153, 114 },
183  { 76, 153, 133 },
184  { 0, 127, 95 },
185  { 63, 127, 111 },
186  { 0, 76, 57 },
187  { 38, 76, 66 },
188  { 0, 255, 255 },
189  { 127, 255, 255 },
190  { 0, 204, 204 },
191  { 102, 204, 204 },
192  { 0, 153, 153 },
193  { 76, 153, 153 },
194  { 0, 127, 127 },
195  { 63, 127, 127 },
196  { 0, 76, 76 },
197  { 38, 76, 76 },
198  { 0, 191, 255 },
199  { 127, 223, 255 },
200  { 0, 153, 204 },
201  { 102, 178, 204 },
202  { 0, 114, 153 },
203  { 76, 133, 153 },
204  { 0, 95, 127 },
205  { 63, 111, 127 },
206  { 0, 57, 76 },
207  { 38, 66, 76 },
208  { 0, 127, 255 },
209  { 127, 191, 255 },
210  { 0, 102, 204 },
211  { 102, 153, 204 },
212  { 0, 76, 153 },
213  { 76, 114, 153 },
214  { 0, 63, 127 },
215  { 63, 95, 127 },
216  { 0, 38, 76 },
217  { 38, 57, 76 },
218  { 0, 63, 255 },
219  { 127, 159, 255 },
220  { 0, 51, 204 },
221  { 102, 127, 204 },
222  { 0, 38, 153 },
223  { 76, 95, 153 },
224  { 0, 31, 127 },
225  { 63, 79, 127 },
226  { 0, 19, 76 },
227  { 38, 47, 76 },
228  { 0, 0, 255 },
229  { 127, 127, 255 },
230  { 0, 0, 204 },
231  { 102, 102, 204 },
232  { 0, 0, 153 },
233  { 76, 76, 153 },
234  { 0, 0, 127 },
235  { 63, 63, 127 },
236  { 0, 0, 76 },
237  { 38, 38, 76 },
238  { 63, 0, 255 },
239  { 159, 127, 255 },
240  { 51, 0, 204 },
241  { 127, 102, 204 },
242  { 38, 0, 153 },
243  { 95, 76, 153 },
244  { 31, 0, 127 },
245  { 79, 63, 127 },
246  { 19, 0, 76 },
247  { 47, 38, 76 },
248  { 127, 0, 255 },
249  { 191, 127, 255 },
250  { 102, 0, 204 },
251  { 153, 102, 204 },
252  { 76, 0, 153 },
253  { 114, 76, 153 },
254  { 63, 0, 127 },
255  { 95, 63, 127 },
256  { 38, 0, 76 },
257  { 57, 38, 76 },
258  { 191, 0, 255 },
259  { 223, 127, 255 },
260  { 153, 0, 204 },
261  { 178, 102, 204 },
262  { 114, 0, 153 },
263  { 133, 76, 153 },
264  { 95, 0, 127 },
265  { 111, 63, 127 },
266  { 57, 0, 76 },
267  { 66, 38, 76 },
268  { 255, 0, 255 },
269  { 255, 127, 255 },
270  { 204, 0, 204 },
271  { 204, 102, 204 },
272  { 153, 0, 153 },
273  { 153, 76, 153 },
274  { 127, 0, 127 },
275  { 127, 63, 127 },
276  { 76, 0, 76 },
277  { 76, 38, 76 },
278  { 255, 0, 191 },
279  { 255, 127, 223 },
280  { 204, 0, 153 },
281  { 204, 102, 178 },
282  { 153, 0, 114 },
283  { 153, 76, 133 },
284  { 127, 0, 95 },
285  { 127, 63, 111 },
286  { 76, 0, 57 },
287  { 76, 38, 66 },
288  { 255, 0, 127 },
289  { 255, 127, 191 },
290  { 204, 0, 102 },
291  { 204, 102, 153 },
292  { 153, 0, 76 },
293  { 153, 76, 114 },
294  { 127, 0, 63 },
295  { 127, 63, 95 },
296  { 76, 0, 38 },
297  { 76, 38, 57 },
298  { 255, 0, 63 },
299  { 255, 127, 159 },
300  { 204, 0, 51 },
301  { 204, 102, 127 },
302  { 153, 0, 38 },
303  { 153, 76, 95 },
304  { 127, 0, 31 },
305  { 127, 63, 79 },
306  { 76, 0, 19 },
307  { 76, 38, 47 },
308  { 51, 51, 51 },
309  { 91, 91, 91 },
310  { 132, 132, 132 },
311  { 173, 173, 173 },
312  { 214, 214, 214 },
313  { 255, 255, 255 },
314 };
315 
316 const char *QgsDxfExport::DXF_ENCODINGS[][2] =
317 {
318  { "ASCII", "" },
319  { "8859_1", "ISO-8859-1" },
320  { "8859_2", "ISO-8859-2" },
321  { "8859_3", "ISO-8859-3" },
322  { "8859_4", "ISO-8859-4" },
323  { "8859_5", "ISO-8859-5" },
324  { "8859_6", "ISO-8859-6" },
325  { "8859_7", "ISO-8859-7" },
326  { "8859_8", "ISO-8859-8" },
327  { "8859_9", "ISO-8859-9" },
328 // { "DOS437", "" },
329  { "DOS850", "CP850" },
330 // { "DOS852", "" },
331 // { "DOS855", "" },
332 // { "DOS857", "" },
333 // { "DOS860", "" },
334 // { "DOS861", "" },
335 // { "DOS863", "" },
336 // { "DOS864", "" },
337 // { "DOS865", "" },
338 // { "DOS869", "" },
339 // { "DOS932", "" },
340  { "MACINTOSH", "MacRoman" },
341  { "BIG5", "Big5" },
342  { "KSC5601", "ksc5601.1987-0" },
343 // { "JOHAB", "" },
344  { "DOS866", "CP866" },
345  { "ANSI_1250", "CP1250" },
346  { "ANSI_1251", "CP1251" },
347  { "ANSI_1252", "CP1252" },
348  { "GB2312", "GB2312" },
349  { "ANSI_1253", "CP1253" },
350  { "ANSI_1254", "CP1254" },
351  { "ANSI_1255", "CP1255" },
352  { "ANSI_1256", "CP1256" },
353  { "ANSI_1257", "CP1257" },
354  { "ANSI_874", "CP874" },
355  { "ANSI_932", "Shift_JIS" },
356  { "ANSI_936", "CP936" },
357  { "ANSI_949", "cp949" },
358  { "ANSI_950", "CP950" },
359 // { "ANSI_1361", "" },
360 // { "ANSI_1200", "" },
361  { "ANSI_1258", "CP1258" },
362 };
363 
365 {
366  *this = dxfExport;
367 }
368 
370 {
371  mMapSettings = dxfExport.mMapSettings;
372  mLayerNameAttribute = dxfExport.mLayerNameAttribute;
373  mSymbologyScale = dxfExport.mSymbologyScale;
374  mSymbologyExport = dxfExport.mSymbologyExport;
375  mMapUnits = dxfExport.mMapUnits;
376  mLayerTitleAsName = dxfExport.mLayerTitleAsName;
377  mSymbolLayerCounter = 0; // internal counter
378  mNextHandleId = 0;
379  mBlockCounter = 0;
381  mFactor = dxfExport.mFactor;
382  mForce2d = dxfExport.mForce2d;
383  return *this;
384 }
385 
387 {
388  mMapSettings = settings;
389 }
390 
391 void QgsDxfExport::setFlags( QgsDxfExport::Flags flags )
392 {
393  mFlags = flags;
394 }
395 
396 QgsDxfExport::Flags QgsDxfExport::flags() const
397 {
398  return mFlags;
399 }
400 
401 void QgsDxfExport::addLayers( const QList<DxfLayer> &layers )
402 {
403  QList<QgsMapLayer *> layerList;
404 
405  mLayerNameAttribute.clear();
406 
407  QList< DxfLayer >::const_iterator layerIt = layers.constBegin();
408  for ( ; layerIt != layers.constEnd(); ++layerIt )
409  {
410  layerList << layerIt->layer();
411  if ( layerIt->layerOutputAttributeIndex() >= 0 )
412  mLayerNameAttribute.insert( layerIt->layer()->id(), layerIt->layerOutputAttributeIndex() );
413  }
414 
415  mMapSettings.setLayers( layerList );
416 }
417 
418 void QgsDxfExport::writeGroup( int code, int i )
419 {
420  writeGroupCode( code );
421  writeInt( i );
422 }
423 
424 void QgsDxfExport::writeGroup( int code, double d )
425 {
426  writeGroupCode( code );
427  writeDouble( d );
428 }
429 
430 void QgsDxfExport::writeGroup( int code, const QString &s )
431 {
432  writeGroupCode( code );
433  writeString( s );
434 }
435 
436 void QgsDxfExport::writeGroup( int code, const QgsPoint &p )
437 {
438  writeGroup( code + 10, p.x() );
439  writeGroup( code + 20, p.y() );
440  if ( !mForce2d && p.is3D() && std::isfinite( p.z() ) )
441  writeGroup( code + 30, p.z() );
442 }
443 
444 void QgsDxfExport::writeGroup( const QColor &color, int exactMatchCode, int rgbCode, int transparencyCode )
445 {
446  int minDistAt = -1;
447  int minDist = INT_MAX;
448 
449  for ( int i = 1; i < static_cast< int >( sizeof( sDxfColors ) / sizeof( *sDxfColors ) ) && minDist > 0; ++i )
450  {
451  int dist = color_distance( color.rgba(), i );
452  if ( dist >= minDist )
453  continue;
454 
455  minDistAt = i;
456  minDist = dist;
457  }
458 
459  if ( minDist == 0 && minDistAt != 7 )
460  {
461  // exact full opaque match, not black/white
462  writeGroup( exactMatchCode, minDistAt );
463  if ( color.alpha() == 255 )
464  return;
465  }
466 
467  int c = ( color.red() & 0xff ) * 0x10000 + ( color.green() & 0xff ) * 0x100 + ( color.blue() & 0xff );
468  writeGroup( rgbCode, c );
469  if ( transparencyCode != -1 && color.alpha() < 255 )
470  writeGroup( transparencyCode, 0x2000000 | color.alpha() );
471 }
472 
474 {
475  mTextStream << QStringLiteral( "%1\n" ).arg( code, 3, 10, QChar( ' ' ) );
476 }
477 
479 {
480  mTextStream << QStringLiteral( "%1\n" ).arg( i, 6, 10, QChar( ' ' ) );
481 }
482 
484 {
485  QString s( qgsDoubleToString( d ) );
486  if ( !s.contains( '.' ) )
487  s += QLatin1String( ".0" );
488  mTextStream << s << '\n';
489 }
490 
491 void QgsDxfExport::writeString( const QString &s )
492 {
493  mTextStream << s << '\n';
494 }
495 
496 int QgsDxfExport::writeToFile( QIODevice *d, const QString &encoding )
497 {
498  if ( !d )
499  {
500  return 1;
501  }
502 
503  if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
504  {
505  return 2;
506  }
507 
508  mTextStream.setDevice( d );
509  mTextStream.setCodec( encoding.toLocal8Bit() );
510 
511  if ( mCrs.isValid() )
512  mMapSettings.setDestinationCrs( mCrs );
513 
514  if ( mExtent.isEmpty() )
515  {
516  const QList< QgsMapLayer * > layers = mMapSettings.layers();
517  for ( QgsMapLayer *ml : layers )
518  {
519  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
520  if ( !vl )
521  continue;
522 
523  QgsRectangle layerExtent = vl->extent();
524  if ( layerExtent.isEmpty() )
525  continue;
526 
527  layerExtent = mMapSettings.layerToMapCoordinates( vl, layerExtent );
528 
529  if ( mExtent.isEmpty() )
530  {
531  mExtent = layerExtent;
532  }
533  else
534  {
535  mExtent.combineExtentWith( layerExtent );
536  }
537  }
538  }
539 
541  mMapSettings.setExtent( mExtent );
542 
543  int dpi = 96;
544  mFactor = 1000 * dpi / mSymbologyScale / 25.4 * QgsUnitTypes::fromUnitToUnitFactor( mapUnits, QgsUnitTypes::DistanceMeters );
545  mMapSettings.setOutputSize( QSize( mExtent.width() * mFactor, mExtent.height() * mFactor ) );
546  mMapSettings.setOutputDpi( dpi );
547 
548  writeHeader( dxfEncoding( encoding ) );
549  writeTables();
550  writeBlocks();
551  writeEntities();
552  writeEndFile();
553 
554  return 0;
555 }
556 
558 {
559  return mMapUnits;
560 }
561 
562 void QgsDxfExport::writeHeader( const QString &codepage )
563 {
564  writeGroup( 999, QStringLiteral( "DXF created from QGIS" ) );
565 
566  startSection();
567  writeGroup( 2, QStringLiteral( "HEADER" ) );
568 
569  // ACADVER
570  writeGroup( 9, QStringLiteral( "$ACADVER" ) );
571  writeGroup( 1, QStringLiteral( "AC1015" ) );
572 
573  // EXTMIN
574  writeGroup( 9, QStringLiteral( "$EXTMIN" ) );
575  writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, mExtent.xMinimum(), mExtent.yMinimum() ) );
576 
577  // EXTMAX
578  writeGroup( 9, QStringLiteral( "$EXTMAX" ) );
579  writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, mExtent.xMaximum(), mExtent.yMaximum() ) );
580 
581  // Global linetype scale
582  writeGroup( 9, QStringLiteral( "$LTSCALE" ) );
583  writeGroup( 40, 1.0 );
584 
585  // Point display mode (33 = circle)
586  writeGroup( 9, QStringLiteral( "$PDMODE" ) );
587  writeGroup( 70, 33 );
588 
589  // Point display size
590  writeGroup( 9, QStringLiteral( "$PDSIZE" ) );
591  writeGroup( 40, 1 );
592 
593  // Controls paper space linetype scaling (1 = No special linetype scaling, 0 = Viewport scaling governs linetype scaling)
594  writeGroup( 9, QStringLiteral( "$PSLTSCALE" ) );
595  writeGroup( 70, 0 );
596 
597  writeGroup( 9, QStringLiteral( "$HANDSEED" ) );
598  writeGroup( 5, DXF_HANDMAX );
599 
600  writeGroup( 9, QStringLiteral( "$DWGCODEPAGE" ) );
601  writeGroup( 3, codepage );
602 
603  endSection();
604 }
605 
606 int QgsDxfExport::writeHandle( int code, int handle )
607 {
608  if ( handle == 0 )
609  handle = mNextHandleId++;
610 
611  Q_ASSERT_X( handle < DXF_HANDMAX, "QgsDxfExport::writeHandle(int, int)", "DXF handle too large" );
612 
613  writeGroup( code, QStringLiteral( "%1" ).arg( handle, 0, 16 ) );
614  return handle;
615 }
616 
617 void QgsDxfExport::writeTables()
618 {
619  startSection();
620  writeGroup( 2, QStringLiteral( "TABLES" ) );
621 
622  // Iterate through all layers and get symbol layer pointers
623  QgsRenderContext context = renderContext();
624  QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
625  if ( mSymbologyExport != NoSymbology )
626  {
627  slList = symbolLayers( context );
628  }
629 
630  // Line types
631  mLineStyles.clear();
632  writeGroup( 0, QStringLiteral( "TABLE" ) );
633  writeGroup( 2, QStringLiteral( "LTYPE" ) );
634  writeHandle();
635  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
636  writeGroup( 70, nLineTypes( slList ) + 5 );
637 
638  writeDefaultLinetypes();
639 
640  // Add custom linestyles
641  QList< QPair< QgsSymbolLayer *, QgsSymbol *> >::const_iterator slIt = slList.constBegin();
642  for ( ; slIt != slList.constEnd(); ++slIt )
643  {
644  writeSymbolLayerLinetype( slIt->first );
645  }
646 
647  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
648 
649  // BLOCK_RECORD
650  writeGroup( 0, QStringLiteral( "TABLE" ) );
651  writeGroup( 2, QStringLiteral( "BLOCK_RECORD" ) );
652  writeHandle();
653 
654  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
655  writeGroup( 70, 0 );
656 
657  const QStringList blockStrings = QStringList() << QStringLiteral( "*Model_Space" ) << QStringLiteral( "*Paper_Space" ) << QStringLiteral( "*Paper_Space0" );
658  for ( const QString &block : blockStrings )
659  {
660  writeGroup( 0, QStringLiteral( "BLOCK_RECORD" ) );
661  mBlockHandles.insert( block, writeHandle() );
662  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
663  writeGroup( 100, QStringLiteral( "AcDbBlockTableRecord" ) );
664  writeGroup( 2, block );
665  }
666 
667  int i = 0;
668  slIt = slList.constBegin();
669  for ( ; slIt != slList.constEnd(); ++slIt )
670  {
671  QgsMarkerSymbolLayer *ml = dynamic_cast< QgsMarkerSymbolLayer *>( slIt->first );
672  if ( !ml )
673  continue;
674 
675  if ( hasDataDefinedProperties( ml, slIt->second ) )
676  continue;
677 
678  QString name = QStringLiteral( "symbolLayer%1" ).arg( i++ );
679  writeGroup( 0, QStringLiteral( "BLOCK_RECORD" ) );
680  mBlockHandles.insert( name, writeHandle() );
681  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
682  writeGroup( 100, QStringLiteral( "AcDbBlockTableRecord" ) );
683  writeGroup( 2, name );
684  }
685 
686  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
687 
688  // APPID
689  writeGroup( 0, QStringLiteral( "TABLE" ) );
690  writeGroup( 2, QStringLiteral( "APPID" ) );
691  writeHandle();
692  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
693  writeGroup( 70, 1 );
694  writeGroup( 0, QStringLiteral( "APPID" ) );
695  writeHandle();
696  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
697  writeGroup( 100, QStringLiteral( "AcDbRegAppTableRecord" ) );
698  writeGroup( 2, QStringLiteral( "ACAD" ) );
699  writeGroup( 70, 0 );
700  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
701 
702  // VIEW
703  writeGroup( 0, QStringLiteral( "TABLE" ) );
704  writeGroup( 2, QStringLiteral( "VIEW" ) );
705  writeHandle();
706  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
707  writeGroup( 70, 0 );
708  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
709 
710  // UCS
711  writeGroup( 0, QStringLiteral( "TABLE" ) );
712  writeGroup( 2, QStringLiteral( "UCS" ) );
713  writeHandle();
714  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
715  writeGroup( 70, 0 );
716  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
717 
718  // VPORT
719  writeGroup( 0, QStringLiteral( "TABLE" ) );
720  writeGroup( 2, QStringLiteral( "VPORT" ) );
721  writeHandle();
722  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
723 
724  writeGroup( 0, QStringLiteral( "VPORT" ) );
725  writeHandle();
726  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
727  writeGroup( 100, QStringLiteral( "AcDbViewportTableRecord" ) );
728  writeGroup( 2, QStringLiteral( "*ACTIVE" ) );
729  writeGroup( 70, 0 ); // flags
730  writeGroup( 0, QgsPoint( 0.0, 0.0 ) ); // lower left
731  writeGroup( 1, QgsPoint( 1.0, 1.0 ) ); // upper right
732  writeGroup( 2, QgsPoint( 0.0, 0.0 ) ); // view center point
733  writeGroup( 3, QgsPoint( 0.0, 0.0 ) ); // snap base point
734  writeGroup( 4, QgsPoint( 1.0, 1.0 ) ); // snap spacing
735  writeGroup( 5, QgsPoint( 1.0, 1.0 ) ); // grid spacing
736  writeGroup( 6, QgsPoint( QgsWkbTypes::PointZ, 0.0, 0.0, 1.0 ) ); // view direction from target point
737  writeGroup( 7, QgsPoint( mExtent.center() ) ); // view target point
738  writeGroup( 40, mExtent.height() ); // view height
739  writeGroup( 41, mExtent.width() / mExtent.height() ); // view aspect ratio
740  writeGroup( 42, 50.0 ); // lens length
741  writeGroup( 43, 0.0 ); // front clipping plane
742  writeGroup( 44, 0.0 ); // back clipping plane
743  writeGroup( 50, 0.0 ); // snap rotation
744  writeGroup( 51, 0.0 ); // view twist angle
745  writeGroup( 71, 0 ); // view mode (0 = deactivates)
746  writeGroup( 72, 100 ); // circle zoom percent
747  writeGroup( 73, 1 ); // fast zoom setting
748  writeGroup( 74, 1 ); // UCSICON setting
749  writeGroup( 75, 0 ); // snapping off
750  writeGroup( 76, 0 ); // grid off
751  writeGroup( 77, 0 ); // snap style
752  writeGroup( 78, 0 ); // snap isopair
753  writeGroup( 281, 0 ); // render mode (0 = 2D optimized)
754  writeGroup( 65, 1 ); // value of UCSVP for this viewport
755  writeGroup( 100, QgsPoint( QgsWkbTypes::PointZ ) ); // UCS origin
756  writeGroup( 101, QgsPoint( QgsWkbTypes::PointZ, 1.0 ) ); // UCS x axis
757  writeGroup( 102, QgsPoint( QgsWkbTypes::PointZ, 0.0, 1.0 ) ); // UCS y axis
758  writeGroup( 79, 0 ); // Orthographic type of UCS (0 = UCS is not orthographic)
759  writeGroup( 146, 0.0 ); // Elevation
760 
761  writeGroup( 70, 0 );
762  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
763 
764  // DIMSTYLE
765  writeGroup( 0, QStringLiteral( "TABLE" ) );
766  writeGroup( 2, QStringLiteral( "DIMSTYLE" ) );
767  writeHandle();
768  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
769  writeGroup( 100, QStringLiteral( "AcDbDimStyleTable" ) );
770  writeGroup( 70, 0 );
771  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
772 
773  QSet<QString> layerNames;
774  const QList< QgsMapLayer * > layers = mMapSettings.layers();
775  for ( QgsMapLayer *ml : layers )
776  {
777  if ( !layerIsScaleBasedVisible( ml ) )
778  continue;
779 
780  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
781  if ( !vl )
782  continue;
783 
784  int attrIdx = mLayerNameAttribute.value( vl->id(), -1 );
785  if ( attrIdx < 0 )
786  {
787  layerNames << dxfLayerName( layerName( vl ) );
788  }
789  else
790  {
791  const QSet<QVariant> values = vl->uniqueValues( attrIdx );
792  for ( const QVariant &v : values )
793  {
794  layerNames << dxfLayerName( v.toString() );
795  }
796  }
797  }
798 
799  // Layers
800  // TODO: iterate features of all layer to produce a data-defined layer list
801  writeGroup( 0, QStringLiteral( "TABLE" ) );
802  writeGroup( 2, QStringLiteral( "LAYER" ) );
803  writeHandle();
804  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
805  writeGroup( 70, layerNames.size() + 1 );
806 
807  writeGroup( 0, QStringLiteral( "LAYER" ) );
808  writeHandle();
809  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
810  writeGroup( 100, QStringLiteral( "AcDbLayerTableRecord" ) );
811  writeGroup( 2, QStringLiteral( "0" ) );
812  writeGroup( 70, 64 );
813  writeGroup( 62, 1 );
814  writeGroup( 6, QStringLiteral( "CONTINUOUS" ) );
816 
817  for ( const QString &layerName : qgis::as_const( layerNames ) )
818  {
819  writeGroup( 0, QStringLiteral( "LAYER" ) );
820  writeHandle();
821  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
822  writeGroup( 100, QStringLiteral( "AcDbLayerTableRecord" ) );
823  writeGroup( 2, layerName );
824  writeGroup( 70, 64 );
825  writeGroup( 62, 1 );
826  writeGroup( 6, QStringLiteral( "CONTINUOUS" ) );
828  }
829  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
830 
831  // Text styles
832  writeGroup( 0, QStringLiteral( "TABLE" ) );
833  writeGroup( 2, QStringLiteral( "STYLE" ) );
834  writeHandle();
835  writeGroup( 100, QStringLiteral( "AcDbSymbolTable" ) );
836  writeGroup( 70, 1 );
837 
838  // Provide only standard font for the moment
839  writeGroup( 0, QStringLiteral( "STYLE" ) );
840  writeHandle();
841  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
842  writeGroup( 100, QStringLiteral( "AcDbTextStyleTableRecord" ) );
843  writeGroup( 2, QStringLiteral( "STANDARD" ) );
844  writeGroup( 70, 64 );
845  writeGroup( 40, 0.0 );
846  writeGroup( 41, 1.0 );
847  writeGroup( 50, 0.0 );
848  writeGroup( 71, 0 );
849  writeGroup( 42, 5.0 );
850  writeGroup( 3, QStringLiteral( "romans.shx" ) );
851  writeGroup( 4, QLatin1String( "" ) );
852 
853  writeGroup( 0, QStringLiteral( "ENDTAB" ) );
854 
855  endSection();
856 }
857 
858 void QgsDxfExport::writeBlocks()
859 {
860  startSection();
861  writeGroup( 2, QStringLiteral( "BLOCKS" ) );
862 
863  const QStringList blockStrings = QStringList() << QStringLiteral( "*Model_Space" ) << QStringLiteral( "*Paper_Space" ) << QStringLiteral( "*Paper_Space0" );
864  for ( const QString &block : blockStrings )
865  {
866  writeGroup( 0, QStringLiteral( "BLOCK" ) );
867  writeHandle();
868  writeGroup( 330, QStringLiteral( "%1" ).arg( mBlockHandles[ block ], 0, 16 ) );
869  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
870  writeGroup( 8, QStringLiteral( "0" ) );
871  writeGroup( 100, QStringLiteral( "AcDbBlockBegin" ) );
872  writeGroup( 2, block );
873  writeGroup( 70, 0 );
875  writeGroup( 3, block );
876  writeGroup( 1, QLatin1String( "" ) );
877  writeGroup( 0, QStringLiteral( "ENDBLK" ) );
878  writeHandle();
879  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
880  writeGroup( 8, QStringLiteral( "0" ) );
881  writeGroup( 100, QStringLiteral( "AcDbBlockEnd" ) );
882  }
883 
884  QgsRenderContext ct = renderContext();
885 
886  // Iterate through all layers and get symbol layer pointers
887  QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
888  if ( mSymbologyExport != NoSymbology )
889  {
890  slList = symbolLayers( ct );
891  }
892 
893  QList< QPair< QgsSymbolLayer *, QgsSymbol * > >::const_iterator slIt = slList.constBegin();
894  for ( ; slIt != slList.constEnd(); ++slIt )
895  {
896  QgsMarkerSymbolLayer *ml = dynamic_cast< QgsMarkerSymbolLayer *>( slIt->first );
897  if ( !ml )
898  continue;
899 
900  // if point symbol layer and no data defined properties: write block
901  QgsSymbolRenderContext ctx( ct, QgsUnitTypes::RenderMapUnits, slIt->second->opacity(), false, slIt->second->renderHints(), nullptr );
902  ml->startRender( ctx );
903 
904  // markers with data defined properties are inserted inline
905  if ( hasDataDefinedProperties( ml, slIt->second ) )
906  {
907  continue;
908  // ml->stopRender( ctx );
909  }
910 
911  QString block( QStringLiteral( "symbolLayer%1" ).arg( mBlockCounter++ ) );
912  mBlockHandle = QStringLiteral( "%1" ).arg( mBlockHandles[ block ], 0, 16 );
913 
914  writeGroup( 0, QStringLiteral( "BLOCK" ) );
915  writeHandle();
916  writeGroup( 330, mBlockHandle );
917  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
918  writeGroup( 8, QStringLiteral( "0" ) );
919  writeGroup( 100, QStringLiteral( "AcDbBlockBegin" ) );
920  writeGroup( 2, block );
921  writeGroup( 70, 0 );
922 
923  // x/y/z coordinates of reference point
924  // todo: consider anchor point
925  // double size = ml->size();
926  // size *= mapUnitScaleFactor( mSymbologyScale, ml->sizeUnit(), mMapUnits );
928  writeGroup( 3, block );
929  writeGroup( 1, QLatin1String( "" ) );
930 
931  // maplayer 0 -> block receives layer from INSERT statement
932  ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScale, ml->sizeUnit(), mMapUnits ), QStringLiteral( "0" ), ctx );
933 
934  writeGroup( 0, QStringLiteral( "ENDBLK" ) );
935  writeHandle();
936  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
937  writeGroup( 8, QStringLiteral( "0" ) );
938  writeGroup( 100, QStringLiteral( "AcDbBlockEnd" ) );
939 
940  mPointSymbolBlocks.insert( ml, block );
941  ml->stopRender( ctx );
942  }
943  endSection();
944 }
945 
946 
947 void QgsDxfExport::writeEntities()
948 {
949  startSection();
950  writeGroup( 2, QStringLiteral( "ENTITIES" ) );
951 
952  mBlockHandle = QStringLiteral( "%1" ).arg( mBlockHandles[ QStringLiteral( "*Model_Space" )], 0, 16 );
953 
954  QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
955  image.setDotsPerMeterX( 96 / 25.4 * 1000 );
956  image.setDotsPerMeterY( 96 / 25.4 * 1000 );
957  QPainter painter( &image );
958 
959  QgsRenderContext ctx;
960  ctx.setPainter( &painter );
961  ctx.setRendererScale( mSymbologyScale );
962  ctx.setExtent( mExtent );
963 
964  ctx.setScaleFactor( 96.0 / 25.4 );
965  ctx.setMapToPixel( QgsMapToPixel( 1.0 / mFactor, mExtent.center().x(), mExtent.center().y(), mExtent.width() * mFactor,
966  mExtent.height() * mFactor, 0 ) );
967 
968  // label engine
969  QgsLabelingEngine engine;
970  engine.setMapSettings( mMapSettings );
971 
972  // iterate through the maplayers
973  const QList< QgsMapLayer *> layers = mMapSettings.layers();
974  for ( QgsMapLayer *ml : layers )
975  {
976  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
977  if ( !vl || !layerIsScaleBasedVisible( vl ) )
978  {
979  continue;
980  }
981 
982  bool hasStyleOverride = mMapSettings.layerStyleOverrides().contains( vl->id() );
983  if ( hasStyleOverride )
984  {
985  QgsDebugMsg( QString( "%1: apply override style" ).arg( vl->id() ) );
986  vl->styleManager()->setOverrideStyle( mMapSettings.layerStyleOverrides().value( vl->id() ) );
987  }
988  else
989  {
990  QgsDebugMsg( QString( "%1: not override style" ).arg( vl->id() ) );
991  }
992 
993  QgsSymbolRenderContext sctx( ctx, QgsUnitTypes::RenderMillimeters, 1.0, false, nullptr, nullptr );
994  if ( !vl->renderer() )
995  {
996  if ( hasStyleOverride )
998  continue;
999  }
1000 
1001  std::unique_ptr< QgsFeatureRenderer > renderer( vl->renderer()->clone() );
1002  renderer->startRender( ctx, vl->fields() );
1003 
1004  QSet<QString> attributes = renderer->usedAttributes( ctx );
1005  int attrIdx = mLayerNameAttribute.value( vl->id(), -1 );
1006  if ( vl->fields().exists( attrIdx ) )
1007  {
1008  QString layerAttr = vl->fields().at( attrIdx ).name();
1009  attributes << layerAttr;
1010  }
1011 
1012  const QgsAbstractVectorLayerLabeling *labeling = vl->labelsEnabled() ? vl->labeling() : nullptr;
1013  QgsDxfLabelProvider *lp = nullptr;
1014  QgsDxfRuleBasedLabelProvider *rblp = nullptr;
1015  if ( const QgsRuleBasedLabeling *rbl = dynamic_cast<const QgsRuleBasedLabeling *>( labeling ) )
1016  {
1017  rblp = new QgsDxfRuleBasedLabelProvider( *rbl, vl, this );
1018  rblp->reinit( vl );
1019  engine.addProvider( rblp );
1020 
1021  if ( !rblp->prepare( ctx, attributes ) )
1022  {
1023  engine.removeProvider( rblp );
1024  rblp = nullptr;
1025  }
1026  }
1027  else if ( labeling )
1028  {
1029  QgsPalLayerSettings settings = labeling->settings();
1030  lp = new QgsDxfLabelProvider( vl, QString(), this, &settings );
1031  engine.addProvider( lp );
1032 
1033  if ( !lp->prepare( ctx, attributes ) )
1034  {
1035  engine.removeProvider( lp );
1036  lp = nullptr;
1037  }
1038  }
1039 
1040  if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology &&
1041  ( renderer->capabilities() & QgsFeatureRenderer::SymbolLevels ) &&
1042  renderer->usingSymbolLevels() )
1043  {
1044  writeEntitiesSymbolLevels( vl );
1045  renderer->stopRender( ctx );
1046 
1047  if ( hasStyleOverride )
1049 
1050  continue;
1051  }
1052 
1053  QgsFeatureRequest freq = QgsFeatureRequest().setSubsetOfAttributes( attributes, vl->fields() ).setExpressionContext( ctx.expressionContext() );
1054  freq.setFilterRect( mMapSettings.mapToLayerCoordinates( vl, mExtent ) );
1055 
1056  QgsFeatureIterator featureIt = vl->getFeatures( freq );
1057 
1058  QgsCoordinateTransform ct = mMapSettings.layerTransform( vl );
1059 
1060  QgsFeature fet;
1061  while ( featureIt.nextFeature( fet ) )
1062  {
1063  ctx.expressionContext().setFeature( fet );
1064  QString lName( dxfLayerName( attrIdx < 0 ? layerName( vl ) : fet.attribute( attrIdx ).toString() ) );
1065 
1066  sctx.setFeature( &fet );
1067  if ( mSymbologyExport == NoSymbology )
1068  {
1069  addFeature( sctx, ct, lName, nullptr, nullptr ); // no symbology at all
1070  }
1071  else
1072  {
1073  QgsSymbolList symbolList = renderer->symbolsForFeature( fet, ctx );
1074  bool hasSymbology = symbolList.size() > 0;
1075 
1076  if ( hasSymbology && mSymbologyExport == QgsDxfExport::SymbolLayerSymbology ) // symbol layer symbology, but layer does not use symbol levels
1077  {
1078  QgsSymbolList::iterator symbolIt = symbolList.begin();
1079  for ( ; symbolIt != symbolList.end(); ++symbolIt )
1080  {
1081  int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
1082  for ( int i = 0; i < nSymbolLayers; ++i )
1083  {
1084  addFeature( sctx, ct, lName, ( *symbolIt )->symbolLayer( i ), *symbolIt );
1085  }
1086  }
1087  }
1088  else if ( hasSymbology )
1089  {
1090  // take first symbollayer from first symbol
1091  QgsSymbol *s = symbolList.first();
1092  if ( !s || s->symbolLayerCount() < 1 )
1093  {
1094  continue;
1095  }
1096  addFeature( sctx, ct, lName, s->symbolLayer( 0 ), s );
1097  }
1098 
1099  if ( lp )
1100  {
1101  lp->registerDxfFeature( fet, ctx, lName );
1102  }
1103  else if ( rblp )
1104  {
1105  rblp->registerDxfFeature( fet, ctx, lName );
1106  }
1107  }
1108  }
1109 
1110  renderer->stopRender( ctx );
1111 
1112  if ( hasStyleOverride )
1114  }
1115 
1116  engine.run( ctx );
1117 
1118  endSection();
1119 }
1120 
1121 void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer *layer )
1122 {
1123  if ( !layer )
1124  {
1125  return;
1126  }
1127 
1128  if ( !layer->renderer() )
1129  {
1130  // TODO return error
1131  return;
1132  }
1133  std::unique_ptr< QgsFeatureRenderer > renderer( layer->renderer()->clone() );
1134  QHash< QgsSymbol *, QList<QgsFeature> > features;
1135 
1136  QgsRenderContext ctx = renderContext();
1138  QgsSymbolRenderContext sctx( ctx, QgsUnitTypes::RenderMillimeters, 1.0, false, nullptr, nullptr );
1139  renderer->startRender( ctx, layer->fields() );
1140 
1141  // get iterator
1142  QgsFeatureRequest req;
1143  if ( layer->wkbType() == QgsWkbTypes::NoGeometry )
1144  {
1146  }
1147  req.setSubsetOfAttributes( renderer->usedAttributes( ctx ), layer->fields() );
1148  req.setFilterRect( mMapSettings.mapToLayerCoordinates( layer, mExtent ) );
1149 
1150  QgsFeatureIterator fit = layer->getFeatures( req );
1151 
1152  // fetch features
1153  QgsFeature fet;
1154  QgsSymbol *featureSymbol = nullptr;
1155  while ( fit.nextFeature( fet ) )
1156  {
1157  ctx.expressionContext().setFeature( fet );
1158  featureSymbol = renderer->symbolForFeature( fet, ctx );
1159  if ( !featureSymbol )
1160  {
1161  continue;
1162  }
1163 
1164  QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
1165  if ( it == features.end() )
1166  {
1167  it = features.insert( featureSymbol, QList<QgsFeature>() );
1168  }
1169  it.value().append( fet );
1170  }
1171 
1172  // find out order
1173  QgsSymbolLevelOrder levels;
1174  QgsSymbolList symbols = renderer->symbols( ctx );
1175  for ( int i = 0; i < symbols.count(); i++ )
1176  {
1177  QgsSymbol *sym = symbols[i];
1178  for ( int j = 0; j < sym->symbolLayerCount(); j++ )
1179  {
1180  int level = sym->symbolLayer( j )->renderingPass();
1181  if ( level < 0 || level >= 1000 ) // ignore invalid levels
1182  continue;
1183  QgsSymbolLevelItem item( sym, j );
1184  while ( level >= levels.count() ) // append new empty levels
1185  levels.append( QgsSymbolLevel() );
1186  levels[level].append( item );
1187  }
1188  }
1189 
1190  QgsCoordinateTransform ct = mMapSettings.layerTransform( layer );
1191 
1192  // export symbol layers and symbology
1193  for ( int l = 0; l < levels.count(); l++ )
1194  {
1195  QgsSymbolLevel &level = levels[l];
1196  for ( int i = 0; i < level.count(); i++ )
1197  {
1198  QgsSymbolLevelItem &item = level[i];
1199  QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
1200  if ( levelIt == features.end() )
1201  {
1202  QgsDebugMsg( QString( "No feature found for symbol on %1 %2.%3" ).arg( layer->id() ).arg( l ).arg( i ) );
1203  continue;
1204  }
1205 
1206  int llayer = item.layer();
1207  QList<QgsFeature> &featureList = levelIt.value();
1208  QList<QgsFeature>::iterator featureIt = featureList.begin();
1209  for ( ; featureIt != featureList.end(); ++featureIt )
1210  {
1211  sctx.setFeature( &*featureIt );
1212  addFeature( sctx, ct, layer->name(), levelIt.key()->symbolLayer( llayer ), levelIt.key() );
1213  }
1214  }
1215  }
1216  renderer->stopRender( ctx );
1217 }
1218 
1219 void QgsDxfExport::writeEndFile()
1220 {
1221  // From GDAL trailer.dxf
1222  mTextStream << "\
1223  0\n\
1224 SECTION\n\
1225  2\n\
1226 OBJECTS\n\
1227  0\n\
1228 DICTIONARY\n\
1229  5\n\
1230 C\n\
1231 330\n\
1232 0\n\
1233 100\n\
1234 AcDbDictionary\n\
1235 281\n\
1236  1\n\
1237  3\n\
1238 ACAD_GROUP\n\
1239 350\n\
1240 D\n\
1241  3\n\
1242 ACAD_LAYOUT\n\
1243 350\n\
1244 1A\n\
1245  3\n\
1246 ACAD_MLEADERSTYLE\n\
1247 350\n\
1248 43\n\
1249  3\n\
1250 ACAD_MLINESTYLE\n\
1251 350\n\
1252 17\n\
1253  3\n\
1254 ACAD_PLOTSETTINGS\n\
1255 350\n\
1256 19\n\
1257  3\n\
1258 ACAD_PLOTSTYLENAME\n\
1259 350\n\
1260 E\n\
1261  3\n\
1262 ACAD_TABLESTYLE\n\
1263 350\n\
1264 42\n\
1265  3\n\
1266 ACAD_VISUALSTYLE\n\
1267 350\n\
1268 2A\n\
1269  0\n\
1270 DICTIONARY\n\
1271  5\n\
1272 D\n\
1273 102\n\
1274 {ACAD_REACTORS\n\
1275 330\n\
1276 C\n\
1277 102\n\
1278 }\n\
1279 330\n\
1280 C\n\
1281 100\n\
1282 AcDbDictionary\n\
1283 281\n\
1284  1\n\
1285  0\n\
1286 DICTIONARY\n\
1287  5\n\
1288 1A\n\
1289 102\n\
1290 {ACAD_REACTORS\n\
1291 330\n\
1292 C\n\
1293 102\n\
1294 }\n\
1295 330\n\
1296 C\n\
1297 100\n\
1298 AcDbDictionary\n\
1299 281\n\
1300  1\n\
1301  3\n\
1302 Layout1\n\
1303 350\n\
1304 1E\n\
1305  3\n\
1306 Layout2\n\
1307 350\n\
1308 26\n\
1309  3\n\
1310 Model\n\
1311 350\n\
1312 22\n\
1313  0\n\
1314 DICTIONARY\n\
1315  5\n\
1316 43\n\
1317 102\n\
1318 {ACAD_REACTORS\n\
1319 330\n\
1320 C\n\
1321 102\n\
1322 }\n\
1323 330\n\
1324 C\n\
1325 100\n\
1326 AcDbDictionary\n\
1327 281\n\
1328  1\n\
1329  0\n\
1330 DICTIONARY\n\
1331  5\n\
1332 17\n\
1333 102\n\
1334 {ACAD_REACTORS\n\
1335 330\n\
1336 C\n\
1337 102\n\
1338 }\n\
1339 330\n\
1340 C\n\
1341 100\n\
1342 AcDbDictionary\n\
1343 281\n\
1344  1\n\
1345  3\n\
1346 Standard\n\
1347 350\n\
1348 18\n\
1349  0\n\
1350 DICTIONARY\n\
1351  5\n\
1352 19\n\
1353 102\n\
1354 {ACAD_REACTORS\n\
1355 330\n\
1356 C\n\
1357 102\n\
1358 }\n\
1359 330\n\
1360 C\n\
1361 100\n\
1362 AcDbDictionary\n\
1363 281\n\
1364  1\n\
1365  0\n\
1366 ACDBDICTIONARYWDFLT\n\
1367  5\n\
1368 E\n\
1369 102\n\
1370 {ACAD_REACTORS\n\
1371 330\n\
1372 C\n\
1373 102\n\
1374 }\n\
1375 330\n\
1376 C\n\
1377 100\n\
1378 AcDbDictionary\n\
1379 281\n\
1380  1\n\
1381  3\n\
1382 Normal\n\
1383 350\n\
1384 F\n\
1385 100\n\
1386 AcDbDictionaryWithDefault\n\
1387 340\n\
1388 F\n\
1389  0\n\
1390 DICTIONARY\n\
1391  5\n\
1392 42\n\
1393 102\n\
1394 {ACAD_REACTORS\n\
1395 330\n\
1396 C\n\
1397 102\n\
1398 }\n\
1399 330\n\
1400 C\n\
1401 100\n\
1402 AcDbDictionary\n\
1403 281\n\
1404  1\n\
1405  0\n\
1406 DICTIONARY\n\
1407  5\n\
1408 2A\n\
1409 102\n\
1410 {ACAD_REACTORS\n\
1411 330\n\
1412 C\n\
1413 102\n\
1414 }\n\
1415 330\n\
1416 C\n\
1417 100\n\
1418 AcDbDictionary\n\
1419 281\n\
1420  1\n\
1421  3\n\
1422 2dWireframe\n\
1423 350\n\
1424 2F\n\
1425  3\n\
1426 3D Hidden\n\
1427 350\n\
1428 31\n\
1429  3\n\
1430 3dWireframe\n\
1431 350\n\
1432 30\n\
1433  3\n\
1434 Basic\n\
1435 350\n\
1436 32\n\
1437  3\n\
1438 Brighten\n\
1439 350\n\
1440 36\n\
1441  3\n\
1442 ColorChange\n\
1443 350\n\
1444 3A\n\
1445  3\n\
1446 Conceptual\n\
1447 350\n\
1448 34\n\
1449  3\n\
1450 Dim\n\
1451 350\n\
1452 35\n\
1453  3\n\
1454 Facepattern\n\
1455 350\n\
1456 39\n\
1457  3\n\
1458 Flat\n\
1459 350\n\
1460 2B\n\
1461  3\n\
1462 FlatWithEdges\n\
1463 350\n\
1464 2C\n\
1465  3\n\
1466 Gouraud\n\
1467 350\n\
1468 2D\n\
1469  3\n\
1470 GouraudWithEdges\n\
1471 350\n\
1472 2E\n\
1473  3\n\
1474 Linepattern\n\
1475 350\n\
1476 38\n\
1477  3\n\
1478 Realistic\n\
1479 350\n\
1480 33\n\
1481  3\n\
1482 Thicken\n\
1483 350\n\
1484 37\n\
1485  0\n\
1486 LAYOUT\n\
1487  5\n\
1488 1E\n\
1489 102\n\
1490 {ACAD_REACTORS\n\
1491 330\n\
1492 1A\n\
1493 102\n\
1494 }\n\
1495 330\n\
1496 1A\n\
1497 100\n\
1498 AcDbPlotSettings\n\
1499  1\n\
1500 \n\
1501  2\n\
1502 none_device\n\
1503  4\n\
1504 \n\
1505  6\n\
1506 \n\
1507  40\n\
1508 0.0\n\
1509  41\n\
1510 0.0\n\
1511  42\n\
1512 0.0\n\
1513  43\n\
1514 0.0\n\
1515  44\n\
1516 0.0\n\
1517  45\n\
1518 0.0\n\
1519  46\n\
1520 0.0\n\
1521  47\n\
1522 0.0\n\
1523  48\n\
1524 0.0\n\
1525  49\n\
1526 0.0\n\
1527 140\n\
1528 0.0\n\
1529 141\n\
1530 0.0\n\
1531 142\n\
1532 1.0\n\
1533 143\n\
1534 1.0\n\
1535  70\n\
1536  688\n\
1537  72\n\
1538  0\n\
1539  73\n\
1540  0\n\
1541  74\n\
1542  5\n\
1543  7\n\
1544 \n\
1545  75\n\
1546  16\n\
1547  76\n\
1548  0\n\
1549  77\n\
1550  2\n\
1551  78\n\
1552  300\n\
1553 147\n\
1554 1.0\n\
1555 148\n\
1556 0.0\n\
1557 149\n\
1558 0.0\n\
1559 100\n\
1560 AcDbLayout\n\
1561  1\n\
1562 Layout1\n\
1563  70\n\
1564  1\n\
1565  71\n\
1566  1\n\
1567  10\n\
1568 0.0\n\
1569  20\n\
1570 0.0\n\
1571  11\n\
1572 12.0\n\
1573  21\n\
1574 9.0\n\
1575  12\n\
1576 0.0\n\
1577  22\n\
1578 0.0\n\
1579  32\n\
1580 0.0\n\
1581  14\n\
1582 1.000000000000000E+20\n\
1583  24\n\
1584 1.000000000000000E+20\n\
1585  34\n\
1586 1.000000000000000E+20\n\
1587  15\n\
1588 -1.000000000000000E+20\n\
1589  25\n\
1590 -1.000000000000000E+20\n\
1591  35\n\
1592 -1.000000000000000E+20\n\
1593 146\n\
1594 0.0\n\
1595  13\n\
1596 0.0\n\
1597  23\n\
1598 0.0\n\
1599  33\n\
1600 0.0\n\
1601  16\n\
1602 1.0\n\
1603  26\n\
1604 0.0\n\
1605  36\n\
1606 0.0\n\
1607  17\n\
1608 0.0\n\
1609  27\n\
1610 1.0\n\
1611  37\n\
1612 0.0\n\
1613  76\n\
1614  0\n\
1615 330\n\
1616 1B\n\
1617  0\n\
1618 LAYOUT\n\
1619  5\n\
1620 26\n\
1621 102\n\
1622 {ACAD_REACTORS\n\
1623 330\n\
1624 1A\n\
1625 102\n\
1626 }\n\
1627 330\n\
1628 1A\n\
1629 100\n\
1630 AcDbPlotSettings\n\
1631  1\n\
1632 \n\
1633  2\n\
1634 none_device\n\
1635  4\n\
1636 \n\
1637  6\n\
1638 \n\
1639  40\n\
1640 0.0\n\
1641  41\n\
1642 0.0\n\
1643  42\n\
1644 0.0\n\
1645  43\n\
1646 0.0\n\
1647  44\n\
1648 0.0\n\
1649  45\n\
1650 0.0\n\
1651  46\n\
1652 0.0\n\
1653  47\n\
1654 0.0\n\
1655  48\n\
1656 0.0\n\
1657  49\n\
1658 0.0\n\
1659 140\n\
1660 0.0\n\
1661 141\n\
1662 0.0\n\
1663 142\n\
1664 1.0\n\
1665 143\n\
1666 1.0\n\
1667  70\n\
1668  688\n\
1669  72\n\
1670  0\n\
1671  73\n\
1672  0\n\
1673  74\n\
1674  5\n\
1675  7\n\
1676 \n\
1677  75\n\
1678  16\n\
1679  76\n\
1680  0\n\
1681  77\n\
1682  2\n\
1683  78\n\
1684  300\n\
1685 147\n\
1686 1.0\n\
1687 148\n\
1688 0.0\n\
1689 149\n\
1690 0.0\n\
1691 100\n\
1692 AcDbLayout\n\
1693  1\n\
1694 Layout2\n\
1695  70\n\
1696  1\n\
1697  71\n\
1698  2\n\
1699  10\n\
1700 0.0\n\
1701  20\n\
1702 0.0\n\
1703  11\n\
1704 0.0\n\
1705  21\n\
1706 0.0\n\
1707  12\n\
1708 0.0\n\
1709  22\n\
1710 0.0\n\
1711  32\n\
1712 0.0\n\
1713  14\n\
1714 0.0\n\
1715  24\n\
1716 0.0\n\
1717  34\n\
1718 0.0\n\
1719  15\n\
1720 0.0\n\
1721  25\n\
1722 0.0\n\
1723  35\n\
1724 0.0\n\
1725 146\n\
1726 0.0\n\
1727  13\n\
1728 0.0\n\
1729  23\n\
1730 0.0\n\
1731  33\n\
1732 0.0\n\
1733  16\n\
1734 1.0\n\
1735  26\n\
1736 0.0\n\
1737  36\n\
1738 0.0\n\
1739  17\n\
1740 0.0\n\
1741  27\n\
1742 1.0\n\
1743  37\n\
1744 0.0\n\
1745  76\n\
1746  0\n\
1747 330\n\
1748 23\n\
1749  0\n\
1750 LAYOUT\n\
1751  5\n\
1752 22\n\
1753 102\n\
1754 {ACAD_REACTORS\n\
1755 330\n\
1756 1A\n\
1757 102\n\
1758 }\n\
1759 330\n\
1760 1A\n\
1761 100\n\
1762 AcDbPlotSettings\n\
1763  1\n\
1764 \n\
1765  2\n\
1766 none_device\n\
1767  4\n\
1768 \n\
1769  6\n\
1770 \n\
1771  40\n\
1772 0.0\n\
1773  41\n\
1774 0.0\n\
1775  42\n\
1776 0.0\n\
1777  43\n\
1778 0.0\n\
1779  44\n\
1780 0.0\n\
1781  45\n\
1782 0.0\n\
1783  46\n\
1784 0.0\n\
1785  47\n\
1786 0.0\n\
1787  48\n\
1788 0.0\n\
1789  49\n\
1790 0.0\n\
1791 140\n\
1792 0.0\n\
1793 141\n\
1794 0.0\n\
1795 142\n\
1796 1.0\n\
1797 143\n\
1798 1.0\n\
1799  70\n\
1800  1712\n\
1801  72\n\
1802  0\n\
1803  73\n\
1804  0\n\
1805  74\n\
1806  0\n\
1807  7\n\
1808 \n\
1809  75\n\
1810  0\n\
1811  76\n\
1812  0\n\
1813  77\n\
1814  2\n\
1815  78\n\
1816  300\n\
1817 147\n\
1818 1.0\n\
1819 148\n\
1820 0.0\n\
1821 149\n\
1822 0.0\n\
1823 100\n\
1824 AcDbLayout\n\
1825  1\n\
1826 Model\n\
1827  70\n\
1828  1\n\
1829  71\n\
1830  0\n\
1831  10\n\
1832 0.0\n\
1833  20\n\
1834 0.0\n\
1835  11\n\
1836 12.0\n\
1837  21\n\
1838 9.0\n\
1839  12\n\
1840 0.0\n\
1841  22\n\
1842 0.0\n\
1843  32\n\
1844 0.0\n\
1845  14\n\
1846 30.0\n\
1847  24\n\
1848 49.75\n\
1849  34\n\
1850 0.0\n\
1851  15\n\
1852 130.5\n\
1853  25\n\
1854 163.1318914119703\n\
1855  35\n\
1856 0.0\n\
1857 146\n\
1858 0.0\n\
1859  13\n\
1860 0.0\n\
1861  23\n\
1862 0.0\n\
1863  33\n\
1864 0.0\n\
1865  16\n\
1866 1.0\n\
1867  26\n\
1868 0.0\n\
1869  36\n\
1870 0.0\n\
1871  17\n\
1872 0.0\n\
1873  27\n\
1874 1.0\n\
1875  37\n\
1876 0.0\n\
1877  76\n\
1878  0\n\
1879 330\n\
1880 1F\n\
1881 331\n\
1882 29\n\
1883  0\n\
1884 MLINESTYLE\n\
1885  5\n\
1886 18\n\
1887 102\n\
1888 {ACAD_REACTORS\n\
1889 330\n\
1890 17\n\
1891 102\n\
1892 }\n\
1893 330\n\
1894 17\n\
1895 100\n\
1896 AcDbMlineStyle\n\
1897  2\n\
1898 Standard\n\
1899  70\n\
1900  0\n\
1901  3\n\
1902 \n\
1903  62\n\
1904  256\n\
1905  51\n\
1906 90.0\n\
1907  52\n\
1908 90.0\n\
1909  71\n\
1910  2\n\
1911  49\n\
1912 0.5\n\
1913  62\n\
1914  256\n\
1915  6\n\
1916 BYLAYER\n\
1917  49\n\
1918 -0.5\n\
1919  62\n\
1920  256\n\
1921  6\n\
1922 BYLAYER\n\
1923  0\n\
1924 ACDBPLACEHOLDER\n\
1925  5\n\
1926 F\n\
1927 102\n\
1928 {ACAD_REACTORS\n\
1929 330\n\
1930 E\n\
1931 102\n\
1932 }\n\
1933 330\n\
1934 E\n\
1935  0\n\
1936 VISUALSTYLE\n\
1937  5\n\
1938 2F\n\
1939 102\n\
1940 {ACAD_REACTORS\n\
1941 330\n\
1942 2A\n\
1943 102\n\
1944 }\n\
1945 330\n\
1946 2A\n\
1947 100\n\
1948 AcDbVisualStyle\n\
1949  2\n\
1950 2dWireframe\n\
1951  70\n\
1952  4\n\
1953  71\n\
1954  0\n\
1955  72\n\
1956  2\n\
1957  73\n\
1958  0\n\
1959  90\n\
1960  0\n\
1961  40\n\
1962 -0.6\n\
1963  41\n\
1964 -30.0\n\
1965  62\n\
1966  5\n\
1967  63\n\
1968  7\n\
1969 421\n\
1970  16777215\n\
1971  74\n\
1972  1\n\
1973  91\n\
1974  4\n\
1975  64\n\
1976  7\n\
1977  65\n\
1978  257\n\
1979  75\n\
1980  1\n\
1981 175\n\
1982  1\n\
1983  42\n\
1984 1.0\n\
1985  92\n\
1986  0\n\
1987  66\n\
1988  257\n\
1989  43\n\
1990 1.0\n\
1991  76\n\
1992  1\n\
1993  77\n\
1994  6\n\
1995  78\n\
1996  2\n\
1997  67\n\
1998  7\n\
1999  79\n\
2000  5\n\
2001 170\n\
2002  0\n\
2003 171\n\
2004  0\n\
2005 290\n\
2006  0\n\
2007 174\n\
2008  0\n\
2009  93\n\
2010  1\n\
2011  44\n\
2012 0.0\n\
2013 173\n\
2014  0\n\
2015 291\n\
2016  0\n\
2017  45\n\
2018 0.0\n\
2019 1001\n\
2020 ACAD\n\
2021 1000\n\
2022 AcDbSavedByObjectVersion\n\
2023 1070\n\
2024  0\n\
2025  0\n\
2026 VISUALSTYLE\n\
2027  5\n\
2028 31\n\
2029 102\n\
2030 {ACAD_REACTORS\n\
2031 330\n\
2032 2A\n\
2033 102\n\
2034 }\n\
2035 330\n\
2036 2A\n\
2037 100\n\
2038 AcDbVisualStyle\n\
2039  2\n\
2040 3D Hidden\n\
2041  70\n\
2042  6\n\
2043  71\n\
2044  1\n\
2045  72\n\
2046  2\n\
2047  73\n\
2048  2\n\
2049  90\n\
2050  0\n\
2051  40\n\
2052 -0.6\n\
2053  41\n\
2054 -30.0\n\
2055  62\n\
2056  5\n\
2057  63\n\
2058  7\n\
2059 421\n\
2060  16777215\n\
2061  74\n\
2062  2\n\
2063  91\n\
2064  2\n\
2065  64\n\
2066  7\n\
2067  65\n\
2068  257\n\
2069  75\n\
2070  2\n\
2071 175\n\
2072  1\n\
2073  42\n\
2074 40.0\n\
2075  92\n\
2076  0\n\
2077  66\n\
2078  257\n\
2079  43\n\
2080 1.0\n\
2081  76\n\
2082  1\n\
2083  77\n\
2084  6\n\
2085  78\n\
2086  2\n\
2087  67\n\
2088  7\n\
2089  79\n\
2090  3\n\
2091 170\n\
2092  0\n\
2093 171\n\
2094  0\n\
2095 290\n\
2096  0\n\
2097 174\n\
2098  0\n\
2099  93\n\
2100  1\n\
2101  44\n\
2102 0.0\n\
2103 173\n\
2104  0\n\
2105 291\n\
2106  0\n\
2107  45\n\
2108 0.0\n\
2109 1001\n\
2110 ACAD\n\
2111 1000\n\
2112 AcDbSavedByObjectVersion\n\
2113 1070\n\
2114  0\n\
2115  0\n\
2116 VISUALSTYLE\n\
2117  5\n\
2118 30\n\
2119 102\n\
2120 {ACAD_REACTORS\n\
2121 330\n\
2122 2A\n\
2123 102\n\
2124 }\n\
2125 330\n\
2126 2A\n\
2127 100\n\
2128 AcDbVisualStyle\n\
2129  2\n\
2130 3dWireframe\n\
2131  70\n\
2132  5\n\
2133  71\n\
2134  0\n\
2135  72\n\
2136  2\n\
2137  73\n\
2138  0\n\
2139  90\n\
2140  0\n\
2141  40\n\
2142 -0.6\n\
2143  41\n\
2144 -30.0\n\
2145  62\n\
2146  5\n\
2147  63\n\
2148  7\n\
2149 421\n\
2150  16777215\n\
2151  74\n\
2152  1\n\
2153  91\n\
2154  4\n\
2155  64\n\
2156  7\n\
2157  65\n\
2158  257\n\
2159  75\n\
2160  1\n\
2161 175\n\
2162  1\n\
2163  42\n\
2164 1.0\n\
2165  92\n\
2166  0\n\
2167  66\n\
2168  257\n\
2169  43\n\
2170 1.0\n\
2171  76\n\
2172  1\n\
2173  77\n\
2174  6\n\
2175  78\n\
2176  2\n\
2177  67\n\
2178  7\n\
2179  79\n\
2180  5\n\
2181 170\n\
2182  0\n\
2183 171\n\
2184  0\n\
2185 290\n\
2186  0\n\
2187 174\n\
2188  0\n\
2189  93\n\
2190  1\n\
2191  44\n\
2192 0.0\n\
2193 173\n\
2194  0\n\
2195 291\n\
2196  0\n\
2197  45\n\
2198 0.0\n\
2199 1001\n\
2200 ACAD\n\
2201 1000\n\
2202 AcDbSavedByObjectVersion\n\
2203 1070\n\
2204  0\n\
2205  0\n\
2206 VISUALSTYLE\n\
2207  5\n\
2208 32\n\
2209 102\n\
2210 {ACAD_REACTORS\n\
2211 330\n\
2212 2A\n\
2213 102\n\
2214 }\n\
2215 330\n\
2216 2A\n\
2217 100\n\
2218 AcDbVisualStyle\n\
2219  2\n\
2220 Basic\n\
2221  70\n\
2222  7\n\
2223  71\n\
2224  1\n\
2225  72\n\
2226  0\n\
2227  73\n\
2228  1\n\
2229  90\n\
2230  0\n\
2231  40\n\
2232 -0.6\n\
2233  41\n\
2234 -30.0\n\
2235  62\n\
2236  5\n\
2237  63\n\
2238  7\n\
2239 421\n\
2240  16777215\n\
2241  74\n\
2242  0\n\
2243  91\n\
2244  4\n\
2245  64\n\
2246  7\n\
2247  65\n\
2248  257\n\
2249  75\n\
2250  1\n\
2251 175\n\
2252  1\n\
2253  42\n\
2254 1.0\n\
2255  92\n\
2256  8\n\
2257  66\n\
2258  7\n\
2259  43\n\
2260 1.0\n\
2261  76\n\
2262  1\n\
2263  77\n\
2264  6\n\
2265  78\n\
2266  2\n\
2267  67\n\
2268  7\n\
2269  79\n\
2270  5\n\
2271 170\n\
2272  0\n\
2273 171\n\
2274  0\n\
2275 290\n\
2276  0\n\
2277 174\n\
2278  0\n\
2279  93\n\
2280  1\n\
2281  44\n\
2282 0.0\n\
2283 173\n\
2284  0\n\
2285 291\n\
2286  1\n\
2287  45\n\
2288 0.0\n\
2289 1001\n\
2290 ACAD\n\
2291 1000\n\
2292 AcDbSavedByObjectVersion\n\
2293 1070\n\
2294  0\n\
2295  0\n\
2296 VISUALSTYLE\n\
2297  5\n\
2298 36\n\
2299 102\n\
2300 {ACAD_REACTORS\n\
2301 330\n\
2302 2A\n\
2303 102\n\
2304 }\n\
2305 330\n\
2306 2A\n\
2307 100\n\
2308 AcDbVisualStyle\n\
2309  2\n\
2310 Brighten\n\
2311  70\n\
2312  12\n\
2313  71\n\
2314  2\n\
2315  72\n\
2316  2\n\
2317  73\n\
2318  0\n\
2319  90\n\
2320  0\n\
2321  40\n\
2322 -0.6\n\
2323  41\n\
2324 -30.0\n\
2325  62\n\
2326  5\n\
2327  63\n\
2328  7\n\
2329 421\n\
2330  16777215\n\
2331  74\n\
2332  1\n\
2333  91\n\
2334  4\n\
2335  64\n\
2336  7\n\
2337  65\n\
2338  257\n\
2339  75\n\
2340  1\n\
2341 175\n\
2342  1\n\
2343  42\n\
2344 1.0\n\
2345  92\n\
2346  8\n\
2347  66\n\
2348  7\n\
2349  43\n\
2350 1.0\n\
2351  76\n\
2352  1\n\
2353  77\n\
2354  6\n\
2355  78\n\
2356  2\n\
2357  67\n\
2358  7\n\
2359  79\n\
2360  5\n\
2361 170\n\
2362  0\n\
2363 171\n\
2364  0\n\
2365 290\n\
2366  0\n\
2367 174\n\
2368  0\n\
2369  93\n\
2370  1\n\
2371  44\n\
2372 50.0\n\
2373 173\n\
2374  0\n\
2375 291\n\
2376  1\n\
2377  45\n\
2378 0.0\n\
2379 1001\n\
2380 ACAD\n\
2381 1000\n\
2382 AcDbSavedByObjectVersion\n\
2383 1070\n\
2384  0\n\
2385  0\n\
2386 VISUALSTYLE\n\
2387  5\n\
2388 3A\n\
2389 102\n\
2390 {ACAD_REACTORS\n\
2391 330\n\
2392 2A\n\
2393 102\n\
2394 }\n\
2395 330\n\
2396 2A\n\
2397 100\n\
2398 AcDbVisualStyle\n\
2399  2\n\
2400 ColorChange\n\
2401  70\n\
2402  16\n\
2403  71\n\
2404  2\n\
2405  72\n\
2406  2\n\
2407  73\n\
2408  3\n\
2409  90\n\
2410  0\n\
2411  40\n\
2412 -0.6\n\
2413  41\n\
2414 -30.0\n\
2415  62\n\
2416  5\n\
2417  63\n\
2418  8\n\
2419 421\n\
2420  8421504\n\
2421  74\n\
2422  1\n\
2423  91\n\
2424  4\n\
2425  64\n\
2426  7\n\
2427  65\n\
2428  257\n\
2429  75\n\
2430  1\n\
2431 175\n\
2432  1\n\
2433  42\n\
2434 1.0\n\
2435  92\n\
2436  8\n\
2437  66\n\
2438  8\n\
2439 424\n\
2440  8421504\n\
2441  43\n\
2442 1.0\n\
2443  76\n\
2444  1\n\
2445  77\n\
2446  6\n\
2447  78\n\
2448  2\n\
2449  67\n\
2450  7\n\
2451  79\n\
2452  5\n\
2453 170\n\
2454  0\n\
2455 171\n\
2456  0\n\
2457 290\n\
2458  0\n\
2459 174\n\
2460  0\n\
2461  93\n\
2462  1\n\
2463  44\n\
2464 0.0\n\
2465 173\n\
2466  0\n\
2467 291\n\
2468  1\n\
2469  45\n\
2470 0.0\n\
2471 1001\n\
2472 ACAD\n\
2473 1000\n\
2474 AcDbSavedByObjectVersion\n\
2475 1070\n\
2476  0\n\
2477  0\n\
2478 VISUALSTYLE\n\
2479  5\n\
2480 34\n\
2481 102\n\
2482 {ACAD_REACTORS\n\
2483 330\n\
2484 2A\n\
2485 102\n\
2486 }\n\
2487 330\n\
2488 2A\n\
2489 100\n\
2490 AcDbVisualStyle\n\
2491  2\n\
2492 Conceptual\n\
2493  70\n\
2494  9\n\
2495  71\n\
2496  3\n\
2497  72\n\
2498  2\n\
2499  73\n\
2500  0\n\
2501  90\n\
2502  0\n\
2503  40\n\
2504 -0.6\n\
2505  41\n\
2506 -30.0\n\
2507  62\n\
2508  5\n\
2509  63\n\
2510  7\n\
2511 421\n\
2512  16777215\n\
2513  74\n\
2514  2\n\
2515  91\n\
2516  2\n\
2517  64\n\
2518  7\n\
2519  65\n\
2520  257\n\
2521  75\n\
2522  1\n\
2523 175\n\
2524  1\n\
2525  42\n\
2526 40.0\n\
2527  92\n\
2528  8\n\
2529  66\n\
2530  7\n\
2531  43\n\
2532 1.0\n\
2533  76\n\
2534  1\n\
2535  77\n\
2536  6\n\
2537  78\n\
2538  2\n\
2539  67\n\
2540  7\n\
2541  79\n\
2542  3\n\
2543 170\n\
2544  0\n\
2545 171\n\
2546  0\n\
2547 290\n\
2548  0\n\
2549 174\n\
2550  0\n\
2551  93\n\
2552  1\n\
2553  44\n\
2554 0.0\n\
2555 173\n\
2556  0\n\
2557 291\n\
2558  0\n\
2559  45\n\
2560 0.0\n\
2561 1001\n\
2562 ACAD\n\
2563 1000\n\
2564 AcDbSavedByObjectVersion\n\
2565 1070\n\
2566  0\n\
2567  0\n\
2568 VISUALSTYLE\n\
2569  5\n\
2570 35\n\
2571 102\n\
2572 {ACAD_REACTORS\n\
2573 330\n\
2574 2A\n\
2575 102\n\
2576 }\n\
2577 330\n\
2578 2A\n\
2579 100\n\
2580 AcDbVisualStyle\n\
2581  2\n\
2582 Dim\n\
2583  70\n\
2584  11\n\
2585  71\n\
2586  2\n\
2587  72\n\
2588  2\n\
2589  73\n\
2590  0\n\
2591  90\n\
2592  0\n\
2593  40\n\
2594 -0.6\n\
2595  41\n\
2596 -30.0\n\
2597  62\n\
2598  5\n\
2599  63\n\
2600  7\n\
2601 421\n\
2602  16777215\n\
2603  74\n\
2604  1\n\
2605  91\n\
2606  4\n\
2607  64\n\
2608  7\n\
2609  65\n\
2610  257\n\
2611  75\n\
2612  1\n\
2613 175\n\
2614  1\n\
2615  42\n\
2616 1.0\n\
2617  92\n\
2618  8\n\
2619  66\n\
2620  7\n\
2621  43\n\
2622 1.0\n\
2623  76\n\
2624  1\n\
2625  77\n\
2626  6\n\
2627  78\n\
2628  2\n\
2629  67\n\
2630  7\n\
2631  79\n\
2632  5\n\
2633 170\n\
2634  0\n\
2635 171\n\
2636  0\n\
2637 290\n\
2638  0\n\
2639 174\n\
2640  0\n\
2641  93\n\
2642  1\n\
2643  44\n\
2644 -50.0\n\
2645 173\n\
2646  0\n\
2647 291\n\
2648  1\n\
2649  45\n\
2650 0.0\n\
2651 1001\n\
2652 ACAD\n\
2653 1000\n\
2654 AcDbSavedByObjectVersion\n\
2655 1070\n\
2656  0\n\
2657  0\n\
2658 VISUALSTYLE\n\
2659  5\n\
2660 39\n\
2661 102\n\
2662 {ACAD_REACTORS\n\
2663 330\n\
2664 2A\n\
2665 102\n\
2666 }\n\
2667 330\n\
2668 2A\n\
2669 100\n\
2670 AcDbVisualStyle\n\
2671  2\n\
2672 Facepattern\n\
2673  70\n\
2674  15\n\
2675  71\n\
2676  2\n\
2677  72\n\
2678  2\n\
2679  73\n\
2680  0\n\
2681  90\n\
2682  0\n\
2683  40\n\
2684 -0.6\n\
2685  41\n\
2686 -30.0\n\
2687  62\n\
2688  5\n\
2689  63\n\
2690  7\n\
2691 421\n\
2692  16777215\n\
2693  74\n\
2694  1\n\
2695  91\n\
2696  4\n\
2697  64\n\
2698  7\n\
2699  65\n\
2700  257\n\
2701  75\n\
2702  1\n\
2703 175\n\
2704  1\n\
2705  42\n\
2706 1.0\n\
2707  92\n\
2708  8\n\
2709  66\n\
2710  7\n\
2711  43\n\
2712 1.0\n\
2713  76\n\
2714  1\n\
2715  77\n\
2716  6\n\
2717  78\n\
2718  2\n\
2719  67\n\
2720  7\n\
2721  79\n\
2722  5\n\
2723 170\n\
2724  0\n\
2725 171\n\
2726  0\n\
2727 290\n\
2728  0\n\
2729 174\n\
2730  0\n\
2731  93\n\
2732  1\n\
2733  44\n\
2734 0.0\n\
2735 173\n\
2736  0\n\
2737 291\n\
2738  1\n\
2739  45\n\
2740 0.0\n\
2741 1001\n\
2742 ACAD\n\
2743 1000\n\
2744 AcDbSavedByObjectVersion\n\
2745 1070\n\
2746  0\n\
2747  0\n\
2748 VISUALSTYLE\n\
2749  5\n\
2750 2B\n\
2751 102\n\
2752 {ACAD_REACTORS\n\
2753 330\n\
2754 2A\n\
2755 102\n\
2756 }\n\
2757 330\n\
2758 2A\n\
2759 100\n\
2760 AcDbVisualStyle\n\
2761  2\n\
2762 Flat\n\
2763  70\n\
2764  0\n\
2765  71\n\
2766  2\n\
2767  72\n\
2768  1\n\
2769  73\n\
2770  1\n\
2771  90\n\
2772  2\n\
2773  40\n\
2774 -0.6\n\
2775  41\n\
2776 30.0\n\
2777  62\n\
2778  5\n\
2779  63\n\
2780  7\n\
2781 421\n\
2782  16777215\n\
2783  74\n\
2784  0\n\
2785  91\n\
2786  4\n\
2787  64\n\
2788  7\n\
2789  65\n\
2790  257\n\
2791  75\n\
2792  1\n\
2793 175\n\
2794  1\n\
2795  42\n\
2796 1.0\n\
2797  92\n\
2798  8\n\
2799  66\n\
2800  7\n\
2801  43\n\
2802 1.0\n\
2803  76\n\
2804  1\n\
2805  77\n\
2806  6\n\
2807  78\n\
2808  2\n\
2809  67\n\
2810  7\n\
2811  79\n\
2812  5\n\
2813 170\n\
2814  0\n\
2815 171\n\
2816  0\n\
2817 290\n\
2818  0\n\
2819 174\n\
2820  0\n\
2821  93\n\
2822  13\n\
2823  44\n\
2824 0.0\n\
2825 173\n\
2826  0\n\
2827 291\n\
2828  1\n\
2829  45\n\
2830 0.0\n\
2831 1001\n\
2832 ACAD\n\
2833 1000\n\
2834 AcDbSavedByObjectVersion\n\
2835 1070\n\
2836  0\n\
2837  0\n\
2838 VISUALSTYLE\n\
2839  5\n\
2840 2C\n\
2841 102\n\
2842 {ACAD_REACTORS\n\
2843 330\n\
2844 2A\n\
2845 102\n\
2846 }\n\
2847 330\n\
2848 2A\n\
2849 100\n\
2850 AcDbVisualStyle\n\
2851  2\n\
2852 FlatWithEdges\n\
2853  70\n\
2854  1\n\
2855  71\n\
2856  2\n\
2857  72\n\
2858  1\n\
2859  73\n\
2860  1\n\
2861  90\n\
2862  2\n\
2863  40\n\
2864 -0.6\n\
2865  41\n\
2866 30.0\n\
2867  62\n\
2868  5\n\
2869  63\n\
2870  7\n\
2871 421\n\
2872  16777215\n\
2873  74\n\
2874  1\n\
2875  91\n\
2876  4\n\
2877  64\n\
2878  7\n\
2879  65\n\
2880  257\n\
2881  75\n\
2882  1\n\
2883 175\n\
2884  1\n\
2885  42\n\
2886 1.0\n\
2887  92\n\
2888  0\n\
2889  66\n\
2890  257\n\
2891  43\n\
2892 1.0\n\
2893  76\n\
2894  1\n\
2895  77\n\
2896  6\n\
2897  78\n\
2898  2\n\
2899  67\n\
2900  7\n\
2901  79\n\
2902  5\n\
2903 170\n\
2904  0\n\
2905 171\n\
2906  0\n\
2907 290\n\
2908  0\n\
2909 174\n\
2910  0\n\
2911  93\n\
2912  13\n\
2913  44\n\
2914 0.0\n\
2915 173\n\
2916  0\n\
2917 291\n\
2918  1\n\
2919  45\n\
2920 0.0\n\
2921 1001\n\
2922 ACAD\n\
2923 1000\n\
2924 AcDbSavedByObjectVersion\n\
2925 1070\n\
2926  0\n\
2927  0\n\
2928 VISUALSTYLE\n\
2929  5\n\
2930 2D\n\
2931 102\n\
2932 {ACAD_REACTORS\n\
2933 330\n\
2934 2A\n\
2935 102\n\
2936 }\n\
2937 330\n\
2938 2A\n\
2939 100\n\
2940 AcDbVisualStyle\n\
2941  2\n\
2942 Gouraud\n\
2943  70\n\
2944  2\n\
2945  71\n\
2946  2\n\
2947  72\n\
2948  2\n\
2949  73\n\
2950  1\n\
2951  90\n\
2952  2\n\
2953  40\n\
2954 -0.6\n\
2955  41\n\
2956 30.0\n\
2957  62\n\
2958  5\n\
2959  63\n\
2960  7\n\
2961 421\n\
2962  16777215\n\
2963  74\n\
2964  0\n\
2965  91\n\
2966  4\n\
2967  64\n\
2968  7\n\
2969  65\n\
2970  257\n\
2971  75\n\
2972  1\n\
2973 175\n\
2974  1\n\
2975  42\n\
2976 1.0\n\
2977  92\n\
2978  0\n\
2979  66\n\
2980  7\n\
2981  43\n\
2982 1.0\n\
2983  76\n\
2984  1\n\
2985  77\n\
2986  6\n\
2987  78\n\
2988  2\n\
2989  67\n\
2990  7\n\
2991  79\n\
2992  5\n\
2993 170\n\
2994  0\n\
2995 171\n\
2996  0\n\
2997 290\n\
2998  0\n\
2999 174\n\
3000  0\n\
3001  93\n\
3002  13\n\
3003  44\n\
3004 0.0\n\
3005 173\n\
3006  0\n\
3007 291\n\
3008  1\n\
3009  45\n\
3010 0.0\n\
3011 1001\n\
3012 ACAD\n\
3013 1000\n\
3014 AcDbSavedByObjectVersion\n\
3015 1070\n\
3016  0\n\
3017  0\n\
3018 VISUALSTYLE\n\
3019  5\n\
3020 2E\n\
3021 102\n\
3022 {ACAD_REACTORS\n\
3023 330\n\
3024 2A\n\
3025 102\n\
3026 }\n\
3027 330\n\
3028 2A\n\
3029 100\n\
3030 AcDbVisualStyle\n\
3031  2\n\
3032 GouraudWithEdges\n\
3033  70\n\
3034  3\n\
3035  71\n\
3036  2\n\
3037  72\n\
3038  2\n\
3039  73\n\
3040  1\n\
3041  90\n\
3042  2\n\
3043  40\n\
3044 -0.6\n\
3045  41\n\
3046 30.0\n\
3047  62\n\
3048  5\n\
3049  63\n\
3050  7\n\
3051 421\n\
3052  16777215\n\
3053  74\n\
3054  1\n\
3055  91\n\
3056  4\n\
3057  64\n\
3058  7\n\
3059  65\n\
3060  257\n\
3061  75\n\
3062  1\n\
3063 175\n\
3064  1\n\
3065  42\n\
3066 1.0\n\
3067  92\n\
3068  0\n\
3069  66\n\
3070  257\n\
3071  43\n\
3072 1.0\n\
3073  76\n\
3074  1\n\
3075  77\n\
3076  6\n\
3077  78\n\
3078  2\n\
3079  67\n\
3080  7\n\
3081  79\n\
3082  5\n\
3083 170\n\
3084  0\n\
3085 171\n\
3086  0\n\
3087 290\n\
3088  0\n\
3089 174\n\
3090  0\n\
3091  93\n\
3092  13\n\
3093  44\n\
3094 0.0\n\
3095 173\n\
3096  0\n\
3097 291\n\
3098  1\n\
3099  45\n\
3100 0.0\n\
3101 1001\n\
3102 ACAD\n\
3103 1000\n\
3104 AcDbSavedByObjectVersion\n\
3105 1070\n\
3106  0\n\
3107  0\n\
3108 VISUALSTYLE\n\
3109  5\n\
3110 38\n\
3111 102\n\
3112 {ACAD_REACTORS\n\
3113 330\n\
3114 2A\n\
3115 102\n\
3116 }\n\
3117 330\n\
3118 2A\n\
3119 100\n\
3120 AcDbVisualStyle\n\
3121  2\n\
3122 Linepattern\n\
3123  70\n\
3124  14\n\
3125  71\n\
3126  2\n\
3127  72\n\
3128  2\n\
3129  73\n\
3130  0\n\
3131  90\n\
3132  0\n\
3133  40\n\
3134 -0.6\n\
3135  41\n\
3136 -30.0\n\
3137  62\n\
3138  5\n\
3139  63\n\
3140  7\n\
3141 421\n\
3142  16777215\n\
3143  74\n\
3144  1\n\
3145  91\n\
3146  4\n\
3147  64\n\
3148  7\n\
3149  65\n\
3150  257\n\
3151  75\n\
3152  7\n\
3153 175\n\
3154  7\n\
3155  42\n\
3156 1.0\n\
3157  92\n\
3158  8\n\
3159  66\n\
3160  7\n\
3161  43\n\
3162 1.0\n\
3163  76\n\
3164  1\n\
3165  77\n\
3166  6\n\
3167  78\n\
3168  2\n\
3169  67\n\
3170  7\n\
3171  79\n\
3172  5\n\
3173 170\n\
3174  0\n\
3175 171\n\
3176  0\n\
3177 290\n\
3178  0\n\
3179 174\n\
3180  0\n\
3181  93\n\
3182  1\n\
3183  44\n\
3184 0.0\n\
3185 173\n\
3186  0\n\
3187 291\n\
3188  1\n\
3189  45\n\
3190 0.0\n\
3191 1001\n\
3192 ACAD\n\
3193 1000\n\
3194 AcDbSavedByObjectVersion\n\
3195 1070\n\
3196  0\n\
3197  0\n\
3198 VISUALSTYLE\n\
3199  5\n\
3200 33\n\
3201 102\n\
3202 {ACAD_REACTORS\n\
3203 330\n\
3204 2A\n\
3205 102\n\
3206 }\n\
3207 330\n\
3208 2A\n\
3209 100\n\
3210 AcDbVisualStyle\n\
3211  2\n\
3212 Realistic\n\
3213  70\n\
3214  8\n\
3215  71\n\
3216  2\n\
3217  72\n\
3218  2\n\
3219  73\n\
3220  0\n\
3221  90\n\
3222  0\n\
3223  40\n\
3224 -0.6\n\
3225  41\n\
3226 -30.0\n\
3227  62\n\
3228  5\n\
3229  63\n\
3230  7\n\
3231 421\n\
3232  16777215\n\
3233  74\n\
3234  1\n\
3235  91\n\
3236  0\n\
3237  64\n\
3238  7\n\
3239  65\n\
3240  257\n\
3241  75\n\
3242  1\n\
3243 175\n\
3244  1\n\
3245  42\n\
3246 1.0\n\
3247  92\n\
3248  8\n\
3249  66\n\
3250  8\n\
3251 424\n\
3252  7895160\n\
3253  43\n\
3254 1.0\n\
3255  76\n\
3256  1\n\
3257  77\n\
3258  6\n\
3259  78\n\
3260  2\n\
3261  67\n\
3262  7\n\
3263  79\n\
3264  5\n\
3265 170\n\
3266  0\n\
3267 171\n\
3268  0\n\
3269 290\n\
3270  0\n\
3271 174\n\
3272  0\n\
3273  93\n\
3274  13\n\
3275  44\n\
3276 0.0\n\
3277 173\n\
3278  0\n\
3279 291\n\
3280  0\n\
3281  45\n\
3282 0.0\n\
3283 1001\n\
3284 ACAD\n\
3285 1000\n\
3286 AcDbSavedByObjectVersion\n\
3287 1070\n\
3288  0\n\
3289  0\n\
3290 VISUALSTYLE\n\
3291  5\n\
3292 37\n\
3293 102\n\
3294 {ACAD_REACTORS\n\
3295 330\n\
3296 2A\n\
3297 102\n\
3298 }\n\
3299 330\n\
3300 2A\n\
3301 100\n\
3302 AcDbVisualStyle\n\
3303  2\n\
3304 Thicken\n\
3305  70\n\
3306  13\n\
3307  71\n\
3308  2\n\
3309  72\n\
3310  2\n\
3311  73\n\
3312  0\n\
3313  90\n\
3314  0\n\
3315  40\n\
3316 -0.6\n\
3317  41\n\
3318 -30.0\n\
3319  62\n\
3320  5\n\
3321  63\n\
3322  7\n\
3323 421\n\
3324  16777215\n\
3325  74\n\
3326  1\n\
3327  91\n\
3328  4\n\
3329  64\n\
3330  7\n\
3331  65\n\
3332  257\n\
3333  75\n\
3334  1\n\
3335 175\n\
3336  1\n\
3337  42\n\
3338 1.0\n\
3339  92\n\
3340  12\n\
3341  66\n\
3342  7\n\
3343  43\n\
3344 1.0\n\
3345  76\n\
3346  1\n\
3347  77\n\
3348  6\n\
3349  78\n\
3350  2\n\
3351  67\n\
3352  7\n\
3353  79\n\
3354  5\n\
3355 170\n\
3356  0\n\
3357 171\n\
3358  0\n\
3359 290\n\
3360  0\n\
3361 174\n\
3362  0\n\
3363  93\n\
3364  1\n\
3365  44\n\
3366 0.0\n\
3367 173\n\
3368  0\n\
3369 291\n\
3370  1\n\
3371  45\n\
3372 0.0\n\
3373 1001\n\
3374 ACAD\n\
3375 1000\n\
3376 AcDbSavedByObjectVersion\n\
3377 1070\n\
3378  0\n\
3379  0\n\
3380 ENDSEC\n\
3381 ";
3382 
3383  writeGroup( 0, QStringLiteral( "EOF" ) );
3384 }
3385 
3386 void QgsDxfExport::startSection()
3387 {
3388  writeGroup( 0, QStringLiteral( "SECTION" ) );
3389 }
3390 
3391 void QgsDxfExport::endSection()
3392 {
3393  writeGroup( 0, QStringLiteral( "ENDSEC" ) );
3394 }
3395 
3396 void QgsDxfExport::writePoint( const QgsPoint &pt, const QString &layer, const QColor &color, QgsSymbolRenderContext &ctx, const QgsSymbolLayer *symbolLayer, const QgsSymbol *symbol, double angle )
3397 {
3398 #if 0
3399  // debug: draw rectangle for debugging
3400  const QgsMarkerSymbolLayer *msl = dynamic_cast< const QgsMarkerSymbolLayer * >( symbolLayer );
3401  if ( msl )
3402  {
3403  double halfSize = msl->size() * mapUnitScaleFactor( mSymbologyScale,
3404  msl->sizeUnit(), mMapUnits ) / 2.0;
3405  writeGroup( 0, "SOLID" );
3406  writeGroup( 8, layer );
3407  writeGroup( 62, 1 );
3408  writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, pt.x() - halfSize, pt.y() - halfSize ) );
3409  writeGroup( 1, QgsPoint( QgsWkbTypes::PointZ, pt.x() + halfSize, pt.y() - halfSize ) );
3410  writeGroup( 2, QgsPoint( QgsWkbTypes::PointZ, pt.x() - halfSize, pt.y() + halfSize ) );
3411  writeGroup( 3, QgsPoint( QgsWkbTypes::PointZ, pt.x() + halfSize, pt.y() + halfSize ) );
3412  }
3413 #endif // 0
3414 
3415  // insert block or write point directly?
3416  QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
3417  if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() )
3418  {
3419  // write symbol directly here
3420  const QgsMarkerSymbolLayer *msl = dynamic_cast< const QgsMarkerSymbolLayer * >( symbolLayer );
3421  if ( msl && symbol )
3422  {
3423  if ( symbolLayer->writeDxf( *this, mapUnitScaleFactor( mSymbologyScale, msl->sizeUnit(), mMapUnits ), layer, ctx, QPointF( pt.x(), pt.y() ) ) )
3424  {
3425  return;
3426  }
3427  }
3428  writePoint( layer, color, pt ); // write default point symbol
3429  }
3430  else
3431  {
3432  // insert block reference
3433  writeGroup( 0, QStringLiteral( "INSERT" ) );
3434  writeHandle();
3435  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3436  writeGroup( 100, QStringLiteral( "AcDbBlockReference" ) );
3437  writeGroup( 8, layer );
3438  writeGroup( 2, blockIt.value() ); // Block name
3439  writeGroup( 50, angle ); // angle
3440  writeGroup( 0, pt ); // Insertion point (in OCS)
3441  }
3442 }
3443 
3444 void QgsDxfExport::writePolyline( const QgsPointSequence &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width )
3445 {
3446  int n = line.size();
3447  if ( n == 0 )
3448  {
3449  QgsDebugMsg( QString( "writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
3450  return;
3451  }
3452 
3453  bool polygon = line[0] == line[ line.size() - 1 ];
3454  if ( polygon )
3455  --n;
3456  if ( n < 2 )
3457  {
3458  QgsDebugMsg( QString( "writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
3459  return;
3460  }
3461 
3462  if ( mForce2d || !line.at( 0 ).is3D() )
3463  {
3464  writeGroup( 0, QStringLiteral( "LWPOLYLINE" ) );
3465  writeHandle();
3466  writeGroup( 8, layer );
3467  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3468  writeGroup( 100, QStringLiteral( "AcDbPolyline" ) );
3469  writeGroup( 6, lineStyleName );
3470  writeGroup( color );
3471 
3472  writeGroup( 90, n );
3473  writeGroup( 70, polygon ? 1 : 0 );
3474  writeGroup( 43, width );
3475 
3476  for ( int i = 0; i < n; i++ )
3477  writeGroup( 0, line[i] );
3478  }
3479  else
3480  {
3481  writeGroup( 0, QStringLiteral( "POLYLINE" ) );
3482  int plHandle = writeHandle();
3483  writeGroup( 330, mBlockHandle );
3484  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3485  writeGroup( 8, layer );
3486  writeGroup( 6, lineStyleName );
3487  writeGroup( color );
3488  writeGroup( 100, QStringLiteral( "AcDb3dPolyline" ) );
3490  writeGroup( 70, 8 );
3491 
3492  for ( int i = 0; i < n; i++ )
3493  {
3494  writeGroup( 0, QStringLiteral( "VERTEX" ) );
3495  writeHandle();
3496  writeGroup( 330, plHandle );
3497  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3498  writeGroup( 8, layer );
3499  writeGroup( color );
3500  writeGroup( 100, QStringLiteral( "AcDbVertex" ) );
3501  writeGroup( 100, QStringLiteral( "AcDb3dPolylineVertex" ) );
3502  writeGroup( 0, line[i] );
3503  writeGroup( 70, 32 );
3504  }
3505 
3506  writeGroup( 0, QStringLiteral( "SEQEND" ) );
3507  writeHandle();
3508  writeGroup( 330, plHandle );
3509  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3510  writeGroup( 8, layer );
3511  writeGroup( color );
3512  }
3513 }
3514 
3515 void QgsDxfExport::writePolygon( const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color )
3516 {
3517  writeGroup( 0, QStringLiteral( "HATCH" ) ); // Entity type
3518  writeHandle();
3519  writeGroup( 330, mBlockHandle );
3520  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3521  writeGroup( 8, layer ); // Layer name
3522  writeGroup( color ); // Color
3523  writeGroup( 100, QStringLiteral( "AcDbHatch" ) );
3524 
3525  writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ ) ); // Elevation point (in OCS)
3526  writeGroup( 200, QgsPoint( QgsWkbTypes::PointZ, 0.0, 0.0, 1.0 ) );
3527 
3528  writeGroup( 2, hatchPattern ); // Hatch pattern name
3529  writeGroup( 70, hatchPattern == QLatin1String( "SOLID" ) ); // Solid fill flag (solid fill = 1; pattern fill = 0)
3530  writeGroup( 71, 0 ); // Associativity flag (associative = 1; non-associative = 0)
3531 
3532  writeGroup( 91, polygon.size() ); // Number of boundary paths (loops)
3533  for ( int i = 0; i < polygon.size(); ++i )
3534  {
3535  writeGroup( 92, 2 ); // Boundary path type flag (bit coded): 0 = Default; 1 = External; 2 = Polyline 4 = Derived; 8 = Textbox; 16 = Outermost
3536  writeGroup( 72, 0 ); // Has bulge flag
3537  writeGroup( 73, 1 ); // Is closed flag
3538  writeGroup( 93, polygon[i].size() ); // Number of edges in this boundary path (only if boundary is not a polyline
3539 
3540  for ( int j = 0; j < polygon[i].size(); ++j )
3541  {
3542  writeGroup( 0, polygon[i][j] ); // Vertex location (in OCS)
3543  }
3544 
3545  writeGroup( 97, 0 ); // Number of source boundary objects
3546  }
3547 
3548  writeGroup( 75, 0 ); // Hatch style: 0 = Hatch "odd parity" area (Normal style), 1 = Hatch outermost area only (Outer style), 2 = Hatch through entire area (Ignore style)
3549  writeGroup( 76, 1 ); // Hatch pattern type: 0 = User-defined; 1 = Predefined; 2 = Custom
3550 
3551  writeGroup( 98, 0 ); // Number of seed points
3552 }
3553 
3554 void QgsDxfExport::writeLine( const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor &color, double width )
3555 {
3556  writePolyline( QgsPointSequence() << pt1 << pt2, layer, lineStyleName, color, width );
3557 }
3558 
3559 void QgsDxfExport::writePoint( const QString &layer, const QColor &color, const QgsPoint &pt )
3560 {
3561  writeGroup( 0, QStringLiteral( "POINT" ) );
3562  writeHandle();
3563  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3564  writeGroup( 100, QStringLiteral( "AcDbPoint" ) );
3565  writeGroup( 8, layer );
3566  writeGroup( color );
3567  writeGroup( 0, pt );
3568 }
3569 
3570 void QgsDxfExport::writeFilledCircle( const QString &layer, const QColor &color, const QgsPoint &pt, double radius )
3571 {
3572  writeGroup( 0, QStringLiteral( "HATCH" ) ); // Entity type
3573  writeHandle();
3574  writeGroup( 330, mBlockHandle );
3575  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3576  writeGroup( 8, layer ); // Layer name
3577  writeGroup( color ); // Color (0 by block, 256 by layer)
3578  writeGroup( 100, QStringLiteral( "AcDbHatch" ) );
3579 
3580  writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ ) ); // Elevation point (in OCS)
3581  writeGroup( 200, QgsPoint( QgsWkbTypes::PointZ, 0.0, 0.0, 1.0 ) );
3582 
3583  writeGroup( 2, QStringLiteral( "SOLID" ) ); // Hatch pattern name
3584  writeGroup( 70, 1 ); // Solid fill flag (solid fill = 1; pattern fill = 0)
3585  writeGroup( 71, 0 ); // Associativity flag (associative = 1; non-associative = 0)
3586 
3587  writeGroup( 91, 1 ); // Number of boundary paths (loops)
3588 
3589  writeGroup( 92, 3 ); // Boundary path type flag (bit coded): 0 = Default; 1 = External; 2 = Polyline 4 = Derived; 8 = Textbox; 16 = Outermost
3590  writeGroup( 72, 1 );
3591  writeGroup( 73, 1 ); // Is closed flag
3592  writeGroup( 93, 2 ); // Number of polyline vertices
3593 
3594  writeGroup( 0, QgsPoint( QgsWkbTypes::Point, pt.x() - radius, pt.y() ) );
3595  writeGroup( 42, 1.0 );
3596 
3597  writeGroup( 0, QgsPoint( QgsWkbTypes::Point, pt.x() + radius, pt.y() ) );
3598  writeGroup( 42, 1.0 );
3599 
3600  writeGroup( 97, 0 ); // Number of source boundary objects
3601 
3602  writeGroup( 75, 0 ); // Hatch style: 0 = Hatch "odd parity" area (Normal style), 1 = Hatch outermost area only (Outer style), 2 = Hatch through entire area (Ignore style)
3603  writeGroup( 76, 1 ); // Hatch pattern type: 0 = User-defined; 1 = Predefined; 2 = Custom
3604  writeGroup( 98, 0 ); // Number of seed points
3605 }
3606 
3607 void QgsDxfExport::writeCircle( const QString &layer, const QColor &color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width )
3608 {
3609  writeGroup( 0, QStringLiteral( "LWPOLYLINE" ) );
3610  writeHandle();
3611  writeGroup( 330, mBlockHandle );
3612  writeGroup( 8, layer );
3613  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3614  writeGroup( 100, QStringLiteral( "AcDbPolyline" ) );
3615  writeGroup( 6, lineStyleName );
3616  writeGroup( color );
3617 
3618  writeGroup( 90, 2 );
3619 
3620  writeGroup( 70, 1 );
3621  writeGroup( 43, width );
3622 
3623  writeGroup( 0, QgsPoint( pt.x() - radius, pt.y() ) );
3624  writeGroup( 42, 1.0 );
3625  writeGroup( 0, QgsPoint( pt.x() + radius, pt.y() ) );
3626  writeGroup( 42, 1.0 );
3627 }
3628 
3629 void QgsDxfExport::writeText( const QString &layer, const QString &text, const QgsPoint &pt, double size, double angle, const QColor &color )
3630 {
3631  writeGroup( 0, QStringLiteral( "TEXT" ) );
3632  writeHandle();
3633  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3634  writeGroup( 100, QStringLiteral( "AcDbText" ) );
3635  writeGroup( 8, layer );
3636  writeGroup( color );
3637  writeGroup( 0, pt );
3638  writeGroup( 40, size );
3639  writeGroup( 1, text );
3640  writeGroup( 50, angle );
3641  writeGroup( 7, QStringLiteral( "STANDARD" ) ); // so far only support for standard font
3642  writeGroup( 100, QStringLiteral( "AcDbText" ) );
3643 }
3644 
3645 void QgsDxfExport::writeMText( const QString &layer, const QString &text, const QgsPoint &pt, double width, double angle, const QColor &color )
3646 {
3647  if ( !mTextStream.codec()->canEncode( text ) )
3648  {
3649  // TODO return error
3650  QgsDebugMsg( QString( "could not encode:%1" ).arg( text ) );
3651  return;
3652  }
3653 
3654  writeGroup( 0, QStringLiteral( "MTEXT" ) );
3655  writeHandle();
3656  writeGroup( 100, QStringLiteral( "AcDbEntity" ) );
3657  writeGroup( 100, QStringLiteral( "AcDbMText" ) );
3658  writeGroup( 8, layer );
3659  writeGroup( color );
3660 
3661  writeGroup( 0, pt );
3662 
3663  QString t( text );
3664  while ( t.length() > 250 )
3665  {
3666  writeGroup( 3, t.left( 250 ) );
3667  t = t.mid( 250 );
3668  }
3669  writeGroup( 1, t );
3670 
3671  writeGroup( 50, angle ); // Rotation angle in radians
3672  writeGroup( 41, width * 1.1 ); // Reference rectangle width
3673 
3674  // Attachment point:
3675  // 1 2 3
3676  // 4 5 6
3677  // 7 8 9
3678  writeGroup( 71, 7 );
3679 
3680  writeGroup( 7, QStringLiteral( "STANDARD" ) ); // so far only support for standard font
3681 }
3682 
3683 void QgsDxfExport::addFeature( QgsSymbolRenderContext &ctx, const QgsCoordinateTransform &ct, const QString &layer, const QgsSymbolLayer *symbolLayer, const QgsSymbol *symbol )
3684 {
3685  const QgsFeature *fet = ctx.feature();
3686  if ( !fet )
3687  return;
3688 
3689  if ( !fet->hasGeometry() )
3690  return;
3691 
3692  std::unique_ptr<QgsAbstractGeometry> geom( fet->geometry().constGet()->clone() );
3693  if ( ct.isValid() )
3694  {
3695  geom->transform( ct );
3696  }
3697 
3698  QgsWkbTypes::Type geometryType = geom->wkbType();
3699 
3700  QColor penColor;
3701  QColor brushColor;
3702  if ( mSymbologyExport != NoSymbology && symbolLayer )
3703  {
3704  penColor = colorFromSymbolLayer( symbolLayer, ctx );
3705  brushColor = symbolLayer->dxfBrushColor( ctx );
3706  }
3707 
3708  Qt::PenStyle penStyle( Qt::SolidLine );
3709  Qt::BrushStyle brushStyle( Qt::NoBrush );
3710  double width = -1;
3711  double offset = 0.0;
3712  double angle = 0.0;
3713  if ( mSymbologyExport != NoSymbology && symbolLayer )
3714  {
3715  width = symbolLayer->dxfWidth( *this, ctx );
3716  offset = symbolLayer->dxfOffset( *this, ctx );
3717  angle = symbolLayer->dxfAngle( ctx );
3718  penStyle = symbolLayer->dxfPenStyle();
3719  brushStyle = symbolLayer->dxfBrushStyle();
3720 
3721  if ( qgsDoubleNear( offset, 0.0 ) )
3722  offset = 0.0;
3723  }
3724 
3725  QString lineStyleName = QStringLiteral( "CONTINUOUS" );
3726  if ( mSymbologyExport != NoSymbology )
3727  {
3728  lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
3729  }
3730 
3731  // single point
3732  if ( QgsWkbTypes::flatType( geometryType ) == QgsWkbTypes::Point )
3733  {
3734  writePoint( geom->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
3735  return;
3736  }
3737 
3738  if ( QgsWkbTypes::flatType( geometryType ) == QgsWkbTypes::MultiPoint )
3739  {
3740  const QgsCoordinateSequence &cs = geom->coordinateSequence();
3741  for ( int i = 0; i < cs.size(); i++ )
3742  {
3743  writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
3744  }
3745  return;
3746  }
3747 
3748  if ( penStyle != Qt::NoPen )
3749  {
3750  const QgsAbstractGeometry *tempGeom = geom.get();
3751 
3752  switch ( QgsWkbTypes::flatType( geometryType ) )
3753  {
3756  tempGeom = geom->segmentize();
3757  if ( !tempGeom )
3758  break;
3759  FALLTHROUGH;
3761  if ( !qgsDoubleNear( offset, 0.0 ) )
3762  {
3763  QgsGeos geos( tempGeom );
3764  if ( tempGeom != geom.get() )
3765  delete tempGeom;
3766  tempGeom = geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 ); //#spellok
3767  if ( !tempGeom )
3768  tempGeom = geom.get();
3769  }
3770 
3771  writePolyline( tempGeom->coordinateSequence().at( 0 ).at( 0 ), layer, lineStyleName, penColor, width );
3772 
3773  break;
3774 
3776  tempGeom = geom->segmentize();
3777  if ( !tempGeom )
3778  break;
3779  FALLTHROUGH;
3781  {
3782  if ( !qgsDoubleNear( offset, 0.0 ) )
3783  {
3784  QgsGeos geos( tempGeom );
3785  if ( tempGeom != geom.get() )
3786  delete tempGeom;
3787  tempGeom = geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 ); //#spellok
3788  if ( !tempGeom )
3789  tempGeom = geom.get();
3790  }
3791 
3792  const QgsCoordinateSequence &cs = tempGeom->coordinateSequence();
3793  for ( int i = 0; i < cs.size(); i++ )
3794  {
3795  writePolyline( cs.at( i ).at( 0 ), layer, lineStyleName, penColor, width );
3796  }
3797 
3798  break;
3799  }
3800 
3802  tempGeom = geom->segmentize();
3803  if ( !tempGeom )
3804  break;
3805  FALLTHROUGH;
3806  case QgsWkbTypes::Polygon:
3807  {
3808  if ( !qgsDoubleNear( offset, 0.0 ) )
3809  {
3810  QgsGeos geos( tempGeom );
3811  if ( tempGeom != geom.get() )
3812  delete tempGeom;
3813  tempGeom = geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 ); //#spellok
3814  if ( !tempGeom )
3815  tempGeom = geom.get();
3816  }
3817 
3818  const QgsCoordinateSequence &cs = tempGeom->coordinateSequence();
3819  for ( int i = 0; i < cs.at( 0 ).size(); i++ )
3820  {
3821  writePolyline( cs.at( 0 ).at( i ), layer, lineStyleName, penColor, width );
3822  }
3823 
3824  break;
3825  }
3826 
3828  {
3829  if ( !qgsDoubleNear( offset, 0.0 ) )
3830  {
3831  QgsGeos geos( tempGeom );
3832  if ( tempGeom != geom.get() )
3833  delete tempGeom;
3834  tempGeom = geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 ); //#spellok
3835  if ( !tempGeom )
3836  tempGeom = geom.get();
3837  }
3838 
3839  const QgsCoordinateSequence &cs = tempGeom->coordinateSequence();
3840  for ( int i = 0; i < cs.size(); i++ )
3841  for ( int j = 0; j < cs.at( i ).size(); j++ )
3842  writePolyline( cs.at( i ).at( j ), layer, lineStyleName, penColor, width );
3843 
3844  break;
3845  }
3846 
3847  default:
3848  break;
3849  }
3850 
3851  if ( tempGeom != geom.get() )
3852  delete tempGeom;
3853  }
3854 
3855  if ( brushStyle != Qt::NoBrush )
3856  {
3857  const QgsAbstractGeometry *tempGeom = geom.get();
3858 
3859  switch ( QgsWkbTypes::flatType( geometryType ) )
3860  {
3862  tempGeom = tempGeom->segmentize();
3863  if ( !tempGeom )
3864  break;
3865  FALLTHROUGH;
3866  case QgsWkbTypes::Polygon:
3867  writePolygon( tempGeom->coordinateSequence().at( 0 ), layer, QStringLiteral( "SOLID" ), brushColor );
3868  break;
3869 
3871  {
3872  const QgsCoordinateSequence &cs = geom->coordinateSequence();
3873  for ( int i = 0; i < cs.size(); i++ )
3874  {
3875  writePolygon( cs.at( i ), layer, QStringLiteral( "SOLID" ), brushColor );
3876  }
3877  break;
3878  }
3879 
3880  default:
3881  break;
3882 
3883  }
3884 
3885  if ( tempGeom != geom.get() )
3886  delete tempGeom;
3887  }
3888 }
3889 
3890 QColor QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayer *symbolLayer, QgsSymbolRenderContext &ctx )
3891 {
3892  if ( !symbolLayer )
3893  return QColor();
3894 
3895  return symbolLayer->dxfColor( ctx );
3896 }
3897 
3898 QString QgsDxfExport::lineStyleFromSymbolLayer( const QgsSymbolLayer *symbolLayer )
3899 {
3900  QString lineStyleName = QStringLiteral( "CONTINUOUS" );
3901  if ( !symbolLayer )
3902  {
3903  return lineStyleName;
3904  }
3905 
3906  QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
3907  if ( lineTypeIt != mLineStyles.constEnd() )
3908  {
3909  lineStyleName = lineTypeIt.value();
3910  return lineStyleName;
3911  }
3912  else
3913  {
3914  return lineNameFromPenStyle( symbolLayer->dxfPenStyle() );
3915  }
3916 }
3917 
3919 {
3920  int idx = 0;
3921  int current_distance = INT_MAX;
3922  for ( int i = 1; i < static_cast< int >( sizeof( sDxfColors ) / sizeof( *sDxfColors ) ); ++i )
3923  {
3924  int dist = color_distance( pixel, i );
3925  if ( dist < current_distance )
3926  {
3927  current_distance = dist;
3928  idx = i;
3929  if ( dist == 0 )
3930  break;
3931  }
3932  }
3933  return idx;
3934 }
3935 
3936 int QgsDxfExport::color_distance( QRgb p1, int index )
3937 {
3938  if ( index > 255 || index < 0 )
3939  {
3940  return 0;
3941  }
3942 
3943  double redDiff = qRed( p1 ) - sDxfColors[index][0];
3944  double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
3945  double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
3946 #if 0
3947  QgsDebugMsg( QString( "color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8" )
3948  .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
3949  .arg( index )
3950  .arg( mDxfColors[index][0] )
3951  .arg( mDxfColors[index][1] )
3952  .arg( mDxfColors[index][2] )
3953  .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ) );
3954 #endif
3955  return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
3956 }
3957 
3958 QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
3959 {
3960  return QColor::fromRgbF( r, g, b ).rgb();
3961 }
3962 
3963 QgsRenderContext QgsDxfExport::renderContext() const
3964 {
3965  QgsRenderContext context;
3966  context.setRendererScale( mSymbologyScale );
3967  return context;
3968 }
3969 
3971 {
3972  if ( symbolUnits == QgsUnitTypes::RenderMapUnits )
3973  {
3974  return 1.0;
3975  }
3976  // MM symbol unit
3977  return scale * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, mapUnits ) / 1000.0;
3978 }
3979 
3980 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers( QgsRenderContext &context )
3981 {
3982  QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
3983 
3984  const QList< QgsMapLayer * > layers = mMapSettings.layers();
3985  for ( QgsMapLayer *ml : layers )
3986  {
3987  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
3988  if ( !vl )
3989  {
3990  continue;
3991  }
3992 
3993  // get renderer
3994  QgsFeatureRenderer *r = vl->renderer();
3995  if ( !r )
3996  {
3997  continue;
3998  }
3999 
4000  // get all symbols
4001  QgsSymbolList symbols = r->symbols( context );
4002  QgsSymbolList::iterator symbolIt = symbols.begin();
4003  for ( ; symbolIt != symbols.end(); ++symbolIt )
4004  {
4005  int maxSymbolLayers = ( *symbolIt )->symbolLayerCount();
4006  if ( mSymbologyExport != SymbolLayerSymbology )
4007  {
4008  maxSymbolLayers = 1;
4009  }
4010  for ( int i = 0; i < maxSymbolLayers; ++i )
4011  {
4012  symbolLayers.append( qMakePair( ( *symbolIt )->symbolLayer( i ), *symbolIt ) );
4013  }
4014  }
4015  }
4016 
4017  return symbolLayers;
4018 }
4019 
4020 void QgsDxfExport::writeDefaultLinetypes()
4021 {
4022  // continuous (Qt solid line)
4023  const QStringList blockStrings = QStringList() << QStringLiteral( "ByLayer" ) << QStringLiteral( "ByBlock" ) << QStringLiteral( "CONTINUOUS" );
4024  for ( const QString &ltype : blockStrings )
4025  {
4026  writeGroup( 0, QStringLiteral( "LTYPE" ) );
4027  writeHandle();
4028  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
4029  writeGroup( 100, QStringLiteral( "AcDbLinetypeTableRecord" ) );
4030  writeGroup( 2, ltype );
4031  writeGroup( 70, 64 );
4032  writeGroup( 3, QStringLiteral( "Defaultstyle" ) );
4033  writeGroup( 72, 65 );
4034  writeGroup( 73, 0 );
4035  writeGroup( 40, 0.0 );
4036  }
4037 
4038  double das = dashSize();
4039  double dss = dashSeparatorSize();
4040  double dos = dotSize();
4041 
4042  QVector<qreal> dashVector( 2 );
4043  dashVector[0] = das;
4044  dashVector[1] = dss;
4045  writeLinetype( QStringLiteral( "DASH" ), dashVector, QgsUnitTypes::RenderMapUnits );
4046 
4047  QVector<qreal> dotVector( 2 );
4048  dotVector[0] = dos;
4049  dotVector[1] = dss;
4050  writeLinetype( QStringLiteral( "DOT" ), dotVector, QgsUnitTypes::RenderMapUnits );
4051 
4052  QVector<qreal> dashDotVector( 4 );
4053  dashDotVector[0] = das;
4054  dashDotVector[1] = dss;
4055  dashDotVector[2] = dos;
4056  dashDotVector[3] = dss;
4057  writeLinetype( QStringLiteral( "DASHDOT" ), dashDotVector, QgsUnitTypes::RenderMapUnits );
4058 
4059  QVector<qreal> dashDotDotVector( 6 );
4060  dashDotDotVector[0] = das;
4061  dashDotDotVector[1] = dss;
4062  dashDotDotVector[2] = dos;
4063  dashDotDotVector[3] = dss;
4064  dashDotDotVector[4] = dos;
4065  dashDotDotVector[5] = dss;
4066  writeLinetype( QStringLiteral( "DASHDOTDOT" ), dashDotDotVector, QgsUnitTypes::RenderMapUnits );
4067 }
4068 
4069 void QgsDxfExport::writeSymbolLayerLinetype( const QgsSymbolLayer *symbolLayer )
4070 {
4071  if ( !symbolLayer )
4072  {
4073  return;
4074  }
4075 
4077  QVector<qreal> customLinestyle = symbolLayer->dxfCustomDashPattern( unit );
4078  if ( !customLinestyle.isEmpty() )
4079  {
4080  QString name = QStringLiteral( "symbolLayer%1" ).arg( mSymbolLayerCounter++ );
4081  writeLinetype( name, customLinestyle, unit );
4082  mLineStyles.insert( symbolLayer, name );
4083  }
4084 }
4085 
4086 int QgsDxfExport::nLineTypes( const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
4087 {
4088  int nLineTypes = 0;
4089  QList< QPair< QgsSymbolLayer *, QgsSymbol *> >::const_iterator slIt = symbolLayers.constBegin();
4090  for ( ; slIt != symbolLayers.constEnd(); ++slIt )
4091  {
4092  const QgsSimpleLineSymbolLayer *simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayer * >( slIt->first );
4093  if ( simpleLine )
4094  {
4095  if ( simpleLine->useCustomDashPattern() )
4096  {
4097  ++nLineTypes;
4098  }
4099  }
4100  }
4101  return nLineTypes;
4102 }
4103 
4104 void QgsDxfExport::writeLinetype( const QString &styleName, const QVector<qreal> &pattern, QgsUnitTypes::RenderUnit u )
4105 {
4106  double length = 0;
4107  QVector<qreal>::const_iterator dashIt = pattern.constBegin();
4108  for ( ; dashIt != pattern.constEnd(); ++dashIt )
4109  {
4110  length += ( *dashIt * mapUnitScaleFactor( mSymbologyScale, u, mMapUnits ) );
4111  }
4112 
4113  writeGroup( 0, QStringLiteral( "LTYPE" ) );
4114  writeHandle();
4115  // 330 5
4116  writeGroup( 100, QStringLiteral( "AcDbSymbolTableRecord" ) );
4117  writeGroup( 100, QStringLiteral( "AcDbLinetypeTableRecord" ) );
4118  writeGroup( 2, styleName );
4119  writeGroup( 70, 64 ); // 0?
4120  writeGroup( 3, QLatin1String( "" ) );
4121  writeGroup( 72, 65 );
4122  writeGroup( 73, pattern.size() );
4123  writeGroup( 40, length );
4124 
4125  dashIt = pattern.constBegin();
4126  bool isGap = false;
4127  for ( ; dashIt != pattern.constEnd(); ++dashIt )
4128  {
4129  // map units or mm?
4130  double segmentLength = ( isGap ? -*dashIt : *dashIt );
4131  segmentLength *= mapUnitScaleFactor( mSymbologyScale, u, mMapUnits );
4132  writeGroup( 49, segmentLength );
4133  writeGroup( 74, 0 );
4134  isGap = !isGap;
4135  }
4136 }
4137 
4138 bool QgsDxfExport::hasDataDefinedProperties( const QgsSymbolLayer *sl, const QgsSymbol *symbol )
4139 {
4140  if ( !sl || !symbol )
4141  {
4142  return false;
4143  }
4144 
4145  if ( symbol->renderHints() & QgsSymbol::DynamicRotation )
4146  {
4147  return true;
4148  }
4149 
4151 }
4152 
4153 double QgsDxfExport::dashSize() const
4154 {
4155  double size = mSymbologyScale * 0.002;
4156  return sizeToMapUnits( size );
4157 }
4158 
4159 double QgsDxfExport::dotSize() const
4160 {
4161  double size = mSymbologyScale * 0.0006;
4162  return sizeToMapUnits( size );
4163 }
4164 
4165 double QgsDxfExport::dashSeparatorSize() const
4166 {
4167  double size = mSymbologyScale * 0.0006;
4168  return sizeToMapUnits( size );
4169 }
4170 
4171 double QgsDxfExport::sizeToMapUnits( double s ) const
4172 {
4173  double size = s * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, mMapUnits );
4174  return size;
4175 }
4176 
4177 QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
4178 {
4179  switch ( style )
4180  {
4181  case Qt::DashLine:
4182  return QStringLiteral( "DASH" );
4183  case Qt::DotLine:
4184  return QStringLiteral( "DOT" );
4185  case Qt::DashDotLine:
4186  return QStringLiteral( "DASHDOT" );
4187  case Qt::DashDotDotLine:
4188  return QStringLiteral( "DASHDOTDOT" );
4189  case Qt::SolidLine:
4190  default:
4191  return QStringLiteral( "CONTINUOUS" );
4192  }
4193 }
4194 
4195 QString QgsDxfExport::dxfLayerName( const QString &name )
4196 {
4197  if ( name.isEmpty() )
4198  return QStringLiteral( "0" );
4199 
4200  // dxf layers can be max 255 characters long
4201  QString layerName = name.left( 255 );
4202 
4203  // replaced restricted characters with underscore
4204  // < > / \ " : ; ? * | = '
4205  // See http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%202010%20User%20Documentation/index.html?url=WS1a9193826455f5ffa23ce210c4a30acaf-7345.htm,topicNumber=d0e41665
4206  layerName.replace( '<', '_' );
4207  layerName.replace( '>', '_' );
4208  layerName.replace( '/', '_' );
4209  layerName.replace( '\\', '_' );
4210  layerName.replace( '\"', '_' );
4211  layerName.replace( ':', '_' );
4212  layerName.replace( ';', '_' );
4213  layerName.replace( '?', '_' );
4214  layerName.replace( '*', '_' );
4215  layerName.replace( '|', '_' );
4216  layerName.replace( '=', '_' );
4217  layerName.replace( '\'', '_' );
4218 
4219  // also remove newline characters (#15067)
4220  layerName.replace( QLatin1String( "\r\n" ), QLatin1String( "_" ) );
4221  layerName.replace( '\r', '_' );
4222  layerName.replace( '\n', '_' );
4223 
4224  return layerName.trimmed();
4225 }
4226 
4227 bool QgsDxfExport::layerIsScaleBasedVisible( const QgsMapLayer *layer ) const
4228 {
4229  if ( !layer )
4230  return false;
4231 
4232  if ( mSymbologyExport == QgsDxfExport::NoSymbology )
4233  return true;
4234 
4235  return layer->isInScaleRange( mSymbologyScale );
4236 }
4237 
4238 QString QgsDxfExport::layerName( const QString &id, const QgsFeature &f ) const
4239 {
4240  const QList< QgsMapLayer * > layers = mMapSettings.layers();
4241  for ( QgsMapLayer *ml : layers )
4242  {
4243  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
4244  if ( vl && vl->id() == id )
4245  {
4246  int attrIdx = mLayerNameAttribute.value( vl->id(), -1 );
4247  return dxfLayerName( attrIdx < 0 ? layerName( vl ) : f.attribute( attrIdx ).toString() );
4248  }
4249  }
4250 
4251  return QStringLiteral( "0" );
4252 }
4253 
4254 QString QgsDxfExport::dxfEncoding( const QString &name )
4255 {
4256  const QList< QByteArray > codecs = QTextCodec::availableCodecs();
4257  for ( const QByteArray &codec : codecs )
4258  {
4259  if ( name != codec )
4260  continue;
4261 
4262  int i;
4263  for ( i = 0; i < static_cast< int >( sizeof( DXF_ENCODINGS ) / sizeof( *DXF_ENCODINGS ) ) && name != DXF_ENCODINGS[i][1]; ++i )
4264  ;
4265 
4266  if ( i == static_cast< int >( sizeof( DXF_ENCODINGS ) / sizeof( *DXF_ENCODINGS ) ) )
4267  continue;
4268 
4269  return DXF_ENCODINGS[i][0];
4270  }
4271 
4272  return QString();
4273 }
4274 
4276 {
4277  QStringList encodings;
4278  const QList< QByteArray > codecs = QTextCodec::availableCodecs();
4279  for ( const QByteArray &codec : codecs )
4280  {
4281  int i;
4282  for ( i = 0; i < static_cast< int >( sizeof( DXF_ENCODINGS ) / sizeof( *DXF_ENCODINGS ) ) && strcmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
4283  ;
4284 
4285  if ( i < static_cast< int >( sizeof( DXF_ENCODINGS ) / sizeof( *DXF_ENCODINGS ) ) )
4286  encodings << codec.data();
4287  }
4288  return encodings;
4289 }
4290 
4292 {
4293  Q_ASSERT( vl );
4294  return mLayerTitleAsName && !vl->title().isEmpty() ? vl->title() : vl->name();
4295 }
4296 
4297 void QgsDxfExport::drawLabel( const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings )
4298 {
4299  Q_UNUSED( context );
4300 
4301  if ( !settings.drawLabels )
4302  return;
4303 
4304  QgsTextLabelFeature *lf = dynamic_cast<QgsTextLabelFeature *>( label->getFeaturePart()->feature() );
4305 
4306  // Copy to temp, editable layer settings
4307  // these settings will be changed by any data defined values, then used for rendering label components
4308  // settings may be adjusted during rendering of components
4309  QgsPalLayerSettings tmpLyr( settings );
4310 
4311  // apply any previously applied data defined settings for the label
4312  const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->dataDefinedValues();
4313 
4314  //font
4315  QFont dFont = lf->definedFont();
4316  QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
4317  QgsDebugMsgLevel( QString( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
4318 
4319  QgsTextFormat format = tmpLyr.format();
4320  format.setFont( dFont );
4321  tmpLyr.setFormat( format );
4322 
4324  {
4325  //calculate font alignment based on label quadrant
4326  switch ( label->getQuadrant() )
4327  {
4332  break;
4337  break;
4342  break;
4343  }
4344  }
4345 
4346  // update tmpLyr with any data defined text style values
4347  QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
4348 
4349  // update tmpLyr with any data defined text buffer values
4350  QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
4351 
4352  // update tmpLyr with any data defined text formatting values
4353  QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
4354 
4355  // add to the results
4356  QString txt = label->getFeaturePart()->feature()->labelText();
4357 
4358  QgsFeatureId fid = label->getFeaturePart()->featureId();
4359  QString dxfLayer = mDxfLayerNames[layerId][fid];
4360 
4361  QString wrapchr = tmpLyr.wrapChar.isEmpty() ? QStringLiteral( "\n" ) : tmpLyr.wrapChar;
4362 
4363  //add the direction symbol if needed
4364  if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line && tmpLyr.addDirectionSymbol )
4365  {
4366  bool prependSymb = false;
4367  QString symb = tmpLyr.rightDirectionSymbol;
4368 
4369  if ( label->getReversed() )
4370  {
4371  prependSymb = true;
4372  symb = tmpLyr.leftDirectionSymbol;
4373  }
4374 
4375  if ( tmpLyr.reverseDirectionSymbol )
4376  {
4377  if ( symb == tmpLyr.rightDirectionSymbol )
4378  {
4379  prependSymb = true;
4380  symb = tmpLyr.leftDirectionSymbol;
4381  }
4382  else
4383  {
4384  prependSymb = false;
4385  symb = tmpLyr.rightDirectionSymbol;
4386  }
4387  }
4388 
4390  {
4391  prependSymb = true;
4392  symb = symb + wrapchr;
4393  }
4395  {
4396  prependSymb = false;
4397  symb = wrapchr + symb;
4398  }
4399 
4400  if ( prependSymb )
4401  {
4402  txt.prepend( symb );
4403  }
4404  else
4405  {
4406  txt.append( symb );
4407  }
4408  }
4409 
4410  if ( mFlags & FlagNoMText )
4411  {
4412  writeText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getHeight(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() );
4413  }
4414  else
4415  {
4416  txt = txt.replace( wrapchr, QLatin1String( "\\P" ) );
4417  txt.replace( " ", "\\~" );
4418 
4419  if ( tmpLyr.format().font().underline() )
4420  {
4421  txt.prepend( "\\L" ).append( "\\l" );
4422  }
4423 
4424  if ( tmpLyr.format().font().overline() )
4425  {
4426  txt.prepend( "\\O" ).append( "\\o" );
4427  }
4428 
4429  if ( tmpLyr.format().font().strikeOut() )
4430  {
4431  txt.prepend( "\\K" ).append( "\\k" );
4432  }
4433 
4434  txt.prepend( QStringLiteral( "\\f%1|i%2|b%3;\\H%4;" )
4435  .arg( tmpLyr.format().font().family() )
4436  .arg( tmpLyr.format().font().italic() ? 1 : 0 )
4437  .arg( tmpLyr.format().font().bold() ? 1 : 0 )
4438  .arg( label->getHeight() / ( 1 + txt.count( QStringLiteral( "\\P" ) ) ) * 0.75 ) );
4439  writeMText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getWidth(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() );
4440  }
4441 }
4442 
4443 
4444 void QgsDxfExport::registerDxfLayer( const QString &layerId, QgsFeatureId fid, const QString &layerName )
4445 {
4446  if ( !mDxfLayerNames.contains( layerId ) )
4447  mDxfLayerNames[ layerId ] = QMap<QgsFeatureId, QString>();
4448 
4449  mDxfLayerNames[layerId][fid] = layerName;
4450 }
4451 
4453 {
4454  mCrs = crs;
4455  mMapUnits = crs.mapUnits();
4456 }
4457 
4459 {
4460  return mCrs;
4461 }
bool restoreOverrideStyle()
Restore the original store after a call to setOverrideStyle()
Export only data.
Definition: qgsdxfexport.h:82
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
QgsDxfExport()=default
Constructor for QgsDxfExport.
virtual QVector< qreal > dxfCustomDashPattern(QgsUnitTypes::RenderUnit &unit) const
get dash pattern
Wrapper for iterator of features from vector data provider or vector layer.
QString labelText() const
Text of the label.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
A rectangle specified with double values.
Definition: qgsrectangle.h:39
Base class for all map layer types.
Definition: qgsmaplayer.h:56
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
double y
Definition: qgspoint.h:42
QString leftDirectionSymbol
String to use for left direction arrows.
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Write line (as a polyline)
void addProvider(QgsAbstractLabelProvider *provider)
Add provider of label features. Takes ownership of the provider.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
Definition: feature.cpp:151
QString name
Definition: qgsfield.h:57
void removeProvider(QgsAbstractLabelProvider *provider)
Remove provider if the provider&#39;s initialization failed. Provider instance is deleted.
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:118
virtual double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
get offset
void writeGroup(int code, int i)
Write a tuple of group code and integer value.
void writePolyline(const QgsPointSequence &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
Place direction symbols on below label.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfields.cpp:135
QVector< QgsRingSequence > QgsCoordinateSequence
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
static double mapUnitScaleFactor(double scale, QgsUnitTypes::RenderUnit symbolUnits, QgsUnitTypes::DistanceUnit mapUnits)
Calculates a scaling factor to convert from map units to a specified symbol unit. ...
Export text as TEXT elements. If not set, text will be exported as MTEXT elements.
Definition: qgsdxfexport.h:90
double getY(int i=0) const
get the down-left y coordinate
double y
Definition: qgspointxy.h:48
void startRender(QgsSymbolRenderContext &context) override
Implements a derived label provider for rule based labels internally used for DXF export...
void setRendererScale(double scale)
Sets the renderer map scale.
void setFont(const QFont &font)
Sets the font used for rendering text.
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > & dataDefinedValues() const
Get data-defined values.
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1461
void setOutputDpi(double dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
void registerDxfLayer(const QString &layerId, QgsFeatureId fid, const QString &layer)
Register name of layer for feature.
static int closestColorMatch(QRgb color)
Get DXF palette index of nearest entry for given color.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QColor color() const
Returns the color that text will be rendered in.
Class that adds extra information to QgsLabelFeature for text labels.
static QStringList encodings()
return list of available DXF encodings
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
bool addDirectionSymbol
If true, &#39;<&#39; or &#39;>&#39; (or custom strings set via leftDirectionSymbol and rightDirectionSymbol) will be ...
void setMapSettings(const QgsMapSettings &mapSettings)
Associate map settings instance.
void registerDxfFeature(QgsFeature &feature, QgsRenderContext &context, const QString &dxfLayerName)
Registration method that keeps track of DXF layer names of individual features.
QgsDxfExport::Flags flags() const
Returns the export flags.
bool drawLabels
Whether to draw labels for this layer.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const override
Calculates a list of unique values contained within an attribute in the layer.
int symbolLayerCount() const
Returns total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:143
MultiLineAlign multilineAlign
Horizontal alignment of multi-line labels.
QgsUnitTypes::DistanceUnit mapUnits() const
Retrieve map units.
virtual double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
get line width
FeaturePart * getFeaturePart()
return the feature corresponding to this labelposition
QList< QgsMapLayer * > layers() const
Get list of layers for map rendering The layers are stored in the reverse order of how they are rende...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
void setExtent(const QgsRectangle &extent)
Rotation of symbol may be changed during rendering and symbol should not be cached.
Definition: qgssymbol.h:104
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:251
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
bool reverseDirectionSymbol
True if direction symbols should be reversed.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
void setFlags(QgsDxfExport::Flags flags)
Sets the export flags.
void writeInt(int i)
Write an integer value.
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
void writePolygon(const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH)
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:145
QList< QgsSymbolLevel > QgsSymbolLevelOrder
Definition: qgsrenderer.h:77
The QgsMapSettings class contains configuration for rendering of the map.
QgsMapLayerStyleManager * styleManager() const
Get access to the layer&#39;s style manager.
void setMapSettings(const QgsMapSettings &settings)
Set map settings and assign layer name attributes.
void writeString(const QString &s)
Write a string value.
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Return coordinate transform from layer&#39;s CRS to destination CRS.
void reinit(QgsVectorLayer *layer)
Reinitialize the subproviders with QgsDxfLabelProviders.
int writeToFile(QIODevice *d, const QString &codec)
Export to a dxf file in the given encoding.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:36
void writePoint(const QString &layer, const QColor &color, const QgsPoint &pt)
Write point.
int renderingPass() const
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:43
void setOutputSize(QSize size)
Set the size of the resulting map image.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
bool prepare(const QgsRenderContext &context, QSet< QString > &attributeNames) override
Prepare for registration of features.
virtual bool prepare(const QgsRenderContext &context, QSet< QString > &attributeNames)
Prepare for registration of features.
#define FALLTHROUGH
Definition: qgis.h:548
QgsFields fields() const override
Returns the list of fields of this layer.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Set destination CRS.
virtual QgsPalLayerSettings settings(const QString &providerId=QString()) const =0
Get associated label settings.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsRectangle extent() const override
Returns the extent of the layer.
bool isEmpty() const
Returns true if the rectangle is empty.
double getHeight() const
double size() const
Returns the symbol size.
void writeGroupCode(int code)
Write a group code.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:142
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:237
QgsWkbTypes::Type wkbType() const override
Returns the WKBType or WKBUnknown in case of error.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer&#39;s property collection, used for data defined overrides...
virtual Qt::BrushStyle dxfBrushStyle() const
get brush/fill style
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Quadrant getQuadrant() const
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
QgsFeatureRenderer * renderer()
Return renderer.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
Abstract base class for all geometries.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
Does vector analysis using the geos library and handles import, export, exception handling*...
Definition: qgsgeos.h:98
void writeText(const QString &layer, const QString &text, const QgsPoint &pt, double size, double angle, const QColor &color)
Write text (TEXT)
QgsSymbolLayer * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
Definition: qgssymbol.cpp:323
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination CRS, or an invalid CRS if no reprojection will be done.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
static QString dxfEncoding(const QString &name)
return DXF encoding for Qt encoding
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc...
double x
Definition: qgspointxy.h:47
QString layerName(const QString &id, const QgsFeature &f) const
Get layer name for feature.
virtual QColor dxfBrushColor(QgsSymbolRenderContext &context) const
get brush/fill color
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:201
Contains geos related utilities and functions.
Definition: qgsgeos.h:36
Place direction symbols on above label.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
void drawLabel(const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings)
Output the label.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
Definition: qgsrenderer.h:239
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:130
QgsExpressionContext & expressionContext()
Gets the expression context.
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:43
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:115
QVector< QgsPoint > QgsPointSequence
void setFeature(const QgsFeature *f)
Definition: qgssymbol.h:499
void combineExtentWith(const QgsRectangle &rect)
Expand the rectangle so that covers both the original rectangle and the given rectangle.
QString wrapChar
Wrapping character string.
virtual Qt::PenStyle dxfPenStyle() const
get pen style
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
static QString dxfLayerName(const QString &name)
Return cleaned layer name for use in DXF.
virtual QgsSymbolList symbols(QgsRenderContext &context)
Returns list of symbols used by the renderer.
Definition: qgsrenderer.h:266
QVector< QgsPointSequence > QgsRingSequence
QgsAbstractGeometry * offsetCurve(double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1863
QString rightDirectionSymbol
String to use for right direction arrows.
The QgsLabelingEngine class provides map labeling functionality.
void run(QgsRenderContext &context)
compute the labeling with given map settings and providers
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point...
Contains information about the context of a rendering operation.
Abstract base class for marker symbol layers.
void writeCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width)
Write circle (as polyline)
QFont definedFont()
Font to be used for rendering.
QMap< QString, QString > layerStyleOverrides() const
Get map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
QList< QgsSymbolLevelItem > QgsSymbolLevel
Definition: qgsrenderer.h:73
double getAlpha() const
get alpha
virtual void stopRender(QgsSymbolRenderContext &context)=0
virtual double dxfAngle(QgsSymbolRenderContext &context) const
get angle
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the symbol&#39;s size.
double getWidth() const
double getX(int i=0) const
get the down-left x coordinate
QgsPointXY layerToMapCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from layer&#39;s CRS to output CRS
virtual QColor dxfColor(QgsSymbolRenderContext &context) const
get color
RenderHints renderHints() const
Returns the rendering hint flags for the symbol.
Definition: qgssymbol.h:276
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbol.h:501
This class represents a coordinate reference system (CRS).
void writeDouble(double d)
Write a floating point value.
void setMapToPixel(const QgsMapToPixel &mtp)
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
Class for doing transforms between two map coordinate systems.
LabelPosition is a candidate feature label position.
Definition: labelposition.h:55
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:120
void setLayers(const QList< QgsMapLayer *> &layers)
Set list of layers for map rendering.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
void registerDxfFeature(QgsFeature &feature, QgsRenderContext &context, const QString &dxfLayerName)
Registration method that keeps track of DXF layer names of individual features.
double z
Definition: qgspoint.h:43
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:125
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
QString name
Definition: qgsmaplayer.h:60
bool setOverrideStyle(const QString &styleDef)
Temporarily apply a different style to the layer.
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:170
bool getReversed() const
bool nextFeature(QgsFeature &f)
Implements a derived label provider internally used for DXF export.
#define DXF_HANDPLOTSTYLE
Definition: qgsdxfexport.h:40
#define DXF_HANDMAX
Definition: qgsdxfexport.h:39
virtual bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const
write as DXF
Container for all settings relating to text rendering.
Geometry is not required. It may still be returned if e.g. required for a filter condition.
int writeHandle(int code=5, int handle=0)
Write a tuple of group code and a handle.
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer&#39;s CRS
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:255
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:427
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
QgsSymbol * symbol()
Definition: qgsrenderer.h:65
QFont font() const
Returns the font used for rendering text.
void writeMText(const QString &layer, const QString &text, const QgsPoint &pt, double width, double angle, const QColor &color)
Write mtext (MTEXT)
void addLayers(const QList< QgsDxfExport::DxfLayer > &layers)
Add layers to export.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsDxfExport & operator=(const QgsDxfExport &dxfExport)
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:100
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:149
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Set flags that affect how features will be fetched.
DirectionSymbols placeDirectionSymbol
Placement option for direction symbols.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Exports one feature per symbol layer (considering symbol levels)
Definition: qgsdxfexport.h:84
double x
Definition: qgspoint.h:41