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 mDevice->write( mCodec->fromUnicode( u
"%1\n"_s.arg( code, 3, 10, QChar(
' ' ) ) ) );
183 mDevice->write( mCodec->fromUnicode( u
"%1\n"_s.arg( i, 6, 10, QChar(
' ' ) ) ) );
189 if ( !s.contains(
'.' ) )
196 mDevice->write( mCodec->fromUnicode( s +
'\n' ) );
206 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
212 mCodec = QTextCodec::codecForName( encoding.toLocal8Bit() );
218 if ( mCrs.isValid() )
219 mMapSettings.setDestinationCrs( mCrs );
221 if ( mExtent.isEmpty() )
224 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
234 layerExtent = mMapSettings.layerToMapCoordinates( vl, layerExtent );
242 extent.combineExtentWith( layerExtent );
245 mMapSettings.setExtent(
extent );
249 mMapSettings.setExtent( mExtent );
252 if ( mMapSettings.extent().isEmpty() )
258 QList<QgsMapLayer *> layers;
259 QStringList skippedLayers;
260 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
270 if ( !mExtent.isEmpty() )
272 const QgsRectangle extentRect = mMapSettings.mapToLayerCoordinates( vl, mExtent );
285 skippedLayers << ml->name();
288 mMapSettings.setLayers( layers );
292 mMapSettings.setOutputSize( QSize( std::floor( mMapSettings.extent().width() * mFactor ), std::floor( mMapSettings.extent().height() * mFactor ) ) );
293 mMapSettings.setOutputDpi( dpi );
304 if ( !skippedLayers.isEmpty() )
306 mFeedbackMessage = QObject::tr(
"The following empty layers were skipped: %1" ).arg( skippedLayers.join(
", "_L1 ) );
317void QgsDxfExport::writeHeader(
const QString &codepage )
319 writeGroup( 999, u
"DXF created from QGIS"_s );
364 handle = mNextHandleId++;
366 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
368 writeGroup( code, QString::number( handle, 16 ) );
372void QgsDxfExport::writeTables()
379 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
380 switch ( mSymbologyExport )
385 slList = symbolLayers( context );
401 writeDefaultLinetypes();
404 for (
const auto &symbolLayer : std::as_const( slList ) )
406 writeSymbolLayerLinetype( symbolLayer.first );
419 const QStringList blockStrings = QStringList() << u
"*Model_Space"_s << u
"*Paper_Space"_s << u
"*Paper_Space0"_s;
420 for (
const QString &block : blockStrings )
424 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
430 for (
const auto &symbolLayer : std::as_const( slList ) )
432 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
436 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
439 if ( !mDataDefinedBlockInfo.contains( ml ) )
444 const QHash<uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
445 for (
const auto &blockInfo : symbolClasses )
447 writeSymbolTableBlockRef( blockInfo.blockName );
454 QString name = u
"symbolLayer%1"_s.arg( i++ );
455 writeSymbolTableBlockRef( name );
468 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
469 writeGroup( 100, u
"AcDbRegAppTableRecord"_s );
498 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
499 writeGroup( 100, u
"AcDbViewportTableRecord"_s );
509 writeGroup( 7, QgsPoint( mMapSettings.extent().center() ) );
510 writeGroup( 40, mMapSettings.extent().height() );
511 writeGroup( 41, mMapSettings.extent().width() / mMapSettings.extent().height() );
545 QSet<QString> layerNames;
546 const QList< QgsMapLayer * > layers = mMapSettings.layers();
547 for ( QgsMapLayer *ml : layers )
549 if ( !layerIsScaleBasedVisible( ml ) )
552 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
556 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
563 const QSet<QVariant> values = vl->
uniqueValues( attrIdx );
564 for (
const QVariant &v : values )
581 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
589 for (
const QString &
layerName : std::as_const( layerNames ) )
593 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
613 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
614 writeGroup( 100, u
"AcDbTextStyleTableRecord"_s );
630void QgsDxfExport::writeSymbolTableBlockRef(
const QString &blockName )
634 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
639void QgsDxfExport::writeBlocks()
644 static const QStringList blockStrings = QStringList() << u
"*Model_Space"_s << u
"*Paper_Space"_s << u
"*Paper_Space0"_s;
645 for (
const QString &block : blockStrings )
649 writeGroup( 330, QString::number( mBlockHandles[block], 16 ) );
665 QgsRenderContext ct = renderContext();
668 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
669 switch ( mSymbologyExport )
674 slList = symbolLayers( ct );
681 for (
const auto &symbolLayer : std::as_const( slList ) )
683 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
688 QgsSymbolRenderContext ctx( ct,
Qgis::RenderUnit::MapUnits, symbolLayer.second->opacity(),
false, symbolLayer.second->renderHints(),
nullptr );
691 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
693 if ( !mDataDefinedBlockInfo.contains( ml ) )
699 const QHash<uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
700 for (
const auto &blockInfo : symbolClasses )
702 ctx.setFeature( &blockInfo.feature );
703 ctx.renderContext().expressionContext().setFeature( blockInfo.feature );
704 writeSymbolLayerBlock( blockInfo.blockName, ml, ctx );
711 QString block( u
"symbolLayer%1"_s.arg( mBlockCounter++ ) );
712 writeSymbolLayerBlock( block, ml, ctx );
714 mPointSymbolBlocks.insert( ml, block );
715 mPointSymbolBlockSizes.insert( ml, ml->
dxfSize( ctx ) );
716 mPointSymbolBlockAngles.insert( ml, ml->
dxfAngle( ctx ) );
723 mBlockHandle = QString::number( mBlockHandles[blockName], 16 );
752void QgsDxfExport::writeEntities()
757 mBlockHandle = QString::number( mBlockHandles[u
"*Model_Space"_s], 16 );
760 for ( DxfLayerJob *job : std::as_const( mJobs ) )
766 writeEntitiesSymbolLevels( job );
771 const QgsCoordinateTransform ct( job->crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
773 QgsFeatureRequest request = QgsFeatureRequest().setSubsetOfAttributes( job->attributes, job->fields ).setExpressionContext( job->renderContext.expressionContext() );
774 QgsCoordinateTransform extentTransform = ct;
781 catch ( QgsCsException &e )
792 QgsFeatureIterator featureIt = job->featureSource.getFeatures( request );
797 job->renderContext.expressionContext().setFeature( fet );
798 QString lName(
dxfLayerName( job->splitLayerAttribute.isNull() ? job->layerDerivedName : fet.
attribute( job->splitLayerAttribute ).toString() ) );
800 sctx.setFeature( &fet );
802 if ( !job->renderer->willRenderFeature( fet, job->renderContext ) )
807 addFeature( sctx, ct, lName,
nullptr,
nullptr );
811 const QgsSymbolList symbolList = job->renderer->symbolsForFeature( fet, job->renderContext );
812 bool hasSymbology = symbolList.size() > 0;
816 for ( QgsSymbol *symbol : symbolList )
819 for ( QgsSymbolLayer *symbolLayer : symbolLayers )
824 if ( !isSymbolLayerEnabled( symbolLayer, sctx ) )
827 bool isGeometryGenerator = ( symbolLayer->layerType() ==
"GeometryGenerator"_L1 );
828 if ( isGeometryGenerator )
830 addGeometryGeneratorSymbolLayer( sctx, ct, lName, symbolLayer,
true );
834 addFeature( sctx, ct, lName, symbolLayer, symbol );
839 else if ( hasSymbology )
842 QgsSymbol *s = symbolList.first();
848 if ( !isSymbolLayerEnabled( s->
symbolLayer( 0 ), sctx ) )
855 addGeometryGeneratorSymbolLayer( sctx, ct, lName, s->
symbolLayer( 0 ),
false );
859 addFeature( sctx, ct, lName, s->
symbolLayer( 0 ), s );
863 if ( job->labelProvider )
865 job->labelProvider->registerFeature( fet, job->renderContext, QgsLabelFeatureDetails() );
870 else if ( job->ruleBasedLabelProvider )
872 job->ruleBasedLabelProvider->registerFeature( fet, job->renderContext, QgsLabelFeatureDetails() );
881 QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
882 image.setDotsPerMeterX( 96 / 25.4 * 1000 );
883 image.setDotsPerMeterY( 96 / 25.4 * 1000 );
884 QPainter painter( &image );
885 mRenderContext.setPainter( &painter );
887 mRenderContext.labelingEngine()->run( mRenderContext );
892void QgsDxfExport::prepareRenderers()
894 Q_ASSERT( mJobs.empty() );
897 mRenderContext.setRendererScale( mSymbologyScale );
898 mRenderContext.setMapToPixel(
899 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 )
906 mLabelingEngine = std::make_unique<QgsDefaultLabelingEngine>( mMapSettings );
907 mRenderContext.setLabelingEngine( mLabelingEngine.get() );
909 const QList< QgsMapLayer * > layers = mMapSettings.layers();
910 for ( QgsMapLayer *ml : layers )
912 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
919 if ( !layerIsScaleBasedVisible( vl ) )
922 QString splitLayerAttribute;
923 int splitLayerAttributeIndex = mLayerNameAttribute.value( vl->
id(), -1 );
924 const QgsFields fields = vl->
fields();
925 if ( splitLayerAttributeIndex >= 0 && splitLayerAttributeIndex < fields.
size() )
926 splitLayerAttribute = fields.
at( splitLayerAttributeIndex ).
name();
927 DxfLayerJob *job =
new DxfLayerJob( vl, mMapSettings.layerStyleOverrides().value( vl->
id() ), mRenderContext,
this, splitLayerAttribute,
layerName( vl ) );
932void QgsDxfExport::writeEntitiesSymbolLevels(
DxfLayerJob *job )
934 QHash< QgsSymbol *, QList<QgsFeature> > features;
936 QgsRenderContext ctx = renderContext();
938 for ( QgsExpressionContextScope *scope : scopes )
943 QgsFeatureRequest req;
945 QgsCoordinateTransform ct( mMapSettings.destinationCrs(), job->
crs, mMapSettings.transformContext() );
950 catch (
const QgsCsException & )
952 QgsDebugError( u
"QgsDxfExport::writeEntitiesSymbolLevels(): extent reprojection failed"_s );
964 QgsSymbol *featureSymbol =
nullptr;
968 featureSymbol = job->
renderer->symbolForFeature( fet, ctx );
969 if ( !featureSymbol )
974 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
975 if ( it == features.end() )
977 it = features.insert( featureSymbol, QList<QgsFeature>() );
979 it.value().append( fet );
985 for ( QgsSymbol *symbol : symbols )
987 for (
int j = 0; j < symbol->symbolLayerCount(); j++ )
989 int level = symbol->symbolLayer( j )->renderingPass();
990 if ( level < 0 || level >= 1000 )
992 QgsSymbolLevelItem item( symbol, j );
993 while ( level >= levels.count() )
995 levels[level].append( item );
1002 for (
const QgsSymbolLevelItem &item : level )
1004 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
1005 if ( levelIt == features.end() )
1010 int llayer = item.layer();
1011 const QList<QgsFeature> &featureList = levelIt.value();
1012 QgsSymbolLayer *symbolLayer = levelIt.key()->symbolLayer( llayer );
1013 for (
const QgsFeature &feature : featureList )
1015 sctx.setFeature( &feature );
1016 sctx.renderContext().expressionContext().setFeature( feature );
1017 if ( !isSymbolLayerEnabled( symbolLayer, sctx ) )
1019 addFeature( sctx, ct, job->
layerName, symbolLayer, levelIt.key() );
1025void QgsDxfExport::stopRenderers()
1027 qDeleteAll( mJobs );
1031void QgsDxfExport::writeEndFile()
1033 mDevice->write( mCodec->fromUnicode(
DXF_TRAILER ) );
1038void QgsDxfExport::startSection()
1043void QgsDxfExport::endSection()
1052 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1060 writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() - halfSize ) );
1061 writeGroup( 1, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() - halfSize ) );
1062 writeGroup( 2, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() + halfSize ) );
1063 writeGroup( 3, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() + halfSize ) );
1068 QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
1069 if ( symbolLayer && blockIt != mPointSymbolBlocks.constEnd() )
1071 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, blockIt.value(), mPointSymbolBlockAngles.value( symbolLayer ), mPointSymbolBlockSizes.value( symbolLayer ) );
1076 QHash< const QgsSymbolLayer *, QHash<uint, DataDefinedBlockInfo> >::const_iterator ddBlockIt = mDataDefinedBlockInfo.constFind( symbolLayer );
1077 if ( symbolLayer && ctx.
feature() && ddBlockIt != mDataDefinedBlockInfo.constEnd() )
1079 const QHash<uint, DataDefinedBlockInfo> &symbolLayerDDBlocks = ddBlockIt.value();
1084 if ( symbolLayerDDBlocks.contains( ddSymbolHash ) )
1086 const DataDefinedBlockInfo &info = symbolLayerDDBlocks[ddSymbolHash];
1087 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, info.blockName, info.angle, info.size );
1093 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1094 if ( msl && symbol )
1104void QgsDxfExport::writePointBlockReference(
1108 const double scale = symbolLayer->
dxfSize( ctx ) / blockSize;
1118 if ( std::isfinite( scale ) && scale != 1.0 )
1132 QgsExpressionContext ctx = context;
1138 std::sort( keys.begin(), keys.end() );
1141 for (
int key : std::as_const( keys ) )
1143 const QVariant evaluated = prop.
value( key, ctx );
1146 hashValue =
qHash( evaluated );
1150 hashValue = hashValue ^
qHash( evaluated );
1160 int n = line.size();
1163 QgsDebugError( u
"writePolyline: empty line layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1169 QgsDebugError( u
"writePolyline: line too short layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1173 if ( mForce2d || !line.at( 0 ).is3D() )
1175 bool polygon = line[0] == line[line.size() - 1];
1191 for (
int i = 0; i < n; i++ )
1207 for (
int i = 0; i < n; i++ )
1216 writeGroup( 100, u
"AcDb3dPolylineVertex"_s );
1230void QgsDxfExport::appendCurve(
const QgsCurve &
c, QVector<QgsPoint> &points, QVector<double> &bulges )
1235 appendLineString( *qgis::down_cast<const QgsLineString *>( &
c ), points, bulges );
1239 appendCircularString( *qgis::down_cast<const QgsCircularString *>( &
c ), points, bulges );
1243 appendCompoundCurve( *qgis::down_cast<const QgsCompoundCurve *>( &
c ), points, bulges );
1247 QgsDebugError( u
"Unexpected curve type %1"_s.arg(
c.wktTypeStr() ) );
1252void QgsDxfExport::appendLineString(
const QgsLineString &ls, QVector<QgsPoint> &points, QVector<double> &bulges )
1254 for (
int i = 0; i < ls.
numPoints(); i++ )
1256 const QgsPoint &p = ls.
pointN( i );
1257 if ( !points.isEmpty() && points.last() == p )
1265void QgsDxfExport::appendCircularString(
const QgsCircularString &cs, QVector<QgsPoint> &points, QVector<double> &bulges )
1267 for (
int i = 0; i < cs.
numPoints() - 2; i += 2 )
1269 const QgsPoint &p1 = cs.
pointN( i );
1270 const QgsPoint &p2 = cs.
pointN( i + 1 );
1271 const QgsPoint &p3 = cs.
pointN( i + 2 );
1273 if ( points.isEmpty() || points.last() != p1 )
1275 else if ( !bulges.isEmpty() )
1276 bulges.removeLast();
1278 double a = ( M_PI - ( p1 - p2 ).angle() + ( p3 - p2 ).
angle() ) / 2.0;
1279 bulges << sin( a ) / cos( a );
1286void QgsDxfExport::appendCompoundCurve(
const QgsCompoundCurve &cc, QVector<QgsPoint> &points, QVector<double> &bulges )
1288 for (
int i = 0; i < cc.
nCurves(); i++ )
1290 const QgsCurve *
c = cc.
curveAt( i );
1292 appendCurve( *
c, points, bulges );
1301 QgsDebugError( u
"writePolyline: empty line layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1307 QgsDebugError( u
"writePolyline: line too short layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1311 QVector<QgsPoint> points;
1312 QVector<double> bulges;
1313 appendCurve( curve, points, bulges );
1315 if ( mForce2d || !curve.
is3D() )
1336 writeGroup( 70,
static_cast<int>( polylineFlags ) );
1339 for (
int i = 0; i < points.size(); i++ )
1342 if ( bulges[i] != 0.0 )
1359 for (
int i = 0; i < points.size(); i++ )
1368 writeGroup( 100, u
"AcDb3dPolylineVertex"_s );
1370 if ( bulges[i] != 0.0 )
1398 writeGroup( 70, hatchPattern ==
"SOLID"_L1 );
1402 for (
int i = 0; i < polygon.size(); ++i )
1409 for (
int j = 0; j < polygon[i].size(); ++j )
1437 writeGroup( 70, hatchPattern ==
"SOLID"_L1 );
1440 QVector<QVector<QgsPoint>> points;
1441 QVector<QVector<double>> bulges;
1444 points.reserve( ringCount + 1 );
1445 bulges.reserve( ringCount + 1 );
1447 points << QVector<QgsPoint>();
1448 bulges << QVector<double>();
1449 appendCurve( *polygon.
exteriorRing(), points.last(), bulges.last() );
1451 for (
int i = 0; i < ringCount; i++ )
1453 points << QVector<QgsPoint>();
1454 bulges << QVector<double>();
1455 appendCurve( *polygon.
interiorRing( i ), points.last(), bulges.last() );
1458 bool hasBulges =
false;
1459 for (
int i = 0; i < points.size() && !hasBulges; ++i )
1460 for (
int j = 0; j < points[i].size() && !hasBulges; ++j )
1461 hasBulges = bulges[i][j] != 0.0;
1465 for (
int i = 0; i < points.size(); ++i )
1472 for (
int j = 0; j < points[i].size(); ++j )
1495 double lblX = label->
getX();
1496 double lblY = label->
getY();
1521 switch ( offsetQuad )
1571 const QString haliString = exprVal.toString();
1572 if ( haliString.compare(
"Center"_L1, Qt::CaseInsensitive ) == 0 )
1576 else if ( haliString.compare(
"Right"_L1, Qt::CaseInsensitive ) == 0 )
1590 const QString valiString = exprVal.toString();
1591 if ( valiString.compare(
"Bottom"_L1, Qt::CaseInsensitive ) != 0 )
1593 if ( valiString.compare(
"Base"_L1, Qt::CaseInsensitive ) == 0 )
1597 else if ( valiString.compare(
"Half"_L1, Qt::CaseInsensitive ) == 0 )
1720 while ( t.length() > 250 )
1751 geom.transform( ct );
1760 penColor = colorFromSymbolLayer( symbolLayer, ctx );
1764 Qt::PenStyle penStyle( Qt::SolidLine );
1765 Qt::BrushStyle brushStyle( Qt::NoBrush );
1767 double offset = 0.0;
1771 width = symbolLayer->
dxfWidth( ctx );
1786 QString lineStyleName = u
"CONTINUOUS"_s;
1789 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
1795 writePoint( geom.constGet()->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1802 for (
int i = 0; i < cs.size(); i++ )
1804 writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1809 if ( penStyle != Qt::NoPen )
1811 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1812 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1824 QgsGeos geos( sourceGeom );
1827 sourceGeom = tempGeom.get();
1829 sourceGeom = geom.constGet();
1832 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( sourceGeom );
1835 writePolyline( *curve, layer, lineStyleName, penColor, width );
1839 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1845 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( gc->
geometryN( i ) );
1847 writePolyline( *curve, layer, lineStyleName, penColor, width );
1861 QgsGeos geos( sourceGeom );
1864 sourceGeom = tempGeom.get();
1866 sourceGeom = geom.constGet();
1869 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1878 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1884 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1885 Q_ASSERT( polygon );
1902 if ( brushStyle != Qt::NoBrush )
1904 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1911 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1912 Q_ASSERT( polygon );
1913 writePolygon( *polygon, layer, u
"SOLID"_s, brushColor );
1920 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1925 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1926 Q_ASSERT( polygon );
1927 writePolygon( *polygon, layer, u
"SOLID"_s, brushColor );
1943 return symbolLayer->
dxfColor( ctx );
1946QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayer *symbolLayer )
1948 QString lineStyleName = u
"CONTINUOUS"_s;
1951 return lineStyleName;
1954 QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
1955 if ( lineTypeIt != mLineStyles.constEnd() )
1957 lineStyleName = lineTypeIt.value();
1958 return lineStyleName;
1962 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
1969 int current_distance = std::numeric_limits<int>::max();
1970 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ); ++i )
1972 int dist = color_distance( pixel, i );
1973 if ( dist < current_distance )
1975 current_distance = dist;
1984int QgsDxfExport::color_distance( QRgb p1,
int index )
1986 if ( index > 255 || index < 0 )
1991 double redDiff = qRed( p1 ) - sDxfColors[index][0];
1992 double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
1993 double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
1995 QgsDebugMsgLevel( u
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8"_s
1996 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
1998 .arg( mDxfColors[index][0] )
1999 .arg( mDxfColors[index][1] )
2000 .arg( mDxfColors[index][2] )
2001 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ), 2 );
2003 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
2006QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
2008 return QColor::fromRgbF( r, g, b ).rgb();
2013 return mRenderContext;
2018 switch ( symbolUnits )
2037 return mapUnitsPerPixel;
2058 double mapUnitsPerPixel = mMapSettings.mapToPixel().mapUnitsPerPixel();
2060 double minSizeMU = std::numeric_limits<double>::lowest();
2063 minSizeMU = scale.
minSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2067 minSizeMU = std::max( minSizeMU, value );
2069 value = std::max( value, minSizeMU );
2071 double maxSizeMU = std::numeric_limits<double>::max();
2074 maxSizeMU = scale.
maxSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2078 maxSizeMU = std::min( maxSizeMU, value );
2080 value = std::min( value, maxSizeMU );
2083QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers(
QgsRenderContext &context )
2085 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
2096 maxSymbolLayers = 1;
2098 for (
int i = 0; i < maxSymbolLayers; ++i )
2100 symbolLayers.append( qMakePair( symbol->
symbolLayer( i ), symbol ) );
2105 return symbolLayers;
2108void QgsDxfExport::writeDefaultLinetypes()
2111 for (
const QString <ype : { u
"ByLayer"_s, u
"ByBlock"_s, u
"CONTINUOUS"_s } )
2115 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
2116 writeGroup( 100, u
"AcDbLinetypeTableRecord"_s );
2125 double das = dashSize();
2126 double dss = dashSeparatorSize();
2127 double dos = dotSize();
2129 QVector<qreal> dashVector( 2 );
2130 dashVector[0] = das;
2131 dashVector[1] = dss;
2134 QVector<qreal> dotVector( 2 );
2139 QVector<qreal> dashDotVector( 4 );
2140 dashDotVector[0] = das;
2141 dashDotVector[1] = dss;
2142 dashDotVector[2] = dos;
2143 dashDotVector[3] = dss;
2146 QVector<qreal> dashDotDotVector( 6 );
2147 dashDotDotVector[0] = das;
2148 dashDotDotVector[1] = dss;
2149 dashDotDotVector[2] = dos;
2150 dashDotDotVector[3] = dss;
2151 dashDotDotVector[4] = dos;
2152 dashDotDotVector[5] = dss;
2156void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayer *symbolLayer )
2165 if ( !customLinestyle.isEmpty() )
2167 QString name = u
"symbolLayer%1"_s.arg( mSymbolLayerCounter++ );
2168 writeLinetype( name, customLinestyle, unit );
2169 mLineStyles.insert( symbolLayer, name );
2173int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
2176 for (
const auto &symbolLayer : symbolLayers )
2178 const QgsSimpleLineSymbolLayer *simpleLine =
dynamic_cast< const QgsSimpleLineSymbolLayer *
>( symbolLayer.first );
2190void QgsDxfExport::writeLinetype(
const QString &styleName,
const QVector<qreal> &pattern,
Qgis::RenderUnit u )
2193 for ( qreal size : pattern )
2201 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
2202 writeGroup( 100, u
"AcDbLinetypeTableRecord"_s );
2211 for ( qreal size : pattern )
2214 double segmentLength = ( isGap ? -size : size );
2224 QgsGeometryGeneratorSymbolLayer *gg =
dynamic_cast<QgsGeometryGeneratorSymbolLayer *
>( symbolLayer );
2230 const QgsFeature *fet = ctx.
feature();
2236 QgsFeature f = *fet;
2240 geomExpr.prepare( &expressionContext );
2241 QgsGeometry geom = geomExpr.evaluate( &expressionContext ).value<QgsGeometry>();
2248 symbolExpressionContextScope->
setFeature( f );
2253 for (
int i = 0; i < nSymbolLayers; ++i )
2255 addFeature( ctx, ct, layer, symbol->
symbolLayer( i ), symbol );
2264 if ( !sl || !symbol )
2269 bool blockBreak =
false;
2276 blockBreak = !properties.isEmpty();
2284 if ( !layer || !layer->
enabled() )
2291double QgsDxfExport::dashSize()
const
2293 double size = mSymbologyScale * 0.002;
2294 return sizeToMapUnits( size );
2297double QgsDxfExport::dotSize()
const
2299 double size = mSymbologyScale * 0.0006;
2300 return sizeToMapUnits( size );
2303double QgsDxfExport::dashSeparatorSize()
const
2305 double size = mSymbologyScale * 0.0006;
2306 return sizeToMapUnits( size );
2309double QgsDxfExport::sizeToMapUnits(
double s )
const
2315QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
2323 case Qt::DashDotLine:
2324 return u
"DASHDOT"_s;
2325 case Qt::DashDotDotLine:
2326 return u
"DASHDOTDOT"_s;
2329 return u
"CONTINUOUS"_s;
2335 if ( name.isEmpty() )
2368bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer *layer )
const
2382 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
2385 if ( vl && vl->
id() ==
id )
2387 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
2397 const QByteArray codec = name.toLocal8Bit();
2398 if ( QTextCodec::codecForName( codec ) )
2401 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2404 if ( i !=
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2406 return DXF_ENCODINGS[i][0];
2416 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2418 for (
const QByteArray &codec : codecs )
2421 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2424 if ( i <
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2436 auto overriddenNameIt = mLayerOverriddenName.constFind( vl->
id() );
2437 if ( overriddenNameIt != mLayerOverriddenName.constEnd() && !overriddenNameIt.value().isEmpty() )
2439 return overriddenNameIt.value();
2466 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->
dataDefinedValues();
2471 QgsDebugMsgLevel( u
"PAL font definedFont: %1, Style: %2"_s.arg( dFont.toString(), dFont.styleName() ), 4 );
2501 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
2504 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
2507 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
2513 QString dxfLayer = mDxfLayerNames[layerId][fid];
2520 bool prependSymb =
false;
2538 prependSymb =
false;
2547 symb = symb + wrapchr;
2551 prependSymb =
false;
2552 symb = wrapchr + symb;
2561 txt.prepend( symb );
2571 txt.replace( QChar( QChar::LineFeed ),
' ' );
2572 txt.replace( QChar( QChar::CarriageReturn ),
' ' );
2577 txt.replace( QString( QChar( QChar::CarriageReturn ) ) + QString( QChar( QChar::LineFeed ) ), u
"\\P"_s );
2578 txt.replace( QChar( QChar::CarriageReturn ), u
"\\P"_s );
2579 txt = txt.replace( wrapchr,
"\\P"_L1 );
2580 txt.replace(
" "_L1,
"\\~"_L1 );
2584 txt.prepend(
"\\L" ).append(
"\\l" );
2589 txt.prepend(
"\\O" ).append(
"\\o" );
2594 txt.prepend(
"\\K" ).append(
"\\k" );
2597 txt.prepend( u
"\\f%1|i%2|b%3;\\H%4;"_s.arg( tmpLyr.
format().
font().family() )
2598 .arg( tmpLyr.
format().
font().italic() ? 1 : 0 )
2599 .arg( tmpLyr.
format().
font().bold() ? 1 : 0 )
2600 .arg( label->
getHeight() / ( 1 + txt.count( u
"\\P"_s ) ) * 0.75 ) );
2608 if ( !mDxfLayerNames.contains( layerId ) )
2609 mDxfLayerNames[layerId] = QMap<QgsFeatureId, QString>();
2611 mDxfLayerNames[layerId][fid] =
layerName;
2627 QString splitLayerFieldName;
2628 const QgsFields fields = mLayer->fields();
2629 if ( mLayerOutputAttributeIndex >= 0 && mLayerOutputAttributeIndex < fields.
size() )
2631 splitLayerFieldName = fields.
at( mLayerOutputAttributeIndex ).
name();
2634 return splitLayerFieldName;
2637void QgsDxfExport::createDDBlockInfo()
2639 int symbolLayerNr = 0;
2642 int ddMaxNumberOfClasses = -1;
2643 bool createDDBlocks = mLayerDDBlockMaxNumberOfClasses.contains( job->
featureSource.
id() );
2644 if ( createDDBlocks )
2646 ddMaxNumberOfClasses = mLayerDDBlockMaxNumberOfClasses[job->
featureSource.
id()];
2655 for (
const QgsSymbol *symbol : symbols )
2666 maxSymbolLayers = 1;
2669 for (
int i = 0; i < maxSymbolLayers; ++i )
2671 const QgsSymbolLayer *sl = symbol->
symbolLayer( i );
2678 if ( !hasBlockBreakingDataDefinedProperties( sl, symbol ) || !createDDBlocks )
2686 const QgsCoordinateTransform ct( job->
crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
2687 QgsFeatureRequest request
2689 QgsCoordinateTransform extentTransform = ct;
2695 catch ( QgsCsException &e )
2697 QgsDebugError( u
"Could not transform extent to layer extent: %1"_s.arg( e.
what() ) );
2703 QHash<uint, QPair<int, DataDefinedBlockInfo> > blockSymbolMap;
2708 uint symbolHash = dataDefinedSymbolClassHash( fet, properties, sctx.renderContext().expressionContext() );
2709 if ( blockSymbolMap.contains( symbolHash ) )
2711 blockSymbolMap[symbolHash].first += 1;
2715 sctx.setFeature( &fet );
2716 sctx.renderContext().expressionContext().setFeature( fet );
2718 DataDefinedBlockInfo blockInfo;
2719 blockInfo.blockName = u
"symbolLayer%1class%2"_s.arg( symbolLayerNr ).arg( symbolHash );
2720 blockInfo.angle = sl->
dxfAngle( sctx );
2721 blockInfo.size = sl->
dxfSize( sctx );
2722 blockInfo.feature = fet;
2724 blockSymbolMap.insert( symbolHash, qMakePair( 1, blockInfo ) );
2729 QMultiMap<int, uint> occurrences;
2730 QHash<uint, QPair<int, DataDefinedBlockInfo> >::const_iterator blockSymbolIt = blockSymbolMap.constBegin();
2731 for ( ; blockSymbolIt != blockSymbolMap.constEnd(); ++blockSymbolIt )
2733 occurrences.insert( blockSymbolIt.value().first, blockSymbolIt.key() );
2736 QHash<uint, DataDefinedBlockInfo > applyBlockSymbolMap;
2737 int nInsertedClasses = 0;
2738 QMultiMap<int, uint>::const_iterator occIt = occurrences.constEnd();
2739 while ( occurrences.size() > 0 && occIt != occurrences.constBegin() )
2742 applyBlockSymbolMap.insert( occIt.value(), blockSymbolMap[occIt.value()].second );
2744 if ( ddMaxNumberOfClasses != -1 && nInsertedClasses >= ddMaxNumberOfClasses )
2751 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.
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 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.
@ InvalidEncodingError
The requested text encoding is not supported.
@ 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
Export all lines with minimum width and don't fill polygons.
@ 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.
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.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the simple curve.
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 angleRadians() 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
size_t 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...