locationtech / locationtech/spatial4j
Contains vs Within ambiguity for equal shapes
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 961
- Forks
- 172
- PR merge metrics
- No merged PRs in 30d
Description
When two shapes are equal, the shape.relate(otherShape) method can ambiguously return either Contains or Within. If the caller wants to know specifically if the relationship is Contains (or Within) it can test to see if they are equal if relate() returns Within (or Contains).
Once we introduce aggregate shapes (e.g. ShapeCollection), the aforementioned equality test isn't good enough because the ShapeCollection.relate() doesn't know if the caller prefers Within or Contains. And that's the problem.
One approach taken in SpatialOpRecursivePrefixTreeTest in Lucene spatial is a ShapePair class that has a boolean bias flag to prefer Contains or Within first. It looks something like this:
private SpatialRelation relateApprox(Shape other) {
if (biasContainsThenWithin) {
if (shape1.relate(other) == CONTAINS || shape1.equals(other)
|| shape2.relate(other) == CONTAINS || shape2.equals(other)) return CONTAINS;
if (shape1.relate(other) == WITHIN && shape2.relate(other) == WITHIN) return WITHIN;
} else {
if ((shape1.relate(other) == WITHIN || shape1.equals(other))
&& (shape2.relate(other) == WITHIN || shape2.equals(other))) return WITHIN;
if (shape1.relate(other) == CONTAINS || shape2.relate(other) == CONTAINS) return CONTAINS;
}
if (shape1.relate(other).intersects() || shape2.relate(other).intersects())
return INTERSECTS;//might actually be 'CONTAINS' if these 2 are adjacent
return DISJOINT;
}
Another possible approach (not mutually exclusive) is to establish a protocol in which the more "complex" shape (defaulting to the current shape, 'this', when both shapes are the same type) will always favor 'Contains'. Then if the caller prefers a bias of Within, it can just flip the who relates to who call. This isn't a complete approach that addresses all theoretical use cases, but known cases in Lucene spatial for example could work with this.
Another possible approach is to add a shape.hasRelation(relation, Shape other):boolean method. This would also give the potential for optimization because the implementation can focus on a yes-no answer instead of returning one of multiple possible enum values. However if the caller needs to know if it's Within OR Intersects OR ... (i.e. multiple conditions) then this optimization rationale evaporates.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Shape.relate and the proposed ShapeCollection behavior, then compare the ShapePair bias logic in SpatialOpRecursivePrefixTreeTest from Lucene spatial. Decide which relation-bias protocol or hasRelation API is required and define the equal-shape and aggregate-shape cases; done means the chosen semantics and scope are resolved for implementation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100