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