Which side of the polyline is the point

I am trying to write code that allows me to identify which side of a random polyline (not closed) by a random point. A polyline is considered infinite, with the first and last segments expanded to infinity. If they intersect, the polyline should be considered as a polygon (I have not yet developed a code for this case). The logic is as follows:

1. Determine the vertex of the polyline whose distance from the point in question is minimal. A variable minimum2pis the distance to this vertex, the I2pindex of the vertex.

2. Determine the segment of the polyline whose distance from the point in question is minimal. Only those segments are counted (variable count_s) that intersect perpendicular from the point in question. A variable minimum2sis the minimum distance to a segment; I2p- index of the first vertex of this segment; flagis a logical variable that stores information about which segment is crossed by the specified perpendicular.

3. Next, you just need to select the correct segment for comparison using, for example, ideas from links link-1 , link-2 or link-3 . I tried this approach from here , but it does not work for many special cases. I use the best answer for interior points of a polyline. So my approach is this:

4. First check if this is the first or last vertex of the polyline. If so, then the selected segment is either the first or the last, respectively, but only if there is no other segment closer than the first or last. If there is another segment, then I selected this segment.

5. , 4 , . , I2p I2s, . , . , , .

6. , ( , ), .

, X Y , 'polylineX' "polylineY" ( "" , "" , - , - ).

, . . ? , ?

:

clear all
close all 
clc
clf
polylineX = [0 1 2 3 4 5 6 7 8];
polylineY = [-10 20 -13 18 -17 16 -21 23 -25];
hold on
title(['polylineX=[',num2str(polylineX),'], polylineY=[',num2str(polylineY),']'])
chosen = 0;
span = 60;

for ii = 10:70
for jj = 30:60
    ii
    jj
    position = -2;
    point = [(jj-round(span/2))/1 (ii-round(span/2))/1];

    axis equal
    plot(polylineX,polylineY,'.-','MarkerSize',1,'LineWidth',1);

    distance2p = zeros(1,length(polylineX)); % distances from the point to the points (2p) of the polyline
    distance2s = zeros(1,length(polylineX)-1); % distances from the point to the segments (2s) of the polyline
    flag = zeros(1,length(polylineX)-1);
    count_s = 0; % counter of segments, which are intersected by the normal pointing from the 'point'
    k = 0;

    for i = 1:length(polylineX)-1
        pos = sign((polylineX(i+1) - polylineX(i)) * (point(2) - polylineY(i)) -...
                   (polylineY(i+1) - polylineY(i)) * (point(1) - polylineX(i)));

        % computing the distances from the 'point' to all segments and mark if
        % the distance vectors intersect the segments
        [flag(i),distance2s(i)] = distanceToLine([polylineX(i) polylineX(i+1)],[polylineY(i) polylineY(i+1)],[point(1) point(2)]);

        if flag(i)
            if k == 0
                minimum2s = distance2s(i);
                I2s = i;
            end;
            k = 1;
            count_s = count_s + 1; % count segments, which are intersected by the normal pointing from the 'point'
            if distance2s(i) < minimum2s
                I2s = i;
                minimum2s = distance2s(i);
            end;
        end;
    end;


    % first compute the distances between the 'point' under consideration and the
    % points of the given polyline
    for i  = 1:length(polylineX)
        distance2p(i) = sqrt((point(1)-polylineX(i))^2+(point(2)-polylineY(i))^2);
    end;
    [minimum2p,I2p] = min(distance2p);
    clear k pos i

    % now we need to choose which segment of the polyline to compare our 'point' with. These
    % segments are either adjacent to that point of the polyline, which is the closest
    % to the 'point' of interest, or the closest to the 'point' segment, which
    % has an intersection with the normale pointing from the 'point'.

    if I2p == 1 % if the 'point' is near the start of polyline
        if exist('minimum2s','var')
            if I2p == I2s
                chosen = I2p;
            else
                chosen = I2s;
            end;
        else
            chosen = I2p;
        end;

    elseif I2p == length(polylineX) % if the 'point' is near the end of polyline
        if exist('minimum2s','var')
            if I2s == I2p-1
                chosen = I2p - 1;
            else
                chosen = I2s;
            end;
        else
            chosen = I2p - 1;
        end;
    else
        if exist('minimum2s','var')
            if I2p == I2s
                chosen = I2p;

            else
                chosen = I2s;
            end;
        else
                pos1 =  sign((polylineX(I2p) - polylineX(I2p-1)) * (point(2) - polylineY(I2p-1)) -...
                 (polylineY(I2p) - polylineY(I2p-1)) * (point(1) - polylineX(I2p-1)));
                % position of the second segment relative to the first segment
                pos2 =  sign((polylineX(I2p) - polylineX(I2p-1)) * (polylineY(I2p+1) - polylineY(I2p-1)) -...
                             (polylineY(I2p) - polylineY(I2p-1)) * (polylineX(I2p+1) - polylineX(I2p-1)));
                if (pos1 == 1 && pos2 == 1) || (pos1 == -1 && pos2 == -1)
                    chosen = I2p;
                elseif pos1 == 0 || pos2 == 0
                    chosen = I2p;
                else
                    chosen = I2p - 1;
                end;
        end;
    end;

    position = sign((polylineX(chosen+1) - polylineX(chosen)) * (point(2) - polylineY(chosen)) -...
                    (polylineY(chosen+1) - polylineY(chosen)) * (point(1) - polylineX(chosen)));

    if position == 1
        plot(point(1),point(2),'r.','MarkerSize',5)
    elseif position == -1;
        plot(point(1),point(2),'.','Color',[0.9 0.9 0.9],'MarkerSize',5) % gray color
    elseif position == 0
        plot(point(1),point(2),'k.','MarkerSize',5)
    elseif position == -2
        plot(point(1),point(2),'g.','MarkerSize',5)
    end;

    pause(0.00000001)
    clear chosen  count_s distance2p distance 2s flag I2p I2s minimum2p minimum2s point pos1 pos2 position

end;
end;
+4
2

, - "? , , .

, , , , 2 * Pi . , , "" "". , +/- Pi, + Pi, -Pi. + Pi -Pi, , .

- () , . , , , . ( ), , . . , - ( z- ), , .

0

, , - . , . atan2.

. , .

python:

from math import atan2,pi
#import matplotlib.pyplot as plt

# difference of two angles should be always -pi < x < pi
def fixed_angle(a):
    if a > pi:
       return a - 2*pi
    elif a < (-1*pi):
       return a + 2*pi
    assert(-1*pi < a < pi) # just check, to be sure
    return a

# polyline
xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
ys = [-10, 20, -13, 18, -17, 16, -21, 23, -25];

# start point
x = 4
y = 0

#from first two points
angle_start = atan2(ys[0]-ys[1],xs[0]-xs[1])
#last angle is angle of last section
angle_end = atan2(ys[-1]-ys[-2],xs[-1]-xs[-2]) 

integ = 0
prev =  angle_start
for i in range(len(xs)):
    a = atan2(ys[i]-y,xs[i]-x)
    integ += fixed_angle(a-prev)
    prev = a

integ += fixed_angle(angle_end - prev)

if integ > 0:
    print("point is left")
else:
    print("point is right")

#plt.plot(xs,ys)
#plt.show()
0

All Articles