400 changes: 196 additions & 204 deletions src/app/nodetool/qgsmaptoolnodetool.cpp

Large diffs are not rendered by default.

7 changes: 1 addition & 6 deletions src/app/nodetool/qgsmaptoolnodetool.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ class QgsMapToolNodeTool: public QgsMapToolVertexEdit
//! called when map tool is being deactivated
void deactivate();

/**
* Returns closest vertex to given point from selected feature
*/
QgsPoint closestVertex( QgsPoint point );

public slots:
void selectedFeatureDestroyed();

Expand Down Expand Up @@ -132,7 +127,7 @@ class QgsMapToolNodeTool: public QgsMapToolVertexEdit
QgsFeatureId mAnother;

/** stored position of last press down action to count how much vertexes should be moved */
QgsPoint* mLastCoordinates;
QgsPoint mLastCoordinates;

/** closest vertex to click */
QgsPoint mClosestVertex;
Expand Down
5 changes: 4 additions & 1 deletion src/core/qgis.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ const QString GEOWKT =
* @note deprecated in 1.8 due to violation of coding conventions (globals
* should be in all caps).
*/
Q_DECL_DEPRECATED const QString GEOWkt = GEOWKT;
#ifndef _MSC_VER
Q_DECL_DEPRECATED
#endif
const QString GEOWkt = GEOWKT;
/** PROJ4 string that represents a geographic coord sys */
const QString GEOPROJ4 = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
/** Magic number for a geographic coord sys in POSTGIS SRID */
Expand Down
108 changes: 80 additions & 28 deletions src/core/qgsgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,12 +578,12 @@ void QgsGeometry::fromWkb( unsigned char * wkb, size_t length )
mDirtyGeos = true;
}

unsigned char * QgsGeometry::asWkb()
unsigned char * QgsGeometry::asWkb( QGis::GeometryType requestedType )
{
if ( mDirtyWkb )
if ( mDirtyWkb || (requestedType!=QGis::UnknownGeometry && requestedType!=type()) )
{
// convert from GEOS
exportGeosToWkb();
exportGeosToWkb( requestedType );
}

return mGeometry;
Expand Down Expand Up @@ -4725,7 +4725,7 @@ bool QgsGeometry::exportWkbToGeos()
return true;
}

