I am trying to draw a perpendicular line from every edge to the opposite vertex of a polygon. I am only interested if the line is inside the polygon. Otherwise, I do not want to draw it. I am using the shapely
library and Polygon.contains
to check if the intersection point is inside the polygon or not. But it is showing me wrong answers. Only two of the lines are drawn but others are omitted even when they are inside the polygon. I am using the calc_Intersect
function to calculate the nearest point from a point to a line. The ray_tracing
function is where I am trying to draw all the perpendicular lines of the edges. Can anybody tell me what am I missing here? Is there something to do with floating point
errors? Here is the code:
from shapely.geometry import Point # For checking the points inside a Polygon
from shapely.geometry.polygon import Polygon # For comparing the points in the shape of the Polygon
import matplotlib.pyplot as plt
import math
class CPP: # Calculate the coverage paths
def __init__(self, polygon, delta):
self.polygon = polygon
self.sorted_polygon = sorted(polygon)
self.rounded_polygon = polygon [polygon[0]]
self.edges = self.calc_edges()
self.pol_obj = Polygon(polygon)
def calc_edges(self): # To calculate the edges in the polygon
edges = []
for i in range(len(self.rounded_polygon) - 1):
edges.append([self.rounded_polygon[i], self.rounded_polygon[i 1]])
return edges
def calc_distance(self, v1, v2): # distance between two points
x1, y1 = v1[0], v1[1]
x2, y2 = v2[0], v2[1]
dist = math.sqrt((x1 - x2) ** 2 (y1 - y2) ** 2)
return dist
def calc_Intersect(self, point, line):
# To calculate the intersection point from a point to the line
# Input is an edge [[x1,y1],[x2,y2]] and a point [x0,y0], output is the nearest point [x_3,y_3]
x1, y1 = line[0]
x2, y2 = line[1]
x0, y0 = point
if x1 == x2:
return [x1, y0]
elif y1 == y2:
return [x0, y1]
else:
m1 = (y1 - y2) / (x1 - x2)
m2 = - (1 / m1)
c1 = y2 - m1 * x2
c2 = y0 - m2 * x0
x3 = (c2 - c1) / (m1 - m2)
y3 = m1 * x3 c1
return [x3, y3]
def ray_tracing(self):
ls = []
for v in self.polygon:
for edge in self.edges:
if not v in edge:
ints_point = self.calc_Intersect(v, edge)
if self.pol_obj.contains(Point(ints_point)):
xc, yc = zip(v, ints_point)
ls.append((v, edge, ints_point))
plt.plot(xc, yc)
print(ls)
return 0
def main():
polygon = [(12, 1), (14, 4), (13, 9), (7, 8), (1, 5), (4, 1)]
delta = 0.5
cpp_object = CPP(polygon, delta)
xs, ys = zip(*cpp_object.rounded_polygon)
print('shortest node = ', cpp_object.ray_tracing())
plt.plot(xs, ys)
plt.show()
CodePudding user response:
At first, you are right, floating errors might cause detecting some points outside. At second, seems shapely contains
function consider points at edges as outside ones:
A line’s endpoints are part of its boundary and are therefore not contained.
I'd recommend to calculate projection of point at line segment using the next method:
dx = x2 - x1
dy = y2 - y1
cdx = x0 - x1
cdy = y0 - y1
t = (cdx * dx cdy * dy) / (dx * dx dy * dy)
if t < 0 or t > 1:
print("Projection lies outside segment")
px = x1 t * dx
py = y1 t * dy
t
parameter tells us about placement of projection on the line containing P1P2 segment