42 #define DXF_HANDSEED 100
43 #define DXF_HANDMAX 9999999
44 #define DXF_HANDPLOTSTYLE 0xf
47 int QgsDxfExport::mDxfColors[][3] =
307 const char *QgsDxfExport::mDxfEncodings[][2] =
310 {
"8859_1",
"ISO-8859-1" },
311 {
"8859_2",
"ISO-8859-2" },
312 {
"8859_3",
"ISO-8859-3" },
313 {
"8859_4",
"ISO-8859-4" },
314 {
"8859_5",
"ISO-8859-5" },
315 {
"8859_6",
"ISO-8859-6" },
316 {
"8859_7",
"ISO-8859-7" },
317 {
"8859_8",
"ISO-8859-8" },
318 {
"8859_9",
"ISO-8859-9" },
320 {
"DOS850",
"CP850" },
331 {
"MACINTOSH",
"MacRoman" },
333 {
"KSC5601",
"ksc5601.1987-0" },
335 {
"DOS866",
"CP866" },
336 {
"ANSI_1250",
"CP1250" },
337 {
"ANSI_1251",
"CP1251" },
338 {
"ANSI_1252",
"CP1252" },
339 {
"GB2312",
"GB2312" },
340 {
"ANSI_1253",
"CP1253" },
341 {
"ANSI_1254",
"CP1254" },
342 {
"ANSI_1255",
"CP1255" },
343 {
"ANSI_1256",
"CP1256" },
344 {
"ANSI_1257",
"CP1257" },
345 {
"ANSI_874",
"CP874" },
346 {
"ANSI_932",
"Shift_JIS" },
347 {
"ANSI_936",
"CP936" },
348 {
"ANSI_949",
"cp949" },
349 {
"ANSI_950",
"CP950" },
352 {
"ANSI_1258",
"CP1258" },
356 : mSymbologyScaleDenominator( 1.0 )
357 , mSymbologyExport( NoSymbology )
358 , mMapUnits(
QGis::Meters )
359 , mSymbolLayerCounter( 0 )
374 mLayers = dxfExport.mLayers;
375 mSymbologyScaleDenominator = dxfExport.mSymbologyScaleDenominator;
376 mSymbologyExport = dxfExport.mSymbologyExport;
377 mMapUnits = dxfExport.mMapUnits;
378 mSymbolLayerCounter = 0;
422 int minDist = INT_MAX;
424 for (
int i = 1; i < ( int )(
sizeof( mDxfColors ) /
sizeof( *mDxfColors ) ) && minDist > 0; ++i )
426 int dist = color_distance( color.rgba(), i );
427 if ( dist >= minDist )
434 if ( minDist == 0 && color.alpha() == 255 && minDistAt != 7 )
441 int c = ( color.red() & 0xff ) * 0x10000 + ( color.green() & 0xff ) * 0x100 + ( color.blue() & 0xff );
443 if ( transparencyCode != -1 && color.alpha() < 255 )
444 writeGroup( transparencyCode, 0x2000000 | color.alpha() );
449 mTextStream << QString(
"%1\n" ).arg( code, 3, 10, QChar(
' ' ) );
454 mTextStream << QString(
"%1\n" ).arg( i, 6, 10, QChar(
' ' ) );
460 if ( !s.contains(
"." ) )
462 mTextStream << s <<
"\n";
467 mTextStream << s <<
"\n";
477 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly ) )
482 mTextStream.setDevice( d );
483 mTextStream.setCodec( encoding.toLocal8Bit() );
494 void QgsDxfExport::writeHeader( QString codepage )
506 if ( !ext.isEmpty() )
545 handle = mNextHandleId++;
547 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
549 writeGroup( code, QString(
"%1" ).arg( handle, 0, 16 ) );
553 void QgsDxfExport::writeTables()
559 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > slList;
562 slList = symbolLayers();
573 writeDefaultLinetypes();
576 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = slList.constBegin();
577 for ( ; slIt != slList.constEnd(); ++slIt )
579 writeSymbolLayerLinetype( slIt->first );
610 slIt = slList.constBegin();
611 for ( ; slIt != slList.constEnd(); ++slIt )
617 if ( hasDataDefinedProperties( ml, slIt->second ) )
624 writeGroup( 2, QString(
"symbolLayer%1" ).arg( i++ ) );
716 QList< QPair<QgsVectorLayer*, int> >::const_iterator layerIt = mLayers.constBegin();
717 QSet<QString> layerNames;
718 for ( ; layerIt != mLayers.constEnd(); ++layerIt )
720 if ( !layerIsScaleBasedVisible( layerIt->first ) )
723 if ( layerIt->first )
725 if ( layerIt->second < 0 )
731 QList<QVariant> values;
732 layerIt->first->uniqueValues( layerIt->second, values );
733 foreach ( QVariant v, values )
759 foreach ( QString
layerName, layerNames )
784 writeGroup( 100,
"AcDbTextStyleTableRecord" );
800 void QgsDxfExport::writeBlocks()
854 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > slList;
857 slList = symbolLayers();
860 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > >::const_iterator slIt = slList.constBegin();
861 for ( ; slIt != slList.constEnd(); ++slIt )
873 if ( hasDataDefinedProperties( ml, slIt->second ) )
885 QString blockName = QString(
"symbolLayer%1" ).arg( mBlockCounter++ );
905 mPointSymbolBlocks.insert( ml, blockName );
911 void QgsDxfExport::writeEntities()
917 QgsDxfPalLabeling labelEngine(
this, mExtent.
isEmpty() ? dxfExtent() : mExtent, mSymbologyScaleDenominator, mMapUnits );
921 QList< QPair< QgsVectorLayer*, int > >::iterator layerIt = mLayers.begin();
922 for ( ; layerIt != mLayers.end(); ++layerIt )
925 if ( !vl || !layerIsScaleBasedVisible( vl ) )
942 if ( !attributes.contains( layerAttr ) )
943 attributes << layerAttr;
946 bool labelLayer = labelEngine.prepareLayer( vl, attributes, ctx ) != 0;
952 writeEntitiesSymbolLevels( vl );
969 sctx.setFeature( &fet );
977 if ( symbolList.size() < 1 )
984 QgsSymbolV2List::iterator symbolIt = symbolList.begin();
985 for ( ; symbolIt != symbolList.end(); ++symbolIt )
987 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
988 for (
int i = 0; i < nSymbolLayers; ++i )
990 addFeature( sctx,
layerName, ( *symbolIt )->symbolLayer( i ), *symbolIt );
1007 labelEngine.registerFeature( vl->
id(), fet, ctx,
layerName );
1015 labelEngine.drawLabeling( ctx );
1019 void QgsDxfExport::writeEntitiesSymbolLevels(
QgsVectorLayer* layer )
1032 QHash< QgsSymbolV2*, QList<QgsFeature> > features;
1057 if ( !featureSymbol )
1062 QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
1063 if ( it == features.end() )
1065 it = features.insert( featureSymbol, QList<QgsFeature>() );
1067 it.value().append( fet );
1073 for (
int i = 0; i < symbols.count(); i++ )
1079 if ( level < 0 || level >= 1000 )
1082 while ( level >= levels.count() )
1084 levels[level].append( item );
1089 for (
int l = 0; l < levels.count(); l++ )
1092 for (
int i = 0; i < level.count(); i++ )
1095 QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
1096 if ( levelIt == features.end() )
1098 QgsDebugMsg( QString(
"No feature found for symbol on %1 %2.%3" ).arg( layer->
id() ).arg( l ).arg( i ) );
1102 int llayer = item.
layer();
1103 QList<QgsFeature>& featureList = levelIt.value();
1104 QList<QgsFeature>::iterator featureIt = featureList.begin();
1105 for ( ; featureIt != featureList.end(); ++featureIt )
1107 sctx.setFeature( &*featureIt );
1108 addFeature( sctx, layer->
name(), levelIt.key()->symbolLayer( llayer ), levelIt.key() );
1115 void QgsDxfExport::writeEndFile()
1142 ACAD_MLEADERSTYLE\n\
1150 ACAD_PLOTSETTINGS\n\
1154 ACAD_PLOTSTYLENAME\n\
1262 ACDBDICTIONARYWDFLT\n\
1282 AcDbDictionaryWithDefault\n\
1478 1.000000000000000E+20\n\
1480 1.000000000000000E+20\n\
1482 1.000000000000000E+20\n\
1484 -1.000000000000000E+20\n\
1486 -1.000000000000000E+20\n\
1488 -1.000000000000000E+20\n\
1750 163.1318914119703\n\
1918 AcDbSavedByObjectVersion\n\
2008 AcDbSavedByObjectVersion\n\
2098 AcDbSavedByObjectVersion\n\
2188 AcDbSavedByObjectVersion\n\
2278 AcDbSavedByObjectVersion\n\
2370 AcDbSavedByObjectVersion\n\
2460 AcDbSavedByObjectVersion\n\
2550 AcDbSavedByObjectVersion\n\
2640 AcDbSavedByObjectVersion\n\
2730 AcDbSavedByObjectVersion\n\
2820 AcDbSavedByObjectVersion\n\
2910 AcDbSavedByObjectVersion\n\
3000 AcDbSavedByObjectVersion\n\
3090 AcDbSavedByObjectVersion\n\
3182 AcDbSavedByObjectVersion\n\
3272 AcDbSavedByObjectVersion\n\
3282 void QgsDxfExport::startSection()
3287 void QgsDxfExport::endSection()
3300 msl->
sizeUnit(), mMapUnits ) / 2.0;
3312 QHash< const QgsSymbolLayerV2*, QString >::const_iterator blockIt = mPointSymbolBlocks.find( symbolLayer );
3313 if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() )
3317 if ( msl && symbol )
3342 double width,
bool polygon )
3357 QgsPolyline::const_iterator lineIt = line.constBegin();
3358 for ( ; lineIt != line.constEnd(); ++lineIt )
3382 for (
int i = 0; i < polygon.size(); ++i )
3389 for (
int j = 0; j < polygon[i].size(); ++j )
3408 writePolyline( line, layer, lineStyleName, color, width,
false );
3501 if ( !mTextStream.codec()->canEncode( text ) )
3517 while ( t.length() > 250 )
3550 void QgsDxfExport::writeVertex(
const QgsPoint& pt,
const QString& layer )
3564 QList< QPair<QgsVectorLayer*, int> >::const_iterator layerIt = mLayers.constBegin();
3565 for ( ; layerIt != mLayers.constEnd(); ++layerIt )
3567 if ( layerIt->first )
3571 extent = layerIt->first->extent();
3599 penColor = colorFromSymbolLayer( symbolLayer, ctx );
3603 Qt::PenStyle penStyle( Qt::SolidLine );
3604 Qt::BrushStyle brushStyle( Qt::NoBrush );
3606 double offset = 0.0;
3607 if ( mSymbologyExport !=
NoSymbology && symbolLayer )
3609 width = symbolLayer->
dxfWidth( *
this, ctx );
3610 offset = symbolLayer->
dxfOffset( *
this, ctx );
3618 QString lineStyleName =
"CONTINUOUS";
3621 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
3635 QgsMultiPoint::const_iterator it = multiPoint.constBegin();
3636 for ( ; it != multiPoint.constEnd(); ++it )
3638 writePoint( *it, layer, penColor, fet, symbolLayer, symbol );
3644 if ( penStyle != Qt::NoPen )
3655 if ( offsetLine != geom )
3662 QgsGeometry *offsetLine = offset == 0.0 ? geom : geom->
offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 );
3667 QgsMultiPolyline::const_iterator lIt = multiLine.constBegin();
3668 for ( ; lIt != multiLine.constEnd(); ++lIt )
3670 writePolyline( *lIt, layer, lineStyleName, penColor, width,
false );
3673 if ( offsetLine != geom )
3680 QgsGeometry *offsetPolygon = offset == 0.0 ? geom : geom->
buffer( -offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 );
3681 if ( !offsetPolygon )
3682 offsetPolygon = geom;
3685 QgsPolygon::const_iterator polyIt = polygon.constBegin();
3686 for ( ; polyIt != polygon.constEnd(); ++polyIt )
3688 writePolyline( *polyIt, layer, lineStyleName, penColor, width,
false );
3691 if ( offsetPolygon != geom )
3692 delete offsetPolygon;
3698 QgsGeometry *offsetPolygon = offset == 0.0 ? geom : geom->
buffer( -offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 );
3699 if ( !offsetPolygon )
3700 offsetPolygon = geom;
3703 QgsMultiPolygon::const_iterator mpIt = mp.constBegin();
3704 for ( ; mpIt != mp.constEnd(); ++mpIt )
3706 QgsPolygon::const_iterator polyIt = mpIt->constBegin();
3707 for ( ; polyIt != mpIt->constEnd(); ++polyIt )
3709 writePolyline( *polyIt, layer, lineStyleName, penColor, width,
true );
3713 if ( offsetPolygon != geom )
3714 delete offsetPolygon;
3718 if ( brushStyle != Qt::NoBrush )
3731 QgsMultiPolygon::const_iterator mpIt = mp.constBegin();
3732 for ( ; mpIt != mp.constEnd(); ++mpIt )
3745 return symbolLayer->
dxfColor( ctx );
3748 QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayerV2* symbolLayer )
3750 QString lineStyleName =
"CONTINUOUS";
3753 return lineStyleName;
3756 QHash< const QgsSymbolLayerV2*, QString >::const_iterator lineTypeIt = mLineStyles.find( symbolLayer );
3757 if ( lineTypeIt != mLineStyles.constEnd() )
3759 lineStyleName = lineTypeIt.value();
3760 return lineStyleName;
3764 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
3771 int current_distance = INT_MAX;
3772 for (
size_t i = 1; i <
sizeof( mDxfColors ) /
sizeof( *mDxfColors ); ++i )
3774 int dist = color_distance( pixel, i );
3775 if ( dist < current_distance )
3777 current_distance = dist;
3786 int QgsDxfExport::color_distance( QRgb p1,
int index )
3788 if ( index > 255 || index < 0 )
3793 double redDiff = qRed( p1 ) - mDxfColors[
index][0];
3794 double greenDiff = qGreen( p1 ) - mDxfColors[
index][1];
3795 double blueDiff = qBlue( p1 ) - mDxfColors[
index][2];
3797 QgsDebugMsg( QString(
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8" )
3798 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
3800 .arg( mDxfColors[index][0] )
3801 .arg( mDxfColors[index][1] )
3802 .arg( mDxfColors[index][2] )
3803 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ) );
3805 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
3808 QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
3810 return QColor::fromRgbF( r, g, b ).rgb();
3830 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > QgsDxfExport::symbolLayers()
3832 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > symbolLayers;
3834 QList< QPair< QgsVectorLayer*, int> >::iterator lIt = mLayers.begin();
3835 for ( ; lIt != mLayers.end(); ++lIt )
3853 QgsSymbolV2List::iterator symbolIt = symbols.begin();
3854 for ( ; symbolIt != symbols.end(); ++symbolIt )
3856 int maxSymbolLayers = ( *symbolIt )->symbolLayerCount();
3859 maxSymbolLayers = 1;
3861 for (
int i = 0; i < maxSymbolLayers; ++i )
3863 symbolLayers.append( qMakePair(( *symbolIt )->symbolLayer( i ), *symbolIt ) );
3868 return symbolLayers;
3871 void QgsDxfExport::writeDefaultLinetypes()
3874 foreach ( QString ltype, QStringList() <<
"ByLayer" <<
"ByBlock" <<
"CONTINUOUS" )
3879 writeGroup( 100,
"AcDbLinetypeTableRecord" );
3888 double das = dashSize();
3889 double dss = dashSeparatorSize();
3890 double dos = dotSize();
3892 QVector<qreal> dashVector( 2 );
3893 dashVector[0] = das;
3894 dashVector[1] = dss;
3897 QVector<qreal> dotVector( 2 );
3902 QVector<qreal> dashDotVector( 4 );
3903 dashDotVector[0] = das;
3904 dashDotVector[1] = dss;
3905 dashDotVector[2] = dos;
3906 dashDotVector[3] = dss;
3909 QVector<qreal> dashDotDotVector( 6 );
3910 dashDotDotVector[0] = das;
3911 dashDotDotVector[1] = dss;
3912 dashDotDotVector[2] = dos;
3913 dashDotDotVector[3] = dss;
3914 dashDotDotVector[4] = dos;
3915 dashDotDotVector[5] = dss;
3919 void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayerV2* symbolLayer )
3928 if ( customLinestyle.size() > 0 )
3930 QString name = QString(
"symbolLayer%1" ).arg( mSymbolLayerCounter++ );
3931 writeLinetype( name, customLinestyle, unit );
3932 mLineStyles.insert( symbolLayer, name );
3936 int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > >& symbolLayers )
3939 QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = symbolLayers.constBegin();
3940 for ( ; slIt != symbolLayers.constEnd(); ++slIt )
3954 void QgsDxfExport::writeLinetype(
const QString& styleName,
const QVector<qreal>& pattern,
QgsSymbolV2::OutputUnit u )
3957 QVector<qreal>::const_iterator dashIt = pattern.constBegin();
3958 for ( ; dashIt != pattern.constEnd(); ++dashIt )
3960 length += ( *dashIt *
mapUnitScaleFactor( mSymbologyScaleDenominator, u, mMapUnits ) );
3967 writeGroup( 100,
"AcDbLinetypeTableRecord" );
3975 dashIt = pattern.constBegin();
3977 for ( ; dashIt != pattern.constEnd(); ++dashIt )
3980 double segmentLength = ( isGap ? -*dashIt : *dashIt );
3990 if ( !sl || !symbol )
4004 double QgsDxfExport::dashSize()
const
4006 double size = mSymbologyScaleDenominator * 0.002;
4007 return sizeToMapUnits( size );
4010 double QgsDxfExport::dotSize()
const
4012 double size = mSymbologyScaleDenominator * 0.0006;
4013 return sizeToMapUnits( size );
4016 double QgsDxfExport::dashSeparatorSize()
const
4018 double size = mSymbologyScaleDenominator * 0.0006;
4019 return sizeToMapUnits( size );
4022 double QgsDxfExport::sizeToMapUnits(
double s )
const
4028 QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
4036 case Qt::DashDotLine:
4038 case Qt::DashDotDotLine:
4039 return "DASHDOTDOT";
4042 return "CONTINUOUS";
4048 if ( name.isEmpty() )
4057 layerName.replace(
"<",
"_" );
4058 layerName.replace(
">",
"_" );
4059 layerName.replace(
"/",
"_" );
4060 layerName.replace(
"\\",
"_" );
4061 layerName.replace(
"\"",
"_" );
4062 layerName.replace(
":",
"_" );
4063 layerName.replace(
";",
"_" );
4064 layerName.replace(
"?",
"_" );
4065 layerName.replace(
"*",
"_" );
4066 layerName.replace(
"|",
"_" );
4067 layerName.replace(
"=",
"_" );
4068 layerName.replace(
"\'",
"_" );
4073 bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer* layer )
const
4081 return layer->
minimumScale() < mSymbologyScaleDenominator &&
4087 QList< QPair<QgsVectorLayer*, int> >::const_iterator layerIt = mLayers.constBegin();
4088 for ( ; layerIt != mLayers.constEnd(); ++layerIt )
4090 if ( layerIt->first && layerIt->first->id() == id )
4091 return dxfLayerName( layerIt->second < 0 ? layerIt->first->name() : f.
attribute( layerIt->second ).toString() );
4099 foreach ( QByteArray codec, QTextCodec::availableCodecs() )
4101 if ( name != codec )
4105 for ( i = 0; i < ( int )(
sizeof( mDxfEncodings ) /
sizeof( *mDxfEncodings ) ) && name != mDxfEncodings[i][1]; ++i )
4108 if ( i == (
int )(
sizeof( mDxfEncodings ) /
sizeof( *mDxfEncodings ) ) )
4111 return mDxfEncodings[i][0];
4114 return QString::null;
4120 foreach ( QByteArray codec, QTextCodec::availableCodecs() )
4123 for ( i = 0; i < ( int )(
sizeof( mDxfEncodings ) /
sizeof( *mDxfEncodings ) ) && strcmp( codec.data(), mDxfEncodings[i][1] ) != 0; ++i )
4126 if ( i < (
int )(
sizeof( mDxfEncodings ) /
sizeof( *mDxfEncodings ) ) )
4127 encodings << codec.data();