function loops = extractloops(edges)
%
% loops=extractloops(edges)
%
% extract individual loop or polyline segment from a collection of edges
%
% author: Qianqian Fang, <q.fang at neu.edu>
% date: 2007/11/21
%
% input:
%    edges:  two column matrix recording the starting/ending
%             points of all edge segments
%
% output:
%    loops:  output, a single vector separated by NaN, each segment
%             is a 3D polyline or loop consisted of node IDs
%
% example:
%    edges=[1 2;2 3;1 4;3 4;7 3;1 9;5 6;6 7;10 9; 8 10;1 8;9 3;11 11;11 12];
%    loops=extractloops(edges)
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

loops = [];
edges(edges(:, 1) == edges(:, 2), :) = []; % remove degenerated edges
loops = [loops, edges(1, :)];
loophead = edges(1, 1);
loopend = edges(1, end);
edges(1, :) = [];

while (~isempty(edges))
    idx = [find(edges(:, 1) == loopend)', find(edges(:, 2) == loopend)'];
    if (length(idx) > 1) % when a node with multiple connection found
        idx = idx(1);   % take the first connection and continue
    end
    if (isempty(idx)) % when an open-line segment gets to one end
        % when both open ends are found
        if (isempty([find(edges(:, 1) == loophead)', find(edges(:, 2) == loophead)']))
            loops = [loops, nan];
            loops = [loops, edges(1, :)];
            loophead = edges(1, 1);
            loopend = edges(1, end);
            edges(1, :) = [];
        else % only the first open end is found, flip and trace the other
            [loophead, loopend] = deal(loopend, loophead);
            lp = fliplr(loops);
            seg = find(isnan(lp), 1);
            if (isempty(seg))
                loops = lp;
            else
                loops = [loops(1:end - seg(1) + 1) lp(1:seg(1) - 1)];
            end
        end
        continue
    end
    if (length(idx) == 1) % tracing along a single line thread
        idx = idx(1);
        ed = edges(idx, :);
        ed(ed == loopend) = [];
        newend = ed(1);
        if (newend == loophead)  % when a loop is found
            loops = [loops loophead nan];
            edges(idx, :) = [];
            if (size(edges, 1) == 0)
                break
            end
            loops = [loops, edges(1, :)];
            loophead = edges(1, 1);
            loopend = edges(1, end);
            edges(1, :) = [];
            continue
        else
            loops = [loops, newend];
        end
        loopend = newend;
        edges(idx, :) = [];
    end
end
