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

Implement and Test All non-multi-Feature Spatial Predicate Combinations #1064

Merged
Show file tree
Hide file tree
Changes from 152 commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
96b28a3
Work on the most obvious parts of allpairs_points_equals_count
thomcom Mar 30, 2023
b8785f7
Build system.
thomcom Mar 30, 2023
c6e3910
Try a hand at copying point_polygon_distance_test.cu
thomcom Mar 30, 2023
45c128c
recording progress with Thomson
isVoid Mar 30, 2023
0f0a0d4
fix 0 sized input error
isVoid Mar 31, 2023
d1fb60c
Pass all tests.
thomcom Mar 31, 2023
da247f8
Switch to atomicAdd
thomcom Mar 31, 2023
2b7d7fa
Write one more test.
thomcom Mar 31, 2023
dd01d6c
using sort-then-search algorithm
isVoid Mar 31, 2023
b4ac329
Resolve merge
thomcom Mar 31, 2023
3dc6195
passes compilation!
isVoid Mar 31, 2023
9931ed1
Merge
thomcom Mar 31, 2023
dbd1bbf
Cleaning up for PR.
thomcom Mar 31, 2023
bd03668
Update docs, fix a typo.
thomcom Mar 31, 2023
313c020
Rename cpp test.
thomcom Mar 31, 2023
1c1e7ce
Strange test error.
thomcom Mar 31, 2023
28d5c13
Write python bindings.
thomcom Mar 31, 2023
6abb44e
Build python bindings and test.
thomcom Mar 31, 2023
c400646
Update cpp/include/cuspatial/experimental/detail/allpairs_multipoint_…
thomcom Mar 31, 2023
d2ac985
Update cpp/include/cuspatial/allpairs_multipoint_equals_count.hpp
thomcom Mar 31, 2023
23f4363
Update cpp/tests/experimental/spatial/allpairs_multipoint_equals_coun…
thomcom Mar 31, 2023
63eea9d
Add specific test.
thomcom Apr 3, 2023
29050fc
Merge branch 'feature/allpairs_point_equals_count' of github.com:thom…
thomcom Apr 3, 2023
30c9c86
refactors to multipoint-multipoint pairwise
isVoid Apr 5, 2023
2d64f3b
add missing files
isVoid Apr 5, 2023
f99810f
Get all tests passing.
thomcom Apr 5, 2023
7f606f9
Fix a bug in column wrapper.
thomcom Apr 6, 2023
c8ae2dd
Merge branch 'branch-23.04' into feature/allpairs_point_equals_count
thomcom Apr 6, 2023
ec24574
Make test untyped.:
thomcom Apr 6, 2023
b1f6207
Update docs
thomcom Apr 7, 2023
0050be0
Transfer python updates from later branch.
thomcom Apr 7, 2023
c178414
Improve .cpp file testing based on length requirement.
thomcom Apr 7, 2023
719d065
Tweak error message.
thomcom Apr 7, 2023
05090bb
Update equals_count docs and tests.
thomcom Apr 7, 2023
ca1218d
Minor docs tweak.
thomcom Apr 7, 2023
76c8aac
Remove repeat tests.
thomcom Apr 7, 2023
5c78146
Fix docs
thomcom Apr 7, 2023
e3aeac7
Merge branch 'branch-23.06' into feature/allpairs_point_equals_count
thomcom Apr 7, 2023
e0bba71
Merge branch 'branch-23.06' into feature/allpairs_point_equals_count
thomcom Apr 10, 2023
3d28ee9
Update cpp/include/cuspatial/experimental/detail/pairwise_multipoint_…
thomcom Apr 19, 2023
32050f9
Doc tweak
thomcom Apr 19, 2023
2420dfe
Merge branch 'feature/allpairs_point_equals_count' of github.com:thom…
thomcom Apr 19, 2023
ac9b755
Update cpp/include/cuspatial/pairwise_multipoint_equals_count.hpp
thomcom Apr 19, 2023
d904762
Update cpp/include/cuspatial/pairwise_multipoint_equals_count.hpp
thomcom Apr 19, 2023
102915b
Update python/cuspatial/cuspatial/core/binops/equals_count.py
thomcom Apr 19, 2023
72d6e97
Merge branch 'feature/allpairs_point_equals_count' of github.com:thom…
thomcom Apr 19, 2023
a806371
Merge branch 'branch-23.06' into feature/allpairs_point_equals_count
thomcom Apr 19, 2023
fbcd2bd
Update python/cuspatial/cuspatial/core/binops/equals_count.py
thomcom Apr 19, 2023
f7c2c98
Update cpp/include/cuspatial/experimental/pairwise_multipoint_equals_…
thomcom Apr 19, 2023
89a54c5
Address comment about multipoint_range docs.
thomcom Apr 19, 2023
37cba19
Merge branch 'feature/allpairs_point_equals_count' of github.com:thom…
thomcom Apr 19, 2023
e63c594
Tweaking because of format issue.
thomcom Apr 19, 2023
66498cf
Tweaking problem with docs.
thomcom Apr 19, 2023
ce1df18
Repair docs?
thomcom Apr 19, 2023
07401fe
CR at beginning of file typo
thomcom Apr 19, 2023
86ad906
First commit of test dispatch branch.
thomcom Apr 19, 2023
1a0072c
Enable xfail.
thomcom Apr 19, 2023
b2ea930
Binpred test dispatch documented and ready for review.
thomcom Apr 19, 2023
dfcd583
Fix bug in test list.
thomcom Apr 19, 2023
1766437
Basic binpred first fork of big PR.
thomcom Apr 19, 2023
1ff4589
Forgot geoseries.py
thomcom Apr 19, 2023
367a420
Refactor contains and contains properly and pass all tests.
thomcom Apr 19, 2023
fbc1618
Remove unneeded predicate.
thomcom Apr 19, 2023
873525a
Tweak docs.
thomcom Apr 19, 2023
0d84603
Clean up docs in feature_contains.py
thomcom Apr 19, 2023
e4132b0
Clean up contains_properly docs.
thomcom Apr 19, 2023
8dfca13
Clean up ContainsProperlyByIntersection.
thomcom Apr 19, 2023
a3d8b8a
Clean up WithinIntersectsPredicate.
thomcom Apr 19, 2023
008631e
Write docs for geoseries.sizes
thomcom Apr 19, 2023
550fa9b
Clean up docs and write docstrings for all _basic utility methods.
thomcom Apr 19, 2023
f45acda
Document and improve binpred_utils.py
thomcom Apr 19, 2023
7198f40
Move files from master branch to new PR.
thomcom Apr 19, 2023
eaee84c
Updating
thomcom Apr 19, 2023
9614dff
Merge
thomcom Apr 19, 2023
fc1ca25
Fix a bad test.
thomcom Apr 20, 2023
b651aaf
Merge
thomcom Apr 20, 2023
8e83ec1
Merge binpred_test_dispatch
thomcom Apr 20, 2023
6a931bb
Pass a couple of tests.
thomcom Apr 20, 2023
ae39c88
Back to 26 failed. Working on within, touches, and crosses only.
thomcom Apr 20, 2023
a48dbbf
Lots of changes trying to get contains working as expected.
thomcom Apr 20, 2023
c0dd549
Create arduous points_and_lines_to_multipoints function.
thomcom Apr 21, 2023
753334c
Pass all contains tests.
thomcom Apr 21, 2023
a5ec83a
Resolve new indexing bug related to fixing a bug in geoseries.
thomcom Apr 21, 2023
1a2456a
Remove breakpoints and pass a couple of old bug tests.
thomcom Apr 22, 2023
a394ea6
Pass all non-binpred-dispatch tests.
thomcom Apr 22, 2023
410fd07
Pass all touches and more
thomcom Apr 23, 2023
bd5aebf
Five failing tests.
thomcom Apr 24, 2023
1c98d6d
Working on the last few cases that depend on variations of .contains …
thomcom Apr 24, 2023
57517cd
296/297 predicates.
thomcom Apr 25, 2023
3fc9d44
Pass 100% of tests!
thomcom Apr 26, 2023
32c9e0a
Merge branch 'branch-23.06' into feature/_basic_binpreds
thomcom Apr 26, 2023
713a27a
Resolve merge
thomcom Apr 27, 2023
d0138c9
Resolve missed merge files.
thomcom Apr 27, 2023
e60af29
Return whitespace.
thomcom Apr 27, 2023
85676d1
Still working on missed files.
thomcom Apr 27, 2023
f64b461
Rename CMakeFiles
thomcom Apr 27, 2023
ddda72c
One too many files.
thomcom Apr 27, 2023
1c0a018
Merge branch 'branch-23.06' into feature/_basic_binpreds
thomcom Apr 27, 2023
0d7ca82
Pull similar files from the master branch.
thomcom Apr 27, 2023
12fa90f
Rename points back to final_rhs
thomcom Apr 27, 2023
b45a731
Update docs a bit.
thomcom Apr 27, 2023
d753bf0
Merge branch 'feature/_basic_binpreds' into feature/binary-predicate-…
thomcom Apr 27, 2023
fe978a3
Add mode argument docs.
thomcom Apr 27, 2023
3b68ec2
Rename complex_geometry_predicate and cleaning up ContainsPredicates.
thomcom Apr 27, 2023
aae2f28
Updating contains and contains_properly to be neater.
thomcom Apr 27, 2023
5924fd0
Merge branch 'feature/_basic_binpreds' into feature/binary-predicate-…
thomcom Apr 27, 2023
96e442e
Cleaning up things throughout.
thomcom Apr 27, 2023
37daece
Cleaning up intersects and within
thomcom Apr 27, 2023
7b52117
Delete unused _basic functions.
thomcom Apr 27, 2023
d7fffac
Remove unsupported test.
thomcom Apr 27, 2023
675f145
Reduce the number of basic predicates.
thomcom Apr 27, 2023
2015405
Missed a couple of ContainsPredicateBases
thomcom Apr 27, 2023
0698322
Updating comments for confusing sections.
thomcom Apr 27, 2023
4fd668e
Begin cleaning up intersects.
thomcom Apr 27, 2023
3de22b3
Theoretically well refactored intersects.
thomcom Apr 27, 2023
195028d
Still pass all tests.
thomcom Apr 27, 2023
6433096
Add another linestring example that proves touches.
thomcom Apr 28, 2023
32a18de
Add complex polygons test to .contains test. It passes!
thomcom Apr 28, 2023
9e65cb4
Update python/cuspatial/cuspatial/core/binpreds/feature_contains_prop…
thomcom Apr 28, 2023
8a1d234
Handle review comments.
thomcom Apr 28, 2023
c433949
Drop one useless inheritance.
thomcom Apr 28, 2023
24e4d9a
Update python/cuspatial/cuspatial/core/geoseries.py
thomcom Apr 28, 2023
a86fb2b
Change error type of mixed geometry geoseries.sizes call.
thomcom Apr 28, 2023
e9dd49e
Merge branch 'feature/_basic_binpreds' of github.com:thomcom/cuspatia…
thomcom Apr 28, 2023
c813ba7
Remove local imports from _basic_predicates.
thomcom Apr 28, 2023
c3d03cb
Get rid of intesrsects_through
thomcom Apr 28, 2023
5814380
Merge branch 'feature/_basic_binpreds' into feature/binary-predicate-…
thomcom Apr 28, 2023
a2bf9d3
Get rid of through call
thomcom Apr 28, 2023
92c918c
Move _basic_predicates into a dedicated file. Handle various review c…
thomcom May 2, 2023
86dd5b3
Update python/cuspatial/cuspatial/core/geoseries.py
thomcom May 2, 2023
4f6f8a8
Update python/cuspatial/cuspatial/core/geoseries.py
thomcom May 2, 2023
c14b4ca
Update python/cuspatial/cuspatial/core/geoseries.py
thomcom May 2, 2023
6e8f6ee
Merge branch 'feature/_basic_binpreds' of github.com:thomcom/cuspatia…
thomcom May 2, 2023
72ad8c9
Update contains predicate docs.
thomcom May 2, 2023
6c6f097
Refactor use of quadtree and language.
thomcom May 2, 2023
c875787
Merge branch 'feature/_basic_binpreds' into feature/binary-predicate-…
thomcom May 2, 2023
43c50ab
Refactor basic predicates.
thomcom May 2, 2023
d628a44
Update python/cuspatial/cuspatial/core/geoseries.py
thomcom May 4, 2023
2eb4b32
Handle @isVoid's final comments.
thomcom May 4, 2023
81d85f5
Merge branch 'feature/_basic_binpreds' of github.com:thomcom/cuspatia…
thomcom May 4, 2023
14ec9d7
Merge branch 'branch-23.06' into feature/_basic_binpreds
thomcom May 4, 2023
9855137
Style
thomcom May 4, 2023
ffa7141
Merge branch 'feature/_basic_binpreds' into feature/binary-predicate-…
thomcom May 4, 2023
35d6bec
Merge branch 'branch-23.06' into feature/binary-predicate-manual-test…
thomcom May 4, 2023
f9b2df6
Disable logging without environment variable.
thomcom May 8, 2023
961d199
Replace missing geoseries tests and clean up touches and binpreds test.
thomcom May 8, 2023
ebc33b8
Enable previosly unsupported tests.
thomcom May 9, 2023
30eded7
Add deeper docs to _points_and_lines_to_multipoints
thomcom May 17, 2023
ded3d74
Resolve core issue with LineStringLineStringTouches and Crosses.
thomcom May 18, 2023
55bac02
Improve PolygonPolygonTouches handling of edge overlapping cases.
thomcom May 18, 2023
ba4e5c6
Add a new test case that blew up linestringlinestring touches and cov…
thomcom May 18, 2023
805d5f3
Improve PolygonLineStringCovers.
thomcom May 18, 2023
9f27a62
Merge branch 'branch-23.06' into feature/binary-predicate-manual-test…
thomcom May 25, 2023
69691d8
Final tweaks.
thomcom May 25, 2023
227bd88
Merge branch 'branch-23.06' into feature/binary-predicate-manual-test…
thomcom May 26, 2023
a999014
Merge branch 'branch-23.06' into feature/binary-predicate-manual-test…
thomcom May 26, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
)


