Skip to content

Commit 07e3065

Browse files
author
mhugent
committed
Precise intersection test in ogr provider, made geos export of QgsGeometry 25D aware, fixed a memory leak
git-svn-id: http://svn.osgeo.org/qgis/trunk@6741 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 661fd9b commit 07e3065

File tree

3 files changed

+114
-99
lines changed

3 files changed

+114
-99
lines changed

src/core/qgsgeometry.cpp

+70-25
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ void QgsGeometry::setWkbAndOwnership(unsigned char * wkb, size_t length)
157157
mDirtyWkb = FALSE;
158158
mDirtyGeos = TRUE;
159159
mDirtyWkt = TRUE;
160-
161160
}
162161

163162
unsigned char * QgsGeometry::wkbBuffer() const
@@ -2190,7 +2189,7 @@ bool QgsGeometry::fast_intersects(const QgsRect& r) const
21902189
rectwkt+="))";
21912190
GEOS_GEOM::GeometryFactory *gf = new GEOS_GEOM::GeometryFactory();
21922191
GEOS_IO::WKTReader *wktReader = new GEOS_IO::WKTReader(gf);
2193-
GEOS_GEOM::Geometry *geosRect = wktReader->read( qstrdup(rectwkt) );
2192+
GEOS_GEOM::Geometry *geosRect = wktReader->read(rectwkt.toLocal8Bit().data());
21942193

21952194
try // geos might throw exception on error
21962195
{
@@ -2209,7 +2208,6 @@ bool QgsGeometry::fast_intersects(const QgsRect& r) const
22092208
QgsLogger::warning("GEOS: " + error);
22102209
}
22112210

2212-
delete geosGeom;
22132211
delete geosRect;
22142212
delete gf;
22152213
delete wktReader;
@@ -2501,8 +2499,6 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
25012499
{
25022500
// No need to convert again
25032501
return mGeos;
2504-
2505-
// TODO: make mGeos useful - assign to it and clear mDirty before we return out of this function
25062502
}
25072503

25082504
if(!mGeometry)
@@ -2522,20 +2518,27 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
25222518
unsigned char *ptr;
25232519
char lsb;
25242520
QgsPoint pt;
2525-
int wkbtype;
2521+
QGis::WKBTYPE wkbtype;
2522+
bool hasZValue = false;
25262523

