All Downloads are FREE. Search and download functionalities are using the official Maven repository.

georegression.metric.Distance2D_F64 Maven / Gradle / Ivy

Go to download

GeoRegression is a free Java based geometry library for scientific computing in fields such as robotics and computer vision with a focus on 2D/3D space.

There is a newer version: 0.27.1
Show newest version
/*
 * Copyright (C) 2020, Peter Abeles. All Rights Reserved.
 *
 * This file is part of Geometric Regression Library (GeoRegression).
 *
 * Licensed 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 georegression.metric;

import georegression.geometry.UtilPoint2D_F64;
import georegression.geometry.polygon.AreaIntersectionPolygon2D_F64;
import georegression.struct.curve.EllipseRotated_F64;
import georegression.struct.line.LineGeneral2D_F64;
import georegression.struct.line.LineParametric2D_F64;
import georegression.struct.line.LineSegment2D_F64;
import georegression.struct.point.Point2D_F64;
import georegression.struct.shapes.Polygon2D_F64;
import georegression.struct.shapes.Quadrilateral_F64;
import georegression.struct.shapes.Rectangle2D_F64;
import org.jetbrains.annotations.Nullable;


/**
 * Functions related to finding the distance of one shape from another shape.  This is often
 * closely related to finding the {@link ClosestPoint3D_F64 closest point}.
 *
 * @author Peter Abeles
 */
// TODO distance between two line segments, line lines
// handle parallel overlapping cases by returning zero
public class Distance2D_F64 {


