I have the following set of 2d data points:
data1=
{
{21.557, 801.607}, {5.84689, 800.425}, {50.9284, 770.49},
{46.4516, 750.192}, {32.9808, 671.931}, {48.8067, 673.198},
{3.59394, 671.167}, {18.1513, 671.949}, {64.1628, 670.801},
{13.1805, 652.588}, {55.6619, 651.298}, {26.9262, 650.35},
{41.4876, 650.752}, {5.45129, 635.602}, {20.3858, 633.391},
{64.1931, 632.506}, {33.9168, 631.006}, {58.7559, 613.401},
{36.0045, 612.007}, {23.5348, 608.289}, {54.6781, 598.251},
{26.4914, 548.723}, {65.0549, 531.442}, {82.9996, 514.631},
{74.4132, 479.425}, {58.3295, 458.015}, {27.1816, 413.334}
}
I want to apply ScalingTransform
, TranslationTransform
and RotationTransform
to find the best fit to transform data1
into data2
, whereby:
data2=
{
{1530.03, 790.2}, {1514.13, 789.}, {1559.17, 758.9},
{1554.5, 738.5}, {1540.5, 660.237}, {1556.15, 661.154},
{1511.34, 659.395}, {1525.63, 660.167}, {1572.13, 658.656},
{1520.66, 640.844}, {1562.55, 639.132}, {1533.79, 638.607},
{1548.37, 638.933}, {1512.62, 623.985}, {1526.88, 621.69},
{1571.44, 620.556}, {1540.44, 618.794}, {1565.69, 601.532},
{1543.06, 600.093}, {1530.22, 596.423}, {1560.9, 586.053},
{1532.93, 536.587}, {1571.9, 519.25}, {1590.15, 501.882},
{1580.39, 467.111}, {1564.73, 445.615}, {1532.8, 400.935}
}
The corresponding points of data1
that should be transformed into data2
are already sorted and at the same position of the lists.
Here are plots of the two data sets:
plot1 = ListPlot[data1, PlotRange -> {{1, 91}, {300, 900}},
PlotStyle -> Red, Frame -> True,
FrameLabel -> {{"y", ""}, {"x", "data1"}},
BaseStyle -> {FontWeight -> "Bold", FontSize -> 15,
FontFamily -> "Calibri"}, ImageSize -> Large];
plot2 = ListPlot[data2, PlotRange -> {{1510, 1600}, {300, 900}},
PlotStyle -> Blue, Frame -> True,
FrameLabel -> {{"y", ""}, {"x", "data2"}},
BaseStyle -> {FontWeight -> "Bold", FontSize -> 15,
FontFamily -> "Calibri"}, ImageSize -> Large];
GraphicsColumn[{plot1, plot2}, ImageSize -> Large,
Spacings -> {{0, 0}, {0, 50}}]
I use the following naming:
s = ScalingTransform[{sx, sy}, {psx, psy}];
t = TranslationTransform[{vecx, vecy}];
r = RotationTransform[theta, {prx, pry}];
The combined transformation for each point {x, y}
of data1
is:
combinedTransformation = s.t.r;
and finally :
combinedTransformation[{x, y}] =
{sx (prx (-Cos[theta]) + prx + pry Sin[theta]) + psx (-sx) + psx +
sx x Cos[theta] - sx y Sin[theta] + sx vecx,
sy (-(prx Sin[theta]) + pry (-Cos[theta]) + pry) + psy (-sy) + psy +
sy x Sin[theta] + sy y Cos[theta] + sy vecy}
The fitting parameters are: sx, sy, vecx, vecy, theta
.
The scaling is centered at the point {psx, psy}
and the 2d rotation is around the point {prx, pry}
.
I would set {psx, psy} = {1, 1}
and {prx, pry} = {1, 1}
.
How can I transform data1
best into data2
and how can I obtain the fitting paramaters and their errors?
ADDENDUM:
I already tried the same as what is proposed below by Ulrich Neumann and Carl Lange.
The problem with
FindGeometricTransform
is, it is not described how the error is obtained - I need this for a paper. See this question.Second
FindGeometricTransform
does not give me the rotation angle and scaling factor in x and y separately, which are not exactly the same.FindGeometricTransform
shows only the transformation function (or matrix) which is not enough for me.
FindGeometricTransform
. It 's not necessary to require ascaling point
and/or arotationpoint
, that is the task ogf the fitting procedure. $\endgroup$data1Transformed = transform@data1; data2Nearest = Flatten[Nearest[data2, #] & /@ data1Transformed, 1]; Mean[Norm[#] & /@ (data1Transformed - data2)]
might do it. $\endgroup$