Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GeoJSON Parsing Verbesserungen #586

Merged
merged 4 commits into from
Feb 5, 2024

Conversation

zimmermannubique
Copy link
Contributor

@zimmermannubique zimmermannubique commented Jan 26, 2024

  • ID wird sauber weitergegeben als ID
  • Möglichkeit zum Parsen von GeoJSON inkl. Punkt-Geometrie

Summary by CodeRabbit

  • New Features

    • Enhanced GeoJSON feature parsing to support point geometries across various platforms, including Android, iOS, and shared codebases.
    • Introduced a new method for creating textures with custom draw callbacks in iOS, leveraging the Metal framework.
  • Refactor

    • Expanded existing interfaces and classes to include new parsing functionalities, improving support for GeoJSON point geometries.
    • Updated method implementations to better handle GeoJSON parsing, including conditional feature context setting based on input feature properties.
  • Documentation

    • Added comments and documentation to newly introduced methods and functionalities, ensuring clarity and ease of use for developers integrating these features.

Copy link
Contributor

coderabbitai bot commented Jan 26, 2024

Walkthrough

The recent updates revolve around enhancing GeoJSON parsing capabilities across Android and iOS platforms, introducing a new method parseWithPointGeometry to process GeoJSON with point geometries. This method returns collections of point objects in their respective environments. Changes span across Kotlin, C++, and Objective-C files, establishing a unified approach to parsing GeoJSON points and integrating these points with existing map layers. Additionally, there's an improvement in texture handling for iOS, alongside refinements in feature parsing and identification.

Changes

Files Change Summary
.../mapscore/shared/map/layers/tiled/GeoJsonFeatureParserInterface.kt
.../jni/map/layers/tiled/NativeGeoJsonFeatureParserInterface.cpp
.../ios/MCGeoJsonFeatureParserInterface+Private.mm
.../ios/MCGeoJsonFeatureParserInterface.h
shared/public/GeoJsonFeatureParser.h
shared/public/GeoJsonFeatureParserInterface.h
djinni/map/layers/tiled/geo_json_parser.djinni
Added parseWithPointGeometry method for parsing GeoJSON with point geometry.
.../jni/map/layers/tiled/NativeGeoJsonPoint.cpp
.../jni/map/layers/tiled/NativeGeoJsonPoint.h
.../ios/MCGeoJsonPoint+Private.h
.../ios/MCGeoJsonPoint+Private.mm
.../ios/MCGeoJsonPoint.h
.../ios/MCGeoJsonPoint.mm
Implemented functionality for converting between C++ and JNI/Objective-C representations of GeoJsonPoint objects.
ios/graphics/Texture/TextureHolder.swift Added a new initializer for creating textures with a draw callback.
shared/public/GeoJsonPoint.h Defined a GeoJsonPoint struct for representing points in GeoJSON format.
shared/public/Value.h Extended FeatureContext class with a new constructor for initializing properties based on input parameters.
shared/src/map/layers/tiled/vector/geojson/GeoJsonFeatureParser.cpp
shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h
Modified to support parseWithPointGeometry method and conditional feature context setting.

