views:

220

answers:

1

Hi,

I have a set of points represented as a 2 row by n column matrix. These points make up a connected boundary or edge. I require a function that traces this contour from a start point P1 and stop at an end point P2. It also needs to be able trace the contour in a clockwise or anti-clockwise direction. I was wondering if this can be achieved by using some of matlabs functions.

I have tried to write my own function but this was riddled with bugs and I have also tried using bwtraceboundary and indexing however this has problematic results as the points within the matrix are not in the order that create the contour.

Thank you in advance for any help.

Btw, I have included a link to a plot of the set of points. It is half the outline of a hand.

The function would ideally trace the contour from ether the red star to the green triangle. Returning the points in order of traversal.

EDIT: This is perhaps a work around to a larger problem I am trying to solve but would it be possible to test if a point on the blue boundary edge is connected to the contour that is between ethier the red stars or green triangular points.

i.e. for a point on the blue boundary, if you were to trace the contour by hand from the left red asterixs to the green triangle the function would return true if the point is on the connected boundary between the two points and false otherwise.

alt text

+2  A: 

If the points are so close together, you should be able to do the trace by always looking for the next closest point in the list.

If the point were farther apart, the problem would not be solvable - imagine the five points where four are corners and one is in the center: what is the 'correct' way of tracing the line?

%%# create some points
npts = 100;
x = linspace(-1,1,100)'; %'
y = 1 - x.^2;
pts = [x,y];

%# shuffle the points
newOrder = randperm(npts);
pts = pts(newOrder,:);

%# find index of start, end point
startIdx = find(newOrder == 1);
endIdx = find(newOrder == npts);

%# this brings us to where you are - pts as a nx2 array
%# startIdx indicates the star, and endIdx indicates the triangle.

%# pre-assign output - traceIdx, which contains the ordered indices of the point on the trace
traceIdx = NaN(npts,1);

%# create distance matrix
distances = squareform(pdist(pts));

%# eliminate zero-distance along the diagonal, b/c we don't want points linking to themselves
distances(logical(eye(npts))) = NaN;

%# starting from startIdx: always find the closest next point, store in traceIdx,
%# check whether we've arrived at the end, and repeat if we haven't
done = false;
traceCt = 1;
traceIdx(1) = startIdx;

while ~done
    %# find the index of the next, closest point
    [dummy,newIdx] = min(distances(traceIdx(traceCt),:));

    %# store new index and up the counter
    traceCt = traceCt + 1;
    traceIdx(traceCt) = newIdx;

    %# check whether we're done
    if newIdx == endIdx
        done = true;
    else
        %# mask the backward distance so that there's no turning back
        distances(newIdx,traceIdx(traceCt-1)) = NaN;
    end %# if
end %# while ~done

%# remove NaNs
traceIdx(~isfinite(traceIdx)) = [];

%# plot result with a line connecting the dots to demonstrate that everything went well.
figure,
plot(pts(traceIdx,1),pts(traceIdx,2),'-o')
hold on,
plot(pts(startIdx,1),pts(startIdx,2),'*r')
plot(pts(endIdx,1),pts(endIdx,2),'>g')
Jonas
Thankyou Jonas I had not realised that this may actually be unsolvable!
Graham
I wouldnt call it unsolvable but rather intractable.
Amro
@Jonas - Thankyou for providing your code snippet. I did incounter one problem which involved the no turning back section, instead of just marking the last point to NaN I selected all the previously selected points to NaN. instead of: distances(newIdx,traceIdx(traceCt-1)) = NaN;distances(:,traceIdx(1:traceCt)) = NaN; (he thinks of the top of his head)Btw Jonas, I am very impressed in your matlab skills!
Graham

related questions