|
46 | 46 | #include "qgsmultilinestringv2.h"
|
47 | 47 | #include "qgscurvepolygonv2.h"
|
48 | 48 | #include "qgsexpressionprivate.h"
|
| 49 | +#include "qgsexpressionsorter.h" |
49 | 50 |
|
50 | 51 | #if QT_VERSION < 0x050000
|
51 | 52 | #include <qtextdocument.h>
|
@@ -2168,6 +2169,70 @@ static QVariant fcnExtrude( const QVariantList& values, const QgsExpressionConte
|
2168 | 2169 | return result;
|
2169 | 2170 | }
|
2170 | 2171 |
|
| 2172 | +static QVariant fcnOrderParts( const QVariantList& values, const QgsExpressionContext* ctx, QgsExpression* parent ) |
| 2173 | +{ |
| 2174 | + if ( values.length() < 2 ) |
| 2175 | + return QVariant(); |
| 2176 | + |
| 2177 | + QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); |
| 2178 | + |
| 2179 | + if ( !fGeom.isMultipart() ) |
| 2180 | + return values.at( 0 ); |
| 2181 | + |
| 2182 | + QString expString = getStringValue( values.at( 1 ), parent ); |
| 2183 | + bool asc = values.value( 2 ).toBool(); |
| 2184 | + |
| 2185 | + QgsExpressionContext* unconstedContext; |
| 2186 | + QgsFeature f; |
| 2187 | + if ( ctx ) |
| 2188 | + { |
| 2189 | + // ExpressionSorter wants a modifiable expression context, but it will return it in the same shape after |
| 2190 | + // so no reason to worry |
| 2191 | + unconstedContext = const_cast<QgsExpressionContext*>( ctx ); |
| 2192 | + f = ctx->feature(); |
| 2193 | + } |
| 2194 | + else |
| 2195 | + { |
| 2196 | + // If there's no context provided, create a fake one |
| 2197 | + unconstedContext = new QgsExpressionContext(); |
| 2198 | + } |
| 2199 | + |
| 2200 | + QgsGeometryCollectionV2* collection = dynamic_cast<QgsGeometryCollectionV2*>( fGeom.geometry() ); |
| 2201 | + Q_ASSERT( collection ); // Should have failed the multipart check above |
| 2202 | + |
| 2203 | + QgsFeatureRequest::OrderBy orderBy; |
| 2204 | + orderBy.append( QgsFeatureRequest::OrderByClause( expString, asc ) ); |
| 2205 | + QgsExpressionSorter sorter( orderBy ); |
| 2206 | + |
| 2207 | + QList<QgsFeature> partFeatures; |
| 2208 | + for ( int i = 0; i < collection->partCount(); ++i ) |
| 2209 | + { |
| 2210 | + f.setGeometry( QgsGeometry( collection->geometryN( i )->clone() ) ); |
| 2211 | + partFeatures << f; |
| 2212 | + } |
| 2213 | + |
| 2214 | + sorter.sortFeatures( partFeatures, unconstedContext ); |
| 2215 | + |
| 2216 | + QgsGeometryCollectionV2* orderedGeom = dynamic_cast<QgsGeometryCollectionV2*>( fGeom.geometry()->clone() ); |
| 2217 | + |
| 2218 | + Q_ASSERT( orderedGeom ); |
| 2219 | + |
| 2220 | + while ( orderedGeom->partCount() ) |
| 2221 | + orderedGeom->removeGeometry( 0 ); |
| 2222 | + |
| 2223 | + Q_FOREACH ( const QgsFeature& feature, partFeatures ) |
| 2224 | + { |
| 2225 | + orderedGeom->addGeometry( feature.constGeometry()->geometry()->clone() ); |
| 2226 | + } |
| 2227 | + |
| 2228 | + QVariant result = QVariant::fromValue( QgsGeometry( orderedGeom ) ); |
| 2229 | + |
| 2230 | + if ( !ctx ) |
| 2231 | + delete unconstedContext; |
| 2232 | + |
| 2233 | + return result; |
| 2234 | +} |
| 2235 | + |
2171 | 2236 | static QVariant fcnClosestPoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
2172 | 2237 | {
|
2173 | 2238 | QgsGeometry fromGeom = getGeometry( values.at( 0 ), parent );
|
@@ -2954,6 +3019,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
2954 | 3019 | << new StaticFunction( "geometry", 1, fcnGetGeometry, "GeometryGroup", QString(), true )
|
2955 | 3020 | << new StaticFunction( "transform", 3, fcnTransformGeometry, "GeometryGroup" )
|
2956 | 3021 | << new StaticFunction( "extrude", 3, fcnExtrude, "GeometryGroup", QString() )
|
| 3022 | + << new StaticFunction( "order_parts", 3, fcnOrderParts, "GeometryGroup", QString() ) |
2957 | 3023 | << new StaticFunction( "closest_point", 2, fcnClosestPoint, "GeometryGroup" )
|
2958 | 3024 | << new StaticFunction( "shortest_line", 2, fcnShortestLine, "GeometryGroup" )
|
2959 | 3025 | << new StaticFunction( "$rownum", 0, fcnRowNumber, "deprecated" )
|
|
0 commit comments