def _basic_equals(lhs, rhs):
def _basic_equals_any(lhs, rhs):
"""Utility method that returns True if any point in the lhs geometry
is equal to a point in the rhs geometry."""
lhs = _multipoints_from_geometry(lhs)
Expand Down
15 changes: 10 additions & 5 deletions python/cuspatial/cuspatial/core/binpreds/feature_contains.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from cuspatial.core.binpreds.basic_predicates import (
_basic_contains_count,
_basic_equals,
_basic_equals_any,
_basic_equals_count,
_basic_intersects,
_basic_intersects_pli,
Expand Down Expand Up @@ -132,20 +132,25 @@ def _compute_predicate(self, lhs, rhs, preprocessor_result):

class PointPointContains(BinPred):
def _preprocess(self, lhs, rhs):
return _basic_equals(lhs, rhs)
return _basic_equals_any(lhs, rhs)


class LineStringPointContains(BinPred):
def _preprocess(self, lhs, rhs):
intersects = _basic_intersects(lhs, rhs)
equals = _basic_equals(lhs, rhs)
equals = _basic_equals_any(lhs, rhs)
return intersects & ~equals


class LineStringLineStringContainsPredicate(BinPred):
def _preprocess(self, lhs, rhs):
count = _basic_equals_count(lhs, rhs)
return count == rhs.sizes
# A linestring A covers another linestring B iff
Copy link
Member

Choose a reason for hiding this comment

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

Is this comment correct? This is contains, not covers. The code for the two looks the same. Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that in the context of LineString+LineString, .contains and .covers are equivalent. This comment persisting in feature_contains.py is not correct, thanks!

https://postgis.net/docs/ST_Covers.html
https://postgis.net/docs/ST_Contains.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

import geopandas
from cuspatial.tests.binpreds.binpred_test_dispatch import (
    features,
    linestring_linestring_dispatch_list,
)
def sample_test_data(features, dispatch_list, size, lib=cuspatial):
    geometry_tuples = [features[key][1:3] for key in dispatch_list]
    geometries = [
        [lhs_geo for lhs_geo, _ in geometry_tuples],
        [rhs_geo for _, rhs_geo in geometry_tuples]
    ]
    lhs = lib.GeoSeries(list(geometries[0]))
    rhs = lib.GeoSeries(list(geometries[1]))
    if lib == geopandas:
        rng = np
    else:
        rng = cp
    rng.random.seed()
    lhs_picks = rng.random.randint(0, len(lhs), size)
    rhs_picks = rng.random.randint(0, len(rhs), size)
    return (
        lhs[lhs_picks].reset_index(drop=True),
        rhs[rhs_picks].reset_index(drop=True)
    )
lhs, rhs = sample_test_data(features, linestring_linestring_dispatch_list, 1000, geopandas)
(lhs.contains(rhs) == lhs.covers(rhs)).all()
True

# no point in B is outside of A.
pli = _basic_intersects_pli(lhs, rhs)
points = _points_and_lines_to_multipoints(pli[1], pli[0])
# Every point in B must be in the intersection
equals = _basic_equals_count(rhs, points) == rhs.sizes
return equals


"""DispatchDict listing the classes to use for each combination of
Expand Down
71 changes: 63 additions & 8 deletions python/cuspatial/cuspatial/core/binpreds/feature_covers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
# Copyright (c) 2023, NVIDIA CORPORATION.

from cuspatial.core.binpreds.binpred_interface import NotImplementedPredicate
from cuspatial.core.binpreds.basic_predicates import (
_basic_contains_any,
_basic_contains_count,
_basic_equals_count,
_basic_intersects_pli,
)
from cuspatial.core.binpreds.binpred_interface import (
BinPred,
ImpossiblePredicate,
NotImplementedPredicate,
)
from cuspatial.core.binpreds.feature_equals import EqualsPredicateBase
from cuspatial.core.binpreds.feature_intersects import (
LineStringPointIntersects,
PointLineStringIntersects,
)
from cuspatial.utils.binpred_utils import (
LineString,
MultiPoint,
Point,
Polygon,
_points_and_lines_to_multipoints,
_zero_series,
)


Expand All @@ -36,21 +47,65 @@ class CoversPredicateBase(EqualsPredicateBase):
pass


class LineStringLineStringCovers(BinPred):
Copy link
Member

Choose a reason for hiding this comment

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

I can't comment on non-changed lines, but please don't add documentation that will go stale quickly, e.g. "in this initial release". Also, the fact that it is implemented using only the equals predicate is an implementation detail, not a feature of the API. Public documentation should cover features and usage of the API, not implementation details.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the clarification, those docs and others definitely needed a cleanup.

def _preprocess(self, lhs, rhs):
# A linestring A covers another linestring B iff
# no point in B is outside of A.
pli = _basic_intersects_pli(lhs, rhs)
points = _points_and_lines_to_multipoints(pli[1], pli[0])
# Every point in B must be in the intersection
equals = _basic_equals_count(rhs, points) == rhs.sizes
return equals


class PolygonPointCovers(BinPred):
def _preprocess(self, lhs, rhs):
return _basic_contains_any(lhs, rhs)
isVoid marked this conversation as resolved.
Show resolved Hide resolved


class PolygonLineStringCovers(BinPred):
def _preprocess(self, lhs, rhs):
isVoid marked this conversation as resolved.
Show resolved Hide resolved
# A polygon covers a linestring if all of the points in the linestring
# are in the interior or exterior of the polygon. This differs from
# a polygon that contains a linestring in that some point of the
# linestring must be in the interior of the polygon.
# Count the number of points from rhs in the interior of lhs
contains_count = _basic_contains_count(lhs, rhs)
# Now count the number of points from rhs in the boundary of lhs
pli = _basic_intersects_pli(lhs, rhs)
intersections = pli[1]
# There may be no intersection, so start with _zero_series
equality = _zero_series(len(rhs))
if len(intersections) > 0:
matching_length_multipoints = _points_and_lines_to_multipoints(
intersections, pli[0]
)
equality = _basic_equals_count(matching_length_multipoints, rhs)
covers = contains_count + equality >= rhs.sizes
return covers


class PolygonPolygonCovers(BinPred):
def _preprocess(self, lhs, rhs):
contains = lhs.contains(rhs)
return contains


DispatchDict = {
(Point, Point): CoversPredicateBase,
(Point, MultiPoint): NotImplementedPredicate,
(Point, LineString): PointLineStringIntersects,
(Point, Polygon): CoversPredicateBase,
(Point, LineString): ImpossiblePredicate,
(Point, Polygon): ImpossiblePredicate,
(MultiPoint, Point): NotImplementedPredicate,
(MultiPoint, MultiPoint): NotImplementedPredicate,
(MultiPoint, LineString): NotImplementedPredicate,
(MultiPoint, Polygon): NotImplementedPredicate,
(LineString, Point): LineStringPointIntersects,
(LineString, MultiPoint): NotImplementedPredicate,
(LineString, LineString): NotImplementedPredicate,
(LineString, LineString): LineStringLineStringCovers,
(LineString, Polygon): CoversPredicateBase,
(Polygon, Point): CoversPredicateBase,
(Polygon, Point): PolygonPointCovers,
(Polygon, MultiPoint): CoversPredicateBase,
(Polygon, LineString): CoversPredicateBase,
(Polygon, Polygon): CoversPredicateBase,
(Polygon, LineString): PolygonLineStringCovers,
(Polygon, Polygon): PolygonPolygonCovers,
}
58 changes: 46 additions & 12 deletions python/cuspatial/cuspatial/core/binpreds/feature_crosses.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
# Copyright (c) 2023, NVIDIA CORPORATION.

from cuspatial.core.binpreds.basic_predicates import (
_basic_equals_count,
_basic_intersects_count,
_basic_intersects_pli,
)
from cuspatial.core.binpreds.binpred_interface import (
BinPred,
ImpossiblePredicate,
NotImplementedPredicate,
)
from cuspatial.core.binpreds.feature_equals import EqualsPredicateBase
from cuspatial.core.binpreds.feature_intersects import IntersectsPredicateBase
from cuspatial.utils.binpred_utils import (
LineString,
MultiPoint,
Point,
Polygon,
_false_series,
_points_and_lines_to_multipoints,
)


Expand All @@ -30,6 +37,33 @@ class CrossesPredicateBase(EqualsPredicateBase):
pass


class LineStringLineStringCrosses(IntersectsPredicateBase):
def _compute_predicate(self, lhs, rhs, preprocessor_result):
# A linestring crosses another linestring iff
# they intersect, and none of the points of the
# intersection are in the boundary of the other
pli = _basic_intersects_pli(rhs, lhs)
intersections = _points_and_lines_to_multipoints(pli[1], pli[0])
equals = (_basic_equals_count(intersections, lhs) > 0) | (
_basic_equals_count(intersections, rhs) > 0
)
intersects = _basic_intersects_count(rhs, lhs) > 0
return intersects & ~equals


class LineStringPolygonCrosses(BinPred):
def _preprocess(self, lhs, rhs):
intersects = _basic_intersects_count(rhs, lhs) > 1
touches = rhs.touches(lhs)
contains = rhs.contains(lhs)
return ~touches & intersects & ~contains


class PolygonLineStringCrosses(LineStringPolygonCrosses):
def _preprocess(self, lhs, rhs):
return super()._preprocess(rhs, lhs)


class PointPointCrosses(CrossesPredicateBase):
def _preprocess(self, lhs, rhs):
"""Points can't cross other points, so we return False."""
Expand All @@ -38,19 +72,19 @@ def _preprocess(self, lhs, rhs):

DispatchDict = {
(Point, Point): PointPointCrosses,
(Point, MultiPoint): NotImplementedPredicate,
(Point, LineString): NotImplementedPredicate,
(Point, MultiPoint): ImpossiblePredicate,
(Point, LineString): ImpossiblePredicate,
(Point, Polygon): CrossesPredicateBase,
(MultiPoint, Point): NotImplementedPredicate,
(MultiPoint, MultiPoint): NotImplementedPredicate,
(MultiPoint, LineString): NotImplementedPredicate,
(MultiPoint, Polygon): NotImplementedPredicate,
(MultiPoint, Point): ImpossiblePredicate,
(MultiPoint, MultiPoint): ImpossiblePredicate,
(MultiPoint, LineString): ImpossiblePredicate,
(MultiPoint, Polygon): ImpossiblePredicate,
(LineString, Point): ImpossiblePredicate,
(LineString, MultiPoint): NotImplementedPredicate,
(LineString, LineString): NotImplementedPredicate,
(LineString, Polygon): NotImplementedPredicate,
(LineString, MultiPoint): ImpossiblePredicate,
(LineString, LineString): LineStringLineStringCrosses,
(LineString, Polygon): LineStringPolygonCrosses,
(Polygon, Point): CrossesPredicateBase,
(Polygon, MultiPoint): CrossesPredicateBase,
(Polygon, LineString): CrossesPredicateBase,
(Polygon, Polygon): CrossesPredicateBase,
(Polygon, LineString): PolygonLineStringCrosses,
(Polygon, Polygon): ImpossiblePredicate,
}
59 changes: 37 additions & 22 deletions python/cuspatial/cuspatial/core/binpreds/feature_disjoint.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Copyright (c) 2023, NVIDIA CORPORATION.

from cuspatial.core.binpreds.basic_predicates import (
_basic_contains_any,
_basic_intersects,
)
from cuspatial.core.binpreds.binpred_interface import (
BinPred,
NotImplementedPredicate,
)
from cuspatial.core.binpreds.feature_intersects import (
IntersectsPredicateBase,
PointLineStringIntersects,
)
from cuspatial.core.binpreds.feature_intersects import IntersectsPredicateBase
from cuspatial.utils.binpred_utils import (
LineString,
MultiPoint,
Expand All @@ -16,7 +17,7 @@
)


class ContainsDisjoint(BinPred):
class DisjointByWayOfContains(BinPred):
def _preprocess(self, lhs, rhs):
"""Disjoint is the opposite of contains, so just implement contains
and then negate the result.
Expand All @@ -26,20 +27,22 @@ def _preprocess(self, lhs, rhs):
(Point, Polygon)
(Polygon, Point)
"""
from cuspatial.core.binpreds.binpred_dispatch import CONTAINS_DISPATCH
return ~_basic_contains_any(lhs, rhs)

predicate = CONTAINS_DISPATCH[(lhs.column_type, rhs.column_type)](
align=self.config.align
)
return ~predicate(lhs, rhs)


class PointLineStringDisjoint(PointLineStringIntersects):
def _postprocess(self, lhs, rhs, op_result):
class PointLineStringDisjoint(BinPred):
def _preprocess(self, lhs, rhs):
"""Disjoint is the opposite of intersects, so just implement intersects
and then negate the result."""
result = super()._postprocess(lhs, rhs, op_result)
return ~result
intersects = _basic_intersects(lhs, rhs)
return ~intersects


class PointPolygonDisjoint(BinPred):
def _preprocess(self, lhs, rhs):
intersects = _basic_intersects(lhs, rhs)
contains = _basic_contains_any(lhs, rhs)
return ~intersects & ~contains


class LineStringPointDisjoint(PointLineStringDisjoint):
Expand All @@ -56,21 +59,33 @@ def _postprocess(self, lhs, rhs, op_result):
return ~result


class LineStringPolygonDisjoint(BinPred):
def _preprocess(self, lhs, rhs):
intersects = _basic_intersects(lhs, rhs)
contains = _basic_contains_any(rhs, lhs)
return ~intersects & ~contains


class PolygonPolygonDisjoint(BinPred):
def _preprocess(self, lhs, rhs):
return ~_basic_contains_any(lhs, rhs) & ~_basic_contains_any(rhs, lhs)


DispatchDict = {
(Point, Point): ContainsDisjoint,
(Point, Point): DisjointByWayOfContains,
(Point, MultiPoint): NotImplementedPredicate,
(Point, LineString): PointLineStringDisjoint,
(Point, Polygon): ContainsDisjoint,
(Point, Polygon): PointPolygonDisjoint,
(MultiPoint, Point): NotImplementedPredicate,
(MultiPoint, MultiPoint): NotImplementedPredicate,
(MultiPoint, LineString): NotImplementedPredicate,
(MultiPoint, Polygon): NotImplementedPredicate,
(MultiPoint, Polygon): LineStringPolygonDisjoint,
(LineString, Point): LineStringPointDisjoint,
(LineString, MultiPoint): NotImplementedPredicate,
(LineString, LineString): LineStringLineStringDisjoint,
(LineString, Polygon): NotImplementedPredicate,
(Polygon, Point): ContainsDisjoint,
(LineString, Polygon): LineStringPolygonDisjoint,
(Polygon, Point): DisjointByWayOfContains,
(Polygon, MultiPoint): NotImplementedPredicate,
(Polygon, LineString): NotImplementedPredicate,
(Polygon, Polygon): NotImplementedPredicate,
(Polygon, LineString): DisjointByWayOfContains,
(Polygon, Polygon): PolygonPolygonDisjoint,
}
13 changes: 11 additions & 2 deletions python/cuspatial/cuspatial/core/binpreds/feature_equals.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from cuspatial.core.binpreds.binpred_interface import (
BinPred,
EqualsOpResult,
ImpossiblePredicate,
NotImplementedPredicate,
PreprocessorResult,
)
Expand Down Expand Up @@ -334,11 +335,19 @@ def _preprocess(self, lhs, rhs):
return _false_series(len(lhs))


class PolygonPolygonEquals(BinPred):
def _preprocess(self, lhs, rhs):
"""Two polygons are equal if they contain each other."""
lhs_contains_rhs = lhs.contains(rhs)
rhs_contains_lhs = rhs.contains(lhs)
return lhs_contains_rhs & rhs_contains_lhs


"""DispatchDict for Equals operations."""
DispatchDict = {
(Point, Point): EqualsPredicateBase,
(Point, MultiPoint): NotImplementedPredicate,
(Point, LineString): NotImplementedPredicate,
(Point, LineString): ImpossiblePredicate,
(Point, Polygon): EqualsPredicateBase,
(MultiPoint, Point): NotImplementedPredicate,
(MultiPoint, MultiPoint): MultiPointMultiPointEquals,
Expand All @@ -351,5 +360,5 @@ def _preprocess(self, lhs, rhs):
(Polygon, Point): EqualsPredicateBase,
(Polygon, MultiPoint): EqualsPredicateBase,
(Polygon, LineString): EqualsPredicateBase,
(Polygon, Polygon): EqualsPredicateBase,
(Polygon, Polygon): PolygonPolygonEquals,
}
Loading