From 9cd5887e0bcb1c05b7030697b1abc6e3b2b06c14 Mon Sep 17 00:00:00 2001 From: jericks Date: Sat, 8 Nov 2014 09:44:31 -0800 Subject: [PATCH 1/2] Add linear referencing methods to linestring --- geoscript/geom/linestring.py | 51 ++++++++++++++++++++++++++++++++++++ tests/test_geom.py | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/geoscript/geom/linestring.py b/geoscript/geom/linestring.py index b67e379..0faf920 100644 --- a/geoscript/geom/linestring.py +++ b/geoscript/geom/linestring.py @@ -1,6 +1,8 @@ from com.vividsolutions.jts.geom import Coordinate from com.vividsolutions.jts.geom import LineString as _LineString +from com.vividsolutions.jts.linearref import LengthIndexedLine from geoscript import core +from geoscript.geom import Point import geom class LineString(_LineString): @@ -27,5 +29,54 @@ def __init__(self, *coords): _LineString.__init__(self, ls.coordinateSequence, geom._factory) + def interpolatePoint(self, position): + """ + Interpolate a :class:`Point ` on the :class:`LineString ` at the given position from 0 to 1. + + *position* is number between 0 and 1 + + """ + indexedLine = LengthIndexedLine(self) + length = self.getLength() + coordinate = indexedLine.extractPoint(position * length) + return Point(coordinate.x, coordinate.y) + + def locatePoint(self, point): + """ + Locate the position of the :class:`point ` along this :class:`LineString `. The position returned is a number between 0 and 1. + + *point* A :class:`Point ` + + """ + indexedLine = LengthIndexedLine(self) + position = indexedLine.indexOf(point.coordinate) + percentAlong = position / self.getLength() + return percentAlong + + def placePoint(self, point): + """ + Place or snap the :class:`point ` to the `LineString `. This method returns a new placed `Point `. + + *point* A :class:`Point ` + + """ + indexedLine = LengthIndexedLine(self) + position = indexedLine.indexOf(point.coordinate) + coord = indexedLine.extractPoint(position) + return Point(coord.x, coord.y) + + def subLine(self, start, end): + """ + Extract a sub :class:`LineString ` using a start and end position. Both positions are numbers between 0 and 1. A new :class:`LineString ` is returned. + + *start* The start position between 0 and 1 + + *end* The end position between 0 and 1 + + """ + indexedLine = LengthIndexedLine(self) + length = self.getLength() + return LineString(indexedLine.extractLine(start * length, end * length)) + geom._enhance(LineString) core.registerTypeMapping(_LineString, LineString) diff --git a/tests/test_geom.py b/tests/test_geom.py index e6aaaf0..50ba0d0 100644 --- a/tests/test_geom.py +++ b/tests/test_geom.py @@ -174,3 +174,53 @@ def testWriteGML(self): poly = geom.Polygon([[1,2],[3,4],[5,6],[1,2]]) assert str(poly) == str(geom.readGML(geom.writeGML(poly,ver=3.2),ver=3.2)) + + def testInterpolatePoint(self): + line = geom.LineString( + (1137466.548141059, 650434.9943107369), + (1175272.4129268457, 648011.541439853), + (1185935.6055587344, 632986.1336403737) + ) + + # start + point1 = line.interpolatePoint(0) + assert str(line.startPoint) == str(point1) + + # middle + point2 = line.interpolatePoint(0.5) + assert "POINT (1165562.9204493894 648633.9448037925)" == str(point2) + + # end + point3 = line.interpolatePoint(1.0) + assert str(line.endPoint) == str(point3) + + def testLocatePoint(self): + line = geom.LineString( + (1137466.548141059, 650434.9943107369), + (1175272.4129268457, 648011.541439853), + (1185935.6055587344, 632986.1336403737) + ) + point = geom.Point(1153461.34, 649950.30) + position = line.locatePoint(point) + self.assertAlmostEqual(0.284, position, places=3) + + def testPlacePoint(self): + line = geom.LineString( + (1137466.548141059, 650434.9943107369), + (1175272.4129268457, 648011.541439853), + (1185935.6055587344, 632986.1336403737) + ) + point1 = geom.Point(1153461.34, 649950.30) + point2 = line.placePoint(point1) + assert "POINT (1153426.8271476042 649411.899502625)" == str(point2) + + def testSubLine(self): + line = geom.LineString( + (1137466.548141059, 650434.9943107369), + (1175272.4129268457, 648011.541439853), + (1185935.6055587344, 632986.1336403737) + ) + subLine = line.subLine(0.33, 0.67) + assert "LINESTRING (1156010.153864557 649246.3016361536, 1175115.6870342216 648021.5879714314)" == str(subLine) + + From 1d049b7dde90995da75b609ffc3c4a16b4d01c99 Mon Sep 17 00:00:00 2001 From: jericks Date: Sun, 16 Nov 2014 19:27:53 -0800 Subject: [PATCH 2/2] Accept variable list of xyz coordinates in addition to a Point --- geoscript/geom/linestring.py | 10 ++++++---- tests/test_geom.py | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/geoscript/geom/linestring.py b/geoscript/geom/linestring.py index 0faf920..ccdda7b 100644 --- a/geoscript/geom/linestring.py +++ b/geoscript/geom/linestring.py @@ -41,25 +41,27 @@ def interpolatePoint(self, position): coordinate = indexedLine.extractPoint(position * length) return Point(coordinate.x, coordinate.y) - def locatePoint(self, point): + def locatePoint(self, *coord): """ Locate the position of the :class:`point ` along this :class:`LineString `. The position returned is a number between 0 and 1. - *point* A :class:`Point ` + *coord* A :class:`Point ` or a variable list of x,y,z arguments. """ + point = coord[0] if isinstance(coord[0], Point) else Point(*coord) indexedLine = LengthIndexedLine(self) position = indexedLine.indexOf(point.coordinate) percentAlong = position / self.getLength() return percentAlong - def placePoint(self, point): + def placePoint(self, *coord): """ Place or snap the :class:`point ` to the `LineString `. This method returns a new placed `Point `. - *point* A :class:`Point ` + *coord* A :class:`Point ` or a variable list of x,y,z arguments. """ + point = coord[0] if isinstance(coord[0], Point) else Point(*coord) indexedLine = LengthIndexedLine(self) position = indexedLine.indexOf(point.coordinate) coord = indexedLine.extractPoint(position) diff --git a/tests/test_geom.py b/tests/test_geom.py index 50ba0d0..2a2ef40 100644 --- a/tests/test_geom.py +++ b/tests/test_geom.py @@ -203,6 +203,8 @@ def testLocatePoint(self): point = geom.Point(1153461.34, 649950.30) position = line.locatePoint(point) self.assertAlmostEqual(0.284, position, places=3) + position = line.locatePoint(1153461.34, 649950.30) + self.assertAlmostEqual(0.284, position, places=3) def testPlacePoint(self): line = geom.LineString( @@ -213,6 +215,8 @@ def testPlacePoint(self): point1 = geom.Point(1153461.34, 649950.30) point2 = line.placePoint(point1) assert "POINT (1153426.8271476042 649411.899502625)" == str(point2) + point3 = line.placePoint(1153461.34, 649950.30) + assert "POINT (1153426.8271476042 649411.899502625)" == str(point3) def testSubLine(self): line = geom.LineString(