Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Version 0.9 (unreleased)
the Geometry object itself. All binary predicates (except ``equals``) make use of this (#92).
* Use previously prepared geometries within ``STRtree`` ``query`` and ``query_bulk``
functions if available (#246).
* Addition of ``is_prepared`` predicate (#252).
* Ensure that ``python setup.py clean`` removes all previously Cythonized and compiled
files (#239).
* Addition of a ``reverse`` function for GEOS >= 3.7 (#254).
Expand Down
13 changes: 8 additions & 5 deletions pygeos/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def geometrycollections(geometries):


def prepare(geometry, **kwargs):
"""Compute a prepared geometry.
"""Prepare a geometry, improving performance of other operations.

A prepared geometry is a normal geometry with added information such as an
index on the line segments. This improves the performance of the following operations:
Expand All @@ -191,16 +191,18 @@ def prepare(geometry, **kwargs):
Parameters
----------
geometry : Geometry or array_like
Geometries are changed inplace

See also
--------
destroy_prepared
is_prepared : Identify whether a geometry is prepared already.
destroy_prepared : Destroy the prepared part of a geometry.
"""
return lib.prepare(geometry, **kwargs)
lib.prepare(geometry, **kwargs)


def destroy_prepared(geometry, **kwargs):
"""Destroy a previously prepared geometry, freeing up memory.
"""Destroy the prepared part of a geometry, freeing up memory.

Note that the prepared geometry will always be cleaned up if the geometry itself
is dereferenced. This function needs only be called in very specific circumstances,
Expand All @@ -209,9 +211,10 @@ def destroy_prepared(geometry, **kwargs):
Parameters
----------
geometry : Geometry or array_like
Geometries are changed inplace

See also
--------
prepare
"""
return lib.destroy_prepared(geometry, **kwargs)
lib.destroy_prepared(geometry, **kwargs)
35 changes: 35 additions & 0 deletions pygeos/predicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"is_empty",
"is_geometry",
"is_missing",
"is_prepared",
"is_ring",
"is_simple",
"is_valid",
Expand Down Expand Up @@ -187,6 +188,40 @@ def is_missing(geometry, **kwargs):
"""
return lib.is_missing(geometry, **kwargs)


@multithreading_enabled
def is_prepared(geometry, **kwargs):
"""Returns True if a Geometry is prepared.

Note that it is not necessary to check if a geometry is already prepared
before preparing it. It is more efficient to call ``prepare`` directly
because it will skip geometries that are already prepared.

This function will return False for missing geometries (None).

Parameters
----------
geometry : Geometry or array_like

See also
--------
is_valid_input : check if an object is a geometry or None
prepare : prepare a geometry

Examples
--------
>>> geometry = Geometry("POINT (0 0)")
>>> is_prepared(Geometry("POINT (0 0)"))
False
>>> from pygeos import prepare; prepare(geometry);
>>> is_prepared(geometry)
True
>>> is_prepared(None)
False
"""
return lib.is_prepared(geometry, **kwargs)


@multithreading_enabled
def is_valid_input(geometry, **kwargs):
"""Returns True if the object is a geometry or None
Expand Down
20 changes: 18 additions & 2 deletions pygeos/test/test_predicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
pygeos.is_missing,
pygeos.is_geometry,
pygeos.is_valid_input,
pygeos.is_prepared,
pytest.param(pygeos.is_ccw, marks=pytest.mark.skipif(pygeos.geos_version < (3, 7, 0), reason="GEOS < 3.7")),
)

Expand Down Expand Up @@ -165,10 +166,25 @@ def test_is_ccw(geom, expected):
assert pygeos.is_ccw(geom) == expected


def _prepare_with_copy(geometry):
"""Prepare without modifying inplace"""
geometry = pygeos.apply(geometry, lambda x: x) # makes a copy
pygeos.prepare(geometry)
return geometry


@pytest.mark.parametrize("a", all_types)
@pytest.mark.parametrize("func", BINARY_PREPARED_PREDICATES)
def test_binary_prepared(a, func):
actual = func(a, point)
pygeos.lib.prepare(a)
result = func(a, point)
result = func(_prepare_with_copy(a), point)
assert actual == result

@pytest.mark.parametrize("geometry", all_types + (empty,))
def test_is_prepared_true(geometry):
assert pygeos.is_prepared(_prepare_with_copy(geometry))


@pytest.mark.parametrize("geometry", all_types + (empty, None))
def test_is_prepared_false(geometry):
assert not pygeos.is_prepared(geometry)
2 changes: 2 additions & 0 deletions src/pygeom.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ char get_geom_with_prepared(GeometryObject* obj, GEOSGeometry** out,
if (*out != NULL) {
// Only if it is not None, fill the prepared geometry
*prep = obj->ptr_prepared;
} else {
*prep = NULL;
}
return 1;
}
Expand Down
22 changes: 22 additions & 0 deletions src/ufuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,27 @@ static void YY_b_p_func(char** args, npy_intp* dimensions, npy_intp* steps, void
}
static PyUFuncGenericFunction YY_b_p_funcs[1] = {&YY_b_p_func};

static char is_prepared_dtypes[2] = {NPY_OBJECT, NPY_BOOL};
static void is_prepared_func(char** args, npy_intp* dimensions, npy_intp* steps,
void* data) {
GEOSGeometry* in1 = NULL;
GEOSPreparedGeometry* in1_prepared = NULL;

GEOS_INIT_THREADS;

UNARY_LOOP {
/* get the geometry: return on error */
if (!get_geom_with_prepared(*(GeometryObject**)ip1, &in1, &in1_prepared)) {
errstate = PGERR_NOT_A_GEOMETRY;
break;
}
*(npy_bool*)op1 = (in1_prepared != NULL);
}

GEOS_FINISH_THREADS;
}
static PyUFuncGenericFunction is_prepared_funcs[1] = {&is_prepared_func};

/* Define the geom -> geom functions (Y_Y) */
static void* envelope_data[1] = {GEOSEnvelope_r};
static void* convex_hull_data[1] = {GEOSConvexHull_r};
Expand Down Expand Up @@ -2530,6 +2551,7 @@ int init_ufuncs(PyObject* m, PyObject* d) {
DEFINE_YY_b(equals);
DEFINE_YY_b_p(covers);
DEFINE_YY_b_p(covered_by);
DEFINE_CUSTOM(is_prepared, 1);

DEFINE_Y_Y(envelope);
DEFINE_Y_Y(convex_hull);
Expand Down