66 #define strcasecmp( a, b ) stricmp( a, b )
78 mMapSettings = settings;
93 QList<QgsMapLayer *> layerList;
95 mLayerNameAttribute.clear();
97 layerList.reserve( layers.size() );
98 for (
const DxfLayer &dxfLayer : layers )
100 layerList << dxfLayer.layer();
101 if ( dxfLayer.layerOutputAttributeIndex() >= 0 )
102 mLayerNameAttribute.insert( dxfLayer.layer()->id(), dxfLayer.layerOutputAttributeIndex() );
136 if ( !mForce2d && p.
is3D() && std::isfinite( p.
z() ) )
143 int minDist = std::numeric_limits<int>::max();
145 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ) && minDist > 0; ++i )
147 int dist = color_distance( color.rgba(), i );
148 if ( dist >= minDist )
155 if ( minDist == 0 && minDistAt != 7 )
159 if ( color.alpha() == 255 )
163 int c = ( color.red() & 0xff ) * 0x10000 + ( color.green() & 0xff ) * 0x100 + ( color.blue() & 0xff );
165 if ( transparencyCode != -1 && color.alpha() < 255 )
166 writeGroup( transparencyCode, 0x2000000 | color.alpha() );
171 mTextStream << QStringLiteral(
"%1\n" ).arg( code, 3, 10, QChar(
' ' ) );
176 mTextStream << QStringLiteral(
"%1\n" ).arg( i, 6, 10, QChar(
' ' ) );
182 if ( !s.contains(
'.' ) )
183 s += QLatin1String(
".0" );
184 mTextStream << s <<
'\n';
189 mTextStream << s <<
'\n';
199 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
204 mTextStream.setDevice( d );
205 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
206 mTextStream.setCodec( encoding.toLocal8Bit() );
208 mTextStream.setEncoding( QStringConverter::encodingForName( encoding.toLocal8Bit() ).value_or( QStringConverter::Utf8 ) );
216 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
231 mExtent = layerExtent;
267 void QgsDxfExport::writeHeader(
const QString &codepage )
269 writeGroup( 999, QStringLiteral(
"DXF created from QGIS" ) );
275 writeGroup( 9, QStringLiteral(
"$ACADVER" ) );
287 writeGroup( 9, QStringLiteral(
"$LTSCALE" ) );
299 writeGroup( 9, QStringLiteral(
"$PSLTSCALE" ) );
302 writeGroup( 9, QStringLiteral(
"$HANDSEED" ) );
305 writeGroup( 9, QStringLiteral(
"$DWGCODEPAGE" ) );
314 handle = mNextHandleId++;
316 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
318 writeGroup( code, QString::number( handle, 16 ) );
322 void QgsDxfExport::writeTables()
329 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
332 slList = symbolLayers( context );
340 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
343 writeDefaultLinetypes();
346 for (
const auto &symbolLayer : std::as_const( slList ) )
348 writeSymbolLayerLinetype( symbolLayer.first );
355 writeGroup( 2, QStringLiteral(
"BLOCK_RECORD" ) );
358 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
361 const QStringList blockStrings = QStringList() << QStringLiteral(
"*Model_Space" ) << QStringLiteral(
"*Paper_Space" ) << QStringLiteral(
"*Paper_Space0" );
362 for (
const QString &block : blockStrings )
364 writeGroup( 0, QStringLiteral(
"BLOCK_RECORD" ) );
366 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
367 writeGroup( 100, QStringLiteral(
"AcDbBlockTableRecord" ) );
372 for (
const auto &symbolLayer : std::as_const( slList ) )
378 if ( hasDataDefinedProperties( ml, symbolLayer.second ) )
381 QString name = QStringLiteral(
"symbolLayer%1" ).arg( i++ );
382 writeGroup( 0, QStringLiteral(
"BLOCK_RECORD" ) );
384 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
385 writeGroup( 100, QStringLiteral(
"AcDbBlockTableRecord" ) );
395 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
399 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
400 writeGroup( 100, QStringLiteral(
"AcDbRegAppTableRecord" ) );
409 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
417 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
425 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
429 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
430 writeGroup( 100, QStringLiteral(
"AcDbViewportTableRecord" ) );
469 writeGroup( 2, QStringLiteral(
"DIMSTYLE" ) );
471 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
472 writeGroup( 100, QStringLiteral(
"AcDbDimStyleTable" ) );
476 QSet<QString> layerNames;
477 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
480 if ( !layerIsScaleBasedVisible( ml ) )
487 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
494 const QSet<QVariant> values = vl->
uniqueValues( attrIdx );
495 for (
const QVariant &v : values )
507 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
512 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
513 writeGroup( 100, QStringLiteral(
"AcDbLayerTableRecord" ) );
517 writeGroup( 6, QStringLiteral(
"CONTINUOUS" ) );
520 for (
const QString &
layerName : std::as_const( layerNames ) )
524 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
525 writeGroup( 100, QStringLiteral(
"AcDbLayerTableRecord" ) );
529 writeGroup( 6, QStringLiteral(
"CONTINUOUS" ) );
538 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
544 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
545 writeGroup( 100, QStringLiteral(
"AcDbTextStyleTableRecord" ) );
546 writeGroup( 2, QStringLiteral(
"STANDARD" ) );
553 writeGroup( 3, QStringLiteral(
"romans.shx" ) );
561 void QgsDxfExport::writeBlocks()
566 static const QStringList blockStrings = QStringList() << QStringLiteral(
"*Model_Space" ) << QStringLiteral(
"*Paper_Space" ) << QStringLiteral(
"*Paper_Space0" );
567 for (
const QString &block : blockStrings )
571 writeGroup( 330, QString::number( mBlockHandles[ block ], 16 ) );
572 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
574 writeGroup( 100, QStringLiteral(
"AcDbBlockBegin" ) );
582 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
584 writeGroup( 100, QStringLiteral(
"AcDbBlockEnd" ) );
590 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
593 slList = symbolLayers( ct );
596 for (
const auto &symbolLayer : std::as_const( slList ) )
606 if ( hasDataDefinedProperties( ml, symbolLayer.second ) )
611 QString block( QStringLiteral(
"symbolLayer%1" ).arg( mBlockCounter++ ) );
612 mBlockHandle = QString::number( mBlockHandles[ block ], 16 );
617 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
619 writeGroup( 100, QStringLiteral(
"AcDbBlockBegin" ) );
632 ml->
writeDxf( *
this,
mapUnitScaleFactor( mSymbologyScale, ml->
sizeUnit(), mMapUnits, ctx.renderContext().mapToPixel().mapUnitsPerPixel() ), QStringLiteral(
"0" ), ctx );
636 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
638 writeGroup( 100, QStringLiteral(
"AcDbBlockEnd" ) );
640 mPointSymbolBlocks.insert( ml, block );
646 void QgsDxfExport::writeEntities()
649 writeGroup( 2, QStringLiteral(
"ENTITIES" ) );
651 mBlockHandle = QString::number( mBlockHandles[ QStringLiteral(
"*Model_Space" )], 16 );
660 job->renderer->usingSymbolLevels() )
662 writeEntitiesSymbolLevels( job );
680 QString lName(
dxfLayerName( job->splitLayerAttribute.isNull() ? job->layerTitle : fet.
attribute( job->splitLayerAttribute ).toString() ) );
682 sctx.setFeature( &fet );
684 if ( !job->renderer->willRenderFeature( fet, mRenderContext ) )
689 addFeature( sctx, ct, lName,
nullptr,
nullptr );
693 const QgsSymbolList symbolList = job->renderer->symbolsForFeature( fet, mRenderContext );
694 bool hasSymbology = symbolList.size() > 0;
706 bool isGeometryGenerator = ( symbolLayer->layerType() == QLatin1String(
"GeometryGenerator" ) );
707 if ( isGeometryGenerator )
709 addGeometryGeneratorSymbolLayer( sctx, ct, lName, symbolLayer,
true );
713 addFeature( sctx, ct, lName, symbolLayer, symbol );
718 else if ( hasSymbology )
729 addGeometryGeneratorSymbolLayer( sctx, ct, lName, s->
symbolLayer( 0 ),
false );
733 addFeature( sctx, ct, lName, s->
symbolLayer( 0 ), s );
737 if ( job->labelProvider )
739 job->labelProvider->registerFeature( fet, mRenderContext );
744 else if ( job->ruleBasedLabelProvider )
746 job->ruleBasedLabelProvider->registerFeature( fet, mRenderContext );
755 QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
756 image.setDotsPerMeterX( 96 / 25.4 * 1000 );
757 image.setDotsPerMeterY( 96 / 25.4 * 1000 );
758 QPainter painter( &image );
766 void QgsDxfExport::prepareRenderers()
768 Q_ASSERT( mJobs.empty() );
776 mExtent.
height() * mFactor, 0 ) );
782 mLabelingEngine = std::make_unique<QgsDefaultLabelingEngine>();
783 mLabelingEngine->setMapSettings( mMapSettings );
786 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
796 if ( !layerIsScaleBasedVisible( vl ) )
799 QString splitLayerAttribute;
800 int splitLayerAttributeIndex = mLayerNameAttribute.value( vl->
id(), -1 );
802 if ( splitLayerAttributeIndex >= 0 && splitLayerAttributeIndex < fields.
size() )
803 splitLayerAttribute = fields.
at( splitLayerAttributeIndex ).
name();
809 void QgsDxfExport::writeEntitiesSymbolLevels(
DxfLayerJob *job )
811 QHash< QgsSymbol *, QList<QgsFeature> > features;
833 featureSymbol = job->
renderer->symbolForFeature( fet, ctx );
834 if ( !featureSymbol )
839 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
840 if ( it == features.end() )
842 it = features.insert( featureSymbol, QList<QgsFeature>() );
844 it.value().append( fet );
852 for (
int j = 0; j < symbol->symbolLayerCount(); j++ )
854 int level = symbol->symbolLayer( j )->renderingPass();
855 if ( level < 0 || level >= 1000 )
858 while ( level >= levels.count() )
860 levels[level].append( item );
869 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
870 if ( levelIt == features.end() )
875 int llayer = item.layer();
876 const QList<QgsFeature> &featureList = levelIt.value();
877 for (
const QgsFeature &feature : featureList )
879 sctx.setFeature( &feature );
880 addFeature( sctx, ct, job->
layerName, levelIt.key()->symbolLayer( llayer ), levelIt.key() );
886 void QgsDxfExport::stopRenderers()
892 void QgsDxfExport::writeEndFile()
899 void QgsDxfExport::startSection()
904 void QgsDxfExport::endSection()
929 QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
930 if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() )
948 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
949 writeGroup( 100, QStringLiteral(
"AcDbBlockReference" ) );
962 QgsDebugMsg( QStringLiteral(
"writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
968 QgsDebugMsg( QStringLiteral(
"writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
972 if ( mForce2d || !line.at( 0 ).is3D() )
974 bool polygon = line[0] == line[ line.size() - 1 ];
978 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
981 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
982 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
990 for (
int i = 0; i < n; i++ )
995 writeGroup( 0, QStringLiteral(
"POLYLINE" ) );
998 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1002 writeGroup( 100, QStringLiteral(
"AcDb3dPolyline" ) );
1006 for (
int i = 0; i < n; i++ )
1011 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1014 writeGroup( 100, QStringLiteral(
"AcDbVertex" ) );
1015 writeGroup( 100, QStringLiteral(
"AcDb3dPolylineVertex" ) );
1023 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1029 void QgsDxfExport::appendCurve(
const QgsCurve &
c, QVector<QgsPoint> &points, QVector<double> &bulges )
1034 appendLineString( *
dynamic_cast<const QgsLineString *
>( &
c ), points, bulges );
1038 appendCircularString( *
dynamic_cast<const QgsCircularString *
>( &
c ), points, bulges );
1042 appendCompoundCurve( *
dynamic_cast<const QgsCompoundCurve *
>( &
c ), points, bulges );
1046 QgsDebugMsg( QStringLiteral(
"Unexpected curve type %1" ).arg(
c.wktTypeStr() ) );
1051 void QgsDxfExport::appendLineString(
const QgsLineString &ls, QVector<QgsPoint> &points, QVector<double> &bulges )
1053 for (
int i = 0; i < ls.
numPoints(); i++ )
1056 if ( !points.isEmpty() && points.last() == p )
1064 void QgsDxfExport::appendCircularString(
const QgsCircularString &cs, QVector<QgsPoint> &points, QVector<double> &bulges )
1066 for (
int i = 0; i < cs.
numPoints() - 2; i += 2 )
1072 if ( points.isEmpty() || points.last() != p1 )
1074 else if ( !bulges.isEmpty() )
1075 bulges.removeLast();
1077 double a = ( M_PI - ( p1 - p2 ).
angle() + ( p3 - p2 ).
angle() ) / 2.0;
1078 bulges << sin( a ) / cos( a );
1085 void QgsDxfExport::appendCompoundCurve(
const QgsCompoundCurve &cc, QVector<QgsPoint> &points, QVector<double> &bulges )
1087 for (
int i = 0; i < cc.
nCurves(); i++ )
1091 appendCurve( *
c, points, bulges );
1100 QgsDebugMsg( QStringLiteral(
"writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1106 QgsDebugMsg( QStringLiteral(
"writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1110 QVector<QgsPoint> points;
1111 QVector<double> bulges;
1112 appendCurve( curve, points, bulges );
1114 if ( mForce2d || !curve.
is3D() )
1116 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1119 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1120 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1125 QgsDxfExport::DxfPolylineFlags polylineFlags;
1127 polylineFlags.setFlag( QgsDxfExport::DxfPolylineFlag::Closed );
1129 polylineFlags.setFlag( QgsDxfExport::DxfPolylineFlag::Curve );
1133 polylineFlags.setFlag( QgsDxfExport::DxfPolylineFlag::ContinuousPattern );
1135 writeGroup( 70,
static_cast<int>( polylineFlags ) );
1138 for (
int i = 0; i < points.size(); i++ )
1141 if ( bulges[i] != 0.0 )
1147 writeGroup( 0, QStringLiteral(
"POLYLINE" ) );
1150 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1154 writeGroup( 100, QStringLiteral(
"AcDb3dPolyline" ) );
1158 for (
int i = 0; i < points.size(); i++ )
1163 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1166 writeGroup( 100, QStringLiteral(
"AcDbVertex" ) );
1167 writeGroup( 100, QStringLiteral(
"AcDb3dPolylineVertex" ) );
1169 if ( bulges[i] != 0.0 )
1177 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1188 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1191 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1197 writeGroup( 70, hatchPattern == QLatin1String(
"SOLID" ) );
1201 for (
int i = 0; i < polygon.size(); ++i )
1208 for (
int j = 0; j < polygon[i].size(); ++j )
1227 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1230 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1236 writeGroup( 70, hatchPattern == QLatin1String(
"SOLID" ) );
1239 QVector<QVector<QgsPoint>> points;
1240 QVector<QVector<double>> bulges;
1243 points.reserve( ringCount + 1 );
1244 bulges.reserve( ringCount + 1 );
1246 points << QVector<QgsPoint>();
1247 bulges << QVector<double>();
1248 appendCurve( *polygon.
exteriorRing(), points.last(), bulges.last() );
1250 for (
int i = 0; i < ringCount; i++ )
1252 points << QVector<QgsPoint>();
1253 bulges << QVector<double>();
1254 appendCurve( *polygon.
interiorRing( i ), points.last(), bulges.last() );
1257 bool hasBulges =
false;
1258 for (
int i = 0; i < points.size() && !hasBulges; ++i )
1259 for (
int j = 0; j < points[i].size() && !hasBulges; ++j )
1260 hasBulges = bulges[i][j] != 0.0;
1264 for (
int i = 0; i < points.size(); ++i )
1271 for (
int j = 0; j < points[i].size(); ++j )
1295 double lblX = label->
getX();
1296 double lblY = label->
getY();
1315 if ( !exprVal.isNull() )
1321 switch ( offsetQuad )
1323 case Qgis::LabelQuadrantPosition::AboveLeft:
1327 case Qgis::LabelQuadrantPosition::Above:
1331 case Qgis::LabelQuadrantPosition::AboveRight:
1335 case Qgis::LabelQuadrantPosition::Left:
1339 case Qgis::LabelQuadrantPosition::Over:
1343 case Qgis::LabelQuadrantPosition::Right:
1347 case Qgis::LabelQuadrantPosition::BelowLeft:
1351 case Qgis::LabelQuadrantPosition::Below:
1355 case Qgis::LabelQuadrantPosition::BelowRight:
1369 if ( !exprVal.isNull() )
1371 const QString haliString = exprVal.toString();
1372 if ( haliString.compare( QLatin1String(
"Center" ), Qt::CaseInsensitive ) == 0 )
1376 else if ( haliString.compare( QLatin1String(
"Right" ), Qt::CaseInsensitive ) == 0 )
1388 if ( !exprVal.isNull() )
1390 const QString valiString = exprVal.toString();
1391 if ( valiString.compare( QLatin1String(
"Bottom" ), Qt::CaseInsensitive ) != 0 )
1393 if ( valiString.compare( QLatin1String(
"Base" ), Qt::CaseInsensitive ) == 0 )
1397 else if ( valiString.compare( QLatin1String(
"Half" ), Qt::CaseInsensitive ) == 0 )
1416 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1417 writeGroup( 100, QStringLiteral(
"AcDbPoint" ) );
1428 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1431 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1462 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1466 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1467 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1486 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1489 writeGroup( 100, QStringLiteral(
"AcDbText" ) );
1500 writeGroup( 7, QStringLiteral(
"STANDARD" ) );
1501 writeGroup( 100, QStringLiteral(
"AcDbText" ) );
1510 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1511 if ( !mTextStream.codec()->canEncode( text ) )
1514 QgsDebugMsg( QStringLiteral(
"could not encode:%1" ).arg( text ) );
1521 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1522 writeGroup( 100, QStringLiteral(
"AcDbMText" ) );
1529 while ( t.length() > 250 )
1545 writeGroup( 7, QStringLiteral(
"STANDARD" ) );
1560 geom.transform( ct );
1567 if ( mSymbologyExport !=
NoSymbology && symbolLayer )
1569 penColor = colorFromSymbolLayer( symbolLayer, ctx );
1573 Qt::PenStyle penStyle( Qt::SolidLine );
1574 Qt::BrushStyle brushStyle( Qt::NoBrush );
1576 double offset = 0.0;
1578 if ( mSymbologyExport !=
NoSymbology && symbolLayer )
1580 width = symbolLayer->
dxfWidth( *
this, ctx );
1581 offset = symbolLayer->
dxfOffset( *
this, ctx );
1590 QString lineStyleName = QStringLiteral(
"CONTINUOUS" );
1593 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
1599 writePoint( geom.constGet()->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol,
angle );
1606 for (
int i = 0; i < cs.size(); i++ )
1608 writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol,
angle );
1613 if ( penStyle != Qt::NoPen )
1616 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1629 tempGeom.reset(
geos.offsetCurve( offset, 0, Qgis::JoinStyle::Miter, 2.0 ) );
1631 sourceGeom = tempGeom.get();
1633 sourceGeom = geom.constGet();
1639 writePolyline( *curve, layer, lineStyleName, penColor, width );
1651 writePolyline( *curve, layer, lineStyleName, penColor, width );
1666 tempGeom.reset(
geos.buffer( offset, 0, Qgis::EndCapStyle::Flat, Qgis::JoinStyle::Miter, 2.0 ) );
1668 sourceGeom = tempGeom.get();
1670 sourceGeom = geom.constGet();
1689 Q_ASSERT( polygon );
1707 if ( brushStyle != Qt::NoBrush )
1710 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1718 Q_ASSERT( polygon );
1719 writePolygon( *polygon, layer, QStringLiteral(
"SOLID" ), brushColor );
1732 Q_ASSERT( polygon );
1733 writePolygon( *polygon, layer, QStringLiteral(
"SOLID" ), brushColor );
1750 return symbolLayer->
dxfColor( ctx );
1753 QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayer *symbolLayer )
1755 QString lineStyleName = QStringLiteral(
"CONTINUOUS" );
1758 return lineStyleName;
1761 QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
1762 if ( lineTypeIt != mLineStyles.constEnd() )
1764 lineStyleName = lineTypeIt.value();
1765 return lineStyleName;
1769 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
1776 int current_distance = std::numeric_limits<int>::max();
1777 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ); ++i )
1779 int dist = color_distance( pixel, i );
1780 if ( dist < current_distance )
1782 current_distance = dist;
1791 int QgsDxfExport::color_distance( QRgb p1,
int index )
1793 if ( index > 255 || index < 0 )
1798 double redDiff = qRed( p1 ) - sDxfColors[index][0];
1799 double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
1800 double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
1802 QgsDebugMsg( QStringLiteral(
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8" )
1803 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
1805 .arg( mDxfColors[index][0] )
1806 .arg( mDxfColors[index][1] )
1807 .arg( mDxfColors[index][2] )
1808 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ) );
1810 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
1813 QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
1815 return QColor::fromRgbF( r, g, b ).rgb();
1820 return mRenderContext;
1835 return mapUnitsPerPixel;
1849 double minSizeMU = std::numeric_limits<double>::lowest();
1852 minSizeMU = scale.
minSizeMM * pixelToMMFactor * mapUnitsPerPixel;
1856 minSizeMU = std::max( minSizeMU, value );
1858 value = std::max( value, minSizeMU );
1860 double maxSizeMU = std::numeric_limits<double>::max();
1863 maxSizeMU = scale.
maxSizeMM * pixelToMMFactor * mapUnitsPerPixel;
1867 maxSizeMU = std::min( maxSizeMU, value );
1869 value = std::min( value, maxSizeMU );
1872 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers(
QgsRenderContext &context )
1874 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
1885 maxSymbolLayers = 1;
1887 for (
int i = 0; i < maxSymbolLayers; ++i )
1889 symbolLayers.append( qMakePair( symbol->
symbolLayer( i ), symbol ) );
1894 return symbolLayers;
1897 void QgsDxfExport::writeDefaultLinetypes()
1900 for (
const QString <ype : { QStringLiteral(
"ByLayer" ), QStringLiteral(
"ByBlock" ), QStringLiteral(
"CONTINUOUS" ) } )
1904 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
1905 writeGroup( 100, QStringLiteral(
"AcDbLinetypeTableRecord" ) );
1908 writeGroup( 3, QStringLiteral(
"Defaultstyle" ) );
1914 double das = dashSize();
1915 double dss = dashSeparatorSize();
1916 double dos = dotSize();
1918 QVector<qreal> dashVector( 2 );
1919 dashVector[0] = das;
1920 dashVector[1] = dss;
1923 QVector<qreal> dotVector( 2 );
1928 QVector<qreal> dashDotVector( 4 );
1929 dashDotVector[0] = das;
1930 dashDotVector[1] = dss;
1931 dashDotVector[2] = dos;
1932 dashDotVector[3] = dss;
1935 QVector<qreal> dashDotDotVector( 6 );
1936 dashDotDotVector[0] = das;
1937 dashDotDotVector[1] = dss;
1938 dashDotDotVector[2] = dos;
1939 dashDotDotVector[3] = dss;
1940 dashDotDotVector[4] = dos;
1941 dashDotDotVector[5] = dss;
1945 void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayer *symbolLayer )
1954 if ( !customLinestyle.isEmpty() )
1956 QString name = QStringLiteral(
"symbolLayer%1" ).arg( mSymbolLayerCounter++ );
1957 writeLinetype( name, customLinestyle, unit );
1958 mLineStyles.insert( symbolLayer, name );
1962 int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
1965 for (
const auto &symbolLayer : symbolLayers )
1979 void QgsDxfExport::writeLinetype(
const QString &styleName,
const QVector<qreal> &pattern,
QgsUnitTypes::RenderUnit u )
1982 for ( qreal size : pattern )
1990 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
1991 writeGroup( 100, QStringLiteral(
"AcDbLinetypeTableRecord" ) );
2000 for ( qreal size : pattern )
2003 double segmentLength = ( isGap ? -size : size );
2029 geomExpr.prepare( &expressionContext );
2037 symbolExpressionContextScope->
setFeature( f );
2042 for (
int i = 0; i < nSymbolLayers; ++i )
2044 addFeature( ctx, ct, layer, symbol->
symbolLayer( i ), symbol );
2053 if ( !sl || !symbol )
2066 double QgsDxfExport::dashSize()
const
2068 double size = mSymbologyScale * 0.002;
2069 return sizeToMapUnits( size );
2072 double QgsDxfExport::dotSize()
const
2074 double size = mSymbologyScale * 0.0006;
2075 return sizeToMapUnits( size );
2078 double QgsDxfExport::dashSeparatorSize()
const
2080 double size = mSymbologyScale * 0.0006;
2081 return sizeToMapUnits( size );
2084 double QgsDxfExport::sizeToMapUnits(
double s )
const
2090 QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
2095 return QStringLiteral(
"DASH" );
2097 return QStringLiteral(
"DOT" );
2098 case Qt::DashDotLine:
2099 return QStringLiteral(
"DASHDOT" );
2100 case Qt::DashDotDotLine:
2101 return QStringLiteral(
"DASHDOTDOT" );
2104 return QStringLiteral(
"CONTINUOUS" );
2110 if ( name.isEmpty() )
2111 return QStringLiteral(
"0" );
2136 layerName.replace( QLatin1String(
"\r\n" ), QLatin1String(
"_" ) );
2143 bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer *layer )
const
2157 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
2161 if ( vl && vl->
id() ==
id )
2163 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
2168 return QStringLiteral(
"0" );
2173 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2174 for (
const QByteArray &codec : codecs )
2176 if ( name != codec )
2180 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && name != DXF_ENCODINGS[i][1]; ++i )
2183 if ( i ==
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2186 return DXF_ENCODINGS[i][0];
2195 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2197 for (
const QByteArray &codec : codecs )
2200 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2203 if ( i <
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2215 return mLayerTitleAsName && !vl->
title().isEmpty() ? vl->
title() : vl->
name();
2233 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->
dataDefinedValues();
2238 QgsDebugMsgLevel( QStringLiteral(
"PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
2244 if ( tmpLyr.
multilineAlign == Qgis::LabelMultiLineAlignment::FollowPlacement )
2268 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
2271 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
2274 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
2280 QString dxfLayer = mDxfLayerNames[layerId][fid];
2282 QString wrapchr = tmpLyr.
wrapChar.isEmpty() ? QStringLiteral(
"\n" ) : tmpLyr.
wrapChar;
2287 bool prependSymb =
false;
2305 prependSymb =
false;
2314 symb = symb + wrapchr;
2318 prependSymb =
false;
2319 symb = wrapchr + symb;
2328 txt.prepend( symb );
2338 txt.replace( QChar( QChar::LineFeed ),
' ' );
2339 txt.replace( QChar( QChar::CarriageReturn ),
' ' );
2344 txt.replace( QString( QChar( QChar::CarriageReturn ) ) + QString( QChar( QChar::LineFeed ) ), QStringLiteral(
"\\P" ) );
2345 txt.replace( QChar( QChar::CarriageReturn ), QStringLiteral(
"\\P" ) );
2346 txt = txt.replace( wrapchr, QLatin1String(
"\\P" ) );
2347 txt.replace( QLatin1String(
" " ), QLatin1String(
"\\~" ) );
2351 txt.prepend(
"\\L" ).append(
"\\l" );
2356 txt.prepend(
"\\O" ).append(
"\\o" );
2361 txt.prepend(
"\\K" ).append(
"\\k" );
2364 txt.prepend( QStringLiteral(
"\\f%1|i%2|b%3;\\H%4;" )
2366 .arg( tmpLyr.
format().
font().italic() ? 1 : 0 )
2367 .arg( tmpLyr.
format().
font().bold() ? 1 : 0 )
2368 .arg( label->
getHeight() / ( 1 + txt.count( QStringLiteral(
"\\P" ) ) ) * 0.75 ) );
2376 if ( !mDxfLayerNames.contains( layerId ) )
2377 mDxfLayerNames[ layerId ] = QMap<QgsFeatureId, QString>();
2379 mDxfLayerNames[layerId][fid] =
layerName;
2395 QString splitLayerFieldName;
2397 if ( mLayerOutputAttributeIndex >= 0 && mLayerOutputAttributeIndex < fields.
size() )
2399 splitLayerFieldName = fields.
at( mLayerOutputAttributeIndex ).
name();
2402 return splitLayerFieldName;