shapelib.core.geometries package#
Geometry classes for shapelib.
Classes: - BaseShapes: Base class extending GeoDataFrame - Polygons: Polygon geometries with area/perimeter calculations - Lines: Line geometries with length calculations - Points: Point geometries - Empty: Empty geometry placeholder
Submodules#
shapelib.core.geometries.base module#
- class shapelib.core.geometries.base.BaseShapes(data=None, *args, geometry=None, crs=None, path=None, driver=None, keep_z=False, **kwargs)[source]#
Bases:
OperationsMixin,GeoDataFrameA base class that extends GeoDataFrame with additional spatial and CRS-related functionality.
This class provides utility methods for handling geometries, projections, and CRS (Coordinate Reference System) transformations. It extends the functionality of GeoDataFrame by incorporating additional metadata and methods for handling different types of spatial data.
- Parameters:
data (
GeoDataFrame|DataFrame|None) – The input data for the GeoDataFrame. Can be either a GeoDataFrame or a standard DataFrame.geometry (
LineString|Point|Polygon|None) – The geometry type to be applied for the spatial data.crs (
CRS|str|None) – The coordinate reference system for the spatial data. Can be provided as a pyproj.CRS object or an EPSG code string.path (
str|Path|None) – Path to the file from which the data is loaded, if applicable.driver (
str|None) – The driver to use for reading the file, e.g., ‘ESRI Shapefile’, ‘GeoJSON’. This is useful when loading spatial data from external sources.keep_z (
bool) – Keep the Z coordinate of 3-D geometries. Defaults to False, which flattens every geometry to 2-D on load. Turn it on when Z is data the caller needs, such as the elevation carried by every vertex of a contour line.*args (
Any) – Additional positional arguments passed to geopandas.GeoDataFrame.**kwargs (
Any) – Additional keyword arguments passed to geopandas.GeoDataFrame.
- Variables:
geometry_column_name (
str, optional) – The name of the active geometry column in the GeoDataFrame.original_crs (
CRS, optional) – The original CRS of the data, if provided. Useful for preserving the original projection of the dataset.utm_crs (
CRS, optional) – The UTM CRS (Universal Transverse Mercator) for the dataset, if calculated.wgs84_crs (
CRS) – The WGS84 CRS (EPSG:4326), used as a default for geographic data.geod (
Geod) – A pyproj.Geod object initialized with the WGS84 ellipsoid, used for performing geodetic calculations.path (
Path, optional) – The file path from which the data was loaded or where it should be saved, if applicable.driver (
str, optional) – The driver used for reading the file, if provided.legacy_datum (
bool) – True when the data is in a legacy datum (e.g. SAD69, Córrego Alegre) that needs a datum shift to reach WGS 84. Its positional accuracy is limited by that shift: see datum_shift_accuracy.datum_shift_accuracy (
float, optional) – For data in a legacy datum, the published accuracy in metres of the shift to WGS 84 (e.g. 2.0 for SAD69 with the IBGE grid); None otherwise, or when no accuracy is published.keep_z (
bool) – Whether 3-D geometries keep their Z coordinate. Carried over to the objects derived from this one (copies, filters, reprojections).
Notes
This class is designed for spatial data operations and extends GeoDataFrame with additional capabilities such as CRS handling and custom metadata. The metadata fields, such as geometry_column_name and original_crs, are populated during initialization to track important spatial information throughout operations.
- classmethod register_writer(writer)[source]#
Register a file writer strategy.
Writers are checked in registration order. The first writer that supports the destination path will be used.
- Parameters:
writer (
FileWriterStrategy) – The writer strategy to register.- Return type:
Examples
>>> from shapelib.core.cloud.writers import CloudFileWriter >>> BaseShapes.register_writer(CloudFileWriter())
- remove_missing_geometries()[source]#
Remove rows with missing (null or empty) geometries from the GeoDataFrame.
This method drops rows that contain null or empty geometries, and then resets the index of the GeoDataFrame to ensure continuity of row indices.
- Returns:
The method modifies the GeoDataFrame in place by removing invalid geometries.
- Return type:
- remove_rows_by_column_values(criteria)[source]#
Remove rows where any column matches its corresponding value (OR logic).
This method filters the GeoDataFrame by removing all rows where at least one column-value pair from the criteria dictionary matches. Multiple criteria are combined with OR logic: a row is removed if it matches ANY of the conditions.
Both column names and string values are matched case-insensitively.
- Parameters:
criteria (
dict[str,Any]) – Dictionary mapping column names to values. Rows matching any key-value pair will be removed. Column names and string values are case-insensitive. Columns that do not exist in the GeoDataFrame are silently ignored.- Returns:
The method modifies the GeoDataFrame in place.
- Return type:
Examples
Remove rows where status is “inactive” OR type is “A” (case-insensitive):
>>> shapes.remove_rows_by_column_values({"STATUS": "Inactive", "Type": "a"})
Remove rows with a specific numeric value:
>>> shapes.remove_rows_by_column_values({"year": 2020})
Ignore non-existent columns (useful for flexible filtering):
>>> # 'chavesig' may not exist in all GeoDataFrames - silently skipped >>> shapes.remove_rows_by_column_values({"chavesig": "ABC", "status": "inactive"})
Big-O
O(n * k), where n is the number of rows and k is the number of criteria.
Notes
The method uses OR logic: rows matching ANY criterion are removed. For AND logic (remove only rows matching ALL criteria), chain multiple calls or use pandas boolean indexing directly.
Case-insensitive matching applies to both column names and string values. Numeric values are compared with exact equality.
Columns specified in criteria that do not exist in the GeoDataFrame are silently ignored, making this method flexible for use with varying schemas.
- add_index(column_name='index')[source]#
Add an index column to the GeoDataFrame.
This method creates a new column in the GeoDataFrame that stores the row index values as integers, effectively adding a new index column.
- Parameters:
column_name (
str) – The name of the index column to add. Defaults to ‘index’.- Returns:
The method modifies the GeoDataFrame in place by adding a new column with index values.
- Return type:
Examples
>>> gdf.add_index() >>> gdf.head() index geometry 0 0 POINT (1 1) 1 1 POINT (2 2)
- has_column(column_name, case_sensitive=False)[source]#
Check if a column exists in the GeoDataFrame.
This method checks whether the GeoDataFrame contains a column with the specified name, either case-sensitive or case-insensitive, depending on the parameter.
- Parameters:
- Returns:
True if the column exists in the GeoDataFrame, otherwise False.
- Return type:
Examples
>>> gdf.has_column("geometry") True
>>> gdf.has_column("Geometry", case_sensitive=True) False
- get_element(index)[source]#
Get a specific element (row) from the GeoDataFrame by index.
This method retrieves a specific row from the GeoDataFrame based on its index and returns it as a new GeoDataFrame.
- Parameters:
index (
int) – The index of the row to retrieve.- Returns:
A GeoDataFrame containing the selected row.
- Return type:
Examples
>>> gdf.get_element(1) geometry 1 POINT (2 2)
Notes
The index parameter corresponds to the row index of the GeoDataFrame.
- check_columns_encoding()[source]#
Check and fix the encoding of column names and cell values in the GeoDataFrame.
This method identifies and fixes encoding issues with column names and individual cell values in the GeoDataFrame. If column names or values are in bytes format, the method decodes them into str format by first decoding from ‘ascii’ to hex and then decoding the resulting string using the ‘iso8859_15’ encoding.
If the GeoDataFrame contains invalid indices (e.g., NaN values in the index), the method returns without performing any further actions.
- Raises:
ValueError – If a column name or cell value cannot be decoded properly.
- Return type:
Examples
Fix encoding issues in a GeoDataFrame:
>>> gdf.check_columns_encoding()
This method will automatically detect and correct any columns or cells in the GeoDataFrame that are incorrectly encoded as bytes.
Notes
This method is particularly useful for fixing encoding issues in data imported from files that may have encoding errors, such as CSV files with mis-encoded text fields.
- multi_to_single_geometries()[source]#
Convert multi-part geometries (e.g., MultiPolygon, MultiLineString) into single geometries.
This method uses the ‘explode’ function to split multi-part geometries into individual geometries and returns a new BaseShapes with each part as a separate geometry.
- Returns:
A new BaseShapes with multi-part geometries split into single geometries.
- Return type:
Examples
>>> gdf.multi_to_single_geometries() The method will convert geometries like MultiPolygons into separate Polygon objects.
Notes
The explode method used in this function will create a new row for each individual geometry, allowing for easier manipulation of each part of multi-part geometries.
- intersect_with_geom(geom, predicate='intersects', sort=False, distance=None)[source]#
Query the spatial index to find geometries that satisfy the given predicate with respect to a provided geometry.
This method uses the spatial index (sindex) of the GeoDataFrame to query for geometries that satisfy the specified spatial predicate (e.g., ‘intersects’, ‘within’, ‘contains’). It returns a subset of the GeoDataFrame containing only those geometries that meet the criteria when compared to the input geometry.
- Parameters:
geom (
Point|Polygon|LineString) – The geometry to query against.predicate (
str) – The spatial predicate to use for the query. Defaults to ‘intersects’.sort (
bool) – Whether to sort the results by distance from the input geometry. Defaults to False.distance (
float|None) – A distance parameter used for certain predicates (e.g., ‘dwithin’). Defaults to None.
- Returns:
A subset of the GeoDataFrame containing geometries that satisfy the predicate.
- Return type:
- Raises:
ValueError – If the spatial index (sindex) is not available or the query fails.
Examples
>>> gdf.intersect_with_geom(Point(1, 1), predicate="contains") This will return all geometries in the GeoDataFrame that contain the Point(1, 1).
Notes
This method relies on the spatial index (sindex) being available. If the sindex is missing, a ValueError is raised. This method is useful for efficient spatial queries.
- estimate_utm_crs()[source]#
Estimate the UTM CRS for the geometries in the GeoDataFrame.
This method estimates the appropriate UTM (Universal Transverse Mercator) CRS for the geometries in the GeoDataFrame by querying possible UTM CRS candidates based on the total bounds (bounding box) of the geometries. The method:
Converts the geometries to WGS84 for accurate CRS estimation.
Determines the appropriate datum based on the geometry’s location.
Queries the UTM CRS candidates for the bounding box using the selected datum.
Automatically sets the UTM CRS if exactly one candidate is found.
If 2 to 4 candidates are found (e.g., data on a zone border or across the equator), lists them and picks the zone holding most of the data (see _dominant_utm_candidate).
Prints an error if no UTM CRS can be determined or if the geometries cover too many zones.
After estimation, the method reverts the GeoDataFrame back to its original CRS.
- Returns:
The method sets the utm_crs attribute or prints messages if estimation fails.
- Return type:
- Raises:
ValueError – If no appropriate datum can be determined for the geometry’s location or if no UTM CRS can be determined for the area.
Notes
This method depends on pyproj.query_utm_crs_info for UTM CRS estimation.
The method automatically selects the most appropriate datum based on the geometry’s location.
Supported datums include: SIRGAS 2000 (South America), NAD83(2011) (USA), NAD83(PA11) (Hawaii), NAD83(CSRS) (Canada), ITRF2008 (Mexico).
- save(path=None, driver=None, schema=None, index=None, **kwargs)[source]#
Save the GeoDataFrame to local file or remote cloud storage.
This method automatically detects whether the path is local or remote and handles the save operation accordingly. For remote paths, the file is first saved locally then uploaded to the cloud destination.
- Parameters:
path (
str|Path|None) – The destination path. Can be: - A local file path (string or Path object) - An HTTPS URL (presigned PUT URL for S3) - An S3 URL (s3://bucket/key) If not provided, uses the instance’s stored path.driver (
str|None) – The file driver (e.g., ‘ESRI Shapefile’, ‘FlatGeobuf’).schema (
Any|None) – The schema definition for the output file.index (
Any|None) – Whether to write the DataFrame index to the file.**kwargs (
Any) – Additional arguments passed to to_file.
- Raises:
FileNotFoundError – If no path is provided and no instance path exists.
ConnectionError – If upload to remote storage fails.
PermissionError – If access to remote destination is denied.
- Returns:
Saves the GeoDataFrame and returns nothing.
- Return type:
Examples
Save to a local file:
>>> gdf.save(path="output.shp", driver="ESRI Shapefile")
Save to S3 using s3:// protocol (requires AWS credentials):
>>> gdf.save(path="s3://my-bucket/output/data.fgb")
Save using a presigned S3 PUT URL:
>>> gdf.save(path="https://bucket.s3.amazonaws.com/file.fgb?...")
Big-O
O(n) where n is data size. Remote saves add network latency.
- save_empty_file()[source]#
Placeholder method to save an empty file (e.g., a blank shapefile).
This method is a placeholder and is not yet implemented. When called, it raises a NotImplementedError to indicate that saving an empty file is not currently supported.
- Raises:
NotImplementedError – Always, as saving an empty file is not yet implemented.
- Return type:
Notes
The implementation could potentially save a blank shapefile or a similar empty file format in the future.
- to_crs(crs=None, epsg=None, inplace=False)[source]#
Transform the geometries to a new CRS with the best transformation known, or fail.
Same contract as geopandas.GeoDataFrame.to_crs, with one difference that matters for precision. geopandas silently falls back to a less accurate transformation when the best one needs a grid that is not installed, or to a “ballpark” one that ignores the datum shift when the datum is unknown — moving the data by metres, or tens of metres — and turns coordinates that fail to transform into
inf. This method only uses the best transformation and checks every coordinate: if that cannot be done, it raises and leaves the data unchanged. Brazil’s legacy datums (SAD69, SAD69(96), Córrego Alegre 1961 and 1970-72) use the IBGE grids bundled with shapelib.Every shapelib method that reprojects (to_utm, to_wgs84, temp_crs, the area and length calculations…) goes through here.
- Parameters:
- Returns:
The transformed copy, or None when
inplaceis True.- Return type:
- Raises:
ValueError – If the data has no CRS, or neither
crsnorepsgis given.DatumTransformationError – If the best transformation cannot be used: it needs a grid that is not installed, or there is no known transformation between the datums.
Examples
>>> lines = read_file("rows_sad69.shp") # SAD69 / UTM zone 23S >>> lines_sirgas = lines.to_crs("EPSG:31983") # IBGE grid, accurate to 1 m
Big-O
O(V) in the total number of vertices.
- to_utm()[source]#
Transform the GeoDataFrame to its estimated UTM (Universal Transverse Mercator) CRS.
This method transforms the GeoDataFrame to the UTM CRS, which is estimated based on the geometries in the dataset. If the UTM CRS is not already set, the method will estimate it. If the GeoDataFrame is empty, this is a no-op with a warning.
- Raises:
ValueError – If the UTM CRS cannot be determined or estimated on a non-empty GeoDataFrame.
- Return type:
Examples
>>> gdf.to_utm() The GeoDataFrame is transformed in place to its appropriate UTM CRS.
- to_wgs84()[source]#
Transform the GeoDataFrame to the WGS84 CRS (EPSG:4326).
This method transforms the GeoDataFrame to the WGS84 CRS (World Geodetic System 1984), which is commonly used for global geographic coordinates (latitude and longitude). The transformation is performed in place, modifying the GeoDataFrame’s CRS.
- Returns:
The method modifies the GeoDataFrame in place.
- Return type:
Examples
>>> gdf.to_wgs84() The GeoDataFrame is transformed to WGS84 (EPSG:4326).
- to_original_crs()[source]#
Revert the GeoDataFrame to its original CRS.
This method transforms the GeoDataFrame back to its original CRS, if it was defined earlier. If the original CRS is not defined, a ValueError is raised.
- Raises:
ValueError – If the original CRS is not defined.
- Returns:
The method modifies the GeoDataFrame in place.
- Return type:
Examples
>>> gdf.to_original_crs() The GeoDataFrame is transformed back to its original CRS, if available.
- temp_crs(crs)[source]#
Temporarily change the CRS (Coordinate Reference System) of the GeoDataFrame.
This method allows you to temporarily set a new CRS for the GeoDataFrame and automatically revert back to the original CRS after the context block is exited. This is useful for performing operations in a specific CRS without permanently altering the GeoDataFrame’s CRS.
- Parameters:
crs (
str|int|CRS) – The new CRS to set, which can be specified as a string (e.g., “EPSG:4326”), an integer representing an EPSG code, or a pyproj.CRS object.- Yields:
BaseShapes– The GeoDataFrame with the temporarily set CRS.- Raises:
pyproj.exceptions.CRSError – If the specified CRS is invalid or cannot be applied.
- Return type:
Examples
Temporarily switch the CRS to WGS84:
>>> with geodataframe.temp_crs("EPSG:4326"): ... # Perform operations with the new CRS ... # CRS will automatically revert back to the original after this block
- filter_by_geom_type(geom_types)[source]#
Filter the GeoDataFrame by geometry type (e.g., ‘Point’, ‘Polygon’).
- simplify(tolerance=0.001, **kwargs)[source]#
Simplify geometries by reducing vertex count.
Geometries are temporarily projected to UTM for metric accuracy. When the geometry count exceeds
_PARALLEL_SIMPLIFY_THRESHOLD, simplification runs in parallel threads (GEOS releases the GIL).- Parameters:
- Returns:
The same object with simplified geometries.
- Return type:
Examples
>>> shapes = BaseShapes(gdf) >>> shapes.simplify(tolerance=0.01)
Big-O
O(n * v) where n = geometry count, v = avg vertices per geometry.
shapelib.core.geometries.empty module#
shapelib.core.geometries.lines module#
- class shapelib.core.geometries.lines.Lines(data=None, *args, geometry=None, crs=None, path=None, driver=None, **kwargs)[source]#
Bases:
BaseShapesA class for managing LineString geometries in a GeoDataFrame.
This class provides specific functionality for handling LineString geometries, including calculating lengths and managing geometry-specific metadata.
- Parameters:
data (
Any) – The input data for the GeoDataFrame, can be a GeoDataFrame or a DataFrame.geometry (
Any) – The geometry type to use (LineString in this case). Defaults to None.crs (
Any) – Coordinate reference system (CRS) to use for the GeoDataFrame.path (
str|Path|None) – The file path for the data (if reading from a file).driver (
str|None) – The file driver to use when reading/writing data.args (Any)
kwargs (Any)
- Variables:
has_spacement_info (
bool) – Indicates whether spacement information is available.length_column_name (
str) – The name of the column storing the calculated length values.geometry_type (
type) – The expected geometry type for this class (LineString).length_precision (
int) – The precision for rounding length values when calculating the total length.
Examples
Create a Lines object:
>>> lines = Lines(data=gdf) >>> total_length = lines.get_total_length() # Get total length of all lines >>> print(f"Total: {total_length} km")
- property length: GeoSeries#
Return the length of each LineString geometry (GeoPandas native behavior).
Deprecated since version 0.1.0: Accessing .length now returns a GeoSeries with individual line lengths, following GeoPandas’ native behavior. Use .get_total_length() to obtain the sum of all line lengths.
This property returns a GeoSeries containing the length of each individual LineString in the GeoDataFrame, computed using the current CRS. This is the standard GeoPandas behavior.
- Returns:
A GeoSeries with the length of each geometry in the current CRS units.
- Return type:
gpd.GeoSeries
See also
get_total_lengthGet the sum of all line lengths with geodetic accuracy.
calculate_lengthCalculate geodetic length for each line and store in a column.
Examples
>>> # Get individual lengths (GeoSeries) >>> lengths = lines.length >>> print(lengths) 0 150.5 1 230.8 dtype: float64
>>> # Get total length of all lines >>> total = lines.get_total_length() >>> print(f"Total: {total} km")
Notes
This property emits a DeprecationWarning to alert users of the behavior change. In previous versions, .length returned the total sum of all line lengths.
- calculate_length(column_name='length')[source]#
Calculate the length of each line in the GeoDataFrame and store the result in a new column.
This method transforms the GeoDataFrame to WGS84 to ensure accurate length calculations, computes the length of each line, and stores the result in a column with the specified name.
- Parameters:
column_name (
str) – The name of the column to store the calculated lengths. Defaults to “length”.- Returns:
The method modifies the GeoDataFrame in place by adding a new column with the length values.
- Return type:
Examples
>>> lines.calculate_length() >>> print(lines["length"]) # See the calculated length for each line.
- get_total_length()[source]#
Return the total length of all lines in the GeoDataFrame.
This method recalculates the length for each line, sums the values, and rounds to the precision specified by length_precision.
- Returns:
The total length of all lines, rounded to the specified precision. Returns 0.0 if the GeoDataFrame is empty.
- Return type:
Examples
>>> total_length = lines.get_total_length() >>> print(f"Total Length: {total_length} km")
- check_spacement_info()[source]#
Check if the GeoDataFrame has a column related to spacement information.
This method searches for common spacement-related column names (e.g., “spacing”, “espaçamento”) in the GeoDataFrame and sets the has_spacement_info flag accordingly. If a matching column is found, its name is returned.
Examples
>>> column = lines.check_spacement_info() >>> if column: ... print(f"Spacement info available in column: {column}") ... else: ... print("No spacement info found.")
- reduce_length(length)[source]#
Reduce the length of all LineString geometries in the GeoDataFrame by the specified length.
This method applies _reduce_geom_length to each geometry, reducing its length by the specified value.
- Parameters:
length (
float) – The length by which to reduce each LineString geometry. If the value is less than or equal to zero, no reduction is performed.- Returns:
The method modifies the geometries in place.
- Return type:
Examples
>>> lines.reduce_length(100) >>> print("Length reduced by 100 meters for all geometries.")
- filter_by_length(length)[source]#
Filter the GeoDataFrame to retain only LineString geometries that are longer than the specified length.
This method removes any geometries whose length is less than the specified value.
- Parameters:
length (
float) – The minimum length required for a geometry to be retained. If the value is less than or equal to zero, no filtering is performed.- Returns:
The method modifies the GeoDataFrame in place.
- Return type:
Examples
>>> lines.filter_by_length(500) >>> print(f"Retained lines longer than 500 meters.")
- buffer_m(length_m, cap_style=2)[source]#
Create a buffer around each LineString geometry in meters and return the result as a Polygons object.
This method creates a buffer of the specified length (in meters) around each LineString geometry and returns a new Polygons object with the buffered geometries.
- Parameters:
- Returns:
A new Polygons object containing the buffered geometries.
- Return type:
Examples
>>> buffered_polys = lines.buffer_m(100) >>> buffered_polys.plot()
- simplify_lines(tolerance)[source]#
Simplify the geometries in the GeoDataFrame by reducing the number of vertices.
This method simplifies the geometries based on the specified tolerance, reducing their complexity and improving performance for rendering or spatial operations.
- Parameters:
tolerance (
float) – The tolerance for simplifying the geometries. Higher values result in greater simplification.- Returns:
The method modifies the geometries in place.
- Return type:
Examples
>>> lines.simplify_lines(0.01) >>> lines.plot()
- split_by_touching_polygons(polygons)[source]#
Separate LineStrings into two groups: those that touch the polygon boundaries and those that do not.
- Parameters:
polygons (
Polygons) – A Polygons object containing the polygon geometries.- Returns:
A tuple where the first element is a Lines object containing LineStrings touching the polygon boundaries, and the second element is a Lines object containing LineStrings not touching the polygon boundaries.
- Return type:
Examples
>>> touching_lines, non_touching_lines = lines.split_by_touching_polygons(polygons) >>> print(f"Lines touching: {len(touching_lines)}, Lines not touching: {len(non_touching_lines)}")
- classmethod from_mask(mask, dataset_reader, window=None, dilation_kernel_size=5, min_distance_points=10, look_ahead_distance=8, min_line_size=10, min_object_size=0)[source]#
Create a Lines object from a labeled or binary mask and a rasterio dataset reader.
This method extracts line geometries from a 2D NumPy array (mask), where nonzero values represent features of interest (e.g., 1 for foreground, 0 for background, or any labeled regions).
- Parameters:
mask (
ndarray[Any,Any]) – A 2D NumPy array where 0 represents background and any nonzero (or labeled) value represents features to be converted into lines.dataset_reader (
DatasetReader) – A rasterio dataset that the mask is derived from, used for transform and CRS.window (
Window|None) – If provided, the transform will be adjusted for the window region. The mask should correspond to the windowed region.dilation_kernel_size (
int) – Size of the morphological dilation kernel. Larger values connect nearby features but may merge distinct lines. Set to 0 to skip dilation. Defaults to 5.min_distance_points (
int) – Minimum distance between consecutive points in the line tracing algorithm. Higher values produce smoother lines with fewer vertices. Defaults to 10.look_ahead_distance (
int) – Look-ahead distance for the line tracing algorithm. Higher values produce smoother but potentially less accurate lines. Defaults to 8.min_line_size (
int) – Minimum number of pixels required for a line to be included in the output. Defaults to 10.min_object_size (
int) – Minimum size (in pixels) of connected components to retain after removing small objects. Components smaller than this will be removed. Defaults to 0 (no removal).
- Returns:
A Lines object containing the extracted lines as georeferenced geometries.
- Return type:
Example
>>> with rasterio.open('image.tif') as src: ... mask = model.predict(src.read(1)) # Get a binary or labeled mask ... lines = Lines.from_mask(mask, src) ... print(lines) ... # Extract lines from a specific window ... window = rasterio.windows.Window(0, 0, 100, 100) ... mask_window = mask[:100, :100] ... lines_window = Lines.from_mask(mask_window, src, window=window) ... print(lines_window)
- to_mask(dataset_reader, fill_value=1, background_value=0, all_touched=True, window=None, min_size=None)[source]#
Convert the Lines object to a binary mask using a rasterio dataset reader.
This method rasterizes the line geometries in this GeoDataFrame into a binary mask with the same dimensions and coordinate reference system as the provided rasterio dataset reader. If a window is provided, only the region inside the window is rasterized.
- Parameters:
dataset_reader (
DatasetReader) – Rasterio dataset reader that defines the target raster properties (transform, CRS, height, width) for the output mask.fill_value (
int) – Value to assign to pixels that intersect with line geometries. Defaults to 1.background_value (
int) – Value to assign to pixels that do not intersect with any line. Defaults to 0.all_touched (
bool) – If True, all pixels touched by geometries will be burned in. If False, only pixels whose center is within the line or that are selected by Bresenham’s line algorithm will be burned in. Defaults to False for more precise boundary adherence.window (
Window) – If provided, only rasterize the region inside the window. The output mask will have shape (window.height, window.width).min_size (
tuple[int,int] |None) – Minimum size (height, width) for the output mask. If the generated mask is smaller than this size, it will be padded with background_value to match the exact minimum size. Defaults to None.
- Returns:
A 2D numpy array (mask) with the same dimensions as the input raster or window, where pixels intersecting with lines have the fill_value and background pixels have the background_value.
- Return type:
ndarray
Examples
>>> import rasterio >>> with rasterio.open('image.tif') as src: ... mask = lines.to_mask(src) ... print(mask.shape) # Should match src.shape ... print(mask.dtype) # uint8 ... ... window = rasterio.windows.Window(0, 0, 50, 50) ... mask_window = lines.to_mask(src, window=window) ... print(mask_window.shape) # Should be (50, 50) ... ... # With minimum size padding ... mask_padded = lines.to_mask(src, window=window, min_size=(256, 256)) ... print(mask_padded.shape) # Should be (256, 256)
- estimate_line_spacing(sample=0.1, min_samples=30, seed=None)[source]#
Estimate the spacing between parallel planting lines (e.g. rows every 1.5 m or 2.4 m).
Samples a few lines, measures each one’s center-to-nearest-line distance, and returns the median. See
shapelib.tools.lines.distance.estimate_line_spacing().
- group_lines(distance_threshold=2.5)[source]#
Cluster these lines into proximity groups.
Thin wrapper around
shapelib.tools.lines.grouping.group_lines(). Lines must be in a projected CRS (metres); callto_utm()first. Filtering by talhão is the caller’s responsibility — call this on the lines of a single talhão to group them in isolation.- Parameters:
distance_threshold (
float) – Maximum spacing (in CRS units) for two lines to be neighbors.- Returns:
A Lines object with the original attributes plus
group_idandline_idcolumns.- Return type:
Examples
>>> lines.to_utm() >>> grouped = lines.group_lines(distance_threshold=3.5) >>> grouped["group_id"].nunique() 2
shapelib.core.geometries.operations_mixin module#
- shapelib.core.geometries.operations_mixin.propagate_class(method)[source]#
Decorator to ensure that operations on a GeoDataFrame return an instance of the correct class and propagate metadata.
This decorator is used to wrap methods that return a GeoDataFrame, ensuring that the resulting object is an instance of the calling class and carries over any metadata, such as the geometry column and CRS.
- Parameters:
method (
F) – The method that operates on the GeoDataFrame.- Returns:
A decorated method that ensures class and metadata propagation after GeoDataFrame operations.
- Return type:
F
Examples
Applying the propagate_class decorator to a method that modifies a GeoDataFrame:
>>> class MyGeoDataFrame(gpd.GeoDataFrame): ... @propagate_class ... def custom_method(self): ... # Some operation that returns a new GeoDataFrame ... return gpd.GeoDataFrame()
Notes
This decorator is useful when extending or subclassing geopandas.GeoDataFrame, as it ensures that the result of operations like explode or dissolve remains an instance of the derived class, rather than reverting to a base GeoDataFrame.
- class shapelib.core.geometries.operations_mixin.OperationsMixin[source]#
Bases:
objectA mixin class that extends common GeoDataFrame operations while ensuring class and metadata propagation.
This mixin applies the propagate_class decorator to methods such as explode and dissolve to maintain the correct class type and carry over any relevant metadata, such as CRS and the geometry column, after performing GeoDataFrame operations.
shapelib.core.geometries.points module#
- class shapelib.core.geometries.points.Points(data=None, *args, geometry=None, crs=None, path=None, driver=None, **kwargs)[source]#
Bases:
BaseShapesA class for managing Point geometries in a GeoDataFrame.
This class provides specific functionality for handling Point geometries, including buffering by metric distances and nearest-neighbor analysis.
- Parameters:
data (
Any) – The input data for the GeoDataFrame, can be a GeoDataFrame or a DataFrame.geometry (
Any) – The geometry type to use (Point in this case). Defaults to None.crs (
Any) – Coordinate reference system (CRS) to use for the GeoDataFrame.path (
str|Path|None) – The file path for the data (if reading from a file).driver (
str|None) – The file driver to use when reading/writing data.args (Any)
kwargs (Any)
- Variables:
geometry_type (
type) – The expected geometry type for this class (Point).
Examples
Create a Points object:
>>> pts = Points(data=gdf) >>> buffered = pts.buffer_m(10) # 10 meters
- buffer_m(length_m, cap_style=1)[source]#
Create a buffer around each Point geometry in meters and return the result as a Polygons object.
This method creates a buffer of the specified length (in meters) around each Point geometry and returns a new Polygons object with the buffered geometries.
- Parameters:
- Returns:
A new Polygons object containing the buffered geometries.
- Return type:
Examples
>>> buffered_polys = points.buffer_m(25) >>> isinstance(buffered_polys, Polygons) True
- calculate_average_nearest_neighbor_distance(max_distance=30.0)[source]#
Calculate the average nearest neighbor distance between points.
For each point, this method finds the closest other point and computes the average of these distances. Distances are computed in the current CRS units.
- Parameters:
max_distance (
float) – Distances greater than this threshold are ignored in the average.- Returns:
Average nearest neighbor distance.
- Return type:
Examples
>>> avg = points.calculate_average_nearest_neighbor_distance() >>> isinstance(avg, float) True
- classmethod from_mask(mask, dataset_reader, window=None)[source]#
Create a Points object from a labeled or binary mask and a rasterio dataset reader.
- Parameters:
mask (
ndarray[Any,Any]) – A 2D NumPy array where 0 represents background and any nonzero (or labeled) value represents features to be converted into points.dataset_reader (
DatasetReader) – A rasterio dataset that the mask is derived from, used for transform and CRS.window (
Window|None) – If provided, the transform will be adjusted for the window region. The mask should correspond to the windowed region.
- Returns:
A Points object containing the extracted points as georeferenced geometries.
- Return type:
- to_mask(dataset_reader, fill_value=1, background_value=0, all_touched=True, window=None)[source]#
Convert the Points object to a binary mask using a rasterio dataset reader.
- Parameters:
dataset_reader (
DatasetReader) – Rasterio dataset reader that defines the target raster properties (transform, CRS, height, width) for the output mask.fill_value (
int) – Value to assign to pixels that coincide with point geometries. Defaults to 1.background_value (
int) – Value to assign to pixels that do not coincide with any point. Defaults to 0.all_touched (
bool) – If True, all pixels touched by geometries will be burned in.window (
Window) – If provided, only rasterize the region inside the window. The output mask will have shape (window.height, window.width).
- Returns:
A 2D numpy array (mask) with the same dimensions as the input raster or window, where pixels corresponding to points have the fill_value and background pixels have the background_value.
- Return type:
ndarray
shapelib.core.geometries.polygons module#
- class shapelib.core.geometries.polygons.Polygons(data=None, *args, geometry=None, crs=None, path=None, driver=None, **kwargs)[source]#
Bases:
BaseShapesA class for managing polygon geometries in a GeoDataFrame.
This class provides specific functionality for polygon geometries, such as calculating areas and managing geometry-specific metadata.
- Parameters:
data (
Any) – The input data for the GeoDataFrame, can be a GeoDataFrame or a DataFrame.geometry (
Any) – The geometry type to use (Polygon in this case). Defaults to None.crs (
Any) – Coordinate reference system (CRS) to use for the GeoDataFrame.path (
str|Path|None) – The file path for the data (if reading from a file).driver (
str|None) – The file driver to use when reading/writing data.args (Any)
kwargs (Any)
- Variables:
Examples
Create a Polygons object:
>>> polys = Polygons(data=gdf) >>> total_area = polys.get_total_area() # Get total area of all polygons >>> print(f"Total: {total_area} ha")
- property area: GeoSeries#
Return the area of each Polygon geometry (GeoPandas native behavior).
Deprecated since version 0.1.0: Accessing .area now returns a GeoSeries with individual polygon areas, following GeoPandas’ native behavior. Use .get_total_area() to obtain the sum of all polygon areas.
This property returns a GeoSeries containing the area of each individual Polygon in the GeoDataFrame, computed using the current CRS. This is the standard GeoPandas behavior.
- Returns:
A GeoSeries with the area of each geometry in the current CRS units.
- Return type:
gpd.GeoSeries
See also
get_total_areaGet the sum of all polygon areas with geodetic accuracy.
calculate_areaCalculate geodetic area for each polygon and store in a column.
Examples
>>> # Get individual areas (GeoSeries) >>> areas = polys.area >>> print(areas) 0 150.5 1 230.8 dtype: float64
>>> # Get total area of all polygons >>> total = polys.get_total_area() >>> print(f"Total: {total} ha")
Notes
This property emits a DeprecationWarning to alert users of the behavior change. In previous versions, .area returned the total sum of all polygon areas.
- calculate_area(column_name='area (ha)')[source]#
Calculate the area for each polygon in the GeoDataFrame and store the result in a new column.
This method transforms the GeoDataFrame to WGS84 to ensure accurate area calculations, validates the geometries, and then calculates the area of each polygon. The area is stored in a column with the specified name.
- Parameters:
column_name (
str) – The name of the column to store the calculated areas. Defaults to “area”.- Returns:
The method modifies the GeoDataFrame in place by adding a new column with the area values.
- Return type:
Examples
>>> polys.calculate_area() >>> print(polys["area"]) # See the calculated area for each polygon.
- calculate_perimeter(column_name='perimeter (m)')[source]#
Calculate the perimeter for each polygon in the GeoDataFrame and store the result in a new column.
This method converts the GeoDataFrame to WGS84 to ensure accurate perimeter calculations, validates the geometries, and calculates the perimeter of each polygon. The perimeter is stored in a column with the specified name.
- Parameters:
column_name (
str) – The name of the column to store the calculated perimeters. Defaults to “perimeter (m)”.- Returns:
This method modifies the GeoDataFrame in place by adding a new column with the perimeter values.
- Return type:
Examples
>>> polys.calculate_perimeter() >>> print(polys["perimeter (m)"]) # See the calculated perimeter for each polygon.
- get_total_perimeter()[source]#
Return the total perimeter of all polygons in the GeoDataFrame.
This method recalculates the perimeter for each polygon, sums the values, and rounds to the precision specified by perimeter_precision.
- Returns:
The total perimeter of all polygons, rounded to the specified precision. Returns 0.0 if the GeoDataFrame is empty.
- Return type:
Examples
>>> total_perimeter = polys.get_total_perimeter() >>> print(f"Total perimeter: {total_perimeter} meters")
- get_total_area()[source]#
Return the total area of all polygons in the GeoDataFrame.
This method recalculates the area for each polygon, sums the values, and rounds to the precision specified by area_precision.
- Returns:
The total area of all polygons, rounded to the specified precision. Returns 0.0 if the GeoDataFrame is empty.
- Return type:
- force_make_valid()[source]#
Force geometries to be valid by exploding, removing invalid/empty geometries, dissolving, and exploding again.
This method modifies the GeoDataFrame in place.
- Return type:
- filter_by_area(area)[source]#
Filter the GeoDataFrame to retain only Polygon geometries that are larger than the specified area.
This method removes any geometries whose area is less than the specified value.
- Parameters:
area (
float) – The minimum area required for a geometry to be retained. If the value is less than or equal to zero, no filtering is performed.- Returns:
The method modifies the GeoDataFrame in place.
- Return type:
Examples
>>> polygons.filter_by_area(500) >>> print(f"Retained polygons larger than 500.")
- simplify(tolerance=0.001, **kwargs)[source]#
Simplify the geometries in the GeoDataFrame by reducing the number of vertices.
This method delegates to BaseShapes.simplify and invalidates area calculations since the simplified geometries will have different areas.
- filter_by_hole_area(area)[source]#
Remove interior rings (holes) whose area is smaller than the specified value, preserving all polygons.
The area threshold is expressed in hectares, consistent with calculate_area. This method temporarily transforms geometries to WGS84 for accurate geodesic area computation and validates geometries before processing. Only holes are removed; exterior boundaries are preserved.
- Parameters:
area (
float) – The minimum area in hectares required for a hole to be retained. Holes with area smaller than this value will be removed.- Returns:
The method modifies the GeoDataFrame in place.
- Return type:
- Raises:
InvalidGeometryError – If geometries cannot be validated after transformation to WGS84.
Examples
Remove small holes (less than 1 hectare) from polygons:
>>> import shapelib >>> polygons = shapelib.read_file("path/to/polygons.shp") >>> print(f"Original: {len(polygons.geometry.iloc[0].interiors)} holes") >>> polygons.filter_by_hole_area(1.0) >>> print(f"After filtering: {len(polygons.geometry.iloc[0].interiors)} holes")
Big-O
O(n * h), where n is the number of geometries and h is the average number of holes per geometry.
Notes
The method uses geodesic area calculation on the WGS84 ellipsoid for accuracy. Area precision is 6 decimal places (0.000001 ha = 0.01 m²). The original CRS is automatically restored after filtering.
- classmethod from_mask(mask, dataset_reader, window=None, target_resolution_cm_per_pixel=None)[source]#
Create a Polygons object from a labeled or binary mask and a rasterio dataset reader.
This method extracts polygon geometries from a 2D NumPy array (mask), where nonzero values represent features of interest (e.g., 1 for foreground, 0 for background, or any labeled regions).
When the mask has been resampled to a different resolution than the original dataset, use target_resolution_cm_per_pixel to ensure correct spatial positioning of the extracted polygons.
- Parameters:
mask (
ndarray[Any,Any]) – A 2D NumPy array where 0 represents background and any nonzero (or labeled) value represents features to be converted into polygons.dataset_reader (
DatasetReader) – An rasterio dataset that the mask is derived from, used for transform and CRS.window (
Window|None) – If provided, the transform will be adjusted for the window region. The mask should correspond to the windowed region.target_resolution_cm_per_pixel (
float|None) –Target resolution in centimeters per pixel if the mask was resampled. If provided and different from the dataset’s original resolution, the transform will be automatically adjusted to account for resampling. This works for both upsampling and downsampling.
- Examples:
Original 6 cm/pixel downsampled to 3 cm/pixel: pass 3.0
Original 3 cm/pixel upsampled to 6 cm/pixel: pass 6.0
No resampling: omit this parameter or pass None
- Returns:
A Polygons object containing the extracted polygons as georeferenced geometries.
- Return type:
Example
>>> with rasterio.open('image.tif') as src: ... # Example 1: Without resampling ... mask = model.predict(src.read(1)) ... polys = Polygons.from_mask(mask, src) ... print(polys) ... ... # Example 2: With resampling (6cm -> 3cm resolution) ... resampled_mask = model.predict_resampled(src.read(1)) ... polys_resampled = Polygons.from_mask( ... resampled_mask, ... src, ... target_resolution_cm_per_pixel=3.0 ... ) ... print(polys_resampled) ... ... # Example 3: With window ... window = rasterio.windows.Window(0, 0, 100, 100) ... mask_window = mask[:100, :100] ... polys_window = Polygons.from_mask(mask_window, src, window=window) ... print(polys_window)
- to_mask(dataset_reader, fill_value=1, background_value=0, all_touched=True, window=None, min_size=None)[source]#
Convert the Polygons object to a binary mask using a rasterio dataset reader.
This method rasterizes the polygon geometries in this GeoDataFrame into a binary mask with the same dimensions and coordinate reference system as the provided rasterio dataset reader. If a window is provided, only the region inside the window is rasterized. If min_size is specified and the resulting mask is smaller, it will be padded with background_value to match the exact minimum size.
- Parameters:
dataset_reader (
DatasetReader) – Rasterio dataset reader that defines the target raster properties (transform, CRS, height, width) for the output mask.fill_value (
int) – Value to assign to pixels that intersect with polygon geometries. Defaults to 1.background_value (
int) – Value to assign to pixels that do not intersect with any polygon. Defaults to 0.all_touched (
bool) – If True, all pixels touched by geometries will be burned in. If False, only pixels whose center is within the polygon or that are selected by Bresenham’s line algorithm will be burned in. Defaults to False for more precise boundary adherence.window (
Window) – If provided, only rasterize the region inside the window. The output mask will have shape (window.height, window.width).min_size (
tuple[int,int] |None) – Minimum size (height, width) for the output mask. If the generated mask is smaller than this size, it will be padded with background_value to match the exact minimum size. Defaults to None.
- Returns:
A 2D numpy array (mask) with the same dimensions as the input raster or window (or min_size if padding was applied), where pixels intersecting with polygons have the fill_value and background pixels have the background_value.
- Return type:
ndarray
Examples
>>> import rasterio >>> with rasterio.open('image.tif') as src: ... mask = polys.to_mask(src) ... print(mask.shape) # Should match src.shape ... print(mask.dtype) # uint8 ... ... window = rasterio.windows.Window(0, 0, 50, 50) ... mask_window = polys.to_mask(src, window=window) ... print(mask_window.shape) # Should be (50, 50) ... ... # With minimum size padding ... mask_padded = polys.to_mask(src, window=window, min_size=(256, 256)) ... print(mask_padded.shape) # Should be (256, 256)