Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PointLocation.isOnSegment function #1048

Merged
merged 4 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,10 @@ public static int locatePointInRing(Coordinate p, Coordinate[] ring)
*/
public static boolean isOnLine(Coordinate p, Coordinate[] pt)
{
LineIntersector lineIntersector = new RobustLineIntersector();
for (int i = 1; i < pt.length; i++) {
Coordinate p0 = pt[i - 1];
Coordinate p1 = pt[i];
lineIntersector.computeIntersection(p, p0, p1);
if (lineIntersector.hasIntersection()) {
if (PointLocation.isOnSegment(p, p0, p1)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,37 @@

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateSequence;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Location;

/**
* Functions for locating points within basic geometric
* structures such as lines and rings.
* structures such as line segments, lines and rings.
*
* @author Martin Davis
*
*/
public class PointLocation {

/**
* Tests whether a point lies on a line segment.
*
* @param p the point to test
* @param p0 a point of the line segment
* @param p1 a point of the line segment
* @return true if the point lies on the line segment
*/
public static boolean isOnSegment(Coordinate p, Coordinate p0, Coordinate p1) {
//-- test envelope first since it's faster
if (! Envelope.intersects(p0, p1, p))
return false;
//-- handle zero-length segments
if (p.equals2D(p0))
return true;
boolean isOnLine = Orientation.COLLINEAR == Orientation.index(p0, p1, p);
return isOnLine;
}

/**
* Tests whether a point lies on the line defined by a list of
* coordinates.
Expand All @@ -35,12 +55,10 @@ public class PointLocation {
*/
public static boolean isOnLine(Coordinate p, Coordinate[] line)
{
LineIntersector lineIntersector = new RobustLineIntersector();
for (int i = 1; i < line.length; i++) {
Coordinate p0 = line[i - 1];
Coordinate p1 = line[i];
lineIntersector.computeIntersection(p, p0, p1);
if (lineIntersector.hasIntersection()) {
if (isOnSegment(p, p0, p1)) {
return true;
}
}
Expand All @@ -58,15 +76,13 @@ public static boolean isOnLine(Coordinate p, Coordinate[] line)
*/
public static boolean isOnLine(Coordinate p, CoordinateSequence line)
{
LineIntersector lineIntersector = new RobustLineIntersector();
Coordinate p0 = new Coordinate();
Coordinate p1 = new Coordinate();
int n = line.size();
for (int i = 1; i < n; i++) {
line.getCoordinate(i-1, p0);
line.getCoordinate(i, p1);
lineIntersector.computeIntersection(p, p0, p1);
if (lineIntersector.hasIntersection()) {
if (isOnSegment(p, p0, p1)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@
import java.util.ArrayList;
import java.util.List;

import org.locationtech.jts.algorithm.LineIntersector;
import org.locationtech.jts.algorithm.Orientation;
import org.locationtech.jts.algorithm.PointLocation;
import org.locationtech.jts.algorithm.PolygonNodeTopology;
import org.locationtech.jts.algorithm.RobustLineIntersector;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateArrays;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.LinearRing;
import org.locationtech.jts.geom.Location;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.noding.BasicSegmentString;
import org.locationtech.jts.noding.MCIndexNoder;
Expand Down Expand Up @@ -185,10 +184,8 @@ private static int ringIndexNext(Coordinate[] ringPts, int index) {
* @return the intersection segment index, or -1 if no intersection is found
*/
private static int intersectingSegIndex(Coordinate[] ringPts, Coordinate pt) {
LineIntersector li = new RobustLineIntersector();
for (int i = 0; i < ringPts.length - 1; i++) {
li.computeIntersection(pt, ringPts[i], ringPts[i + 1]);
if (li.hasIntersection()) {
if (PointLocation.isOnSegment(pt, ringPts[i], ringPts[i + 1])) {
//-- check if pt is the start point of the next segment
if (pt.equals2D(ringPts[i + 1])) {
return i + 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,31 @@
package org.locationtech.jts.algorithm;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;

import junit.framework.TestCase;
import junit.textui.TestRunner;
import test.jts.GeometryTestCase;

/**
* Tests {@link PointLocation#isOnLine(Coordinate, Coordinate[])}.
* Tests {@link PointLocation}.
*
* @version 1.15
*/
public class PointLocationOnLineTest extends GeometryTestCase {
public class PointLocationTest extends GeometryTestCase {

public static void main(String args[]) {
TestRunner.run(PointLocationOnLineTest.class);
TestRunner.run(PointLocationTest.class);
}

public PointLocationOnLineTest(String name) {
public PointLocationTest(String name) {
super(name);
}

public void testOnVertex() throws Exception {
public void testOnLineOnVertex() throws Exception {
checkOnLine(20, 20, "LINESTRING (0 00, 20 20, 30 30)", true);
}

public void testOnSegment() throws Exception {
public void testOnLineInSegment() throws Exception {
checkOnLine(10, 10, "LINESTRING (0 0, 20 20, 0 40)", true);
checkOnLine(10, 30, "LINESTRING (0 0, 20 20, 0 40)", true);
}
Expand All @@ -48,6 +45,30 @@ public void testNotOnLine() throws Exception {
checkOnLine(0, 100, "LINESTRING (10 10, 20 10, 30 10)", false);
}

public void testOnSegment() {
checkOnSegment(5, 5, "LINESTRING(0 0, 9 9)", true);
checkOnSegment(0, 0, "LINESTRING(0 0, 9 9)", true);
checkOnSegment(9, 9, "LINESTRING(0 0, 9 9)", true);
}

public void testNotOnSegment() {
checkOnSegment(5, 6, "LINESTRING(0 0, 9 9)", false);
checkOnSegment(10, 10, "LINESTRING(0 0, 9 9)", false);
checkOnSegment(9, 9.00001, "LINESTRING(0 0, 9 9)", false);
}

public void testOnZeroLengthSegment() {
checkOnSegment(1, 1, "LINESTRING(1 1, 1 1)", true);
checkOnSegment(1, 2, "LINESTRING(1 1, 1 1)", false);
}

private void checkOnSegment(double x, double y, String wktLine, boolean expected) {
LineString line = (LineString) read(wktLine);
Coordinate p0 = line.getCoordinateN(0);
Coordinate p1 = line.getCoordinateN(1);
assertTrue(expected == PointLocation.isOnSegment(new Coordinate(x,y), p0, p1));
}

void checkOnLine(double x, double y, String wktLine, boolean expected) {
LineString line = (LineString) read(wktLine);
assertTrue(expected == PointLocation.isOnLine(new Coordinate(x,y), line.getCoordinates()));
Expand Down
Loading