static VALUE method_geometry_equals(VALUE self, VALUE rhs) { VALUE result; RGeo_GeometryData* self_data; const GEOSGeometry* self_geom; const GEOSGeometry* rhs_geom; GEOSContextHandle_t self_context; char val; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); self_geom = self_data->geom; if (self_geom) { rhs_geom = rgeo_get_geos_geometry_safe(rhs); if (rhs_geom) { self_context = self_data->geos_context; // GEOS has a bug where empty geometries are not spatially equal // to each other. Work around this case first. if (GEOSisEmpty_r(self_context, self_geom) == 1 && GEOSisEmpty_r(RGEO_GEOMETRY_DATA_PTR(rhs)->geos_context, rhs_geom) == 1) { result = Qtrue; } else { val = GEOSEquals_r(self_context, self_geom, rhs_geom); if (val == 0) { result = Qfalse; } else if (val == 1) { result = Qtrue; } } } } return result; }
// Find holes of each face static void findFaceHoles( Face **faces, int nfaces ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); // We sort by envelope area so that we know holes are only // after their shells qsort( faces, nfaces, sizeof( Face * ), compare_by_envarea ); for ( int i = 0; i < nfaces; ++i ) { Face *f = faces[i]; int nholes = GEOSGetNumInteriorRings_r( handle, f->geom ); for ( int h = 0; h < nholes; ++h ) { const GEOSGeometry *hole = GEOSGetInteriorRingN_r( handle, f->geom, h ); for ( int j = i + 1; j < nfaces; ++j ) { Face *f2 = faces[j]; if ( f2->parent ) continue; // hole already assigned /* TODO: can be optimized as the ring would have the * same vertices, possibly in different order. * maybe comparing number of points could already be * useful. */ if ( GEOSEquals_r( handle, GEOSGetExteriorRing_r( handle, f2->geom ), hole ) ) { f2->parent = f; break; } } } } }