|
42 | 42 | #include "qgsgeometrycollectionv2.h"
|
43 | 43 | #include "qgspointv2.h"
|
44 | 44 | #include "qgspolygonv2.h"
|
| 45 | +#include "qgsmultipointv2.h" |
| 46 | +#include "qgsmultilinestringv2.h" |
| 47 | +#include "qgscurvepolygonv2.h" |
45 | 48 |
|
46 | 49 | #if QT_VERSION < 0x050000
|
47 | 50 | #include <qtextdocument.h>
|
@@ -1382,6 +1385,160 @@ static QVariant fcnEndPoint( const QVariantList& values, const QgsExpressionCont
|
1382 | 1385 | return QVariant::fromValue( QgsGeometry( new QgsPointV2( point ) ) );
|
1383 | 1386 | }
|
1384 | 1387 |
|
| 1388 | +static QVariant fcnNodesToPoints( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1389 | +{ |
| 1390 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1391 | + |
| 1392 | + if ( geom.isEmpty() ) |
| 1393 | + return QVariant(); |
| 1394 | + |
| 1395 | + bool ignoreClosing = false; |
| 1396 | + if ( values.length() > 1 ) |
| 1397 | + { |
| 1398 | + ignoreClosing = getIntValue( values.at( 1 ), parent ); |
| 1399 | + } |
| 1400 | + |
| 1401 | + QgsMultiPointV2* mp = new QgsMultiPointV2(); |
| 1402 | + |
| 1403 | + QList< QList< QList< QgsPointV2 > > > coords; |
| 1404 | + geom.geometry()->coordinateSequence( coords ); |
| 1405 | + |
| 1406 | + Q_FOREACH ( const QList< QList< QgsPointV2 > >& part, coords ) |
| 1407 | + { |
| 1408 | + Q_FOREACH ( const QList< QgsPointV2 >& ring, part ) |
| 1409 | + { |
| 1410 | + bool skipLast = false; |
| 1411 | + if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() ) |
| 1412 | + { |
| 1413 | + skipLast = true; |
| 1414 | + } |
| 1415 | + |
| 1416 | + for ( int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i ) |
| 1417 | + { |
| 1418 | + mp->addGeometry( ring.at( i ).clone() ); |
| 1419 | + } |
| 1420 | + } |
| 1421 | + } |
| 1422 | + |
| 1423 | + return QVariant::fromValue( QgsGeometry( mp ) ); |
| 1424 | +} |
| 1425 | + |
| 1426 | +static QVariant fcnSegmentsToLines( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1427 | +{ |
| 1428 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1429 | + |
| 1430 | + if ( geom.isEmpty() ) |
| 1431 | + return QVariant(); |
| 1432 | + |
| 1433 | + QList< QgsAbstractGeometryV2 * > geometries; |
| 1434 | + |
| 1435 | + QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() ); |
| 1436 | + if ( collection ) |
| 1437 | + { |
| 1438 | + for ( int i = 0; i < collection->numGeometries(); ++i ) |
| 1439 | + { |
| 1440 | + geometries.append( collection->geometryN( i ) ); |
| 1441 | + } |
| 1442 | + } |
| 1443 | + else |
| 1444 | + { |
| 1445 | + geometries.append( geom.geometry() ); |
| 1446 | + } |
| 1447 | + |
| 1448 | + QList< QgsLineStringV2* > linesToProcess; |
| 1449 | + while ( ! geometries.isEmpty() ) |
| 1450 | + { |
| 1451 | + QgsAbstractGeometryV2* g = geometries.takeFirst(); |
| 1452 | + QgsCurveV2* curve = dynamic_cast< QgsCurveV2* >( g ); |
| 1453 | + if ( curve ) |
| 1454 | + { |
| 1455 | + linesToProcess << static_cast< QgsLineStringV2* >( curve->segmentize() ); |
| 1456 | + continue; |
| 1457 | + } |
| 1458 | + QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( g ); |
| 1459 | + if ( collection ) |
| 1460 | + { |
| 1461 | + for ( int i = 0; i < collection->numGeometries(); ++i ) |
| 1462 | + { |
| 1463 | + geometries.append( collection->geometryN( i ) ); |
| 1464 | + } |
| 1465 | + } |
| 1466 | + QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( g ); |
| 1467 | + if ( curvePolygon ) |
| 1468 | + { |
| 1469 | + if ( curvePolygon->exteriorRing() ) |
| 1470 | + linesToProcess << static_cast< QgsLineStringV2* >( curvePolygon->exteriorRing()->segmentize() ); |
| 1471 | + |
| 1472 | + for ( int i = 0; i < curvePolygon->numInteriorRings(); ++i ) |
| 1473 | + { |
| 1474 | + linesToProcess << static_cast< QgsLineStringV2* >( curvePolygon->interiorRing( i )->segmentize() ); |
| 1475 | + } |
| 1476 | + continue; |
| 1477 | + } |
| 1478 | + } |
| 1479 | + |
| 1480 | + //ok, now we have a complete list of segmentized lines from the geometry |
| 1481 | + QgsMultiLineStringV2* ml = new QgsMultiLineStringV2(); |
| 1482 | + Q_FOREACH ( QgsLineStringV2* line, linesToProcess ) |
| 1483 | + { |
| 1484 | + for ( int i = 0; i < line->numPoints() - 1; ++i ) |
| 1485 | + { |
| 1486 | + QgsLineStringV2* segment = new QgsLineStringV2(); |
| 1487 | + segment->setPoints( QList<QgsPointV2>() |
| 1488 | + << line->pointN( i ) |
| 1489 | + << line->pointN( i + 1 ) ); |
| 1490 | + ml->addGeometry( segment ); |
| 1491 | + } |
| 1492 | + delete line; |
| 1493 | + } |
| 1494 | + |
| 1495 | + return QVariant::fromValue( QgsGeometry( ml ) ); |
| 1496 | +} |
| 1497 | + |
| 1498 | +static QVariant fcnInteriorRingN( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1499 | +{ |
| 1500 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1501 | + |
| 1502 | + if ( geom.isEmpty() ) |
| 1503 | + return QVariant(); |
| 1504 | + |
| 1505 | + QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( geom.geometry() ); |
| 1506 | + if ( !curvePolygon ) |
| 1507 | + return QVariant(); |
| 1508 | + |
| 1509 | + //idx is 1 based |
| 1510 | + int idx = getIntValue( values.at( 1 ), parent ) - 1; |
| 1511 | + |
| 1512 | + if ( idx >= curvePolygon->numInteriorRings() || idx < 0 ) |
| 1513 | + return QVariant(); |
| 1514 | + |
| 1515 | + QgsCurveV2* curve = static_cast< QgsCurveV2* >( curvePolygon->interiorRing( idx )->clone() ); |
| 1516 | + QVariant result = curve ? QVariant::fromValue( QgsGeometry( curve ) ) : QVariant(); |
| 1517 | + return result; |
| 1518 | +} |
| 1519 | + |
| 1520 | +static QVariant fcnGeometryN( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1521 | +{ |
| 1522 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1523 | + |
| 1524 | + if ( geom.isEmpty() ) |
| 1525 | + return QVariant(); |
| 1526 | + |
| 1527 | + QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() ); |
| 1528 | + if ( !collection ) |
| 1529 | + return QVariant(); |
| 1530 | + |
| 1531 | + //idx is 1 based |
| 1532 | + int idx = getIntValue( values.at( 1 ), parent ) - 1; |
| 1533 | + |
| 1534 | + if ( idx < 0 || idx >= collection->numGeometries() ) |
| 1535 | + return QVariant(); |
| 1536 | + |
| 1537 | + QgsAbstractGeometryV2* part = collection->geometryN( idx )->clone(); |
| 1538 | + QVariant result = part ? QVariant::fromValue( QgsGeometry( part ) ) : QVariant(); |
| 1539 | + return result; |
| 1540 | +} |
| 1541 | + |
1385 | 1542 | static QVariant fcnMakePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
1386 | 1543 | {
|
1387 | 1544 | if ( values.count() < 2 || values.count() > 4 )
|
@@ -1583,6 +1740,77 @@ static QVariant fcnGeomNumPoints( const QVariantList& values, const QgsExpressio
|
1583 | 1740 | return QVariant( geom.isEmpty() ? 0 : geom.geometry()->nCoordinates() );
|
1584 | 1741 | }
|
1585 | 1742 |
|
| 1743 | +static QVariant fcnGeomNumGeometries( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1744 | +{ |
| 1745 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1746 | + if ( geom.isEmpty() ) |
| 1747 | + return QVariant(); |
| 1748 | + |
| 1749 | + return QVariant( geom.geometry()->partCount() ); |
| 1750 | +} |
| 1751 | + |
| 1752 | +static QVariant fcnGeomNumInteriorRings( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1753 | +{ |
| 1754 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1755 | + |
| 1756 | + if ( geom.isEmpty() ) |
| 1757 | + return QVariant(); |
| 1758 | + |
| 1759 | + QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( geom.geometry() ); |
| 1760 | + if ( curvePolygon ) |
| 1761 | + return QVariant( curvePolygon->numInteriorRings() ); |
| 1762 | + |
| 1763 | + QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() ); |
| 1764 | + if ( collection ) |
| 1765 | + { |
| 1766 | + //find first CurvePolygon in collection |
| 1767 | + for ( int i = 0; i < collection->numGeometries(); ++i ) |
| 1768 | + { |
| 1769 | + curvePolygon = dynamic_cast< QgsCurvePolygonV2*>( collection->geometryN( i ) ); |
| 1770 | + if ( !curvePolygon ) |
| 1771 | + continue; |
| 1772 | + |
| 1773 | + return QVariant( curvePolygon->isEmpty() ? 0 : curvePolygon->numInteriorRings() ); |
| 1774 | + } |
| 1775 | + } |
| 1776 | + |
| 1777 | + return QVariant(); |
| 1778 | +} |
| 1779 | + |
| 1780 | +static QVariant fcnGeomNumRings( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) |
| 1781 | +{ |
| 1782 | + QgsGeometry geom = getGeometry( values.at( 0 ), parent ); |
| 1783 | + |
| 1784 | + if ( geom.isEmpty() ) |
| 1785 | + return QVariant(); |
| 1786 | + |
| 1787 | + QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( geom.geometry() ); |
| 1788 | + if ( curvePolygon ) |
| 1789 | + return QVariant( curvePolygon->ringCount() ); |
| 1790 | + |
| 1791 | + bool foundPoly = false; |
| 1792 | + int ringCount = 0; |
| 1793 | + QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() ); |
| 1794 | + if ( collection ) |
| 1795 | + { |
| 1796 | + //find CurvePolygons in collection |
| 1797 | + for ( int i = 0; i < collection->numGeometries(); ++i ) |
| 1798 | + { |
| 1799 | + curvePolygon = dynamic_cast< QgsCurvePolygonV2*>( collection->geometryN( i ) ); |
| 1800 | + if ( !curvePolygon ) |
| 1801 | + continue; |
| 1802 | + |
| 1803 | + foundPoly = true; |
| 1804 | + ringCount += curvePolygon->ringCount(); |
| 1805 | + } |
| 1806 | + } |
| 1807 | + |
| 1808 | + if ( !foundPoly ) |
| 1809 | + return QVariant(); |
| 1810 | + |
| 1811 | + return QVariant( ringCount ); |
| 1812 | +} |
| 1813 | + |
1586 | 1814 | static QVariant fcnBounds( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
1587 | 1815 | {
|
1588 | 1816 | QgsGeometry geom = getGeometry( values.at( 0 ), parent );
|
@@ -2435,7 +2663,10 @@ const QStringList& QgsExpression::BuiltinFunctions()
|
2435 | 2663 | << "color_cmyk" << "color_cmyka" << "color_part" << "set_color_part"
|
2436 | 2664 | << "xat" << "yat" << "$area" << "area" << "perimeter"
|
2437 | 2665 | << "$length" << "$perimeter" << "x" << "y" << "$x" << "$y" << "z" << "m" << "num_points"
|
| 2666 | + << "num_interior_rings" << "num_rings" << "num_geometries" |
| 2667 | + << "geometry_n" << "interior_ring_n" |
2438 | 2668 | << "point_n" << "start_point" << "end_point" << "make_point" << "make_point_m"
|
| 2669 | + << "nodes_to_points" << "segments_to_lines" |
2439 | 2670 | << "make_line" << "make_polygon"
|
2440 | 2671 | << "$x_at" << "x_at" << "xat" << "$y_at" << "y_at" << "yat" << "x_min" << "xmin" << "x_max" << "xmax"
|
2441 | 2672 | << "y_min" << "ymin" << "y_max" << "ymax" << "geom_from_wkt" << "geomFromWKT"
|
@@ -2560,6 +2791,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
2560 | 2791 | << new StaticFunction( "point_n", 2, fcnPointN, "GeometryGroup" )
|
2561 | 2792 | << new StaticFunction( "start_point", 1, fcnStartPoint, "GeometryGroup" )
|
2562 | 2793 | << new StaticFunction( "end_point", 1, fcnEndPoint, "GeometryGroup" )
|
| 2794 | + << new StaticFunction( "nodes_to_points", -1, fcnNodesToPoints, "GeometryGroup" ) |
| 2795 | + << new StaticFunction( "segments_to_lines", 1, fcnSegmentsToLines, "GeometryGroup" ) |
2563 | 2796 | << new StaticFunction( "make_point", -1, fcnMakePoint, "GeometryGroup" )
|
2564 | 2797 | << new StaticFunction( "make_point_m", 3, fcnMakePointM, "GeometryGroup" )
|
2565 | 2798 | << new StaticFunction( "make_line", -1, fcnMakeLine, "GeometryGroup" )
|
@@ -2587,8 +2820,13 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
2587 | 2820 | << new StaticFunction( "point_on_surface", 1, fcnPointOnSurface, "GeometryGroup" )
|
2588 | 2821 | << new StaticFunction( "reverse", 1, fcnReverse, "GeometryGroup" )
|
2589 | 2822 | << new StaticFunction( "exterior_ring", 1, fcnExteriorRing, "GeometryGroup" )
|
| 2823 | + << new StaticFunction( "interior_ring_n", 2, fcnInteriorRingN, "GeometryGroup" ) |
| 2824 | + << new StaticFunction( "geometry_n", 2, fcnGeometryN, "GeometryGroup" ) |
2590 | 2825 | << new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup" )
|
2591 | 2826 | << new StaticFunction( "num_points", 1, fcnGeomNumPoints, "GeometryGroup" )
|
| 2827 | + << new StaticFunction( "num_interior_rings", 1, fcnGeomNumInteriorRings, "GeometryGroup" ) |
| 2828 | + << new StaticFunction( "num_rings", 1, fcnGeomNumRings, "GeometryGroup" ) |
| 2829 | + << new StaticFunction( "num_geometries", 1, fcnGeomNumGeometries, "GeometryGroup" ) |
2592 | 2830 | << new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "GeometryGroup" )
|
2593 | 2831 | << new StaticFunction( "bounds_height", 1, fcnBoundsHeight, "GeometryGroup" )
|
2594 | 2832 | << new StaticFunction( "is_closed", 1, fcnIsClosed, "GeometryGroup" )
|
|
0 commit comments