QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 #include "qgsdxfexport.h"
19 #include "qgsdxfpallabeling.h"
20 #include "qgsvectordataprovider.h"
21 #include "qgspoint.h"
22 #include "qgsrendererv2.h"
23 #include "qgssymbollayerv2.h"
24 #include "qgsfillsymbollayerv2.h"
25 #include "qgslinesymbollayerv2.h"
26 #include "qgsvectorlayer.h"
27 #include <QIODevice>
28 
29 //dxf color palette
30 double QgsDxfExport::mDxfColors[][3] =
31 {
32  {0, 0, 0}, // unused
33  {1, 0, 0}, // 1
34  {1, 1, 0},
35  {0, 1, 0},
36  {0, 1, 1},
37  {0, 0, 1},
38  {1, 0, 1},
39  {1, 1, 1}, // black or white
40  {0.5, 0.5, 0.5},
41  {0.75, 0.75, 0.75},
42  {1, 0, 0}, // 10
43  {1, 0.5, 0.5},
44  {0.65, 0, 0},
45  {0.65, 0.325, 0.325},
46  {0.5, 0, 0},
47  {0.5, 0.25, 0.25},
48  {0.3, 0, 0},
49  {0.3, 0.15, 0.15},
50  {0.15, 0, 0},
51  {0.15, 0.075, 0.075},
52  {1, 0.25, 0}, // 20
53  {1, 0.625, 0.5},
54  {0.65, 0.1625, 0},
55  {0.65, 0.4063, 0.325},
56  {0.5, 0.125, 0},
57  {0.5, 0.3125, 0.25},
58  {0.3, 0.075, 0},
59  {0.3, 0.1875, 0.15},
60  {0.15, 0.0375, 0},
61  {0.15, 0.0938, 0.075},
62  {1, 0.5, 0}, // 30
63  {1, 0.75, 0.5},
64  {0.65, 0.325, 0},
65  {0.65, 0.4875, 0.325},
66  {0.5, 0.25, 0},
67  {0.5, 0.375, 0.25},
68  {0.3, 0.15, 0},
69  {0.3, 0.225, 0.15},
70  {0.15, 0.075, 0},
71  {0.15, 0.1125, 0.075},
72  {1, 0.75, 0}, // 40
73  {1, 0.875, 0.5},
74  {0.65, 0.4875, 0},
75  {0.65, 0.5688, 0.325},
76  {0.5, 0.375, 0},
77  {0.5, 0.4375, 0.25},
78  {0.3, 0.225, 0},
79  {0.3, 0.2625, 0.15},
80  {0.15, 0.1125, 0},
81  {0.15, 0.1313, 0.075},
82  {1, 1, 0}, // 50
83  {1, 1, 0.5},
84  {0.65, 0.65, 0},
85  {0.65, 0.65, 0.325},
86  {0.5, 0.5, 0},
87  {0.5, 0.5, 0.25},
88  {0.3, 0.3, 0},
89  {0.3, 0.3, 0.15},
90  {0.15, 0.15, 0},
91  {0.15, 0.15, 0.075},
92  {0.75, 1, 0}, // 60
93  {0.875, 1, 0.5},
94  {0.4875, 0.65, 0},
95  {0.5688, 0.65, 0.325},
96  {0.375, 0.5, 0},
97  {0.4375, 0.5, 0.25},
98  {0.225, 0.3, 0},
99  {0.2625, 0.3, 0.15},
100  {0.1125, 0.15, 0},
101  {0.1313, 0.15, 0.075},
102  {0.5, 1, 0}, // 70
103  {0.75, 1, 0.5},
104  {0.325, 0.65, 0},
105  {0.4875, 0.65, 0.325},
106  {0.25, 0.5, 0},
107  {0.375, 0.5, 0.25},
108  {0.15, 0.3, 0},
109  {0.225, 0.3, 0.15},
110  {0.075, 0.15, 0},
111  {0.1125, 0.15, 0.075},
112  {0.25, 1, 0}, // 80
113  {0.625, 1, 0.5},
114  {0.1625, 0.65, 0},
115  {0.4063, 0.65, 0.325},
116  {0.125, 0.5, 0},
117  {0.3125, 0.5, 0.25},
118  {0.075, 0.3, 0},
119  {0.1875, 0.3, 0.15},
120  {0.0375, 0.15, 0},
121  {0.0938, 0.15, 0.075},
122  {0, 1, 0}, // 90
123  {0.5, 1, 0.5},
124  {0, 0.65, 0},
125  {0.325, 0.65, 0.325},
126  {0, 0.5, 0},
127  {0.25, 0.5, 0.25},
128  {0, 0.3, 0},
129  {0.15, 0.3, 0.15},
130  {0, 0.15, 0},
131  {0.075, 0.15, 0.075},
132  {0, 1, 0.25}, // 100
133  {0.5, 1, 0.625},
134  {0, 0.65, 0.1625},
135  {0.325, 0.65, 0.4063},
136  {0, 0.5, 0.125},
137  {0.25, 0.5, 0.3125},
138  {0, 0.3, 0.075},
139  {0.15, 0.3, 0.1875},
140  {0, 0.15, 0.0375},
141  {0.075, 0.15, 0.0938},
142  {0, 1, 0.5}, // 110
143  {0.5, 1, 0.75},
144  {0, 0.65, 0.325},
145  {0.325, 0.65, 0.4875},
146  {0, 0.5, 0.25},
147  {0.25, 0.5, 0.375},
148  {0, 0.3, 0.15},
149  {0.15, 0.3, 0.225},
150  {0, 0.15, 0.075},
151  {0.075, 0.15, 0.1125},
152  {0, 1, 0.75}, // 120
153  {0.5, 1, 0.875},
154  {0, 0.65, 0.4875},
155  {0.325, 0.65, 0.5688},
156  {0, 0.5, 0.375},
157  {0.25, 0.5, 0.4375},
158  {0, 0.3, 0.225},
159  {0.15, 0.3, 0.2625},
160  {0, 0.15, 0.1125},
161  {0.075, 0.15, 0.1313},
162  {0, 1, 1}, // 130
163  {0.5, 1, 1},
164  {0, 0.65, 0.65},
165  {0.325, 0.65, 0.65},
166  {0, 0.5, 0.5},
167  {0.25, 0.5, 0.5},
168  {0, 0.3, 0.3},
169  {0.15, 0.3, 0.3},
170  {0, 0.15, 0.15},
171  {0.075, 0.15, 0.15},
172  {0, 0.75, 1}, // 140
173  {0.5, 0.875, 1},
174  {0, 0.4875, 0.65},
175  {0.325, 0.5688, 0.65},
176  {0, 0.375, 0.5},
177  {0.25, 0.4375, 0.5},
178  {0, 0.225, 0.3},
179  {0.15, 0.2625, 0.3},
180  {0, 0.1125, 0.15},
181  {0.075, 0.1313, 0.15},
182  {0, 0.5, 1}, // 150
183  {0.5, 0.75, 1},
184  {0, 0.325, 0.65},
185  {0.325, 0.4875, 0.65},
186  {0, 0.25, 0.5},
187  {0.25, 0.375, 0.5},
188  {0, 0.15, 0.3},
189  {0.15, 0.225, 0.3},
190  {0, 0.075, 0.15},
191  {0.075, 0.1125, 0.15},
192  {0, 0.25, 1}, // 160
193  {0.5, 0.625, 1},
194  {0, 0.1625, 0.65},
195  {0.325, 0.4063, 0.65},
196  {0, 0.125, 0.5},
197  {0.25, 0.3125, 0.5},
198  {0, 0.075, 0.3},
199  {0.15, 0.1875, 0.3},
200  {0, 0.0375, 0.15},
201  {0.075, 0.0938, 0.15},
202  {0, 0, 1}, // 170
203  {0.5, 0.5, 1},
204  {0, 0, 0.65},
205  {0.325, 0.325, 0.65},
206  {0, 0, 0.5},
207  {0.25, 0.25, 0.5},
208  {0, 0, 0.3},
209  {0.15, 0.15, 0.3},
210  {0, 0, 0.15},
211  {0.075, 0.075, 0.15},
212  {0.25, 0, 1}, // 180
213  {0.625, 0.5, 1},
214  {0.1625, 0, 0.65},
215  {0.4063, 0.325, 0.65},
216  {0.125, 0, 0.5},
217  {0.3125, 0.25, 0.5},
218  {0.075, 0, 0.3},
219  {0.1875, 0.15, 0.3},
220  {0.0375, 0, 0.15},
221  {0.0938, 0.075, 0.15},
222  {0.5, 0, 1}, // 190
223  {0.75, 0.5, 1},
224  {0.325, 0, 0.65},
225  {0.4875, 0.325, 0.65},
226  {0.25, 0, 0.5},
227  {0.375, 0.25, 0.5},
228  {0.15, 0, 0.3},
229  {0.225, 0.15, 0.3},
230  {0.075, 0, 0.15},
231  {0.1125, 0.075, 0.15},
232  {0.75, 0, 1}, // 200
233  {0.875, 0.5, 1},
234  {0.4875, 0, 0.65},
235  {0.5688, 0.325, 0.65},
236  {0.375, 0, 0.5},
237  {0.4375, 0.25, 0.5},
238  {0.225, 0, 0.3},
239  {0.2625, 0.15, 0.3},
240  {0.1125, 0, 0.15},
241  {0.1313, 0.075, 0.15},
242  {1, 0, 1}, // 210
243  {1, 0.5, 1},
244  {0.65, 0, 0.65},
245  {0.65, 0.325, 0.65},
246  {0.5, 0, 0.5},
247  {0.5, 0.25, 0.5},
248  {0.3, 0, 0.3},
249  {0.3, 0.15, 0.3},
250  {0.15, 0, 0.15},
251  {0.15, 0.075, 0.15},
252  {1, 0, 0.75}, // 220
253  {1, 0.5, 0.875},
254  {0.65, 0, 0.4875},
255  {0.65, 0.325, 0.5688},
256  {0.5, 0, 0.375},
257  {0.5, 0.25, 0.4375},
258  {0.3, 0, 0.225},
259  {0.3, 0.15, 0.2625},
260  {0.15, 0, 0.1125},
261  {0.15, 0.075, 0.1313},
262  {1, 0, 0.5}, // 230
263  {1, 0.5, 0.75},
264  {0.65, 0, 0.325},
265  {0.65, 0.325, 0.4875},
266  {0.5, 0, 0.25},
267  {0.5, 0.25, 0.375},
268  {0.3, 0, 0.15},
269  {0.3, 0.15, 0.225},
270  {0.15, 0, 0.075},
271  {0.15, 0.075, 0.1125},
272  {1, 0, 0.25}, // 240
273  {1, 0.5, 0.625},
274  {0.65, 0, 0.1625},
275  {0.65, 0.325, 0.4063},
276  {0.5, 0, 0.125},
277  {0.5, 0.25, 0.3125},
278  {0.3, 0, 0.075},
279  {0.3, 0.15, 0.1875},
280  {0.15, 0, 0.0375},
281  {0.15, 0.075, 0.0938},
282  {0.33, 0.33, 0.33}, // 250
283  {0.464, 0.464, 0.464},
284  {0.598, 0.598, 0.598},
285  {0.732, 0.732, 0.732},
286  {0.866, 0.866, 0.866},
287  {1, 1, 1} // 255
288 };
289 
290 QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ),
291  mNextHandleId( 10 ), mBlockCounter( 0 )
292 {
293 }
294 
296 {
297  *this = dxfExport;
298 }
299 
301 {
302  mLayers = dxfExport.mLayers;
305  mMapUnits = dxfExport.mMapUnits;
306  mSymbolLayerCounter = 0; //internal counter
307  mNextHandleId = 0;
308  mBlockCounter = 0;
309  return *this;
310 }
311 
313 {
314 }
315 
316 void QgsDxfExport::writeGroup( int code, int i )
317 {
318  writeGroupCode( code );
319  writeInt( i );
320 }
321 
322 void QgsDxfExport::writeGroup( int code, double d )
323 {
324  writeGroupCode( code );
325  writeDouble( d );
326 }
327 
328 void QgsDxfExport::writeGroup( int code, const QString& s )
329 {
330  writeGroupCode( code );
331  writeString( s );
332 }
333 
335 {
336  if ( code < 10 )
337  {
338  mTextStream << QString( " %1\n" ).arg( code );
339  }
340  else if ( code < 100 )
341  {
342  mTextStream << QString( " %1\n" ).arg( code );
343  }
344  else
345  {
346  mTextStream << QString( "%1\n" ).arg( code );
347  }
348 
349 }
350 
352 {
353  mTextStream << QString( "%1\n" ).arg( i );
354 }
355 
357 {
358  mTextStream << qgsDoubleToString( d ) << "\n";
359 }
360 
361 void QgsDxfExport::writeString( const QString& s )
362 {
363  mTextStream << s << "\n";
364 }
365 
366 int QgsDxfExport::writeToFile( QIODevice* d )
367 {
368  if ( !d )
369  {
370  return 1;
371  }
372 
373  if ( !d->isOpen() && !d->open( QIODevice::WriteOnly ) )
374  {
375  return 2;
376  }
377 
378  mTextStream.setDevice( d );
379 
380  writeHeader();
381  writeTables();
382  writeBlocks();
383  writeEntities();
384  writeEndFile();
385  return 0;
386 }
387 
389 {
390  writeGroup( 999, "DXF created from QGIS" );
391  startSection();
392  writeGroup( 2, "HEADER" );
393 
394  //ACADVER
395  writeGroup( 9, "$ACADVER" );
396  writeGroup( 1, "AC1009" );
397 
398  QgsRectangle ext = dxfExtent();
399  if ( !ext.isEmpty() )
400  {
401  //EXTMIN
402  writeGroup( 9, "$EXTMIN" );
403  writeGroup( 10, ext.xMinimum() );
404  writeGroup( 20, ext.yMinimum() );
405  writeGroup( 30, 0.0 );
406 
407  //EXTMAX
408  writeGroup( 9, "$EXTMAX" );
409  writeGroup( 10, ext.xMaximum() );
410  writeGroup( 20, ext.yMaximum() );
411  writeGroup( 30, 0.0 );
412  }
413 
414  //LTSCALE
415  writeGroup( 9, "$LTSCALE" );
416  writeGroup( 40, 1.0 );
417 
418  //PDMODE
419  writeGroup( 9, "$PDMODE" );
420  writeGroup( 70, 33 );
421 
422  //PDSIZE
423  writeGroup( 9, "$PDSIZE" );
424  writeGroup( 40, 1 );
425 
426  //PSLTSCALE
427  writeGroup( 9, "$PSLTSCALE" );
428  writeGroup( 70, 0 );
429 
430  endSection();
431 }
432 
434 {
435  startSection();
436  writeGroup( 2, "TABLES" );
437 
438  //iterate through all layers and get symbol layer pointers
439  QList< QPair<QgsSymbolLayerV2*, QgsSymbolV2*> > slList;
440  if ( mSymbologyExport != NoSymbology )
441  {
442  slList = symbolLayers();
443  }
444 
445  //LTYPE
446  mLineStyles.clear();
447  writeGroup( 0, "TABLE" );
448  writeGroup( 2, "LTYPE" );
449  writeGroup( 70, nLineTypes( slList ) + 5 );
450 
452  //add custom linestyles
453  QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = slList.constBegin();
454  for ( ; slIt != slList.constEnd(); ++slIt )
455  {
456  writeSymbolLayerLinestyle( slIt->first );
457  }
458 
459  writeGroup( 0, "ENDTAB" );
460 
461  //LAYER
462  writeGroup( 0, "TABLE" );
463  writeGroup( 2, "LAYER" );
464  writeGroup( 70, mLayers.count() );
465 
466  QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin();
467  for ( ; layerIt != mLayers.constEnd(); ++layerIt )
468  {
469  if ( !layerIsScaleBasedVisible(( *layerIt ) ) )
470  {
471  continue;
472  }
473 
474  writeGroup( 0, "LAYER" );
475  QString layerName = *layerIt ? ( *layerIt )->name() : "";
476  writeGroup( 2, dxfLayerName( layerName ) );
477  writeGroup( 70, 64 );
478  writeGroup( 62, 1 );
479  writeGroup( 6, "CONTINUOUS" );
480  }
481  writeGroup( 0, "ENDTAB" );
482 
483  //STYLE
484  writeGroup( 0, "TABLE" );
485  writeGroup( 2, "STYLE" );
486  writeGroup( 70, 1 );
487 
488  //provide only standard font for the moment
489  writeGroup( 0, "STYLE" );
490  writeGroup( 2, "STANDARD" );
491  writeGroup( 70, 64 );
492  writeGroup( 40, 0.0 );
493  writeGroup( 41, 1.0 );
494  writeGroup( 50, 0.0 );
495  writeGroup( 71, 0 );
496  writeGroup( 42, 5.0 );
497  writeGroup( 3, "romans.shx" );
498  writeGroup( 4, "" );
499 
500  writeGroup( 0, "ENDTAB" );
501 
502  endSection();
503 }
504 
506 {
507  startSection();
508  writeGroup( 2, "BLOCKS" );
509 
510  //iterate through all layers and get symbol layer pointers
511  QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > slList;
512  if ( mSymbologyExport != NoSymbology )
513  {
514  slList = symbolLayers();
515  }
516 
517  QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > >::const_iterator slIt = slList.constBegin();
518  for ( ; slIt != slList.constEnd(); ++slIt )
519  {
520  QgsMarkerSymbolLayerV2* ml = dynamic_cast< QgsMarkerSymbolLayerV2*>( slIt->first );
521  if ( ml )
522  {
523  //if point symbol layer and no data defined properties: write block
524  QgsRenderContext ct;
525  QgsSymbolV2RenderContext ctx( ct, QgsSymbolV2::MapUnit, slIt->second->alpha(), false, slIt->second->renderHints(), 0 );
526  ml->startRender( ctx );
527 
528  //markers with data defined properties are inserted inline
529  if ( hasDataDefinedProperties( ml, slIt->second ) )
530  {
531  continue;
532  // ml->stopRender( ctx );
533  }
534  writeGroup( 0, "BLOCK" );
535  writeGroup( 8, 0 );
536  QString blockName = QString( "symbolLayer%1" ).arg( mBlockCounter++ );
537  writeGroup( 2, blockName );
538  writeGroup( 70, 64 );
539 
540  //x/y/z coordinates of reference point
541  //todo: consider anchor point
542  // double size = ml->size();
543  // size *= mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits );
544  writeGroup( 10, 0 );
545  writeGroup( 20, 0 );
546  writeGroup( 30, 0 );
547  writeGroup( 3, blockName );
548 
549  ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ), "0", &ctx, 0 ); //maplayer 0 -> block receives layer from INSERT statement
550 
551  writeGroup( 0, "ENDBLK" );
552  writeGroup( 8, 0 );
553 
554  mPointSymbolBlocks.insert( ml, blockName );
555  ml->stopRender( ctx );
556  }
557  }
558  endSection();
559 }
560 
562 {
563  startSection();
564  writeGroup( 2, "ENTITIES" );
565 
566  //label engine
568  QgsRenderContext& ctx = labelEngine.renderContext();
569 
570  //iterate through the maplayers
571  QList< QgsMapLayer* >::iterator layerIt = mLayers.begin();
572  for ( ; layerIt != mLayers.end(); ++layerIt )
573  {
574  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( *layerIt );
575  if ( !vl || !layerIsScaleBasedVisible( vl ) )
576  {
577  continue;
578  }
579 
580  QgsSymbolV2RenderContext sctx( ctx, QgsSymbolV2::MM , 1.0, false, 0, 0 );
581  QgsFeatureRendererV2* renderer = vl->rendererV2();
582  renderer->startRender( ctx, vl->pendingFields() );
583 
584  QStringList attributes = renderer->usedAttributes();
585 
586  bool labelLayer = ( labelEngine.prepareLayer( vl, attributes, ctx ) != 0 );
587 
589  renderer->usingSymbolLevels() )
590  {
592  renderer->stopRender( ctx );
593  continue;
594  }
595 
597  attributes, vl->pendingFields() );
598  if ( !mExtent.isEmpty() )
599  {
600  freq.setFilterRect( mExtent );
601  }
602  QgsFeatureIterator featureIt = vl->getFeatures( freq );
603  QgsFeature fet;
604  while ( featureIt.nextFeature( fet ) )
605  {
606  sctx.setFeature( &fet );
607  if ( mSymbologyExport == NoSymbology )
608  {
609  addFeature( sctx, dxfLayerName( vl->name() ), 0, 0 ); //no symbology at all
610  }
611  else
612  {
613  if ( !renderer )
614  {
615  continue;
616  }
617  QgsSymbolV2List symbolList = renderer->symbolsForFeature( fet );
618  if ( symbolList.size() < 1 )
619  {
620  continue;
621  }
622 
623  if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology ) //symbol layer symbology, but layer does not use symbol levels
624  {
625  QgsSymbolV2List::iterator symbolIt = symbolList.begin();
626  for ( ; symbolIt != symbolList.end(); ++symbolIt )
627  {
628  int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
629  for ( int i = 0; i < nSymbolLayers; ++i )
630  {
631  addFeature( sctx, dxfLayerName( vl->name() ), ( *symbolIt )->symbolLayer( i ), *symbolIt );
632  }
633  }
634  }
635  else
636  {
637  //take first symbollayer from first symbol
638  QgsSymbolV2* s = symbolList.first();
639  if ( !s || s->symbolLayerCount() < 1 )
640  {
641  continue;
642  }
643  addFeature( sctx, dxfLayerName( vl->name() ), s->symbolLayer( 0 ), s );
644  }
645 
646  if ( labelLayer )
647  {
648  labelEngine.registerFeature( vl->id(), fet, ctx );
649  }
650  }
651  }
652  renderer->stopRender( ctx );
653  }
654 
655  labelEngine.drawLabeling( ctx );
656  endSection();
657 }
658 
660 {
661  if ( !layer )
662  {
663  return;
664  }
665 
666  QgsFeatureRendererV2* renderer = layer->rendererV2();
667  if ( !renderer )
668  {
669  //return error
670  }
671  QHash< QgsSymbolV2*, QList<QgsFeature> > features;
672 
674  QgsSymbolV2RenderContext sctx( ctx, QgsSymbolV2::MM , 1.0, false, 0, 0 );
675  renderer->startRender( ctx, layer->pendingFields() );
676 
677  //get iterator
678  QgsFeatureRequest req;
679  if ( layer->wkbType() == QGis::WKBNoGeometry )
680  {
682  }
683  req.setSubsetOfAttributes( QStringList( renderer->usedAttributes() ), layer->pendingFields() );
684  if ( !mExtent.isEmpty() )
685  {
686  req.setFilterRect( mExtent );
687  }
688  QgsFeatureIterator fit = layer->getFeatures( req );
689 
690  //fetch features
691  QgsFeature fet;
692  QgsSymbolV2* featureSymbol = 0;
693  while ( fit.nextFeature( fet ) )
694  {
695  featureSymbol = renderer->symbolForFeature( fet );
696  if ( !featureSymbol )
697  {
698  continue;
699  }
700 
701  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
702  if ( it == features.end() )
703  {
704  it = features.insert( featureSymbol, QList<QgsFeature>() );
705  }
706  it.value().append( fet );
707  }
708 
709  //find out order
710  QgsSymbolV2LevelOrder levels;
711  QgsSymbolV2List symbols = renderer->symbols();
712  for ( int i = 0; i < symbols.count(); i++ )
713  {
714  QgsSymbolV2* sym = symbols[i];
715  for ( int j = 0; j < sym->symbolLayerCount(); j++ )
716  {
717  int level = sym->symbolLayer( j )->renderingPass();
718  if ( level < 0 || level >= 1000 ) // ignore invalid levels
719  continue;
720  QgsSymbolV2LevelItem item( sym, j );
721  while ( level >= levels.count() ) // append new empty levels
722  levels.append( QgsSymbolV2Level() );
723  levels[level].append( item );
724  }
725  }
726 
727  //export symbol layers and symbology
728  for ( int l = 0; l < levels.count(); l++ )
729  {
730  QgsSymbolV2Level& level = levels[l];
731  for ( int i = 0; i < level.count(); i++ )
732  {
733  QgsSymbolV2LevelItem& item = level[i];
734  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
735 
736  int llayer = item.layer();
737  QList<QgsFeature>& featureList = levelIt.value();
738  QList<QgsFeature>::iterator featureIt = featureList.begin();
739  for ( ; featureIt != featureList.end(); ++featureIt )
740  {
741  addFeature( sctx, layer->name(), levelIt.key()->symbolLayer( llayer ), levelIt.key() );
742  }
743  }
744  }
745  renderer->stopRender( ctx );
746 }
747 
749 {
750  writeGroup( 0, "EOF" );
751 }
752 
754 {
755  writeGroup( 0, "SECTION" );
756 }
757 
759 {
760  writeGroup( 0, "ENDSEC" );
761 }
762 
763 void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, int color, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol )
764 {
765 #if 0
766  //debug: draw rectangle for debugging
767  const QgsMarkerSymbolLayerV2* msl = dynamic_cast< const QgsMarkerSymbolLayerV2* >( symbolLayer );
768  if ( msl )
769  {
770  double halfSize = msl->size() * mapUnitScaleFactor( mSymbologyScaleDenominator,
771  msl->sizeUnit(), mMapUnits ) / 2.0;
772  writeGroup( 0, "SOLID" );
773  writeGroup( 8, layer );
774  writeGroup( 62, 1 );
775  writeGroup( 10, pt.x() - halfSize );
776  writeGroup( 20, pt.y() - halfSize );
777  writeGroup( 30, 0.0 );
778  writeGroup( 11, pt.x() + halfSize );
779  writeGroup( 21, pt.y() - halfSize );
780  writeGroup( 31, 0.0 );
781  writeGroup( 12, pt.x() - halfSize );
782  writeGroup( 22, pt.y() + halfSize );
783  writeGroup( 32, 0.0 );
784  writeGroup( 13, pt.x() + halfSize );
785  writeGroup( 23, pt.y() + halfSize );
786  writeGroup( 33, 0.0 );
787  }
788 #endif //0
789 
790  //insert block or write point directly?
791  QHash< const QgsSymbolLayerV2*, QString >::const_iterator blockIt = mPointSymbolBlocks.find( symbolLayer );
792  if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() )
793  {
794  //write symbol directly here
795  const QgsMarkerSymbolLayerV2* msl = dynamic_cast< const QgsMarkerSymbolLayerV2* >( symbolLayer );
796  if ( symbolLayer && symbol )
797  {
798  QgsRenderContext ct;
799  QgsSymbolV2RenderContext ctx( ct, QgsSymbolV2::MapUnit, symbol->alpha(), false, symbol->renderHints(), f );
800  if ( symbolLayer->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, msl->sizeUnit(), mMapUnits ), layer, &ctx, f, QPointF( pt.x(), pt.y() ) ) )
801  {
802  return;
803  }
804  }
805  writePoint( layer, color, pt ); //write default point symbol
806  }
807  else
808  {
809  //insert block reference
810  writeGroup( 0, "INSERT" );
811  writeGroup( 8, layer );
812  writeGroup( 2, blockIt.value() );
813  writeGroup( 10, pt.x() );
814  writeGroup( 20, pt.y() );
815  writeGroup( 30, 0 );
816  }
817 }
818 
819 void QgsDxfExport::writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color,
820  double width, bool polygon )
821 {
822  writeGroup( 0, "POLYLINE" );
823  writeGroup( 8, layer );
824  writeGroup( 6, lineStyleName );
825  writeGroup( 62, color );
826  writeGroup( 66, 1 );
827  int type = polygon ? 1 : 0;
828  writeGroup( 70, type );
829  if ( width > 0 ) //width -1: use default width
830  {
831  writeGroup( 40, width );
832  writeGroup( 41, width );
833  }
834 
835  QgsPolyline::const_iterator lineIt = line.constBegin();
836  for ( ; lineIt != line.constEnd(); ++lineIt )
837  {
838  writeVertex( *lineIt, layer );
839  }
840 
841  writeGroup( 0, "SEQEND" );
842 }
843 
844 void QgsDxfExport::writeLine( const QgsPoint& pt1, const QgsPoint& pt2, const QString& layer, const QString& lineStyleName, int color, double width )
845 {
846  QgsPolyline line( 2 );
847  line[0] = pt1;
848  line[1] = pt2;
849  writePolyline( line, layer, lineStyleName, color, width, false );
850 }
851 
852 void QgsDxfExport::writePoint( const QString& layer, int color, const QgsPoint& pt )
853 {
854  writeGroup( 0, "POINT" );
855  writeGroup( 8, layer );
856  writeGroup( 62, color );
857  writeGroup( 10, pt.x() );
858  writeGroup( 20, pt.y() );
859  writeGroup( 30, 0.0 );
860 }
861 
862 void QgsDxfExport::writeCircle( const QString& layer, int color, const QgsPoint& pt, double radius )
863 {
864  writeGroup( 0, "CIRCLE" );
865  writeGroup( 8, layer );
866  writeGroup( 62, color );
867  writeGroup( 10, pt.x() );
868  writeGroup( 20, pt.y() );
869  writeGroup( 30, 0 );
870  writeGroup( 40, radius );
871 }
872 
873 void QgsDxfExport::writeText( const QString& layer, const QString& text, const QgsPoint& pt, double size, double angle, int color )
874 {
875  writeGroup( 0, "TEXT" );
876  writeGroup( 8, layer );
877  writeGroup( 62, color );
878  writeGroup( 10, pt.x() );
879  writeGroup( 20, pt.y() );
880  writeGroup( 30, 0 );
881  writeGroup( 40, size );
882  writeGroup( 1, text );
883  writeGroup( 50, angle );
884  writeGroup( 7, "STANDARD" ); //so far only support for standard font
885 }
886 
887 void QgsDxfExport::writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 )
888 {
889  writeGroup( 0, "SOLID" );
890  writeGroup( 8, layer );
891  writeGroup( 62, color );
892  writeGroup( 10, pt1.x() );
893  writeGroup( 20, pt1.y() );
894  writeGroup( 30, 0.0 );
895  writeGroup( 11, pt2.x() );
896  writeGroup( 21, pt2.y() );
897  writeGroup( 31, 0.0 );
898  writeGroup( 12, pt3.x() );
899  writeGroup( 22, pt3.y() );
900  writeGroup( 32, 0.0 );
901  writeGroup( 13, pt4.x() );
902  writeGroup( 23, pt4.y() );
903  writeGroup( 33, 0.0 );
904 }
905 
906 void QgsDxfExport::writeVertex( const QgsPoint& pt, const QString& layer )
907 {
908  writeGroup( 0, "VERTEX" );
909  writeGroup( 8, layer );
910  writeGroup( 10, pt.x() );
911  writeGroup( 20, pt.y() );
912  writeGroup( 30, 0 );
913 }
914 
916 {
918  QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin();
919  for ( ; layerIt != mLayers.constEnd(); ++layerIt )
920  {
921  if ( *layerIt )
922  {
923  if ( extent.isEmpty() )
924  {
925  extent = ( *layerIt )->extent();
926  }
927  else
928  {
929  QgsRectangle layerExtent = ( *layerIt )->extent();
930  extent.combineExtentWith( &layerExtent );
931  }
932  }
933  }
934  return extent;
935 }
936 
937 void QgsDxfExport::addFeature( const QgsSymbolV2RenderContext& ctx, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol )
938 {
939  const QgsFeature* fet = ctx.feature();
940  if ( !fet )
941  {
942  return;
943  }
944 
945  QgsGeometry* geom = fet->geometry();
946  if ( geom )
947  {
948  int c = 0;
949  if ( mSymbologyExport != NoSymbology )
950  {
951  c = colorFromSymbolLayer( symbolLayer, ctx );
952  }
953  double width = -1;
954  if ( mSymbologyExport != NoSymbology && symbolLayer )
955  {
956  width = symbolLayer->dxfWidth( *this, ctx );
957  }
958  QString lineStyleName = "CONTINUOUS";
959  if ( mSymbologyExport != NoSymbology )
960  {
961  lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
962  }
963  QGis::WkbType geometryType = geom->wkbType();
964 
965  //single point
966  if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D )
967  {
968  writePoint( geom->asPoint(), layer, c, fet, symbolLayer, symbol );
969  }
970 
971  //multipoint
972  if ( geometryType == QGis::WKBMultiPoint || geometryType == QGis::WKBMultiPoint25D )
973  {
974  QgsMultiPoint multiPoint = geom->asMultiPoint();
975  QgsMultiPoint::const_iterator it = multiPoint.constBegin();
976  for ( ; it != multiPoint.constEnd(); ++it )
977  {
978  writePoint( *it, layer, c, fet, symbolLayer, symbol );
979  }
980  }
981 
982  //single line
983  if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D )
984  {
985  writePolyline( geom->asPolyline(), layer, lineStyleName, c, width, false );
986  }
987 
988  //multiline
989  if ( geometryType == QGis::WKBMultiLineString || geometryType == QGis::WKBMultiLineString25D )
990  {
991  QgsMultiPolyline multiLine = geom->asMultiPolyline();
992  QgsMultiPolyline::const_iterator lIt = multiLine.constBegin();
993  for ( ; lIt != multiLine.constEnd(); ++lIt )
994  {
995  writePolyline( *lIt, layer, lineStyleName, c, width, false );
996  }
997  }
998 
999  //polygon
1000  if ( geometryType == QGis::WKBPolygon || geometryType == QGis::WKBPolygon25D )
1001  {
1002  QgsPolygon polygon = geom->asPolygon();
1003  QgsPolygon::const_iterator polyIt = polygon.constBegin();
1004  for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings
1005  {
1006  writePolyline( *polyIt, layer, lineStyleName, c, width, true );
1007  }
1008  }
1009 
1010  //multipolygon or polygon
1011  if ( geometryType == QGis::WKBMultiPolygon || geometryType == QGis::WKBMultiPolygon25D )
1012  {
1013  QgsMultiPolygon mp = geom->asMultiPolygon();
1014  QgsMultiPolygon::const_iterator mpIt = mp.constBegin();
1015  for ( ; mpIt != mp.constEnd(); ++mpIt )
1016  {
1017  QgsPolygon::const_iterator polyIt = mpIt->constBegin();
1018  for ( ; polyIt != mpIt->constEnd(); ++polyIt )
1019  {
1020  writePolyline( *polyIt, layer, lineStyleName, c, width, true );
1021  }
1022  }
1023  }
1024  }
1025 }
1026 
1028 {
1029  if ( !symbolLayer )
1030  {
1031  return 0;
1032  }
1033 
1034  QColor c = symbolLayer->dxfColor( ctx );
1035  return closestColorMatch( c.rgba() );
1036 }
1037 
1039 {
1040  QString lineStyleName = "CONTINUOUS";
1041  if ( !symbolLayer )
1042  {
1043  return lineStyleName;
1044  }
1045 
1046  QHash< const QgsSymbolLayerV2*, QString >::const_iterator lineTypeIt = mLineStyles.find( symbolLayer );
1047  if ( lineTypeIt != mLineStyles.constEnd() )
1048  {
1049  lineStyleName = lineTypeIt.value();
1050  }
1051  else
1052  {
1053  return lineNameFromPenStyle( symbolLayer->dxfPenStyle() );
1054  }
1055  return lineStyleName;
1056 }
1057 
1059 {
1060  int idx = 0;
1061  int current_distance = INT_MAX;
1062  for ( int i = 1; i < 256; ++i )
1063  {
1064  int dist = color_distance( pixel, i );
1065  if ( dist < current_distance )
1066  {
1067  current_distance = dist;
1068  idx = i;
1069  }
1070  }
1071  return idx;
1072 }
1073 
1075 {
1076  if ( index > 255 || index < 0 )
1077  {
1078  return 0;
1079  }
1080 
1081  double redDiff = qRed( p1 ) - mDxfColors[index][0] * 255;
1082  double greenDiff = qGreen( p1 ) - mDxfColors[index][1] * 255;
1083  double blueDiff = qBlue( p1 ) - mDxfColors[index][2] * 255;
1084  return ( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff );
1085 }
1086 
1087 QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
1088 {
1089  return QColor::fromRgbF( r, g, b ).rgb();
1090 }
1091 
1093 {
1094  QgsRenderContext context;
1096  return context;
1097 }
1098 
1099 double QgsDxfExport::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
1100 {
1101  if ( symbolUnits == QgsSymbolV2::MapUnit )
1102  {
1103  return 1.0;
1104  }
1105  //MM symbol unit
1106  return scaleDenominator * QGis::fromUnitToUnitFactor( QGis::Meters, mapUnits ) / 1000.0;
1107 }
1108 
1109 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > QgsDxfExport::symbolLayers()
1110 {
1111  QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > symbolLayers;
1112 
1113  QList< QgsMapLayer* >::iterator lIt = mLayers.begin();
1114  for ( ; lIt != mLayers.end(); ++lIt )
1115  {
1116  //cast to vector layer
1117  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( *lIt );
1118  if ( !vl )
1119  {
1120  continue;
1121  }
1122 
1123  //get rendererv2
1124  QgsFeatureRendererV2* r = vl->rendererV2();
1125  if ( !r )
1126  {
1127  continue;
1128  }
1129 
1130  //get all symbols
1131  QgsSymbolV2List symbols = r->symbols();
1132  QgsSymbolV2List::iterator symbolIt = symbols.begin();
1133  for ( ; symbolIt != symbols.end(); ++symbolIt )
1134  {
1135  int maxSymbolLayers = ( *symbolIt )->symbolLayerCount();
1137  {
1138  maxSymbolLayers = 1;
1139  }
1140  for ( int i = 0; i < maxSymbolLayers; ++i )
1141  {
1142  symbolLayers.append( qMakePair(( *symbolIt )->symbolLayer( i ), *symbolIt ) ) ;
1143  }
1144  }
1145  }
1146 
1147  return symbolLayers;
1148 }
1149 
1151 {
1152  double das = dashSize();
1153  double dos = dotSize();
1154  double dss = dashSeparatorSize();
1155 
1156  //continuous (Qt solid line)
1157  writeGroup( 0, "LTYPE" );
1158  writeGroup( 2, "CONTINUOUS" );
1159  writeGroup( 70, 64 );
1160  writeGroup( 3, "Defaultstyle" );
1161  writeGroup( 72, 65 );
1162  writeGroup( 73, 0 );
1163  writeGroup( 40, 0.0 );
1164 
1165  QVector<qreal> dashVector( 2 );
1166  dashVector[0] = das;
1167  dashVector[1] = dss;
1168  writeLinestyle( "DASH", dashVector, QgsSymbolV2::MapUnit );
1169 
1170  QVector<qreal> dotVector( 2 );
1171  dotVector[0] = dos;
1172  dotVector[1] = dss;
1173  writeLinestyle( "DOT", dotVector, QgsSymbolV2::MapUnit );
1174 
1175  QVector<qreal> dashDotVector( 4 );
1176  dashDotVector[0] = das;
1177  dashDotVector[1] = dss;
1178  dashDotVector[2] = dos;
1179  dashDotVector[3] = dss;
1180  writeLinestyle( "DASHDOT", dashDotVector, QgsSymbolV2::MapUnit );
1181 
1182  QVector<qreal> dashDotDotVector( 6 );
1183  dashDotDotVector[0] = das;
1184  dashDotDotVector[1] = dss;
1185  dashDotDotVector[2] = dos;
1186  dashDotDotVector[3] = dss;
1187  dashDotDotVector[4] = dos;
1188  dashDotDotVector[5] = dss;
1189  writeLinestyle( "DASHDOTDOT", dashDotDotVector, QgsSymbolV2::MapUnit );
1190 }
1191 
1193 {
1194  if ( !symbolLayer )
1195  {
1196  return;
1197  }
1198 
1200  QVector<qreal> customLinestyle = symbolLayer->dxfCustomDashPattern( unit );
1201  if ( customLinestyle.size() > 0 )
1202  {
1203  QString name = QString( "symbolLayer%1" ).arg( mSymbolLayerCounter++ );
1204  writeLinestyle( name, customLinestyle, unit );
1205  mLineStyles.insert( symbolLayer, name );
1206  }
1207 }
1208 
1209 int QgsDxfExport::nLineTypes( const QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > >& symbolLayers )
1210 {
1211  int nLineTypes = 0;
1212  QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = symbolLayers.constBegin();
1213  for ( ; slIt != symbolLayers.constEnd(); ++slIt )
1214  {
1215  const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( slIt->first );
1216  if ( simpleLine )
1217  {
1218  if ( simpleLine->useCustomDashPattern() )
1219  {
1220  ++nLineTypes;
1221  }
1222  }
1223  }
1224  return nLineTypes;
1225 }
1226 
1227 void QgsDxfExport::writeLinestyle( const QString& styleName, const QVector<qreal>& pattern, QgsSymbolV2::OutputUnit u )
1228 {
1229  double length = 0;
1230  QVector<qreal>::const_iterator dashIt = pattern.constBegin();
1231  for ( ; dashIt != pattern.constEnd(); ++dashIt )
1232  {
1233  length += ( *dashIt * mapUnitScaleFactor( mSymbologyScaleDenominator, u, mMapUnits ) );
1234  }
1235 
1236  writeGroup( 0, "LTYPE" );
1237  writeGroup( 2, styleName );
1238  writeGroup( 70, 64 );
1239  writeGroup( 3, "" );
1240  writeGroup( 72, 65 );
1241  writeGroup( 73, pattern.size() );
1242  writeGroup( 40, length );
1243 
1244  dashIt = pattern.constBegin();
1245  bool isSpace = false;
1246  for ( ; dashIt != pattern.constEnd(); ++dashIt )
1247  {
1248  //map units or mm?
1249  double segmentLength = ( isSpace ? -*dashIt : *dashIt );
1251  writeGroup( 49, segmentLength );
1252  isSpace = !isSpace;
1253  }
1254 }
1255 
1257 {
1258  if ( !sl || !symbol )
1259  {
1260  return false;
1261  }
1262 
1265  {
1266  return true;
1267  }
1268 
1269  return sl->hasDataDefinedProperties();
1270 }
1271 
1273 {
1274  double size = mSymbologyScaleDenominator * 0.002;
1275  return sizeToMapUnits( size );
1276 }
1277 
1279 {
1280  double size = mSymbologyScaleDenominator * 0.0006;
1281  return sizeToMapUnits( size );
1282 }
1283 
1285 {
1286  double size = mSymbologyScaleDenominator * 0.0006;
1287  return sizeToMapUnits( size );
1288 }
1289 
1290 double QgsDxfExport::sizeToMapUnits( double s ) const
1291 {
1293  return size;
1294 }
1295 
1296 QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
1297 {
1298  switch ( style )
1299  {
1300  case Qt::DashLine:
1301  return "DASH";
1302  case Qt::DotLine:
1303  return "DOT";
1304  case Qt::DashDotLine:
1305  return "DASHDOT";
1306  case Qt::DashDotDotLine:
1307  return "DASHDOTDOT";
1308  case Qt::SolidLine:
1309  default:
1310  return "CONTINUOUS";
1311  }
1312 }
1313 
1314 QString QgsDxfExport::dxfLayerName( const QString& name )
1315 {
1316  //dxf layers can be max 31 characters long
1317  QString layerName = name.left( 31 );
1318 
1319  //allowed characters are 0-9, A-Z, $, -, _
1320  for ( int i = 0; i < layerName.size(); ++i )
1321  {
1322  QChar c = layerName.at( i );
1323  if ( c > 122 )
1324  {
1325  layerName[i] = '_';
1326  continue;
1327  }
1328 
1329  if ( c.isNumber() )
1330  {
1331  continue;
1332  }
1333  if ( c == '$' || c == '-' || c == '_' )
1334  {
1335  continue;
1336  }
1337 
1338  if ( !c.isLetter() )
1339  {
1340  layerName[i] = '_';
1341  }
1342  }
1343  return layerName;
1344 }
1345 
1347 {
1348  if ( !layer )
1349  {
1350  return false;
1351  }
1352 
1354  {
1355  return true;
1356  }
1357 
1358  return ( layer->minimumScale() < mSymbologyScaleDenominator &&
1360 }
1361 
1362 /******************************************************Test with AC_1018 methods***************************************************************/
1363 
1364 void QgsDxfExport::writeHeaderAC1018( QTextStream& stream )
1365 {
1366  stream << "999\n";
1367  stream << "DXF created from QGIS\n";
1368  startSection();
1369  stream << " 2\n";
1370  stream << "HEADER\n";
1371  //ACADVER
1372  stream << " 9\n";
1373  stream << "$ACADVER\n";
1374  stream << " 1\n";
1375  stream << "AC1018\n";
1376 
1377  QgsRectangle ext = dxfExtent();
1378  if ( !ext.isEmpty() )
1379  {
1380  //EXTMIN
1381  stream << " 9\n";
1382  stream << "$EXTMIN\n";
1383  stream << " 10\n";
1384  stream << ext.xMinimum() << "\n";
1385  stream << " 20\n";
1386  stream << ext.yMinimum() << "\n";
1387  stream << " 30\n";
1388  stream << "0\n";
1389  //EXTMAX
1390  stream << " 9\n";
1391  stream << "$EXTMAX\n";
1392  stream << " 10\n";
1393  stream << ext.xMaximum() << "\n";
1394  stream << " 20\n";
1395  stream << ext.yMaximum() << "\n";
1396  stream << " 30\n";
1397  stream << "0\n";
1398  }
1399  //LTSCALE
1400  stream << " 9\n";
1401  stream << "$LTSCALE\n";
1402  stream << " 40\n";
1403  stream << "1.0\n";
1404  //PDMODE
1405  stream << " 9\n";
1406  stream << "$PDMODE\n";
1407  stream << " 70\n";
1408  stream << "33\n";
1409  //PDSIZE
1410  stream << " 9\n";
1411  stream << "$PDSIZE\n";
1412  stream << " 40\n";
1413  stream << "1\n";
1414  endSection();
1415  //PSLTSCALE
1416  stream << " 9\n";
1417  stream << "$PSLTSCALE\n";
1418  stream << " 70\n";
1419  stream << "0\n";
1420 }
1421 
1422 void QgsDxfExport::writeTablesAC1018( QTextStream& stream )
1423 {
1424  startSection();
1425  stream << " 2\n";
1426  stream << "TABLES\n";
1427 
1428  //APPID
1429  stream << " 0\n";
1430  stream << "TABLE\n";
1431  stream << " 2\n";
1432  stream << "APPID\n";
1433  stream << " 5\n";
1434  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1435  stream << "100\n";
1436  stream << "AcDbSymbolTable\n";
1437  stream << " 70\n";
1438  stream << " 1\n";
1439  stream << " 0\n";
1440  stream << "APPID\n";
1441  stream << " 5\n";
1442  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1443  stream << "100\n";
1444  stream << "AcDbSymbolTableRecord\n";
1445  stream << "100\n";
1446  stream << "AcDbRegAppTableRecord\n";
1447  stream << " 2\n";
1448  stream << "ACAD\n";
1449  stream << " 70\n";
1450  stream << " 0\n";
1451  stream << " 0\n";
1452  stream << "ENDTAB\n";
1453 
1454  //VPORT table
1455  stream << " 0\n";
1456  stream << "TABLE\n";
1457  stream << " 2\n";
1458  stream << "VPORT\n";
1459  stream << " 5\n";
1460  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1461  stream << "100\n";
1462  stream << "AcDbSymbolTable\n";
1463  stream << " 70\n";
1464  stream << "1\n";
1465  stream << " 0\n";
1466  stream << "VPORT\n";
1467  stream << " 5\n";
1468  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1469  stream << "100\n";
1470  stream << "AcDbSymbolTableRecord\n";
1471  stream << "100\n";
1472  stream << "AcDbViewportTableRecord\n";
1473  stream << " 2\n";
1474  stream << "*Active\n";
1475  stream << " 70\n";
1476  stream << " 0\n";
1477  stream << " 10\n";
1478  stream << " 0.0\n";
1479  stream << " 20\n";
1480  stream << "0.0\n";
1481  stream << " 11\n";
1482  stream << " 1.0\n";
1483  stream << " 21\n";
1484  stream << "1.0\n";
1485  stream << " 12\n";
1486  stream << "80.25\n";
1487  stream << " 22\n";
1488  stream << "106.4409457059851\n";
1489  stream << " 40\n";
1490  stream << "113.3818914119703\n";
1491  stream << " 41\n";
1492  stream << "0.8863849310366128\n";
1493  stream << " 42\n";
1494  stream << "50.0\n";
1495  stream << " 0\n";
1496  stream << "ENDTAB\n";
1497 
1498  //iterate through all layers and get symbol layer pointers
1499  QList<QgsSymbolLayerV2*> slList;
1500  if ( mSymbologyExport != NoSymbology )
1501  {
1502  //slList = symbolLayers(); //todo...
1503  }
1504 
1505  //LTYPE
1506  mLineStyles.clear();
1507  stream << " 0\n";
1508  stream << "TABLE\n";
1509  stream << " 2\n";
1510  stream << "LTYPE\n";
1511  stream << " 5\n";
1512  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1513  stream << "100\n";
1514  stream << "AcDbSymbolTable\n";
1515  stream << " 70\n";
1516  //stream << QString( "%1\n" ).arg( nLineTypes( slList ) + 1 ); //number of linetypes
1517 
1518  //add continuous style as default
1519  stream << " 0\n";
1520  stream << "LTYPE\n";
1521  stream << " 5\n";
1522  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1523  stream << "100\n";
1524  stream << "AcDbSymbolTableRecord\n";
1525  stream << "100\n";
1526  stream << "AcDbLinetypeTableRecord\n";
1527  stream << " 2\n";
1528  stream << "CONTINUOUS\n";
1529  stream << " 70\n";
1530  stream << "64\n";
1531  stream << " 3\n";
1532  stream << "Defaultstyle\n";
1533  stream << " 72\n";
1534  stream << "65\n";
1535  stream << " 73\n";
1536  stream << "0\n";
1537  stream << " 40\n"; //todo: add segments in group 49
1538  stream << "0.0\n";
1539 
1540  stream << " 0\n";
1541  stream << "LTYPE\n";
1542  stream << " 5\n";
1543  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1544  stream << "100\n";
1545  stream << "AcDbSymbolTableRecord\n";
1546  stream << "100\n";
1547  stream << "AcDbLinetypeTableRecord\n";
1548  stream << " 2\n";
1549  stream << "BYBLOCK\n";
1550  stream << " 70\n";
1551  stream << "64\n";
1552  stream << " 3\n";
1553  stream << "Defaultstyle\n";
1554  stream << " 72\n";
1555  stream << "65\n";
1556  stream << " 73\n";
1557  stream << "0\n";
1558  stream << " 40\n"; //todo: add segments in group 49
1559  stream << "0.0\n";
1560 
1561  stream << " 0\n";
1562  stream << "LTYPE\n";
1563  stream << " 5\n";
1564  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1565  stream << "100\n";
1566  stream << "AcDbSymbolTableRecord\n";
1567  stream << "100\n";
1568  stream << "AcDbLinetypeTableRecord\n";
1569  stream << " 2\n";
1570  stream << "BYLAYER\n";
1571  stream << " 70\n";
1572  stream << "64\n";
1573  stream << " 3\n";
1574  stream << "Defaultstyle\n";
1575  stream << " 72\n";
1576  stream << "65\n";
1577  stream << " 73\n";
1578  stream << "0\n";
1579  stream << " 40\n"; //todo: add segments in group 49
1580  stream << "0.0\n";
1581 
1582  //add symbol layer linestyles
1583  QList<QgsSymbolLayerV2*>::const_iterator slIt = slList.constBegin();
1584  for ( ; slIt != slList.constEnd(); ++slIt )
1585  {
1586  writeSymbolLayerLinestyleAC1018( stream, *slIt );
1587  }
1588 
1589  stream << " 0\n";
1590  stream << "ENDTAB\n";
1591 
1592  //LAYER
1593  stream << " 0\n";
1594  stream << "TABLE\n";
1595  stream << " 2\n";
1596  stream << "LAYER\n";
1597  stream << " 5\n";
1598  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1599  stream << "100\n";
1600  stream << "AcDbSymbolTable\n";
1601  stream << " 70\n";
1602  stream << mLayers.count() << "\n";
1603  QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin();
1604  for ( ; layerIt != mLayers.constEnd(); ++layerIt )
1605  {
1606  stream << " 0\n";
1607  stream << "LAYER\n";
1608  stream << " 5\n";
1609  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1610  stream << "100\n";
1611  stream << "AcDbSymbolTableRecord\n";
1612  stream << "100\n";
1613  stream << "AcDbLayerTableRecord\n";
1614  stream << " 2\n";
1615  if ( *layerIt )
1616  {
1617  stream << ( *layerIt )->name() << "\n";
1618  }
1619  stream << " 70\n"; //layer property
1620  stream << "64\n";
1621  stream << " 62\n"; //layer color
1622  stream << "1\n";
1623  stream << " 6\n"; //layer line type
1624  stream << "CONTINUOUS\n";
1625  }
1626  stream << " 0\n";
1627  stream << "ENDTAB\n";
1628 
1629  //todo: VIEW table
1630 
1631  //todo: UCS table
1632 
1633  //todo: DIMSTYLE table
1634 
1635  //todo: BLOCK_RECORD table
1636 
1637  endSection( );
1638 }
1639 
1640 void QgsDxfExport::writeSymbolLayerLinestyleAC1018( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer )
1641 {
1642  if ( !symbolLayer )
1643  {
1644  return;
1645  }
1646 
1647  //QgsSimpleLineSymbolLayer can have customDashVector() / customDashPatternUnit()
1648  const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( symbolLayer );
1649  if ( simpleLine )
1650  {
1651  if ( simpleLine->useCustomDashPattern() )
1652  {
1654  QString name = QString( "symbolLayer%1" ).arg( mSymbolLayerCounter );
1655  QVector<qreal> dashPattern = simpleLine->customDashVector();
1656  writeLinestyleAC1018( stream, name, dashPattern, simpleLine->customDashPatternUnit() );
1657  mLineStyles.insert( symbolLayer, name );
1658  }
1659  }
1660 }
1661 
1662 void QgsDxfExport::writeLinestyleAC1018( QTextStream& stream, const QString& styleName, const QVector<qreal>& pattern, QgsSymbolV2::OutputUnit u )
1663 {
1664  double length = 0;
1665  QVector<qreal>::const_iterator dashIt = pattern.constBegin();
1666  for ( ; dashIt != pattern.constEnd(); ++dashIt )
1667  {
1668  length += *dashIt;
1669  }
1670 
1671  stream << " 0\n";
1672  stream << "LTYPE\n";
1673  stream << " 5\n";
1674  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1675  stream << "100\n";
1676  stream << "AcDbSymbolTableRecord\n";
1677  stream << "100\n";
1678  stream << "AcDbLinetypeTableRecord\n";
1679  stream << " 2\n";
1680  stream << QString( "%1\n" ).arg( styleName );
1681  stream << " 70\n";
1682  stream << "64\n";
1683  stream << " 3\n";
1684  stream << "\n";
1685  stream << " 72\n";
1686  stream << "65\n";
1687  stream << " 73\n";
1688  stream << QString( "%1\n" ).arg( pattern.size() ); //number of segments
1689  stream << " 40\n"; //total length of segments
1690  stream << QString( "%1\n" ).arg( length );
1691 
1692  dashIt = pattern.constBegin();
1693  bool isSpace = false;
1694  for ( ; dashIt != pattern.constEnd(); ++dashIt )
1695  {
1696  stream << " 49\n";
1697 
1698  //map units or mm?
1699  double segmentLength = ( isSpace ? -*dashIt : *dashIt );
1701  stream << QString( "%1\n" ).arg( segmentLength );
1702  isSpace = !isSpace;
1703  }
1704 }
1705 
1706 void QgsDxfExport::writeEntitiesAC1018( QTextStream& stream )
1707 {
1708  Q_UNUSED( stream );
1709  //todo...
1710 }
1711 
1713 {
1714  Q_UNUSED( stream );
1715  Q_UNUSED( layer );
1716  //todo...
1717 }
1718 
1719 void QgsDxfExport::writePolylineAC1018( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color,
1720  double width, bool polygon )
1721 {
1722  stream << " 0\n";
1723  stream << "LWPOLYLINE\n";
1724  stream << " 5\n";
1725  stream << QString( "%1\n" ).arg( mNextHandleId++ );
1726  stream << " 8\n";
1727  stream << layer << "\n";
1728  stream << "100\n";
1729  stream << "AcDbEntity\n";
1730  stream << "100\n";
1731  stream << "AcDbPolyline\n";
1732 
1733  stream << " 6\n";
1734  stream << QString( "%1\n" ).arg( lineStyleName );
1735 
1736  stream << " 62\n";
1737  stream << color << "\n";
1738 
1739  stream << " 90\n";
1740  stream << QString( "%1\n" ).arg( line.size() );
1741 
1742  stream << " 70\n";
1743  int type = polygon ? 1 : 0;
1744  stream << type << "\n";
1745 
1746  stream << " 43\n";
1747  stream << width << "\n";
1748 
1749  QgsPolyline::const_iterator lineIt = line.constBegin();
1750  for ( ; lineIt != line.constEnd(); ++lineIt )
1751  {
1752  writeVertexAC1018( stream, *lineIt );
1753  }
1754 }
1755 
1756 void QgsDxfExport::writeVertexAC1018( QTextStream& stream, const QgsPoint& pt )
1757 {
1758  stream << " 10\n";
1759  stream << pt.x() << "\n";
1760  stream << " 20\n";
1761  stream << pt.y() << "\n";
1762 }
1763 
void writeCircle(const QString &layer, int color, const QgsPoint &pt, double radius)
static double mapUnitScaleFactor(double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits)
QgsSymbolV2::OutputUnit customDashPatternUnit() const
int mSymbolLayerCounter
Definition: qgsdxfexport.h:109
Wrapper for iterator of features from vector data provider or vector layer.
void writeVertex(const QgsPoint &pt, const QString &layer)
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
QgsRenderContext renderContext() const
static unsigned index
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:48
bool isEmpty() const
test if rectangle is empty.
void writeText(const QString &layer, const QString &text, const QgsPoint &pt, double size, double angle, int color)
virtual Qt::PenStyle dxfPenStyle() const
void writeLinestyle(const QString &styleName, const QVector< qreal > &pattern, QgsSymbolV2::OutputUnit u)
void writeTables()
virtual double dxfWidth(const QgsDxfExport &e, const QgsSymbolV2RenderContext &context) const
QList< QgsSymbolV2 * > QgsSymbolV2List
Definition: qgsrendererv2.h:37
void startSection()
void writeVertexAC1018(QTextStream &stream, const QgsPoint &pt)
void writeGroup(int code, int i)
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:194
void startRender(QgsSymbolV2RenderContext &context)
QgsMultiPolyline asMultiPolyline() const
return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
Definition: qgsgeometry.h:38
static int colorFromSymbolLayer(const QgsSymbolLayerV2 *symbolLayer, const QgsSymbolV2RenderContext &ctx)
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
void writeEntitiesAC1018(QTextStream &stream)
QgsPolygon asPolygon() const
return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list ...
void setRendererScale(double scale)
float minimumScale() const
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QVector< qreal > customDashVector() const
QList< QgsMapLayer * > mLayers
Definition: qgsdxfexport.h:97
double mSymbologyScaleDenominator
Scale for symbology export (used if symbols units are mm)
Definition: qgsdxfexport.h:101
WkbType
Used for symbology operations.
Definition: qgis.h:53
void writeEntitiesSymbolLevelsAC1018(QTextStream &stream, QgsVectorLayer *layer)
void writeSymbolLayerLinestyleAC1018(QTextStream &stream, const QgsSymbolLayerV2 *symbolLayer)
QgsSymbolV2::OutputUnit sizeUnit() const
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:34
virtual QList< QString > usedAttributes()=0
SymbologyExport mSymbologyExport
Definition: qgsdxfexport.h:102
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
void writeEndFile()
QGis::UnitType mMapUnits
Definition: qgsdxfexport.h:103
static int closestColorMatch(QRgb pixel)
void writePoint(const QString &layer, int color, const QgsPoint &pt)
void writePolyline(const QgsPolyline &line, const QString &layer, const QString &lineStyleName, int color, double width=-1, bool polygon=false)
double x() const
Definition: qgspoint.h:110
void writeInt(int i)
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
QgsMultiPolygon asMultiPolygon() const
return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
virtual void stopRender(QgsRenderContext &context)=0
void writeDefaultLinestyles()
void writeString(const QString &s)
const QString & name() const
Get the display name of the layer.
virtual QgsSymbolV2List symbols()=0
for symbol levels
void addFeature(const QgsSymbolV2RenderContext &ctx, const QString &layer, const QgsSymbolLayerV2 *symbolLayer, const QgsSymbolV2 *symbol)
void writeEntitiesSymbolLevels(QgsVectorLayer *layer)
QgsRectangle extent() const
Definition: qgsdxfexport.h:60
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
bool hasScaleBasedVisibility() const
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:196
void writeEntities()
void writeBlocks()
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:199
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
virtual QVector< qreal > dxfCustomDashPattern(QgsSymbolV2::OutputUnit &unit) const
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:128
float maximumScale() const
void writeGroupCode(int code)
double dashSize() const
static bool hasDataDefinedProperties(const QgsSymbolLayerV2 *sl, const QgsSymbolV2 *symbol)
QgsRectangle dxfExtent() const
QgsRectangle mExtent
Extent for export, only intersecting features are exported.
Definition: qgsdxfexport.h:99
void writeLinestyleAC1018(QTextStream &stream, const QString &styleName, const QVector< qreal > &pattern, QgsSymbolV2::OutputUnit u)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QVector< QgsPolygon > QgsMultiPolygon
a collection of QgsPolygons that share a common collection of attributes
Definition: qgsgeometry.h:53
QVector< QgsPoint > QgsMultiPoint
a collection of QgsPoints that share a common collection of attributes
Definition: qgsgeometry.h:47
void writeSolid(const QString &layer, int color, const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, const QgsPoint &pt4)
int symbolLayerCount()
Definition: qgssymbolv2.h:85
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:95
static int color_distance(QRgb p1, int index)
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
QVector< QgsPolyline > QgsPolygon
polygon: first item of the list is outer ring, inner rings (if any) start from second item ...
Definition: qgsgeometry.h:44
void setFeature(const QgsFeature *f)
Definition: qgssymbolv2.h:194
static int nLineTypes(const QList< QPair< QgsSymbolLayerV2 *, QgsSymbolV2 * > > &symbolLayers)
bool hasDataDefinedProperties() const
A class to represent a point geometry.
Definition: qgspoint.h:63
void writeTablesAC1018(QTextStream &stream)
static QRgb createRgbEntry(qreal r, qreal g, qreal b)
virtual QColor dxfColor(const QgsSymbolV2RenderContext &context) const
QString lineStyleFromSymbolLayer(const QgsSymbolLayerV2 *symbolLayer)
virtual bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, const QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
QList< QgsSymbolV2LevelItem > QgsSymbolV2Level
Definition: qgsrendererv2.h:63
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:316
int renderingPass() const
QVector< QgsPolyline > QgsMultiPolyline
a collection of QgsPolylines that share a common collection of attributes
Definition: qgsgeometry.h:50
bool layerIsScaleBasedVisible(const QgsMapLayer *layer) const
void writeSymbolLayerLinestyle(const QgsSymbolLayerV2 *symbolLayer)
static QString dxfLayerName(const QString &name)
QgsPolyline asPolyline() const
return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list ...
void writePolylineAC1018(QTextStream &stream, const QgsPolyline &line, const QString &layer, const QString &lineStyleName, int color, double width=-1, bool polygon=false)
Contains information about the context of a rendering operation.
double dotSize() const
double sizeToMapUnits(double s) const
void writeHeader()
int writeToFile(QIODevice *d)
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat)
return list of symbols used for rendering the feature.
QgsMultiPoint asMultiPoint() const
return contents of the geometry as a multi point if wkbType is WKBMultiPoint, otherwise an empty list...
QgsSymbolV2 * symbol()
Definition: qgsrendererv2.h:55
bool usingSymbolLevels() const
void writeDouble(double d)
static double fromUnitToUnitFactor(QGis::UnitType fromUnit, QGis::UnitType toUnit)
Returns the conversion factor between the specified units.
Definition: qgis.cpp:123
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, int color, double width=-1)
QTextStream mTextStream
Definition: qgsdxfexport.h:105
UnitType
Map units that qgis supports.
Definition: qgis.h:229
QList< QgsSymbolV2Level > QgsSymbolV2LevelOrder
Definition: qgsrendererv2.h:66
double y() const
Definition: qgspoint.h:118
QList< QPair< QgsSymbolLayerV2 *, QgsSymbolV2 * > > symbolLayers()
QHash< const QgsSymbolLayerV2 *, QString > mPointSymbolBlocks
Definition: qgsdxfexport.h:114
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsSymbolLayerV2 * symbolLayer(int layer)
virtual int capabilities()
returns bitwise OR-ed capabilities of the renderer
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
static double mDxfColors[][3]
Definition: qgsdxfexport.h:107
QgsPoint asPoint() const
return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:77
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature)=0
to be overridden
double dashSeparatorSize() const
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
static QString lineNameFromPenStyle(Qt::PenStyle style)
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:189
virtual void stopRender(QgsSymbolV2RenderContext &context)=0
QHash< const QgsSymbolLayerV2 *, QString > mLineStyles
Definition: qgsdxfexport.h:113
QgsFeatureRequest & setFilterRect(const QgsRectangle &rect)
Set rectangle from which features will be taken.
QgsDxfExport & operator=(const QgsDxfExport &dxfExport)
void writeHeaderAC1018(QTextStream &stream)
int renderHints() const
Definition: qgssymbolv2.h:135