|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
#define _STLP_DEBUG 1
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
#include <tcurves.h></tcurves.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <tstroke.h></tstroke.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <tmathutil.h></tmathutil.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <tcurveutil.h></tcurveutil.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <tgl.h></tgl.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <set></set>
|
|
Toshihiro Shimizu |
890ddd |
#include <iterator></iterator>
|
|
Toshihiro Shimizu |
890ddd |
// please do not move, it is necessary to be the last
|
|
Toshihiro Shimizu |
890ddd |
// to work properely with DVAPI macro
|
|
Toshihiro Shimizu |
890ddd |
#include "ext/ExtUtil.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// just to override assert
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
#define EXT_NORMALIZE(a) norm2(a) != 0.0 ? normalize(a) : a
|
|
Toshihiro Shimizu |
890ddd |
#define DEBUG_EXPORT DVAPI
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#define EXT_NORMALIZE(a) normalize(a)
|
|
Toshihiro Shimizu |
890ddd |
#define DEBUG_EXPORT static
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline bool
|
|
Toshihiro Shimizu |
890ddd |
isWGood(double first,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
double second,
|
|
Toshihiro Shimizu |
890ddd |
const TStroke *s)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(first) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(second) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(w))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (s) {
|
|
Toshihiro Shimizu |
890ddd |
if (s->isSelfLoop())
|
|
Toshihiro Shimizu |
890ddd |
if (first > second) {
|
|
Toshihiro Shimizu |
890ddd |
if ((first < w && w <= 1.0) ||
|
|
Toshihiro Shimizu |
890ddd |
(0.0 <= w && w < second))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
} else if (first == second) {
|
|
Toshihiro Shimizu |
890ddd |
if (areAlmostEqual(w, first))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (first < w && w < second)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline int normalizeAngle(int angle)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (angle < 0)
|
|
Toshihiro Shimizu |
890ddd |
angle = -angle;
|
|
Toshihiro Shimizu |
890ddd |
return angle %= 181;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getStrokeId(const TStroke *s,
|
|
Toshihiro Shimizu |
890ddd |
const TVectorImageP &vi)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(s) ||
|
|
Toshihiro Shimizu |
890ddd |
!vi)
|
|
Toshihiro Shimizu |
890ddd |
return -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
count = vi->getStrokeCount();
|
|
Toshihiro Shimizu |
890ddd |
if (!count)
|
|
Toshihiro Shimizu |
890ddd |
return -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (count--) {
|
|
Toshihiro Shimizu |
890ddd |
if (s == vi->getStroke(count))
|
|
Toshihiro Shimizu |
890ddd |
return count;
|
|
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 |
* Verify if a curve is a "almost" point.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Toshihiro Shimizu |
890ddd |
bool isImproper(const T *tq)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
v1 = tq->getP0() - tq->getP1(),
|
|
Toshihiro Shimizu |
890ddd |
v2 = tq->getP2() - tq->getP1();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (isAlmostZero(norm2(v1)) &&
|
|
Toshihiro Shimizu |
890ddd |
isAlmostZero(norm2(v2)))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool areParallel(const TPointD &v1,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &v2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
res = cross(EXT_NORMALIZE(v1), EXT_NORMALIZE(v2));
|
|
Toshihiro Shimizu |
890ddd |
if (isAlmostZero(res))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool areInSameDirection(const TPointD &v1,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &v2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (v1 * v2 >= 0)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/**
|
|
Toshihiro Shimizu |
890ddd |
* Verify if a curve is a straight line.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Toshihiro Shimizu |
890ddd |
bool curveIsStraight(const T *tq,
|
|
Toshihiro Shimizu |
890ddd |
double &t)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
t = -1;
|
|
Toshihiro Shimizu |
890ddd |
assert(tq);
|
|
Toshihiro Shimizu |
890ddd |
if (!tq)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD v1 = tq->getP1() - tq->getP0();
|
|
Toshihiro Shimizu |
890ddd |
TPointD v2 = tq->getP2() - tq->getP1();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
res = cross(v1, v2);
|
|
Toshihiro Shimizu |
890ddd |
if (isAlmostZero(res)) {
|
|
Toshihiro Shimizu |
890ddd |
if (v1 * v2 < 0) {
|
|
Toshihiro Shimizu |
890ddd |
t = tq->getT(tq->getP1());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/**
|
|
Toshihiro Shimizu |
890ddd |
* Verify if junction between two curves, is smooth.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Toshihiro Shimizu |
890ddd |
bool corner(const T *q1,
|
|
Toshihiro Shimizu |
890ddd |
const T *q2,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!q1 ||
|
|
Toshihiro Shimizu |
890ddd |
!q2 ||
|
|
Toshihiro Shimizu |
890ddd |
!areAlmostEqual(q1->getP2(),
|
|
Toshihiro Shimizu |
890ddd |
q2->getP0()))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// really near to the extremes
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
//pnt = q1->getP2(),
|
|
Toshihiro Shimizu |
890ddd |
v1 = q1->getSpeed(1.0), //q1->getPoint(1.0-TConsts::epsilon) - pnt,
|
|
Toshihiro Shimizu |
890ddd |
v2 = q2->getSpeed(0.0); //q2->getPoint(TConsts::epsilon) - pnt;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
v1 = EXT_NORMALIZE(v1);
|
|
Toshihiro Shimizu |
890ddd |
v2 = EXT_NORMALIZE(v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
res = cross(v1, v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!isAlmostZero(res, tolerance))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int detectStraightIntervals_(const TThickQuadratic *ttq,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &intervals,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ttq)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
v0 = ttq->getP1() - ttq->getP0(),
|
|
Toshihiro Shimizu |
890ddd |
v1 = ttq->getP2() - ttq->getP1();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
v0_norm2 = norm(v0),
|
|
Toshihiro Shimizu |
890ddd |
v1_norm2 = norm(v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (v0_norm2 != 0.0)
|
|
Toshihiro Shimizu |
890ddd |
v0 = v0 * (1.0 / v0_norm2);
|
|
Toshihiro Shimizu |
890ddd |
if (v1_norm2 != 0.0)
|
|
Toshihiro Shimizu |
890ddd |
v1 = v1 * (1.0 / v1_norm2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
v0xv1 = v0 * v1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (v0xv1 == 0.0 &&
|
|
Toshihiro Shimizu |
890ddd |
v0_norm2 == 0.0 &&
|
|
Toshihiro Shimizu |
890ddd |
v1_norm2 == 0.0) // null value with all zero
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (isAlmostZero(cross(v0, v1) /*,tolerance*/)) {
|
|
Toshihiro Shimizu |
890ddd |
if (v0xv1 >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(ToonzExt::Interval(0.0, 1.0));
|
|
Toshihiro Shimizu |
890ddd |
return 1;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
t = ttq->getT(ttq->getP1());
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(ToonzExt::Interval(0.0, t));
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(ToonzExt::Interval(t, 1.0));
|
|
Toshihiro Shimizu |
890ddd |
return 2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
// need to be analysed
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
pixelSize = 1.0;
|
|
Toshihiro Shimizu |
890ddd |
#ifndef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
pixelSize = sqrt(tglGetPixelSize2());
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
step = computeStep(*ttq,
|
|
Toshihiro Shimizu |
890ddd |
pixelSize);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//assert( step < 1.0 );
|
|
Toshihiro Shimizu |
890ddd |
if( step > 1.0 )
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
t = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
pnt ,
|
|
Toshihiro Shimizu |
890ddd |
p0 = ttq->getP0(),
|
|
Toshihiro Shimizu |
890ddd |
pn;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
last_interval(-1,-1),
|
|
Toshihiro Shimizu |
890ddd |
curr_interval;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pnt = ttq->getPoint(step);
|
|
Toshihiro Shimizu |
890ddd |
v0 = pnt - p0;
|
|
Toshihiro Shimizu |
890ddd |
if( t+step < 1.0)
|
|
Toshihiro Shimizu |
890ddd |
pn = ttq->getPoint( step+step );
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
pn = ttq->getP2();
|
|
Toshihiro Shimizu |
890ddd |
v1 = pn - pnt;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
v0 = EXT_NORMALIZE(v0);
|
|
Toshihiro Shimizu |
890ddd |
v1 = EXT_NORMALIZE(v1);
|
|
Toshihiro Shimizu |
890ddd |
if( isAlmostZero( cross(v0,v1), tolerance ) )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert( v0*v1 >0);
|
|
Toshihiro Shimizu |
890ddd |
last_interval.first = ttq->getT(p0);
|
|
Toshihiro Shimizu |
890ddd |
last_interval.second= ttq->getT(pn);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
p0 = pn;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for(t=2.0*step;
|
|
Toshihiro Shimizu |
890ddd |
t<1.0;
|
|
Toshihiro Shimizu |
890ddd |
t+=2.0*step)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
pnt = ttq->getPoint(t);
|
|
Toshihiro Shimizu |
890ddd |
v0 = pnt - p0;
|
|
Toshihiro Shimizu |
890ddd |
if( t+step < 1.0)
|
|
Toshihiro Shimizu |
890ddd |
pn = ttq->getPoint( t+step );
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
pn = ttq->getP2();
|
|
Toshihiro Shimizu |
890ddd |
v1 = pn - pnt;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
v0 = EXT_NORMALIZE(v0);
|
|
Toshihiro Shimizu |
890ddd |
v1 = EXT_NORMALIZE(v1);
|
|
Toshihiro Shimizu |
890ddd |
if( isAlmostZero( cross(v0,v1), tolerance ) )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//assert( v0 * v1 > 0 );
|
|
Toshihiro Shimizu |
890ddd |
curr_interval.first = ttq->getT(p0);
|
|
Toshihiro Shimizu |
890ddd |
curr_interval.second = ttq->getT(pn);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if( curr_interval.first != last_interval.second ||
|
|
Toshihiro Shimizu |
890ddd |
v0 * v1 < 0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(last_interval);
|
|
Toshihiro Shimizu |
890ddd |
last_interval.first =
|
|
Toshihiro Shimizu |
890ddd |
last_interval.second = curr_interval.second;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
last_interval.second = curr_interval.second;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// for quadratic is not possible
|
|
Toshihiro Shimizu |
890ddd |
std::swap(p0,pn);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pn=ttq->getP2();
|
|
Toshihiro Shimizu |
890ddd |
v1 = pn - pnt;
|
|
Toshihiro Shimizu |
890ddd |
if( isAlmostZero( cross(v0,v1), tolerance ) )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if( v0 * v1 > 0 )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
curr_interval.first = ttq->getT(p0);
|
|
Toshihiro Shimizu |
890ddd |
curr_interval.second = ttq->getT(pn);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if( curr_interval.first == last_interval.second )
|
|
Toshihiro Shimizu |
890ddd |
last_interval.second = curr_interval.second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(last_interval);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return intervals.size();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
detectStraightIntervals_(const TThickQuadratic* ttq,
|
|
Toshihiro Shimizu |
890ddd |
std::set<double>& values)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if(!ttq ||
|
|
Toshihiro Shimizu |
890ddd |
isImproper( ttq ))
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
v0 = ttq->getP1() - ttq->getP0(),
|
|
Toshihiro Shimizu |
890ddd |
v1 = ttq->getP2() - ttq->getP1();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if( isAlmostZero( cross(v0,v1) ) )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
values.insert(0.0);
|
|
Toshihiro Shimizu |
890ddd |
values.insert(1.0);
|
|
Toshihiro Shimizu |
890ddd |
if(v0 * v1 > 0 )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return values.size()-1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
t = ttq->getT(ttq->getP1());
|
|
Toshihiro Shimizu |
890ddd |
values.insert( t );
|
|
Toshihiro Shimizu |
890ddd |
return values.size()-1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
pixelSize = 1.0;
|
|
Toshihiro Shimizu |
890ddd |
#ifndef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
pixelSize = sqrt(tglGetPixelSize2());
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
step = computeStep(*ttq,
|
|
Toshihiro Shimizu |
890ddd |
pixelSize);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
t = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
pnt ,
|
|
Toshihiro Shimizu |
890ddd |
p0 = ttq->getP0(),
|
|
Toshihiro Shimizu |
890ddd |
pn;
|
|
Toshihiro Shimizu |
890ddd |
for(t=step;
|
|
Toshihiro Shimizu |
890ddd |
t<1.0;
|
|
Toshihiro Shimizu |
890ddd |
t+=2.0*step)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
pnt = ttq->getPoint(t);
|
|
Toshihiro Shimizu |
890ddd |
v0 = pnt - p0;
|
|
Toshihiro Shimizu |
890ddd |
if( t+step < 1.0)
|
|
Toshihiro Shimizu |
890ddd |
pn = ttq->getPoint( t+step );
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
pn = ttq->getP2();
|
|
Toshihiro Shimizu |
890ddd |
v1 = pn - pnt;
|
|
Toshihiro Shimizu |
890ddd |
if( isAlmostZero( cross(v0,v1) ) )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert( v0 * v1 > 0 );
|
|
Toshihiro Shimizu |
890ddd |
values.insert(ttq->getT(p0));
|
|
Toshihiro Shimizu |
890ddd |
values.insert(ttq->getT(pn));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// for quadratic is not possible
|
|
Toshihiro Shimizu |
890ddd |
std::swap(p0,pn);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pn=ttq->getP2();
|
|
Toshihiro Shimizu |
890ddd |
v1 = pn - pnt;
|
|
Toshihiro Shimizu |
890ddd |
if( isAlmostZero( cross(v0,v1) ) )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert( v0 * v1 > 0 );
|
|
Toshihiro Shimizu |
890ddd |
values.insert(ttq->getT(p0));
|
|
Toshihiro Shimizu |
890ddd |
values.insert(ttq->getT(pn));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return values.size()-1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool mapValueInStroke(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *ttq,
|
|
Toshihiro Shimizu |
890ddd |
double value,
|
|
Toshihiro Shimizu |
890ddd |
double &out)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(ttq);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!ttq ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(value))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (value == 1.0) {
|
|
Toshihiro Shimizu |
890ddd |
if (ttq->getPoint(1.0) ==
|
|
Toshihiro Shimizu |
890ddd |
stroke->getPoint(1.0)) {
|
|
Toshihiro Shimizu |
890ddd |
if (!stroke->isSelfLoop())
|
|
Toshihiro Shimizu |
890ddd |
out = 1.0;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
out = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out = stroke->getW(ttq->getPoint(value));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool mapIntervalInStroke(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *ttq,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Interval &ttq_interval,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval &stroke_interval)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ttq ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (ttq_interval.first > ttq_interval.second ||
|
|
Toshihiro Shimizu |
890ddd |
0.0 > ttq_interval.first ||
|
|
Toshihiro Shimizu |
890ddd |
ttq_interval.second > 1.0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool
|
|
Toshihiro Shimizu |
890ddd |
check = mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
ttq,
|
|
Toshihiro Shimizu |
890ddd |
ttq_interval.first,
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval.first);
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
if (!check)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
check = mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
ttq,
|
|
Toshihiro Shimizu |
890ddd |
ttq_interval.second,
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval.second);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
if (!check)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool addQuadraticIntervalInStroke(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &stroke_intervals,
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *ttq,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &ttq_intervals)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ttq ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
size = ttq_intervals.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (size == 0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
i = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
&tmp = ttq_intervals[i];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (tmp.first > tmp.second ||
|
|
Toshihiro Shimizu |
890ddd |
0.0 > tmp.first ||
|
|
Toshihiro Shimizu |
890ddd |
tmp.second > 1.0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
&ttq_interval = ttq_intervals[i];
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// start to add interval in stroke
|
|
Toshihiro Shimizu |
890ddd |
if (mapIntervalInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
ttq,
|
|
Toshihiro Shimizu |
890ddd |
ttq_interval,
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval)) {
|
|
Toshihiro Shimizu |
890ddd |
stroke_intervals.push_back(stroke_interval);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool addQuadraticSetInStroke(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &stroke_intervals,
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *ttq,
|
|
Toshihiro Shimizu |
890ddd |
const std::set<double> &ttq_set)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ttq ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
size = ttq_set.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (size < 1)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::set<double>::const_iterator</double>
|
|
Toshihiro Shimizu |
890ddd |
cit,
|
|
Toshihiro Shimizu |
890ddd |
cit_end = ttq_set.end();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (cit = ttq_set.begin();
|
|
Toshihiro Shimizu |
890ddd |
cit != cit_end;
|
|
Toshihiro Shimizu |
890ddd |
++cit) {
|
|
Toshihiro Shimizu |
890ddd |
if (0.0 > *cit ||
|
|
Toshihiro Shimizu |
890ddd |
*cit > 1.0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cit = ttq_set.begin();
|
|
Toshihiro Shimizu |
890ddd |
std::set<double>::const_iterator</double>
|
|
Toshihiro Shimizu |
890ddd |
next_cit = cit;
|
|
Toshihiro Shimizu |
890ddd |
std::advance(next_cit, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (;
|
|
Toshihiro Shimizu |
890ddd |
next_cit != cit_end;
|
|
Toshihiro Shimizu |
890ddd |
++next_cit) {
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool
|
|
Toshihiro Shimizu |
890ddd |
check = mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
ttq,
|
|
Toshihiro Shimizu |
890ddd |
*cit,
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval.first);
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
if (!check)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
check = mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
ttq,
|
|
Toshihiro Shimizu |
890ddd |
*next_cit,
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval.second);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
if (!check)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(stroke_interval.first <= stroke_interval.second);
|
|
Toshihiro Shimizu |
890ddd |
if (stroke_interval.first > stroke_interval.second)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
stroke_intervals.push_back(stroke_interval);
|
|
Toshihiro Shimizu |
890ddd |
cit = next_cit;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool isThere(double value,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals &intervals)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals::const_iterator
|
|
Toshihiro Shimizu |
890ddd |
cit = intervals.begin(),
|
|
Toshihiro Shimizu |
890ddd |
cit_end = intervals.end();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (cit != cit_end) {
|
|
Toshihiro Shimizu |
890ddd |
if (cit->first == value ||
|
|
Toshihiro Shimizu |
890ddd |
cit->second == value)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
++cit;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool isThere(double value,
|
|
Toshihiro Shimizu |
890ddd |
const std::set<double> &mySet)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::set<double>::const_iterator</double>
|
|
Toshihiro Shimizu |
890ddd |
cit_end = mySet.end();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (cit_end == mySet.find(value))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool isCorner(const ToonzExt::Intervals &values,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
prev = values[0],
|
|
Toshihiro Shimizu |
890ddd |
curr = prev;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// first point
|
|
Toshihiro Shimizu |
890ddd |
if (areAlmostEqual(prev.first,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
tolerance))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
size = values.size();
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 1;
|
|
Toshihiro Shimizu |
890ddd |
i < size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
curr = values[i];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (areAlmostEqual(prev.second,
|
|
Toshihiro Shimizu |
890ddd |
curr.first) &&
|
|
Toshihiro Shimizu |
890ddd |
areAlmostEqual(w,
|
|
Toshihiro Shimizu |
890ddd |
curr.first,
|
|
Toshihiro Shimizu |
890ddd |
tolerance))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
prev = curr;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// last point
|
|
Toshihiro Shimizu |
890ddd |
if (areAlmostEqual(curr.second,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
tolerance))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // end of unnamed namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DEBUG_EXPORT bool
|
|
Toshihiro Shimizu |
890ddd |
isThereACornerMinusThan(double minCos,
|
|
Toshihiro Shimizu |
890ddd |
double minSin,
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *quad1,
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *quad2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!quad1 ||
|
|
Toshihiro Shimizu |
890ddd |
!quad2 ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(fabs(minCos)) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(fabs(minSin)))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
//speed1,
|
|
Toshihiro Shimizu |
890ddd |
//speed2,
|
|
Toshihiro Shimizu |
890ddd |
tan1,
|
|
Toshihiro Shimizu |
890ddd |
tan2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//speed1 = quad1->getSpeed(1);
|
|
Toshihiro Shimizu |
890ddd |
//speed2 = -quad2->getSpeed(0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tan1 = quad1->getSpeed(1);
|
|
Toshihiro Shimizu |
890ddd |
tan2 = -quad2->getSpeed(0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (norm2(tan1) == 0.0 ||
|
|
Toshihiro Shimizu |
890ddd |
norm2(tan2) == 0.0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tan1 = normalize(tan1);
|
|
Toshihiro Shimizu |
890ddd |
tan2 = normalize(tan2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// move cos value to compare just positive values
|
|
Toshihiro Shimizu |
890ddd |
minCos += 1.0;
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
cosVal = 1.0 + (tan1 * tan2); //, sinVal = fabs(cross(tan1,tan2));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(minCos >= 0.0);
|
|
Toshihiro Shimizu |
890ddd |
if (cosVal >= minCos)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DEBUG_EXPORT double
|
|
Toshihiro Shimizu |
890ddd |
degree2cos(int degree)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int tmp = degree < 0 ? -degree : degree;
|
|
Toshihiro Shimizu |
890ddd |
tmp %= 360;
|
|
Toshihiro Shimizu |
890ddd |
degree = degree < 0 ? 360 - tmp : degree;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (degree == 0)
|
|
Toshihiro Shimizu |
890ddd |
return 1.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (degree == 180)
|
|
Toshihiro Shimizu |
890ddd |
return -1.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (degree == 90 ||
|
|
Toshihiro Shimizu |
890ddd |
degree == 270)
|
|
Toshihiro Shimizu |
890ddd |
return 0.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return cos(degree * TConsts::pi_180);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DEBUG_EXPORT double
|
|
Toshihiro Shimizu |
890ddd |
degree2sin(int degree)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return degree2cos(degree - 90);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::findNearestSpireCorners(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval &out,
|
|
Toshihiro Shimizu |
890ddd |
int cornerSize,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals *const cl,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(w))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
*values = cl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!cl) {
|
|
Toshihiro Shimizu |
890ddd |
cornerSize = normalizeAngle(cornerSize);
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::detectSpireIntervals(stroke,
|
|
Toshihiro Shimizu |
890ddd |
tmpValues,
|
|
Toshihiro Shimizu |
890ddd |
cornerSize))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
values = &tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!values ||
|
|
Toshihiro Shimizu |
890ddd |
values->empty()) {
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return findNearestCorners(stroke,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
out,
|
|
Toshihiro Shimizu |
890ddd |
*values,
|
|
Toshihiro Shimizu |
890ddd |
tolerance);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::isASpireCorner(const TStroke *s,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
int cornerSize,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals *const cl,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(s) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(w))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
*values = cl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!cl) {
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::detectSpireIntervals(s,
|
|
Toshihiro Shimizu |
890ddd |
tmpValues,
|
|
Toshihiro Shimizu |
890ddd |
cornerSize))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
values = &tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!values ||
|
|
Toshihiro Shimizu |
890ddd |
values->empty()) {
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return isCorner(*values,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
tolerance);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::detectStraightIntervals(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &intervals,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(tolerance > 0.0 &&
|
|
Toshihiro Shimizu |
890ddd |
tolerance < 1.0 &&
|
|
Toshihiro Shimizu |
890ddd |
"Strange tolerance are you sure???");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
intervals.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// first step:
|
|
Toshihiro Shimizu |
890ddd |
// store information about chunk and straight interval
|
|
Toshihiro Shimizu |
890ddd |
typedef std::pair<const *,="" toonzext::intervals="" tthickquadratic=""> ChunkStraights;</const>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::map<int, chunkstraights=""></int,>
|
|
Toshihiro Shimizu |
890ddd |
arrayOfChunkIntervals;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
chunkCount = stroke->getChunkCount();
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
counter = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < chunkCount;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
values;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic *
|
|
Toshihiro Shimizu |
890ddd |
chunk = stroke->getChunk(i);
|
|
Toshihiro Shimizu |
890ddd |
if (chunk->getLength() == 0.0)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
howMany = detectStraightIntervals_(chunk,
|
|
Toshihiro Shimizu |
890ddd |
values,
|
|
Toshihiro Shimizu |
890ddd |
tolerance);
|
|
Toshihiro Shimizu |
890ddd |
if (howMany > 0) {
|
|
Toshihiro Shimizu |
890ddd |
arrayOfChunkIntervals[counter] = ChunkStraights(chunk, values);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
++counter;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// second step:
|
|
Toshihiro Shimizu |
890ddd |
// add intervals vs stroke
|
|
Toshihiro Shimizu |
890ddd |
std::map<int, chunkstraights="">::iterator</int,>
|
|
Toshihiro Shimizu |
890ddd |
it = arrayOfChunkIntervals.begin(),
|
|
Toshihiro Shimizu |
890ddd |
end = arrayOfChunkIntervals.end(),
|
|
Toshihiro Shimizu |
890ddd |
aux;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
myRange = ToonzExt::Interval(-1, -1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (; it != end; ++it) {
|
|
Toshihiro Shimizu |
890ddd |
aux = it;
|
|
Toshihiro Shimizu |
890ddd |
std::advance(aux, 1);
|
|
Toshihiro Shimizu |
890ddd |
ChunkStraights
|
|
Toshihiro Shimizu |
890ddd |
&cs1 = it->second;
|
|
Toshihiro Shimizu |
890ddd |
if (aux != end) {
|
|
Toshihiro Shimizu |
890ddd |
ChunkStraights
|
|
Toshihiro Shimizu |
890ddd |
&cs2 = aux->second;
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
i1 = it->first,
|
|
Toshihiro Shimizu |
890ddd |
i2 = aux->first;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// if chunk are a sequence
|
|
Toshihiro Shimizu |
890ddd |
if ((i1 + 1 == i2) &&
|
|
Toshihiro Shimizu |
890ddd |
!corner(cs1.first,
|
|
Toshihiro Shimizu |
890ddd |
cs2.first,
|
|
Toshihiro Shimizu |
890ddd |
tolerance)) {
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals &
|
|
Toshihiro Shimizu |
890ddd |
cs1Intervals = cs1.second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
size = cs1Intervals.size();
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
i;
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
tmp;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
tmp = cs1Intervals[i];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (tmp.second == 1.0)
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval;
|
|
Toshihiro Shimizu |
890ddd |
if (mapIntervalInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
cs1.first,
|
|
Toshihiro Shimizu |
890ddd |
tmp,
|
|
Toshihiro Shimizu |
890ddd |
stroke_interval))
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(stroke_interval);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//assert( i == size-1 );
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (myRange.first == -1) {
|
|
Toshihiro Shimizu |
890ddd |
if (!mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
cs1.first,
|
|
Toshihiro Shimizu |
890ddd |
tmp.first,
|
|
Toshihiro Shimizu |
890ddd |
myRange.first))
|
|
Toshihiro Shimizu |
890ddd |
assert(!"Ops problemone!!!");
|
|
Toshihiro Shimizu |
890ddd |
// remove value added to merge
|
|
Toshihiro Shimizu |
890ddd |
// adjacent straight interval
|
|
Toshihiro Shimizu |
890ddd |
cs1.second.pop_back();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tmp = cs2.second.front();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
cs2.first,
|
|
Toshihiro Shimizu |
890ddd |
tmp.second,
|
|
Toshihiro Shimizu |
890ddd |
myRange.second))
|
|
Toshihiro Shimizu |
890ddd |
assert(!"Ops problemone!!!");
|
|
Toshihiro Shimizu |
890ddd |
cs2.second.erase(cs2.second.begin());
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (myRange.first != -1 &&
|
|
Toshihiro Shimizu |
890ddd |
myRange.second != -1) {
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(myRange);
|
|
Toshihiro Shimizu |
890ddd |
myRange = ToonzExt::Interval(-1, -1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// add remaining interval of current stroke
|
|
Toshihiro Shimizu |
890ddd |
addQuadraticIntervalInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
intervals,
|
|
Toshihiro Shimizu |
890ddd |
cs1.first,
|
|
Toshihiro Shimizu |
890ddd |
cs1.second);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (myRange.first != -1 &&
|
|
Toshihiro Shimizu |
890ddd |
myRange.second != -1) {
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(myRange);
|
|
Toshihiro Shimizu |
890ddd |
myRange = ToonzExt::Interval(-1, -1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// add remaining interval of current stroke
|
|
Toshihiro Shimizu |
890ddd |
addQuadraticIntervalInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
intervals,
|
|
Toshihiro Shimizu |
890ddd |
cs1.first,
|
|
Toshihiro Shimizu |
890ddd |
cs1.second);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop()) {
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
v0 = stroke->getSpeed(0.0),
|
|
Toshihiro Shimizu |
890ddd |
vn = stroke->getSpeed(1.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (areParallel(v0, vn) &&
|
|
Toshihiro Shimizu |
890ddd |
areInSameDirection(v0, vn) &&
|
|
Toshihiro Shimizu |
890ddd |
intervals.size() > 1) {
|
|
Toshihiro Shimizu |
890ddd |
// then first interval probably can be merged
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
first = intervals.front(),
|
|
Toshihiro Shimizu |
890ddd |
last = intervals.back();
|
|
Toshihiro Shimizu |
890ddd |
if (first.first == 0.0 &&
|
|
Toshihiro Shimizu |
890ddd |
last.second == 0.0) {
|
|
Toshihiro Shimizu |
890ddd |
intervals.pop_back();
|
|
Toshihiro Shimizu |
890ddd |
first.first = last.first;
|
|
Toshihiro Shimizu |
890ddd |
intervals[0] = first;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return !intervals.empty();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::detectSpireIntervals(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &intervals,
|
|
Toshihiro Shimizu |
890ddd |
int minDegree)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
minDegree = normalizeAngle(minDegree);
|
|
Toshihiro Shimizu |
890ddd |
std::vector<double></double>
|
|
Toshihiro Shimizu |
890ddd |
corners;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool
|
|
Toshihiro Shimizu |
890ddd |
found = ToonzExt::cornersDetector(stroke,
|
|
Toshihiro Shimizu |
890ddd |
minDegree,
|
|
Toshihiro Shimizu |
890ddd |
corners);
|
|
Toshihiro Shimizu |
890ddd |
if (!found)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(!corners.empty());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
intervals.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
first = corners[0],
|
|
Toshihiro Shimizu |
890ddd |
last = first;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
size = corners.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 1;
|
|
Toshihiro Shimizu |
890ddd |
i < size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
last = corners[i];
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(ToonzExt::Interval(first, last));
|
|
Toshihiro Shimizu |
890ddd |
first = last;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//intervals.push_back( ToonzExt::Interval(last,1.0));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop()) {
|
|
Toshihiro Shimizu |
890ddd |
if (corners.size() == 1) {
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
val = corners[0];
|
|
Toshihiro Shimizu |
890ddd |
intervals.push_back(ToonzExt::Interval(val, val));
|
|
Toshihiro Shimizu |
890ddd |
} else if (!intervals.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
first = intervals.front(),
|
|
Toshihiro Shimizu |
890ddd |
last = intervals.back();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
intervals.insert(intervals.begin(), ToonzExt::Interval(last.second, first.first));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return !intervals.empty();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::isAStraightCorner(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals *const cl,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(w))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
*values = cl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!cl) {
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::detectStraightIntervals(stroke,
|
|
Toshihiro Shimizu |
890ddd |
tmpValues,
|
|
Toshihiro Shimizu |
890ddd |
tolerance))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
values = &tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!values ||
|
|
Toshihiro Shimizu |
890ddd |
values->empty()) {
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return isCorner(*values,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
tolerance);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::findNearestStraightCorners(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval &out,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals *const cl,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!stroke ||
|
|
Toshihiro Shimizu |
890ddd |
w < 0.0 ||
|
|
Toshihiro Shimizu |
890ddd |
w > 1.0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
*values = cl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!cl) {
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::detectStraightIntervals(stroke,
|
|
Toshihiro Shimizu |
890ddd |
tmpValues,
|
|
Toshihiro Shimizu |
890ddd |
tolerance))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
values = &tmpValues;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!values ||
|
|
Toshihiro Shimizu |
890ddd |
values->empty()) {
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return findNearestCorners(stroke,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
out,
|
|
Toshihiro Shimizu |
890ddd |
*values,
|
|
Toshihiro Shimizu |
890ddd |
tolerance);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke *
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::rotateControlPoint(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::EvenInt &evenControlPoint,
|
|
Toshihiro Shimizu |
890ddd |
double atLength)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!stroke ||
|
|
Toshihiro Shimizu |
890ddd |
!stroke->isSelfLoop() ||
|
|
Toshihiro Shimizu |
890ddd |
!evenControlPoint.isEven())
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint
|
|
Toshihiro Shimizu |
890ddd |
tp1 = stroke->getControlPoint(0);
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint
|
|
Toshihiro Shimizu |
890ddd |
tp2 = stroke->getControlPoint(stroke->getControlPointCount() - 1);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
controlPoint = (int)evenControlPoint;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const double
|
|
Toshihiro Shimizu |
890ddd |
length = stroke->getLength();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// invalid length
|
|
Toshihiro Shimizu |
890ddd |
if (0.0 > atLength ||
|
|
Toshihiro Shimizu |
890ddd |
atLength > length)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
cpCountAtBegin = stroke->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
// invalid control point
|
|
Toshihiro Shimizu |
890ddd |
if (0 > controlPoint ||
|
|
Toshihiro Shimizu |
890ddd |
controlPoint > cpCountAtBegin)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// identity
|
|
Toshihiro Shimizu |
890ddd |
if ((controlPoint == 0 || controlPoint == (cpCountAtBegin - 1)) &&
|
|
Toshihiro Shimizu |
890ddd |
(areAlmostEqual(atLength, length) || isAlmostZero(atLength)))
|
|
Toshihiro Shimizu |
890ddd |
return new TStroke(*stroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke
|
|
Toshihiro Shimizu |
890ddd |
tmpStroke(*stroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tthickpoint></tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
cp;
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
count = stroke->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < count;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
cp.push_back(stroke->getControlPoint(i));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// add a control point where is necessary to have rotation (head_queue cp)
|
|
Toshihiro Shimizu |
890ddd |
tmpStroke.insertControlPointsAtLength(atLength);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
count = stroke->getControlPointCount(),
|
|
Toshihiro Shimizu |
890ddd |
count2 = tmpStroke.getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
i,
|
|
Toshihiro Shimizu |
890ddd |
firstDifference = -1;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < count;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
if ((tp1 = stroke->getControlPoint(i)) !=
|
|
Toshihiro Shimizu |
890ddd |
(tp2 = tmpStroke.getControlPoint(i))) {
|
|
Toshihiro Shimizu |
890ddd |
firstDifference = i;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < count;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
if (i < firstDifference)
|
|
Toshihiro Shimizu |
890ddd |
assert((tp1 = stroke->getControlPoint(i)) ==
|
|
Toshihiro Shimizu |
890ddd |
(tp2 = tmpStroke.getControlPoint(i)));
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
// assert( (tp1=stroke->getControlPoint(i)) ==
|
|
Toshihiro Shimizu |
890ddd |
// (tp2=tmpStroke.getControlPoint(i+2)));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tp1 = stroke->getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
tp2 = tmpStroke.getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
cpCount = tmpStroke.getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
w = tmpStroke.getParameterAtLength(atLength);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
butta = tmpStroke.getLength(w);
|
|
Toshihiro Shimizu |
890ddd |
assert(areAlmostEqual(butta, atLength));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// retrieve head_queue control point
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint
|
|
Toshihiro Shimizu |
890ddd |
head_queue = tmpStroke.getControlPointAtParameter(w);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// recover index
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < cpCount; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
if (head_queue ==
|
|
Toshihiro Shimizu |
890ddd |
tmpStroke.getControlPoint(i))
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
head_index = i;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// uhmmm really strange
|
|
Toshihiro Shimizu |
890ddd |
if (head_index == cpCount) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!"Error on procedure!!! Not control point found!!!"
|
|
Toshihiro Shimizu |
890ddd |
" Wrong insert control point!!!");
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// head_index is the new head of stroke
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tthickpoint></tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
new_stroke_cp;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = head_index; i < cpCount; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint
|
|
Toshihiro Shimizu |
890ddd |
to_add = tmpStroke.getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
new_stroke_cp.push_back(to_add);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint
|
|
Toshihiro Shimizu |
890ddd |
tmpCP = tmpStroke.getControlPoint(0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool
|
|
Toshihiro Shimizu |
890ddd |
check = areAlmostEqual(new_stroke_cp.back(),
|
|
Toshihiro Shimizu |
890ddd |
tmpCP,
|
|
Toshihiro Shimizu |
890ddd |
0.01);
|
|
Toshihiro Shimizu |
890ddd |
// relaxed check
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!check) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!"Error on procedure!!! Please verify algorithm!!!");
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// 0 position is already inserted
|
|
Toshihiro Shimizu |
890ddd |
for (i = 1; i < head_index; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint
|
|
Toshihiro Shimizu |
890ddd |
to_add = tmpStroke.getControlPoint(i);
|
|
Toshihiro Shimizu |
890ddd |
new_stroke_cp.push_back(to_add);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// now add queue == head cp
|
|
Toshihiro Shimizu |
890ddd |
new_stroke_cp.push_back(new_stroke_cp[0]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert((int)new_stroke_cp.size() ==
|
|
Toshihiro Shimizu |
890ddd |
cpCount);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (new_stroke_cp.back() !=
|
|
Toshihiro Shimizu |
890ddd |
tmpStroke.getControlPoint(head_index)) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!"Error on procedure!!! Please verify algorithm!!!");
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke *out = new TStroke(new_stroke_cp);
|
|
Toshihiro Shimizu |
890ddd |
out->setSelfLoop();
|
|
Toshihiro Shimizu |
890ddd |
return out;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
* A corner is straight, only if is contained two times
|
|
Toshihiro Shimizu |
890ddd |
* in the list of intervals.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::straightCornersDetector(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
std::vector<double> &corners)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals
|
|
Toshihiro Shimizu |
890ddd |
intervals;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(corners.empty());
|
|
Toshihiro Shimizu |
890ddd |
if (!corners.empty())
|
|
Toshihiro Shimizu |
890ddd |
corners.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::detectStraightIntervals(stroke,
|
|
Toshihiro Shimizu |
890ddd |
intervals))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(!intervals.empty() && "Intervals are empty!!!");
|
|
Toshihiro Shimizu |
890ddd |
if (intervals.empty())
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
first;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
prev = intervals[0],
|
|
Toshihiro Shimizu |
890ddd |
curr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop())
|
|
Toshihiro Shimizu |
890ddd |
first = prev.first;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
size = intervals.size();
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 1;
|
|
Toshihiro Shimizu |
890ddd |
i < size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
curr = intervals[i];
|
|
Toshihiro Shimizu |
890ddd |
if (prev.second == curr.first)
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(curr.first);
|
|
Toshihiro Shimizu |
890ddd |
prev = curr;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop() &&
|
|
Toshihiro Shimizu |
890ddd |
curr.second == first)
|
|
Toshihiro Shimizu |
890ddd |
corners.push_back(first);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return !corners.empty();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::cornersDetector(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
int minDegree,
|
|
Toshihiro Shimizu |
890ddd |
std::vector<double> &corners)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(stroke);
|
|
Toshihiro Shimizu |
890ddd |
if (!stroke)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
assert(corners.empty());
|
|
Toshihiro Shimizu |
890ddd |
if (!corners.empty())
|
|
Toshihiro Shimizu |
890ddd |
corners.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(0 <= minDegree &&
|
|
Toshihiro Shimizu |
890ddd |
minDegree <= 180);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
minDegree = normalizeAngle(minDegree);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const double
|
|
Toshihiro Shimizu |
890ddd |
minSin = degree2sin(minDegree),
|
|
Toshihiro Shimizu |
890ddd |
minCos = degree2cos(minDegree);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(0.0 <= minSin &&
|
|
Toshihiro Shimizu |
890ddd |
minSin <= 1.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// first step remove chunks with null lenght
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic
|
|
Toshihiro Shimizu |
890ddd |
*quad1 = 0,
|
|
Toshihiro Shimizu |
890ddd |
*quad2 = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
UINT
|
|
Toshihiro Shimizu |
890ddd |
chunkCount = stroke->getChunkCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
quad1 = stroke->getChunk(0);
|
|
Toshihiro Shimizu |
890ddd |
assert(quad1);
|
|
Toshihiro Shimizu |
890ddd |
if (!quad1)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool
|
|
Toshihiro Shimizu |
890ddd |
error = false,
|
|
Toshihiro Shimizu |
890ddd |
check = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::set<double></double>
|
|
Toshihiro Shimizu |
890ddd |
internal_corners;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
t;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (curveIsStraight(quad1,
|
|
Toshihiro Shimizu |
890ddd |
t)) {
|
|
Toshihiro Shimizu |
890ddd |
if (t != -1) {
|
|
Toshihiro Shimizu |
890ddd |
check = mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
quad1,
|
|
Toshihiro Shimizu |
890ddd |
t,
|
|
Toshihiro Shimizu |
890ddd |
t);
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
if (check)
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.insert(t);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (UINT j = 1; j < chunkCount; j++) {
|
|
Toshihiro Shimizu |
890ddd |
quad2 = stroke->getChunk(j);
|
|
Toshihiro Shimizu |
890ddd |
if (curveIsStraight(quad2,
|
|
Toshihiro Shimizu |
890ddd |
t)) {
|
|
Toshihiro Shimizu |
890ddd |
if (t != -1) {
|
|
Toshihiro Shimizu |
890ddd |
check = mapValueInStroke(stroke,
|
|
Toshihiro Shimizu |
890ddd |
quad2,
|
|
Toshihiro Shimizu |
890ddd |
t,
|
|
Toshihiro Shimizu |
890ddd |
t);
|
|
Toshihiro Shimizu |
890ddd |
assert(check);
|
|
Toshihiro Shimizu |
890ddd |
if (check)
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.insert(t);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(quad2);
|
|
Toshihiro Shimizu |
890ddd |
if (!quad2)
|
|
Toshihiro Shimizu |
890ddd |
error = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
tmp = stroke->getW(quad2->getP0());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// jump zero length curves
|
|
Toshihiro Shimizu |
890ddd |
if (!isAlmostZero(quad1->getLength()) &&
|
|
Toshihiro Shimizu |
890ddd |
!isAlmostZero(quad2->getLength()) &&
|
|
Toshihiro Shimizu |
890ddd |
isThereACornerMinusThan(minCos, minSin, quad1, quad2))
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.insert(tmp);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!isAlmostZero(quad2->getLength()))
|
|
Toshihiro Shimizu |
890ddd |
quad1 = quad2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->isSelfLoop() &&
|
|
Toshihiro Shimizu |
890ddd |
chunkCount > 0) {
|
|
Toshihiro Shimizu |
890ddd |
quad2 = stroke->getChunk(0);
|
|
Toshihiro Shimizu |
890ddd |
quad1 = stroke->getChunk(chunkCount - 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (isThereACornerMinusThan(minCos, minSin, quad1, quad2))
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.insert(0.0);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.insert(0.0);
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.insert(1.0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (error)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::copy(internal_corners.begin(),
|
|
Toshihiro Shimizu |
890ddd |
internal_corners.end(),
|
|
Toshihiro Shimizu |
890ddd |
std::back_inserter(corners));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
temp = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (unsigned int k = 0;
|
|
Toshihiro Shimizu |
890ddd |
k < corners.size();
|
|
Toshihiro Shimizu |
890ddd |
++k) {
|
|
Toshihiro Shimizu |
890ddd |
assert(corners[k] >= temp);
|
|
Toshihiro Shimizu |
890ddd |
temp = corners[k];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return !corners.empty();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ToonzExt::cloneStrokeStatus(const TStroke *from,
|
|
Toshihiro Shimizu |
890ddd |
TStroke *to)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(from) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(to))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
to->setId(from->getId());
|
|
Toshihiro Shimizu |
890ddd |
to->setSelfLoop(from->isSelfLoop());
|
|
Toshihiro Shimizu |
890ddd |
to->setStyle(from->getStyle());
|
|
Toshihiro Shimizu |
890ddd |
to->setAverageThickness(from->getAverageThickness());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
to->invalidate();
|
|
Toshihiro Shimizu |
890ddd |
to->enableComputeOfCaches();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::replaceStroke(TStroke *old_stroke,
|
|
Toshihiro Shimizu |
890ddd |
TStroke *new_stroke,
|
|
Toshihiro Shimizu |
890ddd |
unsigned int n_,
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP &vi)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(old_stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(new_stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
!vi)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const unsigned int
|
|
Toshihiro Shimizu |
890ddd |
strokesCount = vi->getStrokeCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(n_ <= strokesCount);
|
|
Toshihiro Shimizu |
890ddd |
if (n_ > strokesCount)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(vi->getStroke(n_) == old_stroke);
|
|
Toshihiro Shimizu |
890ddd |
if (vi->getStroke(n_) != old_stroke)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// stroke is replaced (old stroke is deleted)
|
|
Toshihiro Shimizu |
890ddd |
// in vector image
|
|
Toshihiro Shimizu |
890ddd |
vi->replaceStroke(n_,
|
|
Toshihiro Shimizu |
890ddd |
new_stroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
new_id = getStrokeId(new_stroke,
|
|
Toshihiro Shimizu |
890ddd |
vi);
|
|
Toshihiro Shimizu |
890ddd |
if (new_id == -1)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
n_ = new_id;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::getAllW(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &pnt,
|
|
Toshihiro Shimizu |
890ddd |
double &dist2,
|
|
Toshihiro Shimizu |
890ddd |
std::vector<double> ¶meters)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(!"To be finished!!!");
|
|
Toshihiro Shimizu |
890ddd |
std::set<double></double>
|
|
Toshihiro Shimizu |
890ddd |
tmp;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(stroke);
|
|
Toshihiro Shimizu |
890ddd |
if (ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
outT,
|
|
Toshihiro Shimizu |
890ddd |
w;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TThickQuadratic
|
|
Toshihiro Shimizu |
890ddd |
*tq = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
chunkFound = -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double
|
|
Toshihiro Shimizu |
890ddd |
distance2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (stroke->getNearestChunk(pnt,
|
|
Toshihiro Shimizu |
890ddd |
outT,
|
|
Toshihiro Shimizu |
890ddd |
chunkFound,
|
|
Toshihiro Shimizu |
890ddd |
distance2,
|
|
Toshihiro Shimizu |
890ddd |
false)) {
|
|
Toshihiro Shimizu |
890ddd |
dist2 = distance2;
|
|
Toshihiro Shimizu |
890ddd |
tq = stroke->getChunk(chunkFound);
|
|
Toshihiro Shimizu |
890ddd |
if (tq) {
|
|
Toshihiro Shimizu |
890ddd |
w = stroke->getW(tq->getPoint(outT));
|
|
Toshihiro Shimizu |
890ddd |
if (ToonzExt::isValid(w))
|
|
Toshihiro Shimizu |
890ddd |
tmp.insert(w);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int
|
|
Toshihiro Shimizu |
890ddd |
i,
|
|
Toshihiro Shimizu |
890ddd |
chunkCount = stroke->getChunkCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0;
|
|
Toshihiro Shimizu |
890ddd |
i < chunkCount;
|
|
Toshihiro Shimizu |
890ddd |
i++) {
|
|
Toshihiro Shimizu |
890ddd |
if (i != chunkFound) {
|
|
Toshihiro Shimizu |
890ddd |
tq = stroke->getChunk(i);
|
|
Toshihiro Shimizu |
890ddd |
TPointD
|
|
Toshihiro Shimizu |
890ddd |
tmp_pnt = tq->getPoint(tq->getT(pnt));
|
|
Toshihiro Shimizu |
890ddd |
if (areAlmostEqual(tdistance2(tmp_pnt, pnt),
|
|
Toshihiro Shimizu |
890ddd |
dist2)) {
|
|
Toshihiro Shimizu |
890ddd |
w = stroke->getW(tmp_pnt);
|
|
Toshihiro Shimizu |
890ddd |
if (ToonzExt::isValid(w))
|
|
Toshihiro Shimizu |
890ddd |
tmp.insert(w);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::copy(tmp.begin(),
|
|
Toshihiro Shimizu |
890ddd |
tmp.end(),
|
|
Toshihiro Shimizu |
890ddd |
std::back_inserter(parameters));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return !tmp.empty();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI bool
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::findNearestCorners(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
double w,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval &out,
|
|
Toshihiro Shimizu |
890ddd |
const ToonzExt::Intervals &values,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
out = ToonzExt::Interval(-1.0, -1.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
!ToonzExt::isValid(w) ||
|
|
Toshihiro Shimizu |
890ddd |
values.empty())
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Interval
|
|
Toshihiro Shimizu |
890ddd |
prev = values[0],
|
|
Toshihiro Shimizu |
890ddd |
curr = prev;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!stroke->isSelfLoop() &&
|
|
Toshihiro Shimizu |
890ddd |
areAlmostEqual(w,
|
|
Toshihiro Shimizu |
890ddd |
prev.first,
|
|
Toshihiro Shimizu |
890ddd |
tolerance)) {
|
|
Toshihiro Shimizu |
890ddd |
out = prev;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int
|
|
Toshihiro Shimizu |
890ddd |
size = values.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 1;
|
|
Toshihiro Shimizu |
890ddd |
i <= size;
|
|
Toshihiro Shimizu |
890ddd |
++i) {
|
|
Toshihiro Shimizu |
890ddd |
if (i < size)
|
|
Toshihiro Shimizu |
890ddd |
curr = values[i];
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
curr = values[0];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// this case, w is an extreme and needs to be considered
|
|
Toshihiro Shimizu |
890ddd |
// the nearest external interval
|
|
Toshihiro Shimizu |
890ddd |
if (areAlmostEqual(w,
|
|
Toshihiro Shimizu |
890ddd |
curr.first,
|
|
Toshihiro Shimizu |
890ddd |
tolerance) &&
|
|
Toshihiro Shimizu |
890ddd |
(prev.second == curr.first)) {
|
|
Toshihiro Shimizu |
890ddd |
if (isWGood(prev.first,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
curr.second,
|
|
Toshihiro Shimizu |
890ddd |
stroke) ||
|
|
Toshihiro Shimizu |
890ddd |
(prev.first == curr.second)) {
|
|
Toshihiro Shimizu |
890ddd |
out.first = prev.first;
|
|
Toshihiro Shimizu |
890ddd |
out.second = curr.second;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// normal case
|
|
Toshihiro Shimizu |
890ddd |
if (isWGood(curr.first,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
curr.second,
|
|
Toshihiro Shimizu |
890ddd |
stroke)) {
|
|
Toshihiro Shimizu |
890ddd |
out = curr;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
prev = curr;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
curr = values.back();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// last point
|
|
Toshihiro Shimizu |
890ddd |
if (!stroke->isSelfLoop() &&
|
|
Toshihiro Shimizu |
890ddd |
areAlmostEqual(curr.second,
|
|
Toshihiro Shimizu |
890ddd |
w,
|
|
Toshihiro Shimizu |
890ddd |
tolerance)) {
|
|
Toshihiro Shimizu |
890ddd |
out = curr;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI void
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::findCorners(const TStroke *stroke,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &corners,
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::Intervals &intervals,
|
|
Toshihiro Shimizu |
890ddd |
int angle,
|
|
Toshihiro Shimizu |
890ddd |
double tolerance)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(stroke && "Stroke is null!!!");
|
|
Toshihiro Shimizu |
890ddd |
if (!ToonzExt::isValid(stroke))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
angle = normalizeAngle(angle);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::detectSpireIntervals(stroke,
|
|
Toshihiro Shimizu |
890ddd |
corners,
|
|
Toshihiro Shimizu |
890ddd |
angle);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// a corner SPIRE is also a STRAIGHT
|
|
Toshihiro Shimizu |
890ddd |
ToonzExt::detectStraightIntervals(stroke,
|
|
Toshihiro Shimizu |
890ddd |
intervals,
|
|
Toshihiro Shimizu |
890ddd |
tolerance);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// End Of File
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|