| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.lucene.geo; |
| |
| import org.apache.lucene.index.PointValues; |
| |
| import static org.apache.lucene.geo.GeoUtils.orient; |
| |
| /** |
| * 2D Geometry object that supports spatial relationships with bounding boxes, |
| * triangles and points. |
| * |
| * @lucene.internal |
| **/ |
| public interface Component2D { |
| |
| /** min X value for the component **/ |
| double getMinX(); |
| |
| /** max X value for the component **/ |
| double getMaxX(); |
| |
| /** min Y value for the component **/ |
| double getMinY(); |
| |
| /** max Y value for the component **/ |
| double getMaxY(); |
| |
| /** relates this component2D with a point **/ |
| boolean contains(double x, double y); |
| |
| /** relates this component2D with a bounding box **/ |
| PointValues.Relation relate(double minX, double maxX, double minY, double maxY); |
| |
| /** return true if this component2D intersects the provided line **/ |
| boolean intersectsLine(double minX, double maxX, double minY, double maxY, |
| double aX, double aY, double bX, double bY); |
| |
| /** return true if this component2D intersects the provided triangle **/ |
| boolean intersectsTriangle(double minX, double maxX, double minY, double maxY, |
| double aX, double aY, double bX, double bY, double cX, double cY); |
| |
| /** return true if this component2D contains the provided line **/ |
| boolean containsLine(double minX, double maxX, double minY, double maxY, |
| double aX, double aY, double bX, double bY); |
| |
| /** return true if this component2D contains the provided triangle **/ |
| boolean containsTriangle(double minX, double maxX, double minY, double maxY, |
| double aX, double aY, double bX, double bY, double cX, double cY); |
| |
| /** Used by withinTriangle to check the within relationship between a triangle and the query shape |
| * (e.g. if the query shape is within the triangle). */ |
| enum WithinRelation { |
| /** If the shape is a candidate for within. Typically this is return if the query shape is fully inside |
| * the triangle or if the query shape intersects only edges that do not belong to the original shape. */ |
| CANDIDATE, |
| /** The query shape intersects an edge that does belong to the original shape or any point of |
| * the triangle is inside the shape. */ |
| NOTWITHIN, |
| /** The query shape is disjoint with the triangle. */ |
| DISJOINT |
| } |
| |
| /** Compute the within relation of this component2D with a point **/ |
| WithinRelation withinPoint(double x, double y); |
| |
| /** Compute the within relation of this component2D with a line **/ |
| WithinRelation withinLine(double minX, double maxX, double minY, double maxY, |
| double aX, double aY, boolean ab, double bX, double bY); |
| |
| /** Compute the within relation of this component2D with a triangle **/ |
| WithinRelation withinTriangle(double minX, double maxX, double minY, double maxY, |
| double aX, double aY, boolean ab, double bX, double bY, boolean bc, double cX, double cY, boolean ca); |
| |
| |
| /** return true if this component2D intersects the provided line **/ |
| default boolean intersectsLine(double aX, double aY, double bX, double bY) { |
| double minY = StrictMath.min(aY, bY); |
| double minX = StrictMath.min(aX, bX); |
| double maxY = StrictMath.max(aY, bY); |
| double maxX = StrictMath.max(aX, bX); |
| return intersectsLine(minX, maxX, minY, maxY, aX, aY, bX, bY); |
| } |
| |
| /** return true if this component2D intersects the provided triangle **/ |
| default boolean intersectsTriangle(double aX, double aY, double bX, double bY, double cX, double cY) { |
| double minY = StrictMath.min(StrictMath.min(aY, bY), cY); |
| double minX = StrictMath.min(StrictMath.min(aX, bX), cX); |
| double maxY = StrictMath.max(StrictMath.max(aY, bY), cY); |
| double maxX = StrictMath.max(StrictMath.max(aX, bX), cX); |
| return intersectsTriangle(minX, maxX, minY, maxY, aX, aY, bX, bY, cX, cY); |
| } |
| |
| /** return true if this component2D contains the provided line **/ |
| default boolean containsLine(double aX, double aY, double bX, double bY) { |
| double minY = StrictMath.min(aY, bY); |
| double minX = StrictMath.min(aX, bX); |
| double maxY = StrictMath.max(aY, bY); |
| double maxX = StrictMath.max(aX, bX); |
| return containsLine(minX, maxX, minY, maxY, aX, aY, bX, bY); |
| } |
| |
| /** return true if this component2D contains the provided triangle **/ |
| default boolean containsTriangle(double aX, double aY, double bX, double bY, double cX, double cY) { |
| double minY = StrictMath.min(StrictMath.min(aY, bY), cY); |
| double minX = StrictMath.min(StrictMath.min(aX, bX), cX); |
| double maxY = StrictMath.max(StrictMath.max(aY, bY), cY); |
| double maxX = StrictMath.max(StrictMath.max(aX, bX), cX); |
| return containsTriangle(minX, maxX, minY, maxY, aX, aY, bX, bY, cX, cY); |
| } |
| |
| /** Compute the within relation of this component2D with a triangle **/ |
| default WithinRelation withinLine(double aX, double aY, boolean ab, double bX, double bY) { |
| double minY = StrictMath.min(aY, bY); |
| double minX = StrictMath.min(aX, bX); |
| double maxY = StrictMath.max(aY, bY); |
| double maxX = StrictMath.max(aX, bX); |
| return withinLine(minX, maxX, minY, maxY, aX, aY, ab, bX, bY); |
| } |
| |
| /** Compute the within relation of this component2D with a triangle **/ |
| default WithinRelation withinTriangle(double aX, double aY, boolean ab, double bX, double bY, boolean bc, double cX, double cY, boolean ca) { |
| double minY = StrictMath.min(StrictMath.min(aY, bY), cY); |
| double minX = StrictMath.min(StrictMath.min(aX, bX), cX); |
| double maxY = StrictMath.max(StrictMath.max(aY, bY), cY); |
| double maxX = StrictMath.max(StrictMath.max(aX, bX), cX); |
| return withinTriangle(minX, maxX, minY, maxY, aX, aY, ab, bX, bY, bc, cX, cY, ca); |
| } |
| |
| /** Compute whether the bounding boxes are disjoint **/ |
| static boolean disjoint(double minX1, double maxX1, double minY1, double maxY1, double minX2, double maxX2, double minY2, double maxY2) { |
| return (maxY1 < minY2 || minY1 > maxY2 || maxX1 < minX2 || minX1 > maxX2); |
| } |
| |
| /** Compute whether the first bounding box 1 is within the second bounding box **/ |
| static boolean within(double minX1, double maxX1, double minY1, double maxY1, double minX2, double maxX2, double minY2, double maxY2) { |
| return (minY2 <= minY1 && maxY2 >= maxY1 && minX2 <= minX1 && maxX2 >= maxX1); |
| } |
| |
| /** returns true if rectangle (defined by minX, maxX, minY, maxY) contains the X Y point */ |
| static boolean containsPoint(final double x, final double y, final double minX, final double maxX, final double minY, final double maxY) { |
| return x >= minX && x <= maxX && y >= minY && y <= maxY; |
| } |
| |
| /** |
| * Compute whether the given x, y point is in a triangle; uses the winding order method */ |
| static boolean pointInTriangle(double minX, double maxX, double minY, double maxY, double x, double y, double aX, double aY, double bX, double bY, double cX, double cY) { |
| // check the bounding box because if the triangle is degenerated, e.g points and lines, we need to filter out |
| // coplanar points that are not part of the triangle. |
| if (x >= minX && x <= maxX && y >= minY && y <= maxY) { |
| int a = orient(x, y, aX, aY, bX, bY); |
| int b = orient(x, y, bX, bY, cX, cY); |
| if (a == 0 || b == 0 || a < 0 == b < 0) { |
| int c = orient(x, y, cX, cY, aX, aY); |
| return c == 0 || (c < 0 == (b < 0 || a < 0)); |
| } |
| return false; |
| } else { |
| return false; |
| } |
| } |
| |
| } |