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