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