Connect points and compute area

前端 未结 4 787
走了就别回头了
走了就别回头了 2021-01-26 12:48

thats my first post, so please be kind.

I have a matrix with 3~10 coordinates and I want to connect these points to become a polygone with maximum size.

I tried

4条回答
  •  难免孤独
    2021-01-26 13:42

    Finding the right order for the points is the hard part, as Amro commented. Does this function suffice?

    function [idx] = Polyfy(x, y)
    % [idx] = Polyfy(x, y)
    % Given vectors x and y that contain pairs of points, find the order that
    % joins them into a polygon. fill(x(idx),y(idx),'r') should show no holes.
    
    %ensure column vectors
    if (size(x,1) == 1)
      x = x';
    end
    if (size(y,1) == 1)
      y = y';
    end
    
    % vectors from centroid of points to each point
    vx = x - mean(x);
    vy = y - mean(y);
    % unit vectors from centroid towards each point
    v = (vx + 1i*vy)./abs(vx + 1i*vy);
    vx = real(v);
    vy = imag(v);
    
    % rotate all unit vectors by first
    rot = [vx(1) vy(1) ; -vy(1) vx(1)];
    v = (rot*[vx vy]')';
    
    % find angles from first vector to each vector
    angles = atan2(v(:,2), v(:,1));
    [angles, idx] = sort(angles);
    end
    

    The idea is to find the centroid of the points, then find vectors from the centroid to each point. You can think of these vectors as sides of triangles. The polygon is made up the set of triangles where each vector is used as the "left" and "right" only once, and no vectors are skipped. This boils down to ordering the vectors by angle around the centroid.

    I chose to do this by normalizing the vectors to unit length, choosing one of them as a rotation vector, and rotating the rest. This allowed me to simply use atan2 to find the angles. There's probably a faster and/or more elegant way to do this, but I was confusing myself with trig identities. Finally, sorting those angles provides the correct order for the points to form the desired polygon.

    This is the test function:

    function [x, y] = TestPolyArea(N)
    x = rand(N,1);
    y = rand(N,1);
    [indexes] = Polyfy(x, y);
    x2 = x(indexes);
    y2 = y(indexes);
    a = polyarea(x2, y2);
    disp(num2str(a));
    fill(x2, y2, 'r');
    hold on
    plot(x2, y2, '.');
    hold off
    end
    

    You can get some pretty wild pictures by passing N = 100 or so!

提交回复
热议问题