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