0

This question is somewhat similar to this. I've gone a bit farther than the OP, though, and I'm in Python 2 (not sure what he was using).

I have a Python function that can determine the distance from a point inside a convex polygon to regularly-defined intervals along the polygon's perimeter. The problem is that it returns "extra" distances that I need to eliminate. (Please note--I suspect this will not work for rectangles yet. I'm not finished with it.) First, the code:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  t1.py
# 
#  Copyright 2015 FRED <fred@matthew24-25>
# 
#  THIS IS TESTING CODE ONLY. IT WILL BE MOVED INTO THE CORRECT MODULE
#  UPON COMPLETION.
# 
from __future__ import division
import math
import matplotlib.pyplot as plt
def Dist(center_point, Pairs, deg_Increment):

# I want to set empty lists to store the values of m_lnsgmnt and b_lnsgmnts
# for every iteration of the for loop.
    m_linesegments = []
    b_linesegments = []

# Scream and die if Pairs[0] is the same as the last element of Pairs--i.e.
# it has already been run once.
#if Pairs[0] == Pairs[len(Pairs)-1]:
  ##print "The vertices contain duplicate points!"

## Creates a new list containing the original list plus the first element. I did this because, due
## to the way the for loop is set up, the last iteration of the loop subtracts the value of the
## last value of Pairs from the first value. I therefore duplicated the first value.
#elif:
    new_Pairs = Pairs + [Pairs[0]]

    # This will calculate the slopes and y-intercepts of the linesegments of the polygon.
    for a in range(len(Pairs)):

        # This calculates the slope of each line segment and appends it to m_linesegments.
        m_lnsgmnt = (new_Pairs[a+1][2] - new_Pairs[a][3]) / (new_Pairs[a+1][0] - new_Pairs[a][0])
        m_linesegments.append(m_lnsgmnt)

        # This calculates the y-intercept of each line segment and appends it to b_linesegments.
        b_lnsgmnt = (Pairs[a][4]) - (m_lnsgmnt * Pairs[a][0])
        b_linesegments.append(b_lnsgmnt)

    # These are temporary testing codes.
    print "m_linesegments =", m_linesegments
    print "b_linesegments =", b_linesegments

    # I want to set empty lists to store the value of m_rys and b_rys for every
    # iteration of the for loop.
    m_rays = []
    b_rays = []

    # I need to set a range of degrees the intercepts will be calculated for.
    theta = range(0, 360, deg_Increment)

    # Temporary testing line.
    print "theta =", theta

    # Calculate the slope and y-intercepts of the rays radiating from the center_point.
    for b in range(len(theta)):

        m_rys = math.tan(math.radians(theta[b]))
        m_rays.append(m_rys)

        b_rys = center_point[1] - (m_rys * center_point[0])
        b_rays.append(b_rys)

    # Temporary testing lines.   
    print "m_rays =", m_rays
    print "b_rays =", b_rays


    # Set empty matrix for Intercepts.
    Intercepts = []
    angle = []

    # Calculate the intersections of the rays with the line segments.
    for c in range((360//deg_Increment)):

        for d in range(len(Pairs)):

            # Calculate the x-coordinates and the y-coordinates of each
            # intersection
            x_Int = (b_rays[c] - b_linesegments[d]) / (m_linesegments[d] - m_rays[c])
            y_Int = ((m_linesegments[d] * x_Int) + b_linesegments[d])


            Intercepts.append((x_Int, y_Int))

            # Calculates the angle of the ray. Rounding is necessary to 
            # compensate for binary-decimal errors. 
            a_ngle = round(math.degrees(math.atan2((y_Int - center_point[1]), (x_Int - center_point[0]))))

            # Substitutes positive equivalent for every negative angle, 
            # i.e. -270 degrees equals 90 degrees.
            if a_ngle < 0:
                a_ngle = a_ngle + 360

            # Selects the angles that correspond to theta
            if a_ngle == theta[c]:
                angle.append(a_ngle)


    print "INT1=", Intercepts
    print "angle=", angle

    dist = []

    # Calculates distance.
    for e in range(len(Intercepts) - 1):
        distA = math.sqrt(((Intercepts[e][0] - center_point[0])**2) +  ((Intercepts[e][5]- center_point[1])**2))
        dist.append(distA)

    print "dist=", dist

if __name__ == "__main__":
    main()  

Now, as to how it works: The code takes 3 inputs: center_point (a point contained in the polygon, given in (x,y) coordinates), Pairs (the vertices of the polygon, also given in (x,y) coordinats), and deg_Increment ( which defines how often to calculate distance). Let's assume that center_point = (4,5), Pairs = [(1, 4), (3, 8), (7, 2)], and deg_Increment = 20. This means that a polygon is created (sort of) whose vertices are Pairs, and center_point is a point contained inside the polygon. Now rays are set to radiate from center_point every 20 degrees (which isdeg_Increment). The intersection points of the rays with the perimeter of the polygon are determined, and the distance is calculated using the distance formula. The only problem is that I'm getting too many distances. :( In my example above, the correct distances are 1.00000 0.85638 0.83712 0.92820 1.20455 2.07086 2.67949 2.29898 2.25083 2.50000 3.05227 2.22683 1.93669 1.91811 2.15767 2.85976 2.96279 1.40513

But my code is returning dist= [2.5, 1.0, 6.000000000000001, 3.2523178818773006, 0.8563799085248148, 3.0522653889161626, 5.622391569468206, 0.8371216462519347, 2.226834844885431, 37.320508075688686, 0.9282032302755089, 1.9366857335569072, 7.8429970322236064, 1.2045483557883576, 1.9181147622136665, 3.753460385470896, 2.070863609380179, 2.157671808913309, 2.6794919243112276, 12.92820323027545, 2.85976265663383, 2.298981118867903, 2.962792920643178, 5.162096782237789, 2.250827351906659, 1.4051274947736863, 69.47032761621092, 2.4999999999999996, 1.0, 6.000000000000004, 3.2523178818773006, 0.8563799085248148, 3.0522653889161626, 5.622391569468206, 0.8371216462519347, 2.226834844885431, 37.32050807568848, 0.9282032302755087, 1.9366857335569074, 7.842997032223602, 1.2045483557883576, 1.9181147622136665, 3.7534603854708997, 2.0708636093801767, 2.1576718089133085, 2.679491924311227, 12.928203230275532, 2.85976265663383, 2.298981118867903, 2.9627929206431776, 5.162096782237789, 2.250827351906659, 1.4051274947736847]

If anyone can help me get only the correct distances, I'd greatly appreciate it. Thanks!

And just for reference, here's what my example looks like with the correct distances only:DISTANCE

Community
  • 1
  • 1
Fred Barclay
  • 834
  • 1
  • 13
  • 24

1 Answers1

1

You're getting too many values in Intercepts because it's being appended to inside the second for-loop [for d in range(len(Pairs))].

You only want one value in Intercept per step through the outer for-loop [for c in range((360//deg_Increment))], so the append to Intercept needs to be in this loop.

I'm not sure what you're doing with the inner loop, but you seem to be calculating a separate intercept for each of the lines that make up the polygon sides. But you only want the one that you're going to hit "first" when going in that direction.

You'll have to add some code to figure out which of the 3 (in this case) sides of the polygon you're actually going to encounter first.

hitzg
  • 12,133
  • 52
  • 54