QByteArray QgsCurvePolygon::asWkb() const { int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 ); QVector<QByteArray> wkbForRings; wkbForRings.reserve( 1 + mInteriorRings.size() ); if ( mExteriorRing ) { QByteArray wkb( mExteriorRing->asWkb() ); binarySize += wkb.length(); wkbForRings << wkb; } for ( const QgsCurve *curve : mInteriorRings ) { QByteArray wkb( curve->asWkb() ); binarySize += wkb.length(); wkbForRings << wkb; } QByteArray wkbArray; wkbArray.resize( binarySize ); QgsWkbPtr wkbPtr( wkbArray ); wkbPtr << static_cast<char>( QgsApplication::endian() ); wkbPtr << static_cast<quint32>( wkbType() ); wkbPtr << static_cast<quint32>( wkbForRings.count() ); for ( const QByteArray &wkb : qgis::as_const( wkbForRings ) ) { wkbPtr << wkb; } return wkbArray; }
QByteArray QgsGeometryCollection::asWkb() const { int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 ); QVector<QByteArray> wkbForGeometries; for ( const QgsAbstractGeometry *geom : mGeometries ) { if ( geom ) { QByteArray wkb( geom->asWkb() ); binarySize += wkb.length(); wkbForGeometries << wkb; } } QByteArray wkbArray; wkbArray.resize( binarySize ); QgsWkbPtr wkb( wkbArray ); wkb << static_cast<char>( QgsApplication::endian() ); wkb << static_cast<quint32>( wkbType() ); wkb << static_cast<quint32>( wkbForGeometries.count() ); for ( const QByteArray &wkbForGeometry : qgis::as_const( wkbForGeometries ) ) { wkb << wkbForGeometry; } return wkbArray; }
void object::test<1>() { // POINT(1.234 5.678) std::string wkt("POINT (1.234 5.678)"); std::string wkb("01010000005839B4C876BEF33F83C0CAA145B61640"); test_wkb(wkb, wkt); }
Polygon::Polygon(OGRGeometryH g, const SpatialReference& srs, geos::ErrorHandler& err) : m_srs(srs) , m_ctx(err.ctx) { OGRwkbGeometryType t = OGR_G_GetGeometryType(g); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << "pdal::Polygon cannot construct geometry because " "OGR geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } OGRGeometry *ogr_g = (OGRGeometry*)g; // // Convert the the GDAL geom to WKB in order to avoid the version // context issues with exporting directoly to GEOS. OGRwkbByteOrder bo = GEOS_getWKBByteOrder() == GEOS_WKB_XDR ? wkbXDR : wkbNDR; int wkbSize = ogr_g->WkbSize(); std::vector<unsigned char> wkb(wkbSize); ogr_g->exportToWkb(bo, wkb.data()); m_geom = GEOSGeomFromWKB_buf_r(m_ctx, wkb.data(), wkbSize); prepare(); }
int QgsInterpolator::addVerticesToCache( const QgsGeometry& geom, bool zCoord, double attributeValue ) { if ( geom.isEmpty() ) return 1; bool hasZValue = false; QByteArray wkb( geom.exportToWkb() ); QgsConstWkbPtr currentWkbPtr( wkb ); currentWkbPtr.readHeader(); vertexData theVertex; //the current vertex QgsWkbTypes::Type wkbType = geom.wkbType(); switch ( wkbType ) { case QgsWkbTypes::Point25D: hasZValue = true; //intentional fall-through FALLTHROUGH; case QgsWkbTypes::Point: { currentWkbPtr >> theVertex.x >> theVertex.y; if ( zCoord && hasZValue ) { currentWkbPtr >> theVertex.z; } else { theVertex.z = attributeValue; } mCachedBaseData.push_back( theVertex ); break; }
QByteArray QgsPolygonV2::asWkb() const { int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 ); // Endianness and WkbType is not stored for LinearRings if ( mExteriorRing ) { binarySize += sizeof( quint32 ) + mExteriorRing->numPoints() * ( 2 + mExteriorRing->is3D() + mExteriorRing->isMeasure() ) * sizeof( double ); } for ( const QgsCurve *curve : mInteriorRings ) { binarySize += sizeof( quint32 ) + curve->numPoints() * ( 2 + curve->is3D() + curve->isMeasure() ) * sizeof( double ); } QByteArray wkbArray; wkbArray.resize( binarySize ); QgsWkbPtr wkb( wkbArray ); wkb << static_cast<char>( QgsApplication::endian() ); wkb << static_cast<quint32>( wkbType() ); wkb << static_cast<quint32>( ( nullptr != mExteriorRing ) + mInteriorRings.size() ); if ( mExteriorRing ) { QgsPointSequence pts; mExteriorRing->points( pts ); QgsGeometryUtils::pointsToWKB( wkb, pts, mExteriorRing->is3D(), mExteriorRing->isMeasure() ); } for ( const QgsCurve *curve : mInteriorRings ) { QgsPointSequence pts; curve->points( pts ); QgsGeometryUtils::pointsToWKB( wkb, pts, curve->is3D(), curve->isMeasure() ); } return wkbArray; }
QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom ) { if ( lineGeom.isEmpty() ) { return QgsGeometry(); } QgsMultiPolyline resultGeom; //need to go with WKB and z coordinate until QgsGeometry supports M values QByteArray wkb( lineGeom.exportToWkb() ); QgsConstWkbPtr wkbPtr( wkb ); wkbPtr.readHeader(); QgsWkbTypes::Type wkbType = lineGeom.wkbType(); if ( wkbType != QgsWkbTypes::LineString25D && wkbType != QgsWkbTypes::MultiLineString25D ) { return QgsGeometry(); } if ( wkbType == QgsWkbTypes::LineString25D ) { locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } else if ( wkbType == QgsWkbTypes::MultiLineString25D ) { int nLines; wkbPtr >> nLines; for ( int i = 0; i < nLines; ++i ) { wkbPtr.readHeader(); wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } }
unsigned char* QgsLineStringV2::asWkb( int& binarySize ) const { binarySize = wkbSize(); unsigned char* geomPtr = new unsigned char[binarySize]; QgsWkbPtr wkb( geomPtr ); wkb << static_cast<char>( QgsApplication::endian() ); wkb << static_cast<quint32>( wkbType() ); QList<QgsPointV2> pts; points( pts ); QgsGeometryUtils::pointsToWKB( wkb, pts, is3D(), isMeasure() ); return geomPtr; }
wkb_buffer_ptr to_polygon_wkb( GeometryType const& g, wkbByteOrder byte_order) { unsigned num_points = g.size(); assert(num_points > 1); typedef std::pair<double,double> point_type; typedef std::vector<point_type> linear_ring; boost::ptr_vector<linear_ring> rings; double x = 0; double y = 0; std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings for (unsigned i=0; i< num_points; ++i) { unsigned command = g.vertex(i,&x,&y); if (command == SEG_MOVETO) { rings.push_back(new linear_ring); // start new loop rings.back().push_back(std::make_pair(x,y)); size += 4; // num_points size += 2 * 8; // point } else if (command == SEG_LINETO) { rings.back().push_back(std::make_pair(x,y)); size += 2 * 8; // point } } unsigned num_rings = rings.size(); wkb_buffer_ptr wkb(new wkb_buffer(size)); wkb_stream ss(wkb->buffer(), wkb->size()); ss.write(reinterpret_cast<char*>(&byte_order),1); int type = static_cast<int>(mapnik::geometry_type::types::Polygon); write(ss,type,4,byte_order); write(ss,num_rings,4,byte_order); for ( linear_ring const& ring : rings) { unsigned num_ring_points = ring.size(); write(ss,num_ring_points,4,byte_order); for ( point_type const& pt : ring) { write(ss,pt.first,8,byte_order); write(ss,pt.second,8,byte_order); } } assert(ss.good()); return std::move(wkb); }
QByteArray QgsCircularString::asWkb() const { int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 ); binarySize += numPoints() * ( 2 + is3D() + isMeasure() ) * sizeof( double ); QByteArray wkbArray; wkbArray.resize( binarySize ); QgsWkbPtr wkb( wkbArray ); wkb << static_cast<char>( QgsApplication::endian() ); wkb << static_cast<quint32>( wkbType() ); QgsPointSequence pts; points( pts ); QgsGeometryUtils::pointsToWKB( wkb, pts, is3D(), isMeasure() ); return wkbArray; }
wkb_buffer_ptr to_point_wkb( GeometryType const& g, wkbByteOrder byte_order) { assert(g.size() == 1); std::size_t size = 1 + 4 + 8*2 ; // byteOrder + wkbType + Point wkb_buffer_ptr wkb(new wkb_buffer(size)); wkb_stream ss(wkb->buffer(), wkb->size()); ss.write(reinterpret_cast<char*>(&byte_order),1); int type = static_cast<int>(mapnik::geometry_type::types::Point); write(ss,type,4,byte_order); double x = 0; double y = 0; g.vertex(0,&x,&y); write(ss,x,8,byte_order); write(ss,y,8,byte_order); assert(ss.good()); return std::move(wkb); }
unsigned char* QgsGeometryCollectionV2::asWkb( int& binarySize ) const { binarySize = wkbSize(); unsigned char* geomPtr = new unsigned char[binarySize]; QgsWkbPtr wkb( geomPtr ); wkb << static_cast<char>( QgsApplication::endian() ); wkb << static_cast<quint32>( wkbType() ); wkb << static_cast<quint32>( mGeometries.size() ); Q_FOREACH ( const QgsAbstractGeometryV2 *geom, mGeometries ) { int geomWkbLen = 0; if ( geom ) { unsigned char* geomWkb = geom->asWkb( geomWkbLen ); memcpy( wkb, geomWkb, geomWkbLen ); wkb += geomWkbLen; delete[] geomWkb; } }
wkb_buffer_ptr to_line_string_wkb( GeometryType const& g, wkbByteOrder byte_order) { unsigned num_points = g.size(); assert(num_points > 1); std::size_t size = 1 + 4 + 4 + 8*2*num_points ; // byteOrder + wkbType + numPoints + Point*numPoints wkb_buffer_ptr wkb(new wkb_buffer(size)); wkb_stream ss(wkb->buffer(), wkb->size()); ss.write(reinterpret_cast<char*>(&byte_order),1); int type = static_cast<int>(mapnik::geometry_type::types::LineString); write(ss,type,4,byte_order); write(ss,num_points,4,byte_order); double x = 0; double y = 0; for (unsigned i=0; i< num_points; ++i) { g.vertex(i,&x,&y); write(ss,x,8,byte_order); write(ss,y,8,byte_order); } assert(ss.good()); return std::move(wkb); }
// // Convert a QgsGeometry into a SpatiaLite geometry BLOB void qgsGeometryToSpatialiteBlob( const QgsGeometry &geom, int32_t srid, char *&blob, int &size ) { const int header_len = SpatialiteBlobHeader::LENGTH; QByteArray wkb( geom.exportToWkb() ); const int wkb_size = wkb.length(); size = header_len + wkb_size; blob = new char[size]; char *p = blob; // write the header SpatialiteBlobHeader pHeader; QgsRectangle bbox = const_cast<QgsGeometry &>( geom ).boundingBox(); // boundingBox should be const pHeader.srid = srid; pHeader.mbrMinX = bbox.xMinimum(); pHeader.mbrMinY = bbox.yMinimum(); pHeader.mbrMaxX = bbox.xMaximum(); pHeader.mbrMaxY = bbox.yMaximum(); pHeader.writeTo( blob ); p += header_len; // wkb of the geometry is // name size value // endianness 1 01 // type 4 int // blob geometry = header + wkb[1:] + 'end' // copy wkb memcpy( p, wkb.constData() + 1, wkb_size - 1 ); p += wkb_size - 1; // end marker *p = '\xFE'; }
QByteArray QgsCompoundCurve::asWkb() const { int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 ); QVector<QByteArray> wkbForCurves; for ( const QgsCurve *curve : mCurves ) { QByteArray wkbForCurve = curve->asWkb(); binarySize += wkbForCurve.length(); wkbForCurves << wkbForCurve; } QByteArray wkbArray; wkbArray.resize( binarySize ); QgsWkbPtr wkb( wkbArray ); wkb << static_cast<char>( QgsApplication::endian() ); wkb << static_cast<quint32>( wkbType() ); wkb << static_cast<quint32>( mCurves.size() ); for ( const QByteArray &wkbForCurve : qgis::as_const( wkbForCurves ) ) { wkb << wkbForCurve; } return wkbArray; }
bool QgsGPXProvider::addFeature( QgsFeature &f ) { QByteArray wkb( f.geometry().exportToWkb() ); const char *geo = wkb.constData(); QgsWkbTypes::Type wkbType = f.geometry().wkbType(); bool success = false; QgsGPSObject *obj = nullptr; QgsAttributes attrs = f.attributes(); QgsAttributeMap::const_iterator it; // is it a waypoint? if ( mFeatureType == WaypointType && geo && wkbType == QgsWkbTypes::Point ) { // add geometry QgsWaypoint wpt; std::memcpy( &wpt.lon, geo + 5, sizeof( double ) ); std::memcpy( &wpt.lat, geo + 13, sizeof( double ) ); // add waypoint-specific attributes for ( int i = 0; i < attrs.count(); ++i ) { if ( indexToAttr.at( i ) == EleAttr ) { bool eleIsOK; double ele = attrs.at( i ).toDouble( &eleIsOK ); if ( eleIsOK ) wpt.ele = ele; } else if ( indexToAttr.at( i ) == SymAttr ) { wpt.sym = attrs.at( i ).toString(); } } QgsGPSData::WaypointIterator iter = data->addWaypoint( wpt ); success = true; obj = &( *iter ); } // is it a route? if ( mFeatureType == RouteType && geo && wkbType == QgsWkbTypes::LineString ) { QgsRoute rte; // reset bounds rte.xMin = std::numeric_limits<double>::max(); rte.xMax = -std::numeric_limits<double>::max(); rte.yMin = std::numeric_limits<double>::max(); rte.yMax = -std::numeric_limits<double>::max(); // add geometry int nPoints; std::memcpy( &nPoints, geo + 5, 4 ); for ( int i = 0; i < nPoints; ++i ) { double lat, lon; std::memcpy( &lon, geo + 9 + 16 * i, sizeof( double ) ); std::memcpy( &lat, geo + 9 + 16 * i + 8, sizeof( double ) ); QgsRoutepoint rtept; rtept.lat = lat; rtept.lon = lon; rte.points.push_back( rtept ); rte.xMin = rte.xMin < lon ? rte.xMin : lon; rte.xMax = rte.xMax > lon ? rte.xMax : lon; rte.yMin = rte.yMin < lat ? rte.yMin : lat; rte.yMax = rte.yMax > lat ? rte.yMax : lat; } // add route-specific attributes for ( int i = 0; i < attrs.count(); ++i ) { if ( indexToAttr.at( i ) == NumAttr ) { bool numIsOK; long num = attrs.at( i ).toInt( &numIsOK ); if ( numIsOK ) rte.number = num; } } QgsGPSData::RouteIterator iter = data->addRoute( rte ); success = true; obj = &( *iter ); } // is it a track? if ( mFeatureType == TrackType && geo && wkbType == QgsWkbTypes::LineString ) { QgsTrack trk; QgsTrackSegment trkseg; // reset bounds trk.xMin = std::numeric_limits<double>::max(); trk.xMax = -std::numeric_limits<double>::max(); trk.yMin = std::numeric_limits<double>::max(); trk.yMax = -std::numeric_limits<double>::max(); // add geometry int nPoints; std::memcpy( &nPoints, geo + 5, 4 ); for ( int i = 0; i < nPoints; ++i ) { double lat, lon; std::memcpy( &lon, geo + 9 + 16 * i, sizeof( double ) ); std::memcpy( &lat, geo + 9 + 16 * i + 8, sizeof( double ) ); QgsTrackpoint trkpt; trkpt.lat = lat; trkpt.lon = lon; trkseg.points.push_back( trkpt ); trk.xMin = trk.xMin < lon ? trk.xMin : lon; trk.xMax = trk.xMax > lon ? trk.xMax : lon; trk.yMin = trk.yMin < lat ? trk.yMin : lat; trk.yMax = trk.yMax > lat ? trk.yMax : lat; } // add track-specific attributes for ( int i = 0; i < attrs.count(); ++i ) { if ( indexToAttr.at( i ) == NumAttr ) { bool numIsOK; long num = attrs.at( i ).toInt( &numIsOK ); if ( numIsOK ) trk.number = num; } } trk.segments.push_back( trkseg ); QgsGPSData::TrackIterator iter = data->addTrack( trk ); success = true; obj = &( *iter ); } // add common attributes if ( obj ) { for ( int i = 0; i < attrs.count(); ++i ) { switch ( indexToAttr.at( i ) ) { case NameAttr: obj->name = attrs.at( i ).toString(); break; case CmtAttr: obj->cmt = attrs.at( i ).toString(); break; case DscAttr: obj->desc = attrs.at( i ).toString(); break; case SrcAttr: obj->src = attrs.at( i ).toString(); break; case URLAttr: obj->url = attrs.at( i ).toString(); break; case URLNameAttr: obj->urlname = attrs.at( i ).toString(); break; } } } return success; }
void QgsOSMDatabase::exportSpatiaLiteNodes( const QString &tableName, const QStringList &tagKeys, const QStringList ¬NullTagKeys ) { QString sqlInsertPoint = QStringLiteral( "INSERT INTO %1 VALUES (?" ).arg( quotedIdentifier( tableName ) ); for ( int i = 0; i < tagKeys.count(); ++i ) sqlInsertPoint += QStringLiteral( ",?" ); sqlInsertPoint += QLatin1String( ", GeomFromWKB(?, 4326))" ); sqlite3_stmt *stmtInsert = nullptr; if ( sqlite3_prepare_v2( mDatabase, sqlInsertPoint.toUtf8().constData(), -1, &stmtInsert, nullptr ) != SQLITE_OK ) { mError = QStringLiteral( "Prepare SELECT FROM nodes failed." ); return; } QgsOSMNodeIterator nodes = listNodes(); QgsOSMNode n; while ( ( n = nodes.next() ).isValid() ) { QgsOSMTags t = tags( false, n.id() ); // skip untagged nodes: probably they form a part of ways if ( t.count() == 0 ) continue; //check not null tags bool skipNull = false; for ( int i = 0; i < notNullTagKeys.count() && !skipNull; ++i ) if ( !t.contains( notNullTagKeys[i] ) ) skipNull = true; if ( skipNull ) continue; QgsGeometry geom = QgsGeometry::fromPoint( n.point() ); int col = 0; sqlite3_bind_int64( stmtInsert, ++col, n.id() ); // tags for ( int i = 0; i < tagKeys.count(); ++i ) { if ( t.contains( tagKeys[i] ) ) sqlite3_bind_text( stmtInsert, ++col, t.value( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT ); else sqlite3_bind_null( stmtInsert, ++col ); } QByteArray wkb( geom.exportToWkb() ); sqlite3_bind_blob( stmtInsert, ++col, wkb.constData(), wkb.length(), SQLITE_STATIC ); int insertRes = sqlite3_step( stmtInsert ); if ( insertRes != SQLITE_DONE ) { mError = QStringLiteral( "Error inserting node %1 [%2]" ).arg( n.id() ).arg( insertRes ); break; } sqlite3_reset( stmtInsert ); sqlite3_clear_bindings( stmtInsert ); } sqlite3_finalize( stmtInsert ); }
int QgsTINInterpolator::insertData( QgsFeature* f, bool zCoord, int attr, InputType type ) { if ( !f ) { return 1; } QgsGeometry g = f->geometry(); { if ( g.isNull() ) { return 2; } } //check attribute value double attributeValue = 0; bool attributeConversionOk = false; if ( !zCoord ) { QVariant attributeVariant = f->attribute( attr ); if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value) { return 3; } attributeValue = attributeVariant.toDouble( &attributeConversionOk ); if ( !attributeConversionOk || qIsNaN( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation { return 4; } } //parse WKB. It is ugly, but we cannot use the methods with QgsPoint because they don't contain z-values for 25D types bool hasZValue = false; double x, y, z; QByteArray wkb( g.exportToWkb() ); QgsConstWkbPtr currentWkbPtr( wkb ); currentWkbPtr.readHeader(); //maybe a structure or break line Line3D* line = nullptr; QgsWkbTypes::Type wkbType = g.wkbType(); switch ( wkbType ) { case QgsWkbTypes::Point25D: hasZValue = true; FALLTHROUGH; case QgsWkbTypes::Point: { currentWkbPtr >> x >> y; if ( zCoord && hasZValue ) { currentWkbPtr >> z; } else { z = attributeValue; } Point3D* thePoint = new Point3D( x, y, z ); if ( mTriangulation->addPoint( thePoint ) == -100 ) { return -1; } break; }
void QgsOSMDatabase::exportSpatiaLiteWays( bool closed, const QString &tableName, const QStringList &tagKeys, const QStringList ¬NullTagKeys ) { Q_UNUSED( tagKeys ); QString sqlInsertLine = QStringLiteral( "INSERT INTO %1 VALUES (?" ).arg( quotedIdentifier( tableName ) ); for ( int i = 0; i < tagKeys.count(); ++i ) sqlInsertLine += QStringLiteral( ",?" ); sqlInsertLine += QLatin1String( ", GeomFromWKB(?, 4326))" ); sqlite3_stmt *stmtInsert = nullptr; if ( sqlite3_prepare_v2( mDatabase, sqlInsertLine.toUtf8().constData(), -1, &stmtInsert, nullptr ) != SQLITE_OK ) { mError = QStringLiteral( "Prepare SELECT FROM ways failed." ); return; } QgsOSMWayIterator ways = listWays(); QgsOSMWay w; while ( ( w = ways.next() ).isValid() ) { QgsOSMTags t = tags( true, w.id() ); QgsPolyline polyline = wayPoints( w.id() ); if ( polyline.count() < 2 ) continue; // invalid way bool isArea = ( polyline.first() == polyline.last() ); // closed way? // filter out closed way that are not areas through tags if ( isArea && ( t.contains( QStringLiteral( "highway" ) ) || t.contains( QStringLiteral( "barrier" ) ) ) ) { // make sure tags that indicate areas are taken into consideration when deciding on a closed way is or isn't an area // and allow for a closed way to be exported both as a polygon and a line in case both area and non-area tags are present if ( ( t.value( QStringLiteral( "area" ) ) != QLatin1String( "yes" ) && !t.contains( QStringLiteral( "amenity" ) ) && !t.contains( QStringLiteral( "landuse" ) ) && !t.contains( QStringLiteral( "building" ) ) && !t.contains( QStringLiteral( "natural" ) ) && !t.contains( QStringLiteral( "leisure" ) ) && !t.contains( QStringLiteral( "aeroway" ) ) ) || !closed ) isArea = false; } if ( closed != isArea ) continue; // skip if it's not what we're looking for //check not null tags bool skipNull = false; for ( int i = 0; i < notNullTagKeys.count() && !skipNull; ++i ) if ( !t.contains( notNullTagKeys[i] ) ) skipNull = true; if ( skipNull ) continue; QgsGeometry geom = closed ? QgsGeometry::fromPolygon( QgsPolygon() << polyline ) : QgsGeometry::fromPolyline( polyline ); int col = 0; sqlite3_bind_int64( stmtInsert, ++col, w.id() ); // tags for ( int i = 0; i < tagKeys.count(); ++i ) { if ( t.contains( tagKeys[i] ) ) sqlite3_bind_text( stmtInsert, ++col, t.value( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT ); else sqlite3_bind_null( stmtInsert, ++col ); } if ( !geom.isNull() ) { QByteArray wkb( geom.exportToWkb() ); sqlite3_bind_blob( stmtInsert, ++col, wkb.constData(), wkb.length(), SQLITE_STATIC ); } else sqlite3_bind_null( stmtInsert, ++col ); int insertRes = sqlite3_step( stmtInsert ); if ( insertRes != SQLITE_DONE ) { mError = QStringLiteral( "Error inserting way %1 [%2]" ).arg( w.id() ).arg( insertRes ); break; } sqlite3_reset( stmtInsert ); sqlite3_clear_bindings( stmtInsert ); } sqlite3_finalize( stmtInsert ); }