Skip to content

Commit

Permalink
feat: add feature cache to GeoFeatureLayer to ensure signal propagation
Browse files Browse the repository at this point in the history
Previously, signals called on one feature would not be triggered on another feature from the same layer loaded by a different call (e.g. two separate "get_features_near_position" calls) since they were entirely different objects.

Now, the two features are the same object and therefore signals propagate between them.

This should have no effects on thread safety as the underlying GDAL feature was already cached and identical, this just makes the wrapper cached as well.
  • Loading branch information
LandscapeLab Office committed Oct 9, 2024
1 parent 931d3d5 commit bf8029d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/geodata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,15 @@ Vector3 GeoFeatureLayer::get_center() {
}

// Utility function for converting a Processing Library Feature to the appropriate GeoFeature
Ref<GeoFeature> get_specialized_feature(std::shared_ptr<Feature> raw_feature) {
Ref<GeoFeature> GeoFeatureLayer::get_specialized_feature(std::shared_ptr<Feature> raw_feature) {
if (feature_cache.count(raw_feature)) {
return feature_cache[raw_feature];
}

// Not cached -> instantiate and cache

Ref<GeoFeature> new_feature;

// Check which geometry this feature has, and cast it to the according
// specialized class
if (raw_feature->geometry_type == raw_feature->POINT) {
Expand All @@ -156,7 +164,7 @@ Ref<GeoFeature> get_specialized_feature(std::shared_ptr<Feature> raw_feature) {

point->set_gdal_feature(point_feature);

return point;
new_feature = point;
} else if (raw_feature->geometry_type == raw_feature->LINE) {
Ref<GeoLine> line;
line.instantiate();
Expand All @@ -165,7 +173,7 @@ Ref<GeoFeature> get_specialized_feature(std::shared_ptr<Feature> raw_feature) {

line->set_gdal_feature(line_feature);

return line;
new_feature = line;
} else if (raw_feature->geometry_type == raw_feature->POLYGON) {
Ref<GeoPolygon> polygon;
polygon.instantiate();
Expand All @@ -174,16 +182,20 @@ Ref<GeoFeature> get_specialized_feature(std::shared_ptr<Feature> raw_feature) {

polygon->set_gdal_feature(polygon_feature);

return polygon;
new_feature = polygon;
} else {
// Geometry type is NONE or unknown
Ref<GeoFeature> feature;
feature.instantiate();

feature->set_gdal_feature(raw_feature);

return feature;
new_feature = feature;
}

feature_cache[raw_feature] = new_feature;

return new_feature;
}

Ref<GeoFeature> GeoFeatureLayer::get_feature_by_id(int id) {
Expand Down
4 changes: 4 additions & 0 deletions src/geodata.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class EXPORT GeoFeatureLayer : public RefCounted {
/// Note that syntax errors are printed to the console by GDAL.
Array get_features_by_attribute_filter(String filter);

/// Returns the (cached) specialized feature of the given raw feature
Ref<GeoFeature> get_specialized_feature(std::shared_ptr<Feature> raw_feature);

/// Set the OGRLayer object directly.
/// Not exposed to Godot since Godot doesn't know about GDALDatasets - this
/// is only for internal use.
Expand All @@ -96,6 +99,7 @@ class EXPORT GeoFeatureLayer : public RefCounted {

private:
std::shared_ptr<NativeLayer> layer;
std::map<std::shared_ptr<Feature>, Ref<GeoFeature>> feature_cache;
Ref<GeoDataset> origin_dataset;
ExtentData extent_data;
};
Expand Down

0 comments on commit bf8029d

Please sign in to comment.