mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
201 lines
6.2 KiB
C++
201 lines
6.2 KiB
C++
#include "radial.h"
|
|
|
|
Pointf3 RadialBasisTransform::Transform(Pointf3 pt) const
|
|
{
|
|
Pointf3 out(0, 0, 0); // = pt * affine;
|
|
for(int i = 0; i < anchor.GetCount(); i++)
|
|
out += radial[i] * exp(-Squared(pt - anchor[i]) / sigma2[i]);
|
|
return out;
|
|
}
|
|
|
|
Color RadialBasisTransform::Transform(Color c) const
|
|
{
|
|
if(IsNull(c)) return c;
|
|
Pointf3 out = Transform(Pointf3(c.GetR(), c.GetG(), c.GetB()));
|
|
return Color(fround(minmax(out.x, 0.0, 255.0)), fround(minmax(out.y, 0.0, 255.0)), fround(minmax(out.z, 0.0, 255.0)));
|
|
}
|
|
|
|
/*
|
|
double RadialBasisTransform::MinSquared(Pointf3 pt) const
|
|
{
|
|
// if(IsAffine())
|
|
// return Null;
|
|
double d = Squared(pt - anchor[0]);
|
|
for(int i = 1; i < anchor.GetCount(); i++)
|
|
d = min(d, Squared(pt - anchor[i]));
|
|
return d;
|
|
}
|
|
*/
|
|
|
|
RadialBasisTransform CalcTransform(const Array<Pointf3>& source, const Array<Pointf3>& target /*, const Vector<double>& rad*/)
|
|
{
|
|
int n = source.GetCount();
|
|
ASSERT(n == target.GetCount());
|
|
|
|
RadialBasisTransform rbt;
|
|
|
|
/*
|
|
switch(n) {
|
|
case 0: return rbt;
|
|
case 1: rbt.affine.a = target[0] - source[0]; return rbt;
|
|
case 2: rbt.affine = Matrixf3Affine(source[0], target[0], source[1], target[1]); return rbt;
|
|
case 3: rbt.affine = Matrixf3Affine(source[0], target[0], source[1], target[1], source[2], target[2]); return rbt;
|
|
case 4: rbt.affine = Matrixf3Affine(source[0], target[0], source[1], target[1], source[2], target[2], source[3], target[3]); return rbt;
|
|
}
|
|
*/
|
|
|
|
enum {
|
|
// AXX, AXY, AXZ, AYX, AYY, AYZ, AZX, AZY, AZZ, BX, BY, BZ,
|
|
RX, RY, RZ
|
|
};
|
|
LinearSolver solver(/*12 +*/ 3 * n);
|
|
double xmin, xmax, ymin, ymax, zmin, zmax;
|
|
xmin = ymin = zmin = +1e100;
|
|
xmax = ymax = zmax = -1e100;
|
|
int i;
|
|
for(i = 0; i < n; i++) {
|
|
Pointf3 src = source[i];
|
|
if(src.x < xmin) xmin = src.x;
|
|
if(src.x > xmax) xmax = src.x;
|
|
if(src.y < ymin) ymin = src.y;
|
|
if(src.y > ymax) ymax = src.y;
|
|
if(src.z < zmin) zmin = src.z;
|
|
if(src.z > zmax) zmax = src.z;
|
|
}
|
|
double sigma2 = pow((xmax - xmin) * (ymax - ymin) * (zmax - zmin), 2.0 / 3.0) / n;
|
|
|
|
for(i = 0; i < n; i++) {
|
|
ASSERT(!IsNull(source[i]) && !IsNull(target[i]));
|
|
Pointf3 si = source[i], ti = target[i];
|
|
/*
|
|
solver(AXX, AXX) += si.x * si.x;
|
|
solver(AXX, AYX) += si.y * si.x;
|
|
solver(AXX, AZX) += si.z * si.x;
|
|
solver(AXX, BX) += 1.0 * si.x;
|
|
solver.Right(AXX) += ti.x * si.x;
|
|
|
|
solver(AYX, AXX) += si.x * si.y;
|
|
solver(AYX, AYX) += si.y * si.y;
|
|
solver(AYX, AZX) += si.z * si.y;
|
|
solver(AYX, BX) += 1.0 * si.y;
|
|
solver.Right(AYX) += ti.x * si.y;
|
|
|
|
solver(AZX, AXX) += si.x * si.z;
|
|
solver(AZX, AYX) += si.y * si.z;
|
|
solver(AZX, AZX) += si.z * si.z;
|
|
solver(AZX, BX) += 1.0 * si.z;
|
|
solver.Right(AZX) += ti.x * si.z;
|
|
|
|
solver(BX, AXX) += si.x;
|
|
solver(BX, AYX) += si.y;
|
|
solver(BX, AZX) += si.z;
|
|
solver(BX, BX) += 1;
|
|
solver.Right(BX) += ti.x;
|
|
|
|
solver(AXY, AXY) += si.x * si.x;
|
|
solver(AXY, AYY) += si.y * si.x;
|
|
solver(AXY, AZY) += si.z * si.x;
|
|
solver(AXY, BY) += 1 * si.x;
|
|
solver.Right(AXY) += ti.y * si.x;
|
|
|
|
solver(AYY, AXY) += si.x * si.y;
|
|
solver(AYY, AYY) += si.y * si.y;
|
|
solver(AYY, AZY) += si.z * si.y;
|
|
solver(AYY, BY) += 1 * si.y;
|
|
solver.Right(AYY) += ti.y * si.y;
|
|
|
|
solver(AZY, AXY) += si.x * si.z;
|
|
solver(AZY, AYY) += si.y * si.z;
|
|
solver(AZY, AZY) += si.z * si.z;
|
|
solver(AZY, BY) += 1 * si.z;
|
|
solver.Right(AZY) += ti.y * si.z;
|
|
|
|
solver(BY, AXY) += si.x;
|
|
solver(BY, AYY) += si.y;
|
|
solver(BY, AZY) += si.z;
|
|
solver(BY, BY) += 1;
|
|
solver.Right(BY) += ti.y;
|
|
|
|
solver(AXZ, AXZ) += si.x * si.x;
|
|
solver(AXZ, AYZ) += si.y * si.x;
|
|
solver(AXZ, AZZ) += si.z * si.x;
|
|
solver(AXZ, BZ) += 1 * si.x;
|
|
solver.Right(AXZ) += ti.z * si.x;
|
|
|
|
solver(AYZ, AXZ) += si.x * si.y;
|
|
solver(AYZ, AYZ) += si.y * si.y;
|
|
solver(AYZ, AZZ) += si.z * si.y;
|
|
solver(AYZ, BZ) += 1 * si.y;
|
|
solver.Right(AYZ) += ti.z * si.y;
|
|
|
|
solver(AZZ, AXZ) += si.x * si.z;
|
|
solver(AZZ, AYZ) += si.y * si.z;
|
|
solver(AZZ, AZZ) += si.z * si.z;
|
|
solver(AZZ, BZ) += 1 * si.z;
|
|
solver.Right(AZZ) += ti.z * si.z;
|
|
|
|
solver(BZ, AXZ) += si.x;
|
|
solver(BZ, AYZ) += si.y;
|
|
solver(BZ, AZZ) += si.z;
|
|
solver(BZ, BZ) += 1;
|
|
solver.Right(BZ) += ti.z;
|
|
*/
|
|
int rx = RX + 3 * i, ry = RY + 3 * i, rz = RZ + 3 * i;
|
|
// solver(rx, AXX) = solver(ry, AXY) = solver(rz, AXZ) = si.x;
|
|
// solver(rx, AYX) = solver(ry, AYY) = solver(rz, AYZ) = si.y;
|
|
// solver(rx, AZX) = solver(ry, AZY) = solver(rz, AZZ) = si.z;
|
|
// solver(rx, BX) = solver(ry, BY) = solver(rz, BZ) = 1;
|
|
solver.Right(rx) = ti.x;
|
|
solver.Right(ry) = ti.y;
|
|
solver.Right(rz) = ti.z;
|
|
for(int r = 0; r < n; r++) {
|
|
// double s2 = rad[r];
|
|
// s2 = (s2 ? s2 * s2 : sigma2);
|
|
solver(rx, RX + 3 * r) = solver(ry, RY + 3 * r) = solver(rz, RZ + 3 * r)
|
|
= exp(-Squared(source[r] - si) / sigma2);
|
|
}
|
|
}
|
|
|
|
Vector<double> out = solver.Solve();
|
|
/*
|
|
rbt.affine.x.x = Nvl(out[AXX], 1.0);
|
|
rbt.affine.x.y = Nvl(out[AXY], 0.0);
|
|
rbt.affine.x.z = Nvl(out[AXZ], 0.0);
|
|
rbt.affine.y.x = Nvl(out[AYX], 0.0);
|
|
rbt.affine.y.y = Nvl(out[AYY], 1.0);
|
|
rbt.affine.y.z = Nvl(out[AYZ], 0.0);
|
|
rbt.affine.z.x = Nvl(out[AZX], 0.0);
|
|
rbt.affine.z.y = Nvl(out[AZY], 0.0);
|
|
rbt.affine.z.z = Nvl(out[AZZ], 1.0);
|
|
rbt.affine.a.x = Nvl(out[BX], 0.0);
|
|
rbt.affine.a.y = Nvl(out[BY], 0.0);
|
|
rbt.affine.a.z = Nvl(out[BZ], 0.0);
|
|
*/
|
|
for(i = 0; i < n; i++) {
|
|
Pointf3 a(out[RX + 3 * i], out[RY + 3 * i], out[RZ + 3 * i]);
|
|
if(!IsNull(a.x) && !IsNull(a.y) && !IsNull(a.z)
|
|
&& (fabs(a.x) >= 1 || fabs(a.y) >= 1 || fabs(a.z) >= 1)) {
|
|
rbt.radial.Add(a);
|
|
// double s2 = rad[i];
|
|
rbt.sigma2.Add(sigma2); //s2 ? s2 * s2 : sigma2);
|
|
rbt.anchor.Add(source[i]);
|
|
}
|
|
}
|
|
|
|
return rbt;
|
|
}
|
|
|
|
RadialBasisTransform CalcTransform(const Vector<Color>& source, const Vector<Color>& target)
|
|
{
|
|
int n = source.GetCount();
|
|
ASSERT(n == target.GetCount());
|
|
Array<Pointf3> spt, dpt;
|
|
spt.Reserve(n);
|
|
dpt.Reserve(n);
|
|
for(int i = 0; i < n; i++)
|
|
if(!IsNull(source[i]) && !IsNull(target[i])) {
|
|
spt.Add(Pointf3(source[i].GetR(), source[i].GetG(), source[i].GetB()));
|
|
dpt.Add(Pointf3(target[i].GetR(), target[i].GetG(), target[i].GetB()));
|
|
}
|
|
return CalcTransform(spt, dpt);
|
|
}
|