-
Notifications
You must be signed in to change notification settings - Fork 1
Optional densify simplify #9
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
base: main
Are you sure you want to change the base?
Optional densify simplify #9
Conversation
…ut still not implemented the last one
…nto optional_densify_simplify
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request enhances the conceptual mesh blueprint with optional geometry simplification and flexible line densification capabilities. The changes enable users to reduce geometric complexity before mesh generation while maintaining control over simplification tolerances and densification strategies.
- Added
simplify_toleranceparameter to polygons, lines, and points for optional geometry simplification - Extended line densification to support three modes: disabled (
False), automatic (using resolution), or custom spacing (float value) - Implemented point deduplication that merges nearby points within tolerance, keeping the point with finest resolution
- Added comprehensive tests to verify polygon/line simplification, point deduplication, and all line densification modes
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 15 comments.
| File | Description |
|---|---|
| src/vorflow/blueprint.py | Core implementation of simplification and densification features, including new parameters in add_polygon, add_line, and add_point methods, plus the new _apply_simplification method and enhanced _apply_densification logic |
| tests/test_conceptual_mesh.py | Comprehensive test coverage for new features including polygon/line simplification, point deduplication with resolution preservation, and three modes of line densification |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/vorflow/blueprint.py
Outdated
| lambda row: self._densify_geometry(row['geometry'], get_line_resolution(row)) | ||
| if get_line_resolution(row) is not None else row['geometry'], axis=1) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get_line_resolution function is called twice per row in the lambda (lines 418-419): once to determine the resolution value and once to check if it's None. This is inefficient. Consider calculating it once and reusing the value, or restructuring the apply logic.
| lambda row: self._densify_geometry(row['geometry'], get_line_resolution(row)) | |
| if get_line_resolution(row) is not None else row['geometry'], axis=1) | |
| lambda row: ( | |
| self._densify_geometry(row['geometry'], resolution) | |
| if resolution is not None else row['geometry'] | |
| ), | |
| axis=1 | |
| ) | |
| # Use a local variable to avoid double evaluation | |
| # (This is done by defining the lambda with a local variable) | |
| # Alternatively, use a regular function: | |
| # def densify_row(row): | |
| # resolution = get_line_resolution(row) | |
| # return self._densify_geometry(row['geometry'], resolution) if resolution is not None else row['geometry'] | |
| # self.clean_lines['geometry'] = self.clean_lines.apply(densify_row, axis=1) |
src/vorflow/blueprint.py
Outdated
| if tol is True: | ||
| lc = poly_data.get('lc') | ||
| tol = lc * 0.5 if lc is not None else None |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for handling tol is True (lines 145-147, 155-157, 179-181) is present but not documented in the API. The simplify_tolerance parameter is documented as float, optional in the docstrings, but the code accepts True as a special value that computes a tolerance based on resolution. Either document this behavior in the parameter descriptions or remove support for True if it's not intended to be part of the public API.
src/vorflow/blueprint.py
Outdated
| #lets sort by resolution first | ||
| sorted_points = sorted( | ||
| self.raw_points, | ||
| key=lambda x: x['lc'] if x['lc'] is not None else float('inf')) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation: the sorted_points tuple has improper alignment with 'key=' on line 167 indented more than expected. This should align with the opening parenthesis on line 165.
| key=lambda x: x['lc'] if x['lc'] is not None else float('inf')) | |
| key=lambda x: x['lc'] if x['lc'] is not None else float('inf')) |
src/vorflow/blueprint.py
Outdated
| for kept in final_points: | ||
| dist = kept['geometry'].distance(current_geom) | ||
| if dist < tol: | ||
| is_merged = True | ||
| break | ||
| if not is_merged: | ||
| final_points.append(point_data) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point deduplication algorithm has O(n²) complexity because it compares each point against all previously kept points (line 184-188). For large numbers of points, this could be a performance bottleneck. Consider using a spatial index (e.g., STRtree from shapely) to efficiently find nearby points within the tolerance distance.
src/vorflow/blueprint.py
Outdated
| tol = lc * 0.5 if lc is not None else None | ||
|
|
||
| if tol is not None and tol > 0: | ||
| self.raw_polygons[i]['geometry'] = poly_data['geometry'].simplify(tol, preserve_topology=False) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using preserve_topology=False for polygon simplification could create invalid geometries or self-intersections. This is risky for mesh generation. Consider using preserve_topology=True to maintain topological validity, or validate the geometry after simplification.
| self.raw_polygons[i]['geometry'] = poly_data['geometry'].simplify(tol, preserve_topology=False) | |
| self.raw_polygons[i]['geometry'] = poly_data['geometry'].simplify(tol, preserve_topology=True) |
src/vorflow/blueprint.py
Outdated
| lower ones. | ||
| """ | ||
| # Sort polygons by priority, with the highest z_order processed first. | ||
| if self.raw_polygons == []: |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The empty list comparison self.raw_polygons == [] is not the most Pythonic way to check for emptiness. Use not self.raw_polygons instead, which is the idiomatic way to check for empty lists in Python.
| if self.raw_polygons == []: | |
| if not self.raw_polygons: |
src/vorflow/blueprint.py
Outdated
| """ | ||
| # Sort polygons by priority, with the highest z_order processed first. | ||
| if self.raw_polygons == []: | ||
| #if this is empty, just create an empty GeoDataFrame |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment on line 207 says "if this is empty, just create an empty GeoDataFrame" but should start with a capital letter and use proper punctuation: "If this is empty, just create an empty GeoDataFrame."
| #if this is empty, just create an empty GeoDataFrame | |
| # If this is empty, just create an empty GeoDataFrame. |
src/vorflow/blueprint.py
Outdated
| def _apply_simplification(self): | ||
| """ | ||
| Applies geometry simplification to raw polygons, lines, and points | ||
| based on their specified tolerances. |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The _apply_simplification() method lacks a docstring describing the point deduplication behavior and algorithm. The current docstring only mentions "simplification" but doesn't explain that points are deduplicated by merging those within tolerance, keeping the one with finest resolution.
| based on their specified tolerances. | |
| based on their specified tolerances. | |
| For points, this method also performs deduplication: points that are within | |
| a specified tolerance of each other are merged, and only the point with the | |
| finest (smallest) resolution is kept. The tolerance for merging is taken from | |
| the 'simplify_tolerance' attribute of each point, or derived from the point's | |
| resolution if set to True. This ensures that closely spaced points do not | |
| result in redundant mesh nodes, and that the most restrictive mesh size is | |
| preserved at each location. |
src/vorflow/blueprint.py
Outdated
| # lets merge points that are very close to each other | ||
| if self.raw_points: | ||
| #lets sort by resolution first |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment style issues: Line 162 should start with a capital letter and use proper grammar ("Let's merge" instead of "lets merge"). Line 164 is missing a space after '#' (should be "# Let's sort" instead of "#lets sort").
| # lets merge points that are very close to each other | |
| if self.raw_points: | |
| #lets sort by resolution first | |
| # Let's merge points that are very close to each other | |
| if self.raw_points: | |
| # Let's sort by resolution first |
tests/test_conceptual_mesh.py
Outdated
| poly = Polygon([ | ||
| (0, 0), (1, 0), | ||
| (1, 1), (0.5, 1.001), (0, 1) | ||
| ]) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Inconsistent spacing in line continuation. The closing parenthesis on line 62 is at a different indentation level than the opening on line 59. For better readability, align the closing parenthesis with the opening statement or place it at the same indentation as the content.
|
@oscarfasanchez - Id recommend adding logging of how much change is incurred in the geometries through simplification. A warning message should inform the user that simplification has resulted in e.g. "x% area difference". Things like that. |
|
I have committed the recommendations made by @rhugman and Copilot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/vorflow/blueprint.py
Outdated
| reduction_pct = 100 * (org_area - new_area) / org_area | ||
| if reduction_pct > 1.0: |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The threshold value of 1.0% for reporting area reduction is a magic number. Consider making it a named constant (e.g., SIGNIFICANT_REDUCTION_PCT = 1.0) to improve code maintainability and make it easier to adjust this threshold in the future.
src/vorflow/blueprint.py
Outdated
| tol = poly_data.get('simplify_tolerance') | ||
| if tol is True: | ||
| lc = poly_data.get('lc') | ||
| tol = lc * 0.5 if lc is not None else None |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The heuristic multiplier of 0.5 for automatic tolerance calculation (when simplify_tolerance=True) is a magic number. Consider defining it as a named constant (e.g., AUTO_SIMPLIFY_FACTOR = 0.5) to make it easier to adjust and maintain consistency across polygon, line, and point simplification.
src/vorflow/blueprint.py
Outdated
| tol = line_data.get('simplify_tolerance') | ||
| if tol is True: | ||
| lc = line_data.get('lc') | ||
| tol = lc * 0.5 if lc is not None else None |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The heuristic multiplier of 0.5 for automatic tolerance calculation is duplicated from line 180. Consider defining it as a named constant to avoid duplication and ensure consistency.
src/vorflow/blueprint.py
Outdated
|
|
||
| if tol is True: | ||
| lc = point_data.get('lc') | ||
| tol = lc * 0.5 if lc is not None else 1e-6 |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback tolerance value of 1e-6 and the automatic tolerance multiplier of 0.5 are magic numbers. These values are also used elsewhere in the code. Consider defining them as named constants for consistency and maintainability.
src/vorflow/blueprint.py
Outdated
| """ | ||
| Applies geometry simplification to raw polygons, lines, and points | ||
| based on their specified tolerances to reduce | ||
| geometric complexity.For polygon and lines |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space after period in docstring. Should be "...complexity. For polygon and lines..." instead of "...complexity.For polygon and lines..."
| geometric complexity.For polygon and lines | |
| geometric complexity. For polygon and lines |
src/vorflow/blueprint.py
Outdated
| return None | ||
|
|
||
| # 2. Explicit custom resolution (e.g., densify=5.0) | ||
| if isinstance(d, (int, float)) and d > 0: |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation logic has the same issue as the validation in add_line: booleans are instances of int in Python, so isinstance(d, (int, float)) will be True when d is True or False. This could cause densify=True to be interpreted as the numeric value 1 instead of the intended default behavior. The check should exclude booleans: if isinstance(d, (int, float)) and not isinstance(d, bool) and d > 0:
| if isinstance(d, (int, float)) and d > 0: | |
| if isinstance(d, (int, float)) and not isinstance(d, bool) and d > 0: |
src/vorflow/blueprint.py
Outdated
| """ | ||
| Applies geometry simplification to raw polygons, lines, and points | ||
| based on their specified tolerances to reduce | ||
| geometric complexity.For polygon and lines |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring states "For polygon and lines" but should be "For polygons and lines" (polygon should be plural to match "lines").
| geometric complexity.For polygon and lines | |
| geometric complexity. For polygons and lines |
src/vorflow/blueprint.py
Outdated
| tol = lc * 0.5 if lc is not None else 1e-6 | ||
| is_merged = False | ||
|
|
||
| #query tree for potential neighbors |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment should start with a capital letter: "Query tree for potential neighbors" instead of "query tree for potential neighbors"
| #query tree for potential neighbors | |
| # Query tree for potential neighbors |
…et of variables for magic numbers
|
Solved. |

This pull request adds geometry simplification and densification options to the conceptual mesh blueprint, allowing users to control the simplification of polygons, lines, and points, as well as providing more flexible densification for lines. It also introduces tests to verify these new features. The most important changes are grouped below.
Geometry Simplification Features:
simplify_toleranceparameter to theadd_polygon,add_line, andadd_pointmethods inblueprint.py, enabling optional geometry simplification for each feature type. The simplification is applied before overlap resolution and mesh generation._apply_simplificationmethod to handle geometry simplification for polygons and lines, and to deduplicate points that are within the specified tolerance, keeping the point with the finest resolution._apply_simplificationbefore resolving overlaps.Line Densification Enhancements:
add_linemethod to accept adensifyparameter, which can beTrue,False, or a float for custom spacing. Updated_apply_densificationto respect this parameter, allowing for more flexible control over line densification.Testing Improvements:
test_conceptual_mesh.pyto verify:False,True, and custom float).