unsigned char* QgsGeometryAnalyzer::locateBetweenWkbString( unsigned char* ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure ) { int* nPoints = ( int* ) ptr; ptr += sizeof( int ); double prevx = 0.0, prevy = 0.0, prevz = 0.0; double *x, *y, *z; QgsPolyline currentLine; QgsPoint pt1, pt2; bool measureInSegment; //true if measure is contained in the segment bool secondPointClipped; //true if second point is != segment endpoint for ( int i = 0; i < *nPoints; ++i ) { x = ( double* )ptr; ptr += sizeof( double ); y = ( double* )ptr; ptr += sizeof( double ); z = ( double* ) ptr; ptr += sizeof( double ); if ( i > 0 ) { measureInSegment = clipSegmentByRange( prevx, prevy, prevz, *x, *y, *z, fromMeasure, toMeasure, pt1, pt2, secondPointClipped ); if ( measureInSegment ) { if ( currentLine.size() < 1 ) //no points collected yet, so the first point needs to be added to the line { currentLine.append( pt1 ); } if ( pt1 != pt2 ) //avoid duplicated entry if measure value equals m-value of vertex { currentLine.append( pt2 ); } if ( secondPointClipped || i == *nPoints - 1 ) //close current segment { if ( currentLine.size() > 1 ) { result.append( currentLine ); } currentLine.clear(); } } } prevx = *x; prevy = *y; prevz = *z; } return ptr; }
void TestQgsDistanceArea::measureAreaAndUnits() { QgsDistanceArea da; da.setSourceCrs( 3452 ); da.setEllipsoidalMode( false ); da.setEllipsoid( "NONE" ); QgsCoordinateReferenceSystem daCRS; daCRS.createFromSrsId( da.sourceCrsId() ); QgsPolyline ring; ring << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 2, 1 ) << QgsPoint( 2, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ); QgsPolygon poly; poly << ring; QgsGeometry polygon( QgsGeometry::fromPolygon( poly ) ); // We check both the measured area AND the units, in case the logic regarding // ellipsoids and units changes in future double area = da.measureArea( &polygon ); QgsUnitTypes::AreaUnit units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QVERIFY(( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::AreaSquareDegrees ) || ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::AreaSquareMeters ) ); da.setEllipsoid( "WGS84" ); area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QVERIFY(( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::AreaSquareDegrees ) || ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::AreaSquareMeters ) ); da.setEllipsoidalMode( true ); area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); // should always be in Meters Squared QGSCOMPARENEAR( area, 37416879192.9, 0.1 ); QCOMPARE( units, QgsUnitTypes::AreaSquareMeters ); // test converting the resultant area area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareMiles ); QGSCOMPARENEAR( area, 14446.7378, 0.001 ); // now try with a source CRS which is in feet ring.clear(); ring << QgsPoint( 1850000, 4423000 ) << QgsPoint( 1851000, 4423000 ) << QgsPoint( 1851000, 4424000 ) << QgsPoint( 1852000, 4424000 ) << QgsPoint( 1852000, 4425000 ) << QgsPoint( 1851000, 4425000 ) << QgsPoint( 1850000, 4423000 ); poly.clear(); poly << ring; polygon = QgsGeometry::fromPolygon( poly ); da.setSourceCrs( 27469 ); da.setEllipsoidalMode( false ); // measurement should be in square feet area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QGSCOMPARENEAR( area, 2000000, 0.001 ); QCOMPARE( units, QgsUnitTypes::AreaSquareFeet ); // test converting the resultant area area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareYards ); QGSCOMPARENEAR( area, 222222.2222, 0.001 ); da.setEllipsoidalMode( true ); // now should be in Square Meters again area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QGSCOMPARENEAR( area, 184149.37, 1.0 ); QCOMPARE( units, QgsUnitTypes::AreaSquareMeters ); // test converting the resultant area area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareYards ); QgsDebugMsg( QString( "measured %1 in sq yrds" ).arg( area ) ); QGSCOMPARENEAR( area, 220240.8172549, 0.00001 ); }
ErrorList topolTest::checkSegmentLength( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ) { Q_UNUSED( layer1 ); Q_UNUSED( layer2 ); Q_UNUSED( isExtent ); int i = 0; ErrorList errorList; QgsFeature f; QList<FeatureLayer>::Iterator it; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); QgsPolygon pol; QgsMultiPolygon mpol; QgsPolyline segm; QgsPolyline ls; QgsMultiPolyline mls; QList<FeatureLayer> fls; TopolErrorShort* err; double distance; for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) { emit progress( i ); } if ( testCancelled() ) { break; } QgsGeometry* g1 = it->feature.geometry(); // switching by type here, because layer can contain both single and multi version geometries switch ( g1->wkbType() ) { case QGis::WKBLineString: case QGis::WKBLineString25D: ls = g1->asPolyline(); for ( int i = 1; i < ls.size(); ++i ) { distance = sqrt( ls[i-1].sqrDist( ls[i] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << ls[i-1] << ls[i]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); //err = new TopolErrorShort(g1->boundingBox(), QgsGeometry::fromPolyline(segm), fls); errorList << err; //break on getting the first error break; } } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: pol = g1->asPolygon(); for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = sqrt( pol[i][j-1].sqrDist( pol[i][j] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << pol[i][j-1] << pol[i][j]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: mls = g1->asMultiPolyline(); for ( int k = 0; k < mls.size(); ++k ) { QgsPolyline& ls = mls[k]; for ( int i = 1; i < ls.size(); ++i ) { distance = sqrt( ls[i-1].sqrDist( ls[i] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << ls[i-1] << ls[i]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: mpol = g1->asMultiPolygon(); for ( int k = 0; k < mpol.size(); ++k ) { QgsPolygon& pol = mpol[k]; for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = pol[i][j-1].sqrDist( pol[i][j] ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << pol[i][j-1] << pol[i][j]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } } break; default: continue; } } return errorList; }