62#define strcasecmp( a, b ) stricmp( a, b )
74 mMapSettings = settings;
90 mLayerNameAttribute.clear();
91 mLayerOverriddenName.clear();
93 mLayerList.reserve( layers.size() );
94 for (
const DxfLayer &dxfLayer : layers )
96 mLayerList << dxfLayer.layer();
97 if ( dxfLayer.layerOutputAttributeIndex() >= 0 )
99 mLayerNameAttribute.insert( dxfLayer.layer()->id(), dxfLayer.layerOutputAttributeIndex() );
101 if ( dxfLayer.buildDataDefinedBlocks() )
103 mLayerDDBlockMaxNumberOfClasses.insert( dxfLayer.layer()->id(), dxfLayer.dataDefinedBlocksMaximumNumberOfClasses() );
105 if ( dxfLayer.overriddenName() != QString() )
107 mLayerOverriddenName.insert( dxfLayer.layer()->id(), dxfLayer.overriddenName() );
140 if ( !mForce2d && p.
is3D() && std::isfinite( p.
z() ) )
147 int minDist = std::numeric_limits<int>::max();
149 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ) && minDist > 0; ++i )
151 int dist = color_distance( color.rgba(), i );
152 if ( dist >= minDist )
159 if ( minDist == 0 && minDistAt != 7 )
163 if ( color.alpha() == 255 )
167 int c = ( color.red() & 0xff ) * 0x10000 + ( color.green() & 0xff ) * 0x100 + ( color.blue() & 0xff );
169 if ( transparencyCode != -1 && color.alpha() < 255 )
170 writeGroup( transparencyCode, 0x2000000 | color.alpha() );
175 mTextStream << u
"%1\n"_s.arg( code, 3, 10, QChar(
' ' ) );
180 mTextStream << u
"%1\n"_s.arg( i, 6, 10, QChar(
' ' ) );
186 if ( !s.contains(
'.' ) )
188 mTextStream << s <<
'\n';
193 mTextStream << s <<
'\n';
203 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
208 mTextStream.setDevice( d );
209 mTextStream.setEncoding( QStringConverter::encodingForName( encoding.toLocal8Bit() ).value_or( QStringConverter::Utf8 ) );
211 if ( mCrs.isValid() )
212 mMapSettings.setDestinationCrs( mCrs );
214 if ( mExtent.isEmpty() )
217 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
227 layerExtent = mMapSettings.layerToMapCoordinates( vl, layerExtent );
235 extent.combineExtentWith( layerExtent );
238 mMapSettings.setExtent(
extent );
242 mMapSettings.setExtent( mExtent );
245 if ( mMapSettings.extent().isEmpty() )
251 QList<QgsMapLayer *> layers;
252 QStringList skippedLayers;
253 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
263 if ( !mExtent.isEmpty() )
265 const QgsRectangle extentRect = mMapSettings.mapToLayerCoordinates( vl, mExtent );
278 skippedLayers << ml->name();
281 mMapSettings.setLayers( layers );
285 mMapSettings.setOutputSize( QSize( std::floor( mMapSettings.extent().width() * mFactor ), std::floor( mMapSettings.extent().height() * mFactor ) ) );
286 mMapSettings.setOutputDpi( dpi );
297 if ( !skippedLayers.isEmpty() )
299 mFeedbackMessage = QObject::tr(
"The following empty layers were skipped: %1" ).arg( skippedLayers.join(
", "_L1 ) );
310void QgsDxfExport::writeHeader(
const QString &codepage )
312 writeGroup( 999, u
"DXF created from QGIS"_s );
357 handle = mNextHandleId++;
359 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
361 writeGroup( code, QString::number( handle, 16 ) );
365void QgsDxfExport::writeTables()
372 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
373 switch ( mSymbologyExport )
378 slList = symbolLayers( context );
394 writeDefaultLinetypes();
397 for (
const auto &symbolLayer : std::as_const( slList ) )
399 writeSymbolLayerLinetype( symbolLayer.first );
412 const QStringList blockStrings = QStringList() << u
"*Model_Space"_s << u
"*Paper_Space"_s << u
"*Paper_Space0"_s;
413 for (
const QString &block : blockStrings )
417 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
423 for (
const auto &symbolLayer : std::as_const( slList ) )
425 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
429 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
432 if ( !mDataDefinedBlockInfo.contains( ml ) )
437 const QHash <uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
438 for (
const auto &blockInfo : symbolClasses )
440 writeSymbolTableBlockRef( blockInfo.blockName );
447 QString name = u
"symbolLayer%1"_s.arg( i++ );
448 writeSymbolTableBlockRef( name );
461 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
462 writeGroup( 100, u
"AcDbRegAppTableRecord"_s );
491 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
492 writeGroup( 100, u
"AcDbViewportTableRecord"_s );
502 writeGroup( 7, QgsPoint( mMapSettings.extent().center() ) );
503 writeGroup( 40, mMapSettings.extent().height() );
504 writeGroup( 41, mMapSettings.extent().width() / mMapSettings.extent().height() );
538 QSet<QString> layerNames;
539 const QList< QgsMapLayer * > layers = mMapSettings.layers();
540 for ( QgsMapLayer *ml : layers )
542 if ( !layerIsScaleBasedVisible( ml ) )
545 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
549 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
556 const QSet<QVariant> values = vl->
uniqueValues( attrIdx );
557 for (
const QVariant &v : values )
574 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
582 for (
const QString &
layerName : std::as_const( layerNames ) )
586 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
606 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
607 writeGroup( 100, u
"AcDbTextStyleTableRecord"_s );
623void QgsDxfExport::writeSymbolTableBlockRef(
const QString &blockName )
627 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
632void QgsDxfExport::writeBlocks()
637 static const QStringList blockStrings = QStringList() << u
"*Model_Space"_s << u
"*Paper_Space"_s << u
"*Paper_Space0"_s;
638 for (
const QString &block : blockStrings )
642 writeGroup( 330, QString::number( mBlockHandles[ block ], 16 ) );
658 QgsRenderContext ct = renderContext();
661 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
662 switch ( mSymbologyExport )
667 slList = symbolLayers( ct );
674 for (
const auto &symbolLayer : std::as_const( slList ) )
676 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
681 QgsSymbolRenderContext ctx( ct,
Qgis::RenderUnit::MapUnits, symbolLayer.second->opacity(),
false, symbolLayer.second->renderHints(),
nullptr );
684 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
686 if ( !mDataDefinedBlockInfo.contains( ml ) )
692 const QHash <uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
693 for (
const auto &blockInfo : symbolClasses )
695 ctx.setFeature( &blockInfo.feature );
696 ctx.renderContext().expressionContext().setFeature( blockInfo.feature );
697 writeSymbolLayerBlock( blockInfo.blockName, ml, ctx );
704 QString block( u
"symbolLayer%1"_s.arg( mBlockCounter++ ) );
705 writeSymbolLayerBlock( block, ml, ctx );
707 mPointSymbolBlocks.insert( ml, block );
708 mPointSymbolBlockSizes.insert( ml, ml->
dxfSize( *
this, ctx ) );
709 mPointSymbolBlockAngles.insert( ml, ml->
dxfAngle( ctx ) );
716 mBlockHandle = QString::number( mBlockHandles[ blockName ], 16 );
745void QgsDxfExport::writeEntities()
750 mBlockHandle = QString::number( mBlockHandles[ u
"*Model_Space"_s], 16 );
753 for ( DxfLayerJob *job : std::as_const( mJobs ) )
759 job->renderer->usingSymbolLevels() )
761 writeEntitiesSymbolLevels( job );
766 const QgsCoordinateTransform ct( job->crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
768 QgsFeatureRequest request = QgsFeatureRequest().setSubsetOfAttributes( job->attributes, job->fields ).setExpressionContext( job->renderContext.expressionContext() );
769 QgsCoordinateTransform extentTransform = ct;
776 catch ( QgsCsException &e )
787 QgsFeatureIterator featureIt = job->featureSource.getFeatures( request );
792 job->renderContext.expressionContext().setFeature( fet );
793 QString lName(
dxfLayerName( job->splitLayerAttribute.isNull() ? job->layerDerivedName : fet.
attribute( job->splitLayerAttribute ).toString() ) );
795 sctx.setFeature( &fet );
797 if ( !job->renderer->willRenderFeature( fet, job->renderContext ) )
802 addFeature( sctx, ct, lName,
nullptr,
nullptr );
806 const QgsSymbolList symbolList = job->renderer->symbolsForFeature( fet, job->renderContext );
807 bool hasSymbology = symbolList.size() > 0;
811 for ( QgsSymbol *symbol : symbolList )
814 for ( QgsSymbolLayer *symbolLayer : symbolLayers )
819 bool isGeometryGenerator = ( symbolLayer->layerType() ==
"GeometryGenerator"_L1 );
820 if ( isGeometryGenerator )
822 addGeometryGeneratorSymbolLayer( sctx, ct, lName, symbolLayer,
true );
826 addFeature( sctx, ct, lName, symbolLayer, symbol );
831 else if ( hasSymbology )
834 QgsSymbol *s = symbolList.first();
842 addGeometryGeneratorSymbolLayer( sctx, ct, lName, s->
symbolLayer( 0 ),
false );
846 addFeature( sctx, ct, lName, s->
symbolLayer( 0 ), s );
850 if ( job->labelProvider )
852 job->labelProvider->registerFeature( fet, job->renderContext );
857 else if ( job->ruleBasedLabelProvider )
859 job->ruleBasedLabelProvider->registerFeature( fet, job->renderContext );
868 QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
869 image.setDotsPerMeterX( 96 / 25.4 * 1000 );
870 image.setDotsPerMeterY( 96 / 25.4 * 1000 );
871 QPainter painter( &image );
872 mRenderContext.setPainter( &painter );
874 mRenderContext.labelingEngine()->run( mRenderContext );
879void QgsDxfExport::prepareRenderers()
881 Q_ASSERT( mJobs.empty() );
883 mRenderContext = QgsRenderContext();
884 mRenderContext.setRendererScale( mSymbologyScale );
885 mRenderContext.setExtent( mMapSettings.extent() );
887 mRenderContext.setScaleFactor( 96.0 / 25.4 );
888 mRenderContext.setMapToPixel( QgsMapToPixel( 1.0 / mFactor,
889 mMapSettings.extent().center().x(),
890 mMapSettings.extent().center().y(),
891 std::floor( mMapSettings.extent().width() * mFactor ),
892 std::floor( mMapSettings.extent().height() * mFactor ), 0 ) );
898 mLabelingEngine = std::make_unique<QgsDefaultLabelingEngine>();
899 mLabelingEngine->setMapSettings( mMapSettings );
900 mRenderContext.setLabelingEngine( mLabelingEngine.get() );
902 const QList< QgsMapLayer * > layers = mMapSettings.layers();
903 for ( QgsMapLayer *ml : layers )
905 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
912 if ( !layerIsScaleBasedVisible( vl ) )
915 QString splitLayerAttribute;
916 int splitLayerAttributeIndex = mLayerNameAttribute.value( vl->
id(), -1 );
917 const QgsFields fields = vl->
fields();
918 if ( splitLayerAttributeIndex >= 0 && splitLayerAttributeIndex < fields.
size() )
919 splitLayerAttribute = fields.
at( splitLayerAttributeIndex ).
name();
920 DxfLayerJob *job =
new DxfLayerJob( vl, mMapSettings.layerStyleOverrides().value( vl->
id() ), mRenderContext,
this, splitLayerAttribute,
layerName( vl ) );
925void QgsDxfExport::writeEntitiesSymbolLevels(
DxfLayerJob *job )
927 QHash< QgsSymbol *, QList<QgsFeature> > features;
929 QgsRenderContext ctx = renderContext();
931 for ( QgsExpressionContextScope *scope : scopes )
936 QgsFeatureRequest req;
938 QgsCoordinateTransform ct( mMapSettings.destinationCrs(), job->
crs, mMapSettings.transformContext() );
943 catch (
const QgsCsException & )
945 QgsDebugError( u
"QgsDxfExport::writeEntitiesSymbolLevels(): extent reprojection failed"_s );
957 QgsSymbol *featureSymbol =
nullptr;
961 featureSymbol = job->
renderer->symbolForFeature( fet, ctx );
962 if ( !featureSymbol )
967 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
968 if ( it == features.end() )
970 it = features.insert( featureSymbol, QList<QgsFeature>() );
972 it.value().append( fet );
978 for ( QgsSymbol *symbol : symbols )
980 for (
int j = 0; j < symbol->symbolLayerCount(); j++ )
982 int level = symbol->symbolLayer( j )->renderingPass();
983 if ( level < 0 || level >= 1000 )
985 QgsSymbolLevelItem item( symbol, j );
986 while ( level >= levels.count() )
988 levels[level].append( item );
995 for (
const QgsSymbolLevelItem &item : level )
997 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
998 if ( levelIt == features.end() )
1003 int llayer = item.layer();
1004 const QList<QgsFeature> &featureList = levelIt.value();
1005 for (
const QgsFeature &feature : featureList )
1007 sctx.setFeature( &feature );
1008 addFeature( sctx, ct, job->
layerName, levelIt.key()->symbolLayer( llayer ), levelIt.key() );
1014void QgsDxfExport::stopRenderers()
1016 qDeleteAll( mJobs );
1020void QgsDxfExport::writeEndFile()
1027void QgsDxfExport::startSection()
1032void QgsDxfExport::endSection()
1041 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1045 msl->
sizeUnit(), mMapUnits ) / 2.0;
1049 writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() - halfSize ) );
1050 writeGroup( 1, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() - halfSize ) );
1051 writeGroup( 2, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() + halfSize ) );
1052 writeGroup( 3, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() + halfSize ) );
1057 QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
1058 if ( symbolLayer && blockIt != mPointSymbolBlocks.constEnd() )
1060 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, blockIt.value(), mPointSymbolBlockAngles.value( symbolLayer ), mPointSymbolBlockSizes.value( symbolLayer ) );
1065 QHash< const QgsSymbolLayer *, QHash <uint, DataDefinedBlockInfo> >::const_iterator ddBlockIt = mDataDefinedBlockInfo.constFind( symbolLayer );
1066 if ( symbolLayer && ctx.
feature() && ddBlockIt != mDataDefinedBlockInfo.constEnd() )
1068 const QHash <uint, DataDefinedBlockInfo> &symbolLayerDDBlocks = ddBlockIt.value();
1072 uint ddSymbolHash = dataDefinedSymbolClassHash( *( ctx.
feature() ), props );
1073 if ( symbolLayerDDBlocks.contains( ddSymbolHash ) )
1075 const DataDefinedBlockInfo &info = symbolLayerDDBlocks[ddSymbolHash];
1076 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, info.blockName, info.angle, info.size );
1082 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1083 if ( msl && symbol )
1093void QgsDxfExport::writePointBlockReference(
const QgsPoint &pt,
const QgsSymbolLayer *symbolLayer,
QgsSymbolRenderContext &ctx,
const QString &layer,
double angle,
const QString &blockName,
double blockAngle,
double blockSize )
1095 const double scale = symbolLayer->
dxfSize( *
this, ctx ) / blockSize;
1105 if ( std::isfinite( scale ) && scale != 1.0 )
1117 QgsPropertyCollection dxfProp = prop;
1121 std::sort( fields.begin(), fields.end() );
1123 for (
const auto &field : std::as_const( fields ) )
1125 QVariant attValue = fet.
attribute( field );
1128 hashValue =
qHash( attValue );
1132 hashValue = hashValue ^
qHash( attValue );
1142 int n = line.size();
1145 QgsDebugError( u
"writePolyline: empty line layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1151 QgsDebugError( u
"writePolyline: line too short layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1155 if ( mForce2d || !line.at( 0 ).is3D() )
1157 bool polygon = line[0] == line[ line.size() - 1 ];
1173 for (
int i = 0; i < n; i++ )
1189 for (
int i = 0; i < n; i++ )
1198 writeGroup( 100, u
"AcDb3dPolylineVertex"_s );
1212void QgsDxfExport::appendCurve(
const QgsCurve &
c, QVector<QgsPoint> &points, QVector<double> &bulges )
1217 appendLineString( *qgis::down_cast<const QgsLineString *>( &
c ), points, bulges );
1221 appendCircularString( *qgis::down_cast<const QgsCircularString *>( &
c ), points, bulges );
1225 appendCompoundCurve( *qgis::down_cast<const QgsCompoundCurve *>( &
c ), points, bulges );
1229 QgsDebugError( u
"Unexpected curve type %1"_s.arg(
c.wktTypeStr() ) );
1234void QgsDxfExport::appendLineString(
const QgsLineString &ls, QVector<QgsPoint> &points, QVector<double> &bulges )
1236 for (
int i = 0; i < ls.
numPoints(); i++ )
1238 const QgsPoint &p = ls.
pointN( i );
1239 if ( !points.isEmpty() && points.last() == p )
1247void QgsDxfExport::appendCircularString(
const QgsCircularString &cs, QVector<QgsPoint> &points, QVector<double> &bulges )
1249 for (
int i = 0; i < cs.
numPoints() - 2; i += 2 )
1251 const QgsPoint &p1 = cs.
pointN( i );
1252 const QgsPoint &p2 = cs.
pointN( i + 1 );
1253 const QgsPoint &p3 = cs.
pointN( i + 2 );
1255 if ( points.isEmpty() || points.last() != p1 )
1257 else if ( !bulges.isEmpty() )
1258 bulges.removeLast();
1260 double a = ( M_PI - ( p1 - p2 ).angle() + ( p3 - p2 ).
angle() ) / 2.0;
1261 bulges << sin( a ) / cos( a );
1268void QgsDxfExport::appendCompoundCurve(
const QgsCompoundCurve &cc, QVector<QgsPoint> &points, QVector<double> &bulges )
1270 for (
int i = 0; i < cc.
nCurves(); i++ )
1272 const QgsCurve *
c = cc.
curveAt( i );
1274 appendCurve( *
c, points, bulges );
1283 QgsDebugError( u
"writePolyline: empty line layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1289 QgsDebugError( u
"writePolyline: line too short layer=%1 lineStyleName=%2"_s.arg( layer, lineStyleName ) );
1293 QVector<QgsPoint> points;
1294 QVector<double> bulges;
1295 appendCurve( curve, points, bulges );
1297 if ( mForce2d || !curve.
is3D() )
1318 writeGroup( 70,
static_cast<int>( polylineFlags ) );
1321 for (
int i = 0; i < points.size(); i++ )
1324 if ( bulges[i] != 0.0 )
1341 for (
int i = 0; i < points.size(); i++ )
1350 writeGroup( 100, u
"AcDb3dPolylineVertex"_s );
1352 if ( bulges[i] != 0.0 )
1380 writeGroup( 70, hatchPattern ==
"SOLID"_L1 );
1384 for (
int i = 0; i < polygon.size(); ++i )
1391 for (
int j = 0; j < polygon[i].size(); ++j )
1419 writeGroup( 70, hatchPattern ==
"SOLID"_L1 );
1422 QVector<QVector<QgsPoint>> points;
1423 QVector<QVector<double>> bulges;
1426 points.reserve( ringCount + 1 );
1427 bulges.reserve( ringCount + 1 );
1429 points << QVector<QgsPoint>();
1430 bulges << QVector<double>();
1431 appendCurve( *polygon.
exteriorRing(), points.last(), bulges.last() );
1433 for (
int i = 0; i < ringCount; i++ )
1435 points << QVector<QgsPoint>();
1436 bulges << QVector<double>();
1437 appendCurve( *polygon.
interiorRing( i ), points.last(), bulges.last() );
1440 bool hasBulges =
false;
1441 for (
int i = 0; i < points.size() && !hasBulges; ++i )
1442 for (
int j = 0; j < points[i].size() && !hasBulges; ++j )
1443 hasBulges = bulges[i][j] != 0.0;
1447 for (
int i = 0; i < points.size(); ++i )
1454 for (
int j = 0; j < points[i].size(); ++j )
1478 double lblX = label->
getX();
1479 double lblY = label->
getY();
1504 switch ( offsetQuad )
1554 const QString haliString = exprVal.toString();
1555 if ( haliString.compare(
"Center"_L1, Qt::CaseInsensitive ) == 0 )
1559 else if ( haliString.compare(
"Right"_L1, Qt::CaseInsensitive ) == 0 )
1573 const QString valiString = exprVal.toString();
1574 if ( valiString.compare(
"Bottom"_L1, Qt::CaseInsensitive ) != 0 )
1576 if ( valiString.compare(
"Base"_L1, Qt::CaseInsensitive ) == 0 )
1580 else if ( valiString.compare(
"Half"_L1, Qt::CaseInsensitive ) == 0 )
1693#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1694 if ( !mTextStream.codec()->canEncode( text ) )
1712 while ( t.length() > 250 )
1743 geom.transform( ct );
1752 penColor = colorFromSymbolLayer( symbolLayer, ctx );
1756 Qt::PenStyle penStyle( Qt::SolidLine );
1757 Qt::BrushStyle brushStyle( Qt::NoBrush );
1759 double offset = 0.0;
1763 width = symbolLayer->
dxfWidth( *
this, ctx );
1764 offset = symbolLayer->
dxfOffset( *
this, ctx );
1778 QString lineStyleName = u
"CONTINUOUS"_s;
1781 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
1787 writePoint( geom.constGet()->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1794 for (
int i = 0; i < cs.size(); i++ )
1796 writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1801 if ( penStyle != Qt::NoPen )
1803 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1804 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1816 QgsGeos geos( sourceGeom );
1819 sourceGeom = tempGeom.get();
1821 sourceGeom = geom.constGet();
1824 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( sourceGeom );
1827 writePolyline( *curve, layer, lineStyleName, penColor, width );
1831 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1837 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( gc->
geometryN( i ) );
1839 writePolyline( *curve, layer, lineStyleName, penColor, width );
1853 QgsGeos geos( sourceGeom );
1856 sourceGeom = tempGeom.get();
1858 sourceGeom = geom.constGet();
1861 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1870 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1876 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1877 Q_ASSERT( polygon );
1895 if ( brushStyle != Qt::NoBrush )
1897 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1904 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1905 Q_ASSERT( polygon );
1906 writePolygon( *polygon, layer, u
"SOLID"_s, brushColor );
1913 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1918 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1919 Q_ASSERT( polygon );
1920 writePolygon( *polygon, layer, u
"SOLID"_s, brushColor );
1937 return symbolLayer->
dxfColor( ctx );
1940QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayer *symbolLayer )
1942 QString lineStyleName = u
"CONTINUOUS"_s;
1945 return lineStyleName;
1948 QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
1949 if ( lineTypeIt != mLineStyles.constEnd() )
1951 lineStyleName = lineTypeIt.value();
1952 return lineStyleName;
1956 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
1963 int current_distance = std::numeric_limits<int>::max();
1964 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ); ++i )
1966 int dist = color_distance( pixel, i );
1967 if ( dist < current_distance )
1969 current_distance = dist;
1978int QgsDxfExport::color_distance( QRgb p1,
int index )
1980 if ( index > 255 || index < 0 )
1985 double redDiff = qRed( p1 ) - sDxfColors[index][0];
1986 double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
1987 double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
1989 QgsDebugMsgLevel( u
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8"_s
1990 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
1992 .arg( mDxfColors[index][0] )
1993 .arg( mDxfColors[index][1] )
1994 .arg( mDxfColors[index][2] )
1995 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ), 2 );
1997 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
2000QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
2002 return QColor::fromRgbF( r, g, b ).rgb();
2007 return mRenderContext;
2022 return mapUnitsPerPixel;
2036 double minSizeMU = std::numeric_limits<double>::lowest();
2039 minSizeMU = scale.
minSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2043 minSizeMU = std::max( minSizeMU, value );
2045 value = std::max( value, minSizeMU );
2047 double maxSizeMU = std::numeric_limits<double>::max();
2050 maxSizeMU = scale.
maxSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2054 maxSizeMU = std::min( maxSizeMU, value );
2056 value = std::min( value, maxSizeMU );
2059QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers(
QgsRenderContext &context )
2061 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
2072 maxSymbolLayers = 1;
2074 for (
int i = 0; i < maxSymbolLayers; ++i )
2076 symbolLayers.append( qMakePair( symbol->
symbolLayer( i ), symbol ) );
2081 return symbolLayers;
2084void QgsDxfExport::writeDefaultLinetypes()
2087 for (
const QString <ype : { u
"ByLayer"_s, u
"ByBlock"_s, u
"CONTINUOUS"_s } )
2091 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
2092 writeGroup( 100, u
"AcDbLinetypeTableRecord"_s );
2101 double das = dashSize();
2102 double dss = dashSeparatorSize();
2103 double dos = dotSize();
2105 QVector<qreal> dashVector( 2 );
2106 dashVector[0] = das;
2107 dashVector[1] = dss;
2110 QVector<qreal> dotVector( 2 );
2115 QVector<qreal> dashDotVector( 4 );
2116 dashDotVector[0] = das;
2117 dashDotVector[1] = dss;
2118 dashDotVector[2] = dos;
2119 dashDotVector[3] = dss;
2122 QVector<qreal> dashDotDotVector( 6 );
2123 dashDotDotVector[0] = das;
2124 dashDotDotVector[1] = dss;
2125 dashDotDotVector[2] = dos;
2126 dashDotDotVector[3] = dss;
2127 dashDotDotVector[4] = dos;
2128 dashDotDotVector[5] = dss;
2132void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayer *symbolLayer )
2141 if ( !customLinestyle.isEmpty() )
2143 QString name = u
"symbolLayer%1"_s.arg( mSymbolLayerCounter++ );
2144 writeLinetype( name, customLinestyle, unit );
2145 mLineStyles.insert( symbolLayer, name );
2149int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
2152 for (
const auto &symbolLayer : symbolLayers )
2154 const QgsSimpleLineSymbolLayer *simpleLine =
dynamic_cast< const QgsSimpleLineSymbolLayer *
>( symbolLayer.first );
2166void QgsDxfExport::writeLinetype(
const QString &styleName,
const QVector<qreal> &pattern,
Qgis::RenderUnit u )
2169 for ( qreal size : pattern )
2171 length += ( size *
mapUnitScaleFactor( mSymbologyScale, u, mMapUnits, mMapSettings.mapToPixel().mapUnitsPerPixel() ) );
2177 writeGroup( 100, u
"AcDbSymbolTableRecord"_s );
2178 writeGroup( 100, u
"AcDbLinetypeTableRecord"_s );
2187 for ( qreal size : pattern )
2190 double segmentLength = ( isGap ? -size : size );
2191 segmentLength *=
mapUnitScaleFactor( mSymbologyScale, u, mMapUnits, mMapSettings.mapToPixel().mapUnitsPerPixel() );
2200 QgsGeometryGeneratorSymbolLayer *gg =
dynamic_cast<QgsGeometryGeneratorSymbolLayer *
>( symbolLayer );
2206 const QgsFeature *fet = ctx.
feature();
2212 QgsFeature f = *fet;
2216 geomExpr.prepare( &expressionContext );
2217 QgsGeometry geom = geomExpr.evaluate( &expressionContext ).value<QgsGeometry>();
2224 symbolExpressionContextScope->
setFeature( f );
2229 for (
int i = 0; i < nSymbolLayers; ++i )
2231 addFeature( ctx, ct, layer, symbol->
symbolLayer( i ), symbol );
2240 if ( !sl || !symbol )
2245 bool blockBreak =
false;
2252 blockBreak = !properties.isEmpty();
2258double QgsDxfExport::dashSize()
const
2260 double size = mSymbologyScale * 0.002;
2261 return sizeToMapUnits( size );
2264double QgsDxfExport::dotSize()
const
2266 double size = mSymbologyScale * 0.0006;
2267 return sizeToMapUnits( size );
2270double QgsDxfExport::dashSeparatorSize()
const
2272 double size = mSymbologyScale * 0.0006;
2273 return sizeToMapUnits( size );
2276double QgsDxfExport::sizeToMapUnits(
double s )
const
2282QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
2290 case Qt::DashDotLine:
2291 return u
"DASHDOT"_s;
2292 case Qt::DashDotDotLine:
2293 return u
"DASHDOTDOT"_s;
2296 return u
"CONTINUOUS"_s;
2302 if ( name.isEmpty() )
2335bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer *layer )
const
2349 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
2352 if ( vl && vl->
id() ==
id )
2354 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
2364 const QByteArray codec = name.toLocal8Bit();
2365 if ( QTextCodec::codecForName( codec ) )
2368 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2371 if ( i !=
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2373 return DXF_ENCODINGS[i][0];
2383 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2385 for (
const QByteArray &codec : codecs )
2388 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2391 if ( i <
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2403 if ( !mLayerOverriddenName.value( vl->
id(), QString() ).isEmpty() )
2405 return mLayerOverriddenName.value( vl->
id() );
2432 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->
dataDefinedValues();
2437 QgsDebugMsgLevel( u
"PAL font definedFont: %1, Style: %2"_s.arg( dFont.toString(), dFont.styleName() ), 4 );
2467 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
2470 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
2473 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
2479 QString dxfLayer = mDxfLayerNames[layerId][fid];
2486 bool prependSymb =
false;
2504 prependSymb =
false;
2513 symb = symb + wrapchr;
2517 prependSymb =
false;
2518 symb = wrapchr + symb;
2527 txt.prepend( symb );
2537 txt.replace( QChar( QChar::LineFeed ),
' ' );
2538 txt.replace( QChar( QChar::CarriageReturn ),
' ' );
2543 txt.replace( QString( QChar( QChar::CarriageReturn ) ) + QString( QChar( QChar::LineFeed ) ), u
"\\P"_s );
2544 txt.replace( QChar( QChar::CarriageReturn ), u
"\\P"_s );
2545 txt = txt.replace( wrapchr,
"\\P"_L1 );
2546 txt.replace(
" "_L1,
"\\~"_L1 );
2550 txt.prepend(
"\\L" ).append(
"\\l" );
2555 txt.prepend(
"\\O" ).append(
"\\o" );
2560 txt.prepend(
"\\K" ).append(
"\\k" );
2563 txt.prepend( u
"\\f%1|i%2|b%3;\\H%4;"_s
2565 .arg( tmpLyr.
format().
font().italic() ? 1 : 0 )
2566 .arg( tmpLyr.
format().
font().bold() ? 1 : 0 )
2567 .arg( label->
getHeight() / ( 1 + txt.count( u
"\\P"_s ) ) * 0.75 ) );
2575 if ( !mDxfLayerNames.contains( layerId ) )
2576 mDxfLayerNames[ layerId ] = QMap<QgsFeatureId, QString>();
2578 mDxfLayerNames[layerId][fid] =
layerName;
2594 QString splitLayerFieldName;
2595 const QgsFields fields = mLayer->fields();
2596 if ( mLayerOutputAttributeIndex >= 0 && mLayerOutputAttributeIndex < fields.
size() )
2598 splitLayerFieldName = fields.
at( mLayerOutputAttributeIndex ).
name();
2601 return splitLayerFieldName;
2604void QgsDxfExport::createDDBlockInfo()
2606 int symbolLayerNr = 0;
2609 int ddMaxNumberOfClasses = -1;
2610 bool createDDBlocks = mLayerDDBlockMaxNumberOfClasses.contains( job->
featureSource.
id() );
2611 if ( createDDBlocks )
2613 ddMaxNumberOfClasses = mLayerDDBlockMaxNumberOfClasses[job->
featureSource.
id()];
2622 for (
const QgsSymbol *symbol : symbols )
2633 maxSymbolLayers = 1;
2636 for (
int i = 0; i < maxSymbolLayers; ++i )
2639 const QgsSymbolLayer *sl = symbol->
symbolLayer( i );
2646 if ( !hasBlockBreakingDataDefinedProperties( sl, symbol ) || !createDDBlocks )
2654 const QgsCoordinateTransform ct( job->
crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
2656 QgsCoordinateTransform extentTransform = ct;
2662 catch ( QgsCsException &e )
2664 QgsDebugError( u
"Could not transform extent to layer extent: %1"_s.arg( e.
what() ) );
2670 QHash <uint, QPair<int, DataDefinedBlockInfo> > blockSymbolMap;
2675 uint symbolHash = dataDefinedSymbolClassHash( fet, properties );
2676 if ( blockSymbolMap.contains( symbolHash ) )
2678 blockSymbolMap[symbolHash].first += 1;
2682 sctx.setFeature( &fet );
2683 sctx.renderContext().expressionContext().setFeature( fet );
2685 DataDefinedBlockInfo blockInfo;
2686 blockInfo.blockName = u
"symbolLayer%1class%2"_s.arg( symbolLayerNr ).arg( symbolHash );
2687 blockInfo.angle = sl->
dxfAngle( sctx );
2688 blockInfo.size = sl->
dxfSize( *
this, sctx );
2689 blockInfo.feature = fet;
2691 blockSymbolMap.insert( symbolHash, qMakePair( 1, blockInfo ) );
2696 QMultiMap<int, uint> occurrences;
2697 QHash <uint, QPair<int, DataDefinedBlockInfo> >::const_iterator blockSymbolIt = blockSymbolMap.constBegin();
2698 for ( ; blockSymbolIt != blockSymbolMap.constEnd(); ++blockSymbolIt )
2700 occurrences.insert( blockSymbolIt.value().first, blockSymbolIt.key() );
2703 QHash <uint, DataDefinedBlockInfo > applyBlockSymbolMap;
2704 int nInsertedClasses = 0;
2705 QMultiMap<int, uint>::const_iterator occIt = occurrences.constEnd();
2706 while ( occurrences.size() > 0 && occIt != occurrences.constBegin() )
2709 applyBlockSymbolMap.insert( occIt.value(), blockSymbolMap[occIt.value()].second );
2711 if ( ddMaxNumberOfClasses != -1 && nInsertedClasses >= ddMaxNumberOfClasses )
2718 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.
@ Millimeters
Millimeters.
@ 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.
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 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 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.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
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 dxfAngle(QgsSymbolRenderContext &context) const override
Gets angle.
double dxfSize(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets marker size.
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.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const final
Returns the set of any fields referenced by the active properties from the collection.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Abstract base class for symbol layers.
virtual double dxfSize(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
Gets marker size.
virtual double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const
Gets offset.
virtual QColor dxfBrushColor(QgsSymbolRenderContext &context) const
Gets brush/fill color.
virtual Qt::PenStyle dxfPenStyle() const
Gets pen style.
virtual QColor dxfColor(QgsSymbolRenderContext &context) const
Gets color.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual 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.
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
Layers and optional attribute index to split into multiple layers using attribute value as layer name...
QString splitLayerAttribute() const
If the split layer attribute is set, the vector layer will be split into several dxf layers,...