🐰✨
In the realm of code, where the data points dance,
A rabbit hopped in, giving maps a new chance.
With a flick and a hop, GeoJSON points align,
Under moon's soft glow, all the vectors combine.
🌍🌟

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between aaf1f32 and e231862.
Files ignored due to path filters (1)
  • djinni/yaml/geo_json_point.yaml is excluded by: !**/*.yaml
Files selected for processing (19)
  • bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/GeoJsonFeatureParserInterface.kt (2 hunks)
  • bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/GeoJsonPoint.kt (1 hunks)
  • bridging/android/jni/map/layers/tiled/NativeGeoJsonFeatureParserInterface.cpp (2 hunks)
  • bridging/android/jni/map/layers/tiled/NativeGeoJsonPoint.cpp (1 hunks)
  • bridging/android/jni/map/layers/tiled/NativeGeoJsonPoint.h (1 hunks)
  • bridging/ios/MCGeoJsonFeatureParserInterface+Private.mm (2 hunks)
  • bridging/ios/MCGeoJsonFeatureParserInterface.h (2 hunks)
  • bridging/ios/MCGeoJsonPoint+Private.h (1 hunks)
  • bridging/ios/MCGeoJsonPoint+Private.mm (1 hunks)
  • bridging/ios/MCGeoJsonPoint.h (1 hunks)
  • bridging/ios/MCGeoJsonPoint.mm (1 hunks)
  • djinni/map/layers/tiled/geo_json_parser.djinni (1 hunks)
  • ios/graphics/Texture/TextureHolder.swift (1 hunks)
  • shared/public/GeoJsonFeatureParser.h (1 hunks)
  • shared/public/GeoJsonFeatureParserInterface.h (1 hunks)
  • shared/public/GeoJsonPoint.h (1 hunks)
  • shared/public/Value.h (1 hunks)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonFeatureParser.cpp (2 hunks)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h (2 hunks)
Files skipped from review due to trivial changes (6)
  • bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/GeoJsonPoint.kt
  • bridging/ios/MCGeoJsonPoint+Private.h
  • bridging/ios/MCGeoJsonPoint+Private.mm
  • bridging/ios/MCGeoJsonPoint.h
  • bridging/ios/MCGeoJsonPoint.mm
  • shared/public/GeoJsonPoint.h
Additional comments: 16
djinni/map/layers/tiled/geo_json_parser.djinni (2)
  • 8-8: Added method parseWithPointGeometry to the interface, which is expected to enhance GeoJSON parsing capabilities by supporting point geometries. Ensure corresponding implementations in all languages (Java, Objective-C, C++) are consistent with this interface definition.
  • 11-13: Introduced a new geo_json_point record with fields point and feature_info. This structure is crucial for representing point geometries along with their associated feature information. Verify that the types coord and vector_layer_feature_info are correctly used and that they provide the necessary data for GeoJSON points.
bridging/ios/MCGeoJsonFeatureParserInterface.h (1)
  • 16-16: The addition of parseWithPointGeometry in the iOS interface aligns with the changes in the Djinni interface definition. This method will enable iOS applications to parse GeoJSON data containing point geometries. Ensure that the implementation correctly bridges to the underlying C++ logic.
shared/public/GeoJsonFeatureParserInterface.h (1)
  • 22-22: The addition of parseWithPointGeometry to the C++ interface is consistent with the Djinni interface changes. This method extends the parser's functionality to support point geometries in GeoJSON data. Ensure that the implementation adheres to the interface contract and correctly handles GeoJSON parsing logic.
shared/public/GeoJsonFeatureParser.h (1)
  • 22-22: The parseWithPointGeometry method has been correctly declared in the GeoJsonFeatureParser class, aligning with the interface definition. This method is crucial for enabling point geometry parsing in the shared C++ codebase. Ensure the implementation is robust and correctly parses GeoJSON point geometries.
bridging/android/jni/map/layers/tiled/NativeGeoJsonPoint.h (1)
  • 11-31: The NativeGeoJsonPoint class provides JNI bridging for the GeoJsonPoint structure, facilitating its use in Android applications. Ensure that the JNI methods toCpp and fromCpp correctly translate between Java and C++ representations, and that the JNI field and method IDs are correctly resolved.
bridging/android/jni/map/layers/tiled/NativeGeoJsonPoint.cpp (2)
  • 14-29: The implementation of fromCpp in NativeGeoJsonPoint correctly converts C++ GeoJsonPoint objects to their Java counterparts. Verify that the JNI environment is correctly used and that the Java object is constructed with the appropriate parameters.
  • 23-28: The toCpp method implementation correctly translates Java GeoJsonPoint objects back to their C++ counterparts. Ensure that the JNI environment is correctly used to access object fields and that the conversion accurately reflects the structure of GeoJsonPoint.
shared/src/map/layers/tiled/vector/geojson/GeoJsonFeatureParser.cpp (1)
  • 34-49: The implementation of parseWithPointGeometry correctly parses GeoJSON data to extract point geometries. Ensure that the nlohmann::json library is correctly used for parsing and that point geometries are accurately extracted and returned as GeoJsonPoint objects.
bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/GeoJsonFeatureParserInterface.kt (2)
  • 18-18: The addition of parseWithPointGeometry to the Kotlin interface for GeoJsonFeatureParserInterface is consistent with the changes across other platforms. This method enables the parsing of GeoJSON data with point geometries on Android. Ensure that the native implementation is correctly invoked.
  • 41-45: The CppProxy inner class correctly implements the parseWithPointGeometry method, ensuring that the native parsing logic is invoked. Verify that the native method native_parseWithPointGeometry is correctly linked and that it accurately processes GeoJSON data.
bridging/ios/MCGeoJsonFeatureParserInterface+Private.mm (1)
  • 49-54: The implementation of parseWithPointGeometry in the Objective-C++ extension correctly bridges the call to the underlying C++ logic. Ensure that exceptions are correctly translated and that the method returns the expected array of MCGeoJsonPoint objects.
bridging/android/jni/map/layers/tiled/NativeGeoJsonFeatureParserInterface.cpp (1)
  • 40-47: The native_parseWithPointGeometry JNI method correctly invokes the parseWithPointGeometry function of the GeoJsonFeatureParserInterface and returns the result as a JNI object. Ensure that the JNI environment is correctly used and that the method accurately bridges the parsing logic.
ios/graphics/Texture/TextureHolder.swift (1)
  • 79-122: The new convenience initializer in TextureHolder correctly creates a texture using the Metal framework based on the provided size and draw callback. Ensure that the Metal context is correctly utilized and that the texture creation process accurately reflects the intended design and functionality.
shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h (1)
  • 89-93: The modification to conditionally set the featureContext based on the presence of an "id" field in the input feature is a significant improvement for accurately transferring IDs as identifiers. Ensure that the logic correctly handles both string IDs and the generation of UUIDs when no ID is provided.
shared/public/Value.h (1)
  • 122-139: > 📝 NOTE

This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

Ensure the file's copyright notice is up-to-date and accurately reflects the current year or the range of years during which the file was modified. This is important for maintaining proper copyright documentation.

Comment on lines +125 to +135
FeatureContext(vtzero::GeomType geomType,
mapType propertiesMap,
const std::string &stringIdentifier):
propertiesMap(std::move(propertiesMap)),
geomType(geomType) {
size_t hash = 0;
std::hash_combine(hash, std::hash<std::string>{}(stringIdentifier));
identifier = hash;

initialize();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new constructor in FeatureContext class that takes a string identifier and converts it to a hash for the identifier member introduces a potential issue with hash collisions. While the likelihood of collisions might be low, it's important to consider the implications of such an event, especially in mapping applications where unique identification is crucial. Consider implementing or documenting a strategy to handle potential hash collisions to ensure the robustness of feature identification.

Comment on lines 122 to 139
initialize();
}

FeatureContext(vtzero::GeomType geomType,
mapType propertiesMap,
const std::string &stringIdentifier):
propertiesMap(std::move(propertiesMap)),
geomType(geomType) {
size_t hash = 0;
std::hash_combine(hash, std::hash<std::string>{}(stringIdentifier));
identifier = hash;

initialize();
}

FeatureContext(vtzero::feature const &feature) {
geomType = feature.geometry_type();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-136]

Consider reviewing the entire file for opportunities to optimize data structures and algorithms for better performance, especially in critical paths of the mapping application. For example, evaluating the use of std::unordered_map and std::vector in frequently accessed methods could lead to performance gains. Additionally, assess the maintainability of the code, ensuring that complex logic is well-documented and that the code structure facilitates easy modifications and extensions in the future.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between e231862 and 9cd9f8c.
Files selected for processing (2)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonFeatureParser.cpp (2 hunks)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h (3 hunks)
Files skipped from review as they are similar to previous changes (1)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonFeatureParser.cpp
Additional comments: 1
shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h (1)
  • 147-218: The parsing methods (parsePoint, parseMultiPoint, parseLineString, parseMultiLineString, parsePolygon, parseMultiPolygon) and utility functions (parseProperties, getFeatureInfo, parseCoordinate) remain unchanged in this PR. These methods are crucial for the functionality of the GeoJsonParser class and appear to be well-implemented based on the provided context. It's important to ensure that these methods are thoroughly tested, especially with the introduction of new functionality related to point geometries and ID handling.

Comment on lines +90 to +94
if(feature["id"].is_string()) {
geometry->featureContext = std::make_shared<FeatureContext>(geomType, properties, feature["id"].get<std::string>());
} else {
geometry->featureContext = std::make_shared<FeatureContext>(geomType, properties, generator.generateUUID());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for setting featureContext based on the presence of an "id" field is sound. However, consider the implications of generating a UUID for every feature without an "id". This could lead to inconsistencies if the same GeoJSON is parsed multiple times, resulting in different UUIDs for the same features. It might be beneficial to document this behavior or consider a deterministic approach to generating UUIDs based on feature properties to ensure consistency.

Comment on lines 102 to 146
static std::vector<::GeoJsonPoint> getPointsWithProperties(const nlohmann::json &geojson) {
// preconditions
std::vector<::GeoJsonPoint> points;

if (!geojson["type"].is_string() ||
geojson["type"] != "FeatureCollection" ||
!geojson["features"].is_array()) {
LogError <<= "Geojson is not valid";
assert(false);
return points;
}

UUIDGenerator generator;

std::shared_ptr<GeoJson> geoJson = std::make_shared<GeoJson>();
for (const auto &feature: geojson["features"]) {
if (!feature["geometry"].is_object() ||
!feature["geometry"]["type"].is_string() ||
!feature["geometry"]["coordinates"].is_array()) {
LogError <<= "Geojson feature is not valid";
continue;
}

const auto &geometryType = feature["geometry"]["type"];
const auto &coordinates = feature["geometry"]["coordinates"];
std::shared_ptr<GeoJsonGeometry> geometry;
vtzero::GeomType geomType;
if (geometryType == "Point") {
geometry = parsePoint(coordinates);
geomType = vtzero::GeomType::POINT;
}

if(!geometry || geometry->coordinates.size() != 1 || geometry->coordinates.front().size() != 1) {
continue;
}

if(!feature["id"].is_string()) {
continue;
}

points.emplace_back(geometry->coordinates.front().front(), GeoJsonParser::getFeatureInfo(feature["properties"], feature["id"].get<std::string>()));
}

return points;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method getPointsWithProperties is a valuable addition for extracting point geometries with their properties. However, there are a few areas for improvement:

  1. The method's precondition checks (lines 106-112) are identical to those in getGeoJson. Consider extracting these checks into a separate method to avoid code duplication.
  2. The method assumes that all features with a "Point" geometry type will have exactly one coordinate (line 134). This is a valid assumption per the GeoJSON specification, but it's worth documenting this assumption in a comment for clarity.
  3. The method skips features without an "id" field (lines 138-140). This behavior is consistent with the handling in getGeoJson, but it may be worth considering if there are use cases where points without an "id" should still be returned, perhaps with a generated UUID as in getGeoJson.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 9cd9f8c and e744ce5.
Files selected for processing (1)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h (3 hunks)
Files skipped from review as they are similar to previous changes (1)
  • shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h

@maurhofer-ubique maurhofer-ubique merged commit 17a6435 into develop Feb 5, 2024
2 checks passed
@maurhofer-ubique maurhofer-ubique deleted the feature/geojson-point-parsing branch February 5, 2024 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants