Index: src/app/qgsmaptooladdfeature.cpp =================================================================== --- src/app/qgsmaptooladdfeature.cpp (revision 9915) +++ src/app/qgsmaptooladdfeature.cpp (working copy) @@ -53,8 +53,7 @@ QGis::WkbType layerWKBType = vlayer->wkbType(); //no support for adding features to 2.5D types yet - if ( layerWKBType == QGis::WKBLineString25D || layerWKBType == QGis::WKBPolygon25D || - layerWKBType == QGis::WKBMultiLineString25D || layerWKBType == QGis::WKBPoint25D || layerWKBType == QGis::WKBMultiPoint25D ) + if ( QGis::wkbTypeCoordNum( layerWKBType ) > 2 ) { QMessageBox::critical( 0, tr( "2.5D shape type not supported" ), tr( "Adding features to 2.5D shapetypes is not supported yet" ) ); delete mRubberBand; Index: src/app/qgsdbtablemodel.cpp =================================================================== --- src/app/qgsdbtablemodel.cpp (revision 9915) +++ src/app/qgsdbtablemodel.cpp (working copy) @@ -215,48 +215,50 @@ QIcon QgsDbTableModel::iconForType( QGis::WkbType type ) const { - if ( type == QGis::WKBPoint || type == QGis::WKBPoint25D || type == QGis::WKBMultiPoint || type == QGis::WKBMultiPoint25D ) + switch ( QGis::wkbType2d( type ) ) { - return QgisApp::getThemeIcon( "/mIconPointLayer.png" ); + case QGis::WKBPoint: + case QGis::WKBMultiPoint: + return QgisApp::getThemeIcon( "/mIconPointLayer.png" ); + + case QGis::WKBLineString: + case QGis::WKBMultiLineString: + return QgisApp::getThemeIcon( "/mIconLineLayer.png" ); + + case QGis::WKBPolygon: + case QGis::WKBMultiPolygon: + return QgisApp::getThemeIcon( "/mIconPolygonLayer.png" ); + + default: + return QIcon(); } - else if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D || type == QGis::WKBMultiLineString || type == QGis::WKBMultiLineString25D ) - { - return QgisApp::getThemeIcon( "/mIconLineLayer.png" ); - } - else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon || type == QGis::WKBMultiPolygon25D ) - { - return QgisApp::getThemeIcon( "/mIconPolygonLayer.png" ); - } - else return QIcon(); } QString QgsDbTableModel::displayStringForType( QGis::WkbType type ) const { - if ( type == QGis::WKBPoint || type == QGis::WKBPoint25D ) + switch ( QGis::wkbType2d( type ) ) { - return tr( "Point" ); + case QGis::WKBPoint: + return tr( "Point" ); + + case QGis::WKBMultiPoint: + return tr( "Multipoint" ); + + case QGis::WKBLineString: + return tr( "Line" ); + + case QGis::WKBMultiLineString: + return tr( "Multiline" ); + + case QGis::WKBPolygon: + return tr( "Polygon" ); + + case QGis::WKBMultiPolygon: + return tr( "Multipolygon" ); + + default: + return tr( "Unknown" ); } - else if ( type == QGis::WKBMultiPoint || type == QGis::WKBMultiPoint25D ) - { - return tr( "Multipoint" ); - } - else if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D ) - { - return tr( "Line" ); - } - else if ( type == QGis::WKBMultiLineString || type == QGis::WKBMultiLineString25D ) - { - return tr( "Multiline" ); - } - else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D ) - { - return tr( "Polygon" ); - } - else if ( type == QGis::WKBMultiPolygon || type == QGis::WKBMultiPolygon25D ) - { - return tr( "Multipolygon" ); - } - return "Unknown"; } QGis::WkbType QgsDbTableModel::qgisTypeFromDbType( const QString& dbType ) const Index: src/app/qgisapp.cpp =================================================================== --- src/app/qgisapp.cpp (revision 9915) +++ src/app/qgisapp.cpp (working copy) @@ -4947,7 +4947,7 @@ if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) { //don't enable vertex move for single point - if ( vlayer->wkbType() != QGis::WKBPoint && vlayer->wkbType() != QGis::WKBPoint25D ) + if ( QGis::wkbType2d( vlayer->wkbType() ) != QGis::WKBPoint ) { mActionMoveVertex->setEnabled( true ); } Index: src/plugins/interpolation/qgsinterpolationdialog.cpp =================================================================== --- src/plugins/interpolation/qgsinterpolationdialog.cpp (revision 9915) +++ src/plugins/interpolation/qgsinterpolationdialog.cpp (working copy) @@ -140,12 +140,7 @@ //find out if the layer has 25D type QGis::WkbType geomType = provider->geometryType(); - if ( geomType == QGis::WKBPoint25D || - geomType == QGis::WKBLineString25D || - geomType == QGis::WKBPolygon25D || - geomType == QGis::WKBMultiPoint25D || - geomType == QGis::WKBMultiLineString25D || - geomType == QGis::WKBMultiPolygon25D ) + if ( QGis::wkbTypeHasZValue( geomType ) ) { mUseZCoordCheckBox->setEnabled( true ); } Index: src/plugins/interpolation/qgsinterpolator.cpp =================================================================== --- src/plugins/interpolation/qgsinterpolator.cpp (revision 9915) +++ src/plugins/interpolation/qgsinterpolator.cpp (working copy) @@ -106,15 +106,15 @@ return 1; } - bool hasZValue = false; unsigned char* currentWkbPtr = geom->asWkb(); vertexData theVertex; //the current vertex QGis::WkbType wkbType = geom->wkbType(); + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + bool hasZValue = QGis::wkbTypeHasZValue( wkbType ); + switch ( wkbType ) { - case QGis::WKBPoint25D: - hasZValue = true; case QGis::WKBPoint: { currentWkbPtr += ( 1 + sizeof( int ) ); @@ -133,8 +133,7 @@ mCachedBaseData.push_back( theVertex ); break; } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { currentWkbPtr += ( 1 + sizeof( int ) ); @@ -149,12 +148,12 @@ if ( zCoordInterpolation && hasZValue ) //skip z-coordinate for 25D geometries { theVertex.z = *(( double * )( currentWkbPtr ) ); - currentWkbPtr += sizeof( double ); } else { theVertex.z = attributeValue; } + currentWkbPtr += ( nCoordNum - 2 ) * sizeof( double ); mCachedBaseData.push_back( theVertex ); } break; Index: src/plugins/north_arrow/plugin.cpp =================================================================== --- src/plugins/north_arrow/plugin.cpp (revision 9915) +++ src/plugins/north_arrow/plugin.cpp (working copy) @@ -340,8 +340,8 @@ double angle = 0.0; // convert to radians for the equations below - p1.multiply( PI / 180.0 ); - p2.multiply( PI / 180.0 ); + p1.multiply2d( PI / 180.0 ); + p2.multiply2d( PI / 180.0 ); double y = sin( p2.x() - p1.x() ) * cos( p2.y() ); double x = cos( p1.y() ) * sin( p2.y() ) - Index: src/plugins/grid_maker/graticulecreator.cpp =================================================================== --- src/plugins/grid_maker/graticulecreator.cpp (revision 9915) +++ src/plugins/grid_maker/graticulecreator.cpp (working copy) @@ -102,7 +102,7 @@ // Create a polygon feature // QgsPolyline myPolyline; - QgsPoint myPoint = QgsPoint( i, j ); + QgsPoint myPoint( i, j ); // // NOTE: dont delete this pointer again - // ownership is passed to the feature which will Index: src/gui/qgsmapcanvasitem.cpp =================================================================== --- src/gui/qgsmapcanvasitem.cpp (revision 9915) +++ src/gui/qgsmapcanvasitem.cpp (working copy) @@ -33,7 +33,7 @@ QgsMapCanvasItem::~QgsMapCanvasItem() { - update(); // shedule redraw of canvas + update(); // schedule redraw of canvas } void QgsMapCanvasItem::paint( QPainter * painter, Index: src/gui/qgsmapcanvassnapper.cpp =================================================================== --- src/gui/qgsmapcanvassnapper.cpp (revision 9915) +++ src/gui/qgsmapcanvassnapper.cpp (working copy) @@ -67,8 +67,8 @@ { //topological editing on? - int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); - if ( topologicalEditing == 0 ) + bool topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 )!=0; + if ( !topologicalEditing ) { mSnapper->setSnapMode( QgsSnapper::SnapWithOneResult ); } Index: src/gui/qgsrubberband.cpp =================================================================== --- src/gui/qgsrubberband.cpp (revision 9916) +++ src/gui/qgsrubberband.cpp (working copy) @@ -169,11 +169,10 @@ reset( mIsPolygon ); - switch ( geom->wkbType() ) + switch ( QGis::wkbType2d( geom->wkbType() ) ) { case QGis::WKBPoint: - case QGis::WKBPoint25D: { mIsPolygon = true; double d = mMapCanvas->extent().width() * 0.005; @@ -194,7 +193,6 @@ break; case QGis::WKBMultiPoint: - case QGis::WKBMultiPoint25D: { mIsPolygon = true; double d = mMapCanvas->extent().width() * 0.005; @@ -221,7 +219,6 @@ break; case QGis::WKBLineString: - case QGis::WKBLineString25D: { mIsPolygon = false; QgsPolyline line = geom->asPolyline(); @@ -240,7 +237,6 @@ break; case QGis::WKBMultiLineString: - case QGis::WKBMultiLineString25D: { mIsPolygon = false; mPoints.clear(); @@ -267,7 +263,6 @@ break; case QGis::WKBPolygon: - case QGis::WKBPolygon25D: { mIsPolygon = true; QgsPolygon poly = geom->asPolygon(); @@ -287,7 +282,6 @@ break; case QGis::WKBMultiPolygon: - case QGis::WKBMultiPolygon25D: { mIsPolygon = true; mPoints.clear(); Index: src/core/qgscoordinatetransform.cpp =================================================================== --- src/core/qgscoordinatetransform.cpp (revision 9915) +++ src/core/qgscoordinatetransform.cpp (working copy) @@ -292,9 +292,9 @@ { if ( mShortCircuit || !mInitialisedFlag ) return; -#ifdef QGISDEBUG -// QgsDebugMsg(QString("Using transform in place %1 %2").arg(__FILE__).arg(__LINE__)); -#endif + + // QgsDebugMsg( "Using transform in place" ); + // transform x try { Index: src/core/qgspoint.cpp =================================================================== --- src/core/qgspoint.cpp (revision 9915) +++ src/core/qgspoint.cpp (working copy) @@ -26,6 +26,8 @@ { m_x = p.x(); m_y = p.y(); + m_z = p.z(); + m_m = p.m(); } QString QgsPoint::toString() const @@ -34,6 +36,17 @@ QTextStream ot( &rep ); ot.setRealNumberPrecision( 12 ); ot << m_x << ", " << m_y; + + if ( is3d() ) + { + ot << ", " << m_z; + } + + if ( isMeasured() ) + { + ot << ", " << m_m; + } + return rep; } @@ -41,40 +54,63 @@ { QString rep = QString::number( m_x, 'f', thePrecision ) + QString( "," ) + QString::number( m_y, 'f', thePrecision ); + + if ( is3d() ) + { + rep += "," + QString::number( m_z, 'f', thePrecision ); + } + + if ( isMeasured() ) + { + rep += "," + QString::number( m_m, 'f', thePrecision ); + } + return rep; } QString QgsPoint::wellKnownText() const { - return QString( "POINT(%1 %2)" ).arg( QString::number( m_x, 'f', 18 ) ).arg( QString::number( m_y, 'f', 18 ) ); + QString wkt = QString( "%1(%2 %3" ) + .arg( isMeasured() && !is3d() ? "POINTM" : "POINT" ) + .arg( QString::number( m_x, 'f', 18 ) ) + .arg( QString::number( m_y, 'f', 18 ) ); + + if ( is3d() ) + { + wkt += " " + QString::number( m_z, 'f', 18 ); + } + + if ( isMeasured() ) + { + wkt += " " + QString::number( m_m, 'f', 18 ); + } + + return wkt + ")"; } -double QgsPoint::sqrDist( double x, double y ) const +double QgsPoint::sqrDist2d( double x, double y ) const { - return ( m_x -x )*( m_x - x ) + ( m_y - y )*( m_y - y ); + return ( m_x - x )*( m_x - x ) + ( m_y - y )*( m_y - y ); } -double QgsPoint::sqrDist( const QgsPoint& other ) const +double QgsPoint::sqrDist2d( const QgsPoint& other ) const { - return sqrDist( other.x(), other.y() ); + return sqrDist2d( other.x(), other.y() ); } // operators -bool QgsPoint::operator==( const QgsPoint & other ) +bool QgsPoint::operator==( const QgsPoint & other ) const { - if (( m_x == other.x() ) && ( m_y == other.y() ) ) - return true; - else - return false; + return other.x() == m_x && + other.y() == m_y && + ( (!other.is3d() && !is3d()) || other.z() == m_z ) && + ( (!other.isMeasured() && !isMeasured()) || other.m() == m_m ); } bool QgsPoint::operator!=( const QgsPoint & other ) const { - if (( m_x == other.x() ) && ( m_y == other.y() ) ) - return false; - else - return true; + return !( *this == other ); } QgsPoint & QgsPoint::operator=( const QgsPoint & other ) @@ -83,18 +119,20 @@ { m_x = other.x(); m_y = other.y(); + m_z = other.z(); + m_m = other.m(); } return *this; } -void QgsPoint::multiply( const double& scalar ) +void QgsPoint::multiply2d( const double& scalar ) { m_x *= scalar; m_y *= scalar; } -int QgsPoint::onSegment( const QgsPoint& a, const QgsPoint& b ) const +int QgsPoint::onSegment2d( const QgsPoint& a, const QgsPoint& b ) const { //algorithm from 'graphics GEMS', A. Paeth: 'A Fast 2D Point-on-line test' if ( Index: src/core/qgsvectorlayer.cpp =================================================================== --- src/core/qgsvectorlayer.cpp (revision 9915) +++ src/core/qgsvectorlayer.cpp (working copy) @@ -347,22 +347,19 @@ unsigned int nPoints = *(( int* )ptr ); ptr = feature + 9; - bool hasZValue = ( wkbType == QGis::WKBLineString25D ); - std::vector x( nPoints ); std::vector y( nPoints ); std::vector z( nPoints, 0.0 ); + int nCoordNum = QGis::wkbTypeCoordNum(( QGis::WkbType ) wkbType ); + // Extract the points from the WKB format into the x and y vectors. for ( register unsigned int i = 0; i < nPoints; ++i ) { x[i] = *(( double * ) ptr ); ptr += sizeof( double ); y[i] = *(( double * ) ptr ); - ptr += sizeof( double ); - - if ( hasZValue ) // ignore Z value - ptr += sizeof( double ); + ptr += ( nCoordNum - 1 ) * sizeof( double ); } // Transform the points into map coordinates (and reproject if @@ -464,8 +461,6 @@ unsigned int wkbType = *(( int* )( feature + 1 ) ); - bool hasZValue = ( wkbType == QGis::WKBPolygon25D ); - int total_points = 0; // A vector containing a pointer to a pair of double vectors.The @@ -476,6 +471,8 @@ // Set pointer to the first ring unsigned char* ptr = feature + 1 + 2 * sizeof( int ); + int nCoordNum = QGis::wkbTypeCoordNum(( QGis::WkbType ) wkbType ); + for ( register unsigned int idx = 0; idx < numRings; idx++ ) { unsigned int nPoints = *(( int* )ptr ); @@ -492,10 +489,7 @@ ring->first[jdx] = *(( double * ) ptr ); ptr += sizeof( double ); ring->second[jdx] = *(( double * ) ptr ); - ptr += sizeof( double ); - - if ( hasZValue ) - ptr += sizeof( double ); + ptr += ( nCoordNum - 1 ) * sizeof( double ); } // If ring has fewer than two points, what is it then? // Anyway, this check prevents a crash @@ -648,7 +642,6 @@ // p->drawPath( path ); - // draw vertex markers if in editing mode, but only to the main canvas if ( mEditable && drawingToEditingCanvas ) { @@ -725,6 +718,7 @@ } else if ( featureCount % 1000 == 0 ) { + QgsDebugMsg( QString( "%1/%2 feature(s) drawn" ).arg( featureCount ).arg( totalFeatures ) ); emit drawingProgress( featureCount, totalFeatures ); qApp->processEvents(); } @@ -777,6 +771,7 @@ QgsLogger::warning( msg ); } + QgsDebugMsg( QString( "%1 feature(s) drawn" ).arg( featureCount ) ); } else { @@ -948,37 +943,7 @@ { if ( mDataProvider ) { - int type = mDataProvider->geometryType(); - switch ( type ) - { - case QGis::WKBPoint: - case QGis::WKBPoint25D: - return QGis::Point; - - case QGis::WKBLineString: - case QGis::WKBLineString25D: - return QGis::Line; - - case QGis::WKBPolygon: - case QGis::WKBPolygon25D: - return QGis::Polygon; - - case QGis::WKBMultiPoint: - case QGis::WKBMultiPoint25D: - return QGis::Point; - - case QGis::WKBMultiLineString: - case QGis::WKBMultiLineString25D: - return QGis::Line; - - case QGis::WKBMultiPolygon: - case QGis::WKBMultiPolygon25D: - return QGis::Polygon; - } -#ifdef QGISDEBUG - QgsLogger::debug( "Warning: Data Provider Geometry type is not recognised, is", type, 1, __FILE__, __FUNCTION__, __LINE__ ); -#endif - + return QGis::geometryTypeFromWkbType( mDataProvider->geometryType() ); } else { @@ -1464,9 +1429,13 @@ return true; } - bool QgsVectorLayer::insertVertex( double x, double y, int atFeatureId, int beforeVertex ) { + return insertVertex( QgsPoint( x, y ), atFeatureId, beforeVertex ); +} + +bool QgsVectorLayer::insertVertex( const QgsPoint &p, int atFeatureId, int beforeVertex ) +{ if ( !mEditable ) { return false; @@ -1485,7 +1454,7 @@ mChangedGeometries[atFeatureId] = mCachedGeometries[atFeatureId]; } - mChangedGeometries[atFeatureId].insertVertex( x, y, beforeVertex ); + mChangedGeometries[atFeatureId].insertVertex( p, beforeVertex ); setModified( true, true ); // only geometry was changed @@ -1497,6 +1466,11 @@ bool QgsVectorLayer::moveVertex( double x, double y, int atFeatureId, int atVertex ) { + return moveVertex( QgsPoint( x, y ), atFeatureId, atVertex ); +} + +bool QgsVectorLayer::moveVertex( const QgsPoint &p, int atFeatureId, int atVertex ) +{ if ( !mEditable ) { return false; @@ -1514,7 +1488,7 @@ mChangedGeometries[atFeatureId] = mCachedGeometries[atFeatureId]; } - mChangedGeometries[atFeatureId].moveVertex( x, y, atVertex ); + mChangedGeometries[atFeatureId].moveVertex( p, atVertex ); setModified( true, true ); // only geometry was changed @@ -1847,10 +1821,9 @@ QGis::WkbType wkbType = geom->wkbType(); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { //line - case QGis::WKBLineString25D: case QGis::WKBLineString: { QgsPolyline theLine = geom->asPolyline(); @@ -1866,7 +1839,6 @@ } //multiline - case QGis::WKBMultiLineString25D: case QGis::WKBMultiLineString: { QgsMultiPolyline theMultiLine = geom->asMultiPolyline(); @@ -1887,7 +1859,6 @@ } //polygon - case QGis::WKBPolygon25D: case QGis::WKBPolygon: { QgsPolygon thePolygon = geom->asPolygon(); @@ -1909,7 +1880,6 @@ } //multipolygon - case QGis::WKBMultiPolygon25D: case QGis::WKBMultiPolygon: { QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon(); @@ -3300,11 +3270,11 @@ unsigned char* feature = geom->asWkb(); QGis::WkbType wkbType = geom->wkbType(); + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { case QGis::WKBPoint: - case QGis::WKBPoint25D: { double x = *(( double * )( feature + 5 ) ); double y = *(( double * )( feature + 5 + sizeof( double ) ) ); @@ -3322,7 +3292,6 @@ break; } case QGis::WKBMultiPoint: - case QGis::WKBMultiPoint25D: { unsigned char *ptr = feature + 5; unsigned int nPoints = *(( int* )ptr ); @@ -3338,11 +3307,8 @@ double x = *(( double * ) ptr ); ptr += sizeof( double ); double y = *(( double * ) ptr ); - ptr += sizeof( double ); + ptr += ( nCoordNum - 1 ) * sizeof( double ); - if ( wkbType == QGis::WKBMultiPoint25D ) // ignore Z value - ptr += sizeof( double ); - transformPoint( x, y, theMapToPixelTransform, ct ); //QPointF pt(x - (marker->width()/2), y - (marker->height()/2)); //QPointF pt(x/markerScaleFactor - (marker->width()/2), y/markerScaleFactor - (marker->height()/2)); @@ -3363,7 +3329,6 @@ break; } case QGis::WKBLineString: - case QGis::WKBLineString25D: { drawLineString( feature, p, @@ -3373,7 +3338,6 @@ break; } case QGis::WKBMultiLineString: - case QGis::WKBMultiLineString25D: { unsigned char* ptr = feature + 5; unsigned int numLineStrings = *(( int* )ptr ); @@ -3390,7 +3354,6 @@ break; } case QGis::WKBPolygon: - case QGis::WKBPolygon25D: { drawPolygon( feature, p, @@ -3400,7 +3363,6 @@ break; } case QGis::WKBMultiPolygon: - case QGis::WKBMultiPolygon25D: { unsigned char *ptr = feature + 5; unsigned int numPolygons = *(( int* )ptr ); Index: src/core/qgssnapper.cpp =================================================================== --- src/core/qgssnapper.cpp (revision 9915) +++ src/core/qgssnapper.cpp (working copy) @@ -72,7 +72,7 @@ newResult.snappedVertex = mMapRenderer->layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().snappedVertex ); newResult.beforeVertex = mMapRenderer->layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().beforeVertex ); newResult.afterVertex = mMapRenderer->layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().afterVertex ); - snappingResultList.insert( sqrt( newResult.snappedVertex.sqrDist( mapCoordPoint ) ), newResult ); + snappingResultList.insert( sqrt( newResult.snappedVertex.sqrDist2d( mapCoordPoint ) ), newResult ); } } Index: src/core/qgsdistancearea.cpp =================================================================== --- src/core/qgsdistancearea.cpp (revision 9915) +++ src/core/qgsdistancearea.cpp (working copy) @@ -178,17 +178,14 @@ { unsigned char* wkb = geometry->asWkb(); 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 - switch ( wkbType ) + switch ( QGis::wkbType2d( (QGis::WkbType) *(unsigned int *) (wkb+1) ) ) { case QGis::WKBLineString: - measureLine( wkb, &res ); + measureLine( wkb, res ); return res; case QGis::WKBMultiLineString: @@ -196,13 +193,13 @@ ptr = wkb + 9; for ( i = 0; i < count; i++ ) { - ptr = measureLine( ptr, &res ); + ptr = measureLine( ptr, res ); resTotal += res; } return resTotal; case QGis::WKBPolygon: - measurePolygon( wkb, &res ); + measurePolygon( wkb, res ); return res; case QGis::WKBMultiPolygon: @@ -210,23 +207,23 @@ ptr = wkb + 9; for ( i = 0; i < count; i++ ) { - ptr = measurePolygon( ptr, &res ); + ptr = measurePolygon( ptr, res ); resTotal += res; } return resTotal; default: - QgsDebugMsg( QString( "measure: unexpected geometry type: %1" ).arg( wkbType ) ); + QgsDebugMsg( QString( "measure: unexpected geometry type: %1" ).arg( (QGis::WkbType) *(unsigned int *) (wkb+1) ) ); return 0; } } -unsigned char* QgsDistanceArea::measureLine( unsigned char* feature, double* area ) +unsigned char* QgsDistanceArea::measureLine( unsigned char* feature, double &area ) { - unsigned char *ptr = feature + 5; - unsigned int nPoints = *(( int* )ptr ); - ptr = feature + 9; + int nCoordNum = QGis::wkbTypeCoordNum( (QGis::WkbType) *(unsigned int *) (feature+1) ); + unsigned int nPoints = *( int* ) (feature+5); + double *pnts = (double *) (feature + 9); QList points; double x, y; @@ -235,15 +232,14 @@ // Extract the points from the WKB format into the vector for ( unsigned int i = 0; i < nPoints; ++i ) { - x = *(( double * ) ptr ); - ptr += sizeof( double ); - y = *(( double * ) ptr ); - ptr += sizeof( double ); + x = *pnts++; + y = *pnts++; points.append( QgsPoint( x, y ) ); + pnts += nCoordNum-2; } - *area = measureLine( points ); - return ptr; + area = measureLine( points ); + return (unsigned char*) pnts; } double QgsDistanceArea::measureLine( const QList& points ) @@ -313,54 +309,58 @@ } -unsigned char* QgsDistanceArea::measurePolygon( unsigned char* feature, double* area ) +unsigned char* QgsDistanceArea::measurePolygon( unsigned char *feature, double &area ) { + int nCoordNum = QGis::wkbTypeCoordNum( (QGis::WkbType) *(unsigned int *)(feature+1) ); + // get number of rings in the polygon - unsigned int numRings = *(( int* )( feature + 1 + sizeof( int ) ) ); - + unsigned int numRings = *( unsigned int* )(feature+5); if ( numRings == 0 ) return 0; // Set pointer to the first ring - unsigned char* ptr = feature + 1 + 2 * sizeof( int ); + unsigned char* ptr = feature + 9; QList points; QgsPoint pnt; double x, y, areaTmp; - *area = 0; + area = 0; try { for ( unsigned int idx = 0; idx < numRings; idx++ ) { - int nPoints = *(( int* )ptr ); - ptr += 4; + int nPoints = *( int* )ptr; + double *pnts = (double *) (ptr + 4); + double z = 0.0; + // Extract the points from the WKB and store in a pair of // vectors. for ( int jdx = 0; jdx < nPoints; jdx++ ) { - x = *(( double * ) ptr ); - ptr += sizeof( double ); - y = *(( double * ) ptr ); - ptr += sizeof( double ); - - pnt = QgsPoint( x, y ); - + x = *pnts++; + y = *pnts++; + if ( mProjectionsEnabled && ( mEllipsoid != "NONE" ) ) { - pnt = mCoordTransform->transform( pnt ); + mCoordTransform->transformInPlace( x, y, z ); } - points.append( pnt ); + + points.append( QgsPoint(x, y) ); + + pnts += nCoordNum - 2; } + ptr = (unsigned char *) pnts; + if ( points.size() > 2 ) { areaTmp = computePolygonArea( points ); if ( idx == 0 ) - *area += areaTmp; // exterior ring + area += areaTmp; // exterior ring else - *area -= areaTmp; // interior rings + area -= areaTmp; // interior rings } points.clear(); Index: src/core/qgsgeometry.cpp =================================================================== --- src/core/qgsgeometry.cpp (revision 9915) +++ src/core/qgsgeometry.cpp (working copy) @@ -230,11 +230,40 @@ return n; } +static void setGeosPoint( GEOSCoordSequence *seq, int i, const QgsPoint &p ) +{ + GEOSCoordSeq_setX( seq, i, p.x() ); + GEOSCoordSeq_setY( seq, i, p.y() ); + if ( p.is3d() ) + GEOSCoordSeq_setZ( seq, i, p.z() ); + if ( p.isMeasured() ) + GEOSCoordSeq_setOrdinate( seq, i, 3, p.m() ); +} + +static void getGeosPoint( const GEOSCoordSequence *seq, int i, QgsPoint &p ) +{ + double v; + GEOSCoordSeq_getX( seq, i, &v ); p.setX( v ); + GEOSCoordSeq_getY( seq, i, &v ); p.setY( v ); + + unsigned int n; + GEOSCoordSeq_getDimensions( seq, &n ); + + if ( n >= 3 ) + { + GEOSCoordSeq_getZ( seq, i, &v ); p.setZ( v ); + } + + if ( n >= 4 ) + { + GEOSCoordSeq_getOrdinate( seq, i, 3, &v ); p.setM( v ); + } +} + static GEOSGeometry *createGeosPoint( const QgsPoint &point ) { - GEOSCoordSequence *coord = GEOSCoordSeq_create( 1, 2 ); - GEOSCoordSeq_setX( coord, 0, point.x() ); - GEOSCoordSeq_setY( coord, 0, point.y() ); + GEOSCoordSequence *coord = GEOSCoordSeq_create( 1, point.isMeasured() ? 4 : ( point.is3d() ? 3 : 2 ) ); + setGeosPoint( coord, 0, point ); return GEOSGeom_createPoint( coord ); } @@ -244,12 +273,12 @@ try { - coord = GEOSCoordSeq_create( points.count(), 2 ); + Q_ASSERT( points.count() > 0 ); + coord = GEOSCoordSeq_create( points.count(), points[0].isMeasured() ? 4 : ( points[0].is3d() ? 3 : 2 ) ); int i; for ( i = 0; i < points.count(); i++ ) { - GEOSCoordSeq_setX( coord, i, points[i].x() ); - GEOSCoordSeq_setY( coord, i, points[i].y() ); + setGeosPoint( coord, i, points[i] ); } return coord; } @@ -605,18 +634,7 @@ exportGeosToWkb(); } - QGis::WkbType type = wkbType(); - if ( type == QGis::WKBPoint || type == QGis::WKBPoint25D || - type == QGis::WKBMultiPoint || type == QGis::WKBMultiPoint25D ) - return QGis::Point; - if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D || - type == QGis::WKBMultiLineString || type == QGis::WKBMultiLineString25D ) - return QGis::Line; - if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D || - type == QGis::WKBMultiPolygon || type == QGis::WKBMultiPolygon25D ) - return QGis::Polygon; - - return QGis::UnknownGeometry; + return QGis::geometryTypeFromWkbType( wkbType() ); } bool QgsGeometry::isMultipart() @@ -627,16 +645,13 @@ exportGeosToWkb(); } - QGis::WkbType type = wkbType(); - if ( type == QGis::WKBMultiPoint || - type == QGis::WKBMultiPoint25D || - type == QGis::WKBMultiLineString || - type == QGis::WKBMultiLineString25D || - type == QGis::WKBMultiPolygon || - type == QGis::WKBMultiPolygon25D ) - return true; + QGis::WkbType type = QGis::wkbType2d( wkbType() ); - return false; + + return + type == QGis::WKBMultiPoint || + type == QGis::WKBMultiLineString || + type == QGis::WKBMultiPolygon; } @@ -685,24 +700,20 @@ memcpy( &wkbType, ( mGeometry + 1 ), sizeof( int ) ); beforeVertex = -1; afterVertex = -1; - bool hasZValue = false; - switch ( wkbType ) + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { x = *(( double * )( mGeometry + 5 ) ); y = *(( double * )( mGeometry + 5 + sizeof( double ) ) ); - actdist = point.sqrDist( x, y ); + actdist = point.sqrDist2d( x, y ); vertexnr = 0; break; } - case QGis::WKBLineString25D: - hasZValue = true; - // fall-through - case QGis::WKBLineString: { unsigned char* ptr = mGeometry + 5; @@ -713,11 +724,11 @@ tempx = ( double* )ptr; ptr += sizeof( double ); tempy = ( double* )ptr; - if ( point.sqrDist( *tempx, *tempy ) < actdist ) + if ( point.sqrDist2d( *tempx, *tempy ) < actdist ) { x = *tempx; y = *tempy; - actdist = point.sqrDist( *tempx, *tempy ); + actdist = point.sqrDist2d( *tempx, *tempy ); vertexnr = index; if ( index == 0 )//assign the rubber band indices { @@ -736,16 +747,11 @@ afterVertex = index + 1; } } - ptr += sizeof( double ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 2 ) * sizeof( double ); } break; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int* nrings = ( int* )( mGeometry + 5 ); @@ -760,11 +766,11 @@ tempx = ( double* )ptr; ptr += sizeof( double ); tempy = ( double* )ptr; - if ( point.sqrDist( *tempx, *tempy ) < actdist ) + if ( point.sqrDist2d( *tempx, *tempy ) < actdist ) { x = *tempx; y = *tempy; - actdist = point.sqrDist( *tempx, *tempy ); + actdist = point.sqrDist2d( *tempx, *tempy ); vertexnr = vertexcounter; //assign the rubber band indices if ( index2 == 0 ) @@ -783,18 +789,13 @@ afterVertex = vertexcounter + 1; } } - ptr += sizeof( double ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); ++vertexcounter; } } break; } - case QGis::WKBMultiPoint25D: - hasZValue = true; + case QGis::WKBMultiPoint: { unsigned char* ptr = mGeometry + 5; @@ -805,23 +806,18 @@ ptr += ( 1 + sizeof( int ) ); //skip endian and point type tempx = ( double* )ptr; tempy = ( double* )( ptr + sizeof( double ) ); - if ( point.sqrDist( *tempx, *tempy ) < actdist ) + if ( point.sqrDist2d( *tempx, *tempy ) < actdist ) { x = *tempx; y = *tempy; - actdist = point.sqrDist( *tempx, *tempy ); + actdist = point.sqrDist2d( *tempx, *tempy ); vertexnr = index; } - ptr += ( 2 * sizeof( double ) ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); } break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { unsigned char* ptr = mGeometry + 5; @@ -838,12 +834,11 @@ tempx = ( double* )ptr; ptr += sizeof( double ); tempy = ( double* )ptr; - ptr += sizeof( double ); - if ( point.sqrDist( *tempx, *tempy ) < actdist ) + if ( point.sqrDist2d( *tempx, *tempy ) < actdist ) { x = *tempx; y = *tempy; - actdist = point.sqrDist( *tempx, *tempy ); + actdist = point.sqrDist2d( *tempx, *tempy ); vertexnr = vertexcounter; if ( index2 == 0 )//assign the rubber band indices @@ -863,17 +858,14 @@ afterVertex = vertexnr + 1; } } - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + + ptr += ( nCoordNum - 1 ) * sizeof( double ); ++vertexcounter; } } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { unsigned char* ptr = mGeometry + 5; @@ -895,11 +887,11 @@ tempx = ( double* )ptr; ptr += sizeof( double ); tempy = ( double* )ptr; - if ( point.sqrDist( *tempx, *tempy ) < actdist ) + if ( point.sqrDist2d( *tempx, *tempy ) < actdist ) { x = *tempx; y = *tempy; - actdist = point.sqrDist( *tempx, *tempy ); + actdist = point.sqrDist2d( *tempx, *tempy ); vertexnr = vertexcounter; //assign the rubber band indices @@ -919,11 +911,7 @@ afterVertex = vertexcounter + 1; } } - ptr += sizeof( double ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); ++vertexcounter; } } @@ -959,18 +947,18 @@ int vertexcounter = 0; QGis::WkbType wkbType; - bool hasZValue = false; - memcpy( &wkbType, ( mGeometry + 1 ), sizeof( int ) ); - switch ( wkbType ) + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + switch ( QGis::wkbType2d( wkbType ) ) { case QGis::WKBPoint: { // NOOP - Points do not have adjacent verticies break; } - case QGis::WKBLineString25D: + case QGis::WKBLineString: { unsigned char* ptr = mGeometry + 5; @@ -1000,8 +988,7 @@ break; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int* nrings = ( int* )( mGeometry + 5 ); @@ -1017,12 +1004,7 @@ for ( int index1 = 0; index1 < *npoints; ++index1 ) { - ptr += sizeof( double ); - ptr += sizeof( double ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); if ( vertexcounter == atVertex ) { if ( index1 == 0 ) @@ -1047,15 +1029,13 @@ } break; } - case QGis::WKBMultiPoint25D: + case QGis::WKBMultiPoint: { // NOOP - Points do not have adjacent verticies break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; case QGis::WKBMultiLineString: { unsigned char* ptr = mGeometry + 5; @@ -1071,12 +1051,7 @@ for ( int index1 = 0; index1 < *npoints; ++index1 ) { - ptr += sizeof( double ); - ptr += sizeof( double ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); if ( vertexcounter == atVertex ) { @@ -1103,8 +1078,7 @@ } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { unsigned char* ptr = mGeometry + 5; @@ -1126,12 +1100,8 @@ for ( int index2 = 0; index2 < *npoints; ++index2 ) { - ptr += sizeof( double ); - ptr += sizeof( double ); - if ( hasZValue ) //skip z-coordinate for 25D geometries - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); + if ( vertexcounter == atVertex ) { // Found the vertex of the linear-ring of the polygon we were looking for. @@ -1168,9 +1138,9 @@ -bool QgsGeometry::insertVertex( double x, double y, +bool QgsGeometry::insertVertex( const QgsPoint &p, int beforeVertex, - const GEOSCoordSequence* old_sequence, + const GEOSCoordSequence *old_sequence, GEOSCoordSequence** new_sequence ) { @@ -1184,7 +1154,10 @@ unsigned int numPoints; GEOSCoordSeq_getSize( old_sequence, &numPoints ); - *new_sequence = GEOSCoordSeq_create( numPoints + 1, 2 ); + unsigned int numDims; + GEOSCoordSeq_getDimensions( old_sequence, &numDims ); + + *new_sequence = GEOSCoordSeq_create( numPoints + 1, numDims ); if ( !*new_sequence ) return false; @@ -1194,34 +1167,79 @@ // Do we insert the new vertex here? if ( beforeVertex == static_cast( i ) ) { - GEOSCoordSeq_setX( *new_sequence, j, x ); - GEOSCoordSeq_setY( *new_sequence, j, y ); + setGeosPoint( *new_sequence, j, p ); j++; inserted = true; } - double aX, aY; - GEOSCoordSeq_getX( old_sequence, i, &aX ); - GEOSCoordSeq_getY( old_sequence, i, &aY ); - - GEOSCoordSeq_setX( *new_sequence, j, aX ); - GEOSCoordSeq_setY( *new_sequence, j, aY ); + QgsPoint aP; + getGeosPoint( old_sequence, i, aP ); + setGeosPoint( *new_sequence, j, aP ); } if ( !inserted ) { // The beforeVertex is greater than the actual number of vertices // in the geometry - append it. - GEOSCoordSeq_setX( *new_sequence, numPoints, x ); - GEOSCoordSeq_setY( *new_sequence, numPoints, y ); + setGeosPoint( *new_sequence, numPoints, p ); } // TODO: Check that the sequence is still simple, e.g. with GEOS_GEOM::Geometry->isSimple() return inserted; } -bool QgsGeometry::moveVertex( double x, double y, int atVertex ) +static void setWkbPoint( QGis::WkbType wkbType, unsigned char *&ptr, const QgsPoint &p ) { + double v; + + v = p.x(); + memcpy( ptr, &v, sizeof( double ) ); + ptr += sizeof( double ); + + v = p.y(); + memcpy( ptr, &v, sizeof( double ) ); + ptr += sizeof( double ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) + { + if( p.is3d() ) + { + v = p.z(); + memcpy( ptr, &v, sizeof( double ) ); + } + ptr += sizeof( double ); + } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + if( p.isMeasured() ) + { + v = p.m(); + memcpy( ptr, &v, sizeof( double ) ); + } + + ptr += sizeof( double ); + } +} + +static void getWkbPoint( QGis::WkbType wkbType, unsigned char *&ptr, QgsPoint &p ) +{ + p.setX( *( double * )ptr ); ptr += sizeof( double ); + p.setY( *( double * )ptr ); ptr += sizeof( double ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) + { + p.setZ( *( double * )ptr ); ptr += sizeof( double ); + } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + p.setM( *( double * )ptr ); ptr += sizeof( double ); + } +} + +bool QgsGeometry::moveVertex( const QgsPoint &p, int atVertex ) +{ int vertexnr = atVertex; // TODO: implement with GEOS @@ -1237,21 +1255,19 @@ } QGis::WkbType wkbType; - bool hasZValue = false; unsigned char* ptr = mGeometry + 1; memcpy( &wkbType, ptr, sizeof( wkbType ) ); ptr += sizeof( wkbType ); - switch ( wkbType ) + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { if ( vertexnr == 0 ) { - memcpy( ptr, &x, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( ptr, &y, sizeof( double ) ); + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } @@ -1260,8 +1276,7 @@ return false; } } - case QGis::WKBMultiPoint25D: - hasZValue = true; + case QGis::WKBMultiPoint: { int* nrPoints = ( int* )ptr; @@ -1270,23 +1285,17 @@ return false; } ptr += sizeof( int ); - if ( hasZValue ) - { - ptr += ( 3 * sizeof( double ) + 1 + sizeof( int ) ) * vertexnr; - } - else - { - ptr += ( 2 * sizeof( double ) + 1 + sizeof( int ) ) * vertexnr; - } + + ptr += ( nCoordNum * sizeof( double ) + 1 + sizeof( int ) ) * vertexnr; + ptr += ( 1 + sizeof( int ) ); - memcpy( ptr, &x, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( ptr, &y, sizeof( double ) ); + + setWkbPoint( wkbType, ptr, p ); + mDirtyGeos = true; return true; } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { int* nrPoints = ( int* )ptr; @@ -1295,19 +1304,12 @@ return false; } ptr += sizeof( int ); - ptr += 2 * sizeof( double ) * vertexnr; - if ( hasZValue ) - { - ptr += sizeof( double ) * vertexnr; - } - memcpy( ptr, &x, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( ptr, &y, sizeof( double ) ); + ptr += nCoordNum * sizeof( double ) * vertexnr; + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { int* nrLines = ( int* )ptr; @@ -1321,32 +1323,22 @@ ptr += sizeof( int ); if ( vertexnr >= pointindex && vertexnr < pointindex + ( *nrPoints ) ) { - ptr += ( vertexnr - pointindex ) * 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += ( vertexnr - pointindex ) * sizeof( double ); - } - memcpy( ptr, &x, sizeof( double ) ); - memcpy( ptr + sizeof( double ), &y, sizeof( double ) ); + ptr += ( vertexnr - pointindex ) * nCoordNum * sizeof( double ); + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } pointindex += ( *nrPoints ); - ptr += 2 * sizeof( double ) * ( *nrPoints ); - if ( hasZValue ) - { - ptr += sizeof( double ) * ( *nrPoints ); - } + ptr += nCoordNum * sizeof( double ) * ( *nrPoints ); } return false; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int* nrRings = ( int* )ptr; ptr += sizeof( int ); - int* nrPoints = 0; //numer of points in a ring + int* nrPoints = 0; //number of points in a ring int pointindex = 0; for ( int ringnr = 0; ringnr < *nrRings; ++ringnr ) @@ -1355,51 +1347,26 @@ ptr += sizeof( int ); if ( vertexnr == pointindex || vertexnr == pointindex + ( *nrPoints - 1 ) )//move two points { - memcpy( ptr, &x, sizeof( double ) ); - memcpy( ptr + sizeof( double ), &y, sizeof( double ) ); - if ( hasZValue ) - { - memcpy( ptr + 3*sizeof( double )*( *nrPoints - 1 ), &x, sizeof( double ) ); - } - else - { - memcpy( ptr + 2*sizeof( double )*( *nrPoints - 1 ), &x, sizeof( double ) ); - } - if ( hasZValue ) - { - memcpy( ptr + sizeof( double ) + 3*sizeof( double )*( *nrPoints - 1 ), &y, sizeof( double ) ); - } - else - { - memcpy( ptr + sizeof( double ) + 2*sizeof( double )*( *nrPoints - 1 ), &y, sizeof( double ) ); - } + setWkbPoint( wkbType, ptr, p ); + ptr += ( *nrPoints - 2 ) * nCoordNum * sizeof( double ); + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } else if ( vertexnr > pointindex && vertexnr < pointindex + ( *nrPoints - 1 ) )//move only one point { - ptr += 2 * sizeof( double ) * ( vertexnr - pointindex ); - if ( hasZValue ) - { - ptr += sizeof( double ) * ( vertexnr - pointindex ); - } - memcpy( ptr, &x, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( ptr, &y, sizeof( double ) ); + ptr += ( vertexnr - pointindex ) * nCoordNum * sizeof( double ); + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } - ptr += 2 * sizeof( double ) * ( *nrPoints ); - if ( hasZValue ) - { - ptr += sizeof( double ) * ( *nrPoints ); - } + ptr += nCoordNum * sizeof( double ) * *nrPoints; pointindex += *nrPoints; } + return false; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { int* nrPolygons = ( int* )ptr; @@ -1419,45 +1386,20 @@ ptr += sizeof( int ); if ( vertexnr == pointindex || vertexnr == pointindex + ( *nrPoints - 1 ) )//move two points { - memcpy( ptr, &x, sizeof( double ) ); - memcpy( ptr + sizeof( double ), &y, sizeof( double ) ); - if ( hasZValue ) - { - memcpy( ptr + 3*sizeof( double )*( *nrPoints - 1 ), &x, sizeof( double ) ); - } - else - { - memcpy( ptr + 2*sizeof( double )*( *nrPoints - 1 ), &x, sizeof( double ) ); - } - if ( hasZValue ) - { - memcpy( ptr + sizeof( double ) + 3*sizeof( double )*( *nrPoints - 1 ), &y, sizeof( double ) ); - } - else - { - memcpy( ptr + sizeof( double ) + 2*sizeof( double )*( *nrPoints - 1 ), &y, sizeof( double ) ); - } + setWkbPoint( wkbType, ptr, p ); + ptr += ( *nrPoints - 2 ) * nCoordNum * sizeof( double ); + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } else if ( vertexnr > pointindex && vertexnr < pointindex + ( *nrPoints - 1 ) )//move only one point { - ptr += 2 * sizeof( double ) * ( vertexnr - pointindex ); - if ( hasZValue ) - { - ptr += 3 * sizeof( double ) * ( vertexnr - pointindex ); - } - memcpy( ptr, &x, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( ptr, &y, sizeof( double ) ); + ptr += ( vertexnr - pointindex ) * nCoordNum * sizeof( double ); + setWkbPoint( wkbType, ptr, p ); mDirtyGeos = true; return true; } - ptr += 2 * sizeof( double ) * ( *nrPoints ); - if ( hasZValue ) - { - ptr += sizeof( double ) * ( *nrPoints ); - } + ptr += nCoordNum * sizeof( double ) * *nrPoints; pointindex += *nrPoints; } } @@ -1490,45 +1432,31 @@ unsigned char* newbuffer; int pointindex = 0; QGis::WkbType wkbType; - bool hasZValue = false; unsigned char* ptr = mGeometry + 1; memcpy( &wkbType, ptr, sizeof( wkbType ) ); - switch ( wkbType ) - { - case QGis::WKBPoint25D: - case QGis::WKBLineString25D: - case QGis::WKBPolygon25D: - case QGis::WKBMultiPoint25D: - case QGis::WKBMultiLineString25D: - case QGis::WKBMultiPolygon25D: - newbuffer = new unsigned char[mGeometrySize-3*sizeof( double )]; - break; - default: - newbuffer = new unsigned char[mGeometrySize-2*sizeof( double )]; - } + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + newbuffer = new unsigned char[mGeometrySize-nCoordNum*sizeof( double )]; + memcpy( newbuffer, mGeometry, 1 + sizeof( int ) ); //endian and type are the same ptr += sizeof( wkbType ); unsigned char* newBufferPtr = newbuffer + 1 + sizeof( int ); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { break; //cannot remove the only point vertex } - case QGis::WKBMultiPoint25D: - hasZValue = true; + case QGis::WKBMultiPoint: { //todo break; } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { int* nPoints = ( int* )ptr; @@ -1547,27 +1475,18 @@ { memcpy( newBufferPtr, ptr, sizeof( double ) ); memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + newBufferPtr += nCoordNum * sizeof( double ); } else { success = true; } - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); ++pointindex; } break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { int* nLines = ( int* )ptr; @@ -1608,28 +1527,19 @@ { memcpy( newBufferPtr, ptr, sizeof( double ) );//x memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//y - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + newBufferPtr += nCoordNum * sizeof( double ); } else { success = true; } - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); ++pointindex; } } break; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int* nRings = ( int* )ptr; @@ -1666,11 +1576,7 @@ { memcpy( newBufferPtr, ptr, sizeof( double ) );//x memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//y - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + newBufferPtr += nCoordNum * sizeof( double ); } else { @@ -1686,18 +1592,13 @@ } success = true; } - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); ++pointindex; } } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { int* nPolys = ( int* )ptr; @@ -1744,11 +1645,7 @@ { memcpy( newBufferPtr, ptr, sizeof( double ) );//x memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//y - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + newBufferPtr += nCoordNum * sizeof( double ); } else { @@ -1764,11 +1661,7 @@ } success = true; } - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); ++pointindex; } } @@ -1777,16 +1670,16 @@ } case QGis::WKBUnknown: break; + + default: + Q_ASSERT( "Should not be reached!" && 0 ); + } if ( success ) { delete [] mGeometry; mGeometry = newbuffer; - mGeometrySize -= ( 2 * sizeof( double ) ); - if ( hasZValue ) - { - mGeometrySize -= sizeof( double ); - } + mGeometrySize -= ( nCoordNum * sizeof( double ) ); mDirtyGeos = true; return true; } @@ -1797,7 +1690,7 @@ } } -bool QgsGeometry::insertVertex( double x, double y, int beforeVertex ) +bool QgsGeometry::insertVertex( const QgsPoint &p, int beforeVertex ) { int vertexnr = beforeVertex; bool success = false; @@ -1819,46 +1712,32 @@ int pointindex = 0; QGis::WkbType wkbType; - bool hasZValue = false; - unsigned char* ptr = mGeometry + 1; memcpy( &wkbType, ptr, sizeof( wkbType ) ); - switch ( wkbType ) - { - case QGis::WKBPoint25D: - case QGis::WKBLineString25D: - case QGis::WKBPolygon25D: - case QGis::WKBMultiPoint25D: - case QGis::WKBMultiLineString25D: - case QGis::WKBMultiPolygon25D: - newbuffer = new unsigned char[mGeometrySize+3*sizeof( double )]; - break; - default: - newbuffer = new unsigned char[mGeometrySize+2*sizeof( double )]; - } + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + newbuffer = new unsigned char[mGeometrySize + nCoordNum*sizeof( double )]; + memcpy( newbuffer, mGeometry, 1 + sizeof( int ) ); //endian and type are the same ptr += sizeof( wkbType ); unsigned char* newBufferPtr = newbuffer + 1 + sizeof( int ); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: - case QGis::WKBPoint://cannot insert a vertex before another one on point types + case QGis::WKBPoint: // cannot insert a vertex before another one on point types { delete newbuffer; return false; } - case QGis::WKBMultiPoint25D: - hasZValue = true; + case QGis::WKBMultiPoint: { //todo break; } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { int* nPoints = ( int* )ptr; @@ -1875,33 +1754,18 @@ { memcpy( newBufferPtr, ptr, sizeof( double ) );//x memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//x - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); + newBufferPtr += nCoordNum * sizeof( double ); ++pointindex; if ( pointindex == vertexnr ) { - memcpy( newBufferPtr, &x, sizeof( double ) ); - memcpy( newBufferPtr + sizeof( double ), &y, sizeof( double ) ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + setWkbPoint( wkbType, newBufferPtr, p ); success = true; } } break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { int* nLines = ( int* )ptr; @@ -1934,31 +1798,19 @@ { memcpy( newBufferPtr, ptr, sizeof( double ) );//x memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//y - ptr += 2 * sizeof( double ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - newBufferPtr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); + newBufferPtr += nCoordNum * sizeof( double ); ++pointindex; if ( pointindex == vertexnr ) { - memcpy( newBufferPtr, &x, sizeof( double ) ); - memcpy( newBufferPtr + sizeof( double ), &y, sizeof( double ) ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + setWkbPoint( wkbType, newBufferPtr, p ); success = true; } } } break; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int* nRings = ( int* )ptr; @@ -1986,33 +1838,19 @@ for ( int pointnr = 0; pointnr < *nPoints; ++pointnr ) { - memcpy( newBufferPtr, ptr, sizeof( double ) );//x - memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//y - ptr += 2 * sizeof( double ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - newBufferPtr += sizeof( double ); - } + memcpy( newBufferPtr, ptr, nCoordNum*sizeof( double ) ); // x+y(+z)(+m) + newBufferPtr += nCoordNum * sizeof( double ); ++pointindex; if ( pointindex == vertexnr ) { - memcpy( newBufferPtr, &x, sizeof( double ) ); - memcpy( newBufferPtr + sizeof( double ), &y, sizeof( double ) ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + setWkbPoint( wkbType, newBufferPtr, p ); success = true; } } } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { int* nPolys = ( int* )ptr; @@ -2051,25 +1889,13 @@ for ( int pointnr = 0; pointnr < *nPoints; ++pointnr ) { - memcpy( newBufferPtr, ptr, sizeof( double ) );//x - memcpy( newBufferPtr + sizeof( double ), ptr + sizeof( double ), sizeof( double ) );//y - ptr += 2 * sizeof( double ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - newBufferPtr += sizeof( double ); - } + memcpy( newBufferPtr, ptr, nCoordNum*sizeof( double ) ); + ptr += nCoordNum * sizeof( double ); + newBufferPtr += nCoordNum * sizeof( double ); ++pointindex; if ( pointindex == vertexnr ) { - memcpy( newBufferPtr, &x, sizeof( double ) ); - memcpy( newBufferPtr + sizeof( double ), &y, sizeof( double ) ); - newBufferPtr += 2 * sizeof( double ); - if ( hasZValue ) - { - newBufferPtr += sizeof( double ); - } + setWkbPoint( wkbType, newBufferPtr, p ); success = true; } } @@ -2078,19 +1904,19 @@ } break; } + case QGis::WKBUnknown: break; + + default: + Q_ASSERT( "Should not be reached!" && 0 ); } if ( success ) { delete [] mGeometry; mGeometry = newbuffer; - mGeometrySize += 2 * sizeof( double ); - if ( hasZValue ) - { - mGeometrySize += sizeof( double ); - } + mGeometrySize += nCoordNum * sizeof( double ); mDirtyGeos = true; return true; } @@ -2103,7 +1929,7 @@ QgsPoint QgsGeometry::vertexAt( int atVertex ) { - double x, y; + QgsPoint p; if ( mDirtyWkb ) { @@ -2117,30 +1943,27 @@ } QGis::WkbType wkbType; - bool hasZValue = false; unsigned char* ptr; - memcpy( &wkbType, ( mGeometry + 1 ), sizeof( int ) ); - switch ( wkbType ) + + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { if ( atVertex == 0 ) { ptr = mGeometry + 1 + sizeof( int ); - memcpy( &x, ptr, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( &y, ptr, sizeof( double ) ); - return QgsPoint( x, y ); + getWkbPoint( wkbType, ptr, p ); + return p; } else { return QgsPoint( 0, 0 ); } } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { int *nPoints; @@ -2155,21 +1978,12 @@ } // copy the vertex coordinates - if ( hasZValue ) - { - ptr = mGeometry + 9 + ( atVertex * 3 * sizeof( double ) ); - } - else - { - ptr = mGeometry + 9 + ( atVertex * 2 * sizeof( double ) ); - } - memcpy( &x, ptr, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( &y, ptr, sizeof( double ) ); - return QgsPoint( x, y ); + ptr = mGeometry + 9 + ( atVertex * nCoordNum * sizeof( double ) ); + + getWkbPoint( wkbType, ptr, p ); + return p; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int *nRings; @@ -2186,23 +2000,17 @@ { if ( pointindex == atVertex ) { - memcpy( &x, ptr, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( &y, ptr, sizeof( double ) ); - return QgsPoint( x, y ); + getWkbPoint( wkbType, ptr, p ); + return p; } - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + + ptr += nCoordNum * sizeof( double ); ++pointindex; } } return QgsPoint( 0, 0 ); } - case QGis::WKBMultiPoint25D: - hasZValue = true; + case QGis::WKBMultiPoint: { ptr = mGeometry + 1 + sizeof( int ); @@ -2211,22 +2019,15 @@ { return QgsPoint( 0, 0 ); } - if ( hasZValue ) - { - ptr += atVertex * ( 3 * sizeof( double ) + 1 + sizeof( int ) ); - } - else - { - ptr += atVertex * ( 2 * sizeof( double ) + 1 + sizeof( int ) ); - } + + ptr += atVertex * ( nCoordNum * sizeof( double ) + 1 + sizeof( int ) ); + ptr += 1 + sizeof( int ); - memcpy( &x, ptr, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( &y, ptr, sizeof( double ) ); - return QgsPoint( x, y ); + + getWkbPoint( wkbType, ptr, p ); + return p; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { ptr = mGeometry + 1 + sizeof( int ); @@ -2243,23 +2044,17 @@ { if ( pointindex == atVertex ) { - memcpy( &x, ptr, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( &y, ptr, sizeof( double ) ); - return QgsPoint( x, y ); + getWkbPoint( wkbType, ptr, p ); + return p; } - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + + ptr += nCoordNum * sizeof( double ); ++pointindex; } } return QgsPoint( 0, 0 ); } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { ptr = mGeometry + 1 + sizeof( int ); @@ -2281,22 +2076,17 @@ { if ( pointindex == atVertex ) { - memcpy( &x, ptr, sizeof( double ) ); - ptr += sizeof( double ); - memcpy( &y, ptr, sizeof( double ) ); - return QgsPoint( x, y ); + getWkbPoint( wkbType, ptr, p ); + return p; } ++pointindex; - ptr += 2 * sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += nCoordNum * sizeof( double ); } } } return QgsPoint( 0, 0 ); } + default: QgsDebugMsg( "error: mGeometry type not recognized" ); return QgsPoint( 0, 0 ); @@ -2310,7 +2100,7 @@ if ( pnt != QgsPoint( 0, 0 ) ) { QgsDebugMsg( "Exiting with distance to " + pnt.toString() ); - return point.sqrDist( pnt ); + return point.sqrDist2d( pnt ); } else { @@ -2320,7 +2110,40 @@ } } +double QgsGeometry::area() +{ + double area = -1.0; + try + { + if ( !mGeos || mDirtyGeos ) + exportWkbToGeos(); + + GEOSArea( mGeos, &area ); + + return area; + } + CATCH_GEOS( -1.0 ); + +} + +double QgsGeometry::length() +{ + double length = -1.0; + + try + { + if ( !mGeos || mDirtyGeos ) + exportWkbToGeos(); + + GEOSLength( mGeos, &length); + + return length; + } + CATCH_GEOS( -1.0 ); + +} + double QgsGeometry::closestVertexWithContext( const QgsPoint& point, int& atVertex ) { double sqrDist = std::numeric_limits::max(); @@ -2348,7 +2171,7 @@ GEOSCoordSeq_getX( sequence, i, &x ); GEOSCoordSeq_getY( sequence, i, &y ); - double testDist = point.sqrDist( x, y ); + double testDist = point.sqrDist2d( x, y ); if ( testDist < sqrDist ) { closestVertexIndex = i; @@ -2401,18 +2224,15 @@ memcpy( &wkbType, ( mGeometry + 1 ), sizeof( int ) ); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: - case QGis::WKBMultiPoint25D: case QGis::WKBMultiPoint: { // Points have no lines return -1; } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { unsigned char* ptr = mGeometry + 1 + sizeof( int ); @@ -2447,8 +2267,7 @@ beforeVertex = closestSegmentIndex; break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { unsigned char* ptr = mGeometry + 1 + sizeof( int ); @@ -2490,8 +2309,7 @@ beforeVertex = closestSegmentIndex; break; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { int index = 0; @@ -2532,8 +2350,7 @@ beforeVertex = closestSegmentIndex; break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { unsigned char* ptr = mGeometry + 1 + sizeof( int ); @@ -2581,6 +2398,7 @@ beforeVertex = closestSegmentIndex; break; } + case QGis::WKBUnknown: default: return -1; @@ -2792,7 +2610,7 @@ return 2; } - if ( wkbType() == QGis::WKBPolygon || wkbType() == QGis::WKBPolygon25D ) + if ( QGis::wkbType2d( wkbType() ) != QGis::WKBPolygon ) { if ( !convertToMultiType() ) { @@ -2801,7 +2619,7 @@ } //bail out if wkbtype is not multipolygon - if ( wkbType() != QGis::WKBMultiPolygon && wkbType() != QGis::WKBMultiPolygon25D ) + if ( QGis::wkbType2d( wkbType() ) != QGis::WKBMultiPolygon ) { return 1; } @@ -2888,33 +2706,29 @@ QGis::WkbType wkbType; memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) ); - bool hasZValue = false; int wkbPosition = 5; + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + switch ( wkbType ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { - translateVertex( wkbPosition, dx, dy, hasZValue ); + translateVertex( wkbPosition, dx, dy, nCoordNum ); } break; - case QGis::WKBLineString25D: - hasZValue = true; case QGis::WKBLineString: { int* npoints = ( int* )( &mGeometry[wkbPosition] ); wkbPosition += sizeof( int ); for ( int index = 0;index < *npoints;++index ) { - translateVertex( wkbPosition, dx, dy, hasZValue ); + translateVertex( wkbPosition, dx, dy, nCoordNum ); } break; } - case QGis::WKBPolygon25D: - hasZValue = true; case QGis::WKBPolygon: { int* nrings = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -2927,14 +2741,12 @@ wkbPosition += sizeof( int ); for ( int index2 = 0;index2 < *npoints;++index2 ) { - translateVertex( wkbPosition, dx, dy, hasZValue ); + translateVertex( wkbPosition, dx, dy, nCoordNum ); } } break; } - case QGis::WKBMultiPoint25D: - hasZValue = true; case QGis::WKBMultiPoint: { int* npoints = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -2942,13 +2754,11 @@ for ( int index = 0;index < *npoints;++index ) { wkbPosition += ( sizeof( int ) + 1 ); - translateVertex( wkbPosition, dx, dy, hasZValue ); + translateVertex( wkbPosition, dx, dy, nCoordNum ); } break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; case QGis::WKBMultiLineString: { int* nlines = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -2961,14 +2771,12 @@ wkbPosition += sizeof( int ); for ( int index2 = 0; index2 < *npoints; ++index2 ) { - translateVertex( wkbPosition, dx, dy, hasZValue ); + translateVertex( wkbPosition, dx, dy, nCoordNum ); } } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; case QGis::WKBMultiPolygon: { int* npolys = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -2986,7 +2794,7 @@ wkbPosition += sizeof( int ); for ( int index3 = 0;index3 < *npoints;++index3 ) { - translateVertex( wkbPosition, dx, dy, hasZValue ); + translateVertex( wkbPosition, dx, dy, nCoordNum ); } } } @@ -3014,33 +2822,29 @@ QGis::WkbType wkbType; memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) ); - bool hasZValue = false; int wkbPosition = 5; - switch ( wkbType ) + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { - transformVertex( wkbPosition, ct, hasZValue ); + transformVertex( wkbPosition, ct, nCoordNum ); } break; - case QGis::WKBLineString25D: - hasZValue = true; case QGis::WKBLineString: { int* npoints = ( int* )( &mGeometry[wkbPosition] ); wkbPosition += sizeof( int ); for ( int index = 0;index < *npoints;++index ) { - transformVertex( wkbPosition, ct, hasZValue ); + transformVertex( wkbPosition, ct, nCoordNum ); } break; } - case QGis::WKBPolygon25D: - hasZValue = true; case QGis::WKBPolygon: { int* nrings = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -3053,14 +2857,12 @@ wkbPosition += sizeof( int ); for ( int index2 = 0;index2 < *npoints;++index2 ) { - transformVertex( wkbPosition, ct, hasZValue ); + transformVertex( wkbPosition, ct, nCoordNum ); } } break; } - case QGis::WKBMultiPoint25D: - hasZValue = true; case QGis::WKBMultiPoint: { int* npoints = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -3068,13 +2870,11 @@ for ( int index = 0;index < *npoints;++index ) { wkbPosition += ( sizeof( int ) + 1 ); - transformVertex( wkbPosition, ct, hasZValue ); + transformVertex( wkbPosition, ct, nCoordNum ); } break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; case QGis::WKBMultiLineString: { int* nlines = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -3087,14 +2887,12 @@ wkbPosition += sizeof( int ); for ( int index2 = 0; index2 < *npoints; ++index2 ) { - transformVertex( wkbPosition, ct, hasZValue ); + transformVertex( wkbPosition, ct, nCoordNum ); } } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; case QGis::WKBMultiPolygon: { int* npolys = ( int* )( &( mGeometry[wkbPosition] ) ); @@ -3112,7 +2910,7 @@ wkbPosition += sizeof( int ); for ( int index3 = 0;index3 < *npoints;++index3 ) { - transformVertex( wkbPosition, ct, hasZValue ); + transformVertex( wkbPosition, ct, nCoordNum ); } } } @@ -3277,7 +3075,6 @@ char lsb; QgsPoint pt; QGis::WkbType wkbType; - bool hasZValue = false; // TODO: implement with GEOS if ( mDirtyWkb ) @@ -3293,9 +3090,11 @@ // consider endian when fetching feature type //wkbType = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4]; //MH: Does not work for 25D geometries memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) ); - switch ( wkbType ) + + int nCoordNum = QGis::wkbTypeCoordNum( wkbType ); + + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: x = ( double * )( mGeometry + 5 ); y = ( double * )( mGeometry + 5 + sizeof( double ) ); @@ -3316,8 +3115,7 @@ ymax = *y; } break; - case QGis::WKBMultiPoint25D: - hasZValue = true; + case QGis::WKBMultiPoint: { ptr = mGeometry + 1 + sizeof( int ); @@ -3329,11 +3127,8 @@ x = ( double * ) ptr; ptr += sizeof( double ); y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); + if ( *x < xmin ) { xmin = *x; @@ -3353,8 +3148,7 @@ } break; } - case QGis::WKBLineString25D: - hasZValue = true; + case QGis::WKBLineString: { // get number of points in the line @@ -3366,11 +3160,8 @@ x = ( double * ) ptr; ptr += sizeof( double ); y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); + if ( *x < xmin ) { xmin = *x; @@ -3390,8 +3181,7 @@ } break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; + case QGis::WKBMultiLineString: { numLineStrings = ( int )( mGeometry[5] ); @@ -3408,11 +3198,8 @@ x = ( double * ) ptr; ptr += sizeof( double ); y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); + if ( *x < xmin ) { xmin = *x; @@ -3433,8 +3220,7 @@ } break; } - case QGis::WKBPolygon25D: - hasZValue = true; + case QGis::WKBPolygon: { // get number of rings in the polygon @@ -3451,11 +3237,8 @@ x = ( double * ) ptr; ptr += sizeof( double ); y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); + if ( *x < xmin ) { xmin = *x; @@ -3476,8 +3259,7 @@ } break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; + case QGis::WKBMultiPolygon: { // get the number of polygons @@ -3503,11 +3285,8 @@ x = ( double * ) ptr; ptr += sizeof( double ); y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) - { - ptr += sizeof( double ); - } + ptr += ( nCoordNum - 1 ) * sizeof( double ); + if ( *x < xmin ) { xmin = *x; @@ -3616,8 +3395,6 @@ } QGis::WkbType wkbType; - bool hasZValue = false; - double *x, *y; QString mWkt; // TODO: rename @@ -3625,23 +3402,37 @@ //wkbType = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4]; memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) ); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { - mWkt += "POINT("; - x = ( double * )( mGeometry + 5 ); - mWkt += QString::number( *x, 'f', 6 ); + double *p = ( double * )( mGeometry + 5 ); + + if ( !QGis::wkbTypeHasZValue( wkbType ) && QGis::wkbTypeHasMValue( wkbType ) ) + mWkt += "POINT("; + else + mWkt += "POINTM("; + + mWkt += QString::number( *p++, 'f', 6 ); mWkt += " "; - y = ( double * )( mGeometry + 5 + sizeof( double ) ); - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *p++, 'f', 6 ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + mWkt += ")"; return mWkt; } - case QGis::WKBLineString25D: - hasZValue = true; case QGis::WKBLineString: { QgsDebugMsg( "LINESTRING found" ); @@ -3649,7 +3440,11 @@ int *nPoints; int idx; - mWkt += "LINESTRING("; + if ( !QGis::wkbTypeHasZValue( wkbType ) && QGis::wkbTypeHasMValue( wkbType ) ) + mWkt += "LINESTRING("; + else + mWkt += "LINESTRINGM("; + // get number of points in the line ptr = mGeometry + 5; nPoints = ( int * ) ptr; @@ -3660,24 +3455,31 @@ { mWkt += ", "; } - x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); + + double *p = ( double * )ptr; + mWkt += QString::number( *p++, 'f', 6 ); mWkt += " "; - ptr += sizeof( double ); - y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); - ptr += sizeof( double ); - if ( hasZValue ) + mWkt += QString::number( *p++, 'f', 6 ); + + + if ( QGis::wkbTypeHasZValue( wkbType ) ) { - ptr += sizeof( double ); + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + + ptr = ( unsigned char * )p; } mWkt += ")"; return mWkt; } - case QGis::WKBPolygon25D: - hasZValue = true; case QGis::WKBPolygon: { QgsDebugMsg( "POLYGON found" ); @@ -3685,7 +3487,11 @@ int idx, jdx; int *numRings, *nPoints; - mWkt += "POLYGON("; + if ( !QGis::wkbTypeHasZValue( wkbType ) && QGis::wkbTypeHasMValue( wkbType ) ) + mWkt += "POLYGON("; + else + mWkt += "POLYGONM("; + // get number of rings in the polygon numRings = ( int * )( mGeometry + 1 + sizeof( int ) ); if ( !( *numRings ) ) // sanity check for zero rings in polygon @@ -3715,17 +3521,25 @@ { mWkt += ","; } - x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); + + double *p = ( double * )ptr; + mWkt += QString::number( *p++, 'f', 6 ); mWkt += " "; - ptr += sizeof( double ); - y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); - ptr += sizeof( double ); - if ( hasZValue ) + mWkt += QString::number( *p++, 'f', 6 ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) { - ptr += sizeof( double ); + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + + ptr = ( unsigned char * )p; } mWkt += ")"; } @@ -3735,15 +3549,17 @@ return mWkt; } - case QGis::WKBMultiPoint25D: - hasZValue = true; case QGis::WKBMultiPoint: { unsigned char *ptr; int idx; int *nPoints; - mWkt += "MULTIPOINT("; + if ( !QGis::wkbTypeHasZValue( wkbType ) && QGis::wkbTypeHasMValue( wkbType ) ) + mWkt += "MULTIPOLYGON("; + else + mWkt += "MULTIPOLYGONM("; + nPoints = ( int* )( mGeometry + 5 ); ptr = mGeometry + 5 + sizeof( int ); for ( idx = 0;idx < *nPoints;++idx ) @@ -3753,24 +3569,31 @@ { mWkt += ", "; } - x = ( double * )( ptr ); - mWkt += QString::number( *x, 'f', 6 ); + + double *p = ( double * )ptr; + + mWkt += QString::number( *p++, 'f', 6 ); mWkt += " "; - ptr += sizeof( double ); - y = ( double * )( ptr ); - mWkt += QString::number( *y, 'f', 6 ); - ptr += sizeof( double ); - if ( hasZValue ) + mWkt += QString::number( *p++, 'f', 6 ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) { - ptr += sizeof( double ); + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + + ptr = ( unsigned char * )p; } mWkt += ")"; return mWkt; } - case QGis::WKBMultiLineString25D: - hasZValue = true; case QGis::WKBMultiLineString: { QgsDebugMsg( "MULTILINESTRING found" ); @@ -3778,7 +3601,11 @@ int idx, jdx, numLineStrings; int *nPoints; - mWkt += "MULTILINESTRING("; + if ( !QGis::wkbTypeHasZValue( wkbType ) && QGis::wkbTypeHasMValue( wkbType ) ) + mWkt += "MULTILINESTRING("; + else + mWkt += "MULTILINESTRINGM("; + numLineStrings = ( int )( mGeometry[5] ); ptr = mGeometry + 9; for ( jdx = 0; jdx < numLineStrings; jdx++ ) @@ -3797,17 +3624,26 @@ { mWkt += ", "; } - x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); - ptr += sizeof( double ); + + double *p = ( double * )ptr; + + mWkt += QString::number( *p++, 'f', 6 ); mWkt += " "; - y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); - ptr += sizeof( double ); - if ( hasZValue ) + mWkt += QString::number( *p++, 'f', 6 ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) { - ptr += sizeof( double ); + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + + ptr = ( unsigned char * )p; } mWkt += ")"; } @@ -3815,8 +3651,6 @@ return mWkt; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; case QGis::WKBMultiPolygon: { QgsDebugMsg( "MULTIPOLYGON found" ); @@ -3824,7 +3658,11 @@ int idx, jdx, kdx; int *numPolygons, *numRings, *nPoints; - mWkt += "MULTIPOLYGON("; + if ( !QGis::wkbTypeHasZValue( wkbType ) && QGis::wkbTypeHasMValue( wkbType ) ) + mWkt += "MULTIPOLYGON("; + else + mWkt += "MULTIPOLYGONM("; + ptr = mGeometry + 5; numPolygons = ( int * ) ptr; ptr = mGeometry + 9; @@ -3853,17 +3691,26 @@ { mWkt += ","; } - x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); - ptr += sizeof( double ); + + double *p = ( double * )ptr; + + mWkt += QString::number( *p++, 'f', 6 ); mWkt += " "; - y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); - ptr += sizeof( double ); - if ( hasZValue ) + mWkt += QString::number( *p++, 'f', 6 ); + + if ( QGis::wkbTypeHasZValue( wkbType ) ) { - ptr += sizeof( double ); + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); } + + if ( QGis::wkbTypeHasMValue( wkbType ) ) + { + mWkt += " "; + mWkt += QString::number( *p++, 'f', 6 ); + } + + ptr = ( unsigned char * )p; } mWkt += ")"; } @@ -3913,16 +3760,14 @@ char lsb; QgsPoint pt; QGis::WkbType wkbtype; - bool hasZValue = false; //wkbtype = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4]; memcpy( &wkbtype, &( mGeometry[1] ), sizeof( int ) ); try { - switch ( wkbtype ) + switch ( QGis::wkbType2d( wkbtype ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { x = ( double * )( mGeometry + 5 ); @@ -3933,8 +3778,6 @@ break; } - case QGis::WKBMultiPoint25D: - hasZValue = true; case QGis::WKBMultiPoint: { QVector points; @@ -3945,23 +3788,32 @@ for ( idx = 0; idx < *nPoints; idx++ ) { ptr += ( 1 + sizeof( int ) ); - x = ( double * ) ptr; - ptr += sizeof( double ); - y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) + + double *p = ( double * ) ptr; + QgsPoint pt; + + pt.setX( *p++ ); + pt.setY( *p++ ); + + if ( QGis::wkbTypeHasZValue( wkbtype ) ) { - ptr += sizeof( double ); + pt.setZ( *p++ ); } - points << createGeosPoint( QgsPoint( *x, *y ) ); + + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + points << createGeosPoint( pt ); + + ptr = ( unsigned char * ) p; } mGeos = createGeosCollection( GEOS_MULTIPOINT, points ); mDirtyGeos = FALSE; break; } - case QGis::WKBLineString25D: - hasZValue = true; case QGis::WKBLineString: { QgsDebugMsg( "Linestring found" ); @@ -3973,24 +3825,32 @@ ptr = mGeometry + 1 + 2 * sizeof( int ); for ( idx = 0; idx < *nPoints; idx++ ) { - x = ( double * ) ptr; - ptr += sizeof( double ); - y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) + double *p = ( double * ) ptr; + + QgsPoint pt; + + pt.setX( *p++ ); + pt.setY( *p++ ); + + if ( QGis::wkbTypeHasZValue( wkbtype ) ) { - ptr += sizeof( double ); + pt.setZ( *p++ ); } - sequence << QgsPoint( *x, *y ); + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + sequence << pt; + + ptr = ( unsigned char * ) p; } mDirtyGeos = FALSE; mGeos = createGeosLineString( sequence ); break; } - case QGis::WKBMultiLineString25D: - hasZValue = true; case QGis::WKBMultiLineString: { QVector lines; @@ -4007,15 +3867,26 @@ ptr += sizeof( int ); for ( idx = 0; idx < *nPoints; idx++ ) { - x = ( double * ) ptr; - ptr += sizeof( double ); - y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) + double *p = ( double * ) ptr; + + QgsPoint pt; + + pt.setX( *p++ ); + pt.setY( *p++ ); + + if ( QGis::wkbTypeHasZValue( wkbtype ) ) { - ptr += sizeof( double ); + pt.setZ( *p++ ); } - sequence << QgsPoint( *x, *y ); + + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + sequence << pt; + + ptr = ( unsigned char * ) p; } lines << createGeosLineString( sequence ); } @@ -4024,8 +3895,6 @@ break; } - case QGis::WKBPolygon25D: - hasZValue = true; case QGis::WKBPolygon: { QgsDebugMsg( "Polygon found" ); @@ -4048,15 +3917,26 @@ for ( jdx = 0; jdx < *nPoints; jdx++ ) { // add points to a point array for drawing the polygon - x = ( double * ) ptr; - ptr += sizeof( double ); - y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) + double *p = ( double * ) ptr; + + QgsPoint pt; + + pt.setX( *p++ ); + pt.setY( *p++ ); + + if ( QGis::wkbTypeHasZValue( wkbtype ) ) { - ptr += sizeof( double ); + pt.setZ( *p++ ); } - sequence << QgsPoint( *x, *y ); + + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + sequence << pt; + + ptr = ( unsigned char * ) p; } rings << createGeosLinearRing( sequence ); @@ -4066,8 +3946,6 @@ break; } - case QGis::WKBMultiPolygon25D: - hasZValue = true; case QGis::WKBMultiPolygon: { QgsDebugMsg( "Multipolygon found" ); @@ -4100,15 +3978,26 @@ for ( jdx = 0; jdx < *nPoints; jdx++ ) { // add points to a point array for drawing the polygon - x = ( double * ) ptr; - ptr += sizeof( double ); - y = ( double * ) ptr; - ptr += sizeof( double ); - if ( hasZValue ) + double *p = ( double * ) ptr; + + QgsPoint pt; + + pt.setX( *p++ ); + pt.setY( *p++ ); + + if ( QGis::wkbTypeHasZValue( wkbtype ) ) { - ptr += sizeof( double ); + pt.setZ( *p++ ); } - sequence << QgsPoint( *x, *y ); + + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + sequence << pt; + + ptr = ( unsigned char * ) p; } rings << createGeosLinearRing( sequence ); @@ -4558,7 +4447,7 @@ minDistPoint.setY( *y1 + t * ( *y2 - *y1 ) ); } - return ( minDistPoint.sqrDist( point ) ); + return ( minDistPoint.sqrDist2d( point ) ); #if 0 double d; @@ -4629,9 +4518,7 @@ QGis::WkbType geomType = wkbType(); - if ( geomType == QGis::WKBMultiPoint || geomType == QGis::WKBMultiPoint25D || - geomType == QGis::WKBMultiLineString || geomType == QGis::WKBMultiLineString25D || - geomType == QGis::WKBMultiPolygon || geomType == QGis::WKBMultiPolygon25D || geomType == QGis::WKBUnknown ) + if ( QGis::wkbTypeIsMulti( wkbType() ) || geomType == QGis::WKBUnknown ) { return false; //no need to convert } @@ -4653,21 +4540,42 @@ case QGis::WKBPoint: newMultiType = QGis::WKBMultiPoint; break; - case QGis::WKBPoint25D: - newMultiType = QGis::WKBMultiPoint25D; + case QGis::WKBPointZ: + newMultiType = QGis::WKBMultiPointZ; break; + case QGis::WKBPointM: + newMultiType = QGis::WKBMultiPointM; + break; + case QGis::WKBPointZM: + newMultiType = QGis::WKBMultiPointZM; + break; + case QGis::WKBLineString: newMultiType = QGis::WKBMultiLineString; break; - case QGis::WKBLineString25D: - newMultiType = QGis::WKBMultiLineString25D; + case QGis::WKBLineStringZ: + newMultiType = QGis::WKBMultiLineStringZ; break; + case QGis::WKBLineStringM: + newMultiType = QGis::WKBMultiLineStringM; + break; + case QGis::WKBLineStringZM: + newMultiType = QGis::WKBMultiLineStringZM; + break; + case QGis::WKBPolygon: newMultiType = QGis::WKBMultiPolygon; break; - case QGis::WKBPolygon25D: - newMultiType = QGis::WKBMultiPolygon25D; + case QGis::WKBPolygonZ: + newMultiType = QGis::WKBMultiPolygonZ; break; + case QGis::WKBPolygonM: + newMultiType = QGis::WKBMultiPolygonM; + break; + case QGis::WKBPolygonZM: + newMultiType = QGis::WKBMultiPolygonZM; + break; + default: delete newGeometry; return false; @@ -4690,51 +4598,24 @@ return true; } -void QgsGeometry::translateVertex( int& wkbPosition, double dx, double dy, bool hasZValue ) +void QgsGeometry::translateVertex( int& wkbPosition, double dx, double dy, int nCoordNum ) { - double x, y, translated_x, translated_y; + double *c = ( double * ) & mGeometry[wkbPosition]; - //x-coordinate - x = *(( double * )( &( mGeometry[wkbPosition] ) ) ); - translated_x = x + dx; - memcpy( &( mGeometry[wkbPosition] ), &translated_x, sizeof( double ) ); - wkbPosition += sizeof( double ); + c[0] += dx; + c[1] += dy; - //y-coordinate - y = *(( double * )( &( mGeometry[wkbPosition] ) ) ); - translated_y = y + dy; - memcpy( &( mGeometry[wkbPosition] ), &translated_y, sizeof( double ) ); - wkbPosition += sizeof( double ); - - if ( hasZValue ) - { - wkbPosition += sizeof( double ); - } + wkbPosition += nCoordNum * sizeof( double ); } -void QgsGeometry::transformVertex( int& wkbPosition, QgsCoordinateTransform& ct, bool hasZValue ) +void QgsGeometry::transformVertex( int& wkbPosition, QgsCoordinateTransform& ct, int nCoordNum ) { - double x, y, z; + double *p = ( double * ) (mGeometry + wkbPosition); + double z = 0.0; // Ignore Z for now. + ct.transformInPlace( *p, *(p+1), z ); - x = *(( double * )( &( mGeometry[wkbPosition] ) ) ); - y = *(( double * )( &( mGeometry[wkbPosition + sizeof( double )] ) ) ); - z = 0.0; // Ignore Z for now. - - ct.transformInPlace( x, y, z ); - - // new x-coordinate - memcpy( &( mGeometry[wkbPosition] ), &x, sizeof( double ) ); - wkbPosition += sizeof( double ); - - // new y-coordinate - memcpy( &( mGeometry[wkbPosition] ), &y, sizeof( double ) ); - wkbPosition += sizeof( double ); - - if ( hasZValue ) - { - wkbPosition += sizeof( double ); - } + wkbPosition += sizeof( double ) * nCoordNum; } int QgsGeometry::splitLinearGeometry( GEOSGeometry *splitLine, QList& newGeometries ) @@ -5102,23 +4983,32 @@ return 0; } -QgsPoint QgsGeometry::asPoint( unsigned char*& ptr, bool hasZValue ) +QgsPoint QgsGeometry::asPoint( unsigned char*& ptr, QGis::WkbType wkbtype ) { - ptr += 5; - double* x = ( double * )( ptr ); - double* y = ( double * )( ptr + sizeof( double ) ); - ptr += 2 * sizeof( double ); + QgsPoint pt; + double *p = ( double * ) (ptr + 5); - if ( hasZValue ) - ptr += sizeof( double ); + pt.setX( *p++ ); + pt.setY( *p++ ); - return QgsPoint( *x, *y ); + if ( QGis::wkbTypeHasZValue( wkbtype ) ) + { + pt.setZ( *p++ ); + } + + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + ptr = ( unsigned char * ) p; + + return pt; } -QgsPolyline QgsGeometry::asPolyline( unsigned char*& ptr, bool hasZValue ) +QgsPolyline QgsGeometry::asPolyline( unsigned char*& ptr, QGis::WkbType wkbtype ) { - double x, y; ptr += 5; unsigned int nPoints = *(( int* )ptr ); ptr += 4; @@ -5128,25 +5018,33 @@ // Extract the points from the WKB format into the x and y vectors. for ( uint i = 0; i < nPoints; ++i ) { - x = *(( double * ) ptr ); - y = *(( double * )( ptr + sizeof( double ) ) ); + QgsPoint pt; + double *p = ( double * ) ptr; - ptr += 2 * sizeof( double ); + pt.setX( *p++ ); + pt.setY( *p++ ); - line[i] = QgsPoint( x, y ); + if ( QGis::wkbTypeHasZValue( wkbtype ) ) + { + pt.setZ( *p++ ); + } - if ( hasZValue ) // ignore Z value - ptr += sizeof( double ); + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + ptr = ( unsigned char * ) p; + + line[i] = pt; } return line; } -QgsPolygon QgsGeometry::asPolygon( unsigned char*& ptr, bool hasZValue ) +QgsPolygon QgsGeometry::asPolygon( unsigned char*& ptr, QGis::WkbType wkbtype ) { - double x, y; - ptr += 5; // get number of rings in the polygon @@ -5167,15 +5065,25 @@ for ( uint jdx = 0; jdx < nPoints; jdx++ ) { - x = *(( double * ) ptr ); - y = *(( double * )( ptr + sizeof( double ) ) ); + QgsPoint pt; + double *p = ( double * ) ptr; - ptr += 2 * sizeof( double ); + pt.setX( *p++ ); + pt.setY( *p++ ); - if ( hasZValue ) - ptr += sizeof( double ); + if ( QGis::wkbTypeHasZValue( wkbtype ) ) + { + pt.setZ( *p++ ); + } - ring[jdx] = QgsPoint( x, y ); + if ( QGis::wkbTypeHasMValue( wkbtype ) ) + { + pt.setM( *p++ ); + } + + ptr = ( unsigned char * ) p; + + ring[jdx] = pt; } rings[idx] = ring; @@ -5188,41 +5096,39 @@ QgsPoint QgsGeometry::asPoint() { QGis::WkbType type = wkbType(); - if ( type != QGis::WKBPoint && type != QGis::WKBPoint25D ) + if ( QGis::wkbType2d( type ) != QGis::WKBPoint ) return QgsPoint( 0, 0 ); unsigned char* ptr = mGeometry; - return asPoint( ptr, type == QGis::WKBPoint25D ); + return asPoint( ptr, type ); } QgsPolyline QgsGeometry::asPolyline() { QGis::WkbType type = wkbType(); - if ( type != QGis::WKBLineString && type != QGis::WKBLineString25D ) + if ( QGis::wkbType2d( type ) != QGis::WKBLineString ) return QgsPolyline(); unsigned char *ptr = mGeometry; - return asPolyline( ptr, type == QGis::WKBLineString25D ); + return asPolyline( ptr, type ); } QgsPolygon QgsGeometry::asPolygon() { QGis::WkbType type = wkbType(); - if ( type != QGis::WKBPolygon && type != QGis::WKBPolygon25D ) + if ( QGis::wkbType2d( type ) != QGis::WKBPolygon ) return QgsPolygon(); unsigned char *ptr = mGeometry; - return asPolygon( ptr, type == QGis::WKBPolygon25D ); + return asPolygon( ptr, type ); } QgsMultiPoint QgsGeometry::asMultiPoint() { QGis::WkbType type = wkbType(); - if ( type != QGis::WKBMultiPoint && type != QGis::WKBMultiPoint25D ) + if ( QGis::wkbType2d( type ) != QGis::WKBMultiPoint ) return QgsMultiPoint(); - bool hasZValue = ( type == QGis::WKBMultiPoint25D ); - unsigned char* ptr = mGeometry + 5; unsigned int nPoints = *(( int* )ptr ); ptr += 4; @@ -5230,7 +5136,7 @@ QgsMultiPoint points( nPoints ); for ( uint i = 0; i < nPoints; i++ ) { - points[i] = asPoint( ptr, hasZValue ); + points[i] = asPoint( ptr, type ); } return points; @@ -5239,11 +5145,9 @@ QgsMultiPolyline QgsGeometry::asMultiPolyline() { QGis::WkbType type = wkbType(); - if ( type != QGis::WKBMultiLineString && type != QGis::WKBMultiLineString25D ) + if ( QGis::wkbType2d( type ) != QGis::WKBMultiLineString ) return QgsMultiPolyline(); - bool hasZValue = ( type == QGis::WKBMultiLineString25D ); - unsigned char* ptr = mGeometry + 5; unsigned int numLineStrings = *(( int* )ptr ); ptr += 4; @@ -5252,7 +5156,7 @@ for ( uint i = 0; i < numLineStrings; i++ ) { - lines[i] = asPolyline( ptr, hasZValue ); + lines[i] = asPolyline( ptr, type ); } return lines; @@ -5261,11 +5165,9 @@ QgsMultiPolygon QgsGeometry::asMultiPolygon() { QGis::WkbType type = wkbType(); - if ( type != QGis::WKBMultiPolygon && type != QGis::WKBMultiPolygon25D ) + if ( QGis::wkbType2d( type ) != QGis::WKBMultiPolygon ) return QgsMultiPolygon(); - bool hasZValue = ( type == QGis::WKBMultiPolygon25D ); - unsigned char* ptr = mGeometry + 5; unsigned int numPolygons = *(( int* )ptr ); ptr += 4; @@ -5274,7 +5176,7 @@ for ( uint i = 0; i < numPolygons; i++ ) { - polygons[i] = asPolygon( ptr, hasZValue ); + polygons[i] = asPolygon( ptr, type ); } return polygons; @@ -5443,3 +5345,4 @@ } CATCH_GEOS( 0 ) } + Index: src/core/qgspoint.h =================================================================== --- src/core/qgspoint.h (revision 9915) +++ src/core/qgspoint.h (working copy) @@ -21,6 +21,12 @@ #include +#include +#ifdef _MSC_VER +#include +#define isnan(f) _isnan(f) +#endif +#include #include /** \ingroup core @@ -32,6 +38,7 @@ public: /// Default constructor QgsPoint() + : m_x( 0.0 ), m_y( 0.0 ), m_z( std::numeric_limits::quiet_NaN() ), m_m( std::numeric_limits::quiet_NaN() ) {} /*! Create a point from another point */ @@ -40,9 +47,11 @@ /*! Create a point from x,y coordinates * @param x x coordinate * @param y y coordinate + * @param z z coordinate + * @param m m value */ - QgsPoint( double x, double y ) - : m_x( x ), m_y( y ) + QgsPoint( double x, double y, double z = std::numeric_limits::quiet_NaN(), double m = std::numeric_limits::quiet_NaN() ) + : m_x( x ), m_y( y ), m_z( z ), m_m( m ) {} ~QgsPoint() @@ -64,11 +73,29 @@ m_y = y; } + /*! Sets the z value of the point + * @param z z coordinate + */ + void setZ( double z ) + { + m_z = z; + } + + /*! Sets the m value of the point + * @param z m value + */ + void setM( double m ) + { + m_m = m; + } + /*! Sets the x and y value of the point */ - void set( double x, double y ) + void set( double x, double y, double z = std::numeric_limits::quiet_NaN(), double m = std::numeric_limits::quiet_NaN() ) { m_x = x; m_y = y; + m_z = z; + m_m = m; } /*! Get the x value of the point @@ -87,6 +114,25 @@ return m_y; } + /*! Get the z value of the point + * @return z coordinate + */ + double z() const + { + return m_z; + } + + /*! Get the m value of the point + * @return m value + */ + double m() const + { + return m_m; + } + + bool is3d() const { return !isnan( m_z ); } + bool isMeasured() const { return !isnan( m_m ); } + //! String representation of the point (x,y) QString toString() const; @@ -100,13 +146,13 @@ QString wellKnownText() const; /**Returns the squared distance between this point and x,y*/ - double sqrDist( double x, double y ) const; + double sqrDist2d( double x, double y ) const; /**Returns the squared distance between this and other point*/ - double sqrDist( const QgsPoint& other ) const; + double sqrDist2d( const QgsPoint& other ) const; //! equality operator - bool operator==( const QgsPoint &other ); + bool operator==( const QgsPoint &other ) const; //! Inequality operator bool operator!=( const QgsPoint &other ) const; @@ -115,13 +161,13 @@ QgsPoint & operator=( const QgsPoint &other ); //! Multiply x and y by the given value - void multiply( const double& scalar ); + void multiply2d( const double& scalar ); //! Test if this point is on the segment defined by points a, b //! @return 0 if this point is not on the open ray through a and b, //! 1 if point is on open ray a, 2 if point is within line segment, //! 3 if point is on open ray b. - int onSegment( const QgsPoint& a, const QgsPoint& b ) const; + int onSegment2d( const QgsPoint& a, const QgsPoint& b ) const; private: @@ -131,18 +177,15 @@ //! y coordinate double m_y; + //! z coordinate + double m_z; + //! m value + double m_m; + }; // class QgsPOint -inline bool operator==( const QgsPoint &p1, const QgsPoint &p2 ) -{ - if (( p1.x() == p2.x() ) && ( p1.y() == p2.y() ) ) - { return true; } - else - { return false; } -} - inline std::ostream& operator << ( std::ostream& os, const QgsPoint &p ) { // Use Local8Bit for printouts @@ -150,6 +193,5 @@ return os; } - #endif //QGSPOINT_H Index: src/core/qgsvectorlayer.h =================================================================== --- src/core/qgsvectorlayer.h (revision 9915) +++ src/core/qgsvectorlayer.h (working copy) @@ -245,12 +245,14 @@ * Not meaningful for Point geometries */ bool insertVertex( double x, double y, int atFeatureId, int beforeVertex ); + bool insertVertex( const QgsPoint &p, int atFeatureId, int beforeVertex ); /** Moves the vertex at the given position number, * ring and item (first number is index 0), and feature * to the given coordinates */ bool moveVertex( double x, double y, int atFeatureId, int atVertex ); + bool moveVertex( const QgsPoint &p, int atFeatureId, int atVertex ); /** Deletes a vertex from a feature */ @@ -393,6 +395,12 @@ /** delete a feature from the layer (but does not commit it) */ bool deleteFeature( int fid ); + /** vector layer is in 3D */ + bool is3d() const; + + /** vector layer is measured (i.e. has m(easured) values) */ + bool isMeasured() const; + /** Attempts to commit any changes to disk. Returns the result of the attempt. If a commit fails, the in-memory changes are left alone. Index: src/core/qgslabel.cpp =================================================================== --- src/core/qgslabel.cpp (revision 9915) +++ src/core/qgslabel.cpp (working copy) @@ -523,13 +523,10 @@ QGis::WkbType wkbType = geometry->wkbType(); labelpoint point; - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: - case QGis::WKBLineString25D: case QGis::WKBLineString: - case QGis::WKBPolygon25D: case QGis::WKBPolygon: { labelPoint( point, geom, geomlen ); @@ -537,11 +534,8 @@ } break; - case QGis::WKBMultiPoint25D: case QGis::WKBMultiPoint: - case QGis::WKBMultiLineString25D: case QGis::WKBMultiLineString: - case QGis::WKBMultiPolygon25D: case QGis::WKBMultiPolygon: // Return a position for each individual in the multi-feature { @@ -586,23 +580,20 @@ memcpy( &wkbType, geom, sizeof( wkbType ) ); geom += sizeof( wkbType ); - int dims = 2; + int dims = QGis::wkbTypeCoordNum( wkbType ); - switch ( wkbType ) + switch ( QGis::wkbType2d( wkbType ) ) { - case QGis::WKBPoint25D: case QGis::WKBPoint: { - Q_ASSERT( geom + 2*sizeof( double ) <= geomend ); + Q_ASSERT( geom + dims*sizeof( double ) <= geomend ); double *pts = ( double * )geom; point.p.set( pts[0], pts[1] ); point.angle = 0.0; - geom += 2 * sizeof( double ); + geom += dims * sizeof( double ); } break; - case QGis::WKBLineString25D: - dims = 3; case QGis::WKBLineString: // Line center { Q_ASSERT( geom + sizeof( int ) <= geomend ); @@ -647,8 +638,6 @@ } break; - case QGis::WKBPolygon25D: - dims = 3; case QGis::WKBPolygon: // centroid of outer ring { Q_ASSERT( geom + sizeof( int ) <= geomend ); Index: src/core/qgsdistancearea.h =================================================================== --- src/core/qgsdistancearea.h (revision 9915) +++ src/core/qgsdistancearea.h (working copy) @@ -90,9 +90,9 @@ protected: //! measures line distance, line points are extracted from WKB - unsigned char* measureLine( unsigned char* feature, double* area ); + unsigned char* measureLine( unsigned char* feature, double &area ); //! measures polygon area, vertices are extracted from WKB - unsigned char* measurePolygon( unsigned char* feature, double* area ); + unsigned char* measurePolygon( unsigned char* feature, double &area ); /** calculates distance from two points on ellipsoid Index: src/core/qgis.h =================================================================== --- src/core/qgis.h (revision 9915) +++ src/core/qgis.h (working copy) @@ -41,23 +41,84 @@ // //! Used for symbology operations - // Feature types + // Feature types (see OGC 06-103r3) enum WkbType { - WKBPoint = 1, + WKBGeometry = 0, + WKBPoint, WKBLineString, WKBPolygon, WKBMultiPoint, WKBMultiLineString, WKBMultiPolygon, + WKBGeometryCollection, + WKBCircularString, + WBKCompoundCurve, + WKBCurvedPolygon, + WKBMultiCurve, + WKBMultiSurface, + WKBCurve, + WKBSurface, + WKBPolyhedralSurface, + WKBTIN, + + WKBGeometryZ = 1000, + WKBPointZ, + WKBLineStringZ, + WKBPolygonZ, + WKBMultiPointZ, + WKBMultiLineStringZ, + WKBMultiPolygonZ, + WKBGeometryCollectionZ, + WKBCircularStringZ, + WBKCompoundCurveZ, + WKBCurvedPolygonZ, + WKBMultiCurveZ, + WKBMultiSurfaceZ, + WKBCurveZ, + WKBSurfaceZ, + WKBPolyhedralSurfaceZ, + WKBTINZ, + + WKBGeometryM = 2000, + WKBPointM, + WKBLineStringM, + WKBPolygonM, + WKBMultiPointM, + WKBMultiLineStringM, + WKBMultiPolygonM, + WKBGeometryCollectionM, + WKBCircularStringM, + WBKCompoundCurveM, + WKBCurvedPolygonM, + WKBMultiCurveM, + WKBMultiSurfaceM, + WKBCurveM, + WKBSurfaceM, + WKBPolyhedralSurfaceM, + WKBTINM, + + WKBGeometryZM = 3000, + WKBPointZM, + WKBLineStringZM, + WKBPolygonZM, + WKBMultiPointZM, + WKBMultiLineStringZM, + WKBMultiPolygonZM, + WKBGeometryCollectionZM, + WKBCircularStringZM, + WBKCompoundCurveZM, + WKBCurvedPolygonZM, + WKBMultiCurveZM, + WKBMultiSurfaceZM, + WKBCurveZM, + WKBSurfaceZM, + WKBPolyhedralSurfaceZM, + WKBTINZM, + WKBUnknown, - WKBPoint25D = 0x80000001, - WKBLineString25D, - WKBPolygon25D, - WKBMultiPoint25D, - WKBMultiLineString25D, - WKBMultiPolygon25D }; + enum GeometryType { Point, @@ -66,12 +127,75 @@ UnknownGeometry }; + static WkbType wkbType2d( WkbType wkbType ) + { + return ( WkbType )( wkbType % 1000 ); + } + + static bool wkbTypeHasZValue( WkbType wkbType ) + { + return ( wkbType >= 1000 && wkbType <= 2000 ) || wkbType > 3000; + } + + static bool wkbTypeHasMValue( WkbType wkbType ) + { + return wkbType >= 2000; + } + + static int wkbTypeCoordNum( WkbType wkbType ) + { + if ( wkbType < 1000 ) + return 2; + else if ( wkbType < 3000 ) + return 3; + else + return 4; + } + + static GeometryType geometryTypeFromWkbType( WkbType wkbType ) + { + switch ( wkbType2d( wkbType ) ) + { + case WKBPoint: + case WKBMultiPoint: + return Point; + + case WKBLineString: + case WKBMultiLineString: + return Line; + + case WKBPolygon: + case WKBMultiPolygon: + return Polygon; + + default: + return UnknownGeometry; + } + } + + static bool wkbTypeIsMulti( WkbType wkbType ) + { + switch ( wkbType2d( wkbType ) ) + { + case WKBMultiPoint: + case WKBMultiLineString: + case WKBMultiPolygon: + case WKBGeometryCollection: + case WKBMultiCurve: + case WKBMultiSurface: + return true; + default: + return false; + } + } + // String representation of geometry types (set in qgis.cpp) static const char *qgisVectorGeometryType[]; //! description strings for feature types - static const char *qgisFeatureTypes[]; + static const char *qgisFeatureTypes( WkbType wkbType ); + //! map units that qgis supports enum UnitType { Index: src/core/qgsclipper.cpp =================================================================== --- src/core/qgsclipper.cpp (revision 9915) +++ src/core/qgsclipper.cpp (working copy) @@ -31,9 +31,3 @@ const double QgsClipper::MIN_Y = -30000; const double QgsClipper::SMALL_NUM = 1e-12; - - - - - - Index: src/core/qgsgeometry.h =================================================================== --- src/core/qgsgeometry.h (revision 9915) +++ src/core/qgsgeometry.h (working copy) @@ -127,9 +127,9 @@ /** Returns true if wkb of the geometry is of WKBMulti* type */ bool isMultipart(); + double length(); + double area(); - - double distance( QgsGeometry& geom ); /** @@ -165,7 +165,7 @@ * these error conditions. (Or maybe we add another method to this * object to help make the distinction?) */ - bool insertVertex( double x, double y, int beforeVertex ); + bool insertVertex( const QgsPoint &p, int beforeVertex ); /** Moves the vertex at the given position number * and item (first number is index 0) @@ -173,7 +173,7 @@ * Returns FALSE if atVertex does not correspond to a valid vertex * on this geometry */ - bool moveVertex( double x, double y, int atVertex ); + bool moveVertex( const QgsPoint &p, int atVertex ); /** Deletes the vertex at the given position number and item * (first number is index 0) @@ -374,7 +374,7 @@ * Returns FALSE if beforeVertex does not correspond to a valid vertex number * on the Coordinate Sequence. */ - bool insertVertex( double x, double y, + bool insertVertex( const QgsPoint &p, int beforeVertex, const GEOSCoordSequence* old_sequence, GEOSCoordSequence** new_sequence ); @@ -390,14 +390,14 @@ @param dx translation of x-coordinate @param dy translation of y-coordinate @param hasZValue 25D type?*/ - void translateVertex( int& wkbPosition, double dx, double dy, bool hasZValue ); + void translateVertex( int& wkbPosition, double dx, double dy, int mCoordNum ); /**Transforms a single vertex by ct. @param ptr pointer to the wkb fragment containing the vertex @param wkbPosition position in wkb array. Is increased automatically by the function @param ct the QgsCoordinateTransform @param hasZValue 25D type?*/ - void transformVertex( int& wkbPosition, QgsCoordinateTransform& ct, bool hasZValue ); + void transformVertex( int& wkbPosition, QgsCoordinateTransform& ct, int mCoordNum ); //helper functions for geometry splitting @@ -423,13 +423,13 @@ int mergeGeometriesMultiTypeSplit( QVector& splitResult ); /** return point from wkb */ - QgsPoint asPoint( unsigned char*& ptr, bool hasZValue ); + QgsPoint asPoint( unsigned char*& ptr, QGis::WkbType wkbtype ); /** return polyline from wkb */ - QgsPolyline asPolyline( unsigned char*& ptr, bool hasZValue ); + QgsPolyline asPolyline( unsigned char*& ptr, QGis::WkbType wkbtype ); /** return polygon from wkb */ - QgsPolygon asPolygon( unsigned char*& ptr, bool hasZValue ); + QgsPolygon asPolygon( unsigned char*& ptr, QGis::WkbType wkbtype ); static int refcount; }; // class QgsGeometry Index: src/core/qgis.cpp =================================================================== --- src/core/qgis.cpp (revision 9915) +++ src/core/qgis.cpp (working copy) @@ -46,16 +46,154 @@ }; // description strings for feature types -const char* QGis::qgisFeatureTypes[] = +const char* QGis::qgisFeatureTypes( QGis::WkbType theType ) { - "Null", - "WKBPoint", - "WKBLineString", - "WKBPolygon", - "WKBMultiPoint", - "WKBMultiLineString", - "WKBMultiPolygon" -}; + switch ( theType ) + { + case QGis::WKBGeometry: + return "WKBGeometry"; + case QGis::WKBPoint: + return "WKBPoint"; + case QGis::WKBLineString: + return "WKBLineString"; + case QGis::WKBPolygon: + return "WKBPolygon"; + case QGis::WKBMultiPoint: + return "WKBMultiPoint"; + case QGis::WKBMultiLineString: + return "WKBMultiLineString"; + case QGis::WKBMultiPolygon: + return "WKBMultiPolygon"; + case QGis::WKBGeometryCollection: + return "WKBGeometryCollection"; + case QGis::WKBCircularString: + return "WKBCircularString"; + case QGis::WBKCompoundCurve: + return "WBKCompoundCurve"; + case QGis::WKBCurvedPolygon: + return "WKBCurvedPolygon"; + case QGis::WKBMultiCurve: + return "WKBMultiCurve"; + case QGis::WKBMultiSurface: + return "WKBMultiSurface"; + case QGis::WKBCurve: + return "WKBCurve"; + case QGis::WKBSurface: + return "WKBSurface"; + case QGis::WKBPolyhedralSurface: + return "WKBPolyhedralSurface"; + case QGis::WKBTIN: + return "WKBTIN"; + case QGis::WKBGeometryZ: + return "WKBGeometryZ"; + case QGis::WKBPointZ: + return "WKBPointZ"; + case QGis::WKBLineStringZ: + return "WKBLineStringZ"; + case QGis::WKBPolygonZ: + return "WKBPolygonZ"; + case QGis::WKBMultiPointZ: + return "WKBMultiPointZ"; + case QGis::WKBMultiLineStringZ: + return "WKBMultiLineStringZ"; + case QGis::WKBMultiPolygonZ: + return "WKBMultiPolygonZ"; + case QGis::WKBGeometryCollectionZ: + return "WKBGeometryCollectionZ"; + case QGis::WKBCircularStringZ: + return "WKBCircularStringZ"; + case QGis::WBKCompoundCurveZ: + return "WBKCompoundCurveZ"; + case QGis::WKBCurvedPolygonZ: + return "WKBCurvedPolygonZ"; + case QGis::WKBMultiCurveZ: + return "WKBMultiCurveZ"; + case QGis::WKBMultiSurfaceZ: + return "WKBMultiSurfaceZ"; + case QGis::WKBCurveZ: + return "WKBCurveZ"; + case QGis::WKBSurfaceZ: + return "WKBSurfaceZ"; + case QGis::WKBPolyhedralSurfaceZ: + return "WKBPolyhedralSurfaceZ"; + case QGis::WKBTINZ: + return "WKBTINZ"; + + case QGis::WKBGeometryM: + return "WKBGeometryM"; + case QGis::WKBPointM: + return "WKBPointM"; + case QGis::WKBLineStringM: + return "WKBLineStringM"; + case QGis::WKBPolygonM: + return "WKBPolygonM"; + case QGis::WKBMultiPointM: + return "WKBMultiPointM"; + case QGis::WKBMultiLineStringM: + return "WKBMultiLineStringM"; + case QGis::WKBMultiPolygonM: + return "WKBMultiPolygonM"; + case QGis::WKBGeometryCollectionM: + return "WKBGeometryCollectionM"; + case QGis::WKBCircularStringM: + return "WKBCircularStringM"; + case QGis::WBKCompoundCurveM: + return "WBKCompoundCurveM"; + case QGis::WKBCurvedPolygonM: + return "WKBCurvedPolygonM"; + case QGis::WKBMultiCurveM: + return "WKBMultiCurveM"; + case QGis::WKBMultiSurfaceM: + return "WKBMultiSurfaceM"; + case QGis::WKBCurveM: + return "WKBCurveM"; + case QGis::WKBSurfaceM: + return "WKBSurfaceM"; + case QGis::WKBPolyhedralSurfaceM: + return "WKBPolyhedralSurfaceM"; + case QGis::WKBTINM: + return "WKBTINM"; + + case QGis::WKBGeometryZM: + return "WKBGeometryZM"; + case QGis::WKBPointZM: + return "WKBPointZM"; + case QGis::WKBLineStringZM: + return "WKBLineStringZM"; + case QGis::WKBPolygonZM: + return "WKBPolygonZM"; + case QGis::WKBMultiPointZM: + return "WKBMultiPointZM"; + case QGis::WKBMultiLineStringZM: + return "WKBMultiLineStringZM"; + case QGis::WKBMultiPolygonZM: + return "WKBMultiPolygonZM"; + case QGis::WKBGeometryCollectionZM: + return "WKBGeometryCollectionZM"; + case QGis::WKBCircularStringZM: + return "WKBCircularStringZM"; + case QGis::WBKCompoundCurveZM: + return "WBKCompoundCurveZM"; + case QGis::WKBCurvedPolygonZM: + return "WKBCurvedPolygonZM"; + case QGis::WKBMultiCurveZM: + return "WKBMultiCurveZM"; + case QGis::WKBMultiSurfaceZM: + return "WKBMultiSurfaceZM"; + case QGis::WKBCurveZM: + return "WKBCurveZM"; + case QGis::WKBSurfaceZM: + return "WKBSurfaceZM"; + case QGis::WKBPolyhedralSurfaceZM: + return "WKBPolyhedralSurfaceZM"; + case QGis::WKBTINZM: + return "WKBTINZM"; + + default: + return "Unknown type"; + } +} + const double QGis::DEFAULT_IDENTIFY_RADIUS = 0.5; Index: src/providers/postgres/qgspostgresprovider.h =================================================================== --- src/providers/postgres/qgspostgresprovider.h (revision 9915) +++ src/providers/postgres/qgspostgresprovider.h (working copy) @@ -397,6 +397,7 @@ * Spatial reference id of the layer */ QString srid; + /** * Rectangle that contains the extent (bounding box) of the layer */ @@ -550,6 +551,7 @@ */ void customEvent( QEvent *e ); + void appendGeomChar( unsigned char c, QString &geomParam ) const; void appendGeomString( QgsGeometry *geom, QString &geomParam ) const; QByteArray paramValue( QString fieldvalue, const QString &defaultValue ) const; Index: src/providers/postgres/qgspostgresprovider.cpp =================================================================== --- src/providers/postgres/qgspostgresprovider.cpp (revision 9915) +++ src/providers/postgres/qgspostgresprovider.cpp (working copy) @@ -395,7 +395,7 @@ if ( fetchGeometry ) { - query += QString( ",asbinary(%1,'%2')" ) + query += QString( ",asewkb(%1,'%2')" ) .arg( quotedIdentifier( geometryColumn ) ) .arg( endianString() ); } @@ -463,9 +463,46 @@ int returnedLength = PQgetlength( queryResult, row, 1 ); if ( returnedLength > 0 ) { - unsigned char *featureGeom = new unsigned char[returnedLength + 1]; - memset( featureGeom, '\0', returnedLength + 1 ); - memcpy( featureGeom, PQgetvalue( queryResult, row, 1 ), returnedLength ); + unsigned int wkbType; + unsigned char *featureGeom, *p = (unsigned char *)PQgetvalue( queryResult, row, 1 ), *q; + + q = p+1; + memcpy( &wkbType, q, sizeof( wkbType ) ); + q += sizeof( wkbType ); + + if ( wkbType & 0xe0000000 ) + { + if ( wkbType & 0x20000000 ) + { + // wkbSRID - skip srid + returnedLength -= 4; + q += 4; + } + + switch ( wkbType & 0xc0000000 ) + { + case 0x80000000: // wkbZ + wkbType = ( wkbType & 0x1fffffff ) + 1000; + break; + case 0x40000000: // wkbM + wkbType = ( wkbType & 0x1fffffff ) + 2000; + break; + case 0xc0000000: // wkbZ|wkbM + wkbType = ( wkbType & 0x1fffffff ) + 3000; + break; + } + + featureGeom = new unsigned char[ returnedLength + 1 ]; + featureGeom[0] = p[0]; + memcpy( featureGeom+1, &wkbType, sizeof( wkbType ) ); + memcpy( featureGeom+5, q, returnedLength - 4 ); + } + else + { + featureGeom = new unsigned char[ returnedLength + 1 ]; + memcpy( featureGeom, p, returnedLength + 1 ); + } + feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else @@ -1741,9 +1778,8 @@ .arg( mSchemaTableName ) .arg( quotedIdentifier( geometryColumn ) ) .arg( quotedIdentifier( primaryKey ) ), - values = QString( ") VALUES (GeomFromWKB($1%1,%2),$2" ) - .arg( connectionRW->useWkbHex() ? "" : "::bytea" ) - .arg( srid ); + values = QString( ") VALUES (GeomFromEWKB($1%1),$2" ) + .arg( connectionRW->useWkbHex() ? "" : "::bytea" ); const QgsAttributeMap &attributevec = flist[0].attributeMap(); @@ -2077,16 +2113,54 @@ return returnvalue; } +void QgsPostgresProvider::appendGeomChar( unsigned char c, QString &geomString ) const +{ + if ( connectionRW->useWkbHex() ) + geomString += QString( "%1" ).arg(( int ) c, 2, 16, QChar( '0' ) ); + else + geomString += QString( "\\%1" ).arg(( int ) c, 3, 8, QChar( '0' ) ); +} + void QgsPostgresProvider::appendGeomString( QgsGeometry *geom, QString &geomString ) const { unsigned char *buf = geom->asWkb(); - for ( uint i = 0; i < geom->wkbSize(); ++i ) + + unsigned int wkbType; + memcpy( &wkbType, buf+1, sizeof(wkbType) ); + + switch( wkbType / 1000 ) { - if ( connectionRW->useWkbHex() ) - geomString += QString( "%1" ).arg(( int ) buf[i], 2, 16, QChar( '0' ) ); - else - geomString += QString( "\\%1" ).arg(( int ) buf[i], 3, 8, QChar( '0' ) ); + case 0: // S + wkbType = (wkbType % 1000) | 0x20000000; + break; + case 1: // ZS + wkbType = (wkbType % 1000) | 0x80000000 | 0x20000000; + break; + case 2: // MS + wkbType = (wkbType % 1000) | 0x40000000 | 0x20000000; + break; + case 3: // ZMS + wkbType = (wkbType % 1000) | 0x80000000 | 0x40000000 | 0x20000000; + break; } + + unsigned int iSrid = srid.toInt(); + + // turn WKB into EWKB + appendGeomChar( buf[0], geomString ); + appendGeomChar( ((unsigned char *) &wkbType)[0], geomString ); + appendGeomChar( ((unsigned char *) &wkbType)[1], geomString ); + appendGeomChar( ((unsigned char *) &wkbType)[2], geomString ); + appendGeomChar( ((unsigned char *) &wkbType)[3], geomString ); + appendGeomChar( ((unsigned char *) &iSrid)[0], geomString ); + appendGeomChar( ((unsigned char *) &iSrid)[1], geomString ); + appendGeomChar( ((unsigned char *) &iSrid)[2], geomString ); + appendGeomChar( ((unsigned char *) &iSrid)[3], geomString ); + + for ( uint i = 5; i < geom->wkbSize(); ++i ) + { + appendGeomChar( buf[i], geomString ); + } } bool QgsPostgresProvider::changeGeometryValues( QgsGeometryMap & geometry_map ) @@ -2103,11 +2177,10 @@ // Start the PostGIS transaction connectionRW->PQexecNR( "BEGIN" ); - QString update = QString( "UPDATE %1 SET %2=GeomFromWKB($1%3,%4) WHERE %5=$2" ) + QString update = QString( "UPDATE %1 SET %2=GeomFromEWKB($1%3) WHERE %4=$2" ) .arg( mSchemaTableName ) .arg( quotedIdentifier( geometryColumn ) ) .arg( connectionRW->useWkbHex() ? "" : "::bytea" ) - .arg( srid ) .arg( quotedIdentifier( primaryKey ) ); PGresult *stmt = connectionRW->PQprepare( "updatefeatures", update, 2, NULL ); @@ -2133,6 +2206,8 @@ params << geomParam; params << QString( "%1" ).arg( iter.key() ); + QgsDebugMsg( QString( "update:%1 id:%2 geomParam:%3" ).arg( update ).arg( iter.key() ).arg( geomParam ) ); + PGresult *result = connectionRW->PQexecPrepared( "updatefeatures", params ); if ( result == 0 || PQresultStatus( result ) == PGRES_FATAL_ERROR ) throw PGException( result ); @@ -2446,8 +2521,9 @@ srid = ""; valid = false; QStringList log; + int nDims = 2; - QString sql = QString( "select type,srid from geometry_columns" + QString sql = QString( "select type,srid,coord_dimension from geometry_columns" " where f_table_name=%1 and f_geometry_column=%2 and f_table_schema=%3" ) .arg( quotedValue( mTableName ) ) .arg( quotedValue( geometryColumn ) ) @@ -2463,13 +2539,14 @@ { fType = QString::fromUtf8( PQgetvalue( result, 0, 0 ) ); srid = QString::fromUtf8( PQgetvalue( result, 0, 1 ) ); + nDims = QString::fromUtf8( PQgetvalue( result, 0, 2 ) ).toInt(); } else { // Didn't find what we need in the geometry_columns table, so // get stuff from the relevant column instead. This may (will?) // fail if there is no data in the relevant table. - sql = QString( "select srid(%1),geometrytype(%1) from %2" ) + sql = QString( "select srid(%1),geometrytype(%1),ndims(%1) from %2" ) .arg( quotedIdentifier( geometryColumn ) ) .arg( mSchemaTableName ); @@ -2487,6 +2564,7 @@ { srid = QString::fromUtf8( PQgetvalue( result, 0, 0 ) ); fType = QString::fromUtf8( PQgetvalue( result, 0, 1 ) ); + nDims = QString::fromUtf8( PQgetvalue( result, 0, 2 ) ).toInt(); } } @@ -2499,8 +2577,11 @@ sql = QString( "select distinct " "case" " when geometrytype(%1) IN ('POINT','MULTIPOINT') THEN 'POINT'" + " when geometrytype(%1) IN ('POINTM','MULTIPOINTM') THEN 'POINTM'" " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'" + " when geometrytype(%1) IN ('LINESTRINGM','MULTILINESTRINGM') THEN 'LINESTRINGM'" " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'" + " when geometrytype(%1) IN ('POLYGONM','MULTIPOLYGONM') THEN 'POLYGONM'" " end " "from %2" ).arg( quotedIdentifier( geometryColumn ) ).arg( mSchemaTableName ); if ( mUri.sql() != "" ) @@ -2515,27 +2596,57 @@ } if ( fType == "POINT" || fType == "POINTM" ) { - geomType = QGis::WKBPoint; + if ( nDims == 3 ) + geomType = fType == "POINT" ? QGis::WKBPointZ : QGis::WKBPointM; + else if ( nDims == 4 ) + geomType = QGis::WKBPointZM; + else + geomType = QGis::WKBPoint; } else if ( fType == "MULTIPOINT" || fType == "MULTIPOINTM" ) { - geomType = QGis::WKBMultiPoint; + if ( nDims == 3 ) + geomType = fType == "MULTIPOINT" ? QGis::WKBMultiPointZ : QGis::WKBMultiPointM; + else if ( nDims == 4 ) + geomType = QGis::WKBMultiPointZM; + else + geomType = QGis::WKBMultiPoint; } else if ( fType == "LINESTRING" || fType == "LINESTRINGM" ) { - geomType = QGis::WKBLineString; + if ( nDims == 3 ) + geomType = fType == "LINESTRING" ? QGis::WKBLineStringZ : QGis::WKBLineStringM; + else if ( nDims == 4 ) + geomType = QGis::WKBLineStringZM; + else + geomType = QGis::WKBLineString; } else if ( fType == "MULTILINESTRING" || fType == "MULTILINESTRINGM" ) { - geomType = QGis::WKBMultiLineString; + if ( nDims == 3 ) + geomType = fType == "MULTILINESTRING" ? QGis::WKBMultiLineStringZ : QGis::WKBMultiLineStringM; + else if ( nDims == 4 ) + geomType = QGis::WKBMultiLineStringZM; + else + geomType = QGis::WKBMultiLineString; } else if ( fType == "POLYGON" || fType == "POLYGONM" ) { - geomType = QGis::WKBPolygon; + if ( nDims == 3 ) + geomType = fType == "POLYGON" ? QGis::WKBPolygonZ : QGis::WKBPolygonM; + else if ( nDims == 4 ) + geomType = QGis::WKBPolygonZM; + else + geomType = QGis::WKBPolygon; } else if ( fType == "MULTIPOLYGON" || fType == "MULTIPOLYGONM" ) { - geomType = QGis::WKBMultiPolygon; + if ( nDims == 3 ) + geomType = fType == "MULTIPOLYGON" ? QGis::WKBMultiPolygonZ : QGis::WKBMultiPolygonM; + else if ( nDims == 4 ) + geomType = QGis::WKBMultiPolygonZM; + else + geomType = QGis::WKBMultiPolygon; } else { @@ -2552,6 +2663,7 @@ showMessageBox( tr( "Unable to get feature type and srid" ), log ); } +#if 0 // store whether the geometry includes measure value if ( fType == "POINTM" || fType == "MULTIPOINTM" || fType == "LINESTRINGM" || fType == "MULTILINESTRINGM" || @@ -2561,14 +2673,14 @@ // as this would lead to corruption of measures enabledCapabilities &= ~( QgsVectorDataProvider::ChangeGeometries | QgsVectorDataProvider::AddFeatures ); } +#endif - if ( valid ) { QgsDebugMsg( "SRID is " + srid ); QgsDebugMsg( "type is " + fType ); QgsDebugMsg( "Feature type is " + QString::number( geomType ) ); - QgsDebugMsg( "Feature type name is " + QString( QGis::qgisFeatureTypes[geomType] ) ); + QgsDebugMsg( "Feature type name is " + QString( QGis::qgisFeatureTypes( geomType ) ) ); } else { Index: src/providers/ogr/qgsogrprovider.h =================================================================== --- src/providers/ogr/qgsogrprovider.h (revision 9915) +++ src/providers/ogr/qgsogrprovider.h (working copy) @@ -246,7 +246,8 @@ long featuresCounted; //! Selection rectangle - OGRGeometryH mSelectionRectangle; + QgsRectangle mSelectionRectangle; + /**Adds one feature*/ bool addFeature( QgsFeature& f ); /**Deletes one feature*/ Index: src/providers/ogr/qgsogrprovider.cpp =================================================================== --- src/providers/ogr/qgsogrprovider.cpp (revision 9915) +++ src/providers/ogr/qgsogrprovider.cpp (working copy) @@ -138,11 +138,6 @@ ogrDataSource = 0; free( extent_ ); extent_ = 0; - if ( mSelectionRectangle ) - { - OGR_G_DestroyGeometry( mSelectionRectangle ); - mSelectionRectangle = 0; - } } void QgsOgrProvider::setEncoding( const QString& e ) @@ -189,7 +184,7 @@ case OFTReal: varType = QVariant::Double; break; // unsupported in OGR 1.3 //case OFTDateTime: varType = QVariant::DateTime; break; -#if GDAL_VERSION_NUM >= 1400 +#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1400 case OFTString: varType = QVariant::String; break; #endif default: varType = QVariant::String; // other unsupported, leave it as a string @@ -281,24 +276,13 @@ feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) ); - if ( mUseIntersect ) + if ( mUseIntersect && mSelectionRectangle.isFinite() ) { - //precise test for intersection with search rectangle - //first make QgsRectangle from OGRPolygon - OGREnvelope env; - memset( &env, 0, sizeof( env ) ); - if ( mSelectionRectangle ) - OGR_G_GetEnvelope( mSelectionRectangle, &env ); - if ( env.MinX != 0 || env.MinY != 0 || env.MaxX != 0 || env.MaxY != 0 ) //if envelope is invalid, skip the precise intersection test + if ( !feature.geometry()->intersects( mSelectionRectangle ) ) { - selectionRect.set( env.MinX, env.MinY, env.MaxX, env.MaxY ); - if ( !feature.geometry()->intersects( selectionRect ) ) - { - OGR_F_Destroy( fet ); - continue; - } + OGR_F_Destroy( fet ); + continue; } - } } @@ -340,26 +324,20 @@ } else { - OGRGeometryH filter = 0; - QString wktExtent = QString( "POLYGON((%1))" ).arg( rect.asPolygon() ); - QByteArray ba = wktExtent.toAscii(); - const char *wktText = ba; + QgsDebugMsg( "Setting spatial filter using " + rect.toString() ); if ( useIntersect ) { // store the selection rectangle for use in filtering features during // an identify and display attributes - if ( mSelectionRectangle ) - OGR_G_DestroyGeometry( mSelectionRectangle ); - - OGR_G_CreateFromWkt(( char ** )&wktText, NULL, &mSelectionRectangle ); - wktText = ba; + mSelectionRectangle = rect; } + else + { + mSelectionRectangle.setMinimal(); + } - OGR_G_CreateFromWkt(( char ** )&wktText, NULL, &filter ); - QgsDebugMsg( "Setting spatial filter using " + wktExtent ); - OGR_L_SetSpatialFilter( ogrLayer, filter ); - OGR_G_DestroyGeometry( filter ); + OGR_L_SetSpatialFilterRect( ogrLayer, rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum() ); } //start with first feature @@ -578,31 +556,31 @@ for ( QgsNewAttributesMap::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter ) { - OGRFieldDefnH fielddefn = - OGR_Fld_Create( mEncoding->fromUnicode( iter.key() ).data(), OFTInteger ); + OGRFieldDefnH fielddefn = OGR_Fld_Create( mEncoding->fromUnicode( iter.key() ).data(), OFTInteger ); - if ( *iter == "OFTInteger" ) + if ( *iter == "Integer" ) { OGR_Fld_SetType( fielddefn, OFTInteger ); + OGR_Fld_SetWidth( fielddefn, 10 ); } - else if ( *iter == "OFTReal" ) + else if ( *iter == "Real" ) { OGR_Fld_SetType( fielddefn, OFTReal ); } - else if ( *iter == "OFTString" ) + else if ( *iter == "String" ) { OGR_Fld_SetType( fielddefn, OFTString ); } else { - QgsLogger::warning( "QgsOgrProvider::addAttributes, type not found" ); + QgsLogger::warning( QString( "QgsOgrProvider::addAttributes, type %1 not found" ).arg( *iter ) ); returnvalue = false; continue; } if ( OGR_L_CreateField( ogrLayer, fielddefn, TRUE ) != OGRERR_NONE ) { - QgsLogger::warning( "QgsOgrProvider.cpp: writing of OFTInteger field failed" ); + QgsLogger::warning( "QgsOgrProvider.cpp: writing of field failed" ); returnvalue = false; } OGR_Fld_Destroy( fielddefn ); @@ -727,7 +705,7 @@ QString sql = QString( "CREATE SPATIAL INDEX ON %1" ).arg( quotedIdentifier( fi.completeBaseName() ) ); // quote the layer name so spaces are handled OGR_DS_ExecuteSQL( ogrDataSource, mEncoding->fromUnicode( sql ).data(), OGR_L_GetSpatialFilter( ogrLayer ), "" ); //find out, if the .qix file is there - QFile indexfile( fi.path().append( "/").append( fi.completeBaseName() ).append( ".qix" ) ); + QFile indexfile( fi.path().append( "/" ).append( fi.completeBaseName() ).append( ".qix" ) ); if ( indexfile.exists() ) { return true; @@ -749,7 +727,7 @@ } } - OGR_L_SyncToDisk( ogrLayer ); + OGR_L_SyncToDisk( ogrLayer ); QFileInfo fi( dataSourceUri() ); // to get the base name QString sql = QString( "REPACK %1" ).arg( fi.completeBaseName() ); // don't quote the layer name as it works with spaces in the name and won't work if the name is quoted OGR_DS_ExecuteSQL( ogrDataSource, mEncoding->fromUnicode( sql ).data(), NULL, NULL ); @@ -852,9 +830,17 @@ { // Ideally this should test for Shapefile type and GDAL >= 1.2.6 // In reality, createSpatialIndex() looks after itself. - ability |= QgsVectorDataProvider::CreateSpatialIndex; + ability |= CreateSpatialIndex; } +#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1600 + // adding attributes was added in GDAL 1.6 + if ( ogrDriverName.startsWith( "ESRI" ) ) + { + ability |= AddAttributes; + } +#endif + // OGR doesn't handle shapefiles without attributes, ie. missing DBFs well, fixes #803 if ( ogrDriverName.startsWith( "ESRI" ) && mAttributeFields.size() == 0 ) { @@ -1216,7 +1202,7 @@ OGR_DS_Destroy( dataSource ); QgsDebugMsg( QString( "GDAL Version number %1" ).arg( GDAL_VERSION_NUM ) ); -#if GDAL_VERSION_NUM >= 1310 +#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1310 if ( reference ) { OSRRelease( reference ); Index: python/core/qgis.sip =================================================================== --- python/core/qgis.sip (revision 9915) +++ python/core/qgis.sip (working copy) @@ -43,19 +43,79 @@ // Feature types enum WkbType { - WKBPoint = 1, - WKBLineString, - WKBPolygon, - WKBMultiPoint, - WKBMultiLineString, - WKBMultiPolygon, - WKBUnknown, - WKBPoint25D = 0x80000001, - WKBLineString25D, - WKBPolygon25D, - WKBMultiPoint25D, - WKBMultiLineString25D, - WKBMultiPolygon25D + WKBGeometry = 0, + WKBPoint, + WKBLineString, + WKBPolygon, + WKBMultiPoint, + WKBMultiLineString, + WKBMultiPolygon, + WKBGeometryCollection, + WKBCircularString, + WBKCompoundCurve, + WKBCurvedPolygon, + WKBMultiCurve, + WKBMultiSurface, + WKBCurve, + WKBSurface, + WKBPolyhedralSurface, + WKBTIN, + + WKBGeometryZ = 0x1000, + WKBPointZ, + WKBLineStringZ, + WKBPolygonZ, + WKBMultiPointZ, + WKBMultiLineStringZ, + WKBMultiPolygonZ, + WKBGeometryCollectionZ, + WKBCircularStringZ, + WBKCompoundCurveZ, + WKBCurvedPolygonZ, + WKBMultiCurveZ, + WKBMultiSurfaceZ, + WKBCurveZ, + WKBSurfaceZ, + WKBPolyhedralSurfaceZ, + WKBTINZ, + + WKBGeometryM = 0x2000, + WKBPointM, + WKBLineStringM, + WKBPolygonM, + WKBMultiPointM, + WKBMultiLineStringM, + WKBMultiPolygonM, + WKBGeometryCollectionM, + WKBCircularStringM, + WBKCompoundCurveM, + WKBCurvedPolygonM, + WKBMultiCurveM, + WKBMultiSurfaceM, + WKBCurveM, + WKBSurfaceM, + WKBPolyhedralSurfaceM, + WKBTINM, + + WKBGeometryZM = 0x3000, + WKBPointZM, + WKBLineStringZM, + WKBPolygonZM, + WKBMultiPointZM, + WKBMultiLineStringZM, + WKBMultiPolygonZM, + WKBGeometryCollectionZM, + WKBCircularStringZM, + WBKCompoundCurveZM, + WKBCurvedPolygonZM, + WKBMultiCurveZM, + WKBMultiSurfaceZM, + WKBCurveZM, + WKBSurfaceZM, + WKBPolyhedralSurfaceZM, + WKBTINZM, + + WKBUnknown, }; enum GeometryType { Index: python/core/qgsgeometry.sip =================================================================== --- python/core/qgsgeometry.sip (revision 9915) +++ python/core/qgsgeometry.sip (working copy) @@ -129,7 +129,7 @@ * these error conditions. (Or maybe we add another method to this * object to help make the distinction?) */ - bool insertVertex(double x, double y, int beforeVertex); + bool insertVertex(const QgsPoint &p, int beforeVertex); /** Moves the vertex at the given position number, * ring and item (first number is index 0) @@ -137,7 +137,7 @@ * Returns FALSE if atVertex does not correspond to a valid vertex * on this geometry */ - bool moveVertex(double x, double y, int atVertex); + bool moveVertex(const QgsPoint &p, int atVertex); /** Deletes the vertex at the given position number, * ring and item (first number is index 0) @@ -149,7 +149,7 @@ * these error conditions. (Or maybe we add another method to this * object to help make the distinction?) */ - bool deleteVertex(int atVertex); + bool deleteVertex(int atVertex); /** * Returns coordinates of a vertex. @@ -276,5 +276,8 @@ if wkbType is WKBPolygon, otherwise an empty list */ QgsMultiPolygon asMultiPolygon(); + double area(); + double length(); + }; // class QgsGeometry Index: python/core/qgspoint.sip =================================================================== --- python/core/qgspoint.sip (revision 9915) +++ python/core/qgspoint.sip (working copy) @@ -20,7 +20,7 @@ * @param x x coordinate * @param y y coordinate */ - QgsPoint(double x, double y); + QgsPoint(double x, double y, double z = 0.0, double m = 0.0 ); ~QgsPoint(); @@ -34,8 +34,18 @@ */ void setY(double y); + /*! Sets the z value of the point + * @param z z coordinate + */ + void setZ(double z); + + /*! Sets the m value of the point + * @param m m value + */ + void setM(double m); + /*! Sets the x and y value of the point */ - void set(double x, double y); + void set(double x, double y, double z = 0.0, double m = 0.0 ); /*! Get the x value of the point * @return x coordinate @@ -47,6 +57,16 @@ */ double y() const; + /*! Get the z value of the point + * @return z coordinate + */ + double z() const; + + /*! Get the m value of the point + * @return m value + */ + double m() const; + //! String representation of the point (x,y) QString toString() const; @@ -60,10 +80,10 @@ QString wellKnownText(); /**Returns the squared distance between this point and x,y*/ - double sqrDist(double x, double y) const; + double sqrDist2d(double x, double y) const; /**Returns the squared distance between this and other point*/ - double sqrDist(const QgsPoint& other); + double sqrDist2d(const QgsPoint& other); //! equality operator bool operator==(const QgsPoint &other); @@ -72,7 +92,7 @@ bool operator!=(const QgsPoint &other); //! Multiply x and y by the given value - void multiply(const double& scalar); + void multiply2d(const double& scalar); SIP_PYOBJECT __repr__(); @@ -102,5 +122,5 @@ -}; // class QgsPOint +}; // class QgsPoint Index: python/core/qgsmaplayerregistry.sip =================================================================== --- python/core/qgsmaplayerregistry.sip (revision 9915) +++ python/core/qgsmaplayerregistry.sip (working copy) @@ -23,7 +23,7 @@ //! Retrieve a pointer to a loaded plugin by id QgsMapLayer * mapLayer(QString theLayerId); - //! Retrieve the mapLayers collection (mainly intended for use by projectio) + //! Retrieve the mapLayers collection (mainly intended for use by projection) QMap & mapLayers(); /** Add a layer to the map of loaded layers Index: tests/src/core/testqgsgeometry.cpp =================================================================== --- tests/src/core/testqgsgeometry.cpp (revision 9915) +++ tests/src/core/testqgsgeometry.cpp (working copy) @@ -335,37 +335,7 @@ QString TestQgsGeometry::wkbTypeAsString( QGis::WkbType theType ) { - switch ( theType ) - { - case QGis::WKBPoint: - return "WKBPoint"; - case QGis::WKBLineString: - return "WKBLineString"; - case QGis::WKBPolygon: - return "WKBPolygon"; - case QGis::WKBMultiPoint: - return "WKBMultiPoint"; - case QGis::WKBMultiLineString: - return "WKBMultiLineString"; - case QGis::WKBMultiPolygon: - return "WKBMultiPolygon"; - case QGis::WKBUnknown: - return "WKBUnknown"; - case QGis::WKBPoint25D: - return "WKBPoint25D"; - case QGis::WKBLineString25D: - return "WKBLineString25D"; - case QGis::WKBPolygon25D: - return "WKBPolygon25D"; - case QGis::WKBMultiPoint25D: - return "WKBMultiPoint25D"; - case QGis::WKBMultiLineString25D: - return "WKBMultiLineString25D"; - case QGis::WKBMultiPolygon25D: - return "WKBMultiPolygon25D"; - default: - return "Unknown type"; - } + return QGis::qgisFeatureTypes( theType ); } QTEST_MAIN( TestQgsGeometry )