[Date Index]
[Thread Index]
[Author Index]
Re: fit plane to xz axis of data
*To*: mathgroup at smc.vnet.net
*Subject*: [mg89610] Re: fit plane to xz axis of data
*From*: will parr <willpowers69 at hotmail.com>
*Date*: Sat, 14 Jun 2008 05:32:12 -0400 (EDT)
> On Jun 11, 11:57 pm, "Szabolcs Horv=E1t"
> <szhor... at gmail.com> wrote:
> > On Wed, Jun 11, 2008 at 10:20, will parr
> <willpower... at hotmail.com> wrote:=
>
> > > Dear Math Forum,
> >
> > > I am having problems fitting a plane to some
> data. I am using the follow=
> ing procedure to fit the plane to my data (data is
> pasted at the bottom of t=
> his message):
> >
> > > In[2]:= plane = Fit[data, {1, x, y}, {x, y}]
> >
> > > Out[2]= 3.28723- 0.189001 x - 0.0874557 y
> >
> > > Then the following to display the points and
> plane:
> >
> > > Show[ListPointPlot3D[data, Boxed -> False, Axes
> -> True,
> > > AxesEdge -> {{-1, -1}, {-1, -1}, {-1, -1}},
> > > AxesLabel -> {"x", "y", "z"}],
> > > Plot3D[plane, {x, Min[data[[All, 1]]],
> Max[data[[All, 1]]]}, {y,
> > > Min[data[[All, 2]]], Max[data[[All, 2]]]},
> > > PlotStyle -> Directive[Green, Opacity[0.5]],
> > > Mesh -> None]]
> >
> > > This works fine at fitting the plane in the xy
> axis, but I want to fit t=
> he plane to the xz axis. Does anyone know how this is
> done?
> >
> > You just need to permute the coordinates:
> >
> > Replace[data, {x_, y_, z_} :> {x, z, y}, 1]
> >
> > Or, if necessary, you can do an "isotropic" fitting
> (that prefers no
> > axis) by calculating the distances from the plane.
> The original
> > fitting attempt showed that the plane will not pass
> through {0,0,0} so
> > we can use the equation a x + b y + c z == 1. The
> distance-squared of=
>
> > point {x,y,z} from this plane is (a x + b y + c z -
> 1)^2/(a^2 + b^2 +
> > c^2), so the fitting can be done like this:
> >
> > In[2]:= planei =
> > a x + b y + c z /.
> > Last@NMinimize[
> > Expand@Total[
> > Function[{x, y, z}, (a x + b y + c z - 1)^2]
> @@@ data]/(
> > a^2 + b^2 + c^2), {a, b, c}]
> >
> > Out[2]= 0.100048 x + 0.0136288 y + 0.0112116 z
> >
> > In[3]:= plane = Fit[data, {1, x, y}, {x, y}]
> >
> > Out[3]= 3.28723- 0.189001 x - 0.0874557 y
> >
> > In[4]:= plane2 =
> > Fit[Replace[data, {x_, y_, z_} -> {x, z, y}, 1],
> {1, x, z}, {x, z}]
> >
> > Out[4]= 8.12817- 0.817828 x - 0.225109 z
> >
> > In[5]:= {{xa, xb}, {ya, yb}, {za, zb}} = {Min[#],
> Max[#]} & /@
> > Transpose[data]
> >
> > Out[5]= {{7.08299, 11.4614}, {-5.66284, 4.59986},
> {-1.83404,
> > 4.49073}}
> >
> > In[6]:= Show[
> > ContourPlot3D[planei == 1, {x, xa, xb}, {y, ya,
> yb}, {z, za, zb},
> > ContourStyle -> Directive[Blue, Opacity[.5]],
> Mesh -> None],
> > Plot3D[plane, {x, xa, xb}, {y, ya, yb},
> > PlotStyle -> Directive[Green, Opacity[0.5]], Mesh
> -> None],
> > ContourPlot3D[plane2 == y, {x, xa, xb}, {y, ya,
> yb}, {z, za, zb},
> > ContourStyle -> Directive[Red, Opacity[.5]], Mesh
> -> None],
> > ListPointPlot3D[data, PlotStyle -> Black],
> > PlotRange -> All, AxesLabel -> {"x", "y", "z"}
> > ]
> >
> > Your points don't seem to lie on a plane, so the
> three approaches give
> > give different results.
>
> The following will find the best-fitting (i.e.,
> least-squares) plane:
>
> m = Mean[data]; {u,w,v] =
> = SingularValueDecomposition[#-m&/@data];
>
> v is a rotation matrix. Tr[w,List] (i.e., the
> diagonal elements of w)
> gives the norms of the projections of the points onto
> the new axes.
> They are in decreasing order, so
>
> ({x,y,z}-m).v[[All,3]] == 0
>
> gives the equation which the best-fitting plane
> satisfies.
>
I'm really interested in this solution, but when I to use this method, I get an answer that I don't really understand, and cannot display (in the form of a plane).
using the original data in this message:
In[122]:= m = Mean[data]; {u, w, v} =
SingularValueDecomposition[# - m & /@ data];
In[123]:= Tr[w, List]
Out[123]= {16.3822, 9.63356, 5.71769}
In[124]:= ({x, y, z} - m).v[[All, 3]] == 0
Out[124]=
0.984797 (-9.86988 + x) + 0.134151 (0.269052+ y) +
0.110358 (-1.44535 + z) == 0
I don't understand this output, it is not of the form:
ax + by + cz
Additionally, is it possible to compute a vector running parallel to the long side (long axis of the SVD plane) of the computed plane, originating at the mean (centroid) of the data, with a length of 1?
I have the following bits of code with respect to this:
(*normalizes a vector to unit length*)
normalizevec[v_] := v/Sqrt[v.v + 0.0];
(*takes equation of a plane (e.g.1+2x+3y) and returns normal vector*)
planeeq2normalvec[e_] := normalizevec[{D[e, x], D[e, y], -1}];
I then use VectorAngle in the following way to find the 2D angle (in degrees) between the calculated 3D vector (that i don't have in this instance) and the x axis:
XVector = {{1, 0, 0}, {1, 0, 0}};
AngleX =
VectorAngle[
XVector[[1]][[{1, 2}]], (CALCULATED3DVECTOR[[{1, 2}]])]*180/\[Pi];
Thanks for your help,
best wishes,
Will
Prev by Date:
**FYI, Tally is still broken. So are some symbolic eigenvalues**
Next by Date:
**Re: Manipulate: Positioning of controls within panel**
Previous by thread:
**Re: fit plane to xz axis of data**
Next by thread:
**Re: fit plane to xz axis of data**
| |