	/**
	 * 

* Returns the Euclidean distance of the closest point on the line from a point. *

* * @param line A line segment. Not modified. * @param p The point. Not modified. * @return Distance the closest point on the line is away from the point. */ public static double distance( LineParametric2D_F64 line, Point2D_F64 p ) { return Math.sqrt(distanceSq(line, p)); } /** *

* Returns the Euclidean distance of the closest point on the line from a point. *

* * @param line A line segment. Not modified. * @param x Point's x-coordinate * @param y Point's y-coordinate * @return Distance the closest point on the line is away from the point. */ public static double distance( LineParametric2D_F64 line, double x , double y ) { return Math.sqrt(distanceSq(line, x,y)); } /** *

* Returns the Euclidean distance squared of the closest point on the line from a point. *

* * @param line A line segment. Not modified. * @param p The point. Not modified. * @return Euclidean distance squared to the closest point on the line is away from the point. */ public static double distanceSq( LineParametric2D_F64 line, Point2D_F64 p ) { double scale = Math.max(Math.abs(line.slope.x),Math.abs(line.slope.y)); double t = ClosestPoint2D_F64.closestPointT( line, p , scale); double a = (line.slope.x/scale) * t + line.p.x; double b = (line.slope.y/scale) * t + line.p.y; double dx = p.x - a; double dy = p.y - b; return dx * dx + dy * dy; } /** *

* Returns the Euclidean distance squared of the closest point on the line from a point. *

* * @param line A line segment. Not modified. * @param x Point's x-coordinate * @param y Point's y-coordinate * @return Euclidean distance squared to the closest point on the line is away from the point. */ public static double distanceSq( LineParametric2D_F64 line, double x , double y ) { double scale = Math.max(Math.abs(line.slope.x),Math.abs(line.slope.y)); double t = ClosestPoint2D_F64.closestPointT( line, x, y , scale); double a = (line.slope.x/scale) * t + line.p.x; double b = (line.slope.y/scale) * t + line.p.y; double dx = x - a; double dy = y - b; return dx * dx + dy * dy; } /** *

* Returns the Euclidean distance of the closest point on a line segment to the specified point. *

* * @param line A line segment. Not modified. * @param p The point. Not modified. * @return Euclidean distance of the closest point on a line is away from a point. */ public static double distance( LineSegment2D_F64 line, Point2D_F64 p ) { return Math.sqrt(distanceSq(line, p)); } /** *

* Returns the Euclidean distance of the closest point on a line segment to the specified point. *

* * @param line A line segment. Not modified. * @param x Point's x-coordinate * @param y Point's y-coordinate * @return Euclidean distance of the closest point on a line is away from a point. */ public static double distance( LineSegment2D_F64 line, double x , double y) { return Math.sqrt(distanceSq(line, x,y)); } /** *

* Returns the Euclidean distance squared of the closest point on a line segment to the specified point. *

* * @param line A line segment. Not modified. * @param p The point. Not modified. * @return Euclidean distance squared of the closest point on a line is away from a point. */ public static double distanceSq( LineSegment2D_F64 line, Point2D_F64 p ) { double a = line.b.x - line.a.x; double b = line.b.y - line.a.y; double t = a * ( p.x - line.a.x ) + b * ( p.y - line.a.y ); t /= ( a * a + b * b ); // if the point of intersection is past the end points return the distance // from the closest end point if( t < 0 ) { return UtilPoint2D_F64.distanceSq(line.a.x, line.a.y, p.x, p.y); } else if( t > 1.0 ) return UtilPoint2D_F64.distanceSq(line.b.x, line.b.y, p.x, p.y); // return the distance of the closest point on the line return UtilPoint2D_F64.distanceSq(line.a.x + t * a, line.a.y + t * b, p.x, p.y); } /** *

* Returns the Euclidean distance squared of the closest point on a line segment to the specified point. *

* * @param line Line segment. Not modified. * @param x Point's x-coordinate * @param y Point's y-coordinate * @return Euclidean distance squared of the closest point on a line is away from a point. */ public static double distanceSq( LineSegment2D_F64 line, double x , double y ) { double a = line.b.x - line.a.x; double b = line.b.y - line.a.y; double t = a * ( x - line.a.x ) + b * ( y - line.a.y ); t /= ( a * a + b * b ); // if the point of intersection is past the end points return the distance // from the closest end point if( t < 0 ) { return UtilPoint2D_F64.distanceSq(line.a.x, line.a.y, x, y); } else if( t > 1.0 ) return UtilPoint2D_F64.distanceSq(line.b.x, line.b.y, x, y); // return the distance of the closest point on the line return UtilPoint2D_F64.distanceSq(line.a.x + t * a, line.a.y + t * b, x, y); } /** * Finds the distance between the two line segments * @param segmentA Line segment. Not modified. * @param segmentB Line segment. Not modified. * @return Euclidean distance of the closest point between the two line segments. */ public static double distance( LineSegment2D_F64 segmentA , LineSegment2D_F64 segmentB ) { return Math.sqrt(distanceSq(segmentA, segmentB)); } /** * Finds the distance squared between the two line segments * @param segmentA Line segment. Not modified. * @param segmentB Line segment. Not modified. * @return Euclidean distance squared of the closest point between the two line segments. */ public static double distanceSq( LineSegment2D_F64 segmentA , LineSegment2D_F64 segmentB ) { // intersection of the two lines relative to A double slopeAX = segmentA.slopeX(); double slopeAY = segmentA.slopeY(); double slopeBX = segmentB.slopeX(); double slopeBY = segmentB.slopeY(); double ta = slopeBX*( segmentA.a.y - segmentB.a.y ) - slopeBY*( segmentA.a.x - segmentB.a.x ); double bottom = slopeBY*slopeAX - slopeAY*slopeBX; // see they intersect if( bottom != 0 ) { // see if the intersection is inside of lineA ta /= bottom; if( ta >= 0 && ta <= 1.0 ) { // see if the intersection is inside of lineB double tb = slopeAX*( segmentB.a.y - segmentA.a.y ) - slopeAY*( segmentB.a.x - segmentA.a.x ); tb /= slopeAY*slopeBX - slopeBY*slopeAX; if( tb >= 0 && tb <= 1.0 ) return 0; } } double closest = Double.MAX_VALUE; closest = Math.min(closest,distanceSq(segmentA, segmentB.a)); closest = Math.min(closest,distanceSq(segmentA, segmentB.b)); closest = Math.min(closest,distanceSq(segmentB, segmentA.a)); closest = Math.min(closest,distanceSq(segmentB, segmentA.b)); return closest; } /** * Returns the Euclidean distance of the closest point on the quadrilateral to the provided point. * * @param quad Quadrilateral * @param p Point * @return Distance apart */ public static double distance( Quadrilateral_F64 quad , Point2D_F64 p ) { return Math.sqrt(distanceSq(quad,p)); } /** * Returns the Euclidean distance squared of the closest point on the quadrilateral to the provided point. * * @param quad Quadrilateral * @param p Point * @return Distance squared apart */ public static double distanceSq( Quadrilateral_F64 quad , Point2D_F64 p ) { LineSegment2D_F64 seg = LineSegment2D_F64.wrap(quad.a, quad.b); double a = distanceSq(seg, p); seg.a = quad.b;seg.b = quad.c; a = Math.min(a,distanceSq(seg,p)); seg.a = quad.c;seg.b = quad.d; a = Math.min(a,distanceSq(seg,p)); seg.a = quad.d;seg.b = quad.a; return Math.min(a, distanceSq(seg, p)); } /** * Returns the Euclidean distance of the closest point on the Polygon to the provided point. * * @param poly Polygon2D * @param p Point * @return Distance squared apart */ public static double distance( Polygon2D_F64 poly , Point2D_F64 p ) { return Math.sqrt(distanceSq(poly, p, null)); } /** * Returns the Euclidean distance squared of the closest point on the Polygon to the provided point. * * @param poly Polygon2D * @param p Point * @param storage Optional storage for linesegment which is used internally to compute the distance * @return Distance squared apart */ public static double distanceSq( Polygon2D_F64 poly , Point2D_F64 p , @Nullable LineSegment2D_F64 storage ) { if( storage == null ) storage = new LineSegment2D_F64(); double minimum = Double.MAX_VALUE; for (int i = 0; i < poly.size(); i++) { int j = (i+1)%poly.size(); storage.a.setTo(poly.vertexes.data[i]); storage.b.setTo(poly.vertexes.data[j]); double d = distanceSq(storage, p); if( d < minimum ) minimum = d; } return minimum; } /** *

* Returns the Euclidean distance of the closest point on the line to the specified point. *

* * @param line A line. Not modified. * @param p The point. Not modified. * @return Euclidean distance of the closest point on the line to the specified point. */ public static double distance( LineGeneral2D_F64 line , Point2D_F64 p ) { return Math.abs(line.A*p.x + line.B*p.y + line.C) / Math.sqrt( line.A*line.A + line.B*line.B ); } /** *

* Returns the signed Euclidean distance of the closest point on the line to the specified point. * The line is assumed be normalized. See {@link LineGeneral2D_F64} for details on normalization. *

* * @param line A normalized line. Not modified. * @param p The point. Not modified. * @return Euclidean distance of the closest point on the line to the specified point. */ public static double distanceNorm(LineGeneral2D_F64 line, Point2D_F64 p) { return Math.abs(line.A*p.x + line.B*p.y + line.C); } /** * Returns the distance of the closest point on the line from the origin * @param line Line * @return Euclidean distance */ public static double distanceOrigin( LineParametric2D_F64 line ) { double top = line.slope.y*line.p.x - line.slope.x*line.p.y; return Math.abs(top)/line.slope.norm(); } /** * Euclidean distance of closest point on ellipse to point 'p'. * * @param ellipse Ellipse * @param p Point * @return Euclidean distance */ public static double distance(EllipseRotated_F64 ellipse , Point2D_F64 p ) { return Math.sqrt(distance2(ellipse, p)); } /** * Euclidean distance squared of closest point on ellipse to point 'p'. * * @param ellipse Ellipse * @param p Point * @return Euclidean distance squared */ public static double distance2(EllipseRotated_F64 ellipse , Point2D_F64 p ) { // put point into ellipse's reference frame double cphi = Math.cos(ellipse.phi); double sphi = Math.sin(ellipse.phi); double xc = p.x - ellipse.center.x; double yc = p.y - ellipse.center.y; double r = Math.sqrt(xc*xc + yc*yc); double x = cphi*xc + sphi*yc; double y = -sphi*xc + cphi*yc; double ct = x/r; double st = y/r; x = ellipse.center.x + ellipse.a*ct*cphi - ellipse.b*st*sphi; y = ellipse.center.y + ellipse.a*ct*sphi + ellipse.b*st*cphi; return p.distance2(x,y); } /** * Returns the Intersection Over Union (IoU) score * * @param a (Input) rectangle * @param b (Input) rectangle * @return IoU score */ public static double scoreIoU(Rectangle2D_F64 a, Rectangle2D_F64 b ) { double areaI = Intersection2D_F64.intersectionArea(a,b); if (areaI == 0.0) return 0.0; return areaI/(a.area() + b.area() - areaI); } /** * Returns the Intersection Over Union (IoU) score for two simple polygon * * @param a (Input) Simple polygon * @param b (Input) Simple polygon * @return IoU score */ public static double scoreIoU(Polygon2D_F64 a, Polygon2D_F64 b, @Nullable AreaIntersectionPolygon2D_F64 computeArea) { if (computeArea == null) computeArea = new AreaIntersectionPolygon2D_F64(); double areaI = Math.abs(computeArea.computeArea(a, b)); if (areaI == 0.0) return 0.0; double areaA = Area2D_F64.polygonSimple(a); double areaB = Area2D_F64.polygonSimple(b); return areaI/(areaA + areaB - areaI); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy