25 m << t.m11() , t.m12() , t.m13()
26 ,t.m21() , t.m22() , t.m23()
27 ,t.m31() , t.m32() , t.m33();
33#include <config-gsl.h>
36#include <gsl/gsl_multimin.h>
43 struct YScaleStrategy {
53 struct XScaleStrategy {
64 QPointF staticPointSrc;
65 QPointF staticPointDst;
66 QPointF movingPointSrc;
67 QPointF movingPointDst;
72 template <
class Strategy>
73 double scaleError1D (
const gsl_vector * x,
void *paramsPtr)
75 double scale = gsl_vector_get(x, 0);
76 double tX = gsl_vector_get(x, 1);
77 double tY = gsl_vector_get(x, 2);
79 const Params1D *params =
static_cast<const Params1D*
>(paramsPtr);
83 Strategy::setScale(&args, scale);
87 QTransform t = m.finalTransform();
89 QPointF transformedStaticPoint = t.map(params->staticPointSrc);
90 QPointF transformedMovingPoint = t.map(params->movingPointSrc);
93 qAbs((transformedMovingPoint - params->movingPointDst).manhattanLength()) +
94 qAbs((transformedStaticPoint - params->staticPointDst).manhattanLength());
99 template <
class Strategy>
101 const QPointF &staticPointSrc,
102 const QPointF &staticPointDst,
103 const QPointF &movingPointSrc,
104 const QPointF &movingPointDst)
106 const gsl_multimin_fminimizer_type *T =
107 gsl_multimin_fminimizer_nmsimplex2;
108 gsl_multimin_fminimizer *s = 0;
110 gsl_multimin_function minex_func;
117 x = gsl_vector_alloc (3);
118 gsl_vector_set (x, 0, Strategy::getScale(args));
123 QTransform t = m.finalTransform();
130 const QPointF transformedMovingPoint = t.map(movingPointSrc);
131 const qreal initialStep = 0.1 *
kisDistance(transformedMovingPoint, movingPointDst);
134 ss = gsl_vector_alloc (3);
135 gsl_vector_set (ss, 0, 0.1);
136 gsl_vector_set (ss, 1, initialStep);
137 gsl_vector_set (ss, 2, initialStep);
141 p.staticPointSrc = staticPointSrc;
142 p.staticPointDst = staticPointDst;
143 p.movingPointSrc = movingPointSrc;
144 p.movingPointDst = movingPointDst;
149 minex_func.f = scaleError1D<Strategy>;
150 minex_func.params = (
void*)&
p;
152 s = gsl_multimin_fminimizer_alloc (T, 3);
153 gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
155 ScaleResult1D result;
156 result.scale = Strategy::getScale(args);
162 status = gsl_multimin_fminimizer_iterate(s);
167 size = gsl_multimin_fminimizer_size (s);
168 status = gsl_multimin_test_size (size, 1e-6);
175 if (status == GSL_SUCCESS && scaleError1D<Strategy>(s->x, &
p) > 0.5) {
176 status = GSL_CONTINUE;
179 if (status == GSL_SUCCESS)
186 result.scale = gsl_vector_get (s->x, 0);
187 result.transformedCenter =
188 QPointF(gsl_vector_get (s->x, 1),
189 gsl_vector_get (s->x, 2));
190 result.isValid =
true;
193 while (status == GSL_CONTINUE && iter < 10000);
197 gsl_multimin_fminimizer_free (s);
203 QPointF staticPointSrc;
204 QPointF staticPointDst;
206 QPointF movingPointSrc;
207 QPointF movingPointDst;
212 double scaleError2D (
const gsl_vector * x,
void *paramsPtr)
214 double scaleX = gsl_vector_get(x, 0);
215 double scaleY = gsl_vector_get(x, 1);
216 double tX = gsl_vector_get(x, 2);
217 double tY = gsl_vector_get(x, 3);
219 const Params2D *params =
static_cast<const Params2D*
>(paramsPtr);
228 QTransform t = m.finalTransform();
230 QPointF transformedStaticPoint = t.map(params->staticPointSrc);
231 QPointF transformedMovingPoint = t.map(params->movingPointSrc);
234 qAbs(transformedMovingPoint.x() - params->movingPointDst.x()) +
235 qAbs(transformedMovingPoint.y() - params->movingPointDst.y()) +
236 qAbs(transformedStaticPoint.x() - params->staticPointDst.x()) +
237 qAbs(transformedStaticPoint.y() - params->staticPointDst.y());
243 const QPointF &staticPointSrc,
244 const QPointF &staticPointDst,
245 const QPointF &movingPointSrc,
246 const QPointF &movingPointDst)
248 const gsl_multimin_fminimizer_type *T =
249 gsl_multimin_fminimizer_nmsimplex2;
250 gsl_multimin_fminimizer *s = 0;
252 gsl_multimin_function minex_func;
259 x = gsl_vector_alloc (4);
260 gsl_vector_set (x, 0, args.
scaleX());
261 gsl_vector_set (x, 1, args.
scaleY());
266 ss = gsl_vector_alloc (4);
267 gsl_vector_set (ss, 0, 0.1);
268 gsl_vector_set (ss, 1, 0.1);
269 gsl_vector_set (ss, 2, 10);
270 gsl_vector_set (ss, 3, 10);
274 p.staticPointSrc = staticPointSrc;
275 p.staticPointDst = staticPointDst;
276 p.movingPointSrc = movingPointSrc;
277 p.movingPointDst = movingPointDst;
282 minex_func.f = scaleError2D;
283 minex_func.params = (
void*)&
p;
285 s = gsl_multimin_fminimizer_alloc (T, 4);
286 gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
288 ScaleResult2D result;
289 result.scaleX = args.
scaleX();
290 result.scaleY = args.
scaleY();
296 status = gsl_multimin_fminimizer_iterate(s);
301 size = gsl_multimin_fminimizer_size (s);
302 status = gsl_multimin_test_size (size, 1e-6);
309 if (status == GSL_SUCCESS && scaleError2D(s->x, &
p) > 0.5) {
310 status = GSL_CONTINUE;
313 if (status == GSL_SUCCESS)
321 result.scaleX = gsl_vector_get (s->x, 0);
322 result.scaleY = gsl_vector_get (s->x, 1);
323 result.transformedCenter =
324 QPointF(gsl_vector_get (s->x, 2),
325 gsl_vector_get (s->x, 3));
326 result.isValid =
true;
329 while (status == GSL_CONTINUE && iter < 10000);
333 gsl_multimin_fminimizer_free (s);
339 const QPointF &staticPointSrc,
340 const QPointF &staticPointDst,
341 const QPointF &movingPointSrc,
342 const QPointF &movingPointDst)
361 Eigen::Matrix3d M1 = projP_t * S_t;
363 Eigen::Matrix<double, 3, 2> P_src;
364 P_src << staticPointSrc.x(), movingPointSrc.x(),
365 staticPointSrc.y(), movingPointSrc.y(),
368 P_src = BRI_t * TS_t * P_src;
370 Eigen::Matrix<double, 3, 2> P_dst;
371 P_dst << staticPointDst.x(), movingPointDst.x(),
372 staticPointDst.y(), movingPointDst.y(),
375 Eigen::Matrix<double, 4, 4>
A;
376 A << M1(0,0) * P_src(0,0), M1(0,1) * P_src(1,0), 1, 0,
377 M1(1,0) * P_src(0,0), M1(1,1) * P_src(1,0), 0, 1,
378 M1(0,0) * P_src(0,1), M1(0,1) * P_src(1,1), 1, 0,
379 M1(1,0) * P_src(0,1), M1(1,1) * P_src(1,1), 0, 1;
381 Eigen::Matrix<double, 4, 1>
B;
382 B << P_dst(0,0), P_dst(1,0), P_dst(0,1), P_dst(1,1);
385 ScaleResult2D result;
387 Eigen::Matrix<double, 4, 1>
X =
A.inverse() *
B;
391 if (result.isValid) {
392 result.scaleX =
X(0);
393 result.scaleY =
X(1);
394 result.transformedCenter.rx() =
X(2);
395 result.transformedCenter.ry() =
X(3);
402 const QPointF &staticPointSrc,
403 const QPointF &staticPointDst,
404 const QPointF &movingPointSrc,
405 const QPointF &movingPointDst)
407 return calculateScale1D<XScaleStrategy>(args,
415 const QPointF &staticPointSrc,
416 const QPointF &staticPointDst,
417 const QPointF &movingPointSrc,
418 const QPointF &movingPointDst)
420 return calculateScale1D<YScaleStrategy>(args,
436 QMessageBox::warning(qApp->activeWindow(),
437 i18nc(
"@title:window",
"Krita"),
438 i18n(
"Krita was built without the support "
439 "of GNU Scientific Library, so you cannot scale "
440 "the selection with handles. Please compile "
441 "Krita with GNU Scientific Library support, or use "
442 "options widget for editing scale values manually."));
446 const QPointF &staticPointSrc,
447 const QPointF &staticPointDst,
448 const QPointF &movingPointSrc,
449 const QPointF &movingPointDst)
461 const QPointF &staticPointSrc,
462 const QPointF &staticPointDst,
463 const QPointF &movingPointSrc,
464 const QPointF &movingPointDst)
466 return calculateScale2D(args, staticPointSrc, staticPointDst, movingPointSrc, movingPointDst);
470 const QPointF &staticPointSrc,
471 const QPointF &staticPointDst,
472 const QPointF &movingPointSrc,
473 const QPointF &movingPointDst)
484 const QPointF &staticPointSrc,
485 const QPointF &staticPointDst,
486 const QPointF &movingPointSrc,
487 const QPointF &movingPointDst)
static bool qFuzzyIsNull(half h)
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
ScaleResult2D calculateScale2DAffine(const ToolTransformArgs &args, const QPointF &staticPointSrc, const QPointF &staticPointDst, const QPointF &movingPointSrc, const QPointF &movingPointDst)
ScaleResult2D calculateScale2D(const ToolTransformArgs &args, const QPointF &staticPointSrc, const QPointF &staticPointDst, const QPointF &movingPointSrc, const QPointF &movingPointDst)
ScaleResult1D calculateScaleX(const ToolTransformArgs &args, const QPointF &staticPointSrc, const QPointF &staticPointDst, const QPointF &movingPointSrc, const QPointF &movingPointDst)
ScaleResult1D calculateScaleY(const ToolTransformArgs &args, const QPointF &staticPointSrc, const QPointF &staticPointDst, const QPointF &movingPointSrc, const QPointF &movingPointDst)
Eigen::Matrix3d fromQTransformStraight(const QTransform &t)
int size(const Forest< T > &forest)
QPointF transformedCenter
QPointF transformedCenter