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