I assume this is a simple task, yet I could not find any documentation or question treating this problem:

Let's say we have a simple binary data set, in this case defining a shape of a circle

data = Flatten[Table[{x, y, If[x^2 + y^2 < 1, 1, 0]}, {x, -2, 2, 0.1}, {y, -2, 2, 0.1}], 1];
ListDensityPlot[data, InterpolationOrder -> 0]

Now I want to have the points forming the boundary of this object, in coordinates {{x1,y1},{x2,y2},...}.

It seems to be exactly what EdgeDetect is doing, but that function does not accept data points, only images. Is there a similar function for data points?

These posts are related, but not the same in my opinion:

  1. Finding edges of a parametrized function
  2. Finding the edge of the plot area
  3. Finding the edge of data set

The last question (3) is probably the same but the input data format seems to be different than here and the data is not available anymore.

enter image description here

  • $\begingroup$ ConvexHullMesh if convex. $\endgroup$ – george2079 Feb 2 '17 at 22:36
  • $\begingroup$ Thanks, but what if it's not convex? $\endgroup$ – Felix Feb 2 '17 at 22:40

Turn the data into an image, apply EdgeDetect, and (if needed) translate back to ImageData:

data = Table[If[x^2 + y^2 < 1, 1, 0], {x, -2, 2, 0.1}, {y, -2, 2, 0.1}];
edge = EdgeDetect[Image[data]]
edgeData = Table[{(x - 21)/10, (y - 21)/10, 
                 ImageData[edge][[x, y]]}, {x, 41}, {y, 41}];

The final line puts the {x,y} coordinates with the edges.

  • $\begingroup$ It works. However, I would suggest as a general approach to keep extract the {x,y} coordinates in a slightly different way. The function f[data_, component_] := Reverse[Partition[data[[All, component]], Length[DeleteDuplicates[data[[All, 2]]]]]] extracts one of the components of data and brings it to the {nx,ny} image shape. Then, edgeData =Transpose[{Flatten[f[data,1]], Flatten[f[data,2]], Flatten[ImageData[edge]]}] (where data is defined as in my post). $\endgroup$ – Felix Feb 3 '17 at 4:32
  • $\begingroup$ Just realized one typo in f. To be robust, it should read f[data_, component_] := Module[{sdata}, sdata = Sort[data, If[#1[[2]] == #2[[2]], #1[[1]] < #2[[1]], #1[[2]] < #2[[2]]] &]; Return[ Reverse[Partition[sdata[[All, component]], Length[DeleteDuplicates[sdata[[All, 1]]]]]]]]; $\endgroup$ – Felix Feb 3 '17 at 5:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.