Ein Stichwort wäre evtl. Kongruenzabbildungen, im Detail ist es aber recht simple Geometrie.
Bei beliebigen Vektorensets kann es sein dass es gar keine Lösung gibt, dürfte wohl klar sein. Kongruenz der Punkte (ohne Spiegelung) muss gewährleistet sein, aber deine Bedingungen hören sich ja exakt danach an.
In Worten:
Sieh die beiden Arrays als Polygonzüge S und D.
1. Verschiebe Polygon D so auf S, dass jeweils Punkt 0 aufeinander zu liegen kommt -> D' (jeder andere korrespondierende Punkt geht auch).
2. Der gesuchte Winkel ist der Winkel zwischen |S1-S0| und |D'1-S0| (w=acos des Dotprodukts der beiden normierten Vektoren) (statt S1 und D'1 sind auch hier wieder beliebige korrespondierende Punkte wählbar).
3. Drehe Polygon S um diesen Winkel -> S' (S' und D haben nun die gleiche Orientierung).
4. Der gesuchte Offset ist t=D0-S'0.
Soweit der (hoffentlich) anschauliche Weg. Natürlich musst du nicht jeweils alle Punkte verschieben und drehen, sondern nur 2 jeweils korrespondierende Punkte aus jedem Set (du brauchst also nichtmal 3 Punkte, höchstens dann wenn sich der Orientierungssinn ändern kann, das müsstest du aber extra abfragen).
Außerdem musst du bei Schritt 2. nicht den tatsächlichen Winkel berechnen und davon wieder eine Rotationsmatrix machen: Dotprodukt der beiden normierten Vektoren ist cos des Winkels (co=x0*y0+x1*y1), und genau dieser cos wird für die Rotationsmatrix benötigt. Der zweite benötigte Wert sin desselben Winkels ist bekanntlich um 90 Grad versetzt, also (si=x0*y1+y0*-x1), da die Senkrechte zu (x,y)=(y,-x) ist. Trigonometrische Funktionen kann man sich hier also komplett sparen.
Die 2x2-Rotationsmatrix sieht bekanntlich so aus (Orientierung spaltenweise):
co -si
si co
Den Offset aus Schritt 4. kannst du auch in eine 3x3-Matrix direkt mit reinnehmen:
co -si tx
si co ty
0 0 1
P.S. hier noch ein entsprechendes Snippet:
Code: Alles auswählen
function getTransformation(src0:Point,src1:Point,dst0:Point,dst1:Point):Matrix{
//1. D auf S verschieben
var v:Point=src0.subtract(dst0);
var dst2:Point=dst1.add(v);
//2. cos und sin des Winkels
var v0:Point=src1.subtract(src0);
var v1:Point=dst2.subtract(src0);
v0.normalize(1);
v1.normalize(1);
var dotCos=v0.x*v1.x+v0.y*v1.y;
var dotSin=v0.x*v1.y-v0.y*v1.x;
//3. S auf gleiche Orientierung wie D drehen
var rot2:Matrix=new Matrix(dotCos,dotSin,-dotSin,dotCos,0,0);
var src2:Point=rot2.transformPoint(src0);
//4. Offset
var offset2=dst0.subtract(src2);
rot2.tx=offset2.x;
rot2.ty=offset2.y;
return rot2;
}