|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tinbetween.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcurves.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tcolorstyles.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tregion.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tmathutil.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tstrokeutil.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
#include <utility></utility>
|
|
Toshihiro Shimizu |
890ddd |
#include <limits></limits>
|
|
Toshihiro Shimizu |
890ddd |
#include <list></list>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "../tvectorimage/tvectorimageP.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//#include "tdebugmessage.h"
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static double average(std::vector<double> &values, double range = 2.5) {</double>
|
|
Shinya Kitaoka |
120a6e |
UINT size = values.size();
|
|
Shinya Kitaoka |
120a6e |
if (size == 0) return std::numeric_limits<double>::signaling_NaN();</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (size == 1) return values[0];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double sum = 0;
|
|
Shinya Kitaoka |
120a6e |
UINT j = 0;
|
|
Shinya Kitaoka |
120a6e |
for (; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
sum += values[j];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double average = sum / size;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double variance = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
variance += (average - values[j]) * (average - values[j]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
variance /= size;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double err;
|
|
Shinya Kitaoka |
120a6e |
int acceptedNum = 0;
|
|
Shinya Kitaoka |
120a6e |
sum = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
err = values[j] - average;
|
|
Shinya Kitaoka |
120a6e |
err *= err;
|
|
Shinya Kitaoka |
120a6e |
if (err <= range * variance) {
|
|
Shinya Kitaoka |
120a6e |
sum += values[j];
|
|
Shinya Kitaoka |
120a6e |
acceptedNum++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(acceptedNum > 0);
|
|
Shinya Kitaoka |
120a6e |
return (acceptedNum > 0) ? sum / (double)acceptedNum : average;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static double weightedAverage(std::vector<double> &values,</double>
|
|
shun-iwasawa |
27b0cf |
std::vector<double> &weights,</double>
|
|
shun-iwasawa |
27b0cf |
double range = 2.5) {
|
|
Shinya Kitaoka |
120a6e |
UINT size = values.size();
|
|
Shinya Kitaoka |
120a6e |
if (size == 0) return std::numeric_limits<double>::signaling_NaN();</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double sum = 0;
|
|
Shinya Kitaoka |
120a6e |
double totalWeight = 0;
|
|
Shinya Kitaoka |
120a6e |
UINT j = 0;
|
|
Shinya Kitaoka |
120a6e |
for (; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
sum += weights[j] * values[j];
|
|
Shinya Kitaoka |
120a6e |
totalWeight += weights[j];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(totalWeight > 0);
|
|
Shinya Kitaoka |
120a6e |
if (totalWeight == 0) return std::numeric_limits<double>::signaling_NaN();</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double average = sum / totalWeight;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double variance = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
variance += weights[j] * (average - values[j]) * (average - values[j]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
variance /= totalWeight;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double err;
|
|
Shinya Kitaoka |
120a6e |
totalWeight = 0;
|
|
Shinya Kitaoka |
120a6e |
sum = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
err = values[j] - average;
|
|
Shinya Kitaoka |
120a6e |
err *= err;
|
|
Shinya Kitaoka |
120a6e |
if (err <= range * variance) {
|
|
Shinya Kitaoka |
120a6e |
sum += weights[j] * values[j];
|
|
Shinya Kitaoka |
120a6e |
totalWeight += weights[j];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(totalWeight > 0);
|
|
Shinya Kitaoka |
120a6e |
return (totalWeight != 0) ? sum / totalWeight : average;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline UINT angleNumber(const std::vector<std::pair<int, double="">> &corners,</std::pair<int,>
|
|
Shinya Kitaoka |
120a6e |
double angle) {
|
|
Shinya Kitaoka |
120a6e |
UINT count = 0;
|
|
Shinya Kitaoka |
120a6e |
UINT size = corners.size();
|
|
Shinya Kitaoka |
120a6e |
for (UINT j = 0; j < size; j++)
|
|
Shinya Kitaoka |
120a6e |
if (corners[j].second >= angle) count++;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return count;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline bool isTooComplex(UINT n1, UINT n2, UINT maxSubsetNumber = 100) {
|
|
Shinya Kitaoka |
120a6e |
UINT n, r;
|
|
Shinya Kitaoka |
120a6e |
if (n1 > n2) {
|
|
Shinya Kitaoka |
120a6e |
n = n1;
|
|
Shinya Kitaoka |
120a6e |
r = n2;
|
|
Shinya Kitaoka |
120a6e |
} else if (n1 < n2) {
|
|
Shinya Kitaoka |
120a6e |
n = n2;
|
|
Shinya Kitaoka |
120a6e |
r = n1;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
assert(!"equal angle number");
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (n - r < r) r = n - r;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
n*(n-1)* ...(n-r+1) < n^r that must be <= 2^(num bits of UINT)-1
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
s:=sizeof(UINT)*8
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if
|
|
Shinya Kitaoka |
120a6e |
n <= 2^( (s-1)/r) =>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
log n <= (s-1)/r (the base of log is 2) =>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
r*log n <= s-1 =>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
log n^r <= log 2^(s-1) =>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
n^r <= 2^(s-1) < (2^s)-1
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const UINT one = 1;
|
|
Shinya Kitaoka |
120a6e |
if (n > (one << ((sizeof(UINT) * 8 - 1) / r))) return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
UINT product1 = n; // product1 = n*(n-1)* ...(n-r+1)
|
|
Shinya Kitaoka |
120a6e |
for (UINT i = 1; i < r; i++) product1 *= --n;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
UINT rFact = r;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (r > 1) rFact *= --r;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return (product1 / rFact > maxSubsetNumber);
|
|
Shinya Kitaoka |
120a6e |
// product1/rFact is number of combination
|
|
Shinya Kitaoka |
120a6e |
// ( n )
|
|
Shinya Kitaoka |
120a6e |
// ( r )
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void eraseSmallAngles(std::vector<std::pair<int, double="">> &corners,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
double angle) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::pair<int, double="">>::iterator it = corners.begin();</std::pair<int,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (it != corners.end()) {
|
|
Shinya Kitaoka |
120a6e |
if ((*it).second < angle)
|
|
Shinya Kitaoka |
120a6e |
it = corners.erase(it);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
++it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
// output:
|
|
Shinya Kitaoka |
120a6e |
// min is the minimum angle greater or equal to minDegree (i.e the minimum angle
|
|
Shinya Kitaoka |
120a6e |
// of the corners)
|
|
Toshihiro Shimizu |
890ddd |
// max is tha maximum angle greater or equal to minDegree
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void detectCorners(const TStroke *stroke, double minDegree,
|
|
shun-iwasawa |
27b0cf |
std::vector<std::pair<int, double="">> &corners,</std::pair<int,>
|
|
shun-iwasawa |
27b0cf |
double &min, double &max) {
|
|
Shinya Kitaoka |
120a6e |
const double minSin = fabs(sin(minDegree * M_PI_180));
|
|
Shinya Kitaoka |
120a6e |
double angle, vectorialProduct, metaCornerLen, partialLen;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT quadCount1 = stroke->getChunkCount();
|
|
Shinya Kitaoka |
120a6e |
TPointD speed1, speed2;
|
|
Shinya Kitaoka |
120a6e |
int j;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD tan1, tan2;
|
|
Shinya Kitaoka |
120a6e |
min = 180;
|
|
Shinya Kitaoka |
120a6e |
max = minDegree;
|
|
Shinya Kitaoka |
120a6e |
for (j = 1; j < (int)quadCount1; j++) {
|
|
Shinya Kitaoka |
120a6e |
speed1 = stroke->getChunk(j - 1)->getSpeed(1);
|
|
Shinya Kitaoka |
120a6e |
speed2 = stroke->getChunk(j)->getSpeed(0);
|
|
Shinya Kitaoka |
120a6e |
if (!(speed1 == TPointD() || speed2 == TPointD())) {
|
|
Shinya Kitaoka |
120a6e |
tan1 = normalize(speed1);
|
|
Shinya Kitaoka |
120a6e |
tan2 = normalize(speed2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
vectorialProduct = fabs(cross(tan1, tan2));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (tan1 * tan2 < 0) {
|
|
Shinya Kitaoka |
120a6e |
angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI;
|
|
Shinya Kitaoka |
120a6e |
corners.push_back(std::make_pair(j, angle));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
//------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (min > angle) min = angle;
|
|
Shinya Kitaoka |
120a6e |
if (max < angle) max = angle;
|
|
Shinya Kitaoka |
120a6e |
} else if (vectorialProduct >= minSin) {
|
|
Shinya Kitaoka |
120a6e |
angle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI;
|
|
Shinya Kitaoka |
120a6e |
corners.push_back(std::make_pair(j, angle));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
//------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (min > angle) min = angle;
|
|
Shinya Kitaoka |
120a6e |
if (max < angle) max = angle;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const double ratioLen = 2.5;
|
|
Shinya Kitaoka |
120a6e |
const double ratioAngle = 0.2;
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::pair<int, double="">>::iterator it = corners.begin();</std::pair<int,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 1; j < (int)quadCount1;
|
|
Shinya Kitaoka |
120a6e |
j++) //"meta angoli" ( meta perche' derivabili)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (it != corners.end() && j == (*it).first) {
|
|
Shinya Kitaoka |
120a6e |
++it;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (j - 2 >= 0 && (corners.empty() || it == corners.begin() ||
|
|
Shinya Kitaoka |
120a6e |
j - 1 != (*(it - 1)).first) &&
|
|
Shinya Kitaoka |
120a6e |
j + 1 < (int)quadCount1 &&
|
|
Shinya Kitaoka |
120a6e |
(corners.empty() || it == corners.end() || j + 1 != (*it).first)) {
|
|
Shinya Kitaoka |
120a6e |
speed1 = stroke->getChunk(j - 2)->getSpeed(1);
|
|
Shinya Kitaoka |
120a6e |
speed2 = stroke->getChunk(j + 1)->getSpeed(0);
|
|
Shinya Kitaoka |
120a6e |
if (!(speed1 == TPointD() || speed2 == TPointD())) {
|
|
Shinya Kitaoka |
120a6e |
tan1 = normalize(speed1);
|
|
Shinya Kitaoka |
120a6e |
tan2 = normalize(speed2);
|
|
Shinya Kitaoka |
120a6e |
vectorialProduct = fabs(cross(tan1, tan2));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (tan1 * tan2 < 0) {
|
|
Shinya Kitaoka |
120a6e |
angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
metaCornerLen = ratioLen * (stroke->getChunk(j - 1)->getLength() +
|
|
Shinya Kitaoka |
120a6e |
stroke->getChunk(j)->getLength());
|
|
Shinya Kitaoka |
120a6e |
partialLen = 0;
|
|
Shinya Kitaoka |
120a6e |
bool goodAngle = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int i = j - 3;
|
|
Shinya Kitaoka |
120a6e |
i >= 0 && (corners.empty() || it == corners.begin() ||
|
|
Shinya Kitaoka |
120a6e |
i + 1 != (*(it - 1)).first);
|
|
Shinya Kitaoka |
120a6e |
i--) {
|
|
Shinya Kitaoka |
120a6e |
tan1 = stroke->getChunk(i)->getSpeed(1);
|
|
Shinya Kitaoka |
120a6e |
if (tan1 == TPointD()) continue;
|
|
Shinya Kitaoka |
120a6e |
tan1 = normalize(tan1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tan2 = stroke->getChunk(i + 1)->getSpeed(1);
|
|
Shinya Kitaoka |
120a6e |
if (tan2 == TPointD()) continue;
|
|
Shinya Kitaoka |
120a6e |
tan2 = normalize(tan2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
vectorialProduct = fabs(cross(tan1, tan2));
|
|
Shinya Kitaoka |
120a6e |
double nearAngle =
|
|
Shinya Kitaoka |
120a6e |
asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI;
|
|
Shinya Kitaoka |
120a6e |
if (tan1 * tan2 < 0) nearAngle = 180 - nearAngle;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (nearAngle > ratioAngle * angle) break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
partialLen += stroke->getChunk(i)->getLength();
|
|
Shinya Kitaoka |
120a6e |
if (partialLen > metaCornerLen) {
|
|
Shinya Kitaoka |
120a6e |
goodAngle = true;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (goodAngle) {
|
|
Shinya Kitaoka |
120a6e |
partialLen = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int i = j + 2; i + 1 < (int)quadCount1 &&
|
|
Shinya Kitaoka |
120a6e |
(corners.empty() || it == corners.end() ||
|
|
Shinya Kitaoka |
120a6e |
i + 1 != (*it).first);
|
|
Shinya Kitaoka |
120a6e |
i++) {
|
|
Shinya Kitaoka |
120a6e |
tan1 = stroke->getChunk(i)->getSpeed(0);
|
|
Shinya Kitaoka |
120a6e |
if (tan1 == TPointD()) continue;
|
|
Shinya Kitaoka |
120a6e |
tan1 = normalize(tan1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tan2 = stroke->getChunk(i + 1)->getSpeed(0);
|
|
Shinya Kitaoka |
120a6e |
if (tan2 == TPointD()) continue;
|
|
Shinya Kitaoka |
120a6e |
tan2 = normalize(tan2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
vectorialProduct = fabs(cross(tan1, tan2));
|
|
Shinya Kitaoka |
120a6e |
double nearAngle =
|
|
Shinya Kitaoka |
120a6e |
asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI;
|
|
Shinya Kitaoka |
120a6e |
if (tan1 * tan2 < 0) nearAngle = 180 - nearAngle;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (nearAngle > 0.1 * angle) break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
partialLen += stroke->getChunk(i)->getLength();
|
|
Shinya Kitaoka |
120a6e |
if (partialLen > metaCornerLen) {
|
|
Shinya Kitaoka |
120a6e |
goodAngle = true;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (goodAngle) {
|
|
Shinya Kitaoka |
120a6e |
// l'angolo viene un po' declassato in quanto meta
|
|
Shinya Kitaoka |
120a6e |
it = corners.insert(it, std::make_pair(j, angle * 0.7)) + 1;
|
|
Shinya Kitaoka |
120a6e |
if (min > angle) min = angle;
|
|
Shinya Kitaoka |
120a6e |
if (max < angle) max = angle;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static double variance(std::vector<double> &values) {</double>
|
|
Shinya Kitaoka |
120a6e |
UINT size = values.size();
|
|
Shinya Kitaoka |
120a6e |
if (size == 0) return std::numeric_limits<double>::signaling_NaN();</double>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double sum = 0;
|
|
Shinya Kitaoka |
120a6e |
UINT j = 0;
|
|
Shinya Kitaoka |
120a6e |
for (; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
sum += values[j];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double average = sum / size;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double variance = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < size; j++) {
|
|
Shinya Kitaoka |
120a6e |
variance += (average - values[j]) * (average - values[j]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return variance / size;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void findBestSolution(const TStroke *stroke1, const TStroke *stroke2,
|
|
Campbell Barton |
8c6c57 |
std::pair<int, double=""> *partialAngles1,</int,>
|
|
Campbell Barton |
8c6c57 |
UINT partialAngles1Size,
|
|
Campbell Barton |
8c6c57 |
const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
UINT r,
|
|
Campbell Barton |
8c6c57 |
std::list<std::pair<int, double="">> &partialSolution,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
double &bestValue, std::vector<int> &bestVector) {</int>
|
|
Shinya Kitaoka |
120a6e |
//-------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
if (r == partialAngles1Size) {
|
|
Shinya Kitaoka |
120a6e |
UINT j;
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::pair<int, double="">> angles1;</std::pair<int,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::list<std::pair<int, double="">>::iterator it = partialSolution.begin();</std::pair<int,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (; it != partialSolution.end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
angles1.push_back(*it);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < partialAngles1Size; j++) {
|
|
Shinya Kitaoka |
120a6e |
angles1.push_back(partialAngles1[j]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT angles1Size = angles1.size();
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> rationAngles(angles1Size), ratioLength(angles1Size + 1);</double>
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> ratioX, ratioY;</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1Size; j++) {
|
|
Shinya Kitaoka |
120a6e |
rationAngles[j] = fabs(angles1[j].second - angles2[j].second) /
|
|
Shinya Kitaoka |
120a6e |
(angles1[j].second + angles2[j].second);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT firstQuad1 = 0;
|
|
Shinya Kitaoka |
120a6e |
UINT firstQuad2 = 0;
|
|
Shinya Kitaoka |
120a6e |
UINT nextQuad1, nextQuad2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox1 = stroke1->getBBox();
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox2 = stroke2->getBBox();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double app, div;
|
|
Shinya Kitaoka |
120a6e |
double invTotalLen1 = stroke1->getLength();
|
|
Shinya Kitaoka |
120a6e |
assert(invTotalLen1 > 0);
|
|
Shinya Kitaoka |
120a6e |
invTotalLen1 = 1.0 / invTotalLen1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double invTotalLen2 = stroke2->getLength();
|
|
Shinya Kitaoka |
120a6e |
assert(invTotalLen2 > 0);
|
|
Shinya Kitaoka |
120a6e |
invTotalLen2 = 1.0 / invTotalLen2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j <= angles1Size; j++) {
|
|
Shinya Kitaoka |
120a6e |
if (j < angles1Size) {
|
|
Shinya Kitaoka |
120a6e |
nextQuad1 = angles1[j].first;
|
|
Shinya Kitaoka |
120a6e |
nextQuad2 = angles2[j].first;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
nextQuad1 = stroke1->getChunkCount();
|
|
Shinya Kitaoka |
120a6e |
nextQuad2 = stroke2->getChunkCount();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ratioLength[j] =
|
|
Shinya Kitaoka |
120a6e |
fabs(stroke1->getLengthAtControlPoint(nextQuad1 * 2) * invTotalLen1 -
|
|
Shinya Kitaoka |
120a6e |
stroke2->getLengthAtControlPoint(nextQuad2 * 2) * invTotalLen2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD p1(stroke1->getChunk(nextQuad1 - 1)->getP2() -
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunk(firstQuad1)->getP0());
|
|
Shinya Kitaoka |
120a6e |
p1.x = fabs(p1.x);
|
|
Shinya Kitaoka |
120a6e |
p1.y = fabs(p1.y);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD p2(stroke2->getChunk(nextQuad2 - 1)->getP2() -
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunk(firstQuad2)->getP0());
|
|
Shinya Kitaoka |
120a6e |
p2.x = fabs(p2.x);
|
|
Shinya Kitaoka |
120a6e |
p2.y = fabs(p2.y);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
app = fabs(bbox1.getLx() * p2.x - bbox2.getLx() * p1.x);
|
|
Shinya Kitaoka |
120a6e |
div = (bbox1.getLx() * p2.x + bbox2.getLx() * p1.x);
|
|
Shinya Kitaoka |
120a6e |
if (div) ratioX.push_back(app / div);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
app = fabs(bbox1.getLy() * p2.y - bbox2.getLy() * p1.y);
|
|
Shinya Kitaoka |
120a6e |
div = (bbox1.getLy() * p2.y + bbox2.getLy() * p1.y);
|
|
Shinya Kitaoka |
120a6e |
if (div) ratioY.push_back(app / div);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
firstQuad1 = nextQuad1;
|
|
Shinya Kitaoka |
120a6e |
firstQuad2 = nextQuad2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double varAng, varX, varY, varLen;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
varX = average(ratioX);
|
|
Shinya Kitaoka |
120a6e |
varY = average(ratioY);
|
|
Shinya Kitaoka |
120a6e |
varLen = average(ratioLength);
|
|
Shinya Kitaoka |
120a6e |
varAng = average(rationAngles);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double estimate = varX + varY + varAng + varLen;
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
#ifdef _DEBUG
|
|
Shinya Kitaoka |
120a6e |
for(UINT dI=0; dI
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream() << angles1[dI].first<<" ";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream() <<"estimate "<< estimate<<"=" ;
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#endif
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (estimate < bestValue) {
|
|
Shinya Kitaoka |
120a6e |
bestValue = estimate;
|
|
Shinya Kitaoka |
120a6e |
if (bestVector.size() != angles1Size) {
|
|
Shinya Kitaoka |
120a6e |
assert(!"bad size for bestVector");
|
|
Shinya Kitaoka |
120a6e |
bestVector.resize(angles1Size);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1Size; j++) {
|
|
Shinya Kitaoka |
120a6e |
bestVector[j] = angles1[j].first;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//-------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (r == 1) {
|
|
Shinya Kitaoka |
120a6e |
for (UINT i = 0; i < partialAngles1Size; i++) {
|
|
Shinya Kitaoka |
120a6e |
findBestSolution(stroke1, stroke2, partialAngles1 + i, 1, angles2, 1,
|
|
Shinya Kitaoka |
120a6e |
partialSolution, bestValue, bestVector);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
partialSolution.push_back(partialAngles1[0]);
|
|
Shinya Kitaoka |
120a6e |
findBestSolution(stroke1, stroke2, partialAngles1 + 1, partialAngles1Size - 1,
|
|
Shinya Kitaoka |
120a6e |
angles2, r - 1, partialSolution, bestValue, bestVector);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
partialSolution.pop_back();
|
|
Shinya Kitaoka |
120a6e |
findBestSolution(stroke1, stroke2, partialAngles1 + 1, partialAngles1Size - 1,
|
|
Shinya Kitaoka |
120a6e |
angles2, r, partialSolution, bestValue, bestVector);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void findBestSolution(const TStroke *stroke1, const TStroke *stroke2,
|
|
Campbell Barton |
8c6c57 |
std::vector<std::pair<int, double="">> &angles1,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
double &bestValue, std::vector<int> &bestVector) {</int>
|
|
Shinya Kitaoka |
120a6e |
assert(angles1.size() > angles2.size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::list<std::pair<int, double="">> partialSolution;</std::pair<int,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
findBestSolution(stroke1, stroke2, &(angles1[0]), angles1.size(), angles2,
|
|
Shinya Kitaoka |
120a6e |
angles2.size(), partialSolution, bestValue, bestVector);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void trivialSolution(const TStroke *stroke1, const TStroke *stroke2,
|
|
Campbell Barton |
8c6c57 |
const std::vector<std::pair<int, double="">> &angles1,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
|
|
Campbell Barton |
8c6c57 |
std::vector<int> &solution) {</int>
|
|
Shinya Kitaoka |
120a6e |
assert(angles1.size() > angles2.size());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT j;
|
|
Shinya Kitaoka |
120a6e |
double subStrokeRatio2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double invTotalLen2 = stroke2->getLength();
|
|
Shinya Kitaoka |
120a6e |
assert(invTotalLen2);
|
|
Shinya Kitaoka |
120a6e |
invTotalLen2 = 1.0 / invTotalLen2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double invTotalLen1 = stroke1->getLength();
|
|
Shinya Kitaoka |
120a6e |
assert(invTotalLen1 > 0);
|
|
Shinya Kitaoka |
120a6e |
invTotalLen1 = 1.0 / invTotalLen1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (solution.size() != angles2.size()) {
|
|
Shinya Kitaoka |
120a6e |
assert(!"bad size for solution");
|
|
Shinya Kitaoka |
120a6e |
solution.resize(angles2.size());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int toBeErased = angles1.size() - angles2.size();
|
|
Shinya Kitaoka |
120a6e |
UINT count = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double diff, ratio, oldRatio = 100;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
subStrokeRatio2 =
|
|
Shinya Kitaoka |
120a6e |
stroke2->getLengthAtControlPoint(angles2[count].first * 2) * invTotalLen2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1.size() && count < solution.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
if (toBeErased == 0) {
|
|
Shinya Kitaoka |
120a6e |
solution[count++] = angles1[j].first;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
ratio =
|
|
Shinya Kitaoka |
120a6e |
stroke1->getLengthAtControlPoint(angles1[j].first * 2) * invTotalLen1;
|
|
Shinya Kitaoka |
120a6e |
assert(ratio > 0 && ratio <= 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
diff = ratio - subStrokeRatio2;
|
|
Shinya Kitaoka |
120a6e |
if (diff >= 0) {
|
|
Shinya Kitaoka |
120a6e |
if (fabs(diff) < fabs(oldRatio - subStrokeRatio2)) {
|
|
Shinya Kitaoka |
120a6e |
solution[count] = angles1[j].first;
|
|
Shinya Kitaoka |
120a6e |
oldRatio = 100;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
assert(j > 0);
|
|
Shinya Kitaoka |
120a6e |
solution[count] = angles1[j - 1].first;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
count++;
|
|
Shinya Kitaoka |
120a6e |
if (angles2.size() < count)
|
|
Shinya Kitaoka |
120a6e |
subStrokeRatio2 =
|
|
Shinya Kitaoka |
120a6e |
stroke2->getLengthAtControlPoint(angles2[count].first * 2) *
|
|
Shinya Kitaoka |
120a6e |
invTotalLen2;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
subStrokeRatio2 = 1;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
toBeErased--;
|
|
Shinya Kitaoka |
120a6e |
oldRatio = ratio;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
assert(count == solution.size());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static TStroke *extract(const TStroke *source, UINT firstQuad, UINT lastQuad) {
|
|
Shinya Kitaoka |
120a6e |
UINT quadCount = source->getChunkCount();
|
|
Shinya Kitaoka |
120a6e |
if (firstQuad >= quadCount) {
|
|
Shinya Kitaoka |
120a6e |
assert(!"bad quadric index");
|
|
Shinya Kitaoka |
120a6e |
firstQuad = quadCount - 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (lastQuad < firstQuad) {
|
|
Shinya Kitaoka |
120a6e |
assert(!"bad quadric index");
|
|
Shinya Kitaoka |
120a6e |
lastQuad = firstQuad;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (lastQuad >= quadCount) {
|
|
Shinya Kitaoka |
120a6e |
assert(!"bad quadric index");
|
|
Shinya Kitaoka |
120a6e |
lastQuad = quadCount - 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT cpIndex0 = firstQuad * 2;
|
|
Shinya Kitaoka |
120a6e |
UINT cpIndex1 = lastQuad * 2 + 2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points(cpIndex1 - cpIndex0 + 1);</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
UINT count = 0;
|
|
Shinya Kitaoka |
120a6e |
for (UINT j = cpIndex0; j <= cpIndex1; j++) {
|
|
Shinya Kitaoka |
120a6e |
points[count++] = source->getControlPoint(j);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return new TStroke(points);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void sample(const TStroke *stroke, int samplingSize,
|
|
Campbell Barton |
8c6c57 |
std::vector<tpointd> &sampledPoint) {</tpointd>
|
|
Shinya Kitaoka |
120a6e |
double samplingFrequency = 1.0 / (double)samplingSize;
|
|
Shinya Kitaoka |
120a6e |
sampledPoint.resize(samplingSize);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double totalLen = stroke->getLength();
|
|
Shinya Kitaoka |
120a6e |
double step = totalLen * samplingFrequency;
|
|
Shinya Kitaoka |
120a6e |
double len = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int p = 0; p < samplingSize - 1; p++) {
|
|
Shinya Kitaoka |
120a6e |
sampledPoint[p] = stroke->getPointAtLength(len);
|
|
Shinya Kitaoka |
120a6e |
len += step;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
sampledPoint.back() =
|
|
Shinya Kitaoka |
120a6e |
stroke->getControlPoint(stroke->getControlPointCount() - 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class TInbetween::Imp {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
//----------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
struct StrokeTransform {
|
|
Shinya Kitaoka |
120a6e |
typedef enum { EQUAL, POINT, GENERAL } TransformationType;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD m_translate;
|
|
Shinya Kitaoka |
120a6e |
TPointD m_rotationAndScaleCenter;
|
|
Shinya Kitaoka |
120a6e |
double m_scaleX, m_scaleY, m_rotation;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TransformationType m_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// saved for optimization
|
|
Shinya Kitaoka |
120a6e |
TAffine m_inverse;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> m_firstStrokeCornerIndexes;</int>
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> m_secondStrokeCornerIndexes;</int>
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//----------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP m_firstImage, m_lastImage;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<stroketransform> m_transformation;</stroketransform>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void computeTransformation();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void transferColor(const TVectorImageP &destination) const;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP tween(double t) const;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Imp(const TVectorImageP firstImage, const TVectorImageP lastImage)
|
|
Shinya Kitaoka |
120a6e |
: m_firstImage(firstImage), m_lastImage(lastImage) {
|
|
Shinya Kitaoka |
120a6e |
computeTransformation();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TInbetween::TInbetween(const TVectorImageP firstImage,
|
|
Shinya Kitaoka |
120a6e |
const TVectorImageP lastImage)
|
|
Shinya Kitaoka |
120a6e |
: m_imp(new TInbetween::Imp(firstImage, lastImage)) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TInbetween::~TInbetween() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TInbetween::Imp::computeTransformation() {
|
|
Shinya Kitaoka |
120a6e |
const UINT samplingPointNumber = 10;
|
|
Shinya Kitaoka |
120a6e |
const UINT bboxSamplingWeight = samplingPointNumber / 2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
StrokeTransform transform;
|
|
Shinya Kitaoka |
120a6e |
double cs, sn, totalLen1, totalLen2, constK, constQ, constB, constD, constA;
|
|
Shinya Kitaoka |
120a6e |
UINT cpCount1, cpCount2;
|
|
Shinya Kitaoka |
120a6e |
TPointD stroke1Centroid, stroke2Centroid, stroke1Begin, stroke2Begin,
|
|
Shinya Kitaoka |
120a6e |
stroke1End, stroke2End, versor1, versor2;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tpointd> samplingPoint1(samplingPointNumber),</tpointd>
|
|
Shinya Kitaoka |
120a6e |
samplingPoint2(samplingPointNumber);
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke1, *stroke2;
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> ratioSampling, weigths, subStrokeXScaling,</double>
|
|
Shinya Kitaoka |
120a6e |
subStrokeYScaling;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT strokeCount1 = m_firstImage->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
UINT strokeCount2 = m_lastImage->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
if (strokeCount1 > strokeCount2) strokeCount1 = strokeCount2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_transformation.clear();
|
|
Shinya Kitaoka |
120a6e |
m_transformation.reserve(strokeCount1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const int maxSubSetNum = (strokeCount1) ? 1000 / strokeCount1 : 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT j, p;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (UINT i = 0; i < strokeCount1; i++) {
|
|
Shinya Kitaoka |
120a6e |
stroke1 = m_firstImage->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
stroke2 = m_lastImage->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// check if the strokes are equal
|
|
Shinya Kitaoka |
120a6e |
cpCount1 = stroke1->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
cpCount2 = stroke2->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.clear();
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.clear();
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate = TPointD();
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter = TPointD();
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = 0;
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleY = 0;
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotation = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isEqual = true;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (cpCount1 == cpCount2) {
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cpCount1 && isEqual; j++) {
|
|
Shinya Kitaoka |
120a6e |
isEqual = (stroke1->getControlPoint(j) == stroke2->getControlPoint(j));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
isEqual = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isEqual) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_type = StrokeTransform::EQUAL;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
totalLen1 = stroke1->getLength();
|
|
Shinya Kitaoka |
120a6e |
totalLen2 = stroke2->getLength();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (totalLen1 == 0 || totalLen2 == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (totalLen1 == 0 && totalLen2 == 0) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_type = StrokeTransform::POINT;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_inverse = TAffine();
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.resize(2);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes[1] = stroke1->getChunkCount();
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.resize(2);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes[1] = stroke2->getChunkCount();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
const double startMinAngle = 30.0;
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::pair<int, double="">> angles1, angles2;</std::pair<int,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_type = StrokeTransform::GENERAL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double minAngle, maxAngle;
|
|
Shinya Kitaoka |
120a6e |
int minAngle1, maxAngle1, minAngle2, maxAngle2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
angles1.clear();
|
|
Shinya Kitaoka |
120a6e |
angles2.clear();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
detectCorners(stroke1, startMinAngle, angles1, minAngle, maxAngle);
|
|
Shinya Kitaoka |
120a6e |
minAngle1 = (int)minAngle;
|
|
Shinya Kitaoka |
120a6e |
maxAngle1 = (int)maxAngle;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::getStream()<
|
|
Shinya Kitaoka |
120a6e |
// TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
detectCorners(stroke2, startMinAngle, angles2, minAngle, maxAngle);
|
|
Shinya Kitaoka |
120a6e |
minAngle2 = (int)minAngle;
|
|
Shinya Kitaoka |
120a6e |
maxAngle2 = (int)maxAngle;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (angles1.empty()) angles2.clear();
|
|
Shinya Kitaoka |
120a6e |
if (angles2.empty()) angles1.clear();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
debugStream.open("c:\\temp\\inbetween.txt", ios_base::out);
|
|
Shinya Kitaoka |
120a6e |
debugStream <<"num angoli 1: "<< angles1.size() << endl;
|
|
Shinya Kitaoka |
120a6e |
debugStream <<"num angoli 2: "<< angles2.size() << endl;
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double bestValue = (std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (angles1.size() != angles2.size()) {
|
|
Shinya Kitaoka |
120a6e |
bestValue = (std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//--------------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) {
|
|
Shinya Kitaoka |
120a6e |
// debugStream <<"is too complex" << endl;
|
|
Shinya Kitaoka |
120a6e |
int firstAngle =
|
|
Shinya Kitaoka |
120a6e |
(int)((angles1.size() < angles2.size()) ? minAngle2
|
|
Shinya Kitaoka |
120a6e |
: minAngle1);
|
|
Shinya Kitaoka |
120a6e |
int lastAngle =
|
|
Shinya Kitaoka |
120a6e |
(int)((angles1.size() < angles2.size()) ? maxAngle1
|
|
Shinya Kitaoka |
120a6e |
: maxAngle2);
|
|
Shinya Kitaoka |
120a6e |
int bestAngle = (int)startMinAngle;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((int)(angles1.size() + angles2.size()) <
|
|
Shinya Kitaoka |
120a6e |
lastAngle - firstAngle + 1) {
|
|
Shinya Kitaoka |
120a6e |
double tempAngle;
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> sortedAngles1, sortedAngles2;</double>
|
|
Shinya Kitaoka |
120a6e |
sortedAngles1.reserve(angles1.size());
|
|
Shinya Kitaoka |
120a6e |
sortedAngles2.reserve(angles2.size());
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
tempAngle = angles1[j].second;
|
|
Shinya Kitaoka |
120a6e |
if (tempAngle >= firstAngle && tempAngle <= lastAngle)
|
|
Shinya Kitaoka |
120a6e |
sortedAngles1.push_back(tempAngle);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles2.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
tempAngle = angles2[j].second;
|
|
Shinya Kitaoka |
120a6e |
if (tempAngle >= firstAngle && tempAngle <= lastAngle)
|
|
Shinya Kitaoka |
120a6e |
sortedAngles2.push_back(tempAngle);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> sortedAngles(sortedAngles1.size() +</double>
|
|
Shinya Kitaoka |
120a6e |
sortedAngles2.size());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::sort(sortedAngles1.begin(), sortedAngles1.end());
|
|
Shinya Kitaoka |
120a6e |
std::sort(sortedAngles2.begin(), sortedAngles2.end());
|
|
Shinya Kitaoka |
120a6e |
std::merge(sortedAngles1.begin(), sortedAngles1.end(),
|
|
Shinya Kitaoka |
120a6e |
sortedAngles2.begin(), sortedAngles2.end(),
|
|
Shinya Kitaoka |
120a6e |
sortedAngles.begin());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < sortedAngles.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
int numAng1 = angleNumber(angles1, sortedAngles[j]);
|
|
Shinya Kitaoka |
120a6e |
int numAng2 = angleNumber(angles2, sortedAngles[j]);
|
|
Shinya Kitaoka |
120a6e |
double val = (numAng1 == numAng2)
|
|
Shinya Kitaoka |
120a6e |
? 0
|
|
Shinya Kitaoka |
120a6e |
: fabs((float)(numAng1 - numAng2)) /
|
|
Shinya Kitaoka |
120a6e |
(numAng1 + numAng2);
|
|
Shinya Kitaoka |
120a6e |
if (val < bestValue) {
|
|
Shinya Kitaoka |
120a6e |
bestValue = val;
|
|
Shinya Kitaoka |
120a6e |
bestAngle = (int)(sortedAngles[j]);
|
|
Shinya Kitaoka |
120a6e |
if (bestValue == 0 ||
|
|
Shinya Kitaoka |
120a6e |
!isTooComplex(numAng1, numAng2, maxSubSetNum))
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} else //-----------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
for (int angle = firstAngle; angle <= lastAngle; angle++) {
|
|
Shinya Kitaoka |
120a6e |
int numAng1 = angleNumber(angles1, angle);
|
|
Shinya Kitaoka |
120a6e |
int numAng2 = angleNumber(angles2, angle);
|
|
Shinya Kitaoka |
120a6e |
double val = (numAng1 == numAng2)
|
|
Shinya Kitaoka |
120a6e |
? 0
|
|
Shinya Kitaoka |
120a6e |
: fabs((float)(numAng1 - numAng2)) /
|
|
Shinya Kitaoka |
120a6e |
(numAng1 + numAng2);
|
|
Shinya Kitaoka |
120a6e |
if (val < bestValue) {
|
|
Shinya Kitaoka |
120a6e |
bestValue = val;
|
|
Shinya Kitaoka |
120a6e |
bestAngle = angle;
|
|
Shinya Kitaoka |
120a6e |
if (bestValue == 0 ||
|
|
Shinya Kitaoka |
120a6e |
!isTooComplex(numAng1, numAng2, maxSubSetNum))
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
eraseSmallAngles(angles1, bestAngle);
|
|
Shinya Kitaoka |
120a6e |
eraseSmallAngles(angles2, bestAngle);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
debugStream <<"bestAngle: "<< bestAngle << endl;
|
|
Shinya Kitaoka |
120a6e |
debugStream <<"num angoli 1: "<< angles1.size() << endl;
|
|
Shinya Kitaoka |
120a6e |
debugStream <<"num angoli 2: "<< angles2.size() << endl;
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
//--------------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bestValue = (std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (angles1.size() == angles2.size()) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles2.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) {
|
|
Shinya Kitaoka |
120a6e |
if (angles1.size() > angles2.size()) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.resize(angles2.size());
|
|
Shinya Kitaoka |
120a6e |
trivialSolution(stroke1, stroke2, angles1, angles2,
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.insert(
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.begin(), 0);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles2.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
angles2[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
angles1[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.resize(angles1.size());
|
|
Shinya Kitaoka |
120a6e |
trivialSolution(stroke2, stroke1, angles2, angles1,
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.insert(
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.begin(), 0);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (angles1.size() > angles2.size()) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.resize(angles2.size());
|
|
Shinya Kitaoka |
120a6e |
findBestSolution(stroke1, stroke2, angles1, angles2, bestValue,
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.insert(
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.begin(), 0);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles2.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
angles2[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
angles1[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.resize(angles1.size());
|
|
Shinya Kitaoka |
120a6e |
findBestSolution(stroke2, stroke1, angles2, angles1, bestValue,
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.insert(
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.begin(), 0);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles1.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(0);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < angles2.size(); j++)
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first);
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes.push_back(
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT cornerSize = transform.m_firstStrokeCornerIndexes.size();
|
|
Shinya Kitaoka |
120a6e |
assert(cornerSize == transform.m_secondStrokeCornerIndexes.size());
|
|
Shinya Kitaoka |
120a6e |
assert(cornerSize >= 2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double totalRadRotation = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TStroke *subStroke1 = 0;
|
|
Shinya Kitaoka |
120a6e |
TStroke *subStroke2 = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke1Centroid = stroke1->getCentroid();
|
|
Shinya Kitaoka |
120a6e |
stroke2Centroid = stroke2->getCentroid();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_firstStrokeCornerIndexes[0] == 0);
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_secondStrokeCornerIndexes[0] == 0);
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_firstStrokeCornerIndexes[cornerSize - 1] ==
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_secondStrokeCornerIndexes[cornerSize - 1] ==
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize - 1; j++) {
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_firstStrokeCornerIndexes[j] <
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes[j + 1]);
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_secondStrokeCornerIndexes[j] <
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes[j + 1]);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_firstStrokeCornerIndexes[j] <
|
|
Shinya Kitaoka |
120a6e |
stroke1->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_secondStrokeCornerIndexes[j] <
|
|
Shinya Kitaoka |
120a6e |
stroke2->getChunkCount());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize - 1; j++) {
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// sampling
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
sample(subStroke1, samplingPointNumber, samplingPoint1);
|
|
Shinya Kitaoka |
120a6e |
subStroke2 =
|
|
Shinya Kitaoka |
120a6e |
extract(stroke2, transform.m_secondStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
sample(subStroke2, samplingPointNumber, samplingPoint2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// compute Rotation
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.clear();
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.reserve(samplingPointNumber);
|
|
Shinya Kitaoka |
120a6e |
weigths.clear();
|
|
Shinya Kitaoka |
120a6e |
weigths.reserve(samplingPointNumber);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD pOld, pNew;
|
|
Shinya Kitaoka |
120a6e |
// double totalW=0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (p = 0; p < samplingPointNumber; p++) {
|
|
Shinya Kitaoka |
120a6e |
pOld = samplingPoint1[p];
|
|
Shinya Kitaoka |
120a6e |
pNew = samplingPoint2[p];
|
|
Shinya Kitaoka |
120a6e |
if (pOld == stroke1Centroid) continue;
|
|
Shinya Kitaoka |
120a6e |
if (pNew == stroke2Centroid) continue;
|
|
Shinya Kitaoka |
120a6e |
versor1 = normalize(pOld - stroke1Centroid);
|
|
Shinya Kitaoka |
120a6e |
versor2 = normalize(pNew - stroke2Centroid);
|
|
Shinya Kitaoka |
120a6e |
weigths.push_back(tdistance(pOld, stroke1Centroid) +
|
|
Shinya Kitaoka |
120a6e |
tdistance(pNew, stroke2Centroid));
|
|
Shinya Kitaoka |
120a6e |
cs = versor1 * versor2;
|
|
Shinya Kitaoka |
120a6e |
sn = cross(versor1, versor2);
|
|
Shinya Kitaoka |
120a6e |
double v = atan2(sn, cs);
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(v);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
delete subStroke1;
|
|
Shinya Kitaoka |
120a6e |
delete subStroke2;
|
|
Shinya Kitaoka |
120a6e |
subStroke1 = 0;
|
|
Shinya Kitaoka |
120a6e |
subStroke2 = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double radRotation = weightedAverage(ratioSampling, weigths);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
totalRadRotation += radRotation;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
totalRadRotation /= (cornerSize - 1);
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotation = totalRadRotation * M_180_PI;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isAlmostZero(transform.m_rotation, 2)) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotation = 0.0;
|
|
Shinya Kitaoka |
120a6e |
totalRadRotation = 0.0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
// TDebugMessage::getStream()<<"rotation "<< transform.m_rotation;
|
|
Toshihiro Shimizu |
890ddd |
// TDebugMessage::flush();
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// compute Scale
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (transform.m_rotation == 0.0) {
|
|
Shinya Kitaoka |
120a6e |
subStrokeXScaling.clear();
|
|
Shinya Kitaoka |
120a6e |
subStrokeXScaling.reserve(cornerSize - 1);
|
|
Shinya Kitaoka |
120a6e |
subStrokeYScaling.clear();
|
|
Shinya Kitaoka |
120a6e |
subStrokeYScaling.reserve(cornerSize - 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize - 1; j++) {
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// sampling
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
subStroke1 =
|
|
Shinya Kitaoka |
120a6e |
extract(stroke1, transform.m_firstStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
sample(subStroke1, samplingPointNumber, samplingPoint1);
|
|
Shinya Kitaoka |
120a6e |
subStroke2 =
|
|
Shinya Kitaoka |
120a6e |
extract(stroke2, transform.m_secondStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
sample(subStroke2, samplingPointNumber, samplingPoint2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// compute X Scale
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.clear();
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight);
|
|
Shinya Kitaoka |
120a6e |
double appX, appY;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD appPoint;
|
|
Shinya Kitaoka |
120a6e |
double bboxXMin, bboxYMin, bboxXMax, bboxYMax;
|
|
Shinya Kitaoka |
120a6e |
bboxXMin = bboxYMin = (std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
bboxXMax = bboxYMax = -(std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
int h;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (h = 0; h < subStroke1->getControlPointCount(); ++h) {
|
|
Shinya Kitaoka |
120a6e |
appPoint = subStroke1->getControlPoint(h);
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.x < bboxXMin) bboxXMin = appPoint.x;
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.x > bboxXMax) bboxXMax = appPoint.x;
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.y < bboxYMin) bboxYMin = appPoint.y;
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.y > bboxYMax) bboxYMax = appPoint.y;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
appX = bboxXMax - bboxXMin;
|
|
Shinya Kitaoka |
120a6e |
appY = bboxYMax - bboxYMin;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (appX) {
|
|
Shinya Kitaoka |
120a6e |
bboxXMin = (std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
bboxXMax = -(std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
for (h = 0; h < subStroke2->getControlPointCount(); ++h) {
|
|
Shinya Kitaoka |
120a6e |
appPoint = subStroke2->getControlPoint(h);
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.x < bboxXMin) bboxXMin = appPoint.x;
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.x > bboxXMax) bboxXMax = appPoint.x;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
appX = (isAlmostZero(appX, 1e-01)) ? -1
|
|
Shinya Kitaoka |
120a6e |
: (bboxXMax - bboxXMin) / appX;
|
|
Shinya Kitaoka |
120a6e |
for (UINT tms = 0; tms < bboxSamplingWeight && appX >= 0; tms++)
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(appX);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (p = 0; p < samplingPointNumber; p++) {
|
|
Shinya Kitaoka |
120a6e |
appX = fabs(samplingPoint1[p].x - stroke1Centroid.x);
|
|
Shinya Kitaoka |
120a6e |
if (appX)
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(
|
|
Shinya Kitaoka |
120a6e |
fabs(samplingPoint2[p].x - stroke2Centroid.x) / appX);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!ratioSampling.empty()) {
|
|
Shinya Kitaoka |
120a6e |
subStrokeXScaling.push_back(average(ratioSampling));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// compute Y Scale
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.clear();
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (appY) {
|
|
Shinya Kitaoka |
120a6e |
bboxYMin = (std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
bboxYMax = -(std::numeric_limits<double>::max)();</double>
|
|
Shinya Kitaoka |
120a6e |
for (h = 0; h < subStroke2->getControlPointCount(); ++h) {
|
|
Shinya Kitaoka |
120a6e |
appPoint = subStroke2->getControlPoint(h);
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.y < bboxYMin) bboxYMin = appPoint.y;
|
|
Shinya Kitaoka |
120a6e |
if (appPoint.y > bboxYMax) bboxYMax = appPoint.y;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
appY = (isAlmostZero(appY, 1e-01)) ? -1
|
|
Shinya Kitaoka |
120a6e |
: (bboxYMax - bboxYMin) / appY;
|
|
Shinya Kitaoka |
120a6e |
for (UINT tms = 0; tms < bboxSamplingWeight && appY >= 0; tms++)
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(appY);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (p = 0; p < samplingPointNumber; p++) {
|
|
Shinya Kitaoka |
120a6e |
appY = fabs(samplingPoint1[p].y - stroke1Centroid.y);
|
|
Shinya Kitaoka |
120a6e |
if (appY)
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(
|
|
Shinya Kitaoka |
120a6e |
fabs(samplingPoint2[p].y - stroke2Centroid.y) / appY);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!ratioSampling.empty()) {
|
|
Shinya Kitaoka |
120a6e |
subStrokeYScaling.push_back(average(ratioSampling));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete subStroke1;
|
|
Shinya Kitaoka |
120a6e |
delete subStroke2;
|
|
Shinya Kitaoka |
120a6e |
subStroke1 = 0;
|
|
Shinya Kitaoka |
120a6e |
subStroke2 = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (subStrokeXScaling.empty()) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = 1.0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = average(subStrokeXScaling);
|
|
Shinya Kitaoka |
120a6e |
if (isAlmostZero(transform.m_scaleX - 1.0))
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = 1.0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (subStrokeYScaling.empty()) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleY = 1.0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleY = average(subStrokeYScaling);
|
|
Shinya Kitaoka |
120a6e |
if (isAlmostZero(transform.m_scaleY - 1.0))
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleY = 1.0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
#ifdef _DEBUG
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<<"x scale "<< transform.m_scaleX ;
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<<"y scale "<< transform.m_scaleY ;
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
#endif
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
subStrokeXScaling.clear();
|
|
Shinya Kitaoka |
120a6e |
subStrokeXScaling.reserve(cornerSize - 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize - 1; j++) {
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// sampling
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
subStroke1 =
|
|
Shinya Kitaoka |
120a6e |
extract(stroke1, transform.m_firstStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
transform.m_firstStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
sample(subStroke1, samplingPointNumber, samplingPoint1);
|
|
Shinya Kitaoka |
120a6e |
subStroke2 =
|
|
Shinya Kitaoka |
120a6e |
extract(stroke2, transform.m_secondStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
transform.m_secondStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
sample(subStroke2, samplingPointNumber, samplingPoint2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// compute Scale
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.clear();
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox1 = subStroke1->getBBox();
|
|
Shinya Kitaoka |
120a6e |
double app = tdistance2(bbox1.getP00(), bbox1.getP11());
|
|
Shinya Kitaoka |
120a6e |
if (app) {
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox2 =
|
|
Shinya Kitaoka |
120a6e |
TRotation(transform.m_rotation).inv() * subStroke2->getBBox();
|
|
Shinya Kitaoka |
120a6e |
app = sqrt(tdistance2(bbox2.getP00(), bbox2.getP11()) / app);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (UINT tms = 0; tms < bboxSamplingWeight; tms++)
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(app);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double app;
|
|
Shinya Kitaoka |
120a6e |
for (p = 0; p < samplingPointNumber; p++) {
|
|
Shinya Kitaoka |
120a6e |
app = tdistance(samplingPoint1[p], stroke1Centroid);
|
|
Shinya Kitaoka |
120a6e |
if (app) {
|
|
Shinya Kitaoka |
120a6e |
ratioSampling.push_back(
|
|
Shinya Kitaoka |
120a6e |
tdistance(samplingPoint2[p], stroke2Centroid) / app);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!ratioSampling.empty()) {
|
|
Shinya Kitaoka |
120a6e |
subStrokeXScaling.push_back(average(ratioSampling));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete subStroke1;
|
|
Shinya Kitaoka |
120a6e |
delete subStroke2;
|
|
Shinya Kitaoka |
120a6e |
subStroke1 = 0;
|
|
Shinya Kitaoka |
120a6e |
subStroke2 = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (subStrokeXScaling.empty()) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = transform.m_scaleY = 1.0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = transform.m_scaleY =
|
|
Shinya Kitaoka |
120a6e |
average(subStrokeXScaling);
|
|
Shinya Kitaoka |
120a6e |
if (isAlmostZero(transform.m_scaleX - 1.0, 0.00001))
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX = transform.m_scaleY = 1.0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
#ifdef _DEBUG
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::getStream()<<"scale "<< transform.m_scaleX ;
|
|
Shinya Kitaoka |
120a6e |
TDebugMessage::flush();
|
|
Shinya Kitaoka |
120a6e |
#endif
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
///////////////////////////////////////// compute centre of Rotation and
|
|
Shinya Kitaoka |
38fd86 |
/// Scaling
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<tpointd> vpOld(cornerSize), vpNew(cornerSize);</tpointd>
|
|
Shinya Kitaoka |
120a6e |
TPointD pOld, pNew;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize - 1; j++) {
|
|
Shinya Kitaoka |
120a6e |
vpOld[j] = stroke1->getChunk(transform.m_firstStrokeCornerIndexes[j])
|
|
Shinya Kitaoka |
120a6e |
->getP0();
|
|
Shinya Kitaoka |
120a6e |
vpNew[j] = stroke2->getChunk(transform.m_secondStrokeCornerIndexes[j])
|
|
Shinya Kitaoka |
120a6e |
->getP0();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
vpOld[j] = stroke1->getControlPoint(stroke1->getControlPointCount());
|
|
Shinya Kitaoka |
120a6e |
vpNew[j] = stroke2->getControlPoint(stroke2->getControlPointCount());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (transform.m_rotation == 0.0) {
|
|
Shinya Kitaoka |
120a6e |
if (transform.m_scaleX == 1.0 && transform.m_scaleY == 1.0) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate = stroke2Centroid - stroke1Centroid;
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter = TPointD();
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (transform.m_scaleX == 1.0) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.x = 0;
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.x = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize; j++) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.x += vpNew[j].x - vpOld[j].x;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.x = transform.m_translate.x / cornerSize;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.x = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize; j++) {
|
|
Shinya Kitaoka |
120a6e |
pOld = vpOld[j];
|
|
Shinya Kitaoka |
120a6e |
pNew = vpNew[j];
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.x +=
|
|
Shinya Kitaoka |
120a6e |
(transform.m_scaleX * pOld.x - pNew.x) /
|
|
Shinya Kitaoka |
120a6e |
(transform.m_scaleX - 1.0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.x =
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.x / cornerSize;
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.x = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (transform.m_scaleY == 1.0) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.y = 0;
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.y = 0;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize; j++) {
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.y += vpNew[j].y - vpOld[j].y;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.y = transform.m_translate.y / cornerSize;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.y = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize; j++) {
|
|
Shinya Kitaoka |
120a6e |
pOld = vpOld[j];
|
|
Shinya Kitaoka |
120a6e |
pNew = vpNew[j];
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.y +=
|
|
Shinya Kitaoka |
120a6e |
(transform.m_scaleY * pOld.y - pNew.y) /
|
|
Shinya Kitaoka |
120a6e |
(transform.m_scaleY - 1.0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.y =
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.y / cornerSize;
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.y = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
assert(transform.m_scaleX == transform.m_scaleY);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
cs = transform.m_scaleX * cos(totalRadRotation);
|
|
Shinya Kitaoka |
120a6e |
sn = transform.m_scaleX * sin(totalRadRotation);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// scelgo punti da usare come vincolo, per ottenere la translazione,
|
|
Shinya Kitaoka |
120a6e |
// dato un centro di rotazione
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// dato il punto pOld e pNew si calcola analiticamnete il punto di
|
|
Shinya Kitaoka |
120a6e |
// rotazione e scala
|
|
Shinya Kitaoka |
120a6e |
// che minimizza la traslazione aggiuntiva e la traslazione stessa
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize; j++) {
|
|
Shinya Kitaoka |
120a6e |
pOld = vpOld[j];
|
|
Shinya Kitaoka |
120a6e |
pNew = vpNew[j];
|
|
Shinya Kitaoka |
120a6e |
constK = pNew.x - cs * pOld.x + sn * pOld.y;
|
|
Shinya Kitaoka |
120a6e |
constQ = pNew.y - sn * pOld.x - cs * pOld.y;
|
|
Shinya Kitaoka |
120a6e |
constB = 2 * (constK * (cs - 1.) + sn * constQ);
|
|
Shinya Kitaoka |
120a6e |
constD = 2 * (constQ * (cs - 1.) - sn * constK);
|
|
Shinya Kitaoka |
120a6e |
constA = transform.m_scaleX * transform.m_scaleX + 1 - 2 * cs;
|
|
Shinya Kitaoka |
120a6e |
assert(constA > 0);
|
|
Shinya Kitaoka |
120a6e |
constA = 1.0 / (2 * constA);
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.x += -constB * constA;
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter.y += -constD * constA;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter =
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotationAndScaleCenter * (1.0 / (double)cornerSize);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.x =
|
|
Shinya Kitaoka |
120a6e |
(cs - 1.0) * transform.m_rotationAndScaleCenter.x -
|
|
Shinya Kitaoka |
120a6e |
sn * transform.m_rotationAndScaleCenter.y + constK;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_translate.y =
|
|
Shinya Kitaoka |
120a6e |
sn * transform.m_rotationAndScaleCenter.x +
|
|
Shinya Kitaoka |
120a6e |
(cs - 1.0) * transform.m_rotationAndScaleCenter.y + constQ;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/////////////////////////////////////////
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
transform.m_inverse = (TTranslation(transform.m_translate) *
|
|
Shinya Kitaoka |
120a6e |
TScale(transform.m_rotationAndScaleCenter,
|
|
Shinya Kitaoka |
120a6e |
transform.m_scaleX, transform.m_scaleY) *
|
|
Shinya Kitaoka |
120a6e |
TRotation(transform.m_rotationAndScaleCenter,
|
|
Shinya Kitaoka |
120a6e |
transform.m_rotation))
|
|
Shinya Kitaoka |
120a6e |
.inv();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// debugStream.close();
|
|
Shinya Kitaoka |
120a6e |
} // end if !isPoint
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} // end if !isEqual
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_transformation.push_back(transform);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} // end for each stroke
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP TInbetween::Imp::tween(double t) const {
|
|
Shinya Kitaoka |
120a6e |
const double step = 5.0;
|
|
Shinya Kitaoka |
120a6e |
const double interpolateError = 1.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = new TVectorImage;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT strokeCount1 = m_firstImage->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
UINT strokeCount2 = m_lastImage->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
vi->setPalette(m_firstImage->getPalette());
|
|
Shinya Kitaoka |
120a6e |
if (strokeCount1 > strokeCount2) strokeCount1 = strokeCount2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(m_transformation.size() == strokeCount1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double totalLen1, totalLen2, len1, len2, step1, step2;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke1, *stroke2, *subStroke1, *subStroke2, *stroke;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TAffine mt, invMatrix;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point2, finalPoint;
|
|
Shinya Kitaoka |
120a6e |
UINT i, j, cp, cpSize;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < strokeCount1; i++) {
|
|
Shinya Kitaoka |
120a6e |
stroke1 = m_firstImage->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
stroke2 = m_lastImage->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_transformation[i].m_type == StrokeTransform::EQUAL) {
|
|
Shinya Kitaoka |
120a6e |
stroke = new TStroke(*stroke1);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
points.clear();
|
|
Shinya Kitaoka |
120a6e |
totalLen1 = stroke1->getLength();
|
|
Shinya Kitaoka |
120a6e |
totalLen2 = stroke2->getLength();
|
|
Shinya Kitaoka |
120a6e |
;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (stroke1->getControlPointCount() == stroke2->getControlPointCount() &&
|
|
Shinya Kitaoka |
120a6e |
stroke1->isSelfLoop() && stroke2->isSelfLoop()) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < stroke1->getControlPointCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p0 = stroke1->getControlPoint(i);
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p1 = stroke2->getControlPoint(i);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(p0 * (1 - t) + p1 * t);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
stroke = new TStroke(points);
|
|
Shinya Kitaoka |
120a6e |
} else if (m_transformation[i].m_type == StrokeTransform::POINT) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint pOld = stroke1->getThickPointAtLength(0.5 * totalLen1);
|
|
Shinya Kitaoka |
120a6e |
TThickPoint pNew = stroke2->getThickPointAtLength(0.5 * totalLen2);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(pOld * (1 - t) + pNew * t);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(points[0]);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(points[0]);
|
|
Shinya Kitaoka |
120a6e |
stroke = new TStroke(points);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
mt = (m_transformation[i].m_inverse.isIdentity())
|
|
Shinya Kitaoka |
120a6e |
? TAffine()
|
|
Shinya Kitaoka |
120a6e |
: TTranslation(m_transformation[i].m_translate * t) *
|
|
Shinya Kitaoka |
120a6e |
TScale(m_transformation[i].m_rotationAndScaleCenter,
|
|
Shinya Kitaoka |
120a6e |
(1 - t) + t * m_transformation[i].m_scaleX,
|
|
Shinya Kitaoka |
120a6e |
(1 - t) + t * m_transformation[i].m_scaleY) *
|
|
Shinya Kitaoka |
120a6e |
TRotation(m_transformation[i].m_rotationAndScaleCenter,
|
|
Shinya Kitaoka |
120a6e |
m_transformation[i].m_rotation * t);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
UINT cornerSize = m_transformation[i].m_firstStrokeCornerIndexes.size();
|
|
Shinya Kitaoka |
120a6e |
assert(cornerSize ==
|
|
Shinya Kitaoka |
120a6e |
m_transformation[i].m_secondStrokeCornerIndexes.size());
|
|
Shinya Kitaoka |
120a6e |
if (cornerSize > m_transformation[i].m_secondStrokeCornerIndexes.size())
|
|
Shinya Kitaoka |
120a6e |
cornerSize = m_transformation[i].m_secondStrokeCornerIndexes.size();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(cornerSize >= 2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> controlPoints;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if not m_transformation[i].m_findCorners => detect corner return
|
|
Shinya Kitaoka |
120a6e |
// different size =>cornerSize==2
|
|
Shinya Kitaoka |
120a6e |
// assert(!m_transformation[i].m_findCorners || cornerSize==2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < cornerSize - 1; j++) {
|
|
Shinya Kitaoka |
120a6e |
points.clear();
|
|
Shinya Kitaoka |
120a6e |
subStroke1 = extract(
|
|
Shinya Kitaoka |
120a6e |
stroke1, m_transformation[i].m_firstStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
m_transformation[i].m_firstStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
subStroke2 = extract(
|
|
Shinya Kitaoka |
120a6e |
stroke2, m_transformation[i].m_secondStrokeCornerIndexes[j],
|
|
Shinya Kitaoka |
120a6e |
m_transformation[i].m_secondStrokeCornerIndexes[j + 1] - 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
totalLen1 = subStroke1->getLength();
|
|
Shinya Kitaoka |
120a6e |
totalLen2 = subStroke2->getLength();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (totalLen1 > totalLen2) {
|
|
Shinya Kitaoka |
120a6e |
step1 = step;
|
|
Shinya Kitaoka |
120a6e |
step2 = (totalLen2 / totalLen1) * step;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
step1 = (totalLen1 / totalLen2) * step;
|
|
Shinya Kitaoka |
120a6e |
step2 = step;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
len1 = 0;
|
|
Shinya Kitaoka |
120a6e |
len2 = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (len1 <= totalLen1 && len2 <= totalLen2) {
|
|
Shinya Kitaoka |
120a6e |
point2 = subStroke2->getThickPointAtLength(len2);
|
|
Shinya Kitaoka |
120a6e |
point2 = TThickPoint(m_transformation[i].m_inverse *
|
|
Shinya Kitaoka |
120a6e |
subStroke2->getThickPointAtLength(len2),
|
|
Shinya Kitaoka |
120a6e |
point2.thick);
|
|
Shinya Kitaoka |
120a6e |
finalPoint =
|
|
Shinya Kitaoka |
120a6e |
subStroke1->getThickPointAtLength(len1) * (1 - t) + t * point2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick));
|
|
Shinya Kitaoka |
120a6e |
len1 += step1;
|
|
Shinya Kitaoka |
120a6e |
len2 += step2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
point2 = subStroke2->getThickPointAtLength(totalLen2);
|
|
Shinya Kitaoka |
120a6e |
point2 = TThickPoint(m_transformation[i].m_inverse *
|
|
Shinya Kitaoka |
120a6e |
subStroke2->getThickPointAtLength(totalLen2),
|
|
Shinya Kitaoka |
120a6e |
point2.thick);
|
|
Shinya Kitaoka |
120a6e |
finalPoint = subStroke1->getThickPointAtLength(totalLen1) * (1 - t) +
|
|
Shinya Kitaoka |
120a6e |
t * point2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke = TStroke::interpolate(points, interpolateError, false
|
|
Shinya Kitaoka |
120a6e |
/*m_transformation[i].m_findCorners*/);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (j == 0)
|
|
Shinya Kitaoka |
120a6e |
controlPoints.push_back(stroke->getControlPoint(0));
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
controlPoints.back() =
|
|
Shinya Kitaoka |
120a6e |
(controlPoints.back() + stroke->getControlPoint(0)) * 0.5;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
cpSize = stroke->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
for (cp = 1; cp < cpSize; cp++) {
|
|
Shinya Kitaoka |
120a6e |
controlPoints.push_back(stroke->getControlPoint(cp));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete subStroke1;
|
|
Shinya Kitaoka |
120a6e |
delete subStroke2;
|
|
Shinya Kitaoka |
120a6e |
delete stroke;
|
|
Shinya Kitaoka |
120a6e |
subStroke1 = 0;
|
|
Shinya Kitaoka |
120a6e |
subStroke2 = 0;
|
|
Shinya Kitaoka |
120a6e |
stroke = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke = new TStroke(controlPoints);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (stroke1->isSelfLoop() && stroke2->isSelfLoop()) stroke->setSelfLoop();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
stroke->setStyle(stroke1->getStyle());
|
|
Shinya Kitaoka |
120a6e |
stroke->outlineOptions() = stroke1->outlineOptions();
|
|
Shinya Kitaoka |
120a6e |
VIStroke *vs =
|
|
Shinya Kitaoka |
120a6e |
new VIStroke(stroke, m_firstImage->getVIStroke(i)->m_groupId);
|
|
Shinya Kitaoka |
120a6e |
vi->m_imp->m_strokes.push_back(vs);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} // end for each stroke
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_firstImage->isComputedRegionAlmostOnce()) transferColor(vi);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return vi;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TInbetween::Imp::transferColor(const TVectorImageP &destination) const {
|
|
Shinya Kitaoka |
120a6e |
const TVectorImageP &original = m_firstImage;
|
|
Shinya Kitaoka |
120a6e |
destination->setPalette(original->getPalette());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
destination->findRegions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (destination->getRegionCount()) {
|
|
Shinya Kitaoka |
120a6e |
UINT strokeCount1 = original->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
UINT strokeCount2 = destination->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
if (strokeCount1 > strokeCount2) strokeCount1 = strokeCount2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (UINT i = 0; i < strokeCount1; i++) {
|
|
Shinya Kitaoka |
120a6e |
TVectorImage::transferStrokeColors(original, i, destination, i);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP TInbetween::tween(double t) const { return m_imp->tween(t); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|