62using namespace Qt::StringLiterals;
65#define strcasecmp( a, b ) stricmp( a, b )
77 mMapSettings = settings;
93 mLayerNameAttribute.clear();
94 mLayerOverriddenName.clear();
96 mLayerList.reserve( layers.size() );
97 for (
const DxfLayer &dxfLayer : layers )
99 mLayerList << dxfLayer.layer();
100 if ( dxfLayer.layerOutputAttributeIndex() >= 0 )
102 mLayerNameAttribute.insert( dxfLayer.layer()->id(), dxfLayer.layerOutputAttributeIndex() );
104 if ( dxfLayer.buildDataDefinedBlocks() )
106 mLayerDDBlockMaxNumberOfClasses.insert( dxfLayer.layer()->id(), dxfLayer.dataDefinedBlocksMaximumNumberOfClasses() );
108 if ( !dxfLayer.overriddenName().isEmpty() )
110 mLayerOverriddenName.insert( dxfLayer.layer()->id(), dxfLayer.overriddenName() );
143 if ( !mForce2d && p.
is3D() && std::isfinite( p.
z() ) )
150 int minDist = std::numeric_limits<int>::max();
152 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ) && minDist > 0; ++i )
154 int dist = color_distance( color.rgba(), i );
155 if ( dist >= minDist )
162 if ( minDist == 0 && minDistAt != 7 )
166 if ( color.alpha() == 255 )
170 int c = ( color.red() & 0xff ) * 0x10000 + ( color.green() & 0xff ) * 0x100 + ( color.blue() & 0xff );
172 if ( transparencyCode != -1 && color.alpha() < 255 )
173 writeGroup( transparencyCode, 0x2000000 | color.alpha() );
178 mTextStream << u
"%1\n"_s.arg( code, 3, 10, QChar(
' ' ) );
183 mTextStream << u
"%1\n"_s.arg( i, 6, 10, QChar(
' ' ) );
189 if ( !s.contains(
'.' ) )
191 mTextStream << s <<
'\n';
196 mTextStream << s <<
'\n';
206 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
211 mTextStream.setDevice( d );
212 mTextStream.setEncoding( QStringConverter::encodingForName( encoding.toLocal8Bit() ).value_or( QStringConverter::Utf8 ) );
214 if ( mCrs.isValid() )
215 mMapSettings.setDestinationCrs( mCrs );
217 if ( mExtent.isEmpty() )
220 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
230 layerExtent = mMapSettings.layerToMapCoordinates( vl, layerExtent );
238 extent.combineExtentWith( layerExtent );
241 mMapSettings.setExtent(
extent );
245 mMapSettings.setExtent( mExtent );
248 if ( mMapSettings.extent().isEmpty() )
254 QList<QgsMapLayer *> layers;
255 QStringList skippedLayers;
256 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
266 if ( !mExtent.isEmpty() )
268 const QgsRectangle extentRect = mMapSettings.mapToLayerCoordinates( vl, mExtent );
281 skippedLayers << ml->name();
284 mMapSettings.setLayers( layers );
288 mMapSettings.setOutputSize( QSize( std::floor( mMapSettings.extent().width() * mFactor ), std::floor( mMapSettings.extent().height() * mFactor ) ) );
289 mMapSettings.setOutputDpi( dpi );
300 if ( !skippedLayers.isEmpty() )
302 mFeedbackMessage = QObject::tr(
"The following empty layers were skipped: %1" ).arg( skippedLayers.join(
", "_L1 ) );
313void QgsDxfExport::writeHeader(
const QString &codepage )
315 writeGroup( 999, u
"DXF created from QGIS"_s );
360 handle = mNextHandleId++;
362 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
364 writeGroup( code, QString::number( handle, 16 ) );
368void QgsDxfExport::writeTables()
375 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
376 switch ( mSymbologyExport )
381 slList = symbolLayers( context );
397 writeDefaultLinetypes();
400 for (
const auto &symbolLayer : std::as_const( slList ) )
402 writeSymbolLayerLinetype( symbolLayer.first );
415 const QStringList blockStrings = QStringList() << u
"*Model_Space"_s << u
"*Paper_Space"_s << u
"*Paper_Space0"_s;
416 for (
const QString &block : blockStrings )
420 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
426 for (
const auto &symbolLayer : std::as_const( slList ) )
428 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
432 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
435 if ( !mDataDefinedBlockInfo.contains( ml ) )
440 const QHash<uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
441 for (
const auto &blockInfo : symbolClasses )
443 writeSymbolTableBlockRef( blockInfo.blockName );
450 QString name = u
"symbolLayer%1"_s.arg( i++ );
451 writeSymbolTableBlockRef( name );
464 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
465 writeGroup( 100, u
"AcDbRegAppTableRecord"_s );
494 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
495 writeGroup( 100, u
"AcDbViewportTableRecord"_s );
505 writeGroup( 7, QgsPoint( mMapSettings.extent().center() ) );
506 writeGroup( 40, mMapSettings.extent().height() );
507 writeGroup( 41, mMapSettings.extent().width() / mMapSettings.extent().height() );
541 QSet<QString> layerNames;
542 const QList< QgsMapLayer * > layers = mMapSettings.layers();
543 for ( QgsMapLayer *ml : layers )
545 if ( !layerIsScaleBasedVisible( ml ) )
548 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
552 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
559 const QSet<QVariant> values = vl->
uniqueValues( attrIdx );
560 for (
const QVariant &v : values )
577 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
585 for (
const QString &
layerName : std::as_const( layerNames ) )
589 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
609 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
610 writeGroup( 100, u
"AcDbTextStyleTableRecord"_s );
626void QgsDxfExport::writeSymbolTableBlockRef(
const QString &blockName )
630 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
635void QgsDxfExport::writeBlocks()
640 static const QStringList blockStrings = QStringList() << u
"*Model_Space"_s << u
"*Paper_Space"_s << u
"*Paper_Space0"_s;
641 for (
const QString &block : blockStrings )
645 writeGroup( 330, QString::number( mBlockHandles[block], 16 ) );
661 QgsRenderContext ct = renderContext();
664 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
665 switch ( mSymbologyExport )
670 slList = symbolLayers( ct );
677 for (
const auto &symbolLayer : std::as_const( slList ) )
679 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
684 QgsSymbolRenderContext ctx( ct,
Qgis::RenderUnit::MapUnits, symbolLayer.second->opacity(),
false, symbolLayer.second->renderHints(),
nullptr );
687 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
689 if ( !mDataDefinedBlockInfo.contains( ml ) )
695 const QHash<uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
696 for (
const auto &blockInfo : symbolClasses )
698 ctx.setFeature( &blockInfo.feature );
699 ctx.renderContext().expressionContext().setFeature( blockInfo.feature );
700 writeSymbolLayerBlock( blockInfo.blockName, ml, ctx );
707 QString block( u
"symbolLayer%1"_s.arg( mBlockCounter++ ) );
708 writeSymbolLayerBlock( block, ml, ctx );
710 mPointSymbolBlocks.insert( ml, block );
711 mPointSymbolBlockSizes.insert( ml, ml->
dxfSize( ctx ) );
712 mPointSymbolBlockAngles.insert( ml, ml->
dxfAngle( ctx ) );
719 mBlockHandle = QString::number( mBlockHandles[blockName], 16 );
748void QgsDxfExport::writeEntities()
753 mBlockHandle = QString::number( mBlockHandles[u
"*Model_Space"_s], 16 );
756 for ( DxfLayerJob *job : std::as_const( mJobs ) )
762 writeEntitiesSymbolLevels( job );
767 const QgsCoordinateTransform ct( job->crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
769 QgsFeatureRequest request = QgsFeatureRequest().setSubsetOfAttributes( job->attributes, job->fields ).setExpressionContext( job->renderContext.expressionContext() );
770 QgsCoordinateTransform extentTransform = ct;
777 catch ( QgsCsException &e )
788 QgsFeatureIterator featureIt = job->featureSource.getFeatures( request );
793 job->renderContext.expressionContext().setFeature( fet );
794 QString lName(
dxfLayerName( job->splitLayerAttribute.isNull() ? job->layerDerivedName : fet.
attribute( job->splitLayerAttribute ).toString() ) );
796 sctx.setFeature( &fet );
798 if ( !job->renderer->willRenderFeature( fet, job->renderContext ) )
803 addFeature( sctx, ct, lName,
nullptr,
nullptr );
807 const QgsSymbolList symbolList = job->renderer->symbolsForFeature( fet, job->renderContext );
808 bool hasSymbology = symbolList.size() > 0;
812 for ( QgsSymbol *symbol : symbolList )
815 for ( QgsSymbolLayer *symbolLayer : symbolLayers )
820 if ( !isSymbolLayerEnabled( symbolLayer, sctx ) )
823 bool isGeometryGenerator = ( symbolLayer->layerType() ==
"GeometryGenerator"_L1 );
824 if ( isGeometryGenerator )
826 addGeometryGeneratorSymbolLayer( sctx, ct, lName, symbolLayer,
true );
830 addFeature( sctx, ct, lName, symbolLayer, symbol );
835 else if ( hasSymbology )
838 QgsSymbol *s = symbolList.first();
844 if ( !isSymbolLayerEnabled( s->
symbolLayer( 0 ), sctx ) )
851 addGeometryGeneratorSymbolLayer( sctx, ct, lName, s->
symbolLayer( 0 ),
false );
855 addFeature( sctx, ct, lName, s->
symbolLayer( 0 ), s );
859 if ( job->labelProvider )
861 job->labelProvider->registerFeature( fet, job->renderContext );
866 else if ( job->ruleBasedLabelProvider )
868 job->ruleBasedLabelProvider->registerFeature( fet, job->renderContext );
877 QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
878 image.setDotsPerMeterX( 96 / 25.4 * 1000 );
879 image.setDotsPerMeterY( 96 / 25.4 * 1000 );
880 QPainter painter( &image );
881 mRenderContext.setPainter( &painter );
883 mRenderContext.labelingEngine()->run( mRenderContext );
888void QgsDxfExport::prepareRenderers()
890 Q_ASSERT( mJobs.empty() );
892 mRenderContext = QgsRenderContext();
893 mRenderContext.setPathResolver( mMapSettings.pathResolver() );
894 mRenderContext.setRendererScale( mSymbologyScale );
895 mRenderContext.setExtent( mMapSettings.extent() );
897 da.
setSourceCrs( mMapSettings.destinationCrs(), mMapSettings.transformContext() );
899 mRenderContext.setDistanceArea( da );
900 mRenderContext.setScaleFactor( 96.0 / 25.4 );
901 mRenderContext.setMapToPixel(
902 QgsMapToPixel( 1.0 / mFactor, mMapSettings.extent().center().x(), mMapSettings.extent().center().y(), std::floor( mMapSettings.extent().width() * mFactor ), std::floor( mMapSettings.extent().height() * mFactor ), 0 )
909 mLabelingEngine = std::make_unique<QgsDefaultLabelingEngine>();
910 mLabelingEngine->setMapSettings( mMapSettings );
911 mRenderContext.setLabelingEngine( mLabelingEngine.get() );
913 const QList< QgsMapLayer * > layers = mMapSettings.layers();
914 for ( QgsMapLayer *ml : layers )
916 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
923 if ( !layerIsScaleBasedVisible( vl ) )
926 QString splitLayerAttribute;
927 int splitLayerAttributeIndex = mLayerNameAttribute.value( vl->
id(), -1 );
928 const QgsFields fields = vl->
fields();
929 if ( splitLayerAttributeIndex >= 0 && splitLayerAttributeIndex < fields.
size() )
930 splitLayerAttribute = fields.
at( splitLayerAttributeIndex ).
name();
931 DxfLayerJob *job =
new DxfLayerJob( vl, mMapSettings.layerStyleOverrides().value( vl->
id() ), mRenderContext,
this, splitLayerAttribute,
layerName( vl ) );
936void QgsDxfExport::writeEntitiesSymbolLevels(
DxfLayerJob *job )
938 QHash< QgsSymbol *, QList<QgsFeature> > features;
940 QgsRenderContext ctx = renderContext();
942 for ( QgsExpressionContextScope *scope : scopes )
947 QgsFeatureRequest req;
949 QgsCoordinateTransform ct( mMapSettings.destinationCrs(), job->
crs, mMapSettings.transformContext() );
954 catch (
const QgsCsException & )
956 QgsDebugError( u
"QgsDxfExport::writeEntitiesSymbolLevels(): extent reprojection failed"_s );
968 QgsSymbol *featureSymbol =
nullptr;
972 featureSymbol = job->
renderer->symbolForFeature( fet, ctx );
973 if ( !featureSymbol )
978 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
979 if ( it == features.end() )
981 it = features.insert( featureSymbol, QList<QgsFeature>() );
983 it.value().append( fet );
989 for ( QgsSymbol *symbol : symbols )
991 for (
int j = 0; j < symbol->symbolLayerCount(); j++ )
993 int level = symbol->symbolLayer( j )->renderingPass();
994 if ( level < 0 || level >= 1000 )
996 QgsSymbolLevelItem item( symbol, j );
997 while ( level >= levels.count() )
999 levels[level].append( item );
1006 for (
const QgsSymbolLevelItem &item : level )
1008 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
1009 if ( levelIt == features.end() )
1014 int llayer = item.layer();
1015 const QList<QgsFeature> &featureList = levelIt.value();
1016 QgsSymbolLayer *symbolLayer = levelIt.key()->symbolLayer( llayer );
1017 for (
const QgsFeature &feature : featureList )
1019 sctx.setFeature( &feature );
1020 sctx.renderContext().expressionContext().setFeature( feature );
1021 if ( !isSymbolLayerEnabled( symbolLayer, sctx ) )
1023 addFeature( sctx, ct, job->
layerName, symbolLayer, levelIt.key() );
1029void QgsDxfExport::stopRenderers()
1031 qDeleteAll( mJobs );
1035void QgsDxfExport::writeEndFile()
1042void QgsDxfExport::startSection()
1047void QgsDxfExport::endSection()
1056 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1064 writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() - halfSize ) );
1065 writeGroup( 1, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() - halfSize ) );
1066 writeGroup( 2, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() + halfSize ) );
1067 writeGroup( 3, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() + halfSize ) );
1072 QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
1073 if ( symbolLayer && blockIt != mPointSymbolBlocks.constEnd() )
1075 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, blockIt.value(), mPointSymbolBlockAngles.value( symbolLayer ), mPointSymbolBlockSizes.value( symbolLayer ) );
1080 QHash< const QgsSymbolLayer *, QHash<uint, DataDefinedBlockInfo> >::const_iterator ddBlockIt = mDataDefinedBlockInfo.constFind( symbolLayer );
1081 if ( symbolLayer && ctx.
feature() && ddBlockIt != mDataDefinedBlockInfo.constEnd() )
1083 const QHash<uint, DataDefinedBlockInfo> &symbolLayerDDBlocks = ddBlockIt.value();
1088 if ( symbolLayerDDBlocks.contains( ddSymbolHash ) )
1090 const DataDefinedBlockInfo &info = symbolLayerDDBlocks[ddSymbolHash];
1091 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, info.blockName, info.angle, info.size );
1097 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1098 if ( msl && symbol )
1108void QgsDxfExport::writePointBlockReference(
1112 const double scale = symbolLayer->
dxfSize( ctx ) / blockSize;
1122 if ( std::isfinite( scale ) && scale != 1.0 )
1136 QgsExpressionContext ctx = context;
1142 std::sort( keys.begin(), keys.end() );
1145 for (
int key : std::as_const( keys ) )
1147 const QVariant evaluated = prop.
value( key, ctx );
1150 hashValue =
qHash( evaluated );
1154 hashValue = hashValue ^
qHash( evaluated );
1164 int n = line.size();
1167 QgsDebugError( u
"writePolyline: empty line layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1173 QgsDebugError( u
"writePolyline: line too short layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1177 if ( mForce2d || !line.at( 0 ).is3D() )
1179 bool polygon = line[0] == line[line.size() - 1];
1195 for (
int i = 0; i < n; i++ )
1211 for (
int i = 0; i < n; i++ )
1220 writeGroup( 100, u
"AcDb3dPolylineVertex"_s );
1234void QgsDxfExport::appendCurve(
const QgsCurve &
c, QVector<QgsPoint> &points, QVector<double> &bulges )
1239 appendLineString( *qgis::down_cast<const QgsLineString *>( &
c ), points, bulges );
1243 appendCircularString( *qgis::down_cast<const QgsCircularString *>( &
c ), points, bulges );
1247 appendCompoundCurve( *qgis::down_cast<const QgsCompoundCurve *>( &
c ), points, bulges );
1251 QgsDebugError( u
"Unexpected curve type %1"_s.arg(
c.wktTypeStr() ) );
1256void QgsDxfExport::appendLineString(
const QgsLineString &ls, QVector<QgsPoint> &points, QVector<double> &bulges )
1258 for (
int i = 0; i < ls.
numPoints(); i++ )
1260 const QgsPoint &p = ls.
pointN( i );
1261 if ( !points.isEmpty() && points.last() == p )
1269void QgsDxfExport::appendCircularString(
const QgsCircularString &cs, QVector<QgsPoint> &points, QVector<double> &bulges )
1271 for (
int i = 0; i < cs.
numPoints() - 2; i += 2 )
1273 const QgsPoint &p1 = cs.
pointN( i );
1274 const QgsPoint &p2 = cs.
pointN( i + 1 );
1275 const QgsPoint &p3 = cs.
pointN( i + 2 );
1277 if ( points.isEmpty() || points.last() != p1 )
1279 else if ( !bulges.isEmpty() )
1280 bulges.removeLast();
1282 double a = ( M_PI - ( p1 - p2 ).angle() + ( p3 - p2 ).
angle() ) / 2.0;
1283 bulges << sin( a ) / cos( a );
1290void QgsDxfExport::appendCompoundCurve(
const QgsCompoundCurve &cc, QVector<QgsPoint> &points, QVector<double> &bulges )
1292 for (
int i = 0; i < cc.
nCurves(); i++ )
1294 const QgsCurve *
c = cc.
curveAt( i );
1296 appendCurve( *
c, points, bulges );
1305 QgsDebugError( u
"writePolyline: empty line layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1311 QgsDebugError( u
"writePolyline: line too short layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1315 QVector<QgsPoint> points;
1316 QVector<double> bulges;
1317 appendCurve( curve, points, bulges );
1319 if ( mForce2d || !curve.
is3D() )
1340 writeGroup( 70,
static_cast<int>( polylineFlags ) );
1343 for (
int i = 0; i < points.size(); i++ )
1346 if ( bulges[i] != 0.0 )
1363 for (
int i = 0; i < points.size(); i++ )
1372 writeGroup( 100, u
"AcDb3dPolylineVertex"_s );
1374 if ( bulges[i] != 0.0 )
1402 writeGroup( 70, hatchPattern ==
"SOLID"_L1 );
1406 for (
int i = 0; i < polygon.size(); ++i )
1413 for (
int j = 0; j < polygon[i].size(); ++j )
1441 writeGroup( 70, hatchPattern ==
"SOLID"_L1 );
1444 QVector<QVector<QgsPoint>> points;
1445 QVector<QVector<double>> bulges;
1448 points.reserve( ringCount + 1 );
1449 bulges.reserve( ringCount + 1 );
1451 points << QVector<QgsPoint>();
1452 bulges << QVector<double>();
1453 appendCurve( *polygon.
exteriorRing(), points.last(), bulges.last() );
1455 for (
int i = 0; i < ringCount; i++ )
1457 points << QVector<QgsPoint>();
1458 bulges << QVector<double>();
1459 appendCurve( *polygon.
interiorRing( i ), points.last(), bulges.last() );
1462 bool hasBulges =
false;
1463 for (
int i = 0; i < points.size() && !hasBulges; ++i )
1464 for (
int j = 0; j < points[i].size() && !hasBulges; ++j )
1465 hasBulges = bulges[i][j] != 0.0;
1469 for (
int i = 0; i < points.size(); ++i )
1476 for (
int j = 0; j < points[i].size(); ++j )
1499 double lblX = label->
getX();
1500 double lblY = label->
getY();
1525 switch ( offsetQuad )
1575 const QString haliString = exprVal.toString();
1576 if ( haliString.compare(
"Center"_L1, Qt::CaseInsensitive ) == 0 )
1580 else if ( haliString.compare(
"Right"_L1, Qt::CaseInsensitive ) == 0 )
1594 const QString valiString = exprVal.toString();
1595 if ( valiString.compare(
"Bottom"_L1, Qt::CaseInsensitive ) != 0 )
1597 if ( valiString.compare(
"Base"_L1, Qt::CaseInsensitive ) == 0 )
1601 else if ( valiString.compare(
"Half"_L1, Qt::CaseInsensitive ) == 0 )
1724 while ( t.length() > 250 )
1755 geom.transform( ct );
1764 penColor = colorFromSymbolLayer( symbolLayer, ctx );
1768 Qt::PenStyle penStyle( Qt::SolidLine );
1769 Qt::BrushStyle brushStyle( Qt::NoBrush );
1771 double offset = 0.0;
1775 width = symbolLayer->
dxfWidth( ctx );
1790 QString lineStyleName = u
"CONTINUOUS"_s;
1793 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
1799 writePoint( geom.constGet()->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1806 for (
int i = 0; i < cs.size(); i++ )
1808 writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1813 if ( penStyle != Qt::NoPen )
1815 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1816 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1828 QgsGeos geos( sourceGeom );
1831 sourceGeom = tempGeom.get();
1833 sourceGeom = geom.constGet();
1836 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( sourceGeom );
1839 writePolyline( *curve, layer, lineStyleName, penColor, width );
1843 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1849 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( gc->
geometryN( i ) );
1851 writePolyline( *curve, layer, lineStyleName, penColor, width );
1865 QgsGeos geos( sourceGeom );
1868 sourceGeom = tempGeom.get();
1870 sourceGeom = geom.constGet();
1873 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1882 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1888 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1889 Q_ASSERT( polygon );
1906 if ( brushStyle != Qt::NoBrush )
1908 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1915 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1916 Q_ASSERT( polygon );
1917 writePolygon( *polygon, layer, u
"SOLID"_s, brushColor );
1924 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1929 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1930 Q_ASSERT( polygon );
1931 writePolygon( *polygon, layer, u
"SOLID"_s, brushColor );
1947 return symbolLayer->
dxfColor( ctx );
1950QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayer *symbolLayer )
1952 QString lineStyleName = u
"CONTINUOUS"_s;
1955 return lineStyleName;
1958 QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
1959 if ( lineTypeIt != mLineStyles.constEnd() )
1961 lineStyleName = lineTypeIt.value();
1962 return lineStyleName;
1966 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
1973 int current_distance = std::numeric_limits<int>::max();
1974 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ); ++i )
1976 int dist = color_distance( pixel, i );
1977 if ( dist < current_distance )
1979 current_distance = dist;
1988int QgsDxfExport::color_distance( QRgb p1,
int index )
1990 if ( index > 255 || index < 0 )
1995 double redDiff = qRed( p1 ) - sDxfColors[index][0];
1996 double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
1997 double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
1999 QgsDebugMsgLevel( u
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8"_s
2000 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
2002 .arg( mDxfColors[index][0] )
2003 .arg( mDxfColors[index][1] )
2004 .arg( mDxfColors[index][2] )
2005 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ), 2 );
2007 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
2010QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
2012 return QColor::fromRgbF( r, g, b ).rgb();
2017 return mRenderContext;
2022 switch ( symbolUnits )
2041 return mapUnitsPerPixel;
2062 double mapUnitsPerPixel = mMapSettings.mapToPixel().mapUnitsPerPixel();
2064 double minSizeMU = std::numeric_limits<double>::lowest();
2067 minSizeMU = scale.
minSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2071 minSizeMU = std::max( minSizeMU, value );
2073 value = std::max( value, minSizeMU );
2075 double maxSizeMU = std::numeric_limits<double>::max();
2078 maxSizeMU = scale.
maxSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2082 maxSizeMU = std::min( maxSizeMU, value );
2084 value = std::min( value, maxSizeMU );
2087QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers(
QgsRenderContext &context )
2089 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
2100 maxSymbolLayers = 1;
2102 for (
int i = 0; i < maxSymbolLayers; ++i )
2104 symbolLayers.append( qMakePair( symbol->
symbolLayer( i ), symbol ) );
2109 return symbolLayers;
2112void QgsDxfExport::writeDefaultLinetypes()
2115 for (
const QString <ype : { u
"ByLayer"_s, u
"ByBlock"_s, u
"CONTINUOUS"_s } )
2119 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
2120 writeGroup( 100, u
"AcDbLinetypeTableRecord"_s );
2129 double das = dashSize();
2130 double dss = dashSeparatorSize();
2131 double dos = dotSize();
2133 QVector<qreal> dashVector( 2 );
2134 dashVector[0] = das;
2135 dashVector[1] = dss;
2138 QVector<qreal> dotVector( 2 );
2143 QVector<qreal> dashDotVector( 4 );
2144 dashDotVector[0] = das;
2145 dashDotVector[1] = dss;
2146 dashDotVector[2] = dos;
2147 dashDotVector[3] = dss;
2150 QVector<qreal> dashDotDotVector( 6 );
2151 dashDotDotVector[0] = das;
2152 dashDotDotVector[1] = dss;
2153 dashDotDotVector[2] = dos;
2154 dashDotDotVector[3] = dss;
2155 dashDotDotVector[4] = dos;
2156 dashDotDotVector[5] = dss;
2160void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayer *symbolLayer )
2169 if ( !customLinestyle.isEmpty() )
2171 QString name = u
"symbolLayer%1"_s.arg( mSymbolLayerCounter++ );
2172 writeLinetype( name, customLinestyle, unit );
2173 mLineStyles.insert( symbolLayer, name );
2177int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
2180 for (
const auto &symbolLayer : symbolLayers )
2182 const QgsSimpleLineSymbolLayer *simpleLine =
dynamic_cast< const QgsSimpleLineSymbolLayer *
>( symbolLayer.first );
2194void QgsDxfExport::writeLinetype(
const QString &styleName,
const QVector<qreal> &pattern,
Qgis::RenderUnit u )
2197 for ( qreal size : pattern )
2205 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
2206 writeGroup( 100, u
"AcDbLinetypeTableRecord"_s );
2215 for ( qreal size : pattern )
2218 double segmentLength = ( isGap ? -size : size );
2228 QgsGeometryGeneratorSymbolLayer *gg =
dynamic_cast<QgsGeometryGeneratorSymbolLayer *
>( symbolLayer );
2234 const QgsFeature *fet = ctx.
feature();
2240 QgsFeature f = *fet;
2244 geomExpr.prepare( &expressionContext );
2245 QgsGeometry geom = geomExpr.evaluate( &expressionContext ).value<QgsGeometry>();
2252 symbolExpressionContextScope->
setFeature( f );
2257 for (
int i = 0; i < nSymbolLayers; ++i )
2259 addFeature( ctx, ct, layer, symbol->
symbolLayer( i ), symbol );
2268 if ( !sl || !symbol )
2273 bool blockBreak =
false;
2280 blockBreak = !properties.isEmpty();
2288 if ( !layer || !layer->
enabled() )
2295double QgsDxfExport::dashSize()
const
2297 double size = mSymbologyScale * 0.002;
2298 return sizeToMapUnits( size );
2301double QgsDxfExport::dotSize()
const
2303 double size = mSymbologyScale * 0.0006;
2304 return sizeToMapUnits( size );
2307double QgsDxfExport::dashSeparatorSize()
const
2309 double size = mSymbologyScale * 0.0006;
2310 return sizeToMapUnits( size );
2313double QgsDxfExport::sizeToMapUnits(
double s )
const
2319QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
2327 case Qt::DashDotLine:
2328 return u
"DASHDOT"_s;
2329 case Qt::DashDotDotLine:
2330 return u
"DASHDOTDOT"_s;
2333 return u
"CONTINUOUS"_s;
2339 if ( name.isEmpty() )
2372bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer *layer )
const
2386 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
2389 if ( vl && vl->
id() ==
id )
2391 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
2401 const QByteArray codec = name.toLocal8Bit();
2402 if ( QTextCodec::codecForName( codec ) )
2405 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2408 if ( i !=
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2410 return DXF_ENCODINGS[i][0];
2420 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2422 for (
const QByteArray &codec : codecs )
2425 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2428 if ( i <
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2440 auto overriddenNameIt = mLayerOverriddenName.constFind( vl->
id() );
2441 if ( overriddenNameIt != mLayerOverriddenName.constEnd() && !overriddenNameIt.value().isEmpty() )
2443 return overriddenNameIt.value();
2470 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->
dataDefinedValues();
2475 QgsDebugMsgLevel( u
"PAL font definedFont: %1, Style: %2"_s.arg( dFont.toString(), dFont.styleName() ), 4 );
2505 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
2508 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
2511 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
2517 QString dxfLayer = mDxfLayerNames[layerId][fid];
2524 bool prependSymb =
false;
2542 prependSymb =
false;
2551 symb = symb + wrapchr;
2555 prependSymb =
false;
2556 symb = wrapchr + symb;
2565 txt.prepend( symb );
2575 txt.replace( QChar( QChar::LineFeed ),
' ' );
2576 txt.replace( QChar( QChar::CarriageReturn ),
' ' );
2581 txt.replace( QString( QChar( QChar::CarriageReturn ) ) + QString( QChar( QChar::LineFeed ) ), u
"\\P"_s );
2582 txt.replace( QChar( QChar::CarriageReturn ), u
"\\P"_s );
2583 txt = txt.replace( wrapchr,
"\\P"_L1 );
2584 txt.replace(
" "_L1,
"\\~"_L1 );
2588 txt.prepend(
"\\L" ).append(
"\\l" );
2593 txt.prepend(
"\\O" ).append(
"\\o" );
2598 txt.prepend(
"\\K" ).append(
"\\k" );
2601 txt.prepend( u
"\\f%1|i%2|b%3;\\H%4;"_s.arg( tmpLyr.
format().
font().family() )
2602 .arg( tmpLyr.
format().
font().italic() ? 1 : 0 )
2603 .arg( tmpLyr.
format().
font().bold() ? 1 : 0 )
2604 .arg( label->
getHeight() / ( 1 + txt.count( u
"\\P"_s ) ) * 0.75 ) );
2612 if ( !mDxfLayerNames.contains( layerId ) )
2613 mDxfLayerNames[layerId] = QMap<QgsFeatureId, QString>();
2615 mDxfLayerNames[layerId][fid] =
layerName;
2631 QString splitLayerFieldName;
2632 const QgsFields fields = mLayer->fields();
2633 if ( mLayerOutputAttributeIndex >= 0 && mLayerOutputAttributeIndex < fields.
size() )
2635 splitLayerFieldName = fields.
at( mLayerOutputAttributeIndex ).
name();
2638 return splitLayerFieldName;
2641void QgsDxfExport::createDDBlockInfo()
2643 int symbolLayerNr = 0;
2646 int ddMaxNumberOfClasses = -1;
2647 bool createDDBlocks = mLayerDDBlockMaxNumberOfClasses.contains( job->
featureSource.
id() );
2648 if ( createDDBlocks )
2650 ddMaxNumberOfClasses = mLayerDDBlockMaxNumberOfClasses[job->
featureSource.
id()];
2659 for (
const QgsSymbol *symbol : symbols )
2670 maxSymbolLayers = 1;
2673 for (
int i = 0; i < maxSymbolLayers; ++i )
2675 const QgsSymbolLayer *sl = symbol->
symbolLayer( i );
2682 if ( !hasBlockBreakingDataDefinedProperties( sl, symbol ) || !createDDBlocks )
2690 const QgsCoordinateTransform ct( job->
crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
2691 QgsFeatureRequest request
2693 QgsCoordinateTransform extentTransform = ct;
2699 catch ( QgsCsException &e )
2701 QgsDebugError( u
"Could not transform extent to layer extent: %1"_s.arg( e.
what() ) );
2707 QHash<uint, QPair<int, DataDefinedBlockInfo> > blockSymbolMap;
2712 uint symbolHash = dataDefinedSymbolClassHash( fet, properties, sctx.renderContext().expressionContext() );
2713 if ( blockSymbolMap.contains( symbolHash ) )
2715 blockSymbolMap[symbolHash].first += 1;
2719 sctx.setFeature( &fet );
2720 sctx.renderContext().expressionContext().setFeature( fet );
2722 DataDefinedBlockInfo blockInfo;
2723 blockInfo.blockName = u
"symbolLayer%1class%2"_s.arg( symbolLayerNr ).arg( symbolHash );
2724 blockInfo.angle = sl->
dxfAngle( sctx );
2725 blockInfo.size = sl->
dxfSize( sctx );
2726 blockInfo.feature = fet;
2728 blockSymbolMap.insert( symbolHash, qMakePair( 1, blockInfo ) );
2733 QMultiMap<int, uint> occurrences;
2734 QHash<uint, QPair<int, DataDefinedBlockInfo> >::const_iterator blockSymbolIt = blockSymbolMap.constBegin();
2735 for ( ; blockSymbolIt != blockSymbolMap.constEnd(); ++blockSymbolIt )
2737 occurrences.insert( blockSymbolIt.value().first, blockSymbolIt.key() );
2740 QHash<uint, DataDefinedBlockInfo > applyBlockSymbolMap;
2741 int nInsertedClasses = 0;
2742 QMultiMap<int, uint>::const_iterator occIt = occurrences.constEnd();
2743 while ( occurrences.size() > 0 && occIt != occurrences.constBegin() )
2746 applyBlockSymbolMap.insert( occIt.value(), blockSymbolMap[occIt.value()].second );
2748 if ( ddMaxNumberOfClasses != -1 && nInsertedClasses >= ddMaxNumberOfClasses )
2755 mDataDefinedBlockInfo.insert( sl, applyBlockSymbolMap );
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
DistanceUnit
Units of distance.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
LabelQuadrantPosition
Label quadrant positions.
@ Miter
Use mitered joins.
@ FollowPlacement
Alignment follows placement of label, e.g., labels to the left of a feature will be drawn with right ...
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
@ Flat
Flat cap (in line with start/end of line).
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ CircularString
CircularString.
@ CurvePolygon
CurvePolygon.
@ MultiSurface
MultiSurface.
@ PerFeature
Keeps the number of features and export symbology per feature.
@ PerSymbolLayer
Exports one feature per symbol layer (considering symbol levels).
@ NoSymbology
Export only data.
@ Reverse
Reverse/inverse transform (from destination to source).
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean.
Circular string geometry type.
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the point at index i within the circular string.
Compound curve geometry type.
int nCurves() const
Returns the number of curves in the geometry.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
Represents a coordinate reference system (CRS).
Qgis::DistanceUnit mapUnits
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
virtual int numPoints() const =0
Returns the number of points in the curve.
virtual bool isClosed() const
Returns true if the curve is closed.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch).
ExportResult
The result of an export as dxf operation.
@ DeviceNotWritableError
Device not writable error.
@ Success
Successful export.
@ EmptyExtentError
Empty extent, no extent given and no extent could be derived from layers.
@ InvalidDeviceError
Invalid device error.
void writeCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width)
Write circle (as polyline).
static Q_DECL_DEPRECATED double mapUnitScaleFactor(double scale, Qgis::RenderUnit symbolUnits, Qgis::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
ExportResult writeToFile(QIODevice *d, const QString &codec)
Export to a dxf file in the given encoding.
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Write line (as a polyline).
void writeGroup(int code, int i)
Write a tuple of group code and integer value.
QString layerName(const QString &id, const QgsFeature &f) const
Gets layer name for feature.
void setFlags(QgsDxfExport::Flags flags)
Sets the export flags.
QgsRectangle extent() const
Gets extent of area to export.
@ FlagHairlineWidthExport
@ FlagOnlySelectedFeatures
Use only selected features for the export.
@ FlagNoMText
Export text as TEXT elements. If not set, text will be exported as MTEXT elements.
void writeInt(int i)
Write an integer value.
void writeMText(const QString &layer, const QString &text, const QgsPoint &pt, double width, double angle, const QColor &color)
Write mtext (MTEXT).
QgsDxfExport()
Constructor for QgsDxfExport.
int writeHandle(int code=5, int handle=0)
Write a tuple of group code and a handle.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination CRS, or an invalid CRS if no reprojection will be done.
HAlign
Horizontal alignments.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Set destination CRS.
void addLayers(const QList< QgsDxfExport::DxfLayer > &layers)
Add layers to export.
static QString dxfLayerName(const QString &name)
Returns cleaned layer name for use in DXF.
void writeDouble(double d)
Write a floating point value.
void writeText(const QString &layer, const QString &text, const QgsPoint &pt, double size, double angle, const QColor &color, QgsDxfExport::HAlign hali=QgsDxfExport::HAlign::Undefined, QgsDxfExport::VAlign vali=QgsDxfExport::VAlign::Undefined)
Write text (TEXT).
void writeString(const QString &s)
Write a string value.
void writePolygon(const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH).
QFlags< DxfPolylineFlag > DxfPolylineFlags
void drawLabel(const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings) override
Add a label to the dxf output.
static QString dxfEncoding(const QString &name)
Returns DXF encoding for Qt encoding.
static int closestColorMatch(QRgb color)
Gets DXF palette index of nearest entry for given color.
void writePoint(const QString &layer, const QColor &color, const QgsPoint &pt)
Write point.
Qgis::DistanceUnit mapUnits() const
Retrieve map units.
Q_DECL_DEPRECATED void registerDxfLayer(const QString &layerId, QgsFeatureId fid, const QString &layer)
Register name of layer for feature.
QgsDxfExport::Flags flags() const
Returns the export flags.
VAlign
Vertical alignments.
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
void writePolyline(const QgsPointSequence &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE).
@ ContinuousPattern
The linetype pattern is generated continuously around the vertices of this polyline.
@ Closed
This is a closed polyline (or a polygon mesh closed in the M direction).
@ Curve
Curve-fit vertices have been added.
static QStringList encodings()
Returns list of available DXF encodings.
void setMapSettings(const QgsMapSettings &settings)
Set map settings and assign layer name attributes.
void writeGroupCode(int code)
Write a group code.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QList< QgsExpressionContextScope * > scopes()
Returns a list of scopes contained within the stack.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature()).
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Container of fields for a vector layer.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
QString geometryExpression() const
Gets the expression to generate this geometry.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
A geometry is the spatial representation of a feature.
Describes a feature that should be used within the labeling engine.
QgsPointXY anchorPosition() const
In case of quadrand or aligned positioning, this is set to the anchor point.
QString labelText() const
Text of the label.
bool reverseDirectionSymbol() const
Returns true if direction symbols should be reversed.
DirectionSymbolPlacement directionSymbolPlacement() const
Returns the placement for direction symbols.
QString leftDirectionSymbol() const
Returns the string to use for left direction arrows.
@ SymbolLeftRight
Place direction symbols on left/right of label.
@ SymbolAbove
Place direction symbols on above label.
@ SymbolBelow
Place direction symbols on below label.
QString rightDirectionSymbol() const
Returns the string to use for right direction arrows.
bool addDirectionSymbol() const
Returns true if '<' or '>' (or custom strings set via leftDirectionSymbol and rightDirectionSymbol) w...
Qgis::LabelQuadrantPosition quadrant() const
Returns the quadrant in which to offset labels from the point.
Line string geometry type, with support for z-dimension and m-values.
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsLayerMetadata metadata
Contains configuration for rendering maps.
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
Abstract base class for marker symbol layers.
double size() const
Returns the symbol size.
double dxfSize(QgsSymbolRenderContext &context) const override
Gets marker size.
double dxfAngle(QgsSymbolRenderContext &context) const override
Gets angle.
Qgis::RenderUnit sizeUnit() const
Returns the units for the symbol's size.
Contains settings for how a map layer will be labeled.
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
QString wrapChar
Wrapping character string.
Qgis::LabelPlacement placement
Label placement mode.
bool drawLabels
Whether to draw labels for this layer.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label's property collection, used for data defined overrides.
Qgis::LabelMultiLineAlignment multilineAlign
Horizontal alignment of multi-line labels.
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
@ Vali
Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top).
@ Hali
Horizontal alignment for data defined label position (Left, Center, Right).
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
const QgsLabelPointSettings & pointSettings() const
Returns the label point settings, which contain settings related to how the label engine places and f...
Point geometry type, with support for z-dimension and m-values.
static QgsProject * instance()
Returns the QgsProject singleton instance.
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
bool hasActiveProperties() const final
Returns true if the collection has any active properties, or false if all properties within the colle...
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double convertToMapUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
QgsExpressionContext & expressionContext()
Gets the expression context.
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Abstract base class for symbol layers.
virtual Q_DECL_DEPRECATED double dxfSize(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
Gets marker size.
virtual Q_DECL_DEPRECATED double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
Gets offset.
virtual QColor dxfBrushColor(QgsSymbolRenderContext &context) const
Gets brush/fill color.
@ LayerEnabled
Whether symbol layer is enabled.
virtual Qt::PenStyle dxfPenStyle() const
Gets pen style.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QColor dxfColor(QgsSymbolRenderContext &context) const
Gets color.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual Q_DECL_DEPRECATED double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
Gets line width.
virtual double dxfAngle(QgsSymbolRenderContext &context) const
Gets angle.
virtual bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const
write as DXF
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual Qt::BrushStyle dxfBrushStyle() const
Gets brush/fill style.
virtual QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const
Gets dash pattern.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
const QgsFeature * feature() const
Returns the current feature being rendered.
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
void setFeature(const QgsFeature *f)
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Qgis::SymbolType type() const
Returns the symbol's type.
Container for all settings relating to text rendering.
void setFont(const QFont &font)
Sets the font used for rendering text.
QColor color() const
Returns the color that text will be rendered in.
QFont font() const
Returns the font used for rendering text.
Adds extra information to QgsLabelFeature for text labels.
QFont definedFont() const
Font to be used for rendering.
const QMap< QgsPalLayerSettings::Property, QVariant > & dataDefinedValues() const
Gets data-defined values.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) override
Gets an iterator for features matching the specified request.
QString id() const
Returns the layer id of the source layer.
QgsFields fields() const
Returns the fields that will be available for features that are retrieved from this source.
Represents a vector layer which manages a vector based dataset.
QgsRectangle extent() const final
Returns the extent of the layer.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
Q_INVOKABLE QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const final
Calculates a list of unique values contained within an attribute in the layer.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
QgsFeatureId featureId() const
Returns the unique ID of the feature.
QgsLabelFeature * feature()
Returns the parent feature.
LabelPosition is a candidate feature label position.
double getAlpha() const
Returns the angle to rotate text (in radians).
bool isReversedFromLineDirection() const
Returns true if the label direction is the reversed from the line or polygon ring direction.
Qgis::LabelQuadrantPosition quadrant() const
Returns the quadrant associated with this label position.
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
double getX(int i=0) const
Returns the down-left x coordinate.
double getY(int i=0) const
Returns the down-left y coordinate.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored).
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
uint qHash(const QVariant &variant)
Hash for QVariant.
#define Q_NOWARN_DEPRECATED_POP
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QVector< QgsRingSequence > QgsCoordinateSequence
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
#define DXF_HANDPLOTSTYLE
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
QList< QgsSymbolLayer * > QgsSymbolLayerList
Holds information about each layer in a DXF job.
QSet< QString > attributes
std::unique_ptr< QgsFeatureRenderer > renderer
QgsRenderContext renderContext
QgsFeatureIds selectedFeatureIds
QgsCoordinateReferenceSystem crs
QgsVectorLayerFeatureSource featureSource
Encapsulates the properties of a vector layer containing features that will be exported to the DXF fi...
QString splitLayerAttribute() const
Returns the name of the field used to split the source layer's features into multiple exported DXF la...