diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html
index 19032c3..daa52fd 100644
--- a/plugin/contents/ui/dancer.html
+++ b/plugin/contents/ui/dancer.html
@@ -1470,20 +1470,35 @@ function constellationArtTransform(source, target) {
.map(v => v / source.length);
const qc = target.reduce((p, v) => [p[0] + v.x, p[1] + v.y], [0, 0])
.map(v => v / target.length);
- let dot = 0, cross = 0, energy = 0;
+ let dot = 0, cross = 0, mirrorA = 0, mirrorB = 0, energy = 0;
for (let i = 0; i < source.length; i++) {
const px = source[i][0] - pc[0], py = source[i][1] - pc[1];
const qx = target[i].x - qc[0], qy = target[i].y - qc[1];
dot += px * qx + py * qy;
cross += px * qy - py * qx;
+ mirrorA += px * qx - py * qy;
+ mirrorB += py * qx + px * qy;
energy += px * px + py * py;
}
if (energy < 1e-6) return null;
- const a = dot / energy;
- const b = cross / energy;
- const e = qc[0] - a * pc[0] + b * pc[1];
- const f = qc[1] - b * pc[0] - a * pc[1];
- return [a, b, -b, a, e, f];
+ const candidate = (a, b, c, d) => {
+ const e = qc[0] - a * pc[0] - c * pc[1];
+ const f = qc[1] - b * pc[0] - d * pc[1];
+ const matrix = [a, b, c, d, e, f];
+ const error = source.reduce((sum, p, i) => {
+ const dx = a * p[0] + c * p[1] + e - target[i].x;
+ const dy = b * p[0] + d * p[1] + f - target[i].y;
+ return sum + dx * dx + dy * dy;
+ }, 0);
+ return { matrix, error };
+ };
+ const rotate = candidate(dot / energy, cross / energy,
+ -cross / energy, dot / energy);
+ /* Ao observar a esfera por dentro, várias cartas precisam inverter a
+ orientação leste/oeste. Esta alternativa inclui a reflexão sem shear. */
+ const reflect = candidate(mirrorA / energy, mirrorB / energy,
+ mirrorB / energy, -mirrorA / energy);
+ return (reflect.error < rotate.error ? reflect : rotate).matrix;
}
function drawConstellationArt(c, constellation, lst, W, horizonPx, previewProjector) {