5
$\begingroup$

I have data of closed shape form

ListPlot[data, AspectRatio -> 1]   

enter image description here

I would like to Interpolate this data to get the missing points so I am using BSplineFunction like this

interdata=BSplineFunction[Flatten[points, 1]];
ParametricPlot[bsF[t], {t, 0, 1}]    

enter image description here

as you can see, the data needs to be sorted in a specific way to make all the points on the circumference of the closed shape and get something like this

enter image description here

Update

The last thing I would like to do is to get points on the circumference that are equally spaced. my idea was that after interpolation I will be able to do that. According to @kglr answer, it can be done as follows

equallyspaceddata = Table[{bsF[t]}, {t, 0, 1, 0.01}];
ListPlot[equallyspaceddata, AspectRatio -> 1, PlotStyle -> Black]

enter image description here

as you can see the points in the top half are denser compared to the bottom one. How can I get equally spaced points?

$\endgroup$

2 Answers 2

5
$\begingroup$

Update: " to get points on the circumference that are equally spaced":

Use MeshFunctions -> {ArcLength} and Mesh -> m to get m equally-spaced points on the parametric curve:

m = 50;

ParametricPlot[bsF[t], {t, 0, 1}, 
 MeshFunctions -> {ArcLength}, 
 Mesh -> m, 
 MeshStyle -> Directive[PointSize @ Medium, Red], 
 Epilog -> {Directive[PointSize @ Medium, Green], Point @ bsF[0]}]

enter image description here

Original answer:

Use FindCurvePath:

fcp = FindCurvePath[data];

sorteddata = data[[fcp[[1]]]];

ListLinePlot[sorteddata, AspectRatio -> 1]

enter image description here

bsF = BSplineFunction[sorteddata];

ParametricPlot[bsF[t], {t, 0, 1}]

enter image description here

Try also ListCurvePathPlot:

ListCurvePathPlot[data]

enter image description here

$\endgroup$
4
  • $\begingroup$ AWESOME, thanks a lot! $\endgroup$ Dec 28, 2021 at 9:25
  • $\begingroup$ may you please see my update? $\endgroup$ Dec 28, 2021 at 10:29
  • $\begingroup$ Thanks, but how can I get the red pint as a list to use them in a calculation? $\endgroup$ Dec 28, 2021 at 11:55
  • 1
    $\begingroup$ @valarmorghulis, one way is to extract the point coordinates from ParametricPlot: e.g,, pp=ParametricPlot[..., MeshFunctions -> {ArcLength}, Mesh ->50]; pointcoords= Cases[Normal@pp, Point[x_] :> x, All] $\endgroup$
    – kglr
    Dec 28, 2021 at 12:24
2
$\begingroup$
data = Import["/Users/roberthanlon/Downloads/data.dat"];

Since you are dealing with a circle:

EDIT 2: Using minimization to determine the center and radius

{center, radius} = {{x0, y0}, r} /. Minimize[{Total[
      (EuclideanDistance[#, {x0, y0}] - r)^2 & /@ data],
     r > 0}, {x0, y0, r}][[2]]

(* {{-4.22506*10^-14, -4.04645*10^-14}, 0.693182} *)

Manipulate[
 Graphics[{
   AbsoluteThickness[1], Red,
   Circle[center, radius], Blue,
   Point[CirclePoints[center, radius, n]]}],
 {{n, 51}, 3, 300, 3, Appearance -> "Labeled"}]

enter image description here

EDIT: Version 13 has a new function RegionFit

{center, radius} = List @@ RegionFit[data, "Circle"]

(* {{-0.00115749, -9.88079*10^-16}, 0.694887} *)
$\endgroup$
1
  • $\begingroup$ that is nice, but it is not always a circle, it can be any closed shape such as a rectangle or triangle. for example, your approach cant work with this data $\endgroup$ Dec 29, 2021 at 6:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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