[QGIS Commit] r15381 - in trunk/qgis: python/core src/app src/core
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Mon Mar 7 15:57:51 EST 2011
Author: jef
Date: 2011-03-07 12:57:51 -0800 (Mon, 07 Mar 2011)
New Revision: 15381
Modified:
trunk/qgis/python/core/qgsdistancearea.sip
trunk/qgis/src/app/qgsfieldcalculator.cpp
trunk/qgis/src/core/qgsdistancearea.cpp
trunk/qgis/src/core/qgsdistancearea.h
trunk/qgis/src/core/qgssearchstringlexer.ll
trunk/qgis/src/core/qgssearchstringparser.yy
trunk/qgis/src/core/qgssearchtreenode.cpp
trunk/qgis/src/core/qgssearchtreenode.h
Log:
[FEATURE] add $x, $y and $perimeter to field calculator
Modified: trunk/qgis/python/core/qgsdistancearea.sip
===================================================================
--- trunk/qgis/python/core/qgsdistancearea.sip 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/python/core/qgsdistancearea.sip 2011-03-07 20:57:51 UTC (rev 15381)
@@ -49,6 +49,9 @@
//! general measurement (line distance or polygon area)
double measure(QgsGeometry* geometry);
+
+ //! measurement perimater of polygon
+ double measurePerimeter(QgsGeometry* geometry);
//! measures line with more segments
double measureLine(const QList<QgsPoint>& points);
Modified: trunk/qgis/src/app/qgsfieldcalculator.cpp
===================================================================
--- trunk/qgis/src/app/qgsfieldcalculator.cpp 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/app/qgsfieldcalculator.cpp 2011-03-07 20:57:51 UTC (rev 15381)
@@ -35,6 +35,7 @@
populateFields();
populateOutputFieldTypes();
+
//default values for field width and precision
mOuputFieldWidthSpinBox->setValue( 10 );
mOutputFieldPrecisionSpinBox->setValue( 3 );
@@ -42,6 +43,8 @@
//disable ok button until there is text for output field and expression
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
+ mExistingFieldComboBox->setDisabled( true );
+
// disable creation of new fields if not supported by data provider
if ( !( vl->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes ) )
{
@@ -151,7 +154,12 @@
// block layerModified signals (that would trigger table update)
mVectorLayer->blockSignals( true );
- bool useGeometry = calcString.contains( "$area" ) || calcString.contains( "$length" );
+ bool useGeometry =
+ calcString.contains( "$area" ) ||
+ calcString.contains( "$length" ) ||
+ calcString.contains( "$perimeter" ) ||
+ calcString.contains( "$x" ) ||
+ calcString.contains( "$y" );
int rownum = 1;
mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), QgsRectangle(), useGeometry, false );
@@ -267,14 +275,8 @@
void QgsFieldCalculator::on_mUpdateExistingFieldCheckBox_stateChanged( int state )
{
- if ( state == Qt::Checked )
- {
- mNewFieldGroupBox->setEnabled( false );
- }
- else
- {
- mNewFieldGroupBox->setEnabled( true );
- }
+ mExistingFieldComboBox->setEnabled( state == Qt::Checked );
+ mNewFieldGroupBox->setDisabled( state == Qt::Checked );
setOkButtonState();
}
Modified: trunk/qgis/src/core/qgsdistancearea.cpp
===================================================================
--- trunk/qgis/src/core/qgsdistancearea.cpp 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/core/qgsdistancearea.cpp 2011-03-07 20:57:51 UTC (rev 15381)
@@ -223,7 +223,7 @@
case QGis::WKBPolygon25D:
hasZptr = true;
case QGis::WKBPolygon:
- measurePolygon( wkb, &res, hasZptr );
+ measurePolygon( wkb, &res, 0, hasZptr );
QgsDebugMsg( "returning " + QString::number( res ) );
return res;
@@ -234,7 +234,7 @@
ptr = wkb + 9;
for ( i = 0; i < count; i++ )
{
- ptr = measurePolygon( ptr, &res, hasZptr );
+ ptr = measurePolygon( ptr, &res, 0, hasZptr );
resTotal += res;
}
QgsDebugMsg( "returning " + QString::number( resTotal ) );
@@ -246,7 +246,60 @@
}
}
+double QgsDistanceArea::measurePerimeter( QgsGeometry* geometry )
+{
+ if ( !geometry )
+ return 0.0;
+ unsigned char* wkb = geometry->asWkb();
+ if ( !wkb )
+ return 0.0;
+
+ unsigned char* ptr;
+ unsigned int wkbType;
+ double res, resTotal = 0;
+ int count, i;
+
+ memcpy( &wkbType, ( wkb + 1 ), sizeof( wkbType ) );
+
+ // measure distance or area based on what is the type of geometry
+ bool hasZptr = false;
+
+ switch ( wkbType )
+ {
+ case QGis::WKBLineString25D:
+ case QGis::WKBLineString:
+ case QGis::WKBMultiLineString25D:
+ case QGis::WKBMultiLineString:
+ return 0.0;
+
+ case QGis::WKBPolygon25D:
+ hasZptr = true;
+ case QGis::WKBPolygon:
+ measurePolygon( wkb, 0, &res, hasZptr );
+ QgsDebugMsg( "returning " + QString::number( res ) );
+ return res;
+
+ case QGis::WKBMultiPolygon25D:
+ hasZptr = true;
+ case QGis::WKBMultiPolygon:
+ count = *(( int* )( wkb + 5 ) );
+ ptr = wkb + 9;
+ for ( i = 0; i < count; i++ )
+ {
+ ptr = measurePolygon( ptr, 0, &res, hasZptr );
+ resTotal += res;
+ }
+ QgsDebugMsg( "returning " + QString::number( resTotal ) );
+ return resTotal;
+
+ default:
+ QgsDebugMsg( QString( "measure: unexpected geometry type: %1" ).arg( wkbType ) );
+ return 0;
+ }
+}
+
+
unsigned char* QgsDistanceArea::measureLine( unsigned char* feature, double* area, bool hasZptr )
{
unsigned char *ptr = feature + 5;
@@ -344,7 +397,7 @@
}
-unsigned char* QgsDistanceArea::measurePolygon( unsigned char* feature, double* area, bool hasZptr )
+unsigned char* QgsDistanceArea::measurePolygon( unsigned char* feature, double* area, double* perimeter, bool hasZptr )
{
// get number of rings in the polygon
unsigned int numRings = *(( int* )( feature + 1 + sizeof( int ) ) );
@@ -357,8 +410,11 @@
QList<QgsPoint> points;
QgsPoint pnt;
- double x, y, areaTmp;
- *area = 0;
+ double x, y;
+ if ( area )
+ *area = 0;
+ if ( perimeter )
+ *perimeter = 0;
try
{
@@ -392,20 +448,38 @@
if ( points.size() > 2 )
{
- areaTmp = computePolygonArea( points );
- if ( idx == 0 )
- *area += areaTmp; // exterior ring
- else
- *area -= areaTmp; // interior rings
+ if ( area )
+ {
+ double areaTmp = computePolygonArea( points );
+ if ( idx == 0 )
+ {
+ // exterior ring
+ *area += areaTmp;
+ }
+ else
+ {
+ *area -= areaTmp; // interior rings
+ }
+ }
+
+ if ( perimeter )
+ {
+ *perimeter += measureLine( points );
+ }
}
points.clear();
+
+ if ( !area )
+ {
+ break;
+ }
}
}
catch ( QgsCsException &cse )
{
Q_UNUSED( cse );
- QgsLogger::warning( QObject::tr( "Caught a coordinate system exception while trying to transform a point. Unable to calculate polygon area." ) );
+ QgsLogger::warning( QObject::tr( "Caught a coordinate system exception while trying to transform a point. Unable to calculate polygon area or perimeter." ) );
}
return ptr;
@@ -679,7 +753,6 @@
{
QString unitLabel;
-
switch ( u )
{
case QGis::Meters:
@@ -785,5 +858,4 @@
return QLocale::system().toString( value, 'f', decimals ) + unitLabel;
-
}
Modified: trunk/qgis/src/core/qgsdistancearea.h
===================================================================
--- trunk/qgis/src/core/qgsdistancearea.h 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/core/qgsdistancearea.h 2011-03-07 20:57:51 UTC (rev 15381)
@@ -77,8 +77,12 @@
//! general measurement (line distance or polygon area)
double measure( QgsGeometry* geometry );
- //! measures line with more segments
+ //! measures perimeter of polygon
+ double measurePerimeter( QgsGeometry* geometry );
+
+ //! measures line
double measureLine( const QList<QgsPoint>& points );
+
//! measures line with one segment
double measureLine( const QgsPoint& p1, const QgsPoint& p2 );
@@ -91,11 +95,10 @@
static QString textUnit( double value, int decimals, QGis::UnitType u, bool isArea, bool keepBaseUnit = false );
protected:
-
//! measures line distance, line points are extracted from WKB
unsigned char* measureLine( unsigned char* feature, double* area, bool hasZptr = false );
- //! measures polygon area, vertices are extracted from WKB
- unsigned char* measurePolygon( unsigned char* feature, double* area, bool hasZptr = false );
+ //! measures polygon area and perimeter, vertices are extracted from WKB
+ unsigned char* measurePolygon( unsigned char* feature, double* area, double* perimeter, bool hasZptr = false );
/**
calculates distance from two points on ellipsoid
Modified: trunk/qgis/src/core/qgssearchstringlexer.ll
===================================================================
--- trunk/qgis/src/core/qgssearchstringlexer.ll 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/core/qgssearchstringlexer.ll 2011-03-07 20:57:51 UTC (rev 15381)
@@ -121,6 +121,9 @@
"$area" { return AREA; }
"$length" { return LENGTH; }
+"$perimeter" { return PERIMETER; }
+"$x" { return X; }
+"$y" { return Y; }
"$id" { return ID; }
{column_ref} { return COLUMN_REF; }
Modified: trunk/qgis/src/core/qgssearchstringparser.yy
===================================================================
--- trunk/qgis/src/core/qgssearchstringparser.yy 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/core/qgssearchstringparser.yy 2011-03-07 20:57:51 UTC (rev 15381)
@@ -74,7 +74,10 @@
%token IN
%token ROWNUM
%token AREA
+%token PERIMETER
%token LENGTH
+%token X
+%token Y
%token ID
%token NULLVALUE
@@ -177,7 +180,10 @@
| scalar_exp CONCAT scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opCONCAT, $1, $3); joinTmpNodes($$, $1, $3); }
| ROWNUM { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opROWNUM, 0, 0); addToTmpNodes($$); }
| AREA { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opAREA, 0, 0); addToTmpNodes($$); }
+ | PERIMETER { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPERIMETER, 0, 0); addToTmpNodes($$); }
| LENGTH { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opLENGTH, 0, 0); addToTmpNodes($$); }
+ | X { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opX, 0, 0); addToTmpNodes($$); }
+ | Y { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opY, 0, 0); addToTmpNodes($$); }
| ID { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opID, 0, 0); addToTmpNodes($$); }
| NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); }
| STRING { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 0); addToTmpNodes($$); }
Modified: trunk/qgis/src/core/qgssearchtreenode.cpp
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.cpp 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/core/qgssearchtreenode.cpp 2011-03-07 20:57:51 UTC (rev 15381)
@@ -139,7 +139,7 @@
{
mCalc = NULL;
- if ( mType == tOperator && ( mOp == opLENGTH || mOp == opAREA ) )
+ if ( mType == tOperator && ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER ) )
{
//initialize QgsDistanceArea
mCalc = new QgsDistanceArea;
@@ -232,14 +232,17 @@
// currently all functions take one parameter
str += QString( "(%1)" ).arg( mLeft->makeSearchString() );
}
- else if ( mOp == opLENGTH || mOp == opAREA || mOp == opROWNUM || mOp == opID )
+ else if ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER || mOp == opROWNUM || mOp == opID || mOp == opX || mOp == opY )
{
// special nullary opeators
switch ( mOp )
{
case opLENGTH: str += "$length"; break;
case opAREA: str += "$area"; break;
+ case opPERIMETER: str += "$perimeter"; break;
case opROWNUM: str += "$rownum"; break;
+ case opX: str += "$x"; break;
+ case opY: str += "$y"; break;
case opID: str += "$id"; break;
default: str += "?";
}
@@ -361,7 +364,7 @@
{
if ( mType == tOperator )
{
- if ( mOp == opLENGTH || mOp == opAREA )
+ if ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER || mOp == opX || mOp == opY )
return true;
if ( mLeft && mLeft->needsGeometry() )
@@ -656,7 +659,7 @@
if ( !getValue( value2, mRight, fields, f ) ) return value2;
}
- if ( mOp == opLENGTH || mOp == opAREA )
+ if ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER || mOp == opX || mOp == opY )
{
if ( !f.geometry() )
{
@@ -664,15 +667,27 @@
}
//check that we don't use area for lines or length for polygons
- if ( mOp == opLENGTH && f.geometry()->type() != QGis::Line )
+ if ( mOp == opLENGTH && f.geometry()->type() == QGis::Line )
{
- return QgsSearchTreeValue( 0 );
+ return QgsSearchTreeValue( mCalc->measure( f.geometry() ) );
}
- if ( mOp == opAREA && f.geometry()->type() != QGis::Polygon )
+ if ( mOp == opAREA && f.geometry()->type() == QGis::Polygon )
{
- return QgsSearchTreeValue( 0 );
+ return QgsSearchTreeValue( mCalc->measure( f.geometry() ) );
}
- return QgsSearchTreeValue( mCalc->measure( f.geometry() ) );
+ if ( mOp == opPERIMETER && f.geometry()->type() == QGis::Polygon )
+ {
+ return QgsSearchTreeValue( mCalc->measurePerimeter( f.geometry() ) );
+ }
+ if ( mOp == opX && f.geometry()->type() == QGis::Point )
+ {
+ return QgsSearchTreeValue( f.geometry()->asPoint().x() );
+ }
+ if ( mOp == opY && f.geometry()->type() == QGis::Point )
+ {
+ return QgsSearchTreeValue( f.geometry()->asPoint().y() );
+ }
+ return QgsSearchTreeValue( 0 );
}
if ( mOp == opID )
Modified: trunk/qgis/src/core/qgssearchtreenode.h
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.h 2011-03-07 16:45:27 UTC (rev 15380)
+++ trunk/qgis/src/core/qgssearchtreenode.h 2011-03-07 20:57:51 UTC (rev 15381)
@@ -82,9 +82,14 @@
opTOREAL,
opTOSTRING,
+ // coordinates
+ opX,
+ opY,
+
// measuring
opLENGTH,
opAREA,
+ opPERIMETER,
// feature id
opID,
More information about the QGIS-commit
mailing list