python distance geos shapely

python - Coordenadas del punto más cercano en una línea.



distance geos (2)

Hay una polilínea con una lista de coordenadas de los vértices = [(x1, y1), (x2, y2), (x3, y3), ...] y un punto (x, y). En Shapely, geometry1.distance(geometry2) devuelve la distancia más corta entre las dos geometrías.

>>> from shapely.geometry import LineString, Point >>> line = LineString([(0,0),(5,7),(12,6)]) #geometry2 >>> list(line.coords) [(0.0, 0.0), (5.0, 7.0), (12.0, 6.0)] >>> p = Point(4,8) #geometry1 >>> list(p.coords) [(4.0, 8.0)] >>> p.distance(line) 1.4142135623730951

Pero también necesito encontrar la coordenada del punto en la línea más cercana al punto (x, y). En el ejemplo anterior, esta es la coordenada del punto en el objeto LineString que se encuentra a 1.4142135623730951 unidad alejada del punto (4,8). El método distance () debe tener las coordenadas al calcular la distancia. ¿Hay alguna manera de obtenerlo devuelto de este método?


El término GIS que está describiendo es referencia lineal , y Shapely tiene estos métodos .

# Length along line that is closest to the point print(line.project(p)) # Now combine with interpolated point on line np = line.interpolate(line.project(p)) print(np) # POINT (5 7)


En caso de que tenga un solo segmento (por ejemplo: una línea, en referencia al título) en lugar de una lista de segmentos, aquí está lo que hice y con un caso de prueba que pasa. Tenga en cuenta que algunos usuarios en esta página solo buscan eso al mirar el título, provenientes de una búsqueda en Google.

Código Python:

def sq_shortest_dist_to_point(self, other_point): dx = self.b.x - self.a.x dy = self.b.y - self.a.y dr2 = float(dx ** 2 + dy ** 2) lerp = ((other_point.x - self.a.x) * dx + (other_point.y - self.a.y) * dy) / dr2 if lerp < 0: lerp = 0 elif lerp > 1: lerp = 1 x = lerp * dx + self.a.x y = lerp * dy + self.a.y _dx = x - other_point.x _dy = y - other_point.y square_dist = _dx ** 2 + _dy ** 2 return square_dist def shortest_dist_to_point(self, other_point): return math.sqrt(self.sq_shortest_dist_to_point(other_point))

Un caso de prueba:

def test_distance_to_other_point(self): # Parametrize test with multiple cases: segments_and_point_and_answer = [ [Segment(Point(1.0, 1.0), Point(1.0, 3.0)), Point(2.0, 4.0), math.sqrt(2.0)], [Segment(Point(1.0, 1.0), Point(1.0, 3.0)), Point(2.0, 3.0), 1.0], [Segment(Point(0.0, 0.0), Point(0.0, 3.0)), Point(1.0, 1.0), 1.0], [Segment(Point(1.0, 1.0), Point(3.0, 3.0)), Point(2.0, 2.0), 0.0], [Segment(Point(-1.0, -1.0), Point(3.0, 3.0)), Point(2.0, 2.0), 0.0], [Segment(Point(1.0, 1.0), Point(1.0, 3.0)), Point(2.0, 3.0), 1.0], [Segment(Point(1.0, 1.0), Point(1.0, 3.0)), Point(2.0, 4.0), math.sqrt(2.0)], [Segment(Point(1.0, 1.0), Point(-3.0, -3.0)), Point(-3.0, -4.0), 1], [Segment(Point(1.0, 1.0), Point(-3.0, -3.0)), Point(-4.0, -3.0), 1], [Segment(Point(1.0, 1.0), Point(-3.0, -3.0)), Point(1, 2), 1], [Segment(Point(1.0, 1.0), Point(-3.0, -3.0)), Point(2, 1), 1], [Segment(Point(1.0, 1.0), Point(-3.0, -3.0)), Point(-3, -1), math.sqrt(2.0)], [Segment(Point(1.0, 1.0), Point(-3.0, -3.0)), Point(-1, -3), math.sqrt(2.0)], [Segment(Point(-1.0, -1.0), Point(3.0, 3.0)), Point(3, 1), math.sqrt(2.0)], [Segment(Point(-1.0, -1.0), Point(3.0, 3.0)), Point(1, 3), math.sqrt(2.0)], [Segment(Point(1.0, 1.0), Point(3.0, 3.0)), Point(3, 1), math.sqrt(2.0)], [Segment(Point(1.0, 1.0), Point(3.0, 3.0)), Point(1, 3), math.sqrt(2.0)] ] for i, (segment, point, answer) in enumerate(segments_and_point_and_answer): result = segment.shortest_dist_to_point(point) self.assertAlmostEqual(result, answer, delta=0.001, msg=str((i, segment, point, answer)))

Nota: Supongo que esta función está dentro de una clase de Segment . En caso de que su línea sea infinita, no limite el límite de 0 a 1 solo, pero al menos proporcione dos puntos a y b distintos.