Skip to content

Fit a smooth closed shape through 4 points

6 messages · Alexander Shenkin, Charles Determan, S Ellison +2 more

#
Hello all,

I have sets of 4 x/y points through which I would like to fit closed, 
smoothed shapes that go through those 4 points exactly.  smooth.spline 
doesn't like my data, since there are only 3 unique x points, and even 
then, i'm not sure smooth.spline likes making closed shapes.

Might anyone else have suggestions for fitting algorithms I could employ?

Thanks,
Allie


shapepoints = structure(c(8.9, 0, -7.7, 0, 0, 2, 0, 3.8), .Dim = c(4L,
2L), .Dimnames = list(NULL, c("x", "y")))

smooth.spline(shapepoints)

# repeat the first point to close the shape
shapepoints = rbind(shapepoints, shapepoints[1,])

smooth.spline(shapepoints)
#
Hi Allie,

What is you goal here?  Do you just want to plot a curve to the data?  Do
you want a function to approximate the data?

You may find the functions spline() and splinefun() useful.

Quick point though, with so few points you are only going to get a very
rough approximation no matter the method used.

Regards,
Charles
On Mon, Mar 21, 2016 at 7:59 AM, Alexander Shenkin <ashenkin at ufl.edu> wrote:

            

  
  
#
Thanks for your reply, Charles.  spline() doesn't seem to fit a closed 
shape; rather, it's producing a parabola.  Perhaps I'm missing an 
argument I should include?

grid.xspline() seems to get close to what I need, but it returns a grob 
object - not sure how to work with those as shapes per se.

My goal is to produce a 2D shape from which I can calculate area, 
average widths, and other such things.  The context is that we have 
measured tree crowns in a manner that has produced 4 points such as 
these from two offset axes.  We want to use the resulting shapes for our 
calculations.

(incidentally, my original points were off - here are the correct ones)

shapepoints = structure(list(x = c(8.9, 0, -7.7, 0, 8.9), y = c(0, 2, 0, 
-3.8,
0)), .Names = c("x", "y"), row.names = c(NA, -5L), class = "data.frame")

plot(spline(shapepoints))

Thanks,
Allie
On 3/21/2016 1:10 PM, Charles Determan wrote:
#
Is there a reason not to use the convex hull for area calculations? Any curve you put through the points would surely be at least as arbitrary as a straight line.

S Ellison
*******************************************************************
This email and any attachments are confidential. Any use...{{dropped:8}}
#
Dear Allie,

You could use elliptic fourier analysis

shapepoints = structure(list(x = c(8.9, 0, -7.7, 0, 8.9), y = c(0, 2, 0,
-3.8,
0)), .Names = c("x", "y"), row.names = c(NA, -5L), class = "data.frame")

shapepoints$Theta <- seq(0, 2 * pi, length = nrow(shapepoints))
model <- lm(cbind(x, y) ~ I(sin(Theta)) + I(cos(Theta)), data = shapepoints)
model2 <- lm(cbind(x, y) ~ I(sin(Theta)) + I(cos(Theta)) + I(sin(2 *
Theta)) + I(cos(2 * Theta)), data = shapepoints)

newdata <- data.frame(Theta = seq(0, 2 * pi, length = 41))
plot(predict(model, newdata = newdata), type = "l", xlim = c(-10, 10), ylim
= c(-10, 10))
points(shapepoints, col = "red")
plot(predict(model2, newdata = newdata), type = "l", xlim = c(-10, 10),
ylim = c(-10, 10))
points(shapepoints, col = "red")

Best regards,

Thierry

ir. Thierry Onkelinx
Instituut voor natuur- en bosonderzoek / Research Institute for Nature and
Forest
team Biometrie & Kwaliteitszorg / team Biometrics & Quality Assurance
Kliniekstraat 25
1070 Anderlecht
Belgium

To call in the statistician after the experiment is done may be no more
than asking him to perform a post-mortem examination: he may be able to say
what the experiment died of. ~ Sir Ronald Aylmer Fisher
The plural of anecdote is not data. ~ Roger Brinner
The combination of some data and an aching desire for an answer does not
ensure that a reasonable answer can be extracted from a given body of data.
~ John Tukey

2016-03-21 15:04 GMT+01:00 Alexander Shenkin <ashenkin at ufl.edu>:

  
  
#
Hi

If Xsplines give you the shape you want, then you can retrieve points on 
the boundary of the shape using xsplinePoints().  For example ...

shapepoints <- structure(list(x = c(8.9, 0, -7.7, 0, 8.9),
                               y = c(0, 2, 0, -3.8, 0)),
                          .Names = c("x", "y"),
                          row.names = c(NA, -5L),
                          class = "data.frame")

library(grid)
grid.newpage()
pushViewport(dataViewport(shapepoints[,1], shapepoints[,2]))
grid.points(shapepoints[,1], shapepoints[,2], default.units="native")
grid.xspline(shapepoints[-1,1], shapepoints[-1,2],
              default.units="native", shape=-1, open=FALSE)

xsg <- xsplineGrob(shapepoints[-1,1], shapepoints[-1,2],
                    default.units="native", shape=-1, open=FALSE)
# THIS is the information I think you want
trace <- xsplinePoints(xsg)
grid.points(trace$x, trace$y, default.units="native",
             size=unit(1, "mm"), pch=16)

Paul
On 22/03/16 03:04, Alexander Shenkin wrote: