Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcenterlinevectP.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================
Toshihiro Shimizu 890ddd
//      Sequence conversion into TStroke
Toshihiro Shimizu 890ddd
//============================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Globals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
const double Polyg_eps_max = 1;     // Sequence simplification max error
Shinya Kitaoka 120a6e
const double Polyg_eps_mul = 0.75;  // Sequence simpl. thickness-multiplier
Shinya Kitaoka 120a6e
                                    // error
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const double Quad_eps_max =
Shinya Kitaoka 120a6e
    infinity;  // As above, for sequence conversion into strokes
Shinya Kitaoka 120a6e
// const double Quad_eps_mul= 0.2;     //NOTE: Substituted by
Shinya Kitaoka 120a6e
// globals->currConfig->m_penalty
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------
Toshihiro Shimizu 890ddd
//      Simplify Sequences
Toshihiro Shimizu 890ddd
//-------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// EXPLANATION:  Before converting sequences in strokes, we simplify them
Shinya Kitaoka 120a6e
// by eliminating sequence of points which lie on the same straight line,
Shinya Kitaoka 120a6e
// leaving the extremities only.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class SequenceSimplifier {
Shinya Kitaoka 120a6e
  const Sequence *m_s;
Shinya Kitaoka 120a6e
  const SkeletonGraph *m_graph;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  class Length {
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    int n;
Shinya Kitaoka 120a6e
    double l;
Shinya Kitaoka 120a6e
    UINT firstNode, secondNode;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    Length() : n(0), l(0) {}
Shinya Kitaoka 120a6e
    Length(int n_, double l_) : n(n_), l(l_) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    inline void infty(void) {
Shinya Kitaoka 120a6e
      n = infinity;
Shinya Kitaoka 120a6e
      l = infinity;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    inline bool operator<(Length sl) {
Shinya Kitaoka 120a6e
      return n < sl.n ? 1 : n > sl.n ? 0 : l < sl.l ? 1 : 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    inline Length operator+(Length sl) { return Length(n + sl.n, l + sl.l); }
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Length lengthOf(UINT a, UINT aLink, UINT b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  // Methods
Shinya Kitaoka 120a6e
  SequenceSimplifier(const Sequence *s) : m_s(s), m_graph(m_s->m_graphHolder) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void simplify(std::vector<unsigned int=""> &result);</unsigned>
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Bellman algorithm for Sequences
Shinya Kitaoka 120a6e
// NOTE: Circular Sequences are dealt.
Shinya Kitaoka 120a6e
void SequenceSimplifier::simplify(std::vector<unsigned int=""> &result) {</unsigned>
Shinya Kitaoka 120a6e
  // Initialize variables
Shinya Kitaoka 120a6e
  unsigned int n;
Shinya Kitaoka 120a6e
  unsigned int i, j, iLink, jLink;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // NOTE: If s is circular, we have to protect
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  i     = m_s->m_head;
Shinya Kitaoka 120a6e
  iLink = m_s->m_headLink;
Shinya Kitaoka 120a6e
  // NOTE: If m_head==m_tail then we have to force the first step by "|| n==1"
Shinya Kitaoka 120a6e
  for (n = 1; i != m_s->m_tail || n == 1; ++n, m_s->next(i, iLink))
Shinya Kitaoka 120a6e
    ;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Length L_att, L_min, l_min, l_ji;
Shinya Kitaoka 120a6e
  unsigned int p_i, a, b;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<length> M(n);</length>
Shinya Kitaoka 120a6e
  std::vector<length> K(n);</length>
Shinya Kitaoka 120a6e
  std::vector<unsigned int=""> P(n);</unsigned>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Search for minimal path
Shinya Kitaoka 120a6e
  i     = m_s->m_head;
Shinya Kitaoka 120a6e
  iLink = m_s->m_headLink;
Shinya Kitaoka 120a6e
  for (a = 1; i != m_s->m_tail || a == 1; m_s->next(i, iLink), ++a) {
Shinya Kitaoka 120a6e
    L_min.infty();
Shinya Kitaoka 120a6e
    l_min.infty();
Shinya Kitaoka 120a6e
    p_i = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    j                  = m_s->m_head;
Shinya Kitaoka 120a6e
    jLink              = m_s->m_headLink;
Shinya Kitaoka 120a6e
    unsigned int iNext = m_graph->getNode(i).getLink(iLink).getNext();
Shinya Kitaoka 120a6e
    for (b = 0; j != iNext || b == 0; m_s->next(j, jLink), ++b) {
Shinya Kitaoka 120a6e
      if ((L_att = M[b] + (l_ji = lengthOf(j, jLink, iNext))) < L_min) {
Shinya Kitaoka 120a6e
        L_min = L_att;
Shinya Kitaoka 120a6e
        p_i   = b;
Shinya Kitaoka 120a6e
        l_min = l_ji;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    M[a] = L_min;
Shinya Kitaoka 120a6e
    K[a] = l_min;
Shinya Kitaoka 120a6e
    P[a] = p_i;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Copies minimal path found to the output reducedIndices vector
Shinya Kitaoka 120a6e
  // NOTE: size() is added due to circular sequences case handling
Shinya Kitaoka 120a6e
  unsigned int redSize = result.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  result.resize(redSize + M[n - 1].n + 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  result[redSize + M[n - 1].n] = K[n - 1].secondNode;
Shinya Kitaoka 120a6e
  for (b = n - 1, a = redSize + M[n - 1].n - 1; b > 0; b = P[b], --a)
Shinya Kitaoka 120a6e
    result[a] = K[b].firstNode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Length between two sequence points
Shinya Kitaoka 120a6e
SequenceSimplifier::Length SequenceSimplifier::lengthOf(UINT a, UINT aLink,
Shinya Kitaoka 120a6e
                                                        UINT b) {
Shinya Kitaoka 120a6e
  UINT curr, old;
Shinya Kitaoka 120a6e
  T3DPointD v;
Shinya Kitaoka 120a6e
  double d, vv;
Shinya Kitaoka 120a6e
  Length res;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  res.n          = 1;
Shinya Kitaoka 120a6e
  res.firstNode  = a;
Shinya Kitaoka 120a6e
  res.secondNode = b;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  v  = *m_graph->getNode(b) - *m_graph->getNode(a);
Shinya Kitaoka 120a6e
  vv = norm(v);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  curr = m_graph->getNode(a).getLink(aLink).getNext();
Shinya Kitaoka 120a6e
  old  = a;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If the distance between extremities is small, check if the same holds
Shinya Kitaoka 120a6e
  // for internal points; if so, ok - otherwise set infty().
Shinya Kitaoka 120a6e
  if (vv < 0.1) {
Shinya Kitaoka 120a6e
    for (; curr != b; m_s->advance(old, curr)) {
Shinya Kitaoka 120a6e
      d = tdistance(*m_graph->getNode(curr), *m_graph->getNode(a));
Shinya Kitaoka 120a6e
      if (d > 0.1) res.infty();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return res;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Otherwise, check distances from line passing from a and b
Shinya Kitaoka 120a6e
  v = v * (1 / vv);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (; curr != b; m_s->advance(old, curr)) {
Shinya Kitaoka 120a6e
    d = tdistance2(*m_graph->getNode(curr), v, *m_graph->getNode(a));
Shinya Kitaoka 120a6e
    if (d >
Shinya Kitaoka 120a6e
        std::min(m_graph->getNode(curr)->z * Polyg_eps_mul, Polyg_eps_max)) {
Shinya Kitaoka 120a6e
      res.infty();
Shinya Kitaoka 120a6e
      return res;
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      res.l += d;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return res;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===============================
Toshihiro Shimizu 890ddd
//      Sequence conversion
Toshihiro Shimizu 890ddd
//===============================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// EXPLANATION: Sequences convert into TStrokes by applying a SequenceConverter
Shinya Kitaoka 120a6e
//  class. A graph minimal-path algorithm is run by using a
Shinya Kitaoka 120a6e
//  lexicographic-ordered
Toshihiro Shimizu 890ddd
//  (number of quadratics, error) length.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class SequenceConverter {
Shinya Kitaoka 120a6e
  const Sequence *m_s;
Shinya Kitaoka 120a6e
  const SkeletonGraph *m_graph;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double m_penalty;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  // Length construction globals (see 'lengthOf' method)
Shinya Kitaoka 120a6e
  unsigned int middle;
Shinya Kitaoka 120a6e
  std::vector<double> pars;</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  class Length {
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    int n;
Shinya Kitaoka 120a6e
    double l;
Shinya Kitaoka 120a6e
    std::vector<t3dpointd> CPs;</t3dpointd>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    Length() : n(0), l(0) {}
Shinya Kitaoka 120a6e
    Length(int n_, double l_) : n(n_), l(l_) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    inline void infty(void) {
Shinya Kitaoka 120a6e
      n = infinity;
Shinya Kitaoka 120a6e
      l = infinity;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    inline bool operator<(Length sl) {
Shinya Kitaoka 120a6e
      return n < sl.n ? 1 : n > sl.n ? 0 : l < sl.l ? 1 : 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    inline Length operator+(Length sl) { return Length(n + sl.n, l + sl.l); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    void set_CPs(const T3DPointD &a, const T3DPointD &b, const T3DPointD &c) {
Shinya Kitaoka 120a6e
      CPs.resize(3);
Shinya Kitaoka 120a6e
      CPs[0] = a;
Shinya Kitaoka 120a6e
      CPs[1] = b;
Shinya Kitaoka 120a6e
      CPs[2] = c;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    void set_CPs(const T3DPointD &a, const T3DPointD &b, const T3DPointD &c,
Shinya Kitaoka 120a6e
                 const T3DPointD &d, const T3DPointD &e) {
Shinya Kitaoka 120a6e
      CPs.resize(5);
Shinya Kitaoka 120a6e
      CPs[0] = a;
Shinya Kitaoka 120a6e
      CPs[1] = b;
Shinya Kitaoka 120a6e
      CPs[2] = c;
Shinya Kitaoka 120a6e
      CPs[3] = d;
Shinya Kitaoka 120a6e
      CPs[4] = e;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Intermediate Sequence form
Shinya Kitaoka 120a6e
  std::vector<t3dpointd> middleAddedSequence;</t3dpointd>
Shinya Kitaoka 120a6e
  std::vector<unsigned int=""> *inputIndices;</unsigned>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Methods
Shinya Kitaoka 120a6e
  SequenceConverter(const Sequence *s, double penalty)
Shinya Kitaoka 120a6e
      : m_s(s), m_graph(m_s->m_graphHolder), m_penalty(penalty) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Length lengthOf(unsigned int a, unsigned int b);
Shinya Kitaoka 120a6e
  void addMiddlePoints();
Shinya Kitaoka 120a6e
  TStroke *operator()(std::vector<unsigned int=""> *indices);</unsigned>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Length construction methods
Shinya Kitaoka 120a6e
  bool parametrize(unsigned int a, unsigned int b);
Shinya Kitaoka 120a6e
  void lengthOfTriplet(unsigned int i, Length &len);
Shinya Kitaoka 120a6e
  bool calculateCPs(unsigned int i, unsigned int j, Length &len);
Shinya Kitaoka 120a6e
  bool penalty(unsigned int a, unsigned int b, Length &len);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Changes in stroke thickness are considered more penalizating
Shinya Kitaoka 120a6e
inline double ellProd(const T3DPointD &a, const T3DPointD &b) {
Shinya Kitaoka 120a6e
  return a.x * b.x + a.y * b.y + 5 * a.z * b.z;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// EXPLANATION:  After simplification, we receive a vector<uint> of indices</uint>
Shinya Kitaoka 120a6e
// corresponding to the vertices of the simplified current sequence.
Shinya Kitaoka 120a6e
// Before beginning conversion, we need to add middle points between the
Shinya Kitaoka 120a6e
// above vertex points.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
inline void SequenceConverter::addMiddlePoints() {
Shinya Kitaoka 120a6e
  unsigned int i, j, n;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  n = inputIndices->size();
Shinya Kitaoka 120a6e
  middleAddedSequence.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (n == 2) {
Shinya Kitaoka 120a6e
    middleAddedSequence.resize(3);
Shinya Kitaoka 120a6e
    middleAddedSequence[0] = *m_graph->getNode((*inputIndices)[0]);
Shinya Kitaoka 120a6e
    middleAddedSequence[1] = (*m_graph->getNode((*inputIndices)[0]) +
Shinya Kitaoka 120a6e
                              *m_graph->getNode((*inputIndices)[1])) *
Shinya Kitaoka 120a6e
                             0.5;
Shinya Kitaoka 120a6e
    middleAddedSequence[2] = *m_graph->getNode((*inputIndices)[1]);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    middleAddedSequence.resize(2 * n - 3);
Shinya Kitaoka 120a6e
    middleAddedSequence[0] = *m_graph->getNode((*inputIndices)[0]);
Shinya Kitaoka 120a6e
    for (i = j = 1; i < n - 2; ++i, j += 2) {
Shinya Kitaoka 120a6e
      middleAddedSequence[j]     = *m_graph->getNode((*inputIndices)[i]);
Shinya Kitaoka 120a6e
      middleAddedSequence[j + 1] = (*m_graph->getNode((*inputIndices)[i]) +
Shinya Kitaoka 120a6e
                                    *m_graph->getNode((*inputIndices)[i + 1])) *
Shinya Kitaoka 120a6e
                                   0.5;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    middleAddedSequence[j]     = *m_graph->getNode((*inputIndices)[n - 2]);
Shinya Kitaoka 120a6e
    middleAddedSequence[j + 1] = *m_graph->getNode((*inputIndices)[n - 1]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStroke *SequenceConverter::operator()(std::vector<unsigned int=""> *indices) {</unsigned>
Shinya Kitaoka 120a6e
  // Prepare Sequence
Shinya Kitaoka 120a6e
  inputIndices = indices;
Shinya Kitaoka 120a6e
  addMiddlePoints();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Initialize local variables
Shinya Kitaoka 120a6e
  unsigned int n =
Shinya Kitaoka 120a6e
      (middleAddedSequence.size() + 1) / 2;  // Number of middle points
Shinya Kitaoka 120a6e
  // unsigned int i, j;
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  int j;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Length L_att, L_min, l_min, l_ji;
Shinya Kitaoka 120a6e
  unsigned int p_i, a, b;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<length> M(n);</length>
Shinya Kitaoka 120a6e
  std::vector<length> K(n);</length>
Shinya Kitaoka 120a6e
  std::vector<unsigned int=""> P(n);</unsigned>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Bellman algorithm
Shinya Kitaoka 120a6e
  for (i = 2, a = 1; i < middleAddedSequence.size(); i += 2, ++a) {
Shinya Kitaoka 120a6e
    L_min.infty();
Shinya Kitaoka 120a6e
    l_min.infty();
Shinya Kitaoka 120a6e
    p_i = 0;
Shinya Kitaoka 120a6e
    // for(j=0, b=0; j
Shinya Kitaoka 120a6e
    for (j = i - 2, b = j / 2; j >= 0; j -= 2, --b) {
Shinya Kitaoka 120a6e
      if ((L_att = M[b] + (l_ji = lengthOf(j, i))) < L_min) {
Shinya Kitaoka 120a6e
        L_min = L_att;
Shinya Kitaoka 120a6e
        p_i   = b;
Shinya Kitaoka 120a6e
        l_min = l_ji;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      // NOTE: The following else may be taken out to perform a deeper
Shinya Kitaoka 120a6e
      // search for optimal result. However, it prevents quadratic complexities
Shinya Kitaoka 120a6e
      // on large-scale images.
Shinya Kitaoka 120a6e
      else if (l_ji.n == infinity)
Shinya Kitaoka 120a6e
        break;  // Stops searching for current i
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    M[a] = L_min;
Shinya Kitaoka 120a6e
    K[a] = l_min;
Shinya Kitaoka 120a6e
    P[a] = p_i;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Read off the output
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> controlPoints(2 * M[n - 1].n + 1);</tthickpoint>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (b = n - 1, a = 2 * M[n - 1].n; b > 0; b = P[b]) {
Shinya Kitaoka 120a6e
    for (i             = K[b].CPs.size() - 1; i > 0; --i, --a)
Shinya Kitaoka 120a6e
      controlPoints[a] = K[b].CPs[i];
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  controlPoints[0] = middleAddedSequence[0];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TStroke *res = new TStroke(controlPoints);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return res;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------
Toshihiro Shimizu 890ddd
//      Conversion Length build-up
Toshihiro Shimizu 890ddd
//--------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
SequenceConverter::Length SequenceConverter::lengthOf(unsigned int a,
Shinya Kitaoka 120a6e
                                                      unsigned int b) {
Shinya Kitaoka 120a6e
  Length l;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If we have a triplet, apply a specific procedure
Shinya Kitaoka 120a6e
  if (b == a + 2) {
Shinya Kitaoka 120a6e
    lengthOfTriplet(a, l);
Shinya Kitaoka 120a6e
    return l;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // otherwise
Shinya Kitaoka 120a6e
  if (!parametrize(a, b) || !calculateCPs(a, b, l) || !penalty(a, b, l))
Shinya Kitaoka 120a6e
    l.infty();
Shinya Kitaoka 120a6e
  return l;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SequenceConverter::lengthOfTriplet(unsigned int i, Length &len) {
Shinya Kitaoka 120a6e
  T3DPointD A = middleAddedSequence[i];
Shinya Kitaoka 120a6e
  T3DPointD B = middleAddedSequence[i + 1];
Shinya Kitaoka 120a6e
  T3DPointD C = middleAddedSequence[i + 2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // We assume that this convertion is faithful, avoiding length penalty
Shinya Kitaoka 120a6e
  len.l    = 0;
Shinya Kitaoka 120a6e
  double d = tdistance(B, C - A, A);
Shinya Kitaoka 120a6e
  if (d <= 2) {
Shinya Kitaoka 120a6e
    len.n = 1;
Shinya Kitaoka 120a6e
    len.set_CPs(A, B, C);
Shinya Kitaoka 120a6e
  } else if (d <= 6) {
Shinya Kitaoka 120a6e
    len.n       = 2;
Shinya Kitaoka 120a6e
    d           = (d - 1) / d;
Shinya Kitaoka 120a6e
    T3DPointD U = A + d * (B - A), V = C + d * (B - C);
Shinya Kitaoka 120a6e
    len.set_CPs(A, U, (U + V) * 0.5, V, C);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    len.n = 2;
Shinya Kitaoka 120a6e
    len.set_CPs(A, (A + B) * 0.5, B, (B + C) * 0.5, C);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool SequenceConverter::parametrize(unsigned int a, unsigned int b) {
Shinya Kitaoka 120a6e
  unsigned int curr, old;
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  double w, t;
Shinya Kitaoka 120a6e
  double den;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  pars.clear();
Shinya Kitaoka 120a6e
  pars.push_back(0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (old = a, curr = a + 1, den = 0; curr < b; old = curr, curr += 2) {
Shinya Kitaoka 120a6e
    w = norm(middleAddedSequence[curr] - middleAddedSequence[old]);
Shinya Kitaoka 120a6e
    den += w;
Shinya Kitaoka 120a6e
    pars.push_back(w);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  w = norm(middleAddedSequence[b] - middleAddedSequence[old]);
Shinya Kitaoka 120a6e
  den += w;
Shinya Kitaoka 120a6e
  pars.push_back(w);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (den < 0.1) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (i = 1, t = 0; i < pars.size(); ++i) {
Shinya Kitaoka 120a6e
    t += 2 * pars[i] / den;
Shinya Kitaoka 120a6e
    pars[i] = t;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Seek the interval which holds 1 - the middle interval
Shinya Kitaoka 120a6e
  for (middle = 0; middle < pars.size() && pars[middle + 1] <= 1; ++middle)
Shinya Kitaoka 120a6e
    ;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
//    CP construcion
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// NOTE: Check my thesis for variable meanings (int_ stands for 'integral').
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Some integrals (int_) for the CP linear system resolution
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline T3DPointD int_H(const T3DPointD &A, const T3DPointD &B, double t1,
Shinya Kitaoka 120a6e
                       double t2) {
Shinya Kitaoka 120a6e
  return -(0.375 * (pow(t2, 4) - pow(t1, 4))) * B +
Shinya Kitaoka 120a6e
         (pow(t2, 3) - pow(t1, 3)) * (B * 0.6667 - A * 0.5) +
Shinya Kitaoka 120a6e
         (pow(t2, 2) - pow(t1, 2)) * A;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline T3DPointD int_K(const T3DPointD &A, const T3DPointD &B, double t1,
Shinya Kitaoka 120a6e
                       double t2) {
Shinya Kitaoka 120a6e
  return (pow(t2, 4) - pow(t1, 4)) * (B * 0.125) +
Shinya Kitaoka 120a6e
         (pow(t2, 3) - pow(t1, 3)) * (A * 0.1667);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool SequenceConverter::calculateCPs(unsigned int i, unsigned int j,
Shinya Kitaoka 120a6e
                                     Length &len) {
Shinya Kitaoka 120a6e
  unsigned int curr, old;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine M;
Shinya Kitaoka 120a6e
  TPointD l;
Shinya Kitaoka 120a6e
  T3DPointD a, e, x, y, A, B;
Shinya Kitaoka 120a6e
  T3DPointD IH, IK, IM, IN_;  //"IN" seems to be reserved word
Shinya Kitaoka 120a6e
  double HxL, KyL, MxO, NyO;
Shinya Kitaoka 120a6e
  unsigned int k;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  a = middleAddedSequence[i];
Shinya Kitaoka 120a6e
  e = middleAddedSequence[j];
Shinya Kitaoka 120a6e
  x = middleAddedSequence[i + 1] - a;
Shinya Kitaoka 120a6e
  y = middleAddedSequence[j - 1] - e;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build TAffine M
Shinya Kitaoka 120a6e
  double par = ellProd(x, y) / 5;
Shinya Kitaoka 120a6e
  M          = TAffine(ellProd(x, x) / 3, par, 0, par, ellProd(y, y) / 3, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Costruisco il termine noto b:
Shinya Kitaoka 120a6e
  // Calculate polygonal integrals
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Integral from 0.0 to 1.0
Shinya Kitaoka 120a6e
  for (k = 0, old = i, curr = i + 1; k < middle; ++k, old = curr, curr += 2) {
Shinya Kitaoka 120a6e
    B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
        (1 / (pars[k + 1] - pars[k]));
Shinya Kitaoka 120a6e
    A = middleAddedSequence[old] - pars[k] * B;
Shinya Kitaoka 120a6e
    IH += int_H(A, B, pars[k], pars[k + 1]);
Shinya Kitaoka 120a6e
    IK += int_K(A, B, pars[k], pars[k + 1]);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (curr == j + 1) curr = j;
Shinya Kitaoka 120a6e
  B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
      (1 / (pars[k + 1] - pars[k]));
Shinya Kitaoka 120a6e
  A = middleAddedSequence[old] - pars[k] * B;
Shinya Kitaoka 120a6e
  IH += int_H(A, B, pars[k], 1.0);
Shinya Kitaoka 120a6e
  IK += int_K(A, B, pars[k], 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Integral from 1.0 to 2.0
Shinya Kitaoka 120a6e
  for (k = pars.size() - 1, old = j, curr = j - 1; k > middle + 1;
Shinya Kitaoka 120a6e
       --k, old = curr, curr -= 2) {
Shinya Kitaoka 120a6e
    B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
        (1 / (pars[k] - pars[k - 1]));
Shinya Kitaoka 120a6e
    A = middleAddedSequence[curr] - (2 - pars[k - 1]) * B;
Shinya Kitaoka 120a6e
    IM += int_K(A, B, 2 - pars[k], 2 - pars[k - 1]);
Shinya Kitaoka 120a6e
    IN_ += int_H(A, B, 2 - pars[k], 2 - pars[k - 1]);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (old == i + 1) curr = i;
Shinya Kitaoka 120a6e
  B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
      (1 / (pars[k] - pars[k - 1]));
Shinya Kitaoka 120a6e
  A = middleAddedSequence[curr] - (2 - pars[k - 1]) * B;
Shinya Kitaoka 120a6e
  IM += int_K(A, B, 2 - pars[k], 1.0);
Shinya Kitaoka 120a6e
  IN_ += int_H(A, B, 2 - pars[k], 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Polygonal-free integrals
Shinya Kitaoka 120a6e
  T3DPointD f = (a + e) * 0.5;
Shinya Kitaoka 120a6e
  HxL         = (ellProd(a, x) * 0.3) + (ellProd(f, x) / 5.0);
Shinya Kitaoka 120a6e
  NyO         = (ellProd(e, y) * 0.3) + (ellProd(f, y) / 5.0);
Shinya Kitaoka 120a6e
  KyL         = (ellProd(a, y) / 15.0) + (ellProd(f, y) / 10.0);
Shinya Kitaoka 120a6e
  MxO         = ((e * x) / 15.0) + (ellProd(f, x) / 10.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Infine, ho il termine noto
Shinya Kitaoka 120a6e
  l = TPointD(ellProd(IH, x) - HxL + ellProd(IM, x) - MxO,
Shinya Kitaoka 120a6e
              ellProd(IK, y) - KyL + ellProd(IN_, y) - NyO);
Shinya Kitaoka 120a6e
  M.a13 = -l.x;
Shinya Kitaoka 120a6e
  M.a23 = -l.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Check validity conditions:
Shinya Kitaoka 120a6e
  //  a) System is not singular
Shinya Kitaoka 120a6e
  if (fabs(M.det()) < 0.01) return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  M = M.inv();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  b) Shift (solution) is positive
Shinya Kitaoka 120a6e
  if (M.a13 < 0 || M.a23 < 0) return 0;
Shinya Kitaoka 120a6e
  T3DPointD b = a + M.a13 * x;
Shinya Kitaoka 120a6e
  T3DPointD d = e + M.a23 * y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  c) The height of every CP must be >=0
Shinya Kitaoka 120a6e
  if (b.z < 0 || d.z < 0) return 0;
Shinya Kitaoka 120a6e
  len.set_CPs(a, b, (b + d) * 0.5, d, e);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
//      Penalties
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline T3DPointD int_B0a(const T3DPointD &A, const T3DPointD &B, double t1,
Shinya Kitaoka 120a6e
                         double t2) {
Shinya Kitaoka 120a6e
  return (0.25 * (pow(t2, 4) - pow(t1, 4))) * B +
Shinya Kitaoka 120a6e
         ((pow(t2, 3) - pow(t1, 3)) / 3.0) * (A - 2.0 * B) +
Shinya Kitaoka 120a6e
         (0.5 * (pow(t2, 2) - pow(t1, 2))) * (B - 2.0 * A) + (t2 - t1) * A;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline T3DPointD int_B1a(const T3DPointD &A, const T3DPointD &B, double t1,
Shinya Kitaoka 120a6e
                         double t2) {
Shinya Kitaoka 120a6e
  return -(0.5 * (pow(t2, 4) - pow(t1, 4))) * B +
Shinya Kitaoka 120a6e
         (2.0 * ((pow(t2, 3) - pow(t1, 3)) / 3.0) * (B - A) +
Shinya Kitaoka 120a6e
          (pow(t2, 2) - pow(t1, 2)) * A);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline T3DPointD int_B2a(const T3DPointD &A, const T3DPointD &B, double t1,
Shinya Kitaoka 120a6e
                         double t2) {
Shinya Kitaoka 120a6e
  return (0.25 * (pow(t2, 4) - pow(t1, 4))) * B +
Shinya Kitaoka 120a6e
         ((pow(t2, 3) - pow(t1, 3)) / 3.0) * A;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double int_a2(const T3DPointD &A, const T3DPointD &B, double t1,
Shinya Kitaoka 120a6e
                     double t2) {
Shinya Kitaoka 120a6e
  return ellProd(A, A) * (t2 - t1) + ellProd(A, B) * (pow(t2, 2) - pow(t1, 2)) +
Shinya Kitaoka 120a6e
         (ellProd(B, B) * (pow(t2, 3) - pow(t1, 3)) / 3.0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Penalty is the integral of the square norm of differences between polygonal
Shinya Kitaoka 120a6e
// and quadratics.
Shinya Kitaoka 120a6e
bool SequenceConverter::penalty(unsigned int a, unsigned int b, Length &len) {
Shinya Kitaoka 120a6e
  unsigned int curr, old;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const std::vector<t3dpointd> &CPs = len.CPs;</t3dpointd>
Shinya Kitaoka 120a6e
  T3DPointD A, B, P0, P1, P2;
Shinya Kitaoka 120a6e
  double p, p_max;
Shinya Kitaoka 120a6e
  unsigned int k;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  len.n = 2;  // A couple of arcs
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Prepare max penalty p_max
Shinya Kitaoka 120a6e
  p_max = 0;
Shinya Kitaoka 120a6e
  for (curr = a + 1, old = a, k = 0; curr < b; ++k, old = curr, curr += 2) {
Shinya Kitaoka 120a6e
    p_max += (middleAddedSequence[curr].z + middleAddedSequence[old].z) *
Shinya Kitaoka 120a6e
             (pars[k + 1] - pars[k]) / 2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  p_max += (middleAddedSequence[b].z + middleAddedSequence[old].z) *
Shinya Kitaoka 120a6e
           (pars[k + 1] - pars[k]) / 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Confronting 4th power of error with mean polygonal thickness
Shinya Kitaoka 120a6e
  // - can be changed
Shinya Kitaoka 120a6e
  p_max = std::min(sqrt(p_max) * m_penalty, Quad_eps_max);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // CP only integral
Shinya Kitaoka 120a6e
  p = (ellProd(CPs[0], CPs[0]) + 2 * ellProd(CPs[2], CPs[2]) +
Shinya Kitaoka 120a6e
       ellProd(CPs[4], CPs[4]) + ellProd(CPs[0], CPs[1]) +
Shinya Kitaoka 120a6e
       ellProd(CPs[1], CPs[2]) + ellProd(CPs[2], CPs[3]) +
Shinya Kitaoka 120a6e
       ellProd(CPs[3], CPs[4])) /
Shinya Kitaoka 120a6e
          5.0 +
Shinya Kitaoka 120a6e
      (2 * (ellProd(CPs[1], CPs[1]) + ellProd(CPs[3], CPs[3])) +
Shinya Kitaoka 120a6e
       ellProd(CPs[0], CPs[2]) + ellProd(CPs[2], CPs[4])) /
Shinya Kitaoka 120a6e
          15.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Penalty from 0.0 to 1.0
Shinya Kitaoka 120a6e
  P0 = P1 = P2 = T3DPointD();
Shinya Kitaoka 120a6e
  for (k = 0, old = a, curr = a + 1; k < middle; ++k, old = curr, curr += 2) {
Shinya Kitaoka 120a6e
    B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
        (1 / (pars[k + 1] - pars[k]));
Shinya Kitaoka 120a6e
    A = middleAddedSequence[old] - pars[k] * B;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Mixed integral
Shinya Kitaoka 120a6e
    P0 += int_B0a(A, B, pars[k], pars[k + 1]);
Shinya Kitaoka 120a6e
    P1 += int_B1a(A, B, pars[k], pars[k + 1]);
Shinya Kitaoka 120a6e
    P2 += int_B2a(A, B, pars[k], pars[k + 1]);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Sequence integral
Shinya Kitaoka 120a6e
    p += int_a2(A, B, pars[k], pars[k + 1]);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (curr == b + 1) curr = b;
Shinya Kitaoka 120a6e
  B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
      (1 / (pars[k + 1] - pars[k]));
Shinya Kitaoka 120a6e
  A = middleAddedSequence[old] - pars[k] * B;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Mixed integral
Shinya Kitaoka 120a6e
  P0 += int_B0a(A, B, pars[k], 1.0);
Shinya Kitaoka 120a6e
  P1 += int_B1a(A, B, pars[k], 1.0);
Shinya Kitaoka 120a6e
  P2 += int_B2a(A, B, pars[k], 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Sequence integral
Shinya Kitaoka 120a6e
  p += int_a2(A, B, pars[k], 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  p -= 2 * (ellProd(P0, CPs[0]) + ellProd(P1, CPs[1]) + ellProd(P2, CPs[2]));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Penalty from 1.0 to 2.0
Shinya Kitaoka 120a6e
  P0 = P1 = P2 = T3DPointD();
Shinya Kitaoka 120a6e
  for (k = pars.size() - 1, old = b, curr = b - 1; k > middle + 1;
Shinya Kitaoka 120a6e
       --k, old = curr, curr -= 2) {
Shinya Kitaoka 120a6e
    B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
        (1 / (pars[k] - pars[k - 1]));
Shinya Kitaoka 120a6e
    A = middleAddedSequence[curr] - (2 - pars[k - 1]) * B;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Mixed integral
Shinya Kitaoka 120a6e
    P0 += int_B0a(A, B, 2 - pars[k], 2 - pars[k - 1]);
Shinya Kitaoka 120a6e
    P1 += int_B1a(A, B, 2 - pars[k], 2 - pars[k - 1]);
Shinya Kitaoka 120a6e
    P2 += int_B2a(A, B, 2 - pars[k], 2 - pars[k - 1]);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Sequence integral
Shinya Kitaoka 120a6e
    p += int_a2(A, B, 2 - pars[k], 2 - pars[k - 1]);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (old == a + 1) curr = a;
Shinya Kitaoka 120a6e
  B = (middleAddedSequence[curr] - middleAddedSequence[old]) *
Shinya Kitaoka 120a6e
      (1 / (pars[k] - pars[k - 1]));
Shinya Kitaoka 120a6e
  A = middleAddedSequence[curr] - (2 - pars[k - 1]) * B;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Mixed integral
Shinya Kitaoka 120a6e
  P0 += int_B0a(A, B, 2 - pars[k], 1.0);
Shinya Kitaoka 120a6e
  P1 += int_B1a(A, B, 2 - pars[k], 1.0);
Shinya Kitaoka 120a6e
  P2 += int_B2a(A, B, 2 - pars[k], 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Sequence integral
Shinya Kitaoka 120a6e
  p += int_a2(A, B, 2 - pars[k], 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  p -= 2 * (ellProd(P0, CPs[4]) + ellProd(P1, CPs[3]) + ellProd(P2, CPs[2]));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // OCCHIO! Ho visto ancora qualche p<0! Da rivedere - non dovrebbe...
Shinya Kitaoka 120a6e
  if (p > p_max || p < 0)
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    len.l = p;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------
Toshihiro Shimizu 890ddd
//      Convertion Mains
Toshihiro Shimizu 890ddd
//-----------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TStroke *convert(const Sequence &s, double penalty) {
Shinya Kitaoka 120a6e
  SkeletonGraph *graph = s.m_graphHolder;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TStroke *result;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // First, we simplify the skeleton sequences found
Shinya Kitaoka 120a6e
  std::vector<unsigned int=""> reducedIndices;</unsigned>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // NOTE: If s is circular, we have to protect head==tail 's adjacent nodes.
Shinya Kitaoka 120a6e
  // We then move away s tail and head, and insert them in the reducedIndices
Shinya Kitaoka 120a6e
  // apart from simplification.
Shinya Kitaoka 120a6e
  if (s.m_head == s.m_tail && graph->getNode(s.m_head).degree() == 2) {
Shinya Kitaoka 120a6e
    Sequence t = s;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    SequenceSimplifier simplifier(&t);
Shinya Kitaoka 120a6e
    reducedIndices.push_back(s.m_head);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    t.m_head     = graph->getNode(s.m_head).getLink(0).getNext();
Shinya Kitaoka 120a6e
    t.m_headLink = !graph->getNode(t.m_head).linkOfNode(s.m_head);
Shinya Kitaoka 120a6e
    t.m_tail     = graph->getNode(s.m_tail).getLink(1).getNext();
Shinya Kitaoka 120a6e
    t.m_tailLink = !graph->getNode(t.m_tail).linkOfNode(s.m_tail);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    simplifier.simplify(reducedIndices);
Shinya Kitaoka 120a6e
    reducedIndices.push_back(s.m_tail);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    SequenceSimplifier simplifier(&s);
Shinya Kitaoka 120a6e
    simplifier.simplify(reducedIndices);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // For segments, apply this immediate conversion
Shinya Kitaoka 120a6e
  if (reducedIndices.size() == 2) {
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> segment(3);</tthickpoint>
Shinya Kitaoka 120a6e
    segment[0] = *graph->getNode(s.m_head);
Shinya Kitaoka 120a6e
    segment[1] = (*graph->getNode(s.m_head) + *graph->getNode(s.m_tail)) * 0.5;
Shinya Kitaoka 120a6e
    segment[2] = *graph->getNode(s.m_tail);
Shinya Kitaoka 120a6e
    return new TStroke(segment);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Then, we convert the sequence in a quadratic stroke
Shinya Kitaoka 120a6e
  SequenceConverter converter(&s, penalty);
Shinya Kitaoka 120a6e
  result = converter(&reducedIndices);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If it is a circular stroke, setSelfLoop
Shinya Kitaoka 120a6e
  // NOTA: Sembra che pero' in questo modo non venga assegnato colore al confine
Shinya Kitaoka 120a6e
  // con la cornice!!!
Shinya Kitaoka 120a6e
  //        => Solo nel caso outline...?
Shinya Kitaoka 120a6e
  // NOTA: Considera anche che pure le outline possono essere splittate per la
Shinya Kitaoka 120a6e
  // colorazione!!
Shinya Kitaoka 120a6e
  // if(globals->currConfig->m_maxThickness == 0.0 && s.m_head == s.m_tail &&
Shinya Kitaoka 120a6e
  // s.m_graphHolder->getNode(s.m_head).degree() == 2)
Shinya Kitaoka 120a6e
  // //globals->currConfig->m_outline
Shinya Kitaoka 120a6e
  //  result->setSelfLoop(true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Pass the SkeletonArc::SS_OUTLINE attribute to the output stroke
Shinya Kitaoka 120a6e
  if (graph->getNode(s.m_head)
Shinya Kitaoka 120a6e
          .getLink(s.m_headLink)
Shinya Kitaoka 120a6e
          ->hasAttribute(SkeletonArc::SS_OUTLINE))
Shinya Kitaoka 120a6e
    result->setFlag(SkeletonArc::SS_OUTLINE, true);
Shinya Kitaoka 120a6e
  else if (graph->getNode(s.m_head)
Shinya Kitaoka 120a6e
               .getLink(s.m_headLink)
Shinya Kitaoka 120a6e
               ->hasAttribute(SkeletonArc::SS_OUTLINE_REVERSED))
Shinya Kitaoka 120a6e
    result->setFlag(SkeletonArc::SS_OUTLINE_REVERSED, true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Converts each forward or single Sequence of the image in its corresponding
Shinya Kitaoka 120a6e
// TStroke. Output is a vector<tstroke*>* whose ownership belongs to the user.</tstroke*>
Shinya Kitaoka 120a6e
// This allow sorts on the TStroke vector *before* adding any stroke to the
Shinya Kitaoka 120a6e
// output TVectorImage.
Shinya Kitaoka 120a6e
// std::vector<tstroke*>* conversionToStrokes(void)</tstroke*>
Shinya Kitaoka 120a6e
void conversionToStrokes(std::vector<tstroke *=""> &strokes,</tstroke>
Shinya Kitaoka 120a6e
                         VectorizerCoreGlobals &g) {
Shinya Kitaoka 120a6e
  SequenceList &singleSequences           = g.singleSequences;
Shinya Kitaoka 120a6e
  JointSequenceGraphList &organizedGraphs = g.organizedGraphs;
Shinya Kitaoka 120a6e
  double penalty                          = g.currConfig->m_penalty;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  unsigned int i, j, k;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Convert single sequences
Shinya Kitaoka 120a6e
  for (i = 0; i < singleSequences.size(); ++i) {
Shinya Kitaoka 120a6e
    if (singleSequences[i].m_head == singleSequences[i].m_tail) {
Shinya Kitaoka 120a6e
      // If the sequence is circular, move your endpoints to an edge middle, in
Shinya Kitaoka 120a6e
      // order
Shinya Kitaoka 120a6e
      // to allow a soft junction
Shinya Kitaoka 120a6e
      SkeletonGraph *currGraph = singleSequences[i].m_graphHolder;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned int head     = singleSequences[i].m_head;
Shinya Kitaoka 120a6e
      unsigned int headLink = singleSequences[i].m_headLink;
Shinya Kitaoka 120a6e
      unsigned int next = currGraph->getNode(head).getLink(headLink).getNext();
Shinya Kitaoka 120a6e
      unsigned int nextLink = currGraph->getNode(next).linkOfNode(head);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      unsigned int addedNode = singleSequences[i].m_graphHolder->newNode(
Shinya Kitaoka 120a6e
          (*currGraph->getNode(head) + *currGraph->getNode(next)) * 0.5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      singleSequences[i].m_graphHolder->insert(addedNode, head, headLink);
Shinya Kitaoka 120a6e
      *singleSequences[i].m_graphHolder->node(addedNode).link(0) =
Shinya Kitaoka 120a6e
          *singleSequences[i].m_graphHolder->node(head).link(headLink);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      singleSequences[i].m_graphHolder->insert(addedNode, next, nextLink);
Shinya Kitaoka 120a6e
      *singleSequences[i].m_graphHolder->node(addedNode).link(1) =
Shinya Kitaoka 120a6e
          *singleSequences[i].m_graphHolder->node(next).link(nextLink);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      singleSequences[i].m_head     = addedNode;
Shinya Kitaoka 120a6e
      singleSequences[i].m_headLink = 0;
Shinya Kitaoka 120a6e
      singleSequences[i].m_tail     = addedNode;
Shinya Kitaoka 120a6e
      singleSequences[i].m_tailLink = 1;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    strokes.push_back(convert(singleSequences[i], penalty));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Convert graph sequences
Shinya Kitaoka 120a6e
  for (i = 0; i < organizedGraphs.size(); ++i)
Shinya Kitaoka 120a6e
    for (j = 0; j < organizedGraphs[i].getNodesCount(); ++j)
Shinya Kitaoka 120a6e
      if (!organizedGraphs[i].getNode(j).hasAttribute(
Shinya Kitaoka 120a6e
              JointSequenceGraph::ELIMINATED))
Shinya Kitaoka 120a6e
        // Otherwise eliminated by junction recovery
Shinya Kitaoka 120a6e
        for (k = 0; k < organizedGraphs[i].getNode(j).getLinksCount(); ++k) {
Shinya Kitaoka 120a6e
          // A sequence is taken at both extremities in our organized graphs
Shinya Kitaoka 120a6e
          if (organizedGraphs[i].getNode(j).getLink(k)->isForward())
Shinya Kitaoka 120a6e
            strokes.push_back(
Shinya Kitaoka 120a6e
                convert(*organizedGraphs[i].getNode(j).getLink(k), penalty));
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
}