72 mMapSettings = settings;
87 QList<QgsMapLayer *> layerList;
89 mLayerNameAttribute.clear();
91 for (
const DxfLayer &dxfLayer : layers )
93 layerList << dxfLayer.layer();
94 if ( dxfLayer.layerOutputAttributeIndex() >= 0 )
95 mLayerNameAttribute.insert( dxfLayer.layer()->id(), dxfLayer.layerOutputAttributeIndex() );
123 if ( !mForce2d && p.
is3D() && std::isfinite( p.
z() ) )
130 int minDist = std::numeric_limits<int>::max();
132 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ) && minDist > 0; ++i )
134 int dist = color_distance( color.rgba(), i );
135 if ( dist >= minDist )
142 if ( minDist == 0 && minDistAt != 7 )
146 if ( color.alpha() == 255 )
150 int c = ( color.red() & 0xff ) * 0x10000 + ( color.green() & 0xff ) * 0x100 + ( color.blue() & 0xff );
152 if ( transparencyCode != -1 && color.alpha() < 255 )
153 writeGroup( transparencyCode, 0x2000000 | color.alpha() );
158 mTextStream << QStringLiteral(
"%1\n" ).arg( code, 3, 10, QChar(
' ' ) );
163 mTextStream << QStringLiteral(
"%1\n" ).arg( i, 6, 10, QChar(
' ' ) );
169 if ( !s.contains(
'.' ) )
170 s += QLatin1String(
".0" );
171 mTextStream << s <<
'\n';
176 mTextStream << s <<
'\n';
186 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
191 mTextStream.setDevice( d );
192 mTextStream.setCodec( encoding.toLocal8Bit() );
199 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
214 mExtent = layerExtent;
250 void QgsDxfExport::writeHeader(
const QString &codepage )
252 writeGroup( 999, QStringLiteral(
"DXF created from QGIS" ) );
258 writeGroup( 9, QStringLiteral(
"$ACADVER" ) );
270 writeGroup( 9, QStringLiteral(
"$LTSCALE" ) );
282 writeGroup( 9, QStringLiteral(
"$PSLTSCALE" ) );
285 writeGroup( 9, QStringLiteral(
"$HANDSEED" ) );
288 writeGroup( 9, QStringLiteral(
"$DWGCODEPAGE" ) );
297 handle = mNextHandleId++;
299 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
301 writeGroup( code, QString::number( handle, 16 ) );
305 void QgsDxfExport::writeTables()
312 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
315 slList = symbolLayers( context );
323 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
326 writeDefaultLinetypes();
329 for (
const auto &symbolLayer : qgis::as_const( slList ) )
331 writeSymbolLayerLinetype( symbolLayer.first );
338 writeGroup( 2, QStringLiteral(
"BLOCK_RECORD" ) );
341 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
344 const QStringList blockStrings = QStringList() << QStringLiteral(
"*Model_Space" ) << QStringLiteral(
"*Paper_Space" ) << QStringLiteral(
"*Paper_Space0" );
345 for (
const QString &block : blockStrings )
347 writeGroup( 0, QStringLiteral(
"BLOCK_RECORD" ) );
349 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
350 writeGroup( 100, QStringLiteral(
"AcDbBlockTableRecord" ) );
355 for (
const auto &symbolLayer : qgis::as_const( slList ) )
361 if ( hasDataDefinedProperties( ml, symbolLayer.second ) )
364 QString name = QStringLiteral(
"symbolLayer%1" ).arg( i++ );
365 writeGroup( 0, QStringLiteral(
"BLOCK_RECORD" ) );
367 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
368 writeGroup( 100, QStringLiteral(
"AcDbBlockTableRecord" ) );
378 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
382 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
383 writeGroup( 100, QStringLiteral(
"AcDbRegAppTableRecord" ) );
392 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
400 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
408 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
412 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
413 writeGroup( 100, QStringLiteral(
"AcDbViewportTableRecord" ) );
452 writeGroup( 2, QStringLiteral(
"DIMSTYLE" ) );
454 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
455 writeGroup( 100, QStringLiteral(
"AcDbDimStyleTable" ) );
459 QSet<QString> layerNames;
460 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
463 if ( !layerIsScaleBasedVisible( ml ) )
470 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
477 const QSet<QVariant> values = vl->
uniqueValues( attrIdx );
478 for (
const QVariant &v : values )
490 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
495 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
496 writeGroup( 100, QStringLiteral(
"AcDbLayerTableRecord" ) );
500 writeGroup( 6, QStringLiteral(
"CONTINUOUS" ) );
503 for (
const QString &
layerName : qgis::as_const( layerNames ) )
507 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
508 writeGroup( 100, QStringLiteral(
"AcDbLayerTableRecord" ) );
512 writeGroup( 6, QStringLiteral(
"CONTINUOUS" ) );
521 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
527 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
528 writeGroup( 100, QStringLiteral(
"AcDbTextStyleTableRecord" ) );
529 writeGroup( 2, QStringLiteral(
"STANDARD" ) );
536 writeGroup( 3, QStringLiteral(
"romans.shx" ) );
544 void QgsDxfExport::writeBlocks()
549 static const QStringList blockStrings = QStringList() << QStringLiteral(
"*Model_Space" ) << QStringLiteral(
"*Paper_Space" ) << QStringLiteral(
"*Paper_Space0" );
550 for (
const QString &block : blockStrings )
554 writeGroup( 330, QString::number( mBlockHandles[ block ], 16 ) );
555 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
557 writeGroup( 100, QStringLiteral(
"AcDbBlockBegin" ) );
565 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
567 writeGroup( 100, QStringLiteral(
"AcDbBlockEnd" ) );
573 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
576 slList = symbolLayers( ct );
579 for (
const auto &symbolLayer : qgis::as_const( slList ) )
589 if ( hasDataDefinedProperties( ml, symbolLayer.second ) )
594 QString block( QStringLiteral(
"symbolLayer%1" ).arg( mBlockCounter++ ) );
595 mBlockHandle = QString::number( mBlockHandles[ block ], 16 );
600 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
602 writeGroup( 100, QStringLiteral(
"AcDbBlockBegin" ) );
615 ml->
writeDxf( *
this,
mapUnitScaleFactor( mSymbologyScale, ml->
sizeUnit(), mMapUnits, ctx.renderContext().mapToPixel().mapUnitsPerPixel() ), QStringLiteral(
"0" ), ctx );
619 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
621 writeGroup( 100, QStringLiteral(
"AcDbBlockEnd" ) );
623 mPointSymbolBlocks.insert( ml, block );
629 void QgsDxfExport::writeEntities()
632 writeGroup( 2, QStringLiteral(
"ENTITIES" ) );
634 mBlockHandle = QString::number( mBlockHandles[ QStringLiteral(
"*Model_Space" )], 16 );
643 job->renderer->usingSymbolLevels() )
645 writeEntitiesSymbolLevels( job );
661 QString lName(
dxfLayerName( job->splitLayerAttribute.isNull() ? job->layerTitle : fet.
attribute( job->splitLayerAttribute ).toString() ) );
663 sctx.setFeature( &fet );
665 if ( !job->renderer->willRenderFeature( fet, mRenderContext ) )
670 addFeature( sctx, ct, lName,
nullptr,
nullptr );
674 const QgsSymbolList symbolList = job->renderer->symbolsForFeature( fet, mRenderContext );
675 bool hasSymbology = symbolList.size() > 0;
687 bool isGeometryGenerator = ( symbolLayer->layerType() == QLatin1String(
"GeometryGenerator" ) );
688 if ( isGeometryGenerator )
690 addGeometryGeneratorSymbolLayer( sctx, ct, lName, symbolLayer,
true );
694 addFeature( sctx, ct, lName, symbolLayer, symbol );
699 else if ( hasSymbology )
710 addGeometryGeneratorSymbolLayer( sctx, ct, lName, s->
symbolLayer( 0 ),
false );
714 addFeature( sctx, ct, lName, s->
symbolLayer( 0 ), s );
718 if ( job->labelProvider )
720 job->labelProvider->registerFeature( fet, mRenderContext );
725 else if ( job->ruleBasedLabelProvider )
727 job->ruleBasedLabelProvider->registerFeature( fet, mRenderContext );
736 QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
737 image.setDotsPerMeterX( 96 / 25.4 * 1000 );
738 image.setDotsPerMeterY( 96 / 25.4 * 1000 );
739 QPainter painter( &image );
747 void QgsDxfExport::prepareRenderers()
749 Q_ASSERT( mJobs.empty() );
757 mExtent.
height() * mFactor, 0 ) );
762 mLabelingEngine = qgis::make_unique<QgsDefaultLabelingEngine>();
763 mLabelingEngine->setMapSettings( mMapSettings );
766 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
776 if ( !layerIsScaleBasedVisible( vl ) )
779 QString splitLayerAttribute;
780 int splitLayerAttributeIndex = mLayerNameAttribute.value( vl->
id(), -1 );
782 if ( splitLayerAttributeIndex >= 0 && splitLayerAttributeIndex < fields.
size() )
783 splitLayerAttribute = fields.
at( splitLayerAttributeIndex ).
name();
789 void QgsDxfExport::writeEntitiesSymbolLevels(
DxfLayerJob *job )
791 QHash< QgsSymbol *, QList<QgsFeature> > features;
813 featureSymbol = job->
renderer->symbolForFeature( fet, ctx );
814 if ( !featureSymbol )
819 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
820 if ( it == features.end() )
822 it = features.insert( featureSymbol, QList<QgsFeature>() );
824 it.value().append( fet );
832 for (
int j = 0; j < symbol->symbolLayerCount(); j++ )
834 int level = symbol->symbolLayer( j )->renderingPass();
835 if ( level < 0 || level >= 1000 )
838 while ( level >= levels.count() )
840 levels[level].append( item );
849 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
850 if ( levelIt == features.end() )
855 int llayer = item.layer();
856 const QList<QgsFeature> &featureList = levelIt.value();
857 for (
const QgsFeature &feature : featureList )
859 sctx.setFeature( &feature );
860 addFeature( sctx, ct, job->
layerName, levelIt.key()->symbolLayer( llayer ), levelIt.key() );
866 void QgsDxfExport::stopRenderers()
872 void QgsDxfExport::writeEndFile()
879 void QgsDxfExport::startSection()
884 void QgsDxfExport::endSection()
909 QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
910 if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() )
928 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
929 writeGroup( 100, QStringLiteral(
"AcDbBlockReference" ) );
942 QgsDebugMsg( QStringLiteral(
"writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
948 QgsDebugMsg( QStringLiteral(
"writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
952 if ( mForce2d || !line.at( 0 ).is3D() )
954 bool polygon = line[0] == line[ line.size() - 1 ];
958 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
961 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
962 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
970 for (
int i = 0; i < n; i++ )
975 writeGroup( 0, QStringLiteral(
"POLYLINE" ) );
978 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
982 writeGroup( 100, QStringLiteral(
"AcDb3dPolyline" ) );
986 for (
int i = 0; i < n; i++ )
991 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
994 writeGroup( 100, QStringLiteral(
"AcDbVertex" ) );
995 writeGroup( 100, QStringLiteral(
"AcDb3dPolylineVertex" ) );
1003 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1009 void QgsDxfExport::appendCurve(
const QgsCurve &
c, QVector<QgsPoint> &points, QVector<double> &bulges )
1014 appendLineString( *
dynamic_cast<const QgsLineString *
>( &
c ), points, bulges );
1018 appendCircularString( *
dynamic_cast<const QgsCircularString *
>( &
c ), points, bulges );
1022 appendCompoundCurve( *
dynamic_cast<const QgsCompoundCurve *
>( &
c ), points, bulges );
1026 QgsDebugMsg( QStringLiteral(
"Unexpected curve type %1" ).arg(
c.wktTypeStr() ) );
1031 void QgsDxfExport::appendLineString(
const QgsLineString &ls, QVector<QgsPoint> &points, QVector<double> &bulges )
1033 for (
int i = 0; i < ls.
numPoints(); i++ )
1036 if ( !points.isEmpty() && points.last() == p )
1044 void QgsDxfExport::appendCircularString(
const QgsCircularString &cs, QVector<QgsPoint> &points, QVector<double> &bulges )
1046 for (
int i = 0; i < cs.
numPoints() - 2; i += 2 )
1052 if ( points.isEmpty() || points.last() != p1 )
1054 else if ( !bulges.isEmpty() )
1055 bulges.removeLast();
1057 double a = ( M_PI - ( p1 - p2 ).
angle() + ( p3 - p2 ).
angle() ) / 2.0;
1058 bulges << sin( a ) / cos( a );
1065 void QgsDxfExport::appendCompoundCurve(
const QgsCompoundCurve &cc, QVector<QgsPoint> &points, QVector<double> &bulges )
1067 for (
int i = 0; i < cc.
nCurves(); i++ )
1071 appendCurve( *
c, points, bulges );
1080 QgsDebugMsg( QStringLiteral(
"writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1086 QgsDebugMsg( QStringLiteral(
"writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1090 QVector<QgsPoint> points;
1091 QVector<double> bulges;
1092 appendCurve( curve, points, bulges );
1094 if ( mForce2d || !curve.
is3D() )
1096 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1099 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1100 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1105 QgsDxfExport::DxfPolylineFlags polylineFlags;
1107 polylineFlags.setFlag( QgsDxfExport::DxfPolylineFlag::Closed );
1109 polylineFlags.setFlag( QgsDxfExport::DxfPolylineFlag::Curve );
1113 polylineFlags.setFlag( QgsDxfExport::DxfPolylineFlag::ContinuousPattern );
1115 writeGroup( 70,
static_cast<int>( polylineFlags ) );
1118 for (
int i = 0; i < points.size(); i++ )
1121 if ( bulges[i] != 0.0 )
1127 writeGroup( 0, QStringLiteral(
"POLYLINE" ) );
1130 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1134 writeGroup( 100, QStringLiteral(
"AcDb3dPolyline" ) );
1138 for (
int i = 0; i < points.size(); i++ )
1143 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1146 writeGroup( 100, QStringLiteral(
"AcDbVertex" ) );
1147 writeGroup( 100, QStringLiteral(
"AcDb3dPolylineVertex" ) );
1149 if ( bulges[i] != 0.0 )
1157 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1168 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1171 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1177 writeGroup( 70, hatchPattern == QLatin1String(
"SOLID" ) );
1181 for (
int i = 0; i < polygon.size(); ++i )
1188 for (
int j = 0; j < polygon[i].size(); ++j )
1207 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1210 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1216 writeGroup( 70, hatchPattern == QLatin1String(
"SOLID" ) );
1219 QVector<QVector<QgsPoint>> points;
1220 QVector<QVector<double>> bulges;
1222 points << QVector<QgsPoint>();
1223 bulges << QVector<double>();
1224 appendCurve( *polygon.
exteriorRing(), points.last(), bulges.last() );
1228 points << QVector<QgsPoint>();
1229 bulges << QVector<double>();
1230 appendCurve( *polygon.
interiorRing( i ), points.last(), bulges.last() );
1233 bool hasBulges =
false;
1234 for (
int i = 0; i < points.size() && !hasBulges; ++i )
1235 for (
int j = 0; j < points[i].size() && !hasBulges; ++j )
1236 hasBulges = bulges[i][j] != 0.0;
1240 for (
int i = 0; i < points.size(); ++i )
1247 for (
int j = 0; j < points[i].size(); ++j )
1271 double lblX = label->
getX();
1272 double lblY = label->
getY();
1281 if ( layerSettings.
placement == QgsPalLayerSettings::Placement::OverPoint )
1291 if ( exprVal.isValid() )
1297 switch ( offsetQuad )
1299 case QgsPalLayerSettings::QuadrantPosition::QuadrantAboveLeft:
1303 case QgsPalLayerSettings::QuadrantPosition::QuadrantAbove:
1307 case QgsPalLayerSettings::QuadrantPosition::QuadrantAboveRight:
1311 case QgsPalLayerSettings::QuadrantPosition::QuadrantLeft:
1315 case QgsPalLayerSettings::QuadrantPosition::QuadrantOver:
1319 case QgsPalLayerSettings::QuadrantPosition::QuadrantRight:
1323 case QgsPalLayerSettings::QuadrantPosition::QuadrantBelowLeft:
1327 case QgsPalLayerSettings::QuadrantPosition::QuadrantBelow:
1331 case QgsPalLayerSettings::QuadrantPosition::QuadrantBelowRight:
1349 if ( exprVal.isValid() )
1351 const QString haliString = exprVal.toString();
1352 if ( haliString.compare( QLatin1String(
"Center" ), Qt::CaseInsensitive ) == 0 )
1356 else if ( haliString.compare( QLatin1String(
"Right" ), Qt::CaseInsensitive ) == 0 )
1368 if ( exprVal.isValid() )
1370 const QString valiString = exprVal.toString();
1371 if ( valiString.compare( QLatin1String(
"Bottom" ), Qt::CaseInsensitive ) != 0 )
1373 if ( valiString.compare( QLatin1String(
"Base" ), Qt::CaseInsensitive ) == 0 )
1377 else if ( valiString.compare( QLatin1String(
"Half" ), Qt::CaseInsensitive ) == 0 )
1396 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1397 writeGroup( 100, QStringLiteral(
"AcDbPoint" ) );
1408 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1411 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1442 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1446 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1447 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1466 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1469 writeGroup( 100, QStringLiteral(
"AcDbText" ) );
1480 writeGroup( 7, QStringLiteral(
"STANDARD" ) );
1481 writeGroup( 100, QStringLiteral(
"AcDbText" ) );
1490 if ( !mTextStream.codec()->canEncode( text ) )
1493 QgsDebugMsg( QStringLiteral(
"could not encode:%1" ).arg( text ) );
1499 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1500 writeGroup( 100, QStringLiteral(
"AcDbMText" ) );
1507 while ( t.length() > 250 )
1523 writeGroup( 7, QStringLiteral(
"STANDARD" ) );
1538 geom.transform( ct );
1545 if ( mSymbologyExport !=
NoSymbology && symbolLayer )
1547 penColor = colorFromSymbolLayer( symbolLayer, ctx );
1551 Qt::PenStyle penStyle( Qt::SolidLine );
1552 Qt::BrushStyle brushStyle( Qt::NoBrush );
1554 double offset = 0.0;
1556 if ( mSymbologyExport !=
NoSymbology && symbolLayer )
1558 width = symbolLayer->
dxfWidth( *
this, ctx );
1559 offset = symbolLayer->
dxfOffset( *
this, ctx );
1568 QString lineStyleName = QStringLiteral(
"CONTINUOUS" );
1571 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
1577 writePoint( geom.constGet()->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol,
angle );
1584 for (
int i = 0; i < cs.size(); i++ )
1586 writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol,
angle );
1591 if ( penStyle != Qt::NoPen )
1594 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1605 tempGeom.reset(
geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 ) );
1607 sourceGeom = tempGeom.get();
1609 sourceGeom = geom.constGet();
1614 writePolyline( *curve, layer, lineStyleName, penColor, width );
1625 tempGeom.reset(
geos.offsetCurve( offset, 0, GEOSBUF_JOIN_MITRE, 2.0 ) );
1627 sourceGeom = tempGeom.get();
1629 sourceGeom = geom.constGet();
1639 writePolyline( *curve, layer, lineStyleName, penColor, width );
1651 tempGeom.reset(
geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 ) );
1653 sourceGeom = tempGeom.get();
1655 sourceGeom = geom.constGet();
1659 Q_ASSERT( polygon );
1674 tempGeom.reset(
geos.buffer( offset, 0, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, 2.0 ) );
1676 sourceGeom = tempGeom.get();
1678 sourceGeom = geom.constGet();
1687 Q_ASSERT( polygon );
1703 if ( brushStyle != Qt::NoBrush )
1706 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1714 Q_ASSERT( polygon );
1715 writePolygon( *polygon, layer, QStringLiteral(
"SOLID" ), brushColor );
1728 Q_ASSERT( polygon );
1729 writePolygon( *polygon, layer, QStringLiteral(
"SOLID" ), brushColor );
1746 return symbolLayer->
dxfColor( ctx );
1749 QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayer *symbolLayer )
1751 QString lineStyleName = QStringLiteral(
"CONTINUOUS" );
1754 return lineStyleName;
1757 QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
1758 if ( lineTypeIt != mLineStyles.constEnd() )
1760 lineStyleName = lineTypeIt.value();
1761 return lineStyleName;
1765 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
1772 int current_distance = std::numeric_limits<int>::max();
1773 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ); ++i )
1775 int dist = color_distance( pixel, i );
1776 if ( dist < current_distance )
1778 current_distance = dist;
1787 int QgsDxfExport::color_distance( QRgb p1,
int index )
1789 if ( index > 255 || index < 0 )
1794 double redDiff = qRed( p1 ) - sDxfColors[index][0];
1795 double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
1796 double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
1798 QgsDebugMsg( QStringLiteral(
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8" )
1799 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
1801 .arg( mDxfColors[index][0] )
1802 .arg( mDxfColors[index][1] )
1803 .arg( mDxfColors[index][2] )
1804 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ) );
1806 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
1809 QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
1811 return QColor::fromRgbF( r, g, b ).rgb();
1816 return mRenderContext;
1831 return mapUnitsPerPixel;
1845 double minSizeMU = std::numeric_limits<double>::lowest();
1848 minSizeMU = scale.
minSizeMM * pixelToMMFactor * mapUnitsPerPixel;
1852 minSizeMU = std::max( minSizeMU, value );
1854 value = std::max( value, minSizeMU );
1856 double maxSizeMU = std::numeric_limits<double>::max();
1859 maxSizeMU = scale.
maxSizeMM * pixelToMMFactor * mapUnitsPerPixel;
1863 maxSizeMU = std::min( maxSizeMU, value );
1865 value = std::min( value, maxSizeMU );
1868 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers(
QgsRenderContext &context )
1870 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
1881 maxSymbolLayers = 1;
1883 for (
int i = 0; i < maxSymbolLayers; ++i )
1885 symbolLayers.append( qMakePair( symbol->
symbolLayer( i ), symbol ) );
1890 return symbolLayers;
1893 void QgsDxfExport::writeDefaultLinetypes()
1896 for (
const QString <ype : { QStringLiteral(
"ByLayer" ), QStringLiteral(
"ByBlock" ), QStringLiteral(
"CONTINUOUS" ) } )
1900 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
1901 writeGroup( 100, QStringLiteral(
"AcDbLinetypeTableRecord" ) );
1904 writeGroup( 3, QStringLiteral(
"Defaultstyle" ) );
1910 double das = dashSize();
1911 double dss = dashSeparatorSize();
1912 double dos = dotSize();
1914 QVector<qreal> dashVector( 2 );
1915 dashVector[0] = das;
1916 dashVector[1] = dss;
1919 QVector<qreal> dotVector( 2 );
1924 QVector<qreal> dashDotVector( 4 );
1925 dashDotVector[0] = das;
1926 dashDotVector[1] = dss;
1927 dashDotVector[2] = dos;
1928 dashDotVector[3] = dss;
1931 QVector<qreal> dashDotDotVector( 6 );
1932 dashDotDotVector[0] = das;
1933 dashDotDotVector[1] = dss;
1934 dashDotDotVector[2] = dos;
1935 dashDotDotVector[3] = dss;
1936 dashDotDotVector[4] = dos;
1937 dashDotDotVector[5] = dss;
1941 void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayer *symbolLayer )
1950 if ( !customLinestyle.isEmpty() )
1952 QString name = QStringLiteral(
"symbolLayer%1" ).arg( mSymbolLayerCounter++ );
1953 writeLinetype( name, customLinestyle, unit );
1954 mLineStyles.insert( symbolLayer, name );
1958 int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
1961 for (
const auto &symbolLayer : symbolLayers )
1975 void QgsDxfExport::writeLinetype(
const QString &styleName,
const QVector<qreal> &pattern,
QgsUnitTypes::RenderUnit u )
1978 for ( qreal size : pattern )
1986 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
1987 writeGroup( 100, QStringLiteral(
"AcDbLinetypeTableRecord" ) );
1996 for ( qreal size : pattern )
1999 double segmentLength = ( isGap ? -size : size );
2025 geomExpr.prepare( &expressionContext );
2033 symbolExpressionContextScope->
setFeature( f );
2038 for (
int i = 0; i < nSymbolLayers; ++i )
2040 addFeature( ctx, ct, layer, symbol->
symbolLayer( i ), symbol );
2049 if ( !sl || !symbol )
2062 double QgsDxfExport::dashSize()
const
2064 double size = mSymbologyScale * 0.002;
2065 return sizeToMapUnits( size );
2068 double QgsDxfExport::dotSize()
const
2070 double size = mSymbologyScale * 0.0006;
2071 return sizeToMapUnits( size );
2074 double QgsDxfExport::dashSeparatorSize()
const
2076 double size = mSymbologyScale * 0.0006;
2077 return sizeToMapUnits( size );
2080 double QgsDxfExport::sizeToMapUnits(
double s )
const
2086 QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
2091 return QStringLiteral(
"DASH" );
2093 return QStringLiteral(
"DOT" );
2094 case Qt::DashDotLine:
2095 return QStringLiteral(
"DASHDOT" );
2096 case Qt::DashDotDotLine:
2097 return QStringLiteral(
"DASHDOTDOT" );
2100 return QStringLiteral(
"CONTINUOUS" );
2106 if ( name.isEmpty() )
2107 return QStringLiteral(
"0" );
2129 layerName.replace( QLatin1String(
"\r\n" ), QLatin1String(
"_" ) );
2136 bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer *layer )
const
2150 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
2154 if ( vl && vl->
id() ==
id )
2156 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
2161 return QStringLiteral(
"0" );
2166 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2167 for (
const QByteArray &codec : codecs )
2169 if ( name != codec )
2173 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && name != DXF_ENCODINGS[i][1]; ++i )
2176 if ( i ==
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2179 return DXF_ENCODINGS[i][0];
2188 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2189 for (
const QByteArray &codec : codecs )
2192 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2195 if ( i <
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2204 return mLayerTitleAsName && !vl->
title().isEmpty() ? vl->
title() : vl->
name();
2222 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->
dataDefinedValues();
2227 QgsDebugMsgLevel( QStringLiteral(
"PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
2257 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
2260 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
2263 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
2269 QString dxfLayer = mDxfLayerNames[layerId][fid];
2271 QString wrapchr = tmpLyr.
wrapChar.isEmpty() ? QStringLiteral(
"\n" ) : tmpLyr.
wrapChar;
2276 bool prependSymb =
false;
2294 prependSymb =
false;
2303 symb = symb + wrapchr;
2307 prependSymb =
false;
2308 symb = wrapchr + symb;
2317 txt.prepend( symb );
2327 txt.replace( QChar( QChar::LineFeed ),
' ' );
2328 txt.replace( QChar( QChar::CarriageReturn ),
' ' );
2333 txt.replace( QString( QChar( QChar::CarriageReturn ) ) + QString( QChar( QChar::LineFeed ) ), QStringLiteral(
"\\P" ) );
2334 txt.replace( QChar( QChar::CarriageReturn ), QStringLiteral(
"\\P" ) );
2335 txt = txt.replace( wrapchr, QLatin1String(
"\\P" ) );
2336 txt.replace(
" ",
"\\~" );
2340 txt.prepend(
"\\L" ).append(
"\\l" );
2345 txt.prepend(
"\\O" ).append(
"\\o" );
2350 txt.prepend(
"\\K" ).append(
"\\k" );
2353 txt.prepend( QStringLiteral(
"\\f%1|i%2|b%3;\\H%4;" )
2355 .arg( tmpLyr.
format().
font().italic() ? 1 : 0 )
2356 .arg( tmpLyr.
format().
font().bold() ? 1 : 0 )
2357 .arg( label->
getHeight() / ( 1 + txt.count( QStringLiteral(
"\\P" ) ) ) * 0.75 ) );
2365 if ( !mDxfLayerNames.contains( layerId ) )
2366 mDxfLayerNames[ layerId ] = QMap<QgsFeatureId, QString>();
2368 mDxfLayerNames[layerId][fid] =
layerName;
2384 QString splitLayerFieldName;
2386 if ( mLayerOutputAttributeIndex >= 0 && mLayerOutputAttributeIndex < fields.
size() )
2388 splitLayerFieldName = fields.
at( mLayerOutputAttributeIndex ).
name();
2391 return splitLayerFieldName;