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