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
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
double weightedAverage(std::vector<double> &values,</double>
Shinya Kitaoka 120a6e
                       std::vector<double> &weights, 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
  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
Shinya Kitaoka 120a6e
void eraseSmallAngles(std::vector<std::pair<int, double="">> &corners,</std::pair<int,>
Shinya Kitaoka 120a6e
                      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
Toshihiro Shimizu 890ddd
void detectCorners(const TStroke *stroke, double minDegree,
Shinya Kitaoka 120a6e
                   std::vector<std::pair<int, double="">> &corners, double &min,</std::pair<int,>
Shinya Kitaoka 120a6e
                   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
Shinya Kitaoka 120a6e
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
Toshihiro Shimizu 890ddd
void findBestSolution(const TStroke *stroke1, const TStroke *stroke2,
Shinya Kitaoka 120a6e
                      std::pair<int, double=""> *partialAngles1,</int,>
Shinya Kitaoka 120a6e
                      UINT partialAngles1Size,
Shinya Kitaoka 120a6e
                      const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
Shinya Kitaoka 120a6e
                      UINT r,
Shinya Kitaoka 120a6e
                      std::list<std::pair<int, double="">> &partialSolution,</std::pair<int,>
Shinya Kitaoka 120a6e
                      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
Toshihiro Shimizu 890ddd
void findBestSolution(const TStroke *stroke1, const TStroke *stroke2,
Shinya Kitaoka 120a6e
                      std::vector<std::pair<int, double="">> &angles1,</std::pair<int,>
Shinya Kitaoka 120a6e
                      const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
Shinya Kitaoka 120a6e
                      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
Toshihiro Shimizu 890ddd
void trivialSolution(const TStroke *stroke1, const TStroke *stroke2,
Shinya Kitaoka 120a6e
                     const std::vector<std::pair<int, double="">> &angles1,</std::pair<int,>
Shinya Kitaoka 120a6e
                     const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
Shinya Kitaoka 120a6e
                     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
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
void sample(const TStroke *stroke, int samplingSize,
Shinya Kitaoka 120a6e
            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
//-------------------------------------------------------------------