2527-
wkbtype = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4];
2524+
//wkbtype = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4];//MH: this does not work for 2.5D types
2525+
wkbtype = wkbType();
25282526
switch(wkbtype)
2529-
{
2530-
case QGis::WKBPoint:
2527+
{
2528+
case QGis::WKBPoint25D:
2529+
case QGis::WKBPoint:
25312530
{
25322531
x = (double *) (mGeometry + 5);
25332532
y = (double *) (mGeometry + 5 + sizeof(double));
25342533

2535-
mDirtyGeos = FALSE;
2536-
return geosGeometryFactory->createPoint(GEOS_GEOM::Coordinate(*x,*y));
2534+
mDirtyGeos = FALSE;
2535+
mGeos = geosGeometryFactory->createPoint(GEOS_GEOM::Coordinate(*x,*y));
2536+
mDirtyGeos = FALSE;
2537+
return mGeos;
25372538
}
2538-
case QGis::WKBMultiPoint:
2539+
case QGis::WKBMultiPoint25D:
2540+
hasZValue = true;
2541+
case QGis::WKBMultiPoint:
25392542
{
25402543
std::vector<GEOS_GEOM::Geometry*>* points=new std::vector<GEOS_GEOM::Geometry*>;
25412544
ptr = mGeometry + 5;
@@ -2549,10 +2552,19 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
25492552
y = (double *) ptr;
25502553
ptr += sizeof(double);
25512554
points->push_back(geosGeometryFactory->createPoint(GEOS_GEOM::Coordinate(*x,*y)));
2555+
if(hasZValue)
2556+
{
2557+
ptr += sizeof(double);
2558+
}
25522559
}
2553-
return geosGeometryFactory->createMultiPoint(points);
2560+
delete mGeos;
2561+
mGeos = geosGeometryFactory->createMultiPoint(points);
2562+
mDirtyGeos = FALSE;
2563+
return mGeos;
25542564
}
2555-
case QGis::WKBLineString:
2565+
case QGis::WKBLineString25D:
2566+
hasZValue = true;
2567+
case QGis::WKBLineString:
25562568
{
25572569
QgsDebugMsg("QgsGeometry::geosGeometry: Linestring found");
25582570

@@ -2567,10 +2579,19 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
25672579
y = (double *) ptr;
25682580
ptr += sizeof(double);
25692581
sequence->add(GEOS_GEOM::Coordinate(*x,*y));
2582+
if(hasZValue)
2583+
{
2584+
ptr += sizeof(double);
2585+
}
25702586
}
2571-
return geosGeometryFactory->createLineString(sequence);
2587+
delete mGeos;
2588+
mGeos = geosGeometryFactory->createLineString(sequence);
2589+
mDirtyGeos = FALSE;
2590+
return mGeos;
25722591
}
2573-
case QGis::WKBMultiLineString:
2592+
case QGis::WKBMultiLineString25D:
2593+
hasZValue = true;
2594+
case QGis::WKBMultiLineString:
25742595
{
25752596
std::vector<GEOS_GEOM::Geometry*>* lines=new std::vector<GEOS_GEOM::Geometry*>;
25762597
numLineStrings = (int) (mGeometry[5]);
@@ -2590,14 +2611,23 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
25902611
y = (double *) ptr;
25912612
ptr += sizeof(double);
25922613
sequence->add(GEOS_GEOM::Coordinate(*x,*y));
2614+
if(hasZValue)
2615+
{
2616+
ptr += sizeof(double);
2617+
}
25932618
}
25942619
lines->push_back(geosGeometryFactory->createLineString(sequence));
25952620
}
2596-
return geosGeometryFactory->createMultiLineString(lines);
2621+
delete mGeos;
2622+
mGeos = geosGeometryFactory->createMultiLineString(lines);
2623+
mDirtyGeos = FALSE;
2624+
return mGeos;
25972625
}
2598-
case QGis::WKBPolygon:
2626+
case QGis::WKBPolygon25D:
2627+
hasZValue = true;
2628+
case QGis::WKBPolygon:
25992629
{
2600-
QgsDebugMsg("Polygon found");
2630+
QgsDebugMsg("Polygon found");
26012631

26022632
// get number of rings in the polygon
26032633
numRings = (int *) (mGeometry + 1 + sizeof(int));
@@ -2623,6 +2653,10 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
26232653
y = (double *) ptr;
26242654
ptr += sizeof(double);
26252655
sequence->add(GEOS_GEOM::Coordinate(*x,*y));
2656+
if(hasZValue)
2657+
{
2658+
ptr += sizeof(double);
2659+
}
26262660
}
26272661
GEOS_GEOM::LinearRing* ring=geosGeometryFactory->createLinearRing(sequence);
26282662
if(idx==0)
@@ -2634,10 +2668,14 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
26342668
inner->push_back(ring);
26352669
}
26362670
}
2637-
return geosGeometryFactory->createPolygon(outer,inner);
2671+
delete mGeos;
2672+
mGeos = geosGeometryFactory->createPolygon(outer,inner);
2673+
mDirtyGeos = FALSE;
2674+
return mGeos;
26382675
}
2639-
2640-
case QGis::WKBMultiPolygon:
2676+
case QGis::WKBMultiPolygon25D:
2677+
hasZValue = true;
2678+
case QGis::WKBMultiPolygon:
26412679
{
26422680
QgsDebugMsg("Multipolygon found");
26432681

@@ -2675,6 +2713,10 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
26752713
y = (double *) ptr;
26762714
ptr += sizeof(double);
26772715
sequence->add(GEOS_GEOM::Coordinate(*x,*y));
2716+
if(hasZValue)
2717+
{
2718+
ptr += sizeof(double);
2719+
}
26782720
}
26792721
GEOS_GEOM::LinearRing* ring=geosGeometryFactory->createLinearRing(sequence);
26802722
if(idx==0)
@@ -2689,10 +2731,13 @@ GEOS_GEOM::Geometry* QgsGeometry::geosGeometry() const
26892731

26902732
polygons->push_back(geosGeometryFactory->createPolygon(outer,inner));
26912733
}
2692-
return (geosGeometryFactory->createMultiPolygon(polygons));
2734+
delete mGeos;
2735+
mGeos = (geosGeometryFactory->createMultiPolygon(polygons));
2736+
mDirtyGeos = false;
2737+
return mGeos;
26932738
}
2694-
default:
2695-
return 0;
2739+
default:
2740+
return 0;
26962741
}
26972742

26982743
}

src/core/qgsgeometry.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ class CORE_EXPORT QgsGeometry {
237237
/** Test for containment of a point (uses GEOS) */
238238
bool contains(QgsPoint* p) const;
239239

240-
/**Creates a geos geometry from this features geometry. Note, that the returned object needs to be deleted*/
240+
/**Returns a geos geometry from the features geometry. Note that object pointer is cached (mGoes) and
241+
should _not_ be deleted by the calling method*/
241242
GEOS_GEOM::Geometry* geosGeometry() const;
242243

243244

src/providers/ogr/qgsogrprovider.cpp

+42-73
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ QgsOgrProvider::~QgsOgrProvider()
175175
extent_ = 0;
176176
delete geometryFactory;
177177
delete wktReader;
178+
delete mSelectionRectangle;
178179
}
179180

