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 << QStringLiteral(
"%1\n" ).arg( code, 3, 10, QChar(
' ' ) );
180 mTextStream << QStringLiteral(
"%1\n" ).arg( i, 6, 10, QChar(
' ' ) );
186 if ( !s.contains(
'.' ) )
187 s += QLatin1String(
".0" );
188 mTextStream << s <<
'\n';
193 mTextStream << s <<
'\n';
203 if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) )
208 mTextStream.setDevice( d );
209#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
210 mTextStream.setCodec( encoding.toLocal8Bit() );
212 mTextStream.setEncoding( QStringConverter::encodingForName( encoding.toLocal8Bit() ).value_or( QStringConverter::Utf8 ) );
215 if ( mCrs.isValid() )
216 mMapSettings.setDestinationCrs( mCrs );
218 if ( mExtent.isEmpty() )
221 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
231 layerExtent = mMapSettings.layerToMapCoordinates( vl, layerExtent );
239 extent.combineExtentWith( layerExtent );
242 mMapSettings.setExtent(
extent );
246 mMapSettings.setExtent( mExtent );
249 if ( mMapSettings.extent().isEmpty() )
255 QList<QgsMapLayer *> layers;
256 QStringList skippedLayers;
257 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
267 if ( !mExtent.isEmpty() )
269 const QgsRectangle extentRect = mMapSettings.mapToLayerCoordinates( vl, mExtent );
282 skippedLayers << ml->name();
285 mMapSettings.setLayers( layers );
289 mMapSettings.setOutputSize( QSize( std::floor( mMapSettings.extent().width() * mFactor ), std::floor( mMapSettings.extent().height() * mFactor ) ) );
290 mMapSettings.setOutputDpi( dpi );
301 if ( !skippedLayers.isEmpty() )
303 mFeedbackMessage = QObject::tr(
"The following empty layers were skipped: %1" ).arg( skippedLayers.join( QLatin1String(
", " ) ) );
314void QgsDxfExport::writeHeader(
const QString &codepage )
316 writeGroup( 999, QStringLiteral(
"DXF created from QGIS" ) );
322 writeGroup( 9, QStringLiteral(
"$ACADVER" ) );
334 writeGroup( 9, QStringLiteral(
"$LTSCALE" ) );
346 writeGroup( 9, QStringLiteral(
"$PSLTSCALE" ) );
349 writeGroup( 9, QStringLiteral(
"$HANDSEED" ) );
352 writeGroup( 9, QStringLiteral(
"$DWGCODEPAGE" ) );
361 handle = mNextHandleId++;
363 Q_ASSERT_X( handle <
DXF_HANDMAX,
"QgsDxfExport::writeHandle(int, int)",
"DXF handle too large" );
365 writeGroup( code, QString::number( handle, 16 ) );
369void QgsDxfExport::writeTables()
376 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
377 switch ( mSymbologyExport )
382 slList = symbolLayers( context );
395 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
398 writeDefaultLinetypes();
401 for (
const auto &symbolLayer : std::as_const( slList ) )
403 writeSymbolLayerLinetype( symbolLayer.first );
410 writeGroup( 2, QStringLiteral(
"BLOCK_RECORD" ) );
413 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
416 const QStringList blockStrings = QStringList() << QStringLiteral(
"*Model_Space" ) << QStringLiteral(
"*Paper_Space" ) << QStringLiteral(
"*Paper_Space0" );
417 for (
const QString &block : blockStrings )
419 writeGroup( 0, QStringLiteral(
"BLOCK_RECORD" ) );
421 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
422 writeGroup( 100, QStringLiteral(
"AcDbBlockTableRecord" ) );
427 for (
const auto &symbolLayer : std::as_const( slList ) )
429 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
433 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
436 if ( !mDataDefinedBlockInfo.contains( ml ) )
441 const QHash <uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
442 for (
const auto &blockInfo : symbolClasses )
444 writeSymbolTableBlockRef( blockInfo.blockName );
451 QString name = QStringLiteral(
"symbolLayer%1" ).arg( i++ );
452 writeSymbolTableBlockRef( name );
461 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
465 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
466 writeGroup( 100, QStringLiteral(
"AcDbRegAppTableRecord" ) );
475 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
483 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
491 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
495 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
496 writeGroup( 100, QStringLiteral(
"AcDbViewportTableRecord" ) );
506 writeGroup( 7, QgsPoint( mMapSettings.extent().center() ) );
507 writeGroup( 40, mMapSettings.extent().height() );
508 writeGroup( 41, mMapSettings.extent().width() / mMapSettings.extent().height() );
535 writeGroup( 2, QStringLiteral(
"DIMSTYLE" ) );
537 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
538 writeGroup( 100, QStringLiteral(
"AcDbDimStyleTable" ) );
542 QSet<QString> layerNames;
543 const QList< QgsMapLayer * > layers = mMapSettings.layers();
544 for ( QgsMapLayer *ml : layers )
546 if ( !layerIsScaleBasedVisible( ml ) )
549 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
553 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
560 const QSet<QVariant> values = vl->
uniqueValues( attrIdx );
561 for (
const QVariant &v : values )
573 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
578 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
579 writeGroup( 100, QStringLiteral(
"AcDbLayerTableRecord" ) );
583 writeGroup( 6, QStringLiteral(
"CONTINUOUS" ) );
586 for (
const QString &
layerName : std::as_const( layerNames ) )
590 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
591 writeGroup( 100, QStringLiteral(
"AcDbLayerTableRecord" ) );
595 writeGroup( 6, QStringLiteral(
"CONTINUOUS" ) );
604 writeGroup( 100, QStringLiteral(
"AcDbSymbolTable" ) );
610 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
611 writeGroup( 100, QStringLiteral(
"AcDbTextStyleTableRecord" ) );
612 writeGroup( 2, QStringLiteral(
"STANDARD" ) );
619 writeGroup( 3, QStringLiteral(
"romans.shx" ) );
627void QgsDxfExport::writeSymbolTableBlockRef(
const QString &blockName )
629 writeGroup( 0, QStringLiteral(
"BLOCK_RECORD" ) );
631 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
632 writeGroup( 100, QStringLiteral(
"AcDbBlockTableRecord" ) );
636void QgsDxfExport::writeBlocks()
641 static const QStringList blockStrings = QStringList() << QStringLiteral(
"*Model_Space" ) << QStringLiteral(
"*Paper_Space" ) << QStringLiteral(
"*Paper_Space0" );
642 for (
const QString &block : blockStrings )
646 writeGroup( 330, QString::number( mBlockHandles[ block ], 16 ) );
647 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
649 writeGroup( 100, QStringLiteral(
"AcDbBlockBegin" ) );
657 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
659 writeGroup( 100, QStringLiteral(
"AcDbBlockEnd" ) );
662 QgsRenderContext ct = renderContext();
665 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > slList;
666 switch ( mSymbologyExport )
671 slList = symbolLayers( ct );
678 for (
const auto &symbolLayer : std::as_const( slList ) )
680 QgsMarkerSymbolLayer *ml =
dynamic_cast< QgsMarkerSymbolLayer *
>( symbolLayer.first );
685 QgsSymbolRenderContext ctx( ct,
Qgis::RenderUnit::MapUnits, symbolLayer.second->opacity(),
false, symbolLayer.second->renderHints(),
nullptr );
688 if ( hasBlockBreakingDataDefinedProperties( ml, symbolLayer.second ) )
690 if ( !mDataDefinedBlockInfo.contains( ml ) )
696 const QHash <uint, DataDefinedBlockInfo> &symbolClasses = mDataDefinedBlockInfo[ml];
697 for (
const auto &blockInfo : symbolClasses )
699 ctx.setFeature( &blockInfo.feature );
700 ctx.renderContext().expressionContext().setFeature( blockInfo.feature );
701 writeSymbolLayerBlock( blockInfo.blockName, ml, ctx );
708 QString block( QStringLiteral(
"symbolLayer%1" ).arg( mBlockCounter++ ) );
709 writeSymbolLayerBlock( block, ml, ctx );
711 mPointSymbolBlocks.insert( ml, block );
712 mPointSymbolBlockSizes.insert( ml, ml->
dxfSize( *
this, ctx ) );
713 mPointSymbolBlockAngles.insert( ml, ml->
dxfAngle( ctx ) );
720 mBlockHandle = QString::number( mBlockHandles[ blockName ], 16 );
724 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
726 writeGroup( 100, QStringLiteral(
"AcDbBlockBegin" ) );
744 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
746 writeGroup( 100, QStringLiteral(
"AcDbBlockEnd" ) );
749void QgsDxfExport::writeEntities()
752 writeGroup( 2, QStringLiteral(
"ENTITIES" ) );
754 mBlockHandle = QString::number( mBlockHandles[ QStringLiteral(
"*Model_Space" )], 16 );
757 for ( DxfLayerJob *job : std::as_const( mJobs ) )
763 job->renderer->usingSymbolLevels() )
765 writeEntitiesSymbolLevels( job );
770 const QgsCoordinateTransform ct( job->crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
772 QgsFeatureRequest request = QgsFeatureRequest().setSubsetOfAttributes( job->attributes, job->fields ).setExpressionContext( job->renderContext.expressionContext() );
773 QgsCoordinateTransform extentTransform = ct;
780 catch ( QgsCsException &e )
782 QgsDebugError( QStringLiteral(
"Error transforming DXF layer extent: %1" ).arg( e.
what() ) );
791 QgsFeatureIterator featureIt = job->featureSource.getFeatures( request );
796 job->renderContext.expressionContext().setFeature( fet );
797 QString lName(
dxfLayerName( job->splitLayerAttribute.isNull() ? job->layerDerivedName : fet.
attribute( job->splitLayerAttribute ).toString() ) );
799 sctx.setFeature( &fet );
801 if ( !job->renderer->willRenderFeature( fet, job->renderContext ) )
806 addFeature( sctx, ct, lName,
nullptr,
nullptr );
810 const QgsSymbolList symbolList = job->renderer->symbolsForFeature( fet, job->renderContext );
811 bool hasSymbology = symbolList.size() > 0;
815 for ( QgsSymbol *symbol : symbolList )
818 for ( QgsSymbolLayer *symbolLayer : symbolLayers )
823 bool isGeometryGenerator = ( symbolLayer->layerType() == QLatin1String(
"GeometryGenerator" ) );
824 if ( isGeometryGenerator )
826 addGeometryGeneratorSymbolLayer( sctx, ct, lName, symbolLayer,
true );
830 addFeature( sctx, ct, lName, symbolLayer, symbol );
835 else if ( hasSymbology )
838 QgsSymbol *s = symbolList.first();
846 addGeometryGeneratorSymbolLayer( sctx, ct, lName, s->
symbolLayer( 0 ),
false );
850 addFeature( sctx, ct, lName, s->
symbolLayer( 0 ), s );
854 if ( job->labelProvider )
856 job->labelProvider->registerFeature( fet, job->renderContext );
861 else if ( job->ruleBasedLabelProvider )
863 job->ruleBasedLabelProvider->registerFeature( fet, job->renderContext );
872 QImage image( 10, 10, QImage::Format_ARGB32_Premultiplied );
873 image.setDotsPerMeterX( 96 / 25.4 * 1000 );
874 image.setDotsPerMeterY( 96 / 25.4 * 1000 );
875 QPainter painter( &image );
876 mRenderContext.setPainter( &painter );
878 mRenderContext.labelingEngine()->run( mRenderContext );
883void QgsDxfExport::prepareRenderers()
885 Q_ASSERT( mJobs.empty() );
887 mRenderContext = QgsRenderContext();
888 mRenderContext.setRendererScale( mSymbologyScale );
889 mRenderContext.setExtent( mMapSettings.extent() );
891 mRenderContext.setScaleFactor( 96.0 / 25.4 );
892 mRenderContext.setMapToPixel( QgsMapToPixel( 1.0 / mFactor,
893 mMapSettings.extent().center().x(),
894 mMapSettings.extent().center().y(),
895 std::floor( mMapSettings.extent().width() * mFactor ),
896 std::floor( mMapSettings.extent().height() * mFactor ), 0 ) );
902 mLabelingEngine = std::make_unique<QgsDefaultLabelingEngine>();
903 mLabelingEngine->setMapSettings( mMapSettings );
904 mRenderContext.setLabelingEngine( mLabelingEngine.get() );
906 const QList< QgsMapLayer * > layers = mMapSettings.layers();
907 for ( QgsMapLayer *ml : layers )
909 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
916 if ( !layerIsScaleBasedVisible( vl ) )
919 QString splitLayerAttribute;
920 int splitLayerAttributeIndex = mLayerNameAttribute.value( vl->
id(), -1 );
921 const QgsFields fields = vl->
fields();
922 if ( splitLayerAttributeIndex >= 0 && splitLayerAttributeIndex < fields.
size() )
923 splitLayerAttribute = fields.
at( splitLayerAttributeIndex ).
name();
924 DxfLayerJob *job =
new DxfLayerJob( vl, mMapSettings.layerStyleOverrides().value( vl->
id() ), mRenderContext,
this, splitLayerAttribute,
layerName( vl ) );
929void QgsDxfExport::writeEntitiesSymbolLevels(
DxfLayerJob *job )
931 QHash< QgsSymbol *, QList<QgsFeature> > features;
933 QgsRenderContext ctx = renderContext();
935 for ( QgsExpressionContextScope *scope : scopes )
940 QgsFeatureRequest req;
942 QgsCoordinateTransform ct( mMapSettings.destinationCrs(), job->
crs, mMapSettings.transformContext() );
947 catch (
const QgsCsException & )
949 QgsDebugError( QStringLiteral(
"QgsDxfExport::writeEntitiesSymbolLevels(): extent reprojection failed" ) );
961 QgsSymbol *featureSymbol =
nullptr;
965 featureSymbol = job->
renderer->symbolForFeature( fet, ctx );
966 if ( !featureSymbol )
971 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
972 if ( it == features.end() )
974 it = features.insert( featureSymbol, QList<QgsFeature>() );
976 it.value().append( fet );
982 for ( QgsSymbol *symbol : symbols )
984 for (
int j = 0; j < symbol->symbolLayerCount(); j++ )
986 int level = symbol->symbolLayer( j )->renderingPass();
987 if ( level < 0 || level >= 1000 )
989 QgsSymbolLevelItem item( symbol, j );
990 while ( level >= levels.count() )
992 levels[level].append( item );
999 for (
const QgsSymbolLevelItem &item : level )
1001 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
1002 if ( levelIt == features.end() )
1007 int llayer = item.layer();
1008 const QList<QgsFeature> &featureList = levelIt.value();
1009 for (
const QgsFeature &feature : featureList )
1011 sctx.setFeature( &feature );
1012 addFeature( sctx, ct, job->
layerName, levelIt.key()->symbolLayer( llayer ), levelIt.key() );
1018void QgsDxfExport::stopRenderers()
1020 qDeleteAll( mJobs );
1024void QgsDxfExport::writeEndFile()
1031void QgsDxfExport::startSection()
1033 writeGroup( 0, QStringLiteral(
"SECTION" ) );
1036void QgsDxfExport::endSection()
1045 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1049 msl->
sizeUnit(), mMapUnits ) / 2.0;
1053 writeGroup( 0, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() - halfSize ) );
1054 writeGroup( 1, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() - halfSize ) );
1055 writeGroup( 2, QgsPoint( QgsWkbTypes::PointZ, pt.
x() - halfSize, pt.
y() + halfSize ) );
1056 writeGroup( 3, QgsPoint( QgsWkbTypes::PointZ, pt.
x() + halfSize, pt.
y() + halfSize ) );
1061 QHash< const QgsSymbolLayer *, QString >::const_iterator blockIt = mPointSymbolBlocks.constFind( symbolLayer );
1062 if ( symbolLayer && blockIt != mPointSymbolBlocks.constEnd() )
1064 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, blockIt.value(), mPointSymbolBlockAngles.value( symbolLayer ), mPointSymbolBlockSizes.value( symbolLayer ) );
1069 QHash< const QgsSymbolLayer *, QHash <uint, DataDefinedBlockInfo> >::const_iterator ddBlockIt = mDataDefinedBlockInfo.constFind( symbolLayer );
1070 if ( symbolLayer && ctx.
feature() && ddBlockIt != mDataDefinedBlockInfo.constEnd() )
1072 const QHash <uint, DataDefinedBlockInfo> &symbolLayerDDBlocks = ddBlockIt.value();
1076 uint ddSymbolHash = dataDefinedSymbolClassHash( *( ctx.
feature() ), props );
1077 if ( symbolLayerDDBlocks.contains( ddSymbolHash ) )
1079 const DataDefinedBlockInfo &info = symbolLayerDDBlocks[ddSymbolHash];
1080 writePointBlockReference( pt, symbolLayer, ctx, layer, angle, info.blockName, info.angle, info.size );
1086 const QgsMarkerSymbolLayer *msl =
dynamic_cast< const QgsMarkerSymbolLayer *
>( symbolLayer );
1087 if ( msl && symbol )
1097void QgsDxfExport::writePointBlockReference(
const QgsPoint &pt,
const QgsSymbolLayer *symbolLayer,
QgsSymbolRenderContext &ctx,
const QString &layer,
double angle,
const QString &blockName,
double blockAngle,
double blockSize )
1099 const double scale = symbolLayer->
dxfSize( *
this, ctx ) / blockSize;
1104 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1105 writeGroup( 100, QStringLiteral(
"AcDbBlockReference" ) );
1109 if ( std::isfinite( scale ) && scale != 1.0 )
1121 QgsPropertyCollection dxfProp = prop;
1125 std::sort( fields.begin(), fields.end() );
1127 for (
const auto &field : std::as_const( fields ) )
1129 QVariant attValue = fet.
attribute( field );
1132 hashValue =
qHash( attValue );
1136 hashValue = hashValue ^
qHash( attValue );
1146 int n = line.size();
1149 QgsDebugError( QStringLiteral(
"writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1155 QgsDebugError( QStringLiteral(
"writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1159 if ( mForce2d || !line.at( 0 ).is3D() )
1161 bool polygon = line[0] == line[ line.size() - 1 ];
1165 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1168 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1169 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1177 for (
int i = 0; i < n; i++ )
1182 writeGroup( 0, QStringLiteral(
"POLYLINE" ) );
1185 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1189 writeGroup( 100, QStringLiteral(
"AcDb3dPolyline" ) );
1193 for (
int i = 0; i < n; i++ )
1198 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1201 writeGroup( 100, QStringLiteral(
"AcDbVertex" ) );
1202 writeGroup( 100, QStringLiteral(
"AcDb3dPolylineVertex" ) );
1210 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1216void QgsDxfExport::appendCurve(
const QgsCurve &
c, QVector<QgsPoint> &points, QVector<double> &bulges )
1221 appendLineString( *qgis::down_cast<const QgsLineString *>( &
c ), points, bulges );
1225 appendCircularString( *qgis::down_cast<const QgsCircularString *>( &
c ), points, bulges );
1229 appendCompoundCurve( *qgis::down_cast<const QgsCompoundCurve *>( &
c ), points, bulges );
1233 QgsDebugError( QStringLiteral(
"Unexpected curve type %1" ).arg(
c.wktTypeStr() ) );
1238void QgsDxfExport::appendLineString(
const QgsLineString &ls, QVector<QgsPoint> &points, QVector<double> &bulges )
1240 for (
int i = 0; i < ls.
numPoints(); i++ )
1242 const QgsPoint &p = ls.
pointN( i );
1243 if ( !points.isEmpty() && points.last() == p )
1251void QgsDxfExport::appendCircularString(
const QgsCircularString &cs, QVector<QgsPoint> &points, QVector<double> &bulges )
1253 for (
int i = 0; i < cs.
numPoints() - 2; i += 2 )
1255 const QgsPoint &p1 = cs.
pointN( i );
1256 const QgsPoint &p2 = cs.
pointN( i + 1 );
1257 const QgsPoint &p3 = cs.
pointN( i + 2 );
1259 if ( points.isEmpty() || points.last() != p1 )
1261 else if ( !bulges.isEmpty() )
1262 bulges.removeLast();
1264 double a = ( M_PI - ( p1 - p2 ).angle() + ( p3 - p2 ).
angle() ) / 2.0;
1265 bulges << sin( a ) / cos( a );
1272void QgsDxfExport::appendCompoundCurve(
const QgsCompoundCurve &cc, QVector<QgsPoint> &points, QVector<double> &bulges )
1274 for (
int i = 0; i < cc.
nCurves(); i++ )
1276 const QgsCurve *
c = cc.
curveAt( i );
1278 appendCurve( *
c, points, bulges );
1287 QgsDebugError( QStringLiteral(
"writePolyline: empty line layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1293 QgsDebugError( QStringLiteral(
"writePolyline: line too short layer=%1 lineStyleName=%2" ).arg( layer, lineStyleName ) );
1297 QVector<QgsPoint> points;
1298 QVector<double> bulges;
1299 appendCurve( curve, points, bulges );
1301 if ( mForce2d || !curve.
is3D() )
1303 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1306 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1307 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1322 writeGroup( 70,
static_cast<int>( polylineFlags ) );
1325 for (
int i = 0; i < points.size(); i++ )
1328 if ( bulges[i] != 0.0 )
1334 writeGroup( 0, QStringLiteral(
"POLYLINE" ) );
1337 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1341 writeGroup( 100, QStringLiteral(
"AcDb3dPolyline" ) );
1345 for (
int i = 0; i < points.size(); i++ )
1350 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1353 writeGroup( 100, QStringLiteral(
"AcDbVertex" ) );
1354 writeGroup( 100, QStringLiteral(
"AcDb3dPolylineVertex" ) );
1356 if ( bulges[i] != 0.0 )
1364 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1375 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1378 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1384 writeGroup( 70, hatchPattern == QLatin1String(
"SOLID" ) );
1388 for (
int i = 0; i < polygon.size(); ++i )
1395 for (
int j = 0; j < polygon[i].size(); ++j )
1414 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1417 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1423 writeGroup( 70, hatchPattern == QLatin1String(
"SOLID" ) );
1426 QVector<QVector<QgsPoint>> points;
1427 QVector<QVector<double>> bulges;
1430 points.reserve( ringCount + 1 );
1431 bulges.reserve( ringCount + 1 );
1433 points << QVector<QgsPoint>();
1434 bulges << QVector<double>();
1435 appendCurve( *polygon.
exteriorRing(), points.last(), bulges.last() );
1437 for (
int i = 0; i < ringCount; i++ )
1439 points << QVector<QgsPoint>();
1440 bulges << QVector<double>();
1441 appendCurve( *polygon.
interiorRing( i ), points.last(), bulges.last() );
1444 bool hasBulges =
false;
1445 for (
int i = 0; i < points.size() && !hasBulges; ++i )
1446 for (
int j = 0; j < points[i].size() && !hasBulges; ++j )
1447 hasBulges = bulges[i][j] != 0.0;
1451 for (
int i = 0; i < points.size(); ++i )
1458 for (
int j = 0; j < points[i].size(); ++j )
1482 double lblX = label->
getX();
1483 double lblY = label->
getY();
1508 switch ( offsetQuad )
1558 const QString haliString = exprVal.toString();
1559 if ( haliString.compare( QLatin1String(
"Center" ), Qt::CaseInsensitive ) == 0 )
1563 else if ( haliString.compare( QLatin1String(
"Right" ), Qt::CaseInsensitive ) == 0 )
1577 const QString valiString = exprVal.toString();
1578 if ( valiString.compare( QLatin1String(
"Bottom" ), Qt::CaseInsensitive ) != 0 )
1580 if ( valiString.compare( QLatin1String(
"Base" ), Qt::CaseInsensitive ) == 0 )
1584 else if ( valiString.compare( QLatin1String(
"Half" ), Qt::CaseInsensitive ) == 0 )
1603 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1604 writeGroup( 100, QStringLiteral(
"AcDbPoint" ) );
1615 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1618 writeGroup( 100, QStringLiteral(
"AcDbHatch" ) );
1649 writeGroup( 0, QStringLiteral(
"LWPOLYLINE" ) );
1653 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1654 writeGroup( 100, QStringLiteral(
"AcDbPolyline" ) );
1673 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1676 writeGroup( 100, QStringLiteral(
"AcDbText" ) );
1687 writeGroup( 7, QStringLiteral(
"STANDARD" ) );
1688 writeGroup( 100, QStringLiteral(
"AcDbText" ) );
1697#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1698 if ( !mTextStream.codec()->canEncode( text ) )
1701 QgsDebugError( QStringLiteral(
"could not encode:%1" ).arg( text ) );
1708 writeGroup( 100, QStringLiteral(
"AcDbEntity" ) );
1709 writeGroup( 100, QStringLiteral(
"AcDbMText" ) );
1716 while ( t.length() > 250 )
1732 writeGroup( 7, QStringLiteral(
"STANDARD" ) );
1747 geom.transform( ct );
1756 penColor = colorFromSymbolLayer( symbolLayer, ctx );
1760 Qt::PenStyle penStyle( Qt::SolidLine );
1761 Qt::BrushStyle brushStyle( Qt::NoBrush );
1763 double offset = 0.0;
1767 width = symbolLayer->
dxfWidth( *
this, ctx );
1768 offset = symbolLayer->
dxfOffset( *
this, ctx );
1782 QString lineStyleName = QStringLiteral(
"CONTINUOUS" );
1785 lineStyleName = lineStyleFromSymbolLayer( symbolLayer );
1791 writePoint( geom.constGet()->coordinateSequence().at( 0 ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1798 for (
int i = 0; i < cs.size(); i++ )
1800 writePoint( cs.at( i ).at( 0 ).at( 0 ), layer, penColor, ctx, symbolLayer, symbol, angle );
1805 if ( penStyle != Qt::NoPen )
1807 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1808 std::unique_ptr< QgsAbstractGeometry > tempGeom;
1820 QgsGeos geos( sourceGeom );
1823 sourceGeom = tempGeom.get();
1825 sourceGeom = geom.constGet();
1828 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( sourceGeom );
1831 writePolyline( *curve, layer, lineStyleName, penColor, width );
1835 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1841 const QgsCurve *curve =
dynamic_cast<const QgsCurve *
>( gc->
geometryN( i ) );
1843 writePolyline( *curve, layer, lineStyleName, penColor, width );
1857 QgsGeos geos( sourceGeom );
1860 sourceGeom = tempGeom.get();
1862 sourceGeom = geom.constGet();
1865 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1874 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1880 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1881 Q_ASSERT( polygon );
1899 if ( brushStyle != Qt::NoBrush )
1901 const QgsAbstractGeometry *sourceGeom = geom.constGet();
1908 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( sourceGeom );
1909 Q_ASSERT( polygon );
1910 writePolygon( *polygon, layer, QStringLiteral(
"SOLID" ), brushColor );
1917 const QgsGeometryCollection *gc =
dynamic_cast<const QgsGeometryCollection *
>( sourceGeom );
1922 const QgsCurvePolygon *polygon =
dynamic_cast<const QgsCurvePolygon *
>( gc->
geometryN( i ) );
1923 Q_ASSERT( polygon );
1924 writePolygon( *polygon, layer, QStringLiteral(
"SOLID" ), brushColor );
1941 return symbolLayer->
dxfColor( ctx );
1944QString QgsDxfExport::lineStyleFromSymbolLayer(
const QgsSymbolLayer *symbolLayer )
1946 QString lineStyleName = QStringLiteral(
"CONTINUOUS" );
1949 return lineStyleName;
1952 QHash< const QgsSymbolLayer *, QString >::const_iterator lineTypeIt = mLineStyles.constFind( symbolLayer );
1953 if ( lineTypeIt != mLineStyles.constEnd() )
1955 lineStyleName = lineTypeIt.value();
1956 return lineStyleName;
1960 return lineNameFromPenStyle( symbolLayer->
dxfPenStyle() );
1967 int current_distance = std::numeric_limits<int>::max();
1968 for (
int i = 1; i < static_cast< int >(
sizeof( sDxfColors ) /
sizeof( *sDxfColors ) ); ++i )
1970 int dist = color_distance( pixel, i );
1971 if ( dist < current_distance )
1973 current_distance = dist;
1982int QgsDxfExport::color_distance( QRgb p1,
int index )
1984 if ( index > 255 || index < 0 )
1989 double redDiff = qRed( p1 ) - sDxfColors[index][0];
1990 double greenDiff = qGreen( p1 ) - sDxfColors[index][1];
1991 double blueDiff = qBlue( p1 ) - sDxfColors[index][2];
1993 QgsDebugMsgLevel( QStringLiteral(
"color_distance( r:%1 g:%2 b:%3 <=> i:%4 r:%5 g:%6 b:%7 ) => %8" )
1994 .arg( qRed( p1 ) ).arg( qGreen( p1 ) ).arg( qBlue( p1 ) )
1996 .arg( mDxfColors[index][0] )
1997 .arg( mDxfColors[index][1] )
1998 .arg( mDxfColors[index][2] )
1999 .arg( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ), 2 );
2001 return redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff;
2004QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b )
2006 return QColor::fromRgbF( r, g, b ).rgb();
2011 return mRenderContext;
2026 return mapUnitsPerPixel;
2040 double minSizeMU = std::numeric_limits<double>::lowest();
2043 minSizeMU = scale.
minSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2047 minSizeMU = std::max( minSizeMU, value );
2049 value = std::max( value, minSizeMU );
2051 double maxSizeMU = std::numeric_limits<double>::max();
2054 maxSizeMU = scale.
maxSizeMM * pixelToMMFactor * mapUnitsPerPixel;
2058 maxSizeMU = std::min( maxSizeMU, value );
2060 value = std::min( value, maxSizeMU );
2063QList< QPair< QgsSymbolLayer *, QgsSymbol * > > QgsDxfExport::symbolLayers(
QgsRenderContext &context )
2065 QList< QPair< QgsSymbolLayer *, QgsSymbol * > > symbolLayers;
2076 maxSymbolLayers = 1;
2078 for (
int i = 0; i < maxSymbolLayers; ++i )
2080 symbolLayers.append( qMakePair( symbol->
symbolLayer( i ), symbol ) );
2085 return symbolLayers;
2088void QgsDxfExport::writeDefaultLinetypes()
2091 for (
const QString <ype : { QStringLiteral(
"ByLayer" ), QStringLiteral(
"ByBlock" ), QStringLiteral(
"CONTINUOUS" ) } )
2095 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
2096 writeGroup( 100, QStringLiteral(
"AcDbLinetypeTableRecord" ) );
2099 writeGroup( 3, QStringLiteral(
"Defaultstyle" ) );
2105 double das = dashSize();
2106 double dss = dashSeparatorSize();
2107 double dos = dotSize();
2109 QVector<qreal> dashVector( 2 );
2110 dashVector[0] = das;
2111 dashVector[1] = dss;
2114 QVector<qreal> dotVector( 2 );
2119 QVector<qreal> dashDotVector( 4 );
2120 dashDotVector[0] = das;
2121 dashDotVector[1] = dss;
2122 dashDotVector[2] = dos;
2123 dashDotVector[3] = dss;
2126 QVector<qreal> dashDotDotVector( 6 );
2127 dashDotDotVector[0] = das;
2128 dashDotDotVector[1] = dss;
2129 dashDotDotVector[2] = dos;
2130 dashDotDotVector[3] = dss;
2131 dashDotDotVector[4] = dos;
2132 dashDotDotVector[5] = dss;
2136void QgsDxfExport::writeSymbolLayerLinetype(
const QgsSymbolLayer *symbolLayer )
2145 if ( !customLinestyle.isEmpty() )
2147 QString name = QStringLiteral(
"symbolLayer%1" ).arg( mSymbolLayerCounter++ );
2148 writeLinetype( name, customLinestyle, unit );
2149 mLineStyles.insert( symbolLayer, name );
2153int QgsDxfExport::nLineTypes(
const QList< QPair< QgsSymbolLayer *, QgsSymbol * > > &symbolLayers )
2156 for (
const auto &symbolLayer : symbolLayers )
2158 const QgsSimpleLineSymbolLayer *simpleLine =
dynamic_cast< const QgsSimpleLineSymbolLayer *
>( symbolLayer.first );
2170void QgsDxfExport::writeLinetype(
const QString &styleName,
const QVector<qreal> &pattern,
Qgis::RenderUnit u )
2173 for ( qreal size : pattern )
2175 length += ( size *
mapUnitScaleFactor( mSymbologyScale, u, mMapUnits, mMapSettings.mapToPixel().mapUnitsPerPixel() ) );
2181 writeGroup( 100, QStringLiteral(
"AcDbSymbolTableRecord" ) );
2182 writeGroup( 100, QStringLiteral(
"AcDbLinetypeTableRecord" ) );
2191 for ( qreal size : pattern )
2194 double segmentLength = ( isGap ? -size : size );
2195 segmentLength *=
mapUnitScaleFactor( mSymbologyScale, u, mMapUnits, mMapSettings.mapToPixel().mapUnitsPerPixel() );
2204 QgsGeometryGeneratorSymbolLayer *gg =
dynamic_cast<QgsGeometryGeneratorSymbolLayer *
>( symbolLayer );
2210 const QgsFeature *fet = ctx.
feature();
2216 QgsFeature f = *fet;
2220 geomExpr.prepare( &expressionContext );
2221 QgsGeometry geom = geomExpr.evaluate( &expressionContext ).value<QgsGeometry>();
2228 symbolExpressionContextScope->
setFeature( f );
2233 for (
int i = 0; i < nSymbolLayers; ++i )
2235 addFeature( ctx, ct, layer, symbol->
symbolLayer( i ), symbol );
2244 if ( !sl || !symbol )
2249 bool blockBreak =
false;
2256 blockBreak = !properties.isEmpty();
2262double QgsDxfExport::dashSize()
const
2264 double size = mSymbologyScale * 0.002;
2265 return sizeToMapUnits( size );
2268double QgsDxfExport::dotSize()
const
2270 double size = mSymbologyScale * 0.0006;
2271 return sizeToMapUnits( size );
2274double QgsDxfExport::dashSeparatorSize()
const
2276 double size = mSymbologyScale * 0.0006;
2277 return sizeToMapUnits( size );
2280double QgsDxfExport::sizeToMapUnits(
double s )
const
2286QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style )
2291 return QStringLiteral(
"DASH" );
2293 return QStringLiteral(
"DOT" );
2294 case Qt::DashDotLine:
2295 return QStringLiteral(
"DASHDOT" );
2296 case Qt::DashDotDotLine:
2297 return QStringLiteral(
"DASHDOTDOT" );
2300 return QStringLiteral(
"CONTINUOUS" );
2306 if ( name.isEmpty() )
2307 return QStringLiteral(
"0" );
2332 layerName.replace( QLatin1String(
"\r\n" ), QLatin1String(
"_" ) );
2339bool QgsDxfExport::layerIsScaleBasedVisible(
const QgsMapLayer *layer )
const
2353 for (
QgsMapLayer *ml : std::as_const( mLayerList ) )
2356 if ( vl && vl->
id() ==
id )
2358 int attrIdx = mLayerNameAttribute.value( vl->
id(), -1 );
2363 return QStringLiteral(
"0" );
2368 const QByteArray codec = name.toLocal8Bit();
2369 if ( QTextCodec::codecForName( codec ) )
2372 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2375 if ( i !=
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2377 return DXF_ENCODINGS[i][0];
2387 const QList< QByteArray > codecs = QTextCodec::availableCodecs();
2389 for (
const QByteArray &codec : codecs )
2392 for ( i = 0; i < static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) && strcasecmp( codec.data(), DXF_ENCODINGS[i][1] ) != 0; ++i )
2395 if ( i <
static_cast< int >(
sizeof( DXF_ENCODINGS ) /
sizeof( *DXF_ENCODINGS ) ) )
2407 if ( !mLayerOverriddenName.value( vl->
id(), QString() ).isEmpty() )
2409 return mLayerOverriddenName.value( vl->
id() );
2436 const QMap< QgsPalLayerSettings::Property, QVariant > &ddValues = lf->
dataDefinedValues();
2441 QgsDebugMsgLevel( QStringLiteral(
"PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
2471 QgsPalLabeling::dataDefinedTextStyle( tmpLyr, ddValues );
2474 QgsPalLabeling::dataDefinedTextBuffer( tmpLyr, ddValues );
2477 QgsPalLabeling::dataDefinedTextFormatting( tmpLyr, ddValues );
2483 QString dxfLayer = mDxfLayerNames[layerId][fid];
2485 QString wrapchr = tmpLyr.
wrapChar.isEmpty() ? QStringLiteral(
"\n" ) : tmpLyr.
wrapChar;
2490 bool prependSymb =
false;
2508 prependSymb =
false;
2517 symb = symb + wrapchr;
2521 prependSymb =
false;
2522 symb = wrapchr + symb;
2531 txt.prepend( symb );
2541 txt.replace( QChar( QChar::LineFeed ),
' ' );
2542 txt.replace( QChar( QChar::CarriageReturn ),
' ' );
2547 txt.replace( QString( QChar( QChar::CarriageReturn ) ) + QString( QChar( QChar::LineFeed ) ), QStringLiteral(
"\\P" ) );
2548 txt.replace( QChar( QChar::CarriageReturn ), QStringLiteral(
"\\P" ) );
2549 txt = txt.replace( wrapchr, QLatin1String(
"\\P" ) );
2550 txt.replace( QLatin1String(
" " ), QLatin1String(
"\\~" ) );
2554 txt.prepend(
"\\L" ).append(
"\\l" );
2559 txt.prepend(
"\\O" ).append(
"\\o" );
2564 txt.prepend(
"\\K" ).append(
"\\k" );
2567 txt.prepend( QStringLiteral(
"\\f%1|i%2|b%3;\\H%4;" )
2569 .arg( tmpLyr.
format().
font().italic() ? 1 : 0 )
2570 .arg( tmpLyr.
format().
font().bold() ? 1 : 0 )
2571 .arg( label->
getHeight() / ( 1 + txt.count( QStringLiteral(
"\\P" ) ) ) * 0.75 ) );
2579 if ( !mDxfLayerNames.contains( layerId ) )
2580 mDxfLayerNames[ layerId ] = QMap<QgsFeatureId, QString>();
2582 mDxfLayerNames[layerId][fid] =
layerName;
2598 QString splitLayerFieldName;
2599 const QgsFields fields = mLayer->fields();
2600 if ( mLayerOutputAttributeIndex >= 0 && mLayerOutputAttributeIndex < fields.
size() )
2602 splitLayerFieldName = fields.
at( mLayerOutputAttributeIndex ).
name();
2605 return splitLayerFieldName;
2608void QgsDxfExport::createDDBlockInfo()
2610 int symbolLayerNr = 0;
2613 int ddMaxNumberOfClasses = -1;
2614 bool createDDBlocks = mLayerDDBlockMaxNumberOfClasses.contains( job->
featureSource.
id() );
2615 if ( createDDBlocks )
2617 ddMaxNumberOfClasses = mLayerDDBlockMaxNumberOfClasses[job->
featureSource.
id()];
2626 for (
const QgsSymbol *symbol : symbols )
2637 maxSymbolLayers = 1;
2640 for (
int i = 0; i < maxSymbolLayers; ++i )
2643 const QgsSymbolLayer *sl = symbol->
symbolLayer( i );
2650 if ( !hasBlockBreakingDataDefinedProperties( sl, symbol ) || !createDDBlocks )
2658 const QgsCoordinateTransform ct( job->
crs, mMapSettings.destinationCrs(), mMapSettings.transformContext() );
2660 QgsCoordinateTransform extentTransform = ct;
2666 catch ( QgsCsException &e )
2668 QgsDebugError( QStringLiteral(
"Could not transform extent to layer extent: %1" ).arg( e.
what() ) );
2674 QHash <uint, QPair<int, DataDefinedBlockInfo> > blockSymbolMap;
2679 uint symbolHash = dataDefinedSymbolClassHash( fet, properties );
2680 if ( blockSymbolMap.contains( symbolHash ) )
2682 blockSymbolMap[symbolHash].first += 1;
2686 sctx.setFeature( &fet );
2687 sctx.renderContext().expressionContext().setFeature( fet );
2689 DataDefinedBlockInfo blockInfo;
2690 blockInfo.blockName = QStringLiteral(
"symbolLayer%1class%2" ).arg( symbolLayerNr ).arg( symbolHash );
2691 blockInfo.angle = sl->
dxfAngle( sctx );
2692 blockInfo.size = sl->
dxfSize( *
this, sctx );
2693 blockInfo.feature = fet;
2695 blockSymbolMap.insert( symbolHash, qMakePair( 1, blockInfo ) );
2700 QMultiMap<int, uint> occurrences;
2701 QHash <uint, QPair<int, DataDefinedBlockInfo> >::const_iterator blockSymbolIt = blockSymbolMap.constBegin();
2702 for ( ; blockSymbolIt != blockSymbolMap.constEnd(); ++blockSymbolIt )
2704 occurrences.insert( blockSymbolIt.value().first, blockSymbolIt.key() );
2707 QHash <uint, DataDefinedBlockInfo > applyBlockSymbolMap;
2708 int nInsertedClasses = 0;
2709 QMultiMap<int, uint>::const_iterator occIt = occurrences.constEnd();
2710 while ( occurrences.size() > 0 && occIt != occurrences.constBegin() )
2713 applyBlockSymbolMap.insert( occIt.value(), blockSymbolMap[occIt.value()].second );
2715 if ( ddMaxNumberOfClasses != -1 && nInsertedClasses >= ddMaxNumberOfClasses )
2722 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,...