bool QgsGeometry::exportGeosToWkb()
bool QgsGeometry::exportGeosToWkb( QGis::GeometryType geomType )
{
//QgsDebugMsg("entered.");
if ( !mDirtyWkb )
Expand All @@ -4751,7 +4751,27 @@ bool QgsGeometry::exportGeosToWkb()
// set up byteOrder
char byteOrder = QgsApplication::endian();

switch ( GEOSGeomTypeId( mGeos ) )
int type = GEOSGeomTypeId( mGeos );

if( type == GEOS_GEOMETRYCOLLECTION )
{
switch( geomType )
{
case QGis::Point:
type = GEOS_MULTIPOINT;
break;
case QGis::Line:
type = GEOS_MULTILINESTRING;
break;
case QGis::Polygon:
type = GEOS_MULTIPOLYGON;
break;
default:
break;
}
}

switch ( type )
{
case GEOS_POINT: // a point
{
Expand Down Expand Up @@ -4923,13 +4943,25 @@ bool QgsGeometry::exportGeosToWkb()

case GEOS_MULTIPOINT: // a collection of points
{
QList<const GEOSGeometry *> points;

// determine size of geometry
int geometrySize = 1 + 2 * sizeof( int );
for ( int i = 0; i < GEOSGetNumGeometries( mGeos ); i++ )
{
const GEOSGeometry *point = GEOSGetGeometryN( mGeos, i );
if( GEOSGeomTypeId( point ) != GEOS_POINT )
continue;
points << point;
geometrySize += 1 + sizeof( int ) + 2 * sizeof( double );
}

if ( points.size() == 0 )
{
QgsMessageLog::logMessage( "Empty multipolygon skipped." );
return false;
}

mGeometry = new unsigned char[geometrySize];
mGeometrySize = geometrySize;
int wkbPosition = 0; //current position in the byte array
Expand All @@ -4939,24 +4971,21 @@ bool QgsGeometry::exportGeosToWkb()
int wkbtype = QGis::WKBMultiPoint;
memcpy( &mGeometry[wkbPosition], &wkbtype, sizeof( int ) );
wkbPosition += sizeof( int );
int numPoints = GEOSGetNumGeometries( mGeos );
int numPoints = points.size();
memcpy( &mGeometry[wkbPosition], &numPoints, sizeof( int ) );
wkbPosition += sizeof( int );

int pointType = QGis::WKBPoint;
const GEOSGeometry *currentPoint = 0;

for ( int i = 0; i < GEOSGetNumGeometries( mGeos ); i++ )
foreach( const GEOSGeometry *point, points )
{
//copy endian and point type
memcpy( &mGeometry[wkbPosition], &byteOrder, 1 );
wkbPosition += 1;
memcpy( &mGeometry[wkbPosition], &pointType, sizeof( int ) );
wkbPosition += sizeof( int );

currentPoint = GEOSGetGeometryN( mGeos, i );

const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq( currentPoint );
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq( point );

GEOSCoordSeq_getX( cs, 0, ( double* )&mGeometry[wkbPosition] );
wkbPosition += sizeof( double );
Expand All @@ -4969,12 +4998,25 @@ bool QgsGeometry::exportGeosToWkb()

case GEOS_MULTILINESTRING: // a collection of linestrings
{
QList<const GEOSGeometry *> linestrings;

// determine size of geometry
int geometrySize = 1 + 2 * sizeof( int );
for ( int i = 0; i < GEOSGetNumGeometries( mGeos ); i++ )
{
const GEOSGeometry *linestring = GEOSGetGeometryN( mGeos, i );
if( GEOSGeomTypeId( linestring ) != GEOS_LINESTRING )
continue;

linestrings << linestring;
geometrySize += 1 + 2 * sizeof( int );
geometrySize += getNumGeosPoints( GEOSGetGeometryN( mGeos, i ) ) * 2 * sizeof( double );
geometrySize += getNumGeosPoints( linestring ) * 2 * sizeof( double );
}

if ( linestrings.size() == 0 )
{
QgsMessageLog::logMessage( "Empty multilinestring skipped." );
return false;
}

mGeometry = new unsigned char[geometrySize];
Expand All @@ -4986,7 +5028,7 @@ bool QgsGeometry::exportGeosToWkb()
int wkbtype = QGis::WKBMultiLineString;
memcpy( &mGeometry[wkbPosition], &wkbtype, sizeof( int ) );
wkbPosition += sizeof( int );
int numLines = GEOSGetNumGeometries( mGeos );
int numLines = linestrings.size();
memcpy( &mGeometry[wkbPosition], &numLines, sizeof( int ) );
wkbPosition += sizeof( int );

Expand All @@ -4995,15 +5037,15 @@ bool QgsGeometry::exportGeosToWkb()
const GEOSCoordSequence *cs = 0;
unsigned int lineSize;

for ( int i = 0; i < GEOSGetNumGeometries( mGeos ); i++ )
foreach( const GEOSGeometry *linestring, linestrings )
{
//endian and type WKBLineString
memcpy( &mGeometry[wkbPosition], &byteOrder, 1 );
wkbPosition += 1;
memcpy( &mGeometry[wkbPosition], &lineType, sizeof( int ) );
wkbPosition += sizeof( int );

cs = GEOSGeom_getCoordSeq( GEOSGetGeometryN( mGeos, i ) );
cs = GEOSGeom_getCoordSeq( linestring );

//line size
GEOSCoordSeq_getSize( cs, &lineSize );
Expand All @@ -5025,26 +5067,38 @@ bool QgsGeometry::exportGeosToWkb()

case GEOS_MULTIPOLYGON: // a collection of polygons
{
QList<const GEOSGeometry *> polygons;

//first determine size of geometry
int geometrySize = 1 + ( 2 * sizeof( int ) ); //endian, type, number of polygons
for ( int i = 0; i < GEOSGetNumGeometries( mGeos ); i++ )
{
const GEOSGeometry *thePoly = GEOSGetGeometryN( mGeos, i );
const GEOSGeometry *poly = GEOSGetGeometryN( mGeos, i );
if( GEOSGeomTypeId( poly ) != GEOS_POLYGON )
continue;

polygons << poly;
geometrySize += 1 + 2 * sizeof( int ); //endian, type, number of rings
//exterior ring
geometrySize += sizeof( int ); //number of points in exterior ring
const GEOSGeometry *exRing = GEOSGetExteriorRing( thePoly );
const GEOSGeometry *exRing = GEOSGetExteriorRing( poly );
geometrySize += 2 * sizeof( double ) * getNumGeosPoints( exRing );

const GEOSGeometry *intRing = 0;
for ( int j = 0; j < GEOSGetNumInteriorRings( thePoly ); j++ )
for ( int j = 0; j < GEOSGetNumInteriorRings( poly ); j++ )
{
geometrySize += sizeof( int ); //number of points in ring
intRing = GEOSGetInteriorRingN( thePoly, j );
intRing = GEOSGetInteriorRingN( poly, j );
geometrySize += 2 * sizeof( double ) * getNumGeosPoints( intRing );
}
}

if ( polygons.size() == 0 )
{
QgsMessageLog::logMessage( "Empty multipolyon skipped." );
return false;
}

mGeometry = new unsigned char[geometrySize];
mGeometrySize = geometrySize;
int wkbPosition = 0; //current position in the byte array
Expand All @@ -5054,25 +5108,24 @@ bool QgsGeometry::exportGeosToWkb()
int wkbtype = QGis::WKBMultiPolygon;
memcpy( &mGeometry[wkbPosition], &wkbtype, sizeof( int ) );
wkbPosition += sizeof( int );
int numPolygons = GEOSGetNumGeometries( mGeos );
int numPolygons = polygons.size();
memcpy( &mGeometry[wkbPosition], &numPolygons, sizeof( int ) );
wkbPosition += sizeof( int );

//loop over polygons
for ( int i = 0; i < GEOSGetNumGeometries( mGeos ); i++ )
foreach ( const GEOSGeometry *poly, polygons )
{
const GEOSGeometry *thePoly = GEOSGetGeometryN( mGeos, i );
memcpy( &mGeometry[wkbPosition], &byteOrder, 1 );
wkbPosition += 1;
int polygonType = QGis::WKBPolygon;
memcpy( &mGeometry[wkbPosition], &polygonType, sizeof( int ) );
wkbPosition += sizeof( int );
int numRings = GEOSGetNumInteriorRings( thePoly ) + 1;
int numRings = GEOSGetNumInteriorRings( poly ) + 1;
memcpy( &mGeometry[wkbPosition], &numRings, sizeof( int ) );
wkbPosition += sizeof( int );

//exterior ring
const GEOSGeometry *theRing = GEOSGetExteriorRing( thePoly );
const GEOSGeometry *theRing = GEOSGetExteriorRing( poly );
int nPointsInRing = getNumGeosPoints( theRing );
memcpy( &mGeometry[wkbPosition], &nPointsInRing, sizeof( int ) );
wkbPosition += sizeof( int );
Expand All @@ -5087,9 +5140,9 @@ bool QgsGeometry::exportGeosToWkb()
}

//interior rings
for ( int j = 0; j < GEOSGetNumInteriorRings( thePoly ); j++ )
for ( int j = 0; j < GEOSGetNumInteriorRings( poly ); j++ )
{
theRing = GEOSGetInteriorRingN( thePoly, j );
theRing = GEOSGetInteriorRingN( poly, j );
nPointsInRing = getNumGeosPoints( theRing );
memcpy( &mGeometry[wkbPosition], &nPointsInRing, sizeof( int ) );
wkbPosition += sizeof( int );
Expand All @@ -5110,8 +5163,7 @@ bool QgsGeometry::exportGeosToWkb()

case GEOS_GEOMETRYCOLLECTION: // a collection of heterogeneus geometries
{
// TODO
QgsDebugMsg( "geometry collection - not supported" );
QgsMessageLog::logMessage( "Geometry collection skipped." );
break;
} // case GEOS_GEOM::GEOS_GEOMETRYCOLLECTION

Expand Down
6 changes: 3 additions & 3 deletions src/core/qgsgeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class CORE_EXPORT QgsGeometry
Returns the buffer containing this geometry in WKB format.
You may wish to use in conjunction with wkbSize().
*/
unsigned char * asWkb();
unsigned char *asWkb( QGis::GeometryType requestedType = QGis::UnknownGeometry );

/**
Returns the size of the WKB in asWkb().
Expand All @@ -119,7 +119,7 @@ class CORE_EXPORT QgsGeometry

/**Returns a geos geomtry. QgsGeometry keeps ownership, don't delete the returned object!
@note this method was added in version 1.1*/
GEOSGeometry* asGeos();
GEOSGeometry *asGeos();

/** Returns type of wkb (point / linestring / polygon etc.) */
QGis::WkbType wkbType();
Expand Down Expand Up @@ -477,7 +477,7 @@ class CORE_EXPORT QgsGeometry
/** Converts from the GEOS geometry to the WKB geometry.
@return true in case of success and false else
*/
bool exportGeosToWkb();
bool exportGeosToWkb( QGis::GeometryType type = QGis::UnknownGeometry );

/** Insert a new vertex before the given vertex index (first number is index 0)
* in the given GEOS Coordinate Sequence.
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsvectorfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ bool QgsVectorFileWriter::addFeature( QgsFeature& feature )
return false;
}

OGRErr err = OGR_G_ImportFromWkb( mGeom2, geom->asWkb(), geom->wkbSize() );
OGRErr err = OGR_G_ImportFromWkb( mGeom2, geom->asWkb( QGis::Polygon ), geom->wkbSize() );
if ( err != OGRERR_NONE )
{
QgsDebugMsg( QString( "Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
Expand Down