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