| /* |
| * 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 static org.apache.lucene.geo.GeoUtils.orient; |
| |
| import org.apache.lucene.index.PointValues; |
| |
| /** |
| * 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; |
| } |
| } |
| } |