Draw line from every edge of the polygon to opposite vertex

Question:

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()

Answers:

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

Answered By: MBo