180181
void QgsOgrProvider::setEncoding(const QString& e)
@@ -245,90 +246,58 @@ bool QgsOgrProvider::getNextFeature(QgsFeature& feature,
245246
}
246247

247248
OGRFeature *fet;
249+
QgsRect selectionRect;
248250

249-
// skip features without geometry
250251
while ((fet = ogrLayer->GetNextFeature()) != NULL)
251252
{
253+
// skip features without geometry
252254
if (fet->GetGeometryRef() != NULL || mFetchFeaturesWithoutGeom)
253255
{
256+
OGRFeatureDefn * featureDefinition = fet->GetDefnRef();
257+
QString featureTypeName = featureDefinition ? QString(featureDefinition->GetName()) : QString("");
258+
feature.setFeatureId(fet->GetFID());
259+
feature.setTypeName(featureTypeName);
260+
261+
if (fetchGeometry)
262+
{
263+
OGRGeometry *geom = fet->GetGeometryRef();
264+
265+
// get the wkb representation
266+
unsigned char *wkb = new unsigned char[geom->WkbSize()];
267+
geom->exportToWkb((OGRwkbByteOrder) QgsApplication::endian(), wkb);
268+
269+
feature.setGeometryAndOwnership(wkb, geom->WkbSize());
270+
271+
if(mUseIntersect)
272+
{
273+
//precise test for intersection with search rectangle
274+
//first make QgsRect from OGRPolygon
275+
OGREnvelope env;
276+
mSelectionRectangle->getEnvelope(&env);
277+
if(env.IsInit()) //if envelope is invalid, skip the precise intersection test
278+
{
279+
selectionRect.set(env.MinX, env.MinY, env.MaxX, env.MaxY);
280+
if(!feature.geometry()->fast_intersects(selectionRect))
281+
{
282+
delete fet;
283+
continue;
284+
}
285+
}
286+
}
287+
}
288+
289+
for(QgsAttributeList::iterator it = fetchAttributes.begin(); it != fetchAttributes.end(); ++it)
290+
{
291+
getFeatureAttribute(fet,feature,*it);
292+
}
293+
254294
break;
255295
}
256-
257-
delete fet;
258-
259-
/* TODO: [MD]
260-
if (mUseIntersect)
261-
{
262-
GEOS_GEOM::Geometry *geosGeom = 0;
263-
geosGeom = f->geometry()->geosGeometry();
264-
assert(geosGeom != 0);
265-
266-
char *sWkt = new char[2 * mSelectionRectangle->WkbSize()];
267-
mSelectionRectangle->exportToWkt(&sWkt);
268-
GEOS_GEOM::Geometry *geosRect = wktReader->read(sWkt);
269-
assert(geosRect != 0);
270-
try // geos might throw exception on error
271-
{
272-
if(geosGeom->intersects(geosRect))
273-
{
274-
returnval=true;
275-
}
276-
}
277-
catch (GEOS_UTIL::TopologyException* e)
278-
{
279-
#if GEOS_VERSION_MAJOR < 3
280-
QString error = e->toString().c_str();
281-
#else
282-
QString error = e->what();
283-
#endif
284-
QString error = e->toString().c_str();
285-
QgsLogger::warning("GEOS: " + error);
286-
}
287-
288-
if (returnval)
289-
{
290-
QgsDebugMsg("intersection found");
291-
delete[] sWkt;
292-
delete geosGeom;
293-
break;
294-
}
295-
else
296-
{
297-
QgsDebugMsg("no intersection found");
298-
delete[] sWkt;
299-
delete geosGeom;
300-
delete f;
301-
f=0;
302-
}
303-
}*/
304296
}
305-
297+
306298
if (fet)
307299
{
308-
// get type name
309-
OGRFeatureDefn * featureDefinition = fet->GetDefnRef();
310-
QString featureTypeName =
311-
featureDefinition ? QString(featureDefinition->GetName()) : QString("");
312-
313-
feature = QgsFeature(fet->GetFID(), featureTypeName);
314-
315-
if (fetchGeometry)
316-
{
317-
OGRGeometry *geom = fet->GetGeometryRef();
318-
319-
// get the wkb representation
320-
unsigned char *wkb = new unsigned char[geom->WkbSize()];
321-
geom->exportToWkb((OGRwkbByteOrder) QgsApplication::endian(), wkb);
322-
323-
feature.setGeometryAndOwnership(wkb, geom->WkbSize());
324-
}
325-
326-
for(QgsAttributeList::iterator it = fetchAttributes.begin(); it != fetchAttributes.end(); ++it)
327-
{
328-
getFeatureAttribute(fet,feature,*it);
329-
}
330300
delete fet;
331-
332301
return true;
333302
}
334303
else

0 commit comments

Comments
 (0)