29 namespace lsst {
namespace meas {
namespace astrom {
43 poly._xCoeffs(1, 0) += 1;
44 poly._yCoeffs(0, 1) += 1;
49 afw::geom::AffineTransform(afw::geom::Point2D() - other.
getPixelOrigin())
58 poly._xCoeffs(1, 0) += 1;
59 poly._yCoeffs(0, 1) += 1;
61 afw::geom::AffineTransform(afw::geom::Extent2D(other.
getPixelOrigin())),
77 pex::exceptions::LengthError,
78 "PolynomialTransform order must be >= 0"
82 _xCoeffs.reset(ndarray::Array<double,2,2>(ndarray::allocate(order + 1, order + 1)));
83 _yCoeffs.reset(ndarray::Array<double,2,2>(ndarray::allocate(order + 1, order + 1)));
86 _u = Eigen::VectorXd(order + 1);
87 _v = Eigen::VectorXd(order + 1);
91 ndarray::Array<double const,2,2>
const & xCoeffs,
92 ndarray::Array<double const,2,2>
const & yCoeffs
93 ) : _xCoeffs(ndarray::copy(xCoeffs)),
94 _yCoeffs(ndarray::copy(yCoeffs)),
98 if (xCoeffs.getShape() != yCoeffs.getShape()) {
100 pex::exceptions::LengthError,
102 "X and Y coefficient matrices must have the same shape: "
103 " (%d,%d) != (%d,%d)"
104 ) % xCoeffs.getSize<0>() % xCoeffs.getSize<1>()
105 % yCoeffs.getSize<0>() % yCoeffs.getSize<1>()
109 if (_xCoeffs.cols() != _xCoeffs.rows()) {
111 pex::exceptions::LengthError,
113 "Coefficient matrices must be triangular, not trapezoidal: "
115 ) % _xCoeffs.rows() % _xCoeffs.cols()
122 _xCoeffs(ndarray::copy(other.getXCoeffs())),
123 _yCoeffs(ndarray::copy(other.getYCoeffs())),
138 if (&other !=
this) {
146 if (&other !=
this) {
153 _xCoeffs.swap(other._xCoeffs);
154 _yCoeffs.swap(other._yCoeffs);
160 double xu = 0.0, xv = 0.0, yu = 0.0, yv = 0.0, x = 0.0, y = 0.0;
164 for (
int p = 0; p <= order; ++p) {
165 for (
int q = 0; q <= order; ++q) {
167 xu += _xCoeffs(p, q) * p * _u[p - 1] * _v[q];
168 yu += _yCoeffs(p, q) * p * _u[p - 1] * _v[q];
171 xv += _xCoeffs(p, q) * q * _u[p] * _v[q - 1];
172 yv += _yCoeffs(p, q) * q * _u[p] * _v[q - 1];
174 x += _xCoeffs(p, q) * _u[p] * _v[q];
175 y += _yCoeffs(p, q) * _u[p] * _v[q];
178 afw::geom::LinearTransform linear;
179 linear.getMatrix()(0, 0) = xu;
180 linear.getMatrix()(0, 1) = xv;
181 linear.getMatrix()(1, 0) = yu;
182 linear.getMatrix()(1, 1) = yv;
183 afw::geom::Point2D origin(x, y);
184 return afw::geom::AffineTransform(linear, origin - linear(in));
193 for (
int p = 0; p <= order; ++p) {
194 for (
int q = 0; q <= order; ++q) {
195 x += _xCoeffs(p, q) * _u[p] * _v[q];
196 y += _yCoeffs(p, q) * _u[p] * _v[q];
199 return afw::geom::Point2D(x, y);
209 afw::geom::AffineTransform(afw::geom::Point2D(0, 0) - sipForward.
getPixelOrigin()),
210 afw::geom::AffineTransform(sipForward.
getCDMatrix())
214 result._poly._xCoeffs(1, 0) += 1;
215 result._poly._yCoeffs(0, 1) += 1;
222 afw::geom::AffineTransform(sipReverse._cdInverse),
223 afw::geom::AffineTransform(afw::geom::Extent2D(sipReverse.
getPixelOrigin()))
225 result._poly._xCoeffs(1, 0) += 1;
226 result._poly._yCoeffs(0, 1) += 1;
232 afw::geom::AffineTransform
const & inputScaling,
233 afw::geom::AffineTransform
const & outputScalingInverse
236 _inputScaling(inputScaling),
237 _outputScalingInverse(outputScalingInverse)
241 _poly.
swap(other._poly);
242 std::swap(_inputScaling, other._inputScaling);
243 std::swap(_outputScalingInverse, other._outputScalingInverse);
247 return _outputScalingInverse*_poly.
linearize(_inputScaling(in))*_inputScaling;
251 return _outputScalingInverse(_poly(_inputScaling(in)));
255 typedef afw::geom::AffineTransform AT;
257 result._xCoeffs = t2._xCoeffs*t1[AT::XX] + t2._yCoeffs*t1[AT::XY];
258 result._yCoeffs = t2._xCoeffs*t1[AT::YX] + t2._yCoeffs*t1[AT::YY];
259 result._xCoeffs(0, 0) += t1[AT::X];
260 result._yCoeffs(0, 0) += t1[AT::Y];
265 typedef afw::geom::AffineTransform AT;
269 t1a._xCoeffs(0, 0) = t1._xCoeffs(0, 0);
270 t1a._yCoeffs(0, 0) = t1._yCoeffs(0, 0);
282 for (
int p = 0; p <= order; ++p) {
283 for (
int m = 0; m <= p; ++m) {
284 for (
int j = 0; j <= m; ++j) {
285 for (
int q = 0; p + q <= order; ++q) {
286 for (
int n = 0; n <= q; ++n) {
287 for (
int k = 0; k <= n; ++k) {
288 double z = binomial(p,m) * t2u[p-m] * binomial(m,j) * t2uu[j] * t2uv[m-j] *
289 binomial(q,n) * t2v[q-n] * binomial(n,k) * t2vu[k] * t2vv[n-k];
290 result._xCoeffs(j + k, m + n - j - k) += t1._xCoeffs(p, q) * z;
291 result._yCoeffs(j + k, m + n - j - k) += t1._yCoeffs(p, q) * z;
A class that computes binomial coefficients up to a certain power.
PolynomialTransform compose(afw::geom::AffineTransform const &t1, PolynomialTransform const &t2)
Return a PolynomialTransform that is equivalent to the composition t1(t2())
void computePowers(Eigen::VectorXd &r, double x)
Fill an array with integer powers of x, so .