Skip to content

Commit

Permalink
bump
Browse files Browse the repository at this point in the history
  • Loading branch information
cnheider committed Sep 12, 2024
1 parent 02d26e7 commit 463a4ec
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 91 deletions.
2 changes: 1 addition & 1 deletion jord/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

__project__ = "Jord"
__author__ = "Christian Heider Lindbjerg"
__version__ = "0.7.3"
__version__ = "0.7.4"
__doc__ = r"""
.. module:: jord
:platform: Unix, Windows
Expand Down
31 changes: 16 additions & 15 deletions jord/qlive_utilities/procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def add_wkt_layer(
)


@passes_kws_to(add_wkt)
@passes_kws_to(add_wkb)
def add_shapely_geometry(
qgis_instance_handle: Any, geom: BaseGeometry, *args, **kwargs
) -> List:
Expand All @@ -250,7 +250,7 @@ def add_shapely_geometry(
:return:
"""

return add_wkt(qgis_instance_handle, geom.wkt, *args, **kwargs)
return add_wkb(qgis_instance_handle, geom.wkb, *args, **kwargs)


@passes_kws_to(add_shapely_geometry)
Expand All @@ -270,7 +270,7 @@ def add_shapely_geometries(
)


@passes_kws_to(add_wkt_layer)
@passes_kws_to(add_wkb_layer)
def add_shapely_layer(
qgis_instance_handle: Any,
geoms: Iterable[shapely.geometry.base.BaseGeometry],
Expand All @@ -281,8 +281,8 @@ def add_shapely_layer(
if isinstance(geoms, shapely.geometry.base.BaseGeometry):
geoms = [geoms]

return add_wkt_layer(
qgis_instance_handle, [geom.wkt for geom in geoms], *args, **kwargs
return add_wkb_layer(
qgis_instance_handle, [geom.wkb for geom in geoms], *args, **kwargs
)


Expand Down Expand Up @@ -310,9 +310,9 @@ def add_dataframe(
geom_dict = split_on_geom_type(dataframe)
for df in geom_dict.values():
if False:
for w in df.geometry.to_wkt(rounding_precision=-1):
for w in df.geometry.to_wkb(): # .to_wkt(rounding_precision=-1):
return_list.append(
add_wkt(qgis_instance_handle, w, *args, **kwargs)
add_wkb(qgis_instance_handle, w, *args, **kwargs)
)
else:
for columns, w in zip(
Expand All @@ -330,14 +330,16 @@ def add_dataframe(
a = dataframe[geometry_column][0]
# if a.geom_type == "MultiPolygon":

wkts = [d.wkt for d in dataframe[geometry_column]]
wkts = [d.wkb for d in dataframe[geometry_column]]
elif isinstance(dataframe[geometry_column][0], bytes):
wkts = dataframe[geometry_column]
elif isinstance(dataframe[geometry_column][0], str):
wkts = dataframe[geometry_column]
else:
raise NotImplemented

for row in wkts:
return_list.append(add_wkt(qgis_instance_handle, row, *args, **kwargs))
return_list.append(add_wkb(qgis_instance_handle, row, *args, **kwargs))
else:
raise NotImplemented

Expand All @@ -358,7 +360,7 @@ def add_dataframes(
return return_list


@passes_kws_to(add_wkt_layer)
@passes_kws_to(add_wkb_layer)
def add_dataframe_layer(
qgis_instance_handle: Any,
dataframe: DataFrame,
Expand All @@ -373,7 +375,6 @@ def add_dataframe_layer(
return_list = []

if isinstance(dataframe, GeoDataFrame):

total_feature_len = len(dataframe)
split_accum_len = 0
accum_feature_len = 0
Expand All @@ -398,7 +399,7 @@ def add_dataframe_layer(
# logger.info(f"{name=} has {len(df.geometry)} {k.value} geometries")

for (i, c), w in zip(
df.iterrows(), df.geometry.to_wkt(rounding_precision=-1)
df.iterrows(), df.geometry.to_wkb() # .to_wkt(rounding_precision=-1)
):
c.pop(geometry_column)
geoms.append(w)
Expand All @@ -411,7 +412,7 @@ def add_dataframe_layer(
layer_name = name

if geoms:
added_layers = add_wkt_layer(
added_layers = add_wkb_layer(
qgis_instance_handle,
geoms,
name=layer_name,
Expand All @@ -433,14 +434,14 @@ def add_dataframe_layer(
geoms = []
columns = []
for (i, c), w in zip(
df.iterrows(), df.geometry.to_wkt(rounding_precision=-1)
df.iterrows(), df.geometry.to_wkb() # .to_wkt(rounding_precision=-1)
):
c.pop(geometry_column)
geoms.append(w)
columns.append({**c})

return_list.append(
add_wkt_layer(
add_wkb_layer(
qgis_instance_handle, geoms, columns=columns, *args, **kwargs
)
)
Expand Down
1 change: 1 addition & 0 deletions jord/shapely_utilities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
from .grouping import *
from .mirroring import *
from .selection import *
from .uniformity import *
42 changes: 8 additions & 34 deletions jord/shapely_utilities/base.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,22 @@
import logging
from typing import Any, Mapping, Optional

import shapely
from shapely import Point
from shapely import LineString, Point
from shapely.geometry.base import BaseGeometry
from shapely.validation import make_valid

from .morphology import closing, dilate, opening
from .morphology import closing, opening
from .uniformity import clean_shape, zero_buffer

__all__ = [
"zero_buffer",
"deflimmer",
"clean_geometry",
"unflimmer",
"sanitise",
"clean_shape",
]

logger = logging.getLogger(__name__)


def zero_buffer(
geom: BaseGeometry,
) -> BaseGeometry:
return dilate(geom, distance=0)


def clean_shape(
shape: shapely.geometry.base.BaseGeometry,
) -> shapely.geometry.base.BaseGeometry:
"""
removes self-intersections and duplicate points
:param shape: The shape to cleaned
:return: the cleaned shape
"""

shape = zero_buffer(shape).simplify(0)

if not shape.is_valid:
try:
shape = make_valid(shape)
except shapely.errors.GEOSException as e:
logger.error(e)

return shape


def deflimmer(geom: BaseGeometry, eps: float = 1e-7) -> BaseGeometry:
"""
Expand Down Expand Up @@ -97,4 +67,8 @@ def ausdhasu():
p = Point((1, 1))
print(clean_shape(p))

ausdhasu()
def ausdhasu2():
p = LineString([(1, 1), (1, 1)])
print(clean_shape(p))

ausdhasu2()
17 changes: 17 additions & 0 deletions jord/shapely_utilities/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
Point,
box,
)
import shapely
from shapely.geometry.base import BaseGeometry
from shapely.ops import linemerge as shapely_linemerge

Expand Down Expand Up @@ -108,6 +109,9 @@ def to_lines(
"""

lines = []
if isinstance(geoms, shapely.GeometryCollection):
geoms = geoms.geoms

if isinstance(geoms, Iterable):
for g in geoms:
if isinstance(g, (LineString)):
Expand All @@ -123,12 +127,25 @@ def to_lines(
lines.append(LineString(coordinates=boundary.geoms))
else:
lines.append(boundary)
else:
raise NotImplementedError(f"{g, type(g)}")
else:
raise NotImplementedError(f"{g, type(g)}")
elif isinstance(geoms, MultiLineString):
lines = geoms.geoms
elif isinstance(geoms, LineString):
lines = [geoms]
elif isinstance(geoms, (BaseGeometry)):
boundary = geoms.boundary
if boundary:
if isinstance(boundary, MultiLineString):
lines.extend(to_lines(boundary.geoms))
elif isinstance(boundary, MultiPoint):
lines.append(LineString(coordinates=boundary.geoms))
else:
lines.append(boundary)
else:
raise NotImplementedError(f"{geoms, type(geoms)}")
else:
raise NotImplementedError(f"{geoms, type(geoms)}")

Expand Down
35 changes: 3 additions & 32 deletions jord/shapely_utilities/polygons.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from .base import sanitise
from .geometry_types import is_multi
from .lines import segments
from .rings import ensure_ccw_ring, ensure_cw_ring

__all__ = [
"explode_polygons",
Expand Down Expand Up @@ -276,7 +275,9 @@ def discard_holes(
return shapely.GeometryCollection(shape_parts)

raise NotImplementedError(
f"Discarding hole for {shape.type if isinstance(shape, shapely.geometry.base.BaseGeometry) else type(shape)} is not implemented"
f"Discarding hole for "
f"{shape.type if isinstance(shape, shapely.geometry.base.BaseGeometry) else type(shape)} is not "
f"implemented"
)


Expand All @@ -291,36 +292,6 @@ def has_holes(shape: Union[shapely.Polygon, shapely.MultiPolygon]) -> bool:
return False


def ensure_ccw_poly(polygon: Polygon) -> Polygon:
"""
This function checks if the polygon is counter-clockwise if not it is reversed
:param polygon: The polygon to check
:return: Returns the polygon turned clockwise
"""

return Polygon(
shell=ensure_ccw_ring(polygon.exterior),
holes=[ensure_ccw_ring(hole) for hole in polygon.interiors],
)


def ensure_cw_poly(polygon: Polygon) -> Polygon:
"""
This function checks if the polygon is clockwise if not it is reversed
:param polygon: The polygon to check
:return: Returns the polygon turned clockwise
"""

return Polygon(
shell=ensure_cw_ring(polygon.exterior),
holes=[ensure_cw_ring(hole) for hole in polygon.interiors],
)


def is_polygonal(cleaned):
if isinstance(
cleaned, (shapely.Point, shapely.MultiPoint, LineString, MultiLineString)
Expand Down
88 changes: 88 additions & 0 deletions jord/shapely_utilities/uniformity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import logging
from typing import Optional

import shapely
from shapely import Polygon
from shapely.geometry.base import BaseGeometry
from shapely.validation import make_valid

from .morphology import dilate
from .rings import ensure_ccw_ring, ensure_cw_ring

logger = logging.getLogger(__name__)

__all__ = ["clean_shape", "ensure_cw_poly", "ensure_ccw_poly", "zero_buffer"]


def clean_shape(
shape: shapely.geometry.base.BaseGeometry, grid_size: Optional[float] = None
) -> shapely.geometry.base.BaseGeometry:
"""
removes self-intersections and duplicate points
:param grid_size:
:param shape: The shape to cleaned
:return: the cleaned shape
"""

if isinstance(shape, shapely.Polygon):
shape = ensure_cw_poly(shape)

if grid_size is not None:
if not shape.is_valid:
try:
shape = make_valid(shape)
except shapely.errors.GEOSException as e:
logger.error(e)

shape = shapely.set_precision(
shape,
grid_size,
mode="keep_collapsed",
)

shape = zero_buffer(shape).simplify(0)

if not shape.is_valid:
try:
shape = make_valid(shape)
except shapely.errors.GEOSException as e:
logger.error(e)

return shape


def ensure_ccw_poly(polygon: Polygon) -> Polygon:
"""
This function checks if the polygon is counter-clockwise if not it is reversed
:param polygon: The polygon to check
:return: Returns the polygon turned clockwise
"""

return Polygon(
shell=ensure_ccw_ring(polygon.exterior),
holes=[ensure_ccw_ring(hole) for hole in polygon.interiors],
)


def ensure_cw_poly(polygon: Polygon) -> Polygon:
"""
This function checks if the polygon is clockwise if not it is reversed
:param polygon: The polygon to check
:return: Returns the polygon turned clockwise
"""

return Polygon(
shell=ensure_cw_ring(polygon.exterior),
holes=[ensure_cw_ring(hole) for hole in polygon.interiors],
)


def zero_buffer(
geom: BaseGeometry,
) -> BaseGeometry:
return dilate(geom, distance=0)
Loading

0 comments on commit 463a4ec

Please sign in to comment.