Home > matGeom > polygons2d > medialAxisConvex.m

medialAxisConvex

PURPOSE ^

MEDIALAXISCONVEX Compute medial axis of a convex polygon.

SYNOPSIS ^

function [nodes, edges] = medialAxisConvex(points)

DESCRIPTION ^

MEDIALAXISCONVEX Compute medial axis of a convex polygon.

   [N, E] = medialAxisConvex(POLYGON);
   where POLYGON is given as a set of points [x1 y1;x2 y2 ...], returns
   the medial axis of the polygon as a graph.
   N is a set of nodes. The first elements of N are the vertices of the
   original polygon.
   E is a set of edges, containing indices of source and target nodes.
   Edges are sorted according to order of creation. Index of first vertex
   is lower than index of last vertex, i.e. edges always point to newly
   created nodes.

   Notes:
   - Is not fully implemented, need more development (usually crashes for
       polygons with more than 6-7 points...)
   - Works only for convex polygons.
   - Complexity is not optimal: this algorithm is O(n*log n), but linear
   algorithms exist.

   See also:
   polygons2d, bisector

   ---------
   author : David Legland
   INRA - TPV URPOI - BIA IMASTE
   created the 07/07/2005.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [nodes, edges] = medialAxisConvex(points)
0002 %MEDIALAXISCONVEX Compute medial axis of a convex polygon.
0003 %
0004 %   [N, E] = medialAxisConvex(POLYGON);
0005 %   where POLYGON is given as a set of points [x1 y1;x2 y2 ...], returns
0006 %   the medial axis of the polygon as a graph.
0007 %   N is a set of nodes. The first elements of N are the vertices of the
0008 %   original polygon.
0009 %   E is a set of edges, containing indices of source and target nodes.
0010 %   Edges are sorted according to order of creation. Index of first vertex
0011 %   is lower than index of last vertex, i.e. edges always point to newly
0012 %   created nodes.
0013 %
0014 %   Notes:
0015 %   - Is not fully implemented, need more development (usually crashes for
0016 %       polygons with more than 6-7 points...)
0017 %   - Works only for convex polygons.
0018 %   - Complexity is not optimal: this algorithm is O(n*log n), but linear
0019 %   algorithms exist.
0020 %
0021 %   See also:
0022 %   polygons2d, bisector
0023 %
0024 %   ---------
0025 %   author : David Legland
0026 %   INRA - TPV URPOI - BIA IMASTE
0027 %   created the 07/07/2005.
0028 %
0029 
0030 %   HISTORY
0031 %   18/04/2007: fix some typos, note the function to be unimplemented
0032 
0033 %   TODO: is not fully implemented, need to finish it
0034 
0035 % eventually remove the last point if it is the same as the first one
0036 if points(1,:) == points(end, :)
0037     nodes = points(1:end-1, :);
0038 else
0039     nodes = points;
0040 end
0041 
0042 % special case of triangles:
0043 % compute directly the gravity center, and simplify computation.
0044 if size(nodes, 1)==3
0045     nodes = [nodes; mean(nodes, 1)];
0046     edges = [1 4;2 4;3 4];
0047     return
0048 end
0049 
0050 % number of nodes, and also of initial rays
0051 N = size(nodes, 1);
0052 
0053 % create ray of each vertex
0054 rays = zeros(N, 4);
0055 rays(1, 1:4) = bisector(nodes([2 1 N], :));
0056 rays(N, 1:4) = bisector(nodes([1 N N-1], :));
0057 for i=2:N-1
0058     rays(i, 1:4) = bisector(nodes([i+1, i, i-1], :));
0059 end
0060 
0061 % add indices of edges producing rays (indices of first vertex, second
0062 % vertex is obtained by adding one modulo N).
0063 rayEdges = [[N (1:N-1)]' (1:N)'];
0064 
0065 pint = intersectLines(rays, rays([2:N 1], :));
0066 
0067 % compute the distance between each intersection point and the closest
0068 % edge. This distance is used as marker to propagate processing front.
0069 ti = zeros(N, 1);
0070 for i = 1:N
0071     line = createLine(points(mod(i-2, N)+1, :), points(i, :));
0072     ti(i) = abs(distancePointLine(pint(i,:), line));
0073 end
0074 
0075 % create list of events.
0076 % terms are : R1 R2 X Y t0
0077 % R1 and R2 are indices of involved rays
0078 % X and Y is coordinate of intersection point
0079 % t0 is position of point on rays
0080 events = sortrows([ (1:N)' [2:N 1]' pint ti], 5);
0081 
0082 % initialize edges
0083 edges = zeros(0, 2);
0084 
0085 
0086 % -------------------
0087 % process each event until there is no more
0088 
0089 % start after index of last vertex, and process N-3 intermediate rays
0090 for i = N+1:2*N-3
0091     % add new node at the rays intersection
0092     nodes(i,:) = events(1, 3:4);
0093     
0094     % add new couple of edges
0095     edges = [edges; events(1,1) i; events(1,2) i]; %#ok<AGROW>
0096             
0097     % find the two edges creating the new emanating ray
0098     n1 = rayEdges(events(1, 1), 1);
0099     n2 = rayEdges(events(1, 2), 2);    
0100     
0101     % create the new ray
0102     line1 = createLine(nodes(n1, :), nodes(mod(n1,N)+1, :));
0103     line2 = createLine(nodes(mod(n2,N)+1, :), nodes(n2, :));
0104     ray0 = bisector(line1, line2);
0105     
0106     % set its origin to emanating point
0107     ray0(1:2) = nodes(i, :);
0108 
0109     % add the new ray to the list
0110     rays = [rays; ray0]; %#ok<AGROW>
0111     rayEdges(size(rayEdges, 1)+1, 1:2) = [n1 n2];
0112     
0113     % find the two neighbour rays
0114     ind = sum(ismember(events(:,1:2), events(1, 1:2)), 2) ~= 0;
0115     ir = unique(events(ind, 1:2));
0116     ir = ir(~ismember(ir, events(1,1:2)));
0117     
0118     % create new intersections
0119     pint = intersectLines(ray0, rays(ir, :));
0120     ti = abs(distancePointLine(pint, line1));
0121     
0122     % remove all events involving old intersected rays
0123     ind = sum(ismember(events(:,1:2), events(1, 1:2)), 2) == 0;
0124     events = events(ind, :);
0125     
0126     % add the newly formed events
0127     events = [events; ir(1) i pint(1,:) ti(1); ir(2) i pint(2,:) ti(2)]; %#ok<AGROW>
0128 
0129     % and sort them according to 'position' parameter
0130     events = sortrows(events, 5);
0131 end
0132 
0133 % centroid computation for last 3 rays
0134 nodes = [nodes; mean(events(:, 3:4))];
0135 edges = [edges; [unique(events(:,1:2)) ones(3, 1)*(2*N-2)]];

Generated on Wed 16-Feb-2022 15:10:47 by m2html © 2003-2019