Added distance to point to 2D Line and Segment.
Patch provided by Curtis Jensen applied with minor modifications. JIRA: MATH-641 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1392022 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3246e42006
commit
df92c3b6f1
3
pom.xml
3
pom.xml
|
@ -192,6 +192,9 @@
|
|||
<contributor>
|
||||
<name>Matthias Hummel</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Curtis Jensen</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Ismael Juma</name>
|
||||
</contributor>
|
||||
|
|
|
@ -52,8 +52,11 @@ If the output is not quite correct, check for invisible trailing spaces!
|
|||
<body>
|
||||
<release version="3.1" date="TBD" description="
|
||||
">
|
||||
<action dev="luc" type="fix" issue="MATH-641" due-to="Curtis Jensen">
|
||||
Added distance to point to 2D Line and Segment.
|
||||
</action>
|
||||
<action dev="erans" type="fix" issue="MATH-783">
|
||||
"PowellOptimizer" (package "o.a.c.m.optimization.direct") uses
|
||||
"PowellOptimizer" (package "o.a.c.m.optimization.direct") uses
|
||||
"BrentOptimizer" as its internal line search optimizer. The fix
|
||||
forces the convergence criterion of "BrentOptimizer" to use
|
||||
function values (instead of domain values).
|
||||
|
|
|
@ -263,6 +263,18 @@ public class Line implements Hyperplane<Euclidean2D>, Embedding<Euclidean2D, Euc
|
|||
return FastMath.abs(getOffset(p)) < 1.0e-10;
|
||||
}
|
||||
|
||||
/** Compute the distance between the instance and a point.
|
||||
* This is a shortcut for invoking FastMath.abs(getOffset(p)),
|
||||
* and provides consistency with what is in the
|
||||
* org.apache.commons.math3.geometry.euclidean.threed.Line class.
|
||||
*
|
||||
* @param p to check
|
||||
* @return distance between the instance and the point
|
||||
*/
|
||||
public double distance(final Vector2D p) {
|
||||
return FastMath.abs(getOffset(p));
|
||||
}
|
||||
|
||||
/** Check the instance is parallel to another line.
|
||||
* @param line other line to check
|
||||
* @return true if the instance is parallel to the other line
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.apache.commons.math3.geometry.euclidean.twod;
|
||||
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
/** Simple container for a two-points segment.
|
||||
* @version $Id$
|
||||
|
@ -64,4 +65,43 @@ public class Segment {
|
|||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the shortest distance from a point to this line segment.
|
||||
* <p>
|
||||
* If the perpendicular extension from the point to the line does not
|
||||
* cross in the bounds of the line segment, the shortest distance to
|
||||
* the two end points will be returned.
|
||||
* </p>
|
||||
*
|
||||
* Algorithm adapted from: http://www.codeguru.com/forum/printthread.php?s=cc8cf0596231f9a7dba4da6e77c29db3&t=194400&pp=15&page=1
|
||||
*/
|
||||
public double distance(final Vector2D p) {
|
||||
final double deltaX = end.getX() - start.getX();
|
||||
final double deltaY = end.getY() - start.getY();
|
||||
|
||||
final double r = ((p.getX() - start.getX()) * deltaX + (p.getY() - start.getY()) * deltaY) /
|
||||
(deltaX * deltaX + deltaY * deltaY);
|
||||
|
||||
// r == 0 => P = startPt
|
||||
// r == 1 => P = endPt
|
||||
// r < 0 => P is on the backward extension of the segment
|
||||
// r > 1 => P is on the forward extension of the segment
|
||||
// 0 < r < 1 => P is on the segment
|
||||
|
||||
// if point isn't on the line segment, just return the shortest distance to the end points
|
||||
if (r < 0 || r > 1) {
|
||||
final double dist1 = getStart().distance(p);
|
||||
final double dist2 = getEnd().distance(p);
|
||||
|
||||
return FastMath.min(dist1, dist2);
|
||||
}
|
||||
else {
|
||||
// find point on line and see if it is in the line segment
|
||||
final double px = start.getX() + r * deltaX;
|
||||
final double py = start.getY() + r * deltaY;
|
||||
|
||||
final Vector2D interPt = new Vector2D(px, py);
|
||||
return interPt.distance(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,13 @@ public class LineTest {
|
|||
Assert.assertEquals(+5.0, l.getOffset(new Vector2D(-5, 2)), 1.0e-10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistance() {
|
||||
Line l = new Line(new Vector2D(2, 1), new Vector2D(-2, -2));
|
||||
Assert.assertEquals(+5.0, l.distance(new Vector2D(5, -3)), 1.0e-10);
|
||||
Assert.assertEquals(+5.0, l.distance(new Vector2D(-5, 2)), 1.0e-10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointAt() {
|
||||
Line l = new Line(new Vector2D(2, 1), new Vector2D(-2, -2));
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.commons.math3.geometry.euclidean.twod;
|
||||
|
||||
import org.apache.commons.math3.geometry.euclidean.twod.Line;
|
||||
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SegmentTest {
|
||||
|
||||
@Test
|
||||
public void testDistance() {
|
||||
Vector2D start = new Vector2D(2, 2);
|
||||
Vector2D end = new Vector2D(-2, -2);
|
||||
Segment segment = new Segment(start, end, new Line(start, end));
|
||||
|
||||
// distance to center of segment
|
||||
Assert.assertEquals(FastMath.sqrt(2), segment.distance(new Vector2D(1, -1)), 1.0e-10);
|
||||
|
||||
// distance a point on segment
|
||||
Assert.assertEquals(FastMath.sin(Math.PI / 4.0), segment.distance(new Vector2D(0, -1)), 1.0e-10);
|
||||
|
||||
// distance to end point
|
||||
Assert.assertEquals(FastMath.sqrt(8), segment.distance(new Vector2D(0, 4)), 1.0e-10);
|
||||
|
||||
// distance to start point
|
||||
Assert.assertEquals(FastMath.sqrt(8), segment.distance(new Vector2D(0, -4)), 1.0e-10);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue