2016-03-19 06:57:51 +13:00
//#include "tsystem.h"
# include "tmachine.h"
# include "tcurves.h"
# include "tcommon.h"
# include "tregion.h"
//#include "tregionutil.h"
# include "tstopwatch.h"
# include "tstroke.h"
# include "tstrokeutil.h"
# include "tvectorimageP.h"
# include "tdebugmessage.h"
# include <vector>
# include "tcurveutil.h"
# include <algorithm>
# if !defined(TNZ_LITTLE_ENDIAN)
TNZ_LITTLE_ENDIAN undefined ! !
# endif
//-----------------------------------------------------------------------------
# ifdef IS_DOTNET
# define NULL_ITER list<IntersectedStroke>::iterator()
# else
# define NULL_ITER 0
# endif
using namespace std ;
typedef TVectorImage : : IntersectionBranch IntersectionBranch ;
//-----------------------------------------------------------------------------
inline double myRound ( double x )
{
return ( 1.0 / REGION_COMPUTING_PRECISION ) * ( ( long ) ( x * REGION_COMPUTING_PRECISION ) ) ;
}
inline TThickPoint myRound ( const TThickPoint & p )
{
return TThickPoint ( myRound ( p . x ) , myRound ( p . y ) , p . thick ) ;
}
void print ( list < Intersection > & intersectionList , char * str )
{
ofstream of ( str ) ;
of < < " *************************** " < < endl ;
list < Intersection > : : const_iterator it ;
list < IntersectedStroke > : : const_iterator it1 ;
int i , j ;
for ( i = 0 , it = intersectionList . begin ( ) ; it ! = intersectionList . end ( ) ; it + + , i + + ) {
of < < " *************************** " < < endl ;
of < < " Intersection# " < < i < < " : " < < it - > m_intersection < < " numBranches: " < < it - > m_numInter < < endl ;
of < < endl ;
for ( j = 0 , it1 = it - > m_strokeList . begin ( ) ; it1 ! = it - > m_strokeList . end ( ) ; it1 + + , j + + ) {
of < < " ----Branch # " < < j ;
if ( it1 - > m_edge . m_index < 0 )
of < < " (AUTOCLOSE) " ;
of < < " Intersection at " < < it1 - > m_edge . m_w0 < < " : "
< < " : " < < endl ;
of < < " ColorId: " < < it1 - > m_edge . m_styleId < < endl ;
/*
TColorStyle * fs = it1 - > m_edge . m_fillStyle ;
if ( fs = = 0 )
of < < " NO color: " < < endl ;
else
{
TFillStyleP fp = fs - > getFillStyle ( ) ;
if ( fp )
{
fp - >
assert ( false ) ;
else
of < < " Color: ( " < < colorStyle - > getColor ( ) . r < < " , " < < colorStyle - > getColor ( ) . g < < " , " < < colorStyle - > getColor ( ) . b < < " ) " < < endl ;
*/
of < < " ----Stroke " < < ( it1 - > m_gettingOut ? " OUT " : " IN " ) < < " # " < < it1 - > m_edge . m_index < < " : " < < endl ;
//if (it1->m_dead)
//of<<"---- DEAD Intersection.";
//else
{
of < < " ---- NEXT Intersection: " ;
if ( it1 - > m_nextIntersection ! = intersectionList . end ( ) ) {
int dist = std : : distance ( intersectionList . begin ( ) , it1 - > m_nextIntersection ) ;
of < < dist ;
list < Intersection > : : iterator iit = intersectionList . begin ( ) ;
std : : advance ( iit , dist ) ;
of < < " " < < std : : distance ( iit - > m_strokeList . begin ( ) , it1 - > m_nextStroke ) ;
}
else
of < < " NULL!! " ;
of < < " ---- NEXT Stroke: " ;
if ( it1 - > m_nextIntersection ! = intersectionList . end ( ) )
of < < it1 - > m_nextStroke - > m_edge . m_index ;
else
of < < " NULL!! " ;
}
of < < endl
< < endl ;
}
}
}
void findNearestIntersection ( list < Intersection > & interList ,
const list < Intersection > : : iterator & i1 ,
const list < IntersectedStroke > : : iterator & i2 ) ;
//-----------------------------------------------------------------------------
# ifdef _TOLGO
void checkInterList ( list < Intersection > & intersectionList )
{
list < Intersection > : : iterator it ;
list < IntersectedStroke > : : iterator it1 ;
for ( it = intersectionList . begin ( ) ; it ! = intersectionList . end ( ) ; it + + ) {
int count = 0 ;
for ( it1 = it - > m_strokeList . begin ( ) ; it1 ! = it - > m_strokeList . end ( ) ; it1 + + ) {
int val ;
if ( it1 - > m_nextIntersection ! = intersectionList . end ( ) ) {
count + + ;
//assert (it1->m_nextIntersection!=intersectionList.end());
assert ( it1 - > m_nextStroke - > m_nextIntersection = = it ) ;
assert ( it1 - > m_nextStroke - > m_nextStroke = = it1 ) ;
//int k = it1->m_edge.m_index;
val = std : : distance ( intersectionList . begin ( ) , it1 - > m_nextIntersection ) ;
}
//else
// assert(it1->m_nextIntersection==intersectionList.end());
}
assert ( count = = it - > m_numInter ) ;
}
}
# else
# define checkInterList
# endif
//-----------------------------------------------------------------------------
//void addFakeIntersection(list<Intersection>& intersectionList,TStroke* s, UINT ii, double w);
void addIntersections ( IntersectionData & intersectionData ,
const vector < VIStroke * > & s , int ii , int jj , const vector < DoublePair > & intersections , int numStrokes ) ;
void addIntersection ( IntersectionData & intData ,
const vector < VIStroke * > & s , int ii , int jj ,
DoublePair intersections , int strokeSize ) ;
//-----------------------------------------------------------------------------
bool sortBBox ( const TStroke * s1 , const TStroke * s2 )
{
return s1 - > getBBox ( ) . x0 < s2 - > getBBox ( ) . x0 ;
}
//-----------------------------------------------------------------------------
void cleanIntersectionMarks ( list < Intersection > & interList )
{
for ( list < Intersection > : : iterator it1 = interList . begin ( ) ; it1 ! = interList . end ( ) ; it1 + + )
for ( list < IntersectedStroke > : : iterator it2 = ( * it1 ) . m_strokeList . begin ( ) ; it2 ! = ( * it1 ) . m_strokeList . end ( ) ; it2 + + ) {
it2 - > m_visited = false ; // Ogni ramo della lista viene messo nella condizione
// di poter essere visitato
if ( it2 - > m_nextIntersection ! = interList . end ( ) ) {
it2 - > m_nextIntersection = interList . end ( ) ; //pezza tremenda, da togliere!!!
it1 - > m_numInter - - ;
}
}
}
//-----------------------------------------------------------------------------
void cleanNextIntersection ( list < Intersection > & interList , TStroke * s )
{
for ( list < Intersection > : : iterator it1 = interList . begin ( ) ; it1 ! = interList . end ( ) ; it1 + + )
for ( list < IntersectedStroke > : : iterator it2 = ( * it1 ) . m_strokeList . begin ( ) ; it2 ! = ( * it1 ) . m_strokeList . end ( ) ; it2 + + )
if ( it2 - > m_edge . m_s = = s ) {
//if (it2->m_nextIntersection==NULL)
// return; //gia' ripulita prima
if ( it2 - > m_nextIntersection ! = interList . end ( ) ) {
it2 - > m_nextIntersection = interList . end ( ) ;
it1 - > m_numInter - - ;
}
it2 - > m_nextStroke = ( * it1 ) . m_strokeList . end ( ) ;
}
}
//-----------------------------------------------------------------------------
void TVectorImage : : Imp : : eraseEdgeFromStroke ( list < IntersectedStroke > : : iterator it2 )
{
if ( it2 - > m_edge . m_index > = 0 ) //elimino il puntatore all'edge nella lista della VIStroke
{
VIStroke * s ;
s = m_strokes [ it2 - > m_edge . m_index ] ;
assert ( s - > m_s = = it2 - > m_edge . m_s ) ;
list < TEdge * > : : iterator iit = s - > m_edgeList . begin ( ) , it_e = s - > m_edgeList . end ( ) ;
for ( ; iit ! = it_e ; + + iit )
if ( ( * iit ) - > m_w0 = = it2 - > m_edge . m_w0 & & ( * iit ) - > m_w1 = = it2 - > m_edge . m_w1 ) {
assert ( ( * iit ) - > m_toBeDeleted = = false ) ;
s - > m_edgeList . erase ( iit ) ;
return ;
}
}
}
//-----------------------------------------------------------------------------
list < IntersectedStroke > : : iterator TVectorImage : : Imp : : eraseBranch ( list < Intersection > : : iterator it1 ,
list < IntersectedStroke > : : iterator it2 )
{
//list<Intersection>::iterator iit1;
//list<IntersectedStroke>::iterator iit2;
list < Intersection > & intList = m_intersectionData . m_intList ;
if ( it2 - > m_nextIntersection ! = intList . end ( ) ) {
list < Intersection > : : iterator nextInt = it2 - > m_nextIntersection ;
list < IntersectedStroke > : : iterator nextStroke = it2 - > m_nextStroke ;
assert ( nextStroke - > m_nextIntersection = = it1 ) ;
assert ( nextStroke - > m_nextStroke = = it2 ) ;
assert ( nextStroke ! = it2 ) ;
//nextStroke->m_nextIntersection = intList.end();
//nextStroke->m_nextStroke = nextInt->m_strokeList.end();
if ( nextStroke - > m_nextIntersection ! = intList . end ( ) ) {
nextStroke - > m_nextIntersection = intList . end ( ) ;
nextInt - > m_numInter - - ;
}
//nextInt->m_strokeList.erase(nextStroke);//non posso cancellarla, puo' servire in futuro!
}
if ( it2 - > m_nextIntersection ! = intList . end ( ) )
it1 - > m_numInter - - ;
eraseEdgeFromStroke ( it2 ) ;
it2 - > m_edge . m_w0 = it2 - > m_edge . m_w1 = - 3 ;
it2 - > m_edge . m_index = - 3 ;
it2 - > m_edge . m_s = 0 ;
it2 - > m_edge . m_styleId = - 3 ;
list < IntersectedStroke > : : iterator ret = ( * it1 ) . m_strokeList . erase ( it2 ) ;
return ret ;
}
//-----------------------------------------------------------------------------
void TVectorImage : : Imp : : eraseDeadIntersections ( )
{
list < Intersection > : : iterator it ;
for ( it = m_intersectionData . m_intList . begin ( ) ; it ! = m_intersectionData . m_intList . end ( ) ; ) //la faccio qui, e non nella eraseIntersection. vedi commento li'.
{
list < Intersection > & intList = m_intersectionData . m_intList ;
if ( it - > m_strokeList . size ( ) = = 1 ) {
eraseBranch ( it , ( * it ) . m_strokeList . begin ( ) ) ;
assert ( it - > m_strokeList . empty ( ) ) ;
it = intList . erase ( it ) ;
} else if ( it - > m_strokeList . size ( ) = = 2 & &
( ( * it ) . m_strokeList . front ( ) . m_edge . m_s = = ( * it ) . m_strokeList . back ( ) . m_edge . m_s & &
( * it ) . m_strokeList . front ( ) . m_edge . m_w0 = = ( * it ) . m_strokeList . back ( ) . m_edge . m_w0 ) ) //intersezione finta
{
list < IntersectedStroke > : : iterator it1 = it - > m_strokeList . begin ( ) , iit1 , iit2 ;
list < IntersectedStroke > : : iterator it2 = it1 ;
it2 + + ;
eraseEdgeFromStroke ( it1 ) ;
eraseEdgeFromStroke ( it2 ) ;
iit1 = ( it1 - > m_nextIntersection = = intList . end ( ) ) ? NULL_ITER : it1 - > m_nextStroke ;
iit2 = ( it2 - > m_nextIntersection = = intList . end ( ) ) ? NULL_ITER : it2 - > m_nextStroke ;
if ( iit1 ! = NULL_ITER & & iit2 ! = NULL_ITER ) {
iit1 - > m_edge . m_w1 = iit2 - > m_edge . m_w0 ;
iit2 - > m_edge . m_w1 = iit1 - > m_edge . m_w0 ;
}
if ( iit1 ! = NULL_ITER ) {
iit1 - > m_nextStroke = iit2 ;
iit1 - > m_nextIntersection = it2 - > m_nextIntersection ;
if ( iit1 - > m_nextIntersection = = intList . end ( ) )
it1 - > m_nextIntersection - > m_numInter - - ;
}
if ( iit2 ! = NULL_ITER ) {
iit2 - > m_nextStroke = iit1 ;
iit2 - > m_nextIntersection = it1 - > m_nextIntersection ;
if ( iit2 - > m_nextIntersection = = intList . end ( ) )
it2 - > m_nextIntersection - > m_numInter - - ;
}
it - > m_strokeList . clear ( ) ;
it - > m_numInter = 0 ;
it = intList . erase ( it ) ;
} else
+ + it ;
}
}
//-----------------------------------------------------------------------------
void TVectorImage : : Imp : : doEraseIntersection ( int index , vector < int > * toBeDeleted )
{
list < Intersection > & interList = m_intersectionData . m_intList ;
list < Intersection > : : iterator it1 = interList . begin ( ) ;
TStroke * deleteIt = 0 ;
while ( it1 ! = interList . end ( ) ) {
bool removeAutocloses = false ;
list < IntersectedStroke > : : iterator it2 = ( * it1 ) . m_strokeList . begin ( ) ;
while ( it2 ! = ( * it1 ) . m_strokeList . end ( ) ) {
IntersectedStroke & is = * it2 ;
if ( is . m_edge . m_index = = index ) {
if ( is . m_edge . m_index > = 0 )
//if (!is.m_autoclose && (is.m_edge.m_w0==1 || is.m_edge.m_w0==0))
removeAutocloses = true ;
else
deleteIt = is . m_edge . m_s ;
it2 = eraseBranch ( it1 , it2 ) ;
} else
+ + it2 ;
//checkInterList(interList);
}
if ( removeAutocloses ) //se ho tolto una stroke dall'inter corrente, tolgo tutti le stroke di autclose che partono da qui
{
assert ( toBeDeleted ) ;
for ( it2 = ( * it1 ) . m_strokeList . begin ( ) ; it2 ! = ( * it1 ) . m_strokeList . end ( ) ; it2 + + )
if ( it2 - > m_edge . m_index < 0 & & ( it2 - > m_edge . m_w0 = = 1 | | it2 - > m_edge . m_w0 = = 0 ) )
toBeDeleted - > push_back ( it2 - > m_edge . m_index ) ;
}
if ( ( * it1 ) . m_strokeList . empty ( ) )
it1 = interList . erase ( it1 ) ;
else
it1 + + ;
}
if ( deleteIt )
delete deleteIt ;
}
//-----------------------------------------------------------------------------
UINT TVectorImage : : Imp : : getFillData ( IntersectionBranch * & v )
{
//print(m_intersectionData.m_intList, "C:\\temp\\intersectionPrimaSave.txt");
list < Intersection > & intList = m_intersectionData . m_intList ;
if ( intList . empty ( ) )
return 0 ;
list < Intersection > : : iterator it1 ;
list < IntersectedStroke > : : iterator it2 ;
UINT currInt = 0 ;
vector < UINT > branchesBefore ( intList . size ( ) + 1 ) ;
branchesBefore [ 0 ] = 0 ;
UINT count = 0 , size = 0 ;
for ( it1 = intList . begin ( ) ; it1 ! = intList . end ( ) ; + + it1 , currInt + + ) {
UINT strokeListSize = it1 - > m_strokeList . size ( ) ;
size + = strokeListSize ;
branchesBefore [ currInt + 1 ] = branchesBefore [ currInt ] + strokeListSize ;
}
v = new IntersectionBranch [ size ] ;
currInt = 0 ;
for ( it1 = intList . begin ( ) ; it1 ! = intList . end ( ) ; + + it1 , currInt + + ) {
UINT currBranch = 0 ;
for ( it2 = it1 - > m_strokeList . begin ( ) ; it2 ! = it1 - > m_strokeList . end ( ) ; + + it2 , currBranch + + ) {
IntersectionBranch & b = v [ count ] ;
b . m_currInter = currInt ;
b . m_strokeIndex = it2 - > m_edge . m_index ;
b . m_w = it2 - > m_edge . m_w0 ;
b . m_style = it2 - > m_edge . m_styleId ;
//assert(b.m_style<100);
b . m_gettingOut = it2 - > m_gettingOut ;
if ( it2 - > m_nextIntersection = = intList . end ( ) )
b . m_nextBranch = count ;
else {
UINT distInt = std : : distance ( intList . begin ( ) , it2 - > m_nextIntersection ) ;
UINT distBranch = std : : distance ( it2 - > m_nextIntersection - > m_strokeList . begin ( ) , it2 - > m_nextStroke ) ;
if ( ( distInt < currInt ) | |
( distInt = = currInt & & distBranch < currBranch ) ) {
UINT posNext = branchesBefore [ distInt ] + distBranch ;
assert ( posNext < count ) ;
b . m_nextBranch = posNext ;
assert ( v [ posNext ] . m_nextBranch = = ( std : : numeric_limits < UINT > : : max ) ( ) ) ;
v [ posNext ] . m_nextBranch = count ;
} else
b . m_nextBranch = ( std : : numeric_limits < UINT > : : max ) ( ) ;
}
count + + ;
}
}
//for (UINT i=0; i<count; i++)
// assert(v[i].m_nextBranch != std::numeric_limits<UINT>::max());
# ifdef _DEBUG
/*ofstream of("C:\\temp\\fillDataOut.txt");
for ( UINT ii = 0 ; ii < size ; ii + + )
{
of < < ii < < " ---------------------- " < < endl ;
of < < " index: " < < v [ ii ] . m_strokeIndex < < endl ;
of < < " w: " < < v [ ii ] . m_w < < endl ;
of < < " curr inter: " < < v [ ii ] . m_currInter < < endl ;
of < < " next inter: " < < v [ ii ] . m_nextBranch < < endl ;
of < < " gettingOut: " < < ( ( v [ ii ] . m_gettingOut ) ? " TRUE " : " FALSE " ) < < endl ;
of < < " colorId: " < < v [ ii ] . m_style < < endl ;
} */
# endif
return size ;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
namespace
{
TStroke * reconstructAutocloseStroke ( list < Intersection > & intList ,
list < Intersection > : : iterator it1 ,
list < IntersectedStroke > : : iterator it2 )
{
bool found = false ;
list < Intersection > : : iterator iit1 = it1 ;
list < IntersectedStroke > : : iterator iit2 ;
iit1 + + ;
//vector<TEdge*> vapp;
for ( ; ! found & & iit1 ! = intList . end ( ) ; iit1 + + ) {
for ( iit2 = iit1 - > m_strokeList . begin ( ) ; ! found & & iit2 ! = iit1 - > m_strokeList . end ( ) ; iit2 + + ) {
if ( it2 - > m_edge . m_index = = iit2 - > m_edge . m_index ) {
if ( ( iit2 - > m_edge . m_w0 = = 1 & & it2 - > m_edge . m_w0 = = 0 ) | |
( iit2 - > m_edge . m_w0 = = 0 & & it2 - > m_edge . m_w0 = = 1 ) ) {
found = true ;
vector < TPointD > v ;
if ( it2 - > m_edge . m_w0 = = 0 ) {
v . push_back ( it1 - > m_intersection ) ;
v . push_back ( iit1 - > m_intersection ) ;
} else {
v . push_back ( iit1 - > m_intersection ) ;
v . push_back ( it1 - > m_intersection ) ;
}
it2 - > m_edge . m_s = iit2 - > m_edge . m_s = new TStroke ( v ) ;
//for (UINT ii=0; ii<vapp.size(); ii++)
// vapp[ii]->m_s = it2->m_edge.m_s;
}
//else if (iit2->m_edge.m_w0!=0 && iit2->m_edge.m_w0!=1)
// vapp.push_back(&(iit2->m_edge));
}
}
}
assert ( found ) ;
if ( ! found )
it2 - > m_edge . m_s = 0 ;
return it2 - > m_edge . m_s ;
}
} //namespace
//-----------------------------------------------------------------------------
void TVectorImage : : Imp : : setFillData ( IntersectionBranch * v , UINT branchCount )
{
# ifdef _DEBUG
/*ofstream of("C:\\temp\\fillDataIn.txt");
for ( UINT ii = 0 ; ii < branchCount ; ii + + )
{
of < < ii < < " ---------------------- " < < endl ;
of < < " index: " < < v [ ii ] . m_strokeIndex < < endl ;
of < < " w: " < < v [ ii ] . m_w < < endl ;
of < < " curr inter: " < < v [ ii ] . m_currInter < < endl ;
of < < " next inter: " < < v [ ii ] . m_nextBranch < < endl ;
of < < " gettingOut: " < < ( ( v [ ii ] . m_gettingOut ) ? " TRUE " : " FALSE " ) < < endl ;
of < < " colorId: " < < v [ ii ] . m_style < < endl ;
} */
# endif
if ( branchCount = = 0 )
return ;
list < Intersection > & intList = m_intersectionData . m_intList ;
clearPointerContainer ( m_regions ) ;
m_regions . clear ( ) ;
intList . clear ( ) ;
list < Intersection > : : iterator currInt ;
list < IntersectedStroke > : : iterator currBranch ;
vector < UINT > branchesBefore ( v [ branchCount - 1 ] . m_currInter + 1 ) ;
UINT i = 0 ;
for ( ; i < branchCount ; i + + ) {
const IntersectionBranch & b = v [ i ] ;
if ( i = = 0 | | v [ i ] . m_currInter ! = v [ i - 1 ] . m_currInter ) {
assert ( i = = 0 | | v [ i ] . m_currInter = = v [ i - 1 ] . m_currInter + 1 ) ;
branchesBefore [ v [ i ] . m_currInter ] = i ;
intList . push_back ( Intersection ( ) ) ;
currInt = intList . begin ( ) ;
advance ( currInt , intList . size ( ) - 1 ) ;
}
IntersectedStroke is ;
currInt - > m_strokeList . push_back ( is ) ;
currBranch = currInt - > m_strokeList . begin ( ) ;
advance ( currBranch , currInt - > m_strokeList . size ( ) - 1 ) ;
currBranch - > m_edge . m_styleId = b . m_style ;
//assert(b.m_style<100);
currBranch - > m_edge . m_index = b . m_strokeIndex ;
if ( b . m_strokeIndex > = 0 )
currBranch - > m_edge . m_s = m_strokes [ b . m_strokeIndex ] - > m_s ;
else
currBranch - > m_edge . m_s = 0 ;
currBranch - > m_gettingOut = b . m_gettingOut ;
currBranch - > m_edge . m_w0 = b . m_w ;
currBranch - > m_edge . m_w1 = v [ b . m_nextBranch ] . m_w ;
assert ( currBranch - > m_edge . m_w0 > = - 1e-8 & & currBranch - > m_edge . m_w0 < = 1 + 1e-8 ) ;
assert ( currBranch - > m_edge . m_w1 > = - 1e-8 & & currBranch - > m_edge . m_w1 < = 1 + 1e-8 ) ;
if ( b . m_nextBranch < i ) {
list < Intersection > : : iterator it1 ;
list < IntersectedStroke > : : iterator it2 ;
it1 = intList . begin ( ) ;
std : : advance ( it1 , v [ b . m_nextBranch ] . m_currInter ) ;
it2 = it1 - > m_strokeList . begin ( ) ;
assert ( b . m_nextBranch - branchesBefore [ v [ b . m_nextBranch ] . m_currInter ] > = 0 ) ;
std : : advance ( it2 , b . m_nextBranch - branchesBefore [ v [ b . m_nextBranch ] . m_currInter ] ) ;
currBranch - > m_nextIntersection = it1 ;
currBranch - > m_nextStroke = it2 ;
it2 - > m_nextIntersection = currInt ;
it2 - > m_nextStroke = currBranch ;
//if (currBranch == currInt->m_strokeList.begin())
// currInt->m_intersection = currBranch->m_edge.m_s->getPoint(currBranch->m_edge.m_w0);
currInt - > m_numInter + + ;
it1 - > m_numInter + + ;
} else if ( b . m_nextBranch = = i )
currBranch - > m_nextIntersection = intList . end ( ) ;
else if ( b . m_nextBranch = = ( std : : numeric_limits < UINT > : : max ) ( ) ) {
currBranch - > m_nextIntersection = intList . end ( ) ;
currBranch - > m_nextStroke = currInt - > m_strokeList . end ( ) ;
}
/* {
assert ( b . m_nextBranch < branchCount ) ;
assert ( v [ b . m_nextBranch ] . m_nextBranch = = i ) ;
} */
if ( i = = branchCount - 1 | | v [ i ] . m_currInter ! = v [ i + 1 ] . m_currInter ) {
int j = i ;
while ( v [ j ] . m_strokeIndex < 0 & & ( ( j > 0 & & v [ j ] . m_currInter = = v [ j - 1 ] . m_currInter ) | | j = = 0 ) )
j - - ;
if ( v [ j ] . m_strokeIndex > = 0 )
currInt - > m_intersection = m_strokes [ v [ j ] . m_strokeIndex ] - > m_s - > getPoint ( v [ j ] . m_w ) ;
}
}
for ( i = 0 ; i < m_strokes . size ( ) ; i + + )
m_strokes [ i ] - > m_isNewForFill = false ;
//computeRegions();
list < Intersection > : : iterator it1 ;
list < IntersectedStroke > : : iterator it2 ;
vector < UINT > toBeDeleted ;
for ( it1 = intList . begin ( ) ; it1 ! = intList . end ( ) ; it1 + + )
for ( it2 = it1 - > m_strokeList . begin ( ) ; it2 ! = it1 - > m_strokeList . end ( ) ; + + it2 ) {
if ( it2 - > m_edge . m_index < 0 & & ! it2 - > m_edge . m_s & &
( it2 - > m_edge . m_w0 = = 0 | | it2 - > m_edge . m_w0 = = 1 ) ) {
it2 - > m_edge . m_s = reconstructAutocloseStroke ( intList , it1 , it2 ) ;
if ( it2 - > m_edge . m_s )
m_intersectionData . m_autocloseMap [ it2 - > m_edge . m_index ] = it2 - > m_edge . m_s ;
else
toBeDeleted . push_back ( it2 - > m_edge . m_index ) ;
}
}
for ( it1 = intList . begin ( ) ; it1 ! = intList . end ( ) ; it1 + + )
for ( it2 = it1 - > m_strokeList . begin ( ) ; it2 ! = it1 - > m_strokeList . end ( ) ; + + it2 ) {
if ( ! it2 - > m_edge . m_s & & it2 - > m_edge . m_index < 0 ) {
it2 - > m_edge . m_s = m_intersectionData . m_autocloseMap [ it2 - > m_edge . m_index ] ;
//TEdge& e = it2->m_edge;
if ( ! it2 - > m_edge . m_s )
toBeDeleted . push_back ( it2 - > m_edge . m_index ) ;
}
}
for ( i = 0 ; i < toBeDeleted . size ( ) ; i + + )
eraseIntersection ( toBeDeleted [ i ] ) ;
m_areValidRegions = false ;
computeRegions ( ) ;
//print(m_intersectionData.m_intList, "C:\\temp\\intersectionDopoLoad.txt");
}
//-----------------------------------------------------------------------------
void TVectorImage : : Imp : : eraseIntersection ( int index )
{
vector < int > autocloseStrokes ;
doEraseIntersection ( index , & autocloseStrokes ) ;
for ( UINT i = 0 ; i < autocloseStrokes . size ( ) ; i + + ) {
doEraseIntersection ( autocloseStrokes [ i ] ) ;
assert ( autocloseStrokes [ i ] < 0 ) ;
m_intersectionData . m_autocloseMap . erase ( autocloseStrokes [ i ] ) ;
}
}
//-----------------------------------------------------------------------------
void findNearestIntersection ( list < Intersection > & interList )
{
list < Intersection > : : iterator i1 ;
list < IntersectedStroke > : : iterator i2 ;
for ( i1 = interList . begin ( ) ; i1 ! = interList . end ( ) ; i1 + + ) {
for ( i2 = ( * i1 ) . m_strokeList . begin ( ) ; i2 ! = ( * i1 ) . m_strokeList . end ( ) ; i2 + + ) {
if ( ( * i2 ) . m_nextIntersection ! = interList . end ( ) ) //already set
continue ;
int versus = ( i2 - > m_gettingOut ) ? 1 : - 1 ;
double minDelta = ( std : : numeric_limits < double > : : max ) ( ) ;
list < Intersection > : : iterator it1 , it1Res ;
list < IntersectedStroke > : : iterator it2 , it2Res ;
for ( it1 = i1 ; it1 ! = interList . end ( ) ; + + it1 ) {
if ( it1 = = i1 )
it2 = i2 , it2 + + ;
else
it2 = ( * it1 ) . m_strokeList . begin ( ) ;
for ( ; it2 ! = ( * it1 ) . m_strokeList . end ( ) ; + + it2 ) {
if ( ( * it2 ) . m_edge . m_index = = i2 - > m_edge . m_index & &
( * it2 ) . m_gettingOut = = ! i2 - > m_gettingOut ) {
double delta = versus * ( it2 - > m_edge . m_w0 - i2 - > m_edge . m_w0 ) ;
if ( delta > 0 & & delta < minDelta ) {
it1Res = it1 ;
it2Res = it2 ;
minDelta = delta ;
}
}
}
}
if ( minDelta ! = ( std : : numeric_limits < double > : : max ) ( ) ) {
( * it2Res ) . m_nextIntersection = i1 ;
( * it2Res ) . m_nextStroke = i2 ;
( * it2Res ) . m_edge . m_w1 = i2 - > m_edge . m_w0 ;
( * i2 ) . m_nextIntersection = it1Res ;
( * i2 ) . m_nextStroke = it2Res ;
( * i2 ) . m_edge . m_w1 = it2Res - > m_edge . m_w0 ;
i1 - > m_numInter + + ;
it1Res - > m_numInter + + ;
}
}
}
}
//-----------------------------------------------------------------------------
void markDeadIntersections ( list < Intersection > & intList ,
list < Intersection > : : iterator it ) ;
//questa funzione "cuscinetto" serve perche crashava il compilatore in release!!!
void inline markDeadIntersectionsRic ( list < Intersection > & intList ,
list < Intersection > : : iterator it )
{
markDeadIntersections ( intList , it ) ;
}
//-----------------------------------------------------------------------------
void markDeadIntersections ( list < Intersection > & intList ,
list < Intersection > : : iterator it )
{
list < IntersectedStroke > : : iterator it1 = it - > m_strokeList . begin ( ) ;
if ( it - > m_numInter = = 1 ) {
while ( it1 - > m_nextIntersection = = intList . end ( ) )
it1 + + ;
assert ( it1 ! = it - > m_strokeList . end ( ) ) ;
list < Intersection > : : iterator nextInt = it1 - > m_nextIntersection ;
list < IntersectedStroke > : : iterator nextStroke = it1 - > m_nextStroke ;
it - > m_numInter = 0 ;
it1 - > m_nextIntersection = intList . end ( ) ;
if ( nextInt ! = intList . end ( ) /*&& !nextStroke->m_dead*/ ) {
nextInt - > m_numInter - - ;
nextStroke - > m_nextIntersection = intList . end ( ) ;
markDeadIntersectionsRic ( intList , nextInt ) ;
}
} else if ( it - > m_numInter = = 2 ) //intersezione finta (forse)
{
while ( it1 ! = it - > m_strokeList . end ( ) & & it1 - > m_nextIntersection = = intList . end ( ) )
it1 + + ;
assert ( it1 ! = it - > m_strokeList . end ( ) ) ;
list < IntersectedStroke > : : iterator it2 = it1 ;
it2 + + ;
while ( it2 ! = it - > m_strokeList . end ( ) & & it2 - > m_nextIntersection = = intList . end ( ) )
it2 + + ;
assert ( it2 ! = it - > m_strokeList . end ( ) ) ;
if ( it1 - > m_edge . m_s = = it2 - > m_edge . m_s & & it1 - > m_edge . m_w0 = = it2 - > m_edge . m_w0 ) //intersezione finta
{
list < IntersectedStroke > : : iterator iit1 , iit2 ;
assert ( it1 - > m_nextIntersection ! = intList . end ( ) & & it2 - > m_nextIntersection ! = intList . end ( ) ) ;
iit1 = it1 - > m_nextStroke ;
iit2 = it2 - > m_nextStroke ;
iit2 - > m_edge . m_w1 = iit1 - > m_edge . m_w0 ;
iit1 - > m_edge . m_w1 = iit2 - > m_edge . m_w0 ;
//if (iit1!=0)
( * iit1 ) . m_nextStroke = iit2 ;
//if (iit2!=0)
( * iit2 ) . m_nextStroke = iit1 ;
//if (iit1!=0)
( * iit1 ) . m_nextIntersection = it2 - > m_nextIntersection ;
//if (iit2!=0)
( * iit2 ) . m_nextIntersection = it1 - > m_nextIntersection ;
it - > m_numInter = 0 ;
it1 - > m_nextIntersection = intList . end ( ) ;
it2 - > m_nextIntersection = intList . end ( ) ;
}
}
}
//-----------------------------------------------------------------------------
//se cross val era 0, cerco di spostarmi un po' su w per vedere come sono orientate le tangenti agli stroke...
double nearCrossVal ( TStroke * s0 , double w0 , TStroke * s1 , double w1 )
{
double ltot0 = s0 - > getLength ( ) ;
double ltot1 = s1 - > getLength ( ) ;
double dl = tmin ( ltot1 , ltot0 ) / 1000 ;
double crossVal , dl0 = dl , dl1 = dl ;
TPointD p0 , p1 ;
int count = 0 ;
if ( w0 = = 1.0 )
dl0 = - dl0 ;
if ( w1 = = 1.0 )
dl1 = - dl1 ;
double l0 = s0 - > getLength ( w0 ) + dl0 ;
double l1 = s1 - > getLength ( w1 ) + dl1 ;
do {
p0 = s0 - > getSpeed ( s0 - > getParameterAtLength ( l0 ) ) ;
p1 = s1 - > getSpeed ( s1 - > getParameterAtLength ( l1 ) ) ;
crossVal = cross ( p0 , p1 ) ;
l0 + = dl0 , l1 + = dl1 ;
count + + ;
} while ( areAlmostEqual ( crossVal , 0.0 ) & &
( ( dl0 > 0 & & l0 < ltot0 ) | | ( dl0 < 0 & & l0 > 0 ) ) & &
( ( dl1 > 0 & & l1 < ltot1 ) | | ( dl1 < 0 & & l1 > 0 ) ) ) ;
return crossVal ;
}
//-----------------------------------------------------------------------------
inline void insertBranch ( Intersection & interList , IntersectedStroke & item , bool gettingOut )
{
if ( item . m_edge . m_w0 ! = ( gettingOut ? 1.0 : 0.0 ) ) {
item . m_gettingOut = gettingOut ;
interList . m_strokeList . push_back ( item ) ;
}
}
//-----------------------------------------------------------------------------
double getAngle ( const TPointD & p0 , const TPointD & p1 )
{
double angle1 = 180 * atan2 ( p0 . x , p0 . y ) / TConsts : : pi ;
double angle2 = 180 * atan2 ( p1 . x , p1 . y ) / TConsts : : pi ;
if ( angle1 < 0 )
angle1 = 360 + angle1 ;
if ( angle2 < 0 )
angle2 = 360 + angle2 ;
return ( angle2 - angle1 ) < 0 ? 360 + angle2 - angle1 : angle2 - angle1 ;
}
//-----------------------------------------------------------------------------
//nel caso l'angolo tra due stroke in un certo w sia nullo,
// si va un po' avanti per vedere come sono orientate....
double getNearAngle ( const TStroke * s1 , double w1 , bool out1 , const TStroke * s2 , double w2 , bool out2 )
{
bool verse1 = ( out1 & & w1 < 1 ) | | ( ! out1 & & w1 = = 0 ) ;
bool verse2 = ( out2 & & w2 < 1 ) | | ( ! out2 & & w2 = = 0 ) ;
double ltot1 = s1 - > getLength ( ) ;
double ltot2 = s2 - > getLength ( ) ;
double l1 = s1 - > getLength ( w1 ) ;
double l2 = s2 - > getLength ( w2 ) ;
double dl = min ( ltot1 , ltot2 ) / 1000 ;
double dl1 = verse1 ? dl : - dl ;
double dl2 = verse2 ? dl : - dl ;
while ( ( ( verse1 & & l1 < ltot1 ) | | ( ! verse1 & & l1 > 0 ) ) & & ( ( verse2 & & l2 < ltot2 ) | | ( ! verse2 & & l2 > 0 ) ) ) {
l1 + = dl1 ;
l2 + = dl2 ;
TPointD p1 = ( out1 ? 1 : - 1 ) * s1 - > getSpeed ( s1 - > getParameterAtLength ( l1 ) ) ;
TPointD p2 = ( out2 ? 1 : - 1 ) * s2 - > getSpeed ( s2 - > getParameterAtLength ( l2 ) ) ;
double angle = getAngle ( p1 , p2 ) ;
if ( ! areAlmostEqual ( angle , 0 , 1e-9 ) )
return angle ;
}
return 0 ;
}
//-----------------------------------------------------------------------------
bool makeEdgeIntersection ( Intersection & interList , IntersectedStroke & item1 , IntersectedStroke & item2 ,
const TPointD & p1a , const TPointD & p1b , const TPointD & p2a , const TPointD & p2b )
{
double angle1 = getAngle ( p1a , p1b ) ;
double angle2 = getAngle ( p1a , p2a ) ;
double angle3 = getAngle ( p1a , p2b ) ;
double angle ;
bool eraseP1b = false , eraseP2a = false , eraseP2b = false ;
if ( areAlmostEqual ( angle1 , 0 , 1e-9 ) ) {
angle1 = getNearAngle ( item1 . m_edge . m_s , item1 . m_edge . m_w0 , true , item1 . m_edge . m_s , item1 . m_edge . m_w0 , false ) ;
if ( areAlmostEqual ( angle1 , 1e-9 ) )
eraseP1b = true ;
}
if ( areAlmostEqual ( angle2 , 0 , 1e-9 ) ) {
angle2 = getNearAngle ( item1 . m_edge . m_s , item1 . m_edge . m_w0 , true , item2 . m_edge . m_s , item2 . m_edge . m_w0 , true ) ;
if ( areAlmostEqual ( angle2 , 1e-9 ) )
eraseP2a = true ;
}
if ( areAlmostEqual ( angle3 , 0 , 1e-9 ) ) {
angle3 = getNearAngle ( item1 . m_edge . m_s , item1 . m_edge . m_w0 , true , item2 . m_edge . m_s , item2 . m_edge . m_w0 , false ) ;
if ( areAlmostEqual ( angle3 , 1e-9 ) )
eraseP2b = true ;
}
if ( areAlmostEqual ( angle1 , angle2 , 1e-9 ) ) {
angle = getNearAngle ( item1 . m_edge . m_s , item1 . m_edge . m_w0 , false , item2 . m_edge . m_s , item2 . m_edge . m_w0 , true ) ;
if ( angle ! = 0 ) {
angle2 + = angle ;
if ( angle2 > 360 )
angle2 - = 360 ;
} else
eraseP2a = true ;
}
if ( areAlmostEqual ( angle1 , angle3 , 1e-9 ) ) {
angle = getNearAngle ( item1 . m_edge . m_s , item1 . m_edge . m_w0 , false , item2 . m_edge . m_s , item2 . m_edge . m_w0 , false ) ;
if ( angle ! = 0 ) {
angle3 + = angle ;
if ( angle3 > 360 )
angle3 - = 360 ;
} else
eraseP2b = true ;
}
if ( areAlmostEqual ( angle2 , angle3 , 1e-9 ) ) {
angle = getNearAngle ( item1 . m_edge . m_s , item1 . m_edge . m_w0 , false , item2 . m_edge . m_s , item2 . m_edge . m_w0 , true ) ;
if ( angle ! = 0 ) {
angle3 + = angle ;
if ( angle3 > 360 )
angle3 - = 360 ;
} else
eraseP2b = true ;
}
int fac = ( angle1 < angle2 ) | ( ( angle1 < angle3 ) < < 1 ) | ( ( angle2 < angle3 ) < < 2 ) ;
switch ( fac ) {
CASE 0 : //p1a p2b p2a p1b
insertBranch ( interList , item1 , true ) ;
if ( ! eraseP2b )
insertBranch ( interList , item2 , false ) ;
if ( ! eraseP2a )
insertBranch ( interList , item2 , true ) ;
if ( ! eraseP1b )
insertBranch ( interList , item1 , false ) ;
CASE 1 : //p1a p2b p1b p2a
insertBranch ( interList , item1 , true ) ;
if ( ! eraseP2b )
insertBranch ( interList , item2 , false ) ;
if ( ! eraseP1b )
insertBranch ( interList , item1 , false ) ;
if ( ! eraseP2a )
insertBranch ( interList , item2 , true ) ;
CASE 2 : assert ( false ) ;
CASE 3 : //p1a p1b p2b p2a
insertBranch ( interList , item1 , true ) ;
if ( ! eraseP1b )
insertBranch ( interList , item1 , false ) ;
if ( ! eraseP2b )
insertBranch ( interList , item2 , false ) ;
if ( ! eraseP2a )
insertBranch ( interList , item2 , true ) ;
CASE 4 : //p1a p2a p2b p1b
insertBranch ( interList , item1 , true ) ;
if ( ! eraseP2a )
insertBranch ( interList , item2 , true ) ;
if ( ! eraseP2b )
insertBranch ( interList , item2 , false ) ;
if ( ! eraseP1b )
insertBranch ( interList , item1 , false ) ;
CASE 5 : assert ( false ) ;
CASE 6 : //p1a p2a p1b p2b
insertBranch ( interList , item1 , true ) ;
if ( ! eraseP2a )
insertBranch ( interList , item2 , true ) ;
if ( ! eraseP1b )
insertBranch ( interList , item1 , false ) ;
if ( ! eraseP2b )
insertBranch ( interList , item2 , false ) ;
CASE 7 : //p1a p1b p2a p2b
insertBranch ( interList , item1 , true ) ;
if ( ! eraseP1b )
insertBranch ( interList , item1 , false ) ;
if ( ! eraseP2a )
insertBranch ( interList , item2 , true ) ;
if ( ! eraseP2b )
insertBranch ( interList , item2 , false ) ;
DEFAULT :
assert ( false ) ;
}
return true ;
}
//-----------------------------------------------------------------------------
bool makeIntersection ( IntersectionData & intData , const vector < VIStroke * > & s , int ii , int jj ,
DoublePair inter , int strokeSize , Intersection & interList )
{
IntersectedStroke item1 ( intData . m_intList . end ( ) , NULL_ITER ) ,
item2 ( intData . m_intList . end ( ) , NULL_ITER ) ;
interList . m_intersection = s [ ii ] - > m_s - > getPoint ( inter . first ) ;
item1 . m_edge . m_w0 = inter . first ;
item2 . m_edge . m_w0 = inter . second ;
if ( ii > = 0 & & ii < strokeSize ) {
item1 . m_edge . m_s = s [ ii ] - > m_s ;
item1 . m_edge . m_index = ii ;
} else {
if ( ii < 0 ) {
item1 . m_edge . m_s = intData . m_autocloseMap [ ii ] ;
item1 . m_edge . m_index = ii ;
} else {
item1 . m_edge . m_s = s [ ii ] - > m_s ;
item1 . m_edge . m_index = - ( ii + intData . maxAutocloseId * 100000 ) ;
intData . m_autocloseMap [ item1 . m_edge . m_index ] = item1 . m_edge . m_s ;
}
}
if ( jj > = 0 & & jj < strokeSize ) {
item2 . m_edge . m_s = s [ jj ] - > m_s ;
item2 . m_edge . m_index = jj ;
} else {
if ( jj < 0 ) {
item2 . m_edge . m_s = intData . m_autocloseMap [ jj ] ;
item2 . m_edge . m_index = jj ;
} else {
item2 . m_edge . m_s = s [ jj ] - > m_s ;
item2 . m_edge . m_index = - ( jj + intData . maxAutocloseId * 100000 ) ;
intData . m_autocloseMap [ item2 . m_edge . m_index ] = item2 . m_edge . m_s ;
}
}
bool reversed = false ;
TPointD p0 , p0b , p1 , p1b ;
bool ret1 = item1 . m_edge . m_s - > getSpeedTwoValues ( item1 . m_edge . m_w0 , p0 , p0b ) ;
bool ret2 = item2 . m_edge . m_s - > getSpeedTwoValues ( item2 . m_edge . m_w0 , p1 , p1b ) ;
if ( ret1 | | ret2 ) //punto angoloso!!!!
return makeEdgeIntersection ( interList , item1 , item2 , p0 , p0b , p1 , p1b ) ;
double crossVal = cross ( p0 , p1 ) ;
//crossVal = cross(p0, p1);
if ( areAlmostEqual ( crossVal , 0.0 ) ) {
bool endpoint1 = ( item1 . m_edge . m_w0 = = 0.0 | | item1 . m_edge . m_w0 = = 1.0 ) ;
bool endpoint2 = ( item2 . m_edge . m_w0 = = 0.0 | | item2 . m_edge . m_w0 = = 1.0 ) ;
if ( endpoint1 & &
endpoint2 & &
( ( p0 . x * p1 . x > = 0 & & p0 . y * p1 . y > = 0 & & item1 . m_edge . m_w0 ! = item2 . m_edge . m_w0 ) | |
( p0 . x * p1 . x < = 0 & & p0 . y * p1 . y < = 0 & & item1 . m_edge . m_w0 = = item2 . m_edge . m_w0 ) ) )
//due endpoint a 180 gradi;metto
{
item1 . m_gettingOut = ( item1 . m_edge . m_w0 = = 0.0 ) ;
interList . m_strokeList . push_back ( item1 ) ;
item2 . m_gettingOut = ( item2 . m_edge . m_w0 = = 0.0 ) ;
interList . m_strokeList . push_back ( item2 ) ;
return true ;
}
//crossVal = nearCrossVal(item1.m_edge.m_s, item1.m_edge.m_w0, item2.m_edge.m_s, item2.m_edge.m_w0);
//if (areAlmostEqual(crossVal, 0.0))
// return false;
return makeEdgeIntersection ( interList , item1 , item2 , p0 , p0b , p1 , p1b ) ;
}
if ( crossVal > 0 )
reversed = true ; //std::reverse(interList.m_strokeList.begin(), interList.m_strokeList.end());
if ( item1 . m_edge . m_w0 ! = 1.0 ) {
item1 . m_gettingOut = true ;
interList . m_strokeList . push_back ( item1 ) ;
}
if ( item2 . m_edge . m_w0 ! = ( reversed ? 0.0 : 1.0 ) ) {
item2 . m_gettingOut = ! reversed ;
interList . m_strokeList . push_back ( item2 ) ;
}
if ( item1 . m_edge . m_w0 ! = 0.0 ) {
item1 . m_gettingOut = false ;
interList . m_strokeList . push_back ( item1 ) ;
}
if ( item2 . m_edge . m_w0 ! = ( reversed ? 1.0 : 0.0 ) ) {
item2 . m_gettingOut = reversed ;
interList . m_strokeList . push_back ( item2 ) ;
}
return true ;
}
//-----------------------------------------------------------------------------
/*
void checkAuto ( const vector < VIStroke * > & s )
{
for ( int i = 0 ; i < ( int ) s . size ( ) ; i + + )
for ( int j = i + 1 ; j < ( int ) s . size ( ) ; j + + )
if ( s [ i ] - > m_s - > getChunkCount ( ) = = 1 & & s [ j ] - > m_s - > getChunkCount ( ) = = 1 ) //se ha una sola quadratica, probabilmente e' un autoclose.
{
const TThickQuadratic * q = s [ i ] - > m_s - > getChunk ( 0 ) ;
const TThickQuadratic * p = s [ j ] - > m_s - > getChunk ( 0 ) ;
if ( areAlmostEqual ( q - > getP0 ( ) , p - > getP0 ( ) , 1e-2 ) & & areAlmostEqual ( q - > getP2 ( ) , p - > getP2 ( ) , 1e-2 ) )
assert ( ! " eccolo! " ) ;
if ( areAlmostEqual ( q - > getP0 ( ) , p - > getP2 ( ) , 1e-2 ) & & areAlmostEqual ( q - > getP2 ( ) , p - > getP0 ( ) , 1e-2 ) )
assert ( ! " eccolo! " ) ;
}
}
*/
//-----------------------------------------------------------------------------
bool addAutocloseIntersection ( IntersectionData & intData , vector < VIStroke * > & s ,
int ii , int jj , double w0 , double w1 , int strokeSize )
{
list < Intersection > : : reverse_iterator rit = intData . m_intList . rbegin ( ) ;
assert ( w0 > = 0.0 & & w0 < = 1.0 ) ;
assert ( w1 > = 0.0 & & w1 < = 1.0 ) ;
for ( ; rit ! = intData . m_intList . rend ( ) ; rit + + ) // evito di fare la connessione, se gia' ce
// ne e' una simile tra le stesse due stroke
{
if ( rit - > m_strokeList . size ( ) < 2 )
continue ;
list < IntersectedStroke > : : iterator is = rit - > m_strokeList . begin ( ) ;
int s0 = is - > m_edge . m_index ;
if ( s0 < 0 )
continue ;
double ww0 = is - > m_edge . m_w0 ;
is + + ;
if ( is - > m_edge . m_index = = s0 & & is - > m_edge . m_w0 = = ww0 ) {
is + + ;
if ( is = = rit - > m_strokeList . end ( ) )
continue ;
}
int s1 = is - > m_edge . m_index ;
if ( s1 < 0 )
continue ;
double ww1 = is - > m_edge . m_w0 ;
if ( ! ( ( s0 = = ii & & s1 = = jj ) | | ( s0 = = jj & & s1 = = ii ) ) )
continue ;
if ( s0 = = ii & & areAlmostEqual ( w0 , ww0 , 0.1 ) & & areAlmostEqual ( w1 , ww1 , 0.1 ) )
return false ;
else if ( s1 = = ii & & areAlmostEqual ( w0 , ww1 , 0.1 ) & & areAlmostEqual ( w1 , ww0 , 0.1 ) )
return false ;
}
vector < TPointD > v ;
v . push_back ( s [ ii ] - > m_s - > getPoint ( w0 ) ) ;
v . push_back ( s [ jj ] - > m_s - > getPoint ( w1 ) ) ;
if ( v [ 0 ] = = v [ 1 ] ) //le stroke si intersecano , ma la fottuta funzione intersect non ha trovato l'intersezione(tipicamente, questo accade agli estremi)!!!
{
addIntersection ( intData , s , ii , jj , DoublePair ( w0 , w1 ) , strokeSize ) ;
return true ;
}
//se gia e' stato messo questo autoclose, evito
for ( int i = 0 ; i < ( int ) s . size ( ) ; i + + )
if ( s [ i ] - > m_s - > getChunkCount ( ) = = 1 ) //se ha una sola quadratica, probabilmente e' un autoclose.
{
const TThickQuadratic * q = s [ i ] - > m_s - > getChunk ( 0 ) ;
if ( areAlmostEqual ( q - > getP0 ( ) , v [ 0 ] , 1e-2 ) & & areAlmostEqual ( q - > getP2 ( ) , v [ 1 ] , 1e-2 ) | |
areAlmostEqual ( q - > getP0 ( ) , v [ 1 ] , 1e-2 ) & & areAlmostEqual ( q - > getP2 ( ) , v [ 0 ] , 1e-2 ) ) {
return true ;
addIntersection ( intData , s , i , ii , DoublePair ( 0.0 , w0 ) , strokeSize ) ;
addIntersection ( intData , s , i , jj , DoublePair ( 1.0 , w1 ) , strokeSize ) ;
return true ;
}
}
s . push_back ( new VIStroke ( new TStroke ( v ) ) ) ;
addIntersection ( intData , s , s . size ( ) - 1 , ii , DoublePair ( 0.0 , w0 ) , strokeSize ) ;
addIntersection ( intData , s , s . size ( ) - 1 , jj , DoublePair ( 1.0 , w1 ) , strokeSize ) ;
return true ;
}
//-----------------------------------------------------------------------------
double g_autocloseTolerance = c_newAutocloseTolerance ;
bool makeEndPointConnections ( vector < VIStroke * > & s ,
int ii , bool isIStartPoint ,
int jj , bool isJStartPoint , IntersectionData & intData ,
int strokeSize )
{
double x0 = ( isIStartPoint ? 0.0 : 1.0 ) ;
double x1 = ( isJStartPoint ? 0.0 : 1.0 ) ;
TThickPoint p0 = s [ ii ] - > m_s - > getThickPoint ( x0 ) ;
TThickPoint p1 = s [ jj ] - > m_s - > getThickPoint ( x1 ) ;
double dist2 ;
dist2 = tdistance2 ( p0 , p1 ) ;
if ( dist2 > = 0 & & dist2 < = tmax ( ( g_autocloseTolerance = = c_oldAutocloseTolerance ) ? 9.09 : 2.0 , g_autocloseTolerance * ( p0 . thick + p1 . thick ) * ( p0 . thick + p1 . thick ) ) ) //0.01 tiene conto di quando thick==0
{
if ( ii = = jj ) {
TRectD r = s [ ii ] - > m_s - > getBBox ( ) ; //se e' un autoclose su una stroke piccolissima, creerebbe uan area trascurabile, ignoro
if ( fabs ( r . x1 - r . x0 ) < 2 & & fabs ( r . y1 - r . y0 ) < 2 )
return false ;
}
return addAutocloseIntersection ( intData , s , ii , jj , x0 , x1 , strokeSize ) ;
}
return false ;
}
/*
if ( s [ ii ] = = s [ jj ] )
return ;
dist2 = c_autocloseTolerance * tdistance2 ( p01 , p10 ) ;
if ( dist2 > 0 & & dist2 < = ( p01 . thick + p10 . thick ) * ( p01 . thick + p10 . thick ) )
addAutocloseIntersection ( intData , s , ii , jj , 1.0 , 0.0 , strokeSize ) ;
dist2 = c_autocloseTolerance * tdistance2 ( p00 , p10 ) ;
if ( ( dist2 > 0 & & dist2 < = ( p00 . thick + p10 . thick ) * ( p00 . thick + p10 . thick ) ) )
addAutocloseIntersection ( intData , s , ii , jj , 0.0 , 0.0 , strokeSize ) ;
dist2 = c_autocloseTolerance * tdistance2 ( p01 , p11 ) ;
if ( ( dist2 > 0 & & dist2 < = ( p01 . thick + p11 . thick ) * ( p01 . thick + p11 . thick ) ) )
addAutocloseIntersection ( intData , s , ii , jj , 1.0 , 1.0 , strokeSize ) ;
}
*/
//-----------------------------------------------------------------------------
double getCurlW ( TStroke * s , bool isBegin ) / / trova il punto di split su una stroke , in prossimita di un ricciolo ;
// un ricciolo c'e' se la curva ha un min o max relativo su x seguito da uno su y, o viceversa.
{
int numChunks = s - > getChunkCount ( ) ;
double dx2 , dx1 = 0 , dy2 , dy1 = 0 ;
for ( int i = 0 ; i < numChunks ; i + + ) {
const TQuadratic * q = s - > getChunk ( isBegin ? i : numChunks - 1 - i ) ;
dy2 = q - > getP1 ( ) . y - q - > getP0 ( ) . y ;
if ( dy1 * dy2 < 0 )
break ;
dy1 = dy2 ;
dy2 = q - > getP2 ( ) . y - q - > getP1 ( ) . y ;
if ( dy1 * dy2 < 0 )
break ;
dy1 = dy2 ;
}
if ( i = = numChunks )
return - 1 ;
int maxMin0 = isBegin ? i : numChunks - 1 - i ;
for ( int j = 0 ; j < numChunks ; j + + ) {
const TQuadratic * q = s - > getChunk ( isBegin ? j : numChunks - 1 - j ) ;
dx2 = q - > getP1 ( ) . x - q - > getP0 ( ) . x ;
if ( dx1 * dx2 < 0 )
break ;
dx1 = dx2 ;
dx2 = q - > getP2 ( ) . x - q - > getP1 ( ) . x ;
if ( dx1 * dx2 < 0 )
break ;
dx1 = dx2 ;
}
if ( j = = numChunks )
return - 1 ;
int maxMin1 = isBegin ? j : numChunks - 1 - j ;
return getWfromChunkAndT ( s , isBegin ? tmax ( maxMin0 , maxMin1 ) : tmin ( maxMin0 , maxMin1 ) , isBegin ? 1.0 : 0.0 ) ;
}
# ifdef Levo
bool lastIsX = false , lastIsY = false ;
for ( int i = 0 ; i < numChunks ; i + + ) {
const TThickQuadratic * q = s - > getChunk ( isBegin ? i : numChunks - 1 - i ) ;
if ( ( q - > getP0 ( ) . y < q - > getP1 ( ) . y & & q - > getP2 ( ) . y < q - > getP1 ( ) . y ) | | //la quadratica ha un minimo o massimo relativo
( q - > getP0 ( ) . y > q - > getP1 ( ) . y & & q - > getP2 ( ) . y > q - > getP1 ( ) . y ) ) {
double w = getWfromChunkAndT ( s , isBegin ? i : numChunks - 1 - i , isBegin ? 1.0 : 0.0 ) ;
if ( lastIsX ) //e' il secondo min o max relativo
return w ;
lastIsX = false ;
lastIsY = true ;
} else if ( ( q - > getP0 ( ) . x < q - > getP1 ( ) . x & & q - > getP2 ( ) . x < q - > getP1 ( ) . x ) | | //la quadratica ha un minimo o massimo relativo
( q - > getP0 ( ) . x > q - > getP1 ( ) . x & & q - > getP2 ( ) . x > q - > getP1 ( ) . x ) ) {
double w = getWfromChunkAndT ( s , isBegin ? i : numChunks - 1 - i , isBegin ? 1.0 : 0.0 ) ;
if ( lastIsY ) //e' il secondo min o max relativo
return w ;
lastIsX = true ;
lastIsY = false ;
}
}
return - 1 ;
}
# endif
//-----------------------------------------------------------------------------
void makeConnection ( vector < VIStroke * > & s , int ii , int jj , bool isBegin , IntersectionData & intData ,
int strokeSize )
{
if ( s [ ii ] - > m_s - > isSelfLoop ( ) )
return ;
double w0 = isBegin ? 0.0 : 1.0 ;
TThickPoint p0 = s [ ii ] - > m_s - > getThickPoint ( w0 ) ;
double t , dist2 ;
int index ;
TStroke sAux , * sComp ;
if ( ii = = jj ) //per trovare le intersezioni con una stroke e se stessa, si toglie il
//pezzo di stroke di cui si cercano vicinanze fino alla prima curva
{
double w = getCurlW ( s [ ii ] - > m_s , isBegin ) ;
if ( w = = - 1 )
return ;
split < TStroke > ( * ( s [ ii ] - > m_s ) , tmin ( isBegin ? 1.0 : 0.0 , w ) , tmax ( isBegin ? 1.0 : 0.0 , w ) , sAux ) ;
sComp = & sAux ;
} else
sComp = s [ jj ] - > m_s ;
if ( sComp - > getNearestChunk ( p0 , t , index , dist2 ) & & dist2 > 0 ) {
if ( ii = = jj ) {
double dummy ;
s [ jj ] - > m_s - > getNearestChunk ( sComp - > getChunk ( index ) - > getPoint ( t ) , t , index , dummy ) ;
}
//if (areAlmostEqual(w, 0.0, 0.05) || areAlmostEqual(w, 1.0, 0.05))
// return; //se w e' vicino ad un estremo, rientra nell'autoclose point to point
//if (s[jj]->m_s->getLength(w)<=s[jj]->m_s->getThickPoint(0).thick ||
// s[jj]->m_s->getLength(w, 1)<=s[jj]->m_s->getThickPoint(1).thick)
// return;
TThickPoint p1 = s [ jj ] - > m_s - > getChunk ( index ) - > getThickPoint ( t ) ;
if ( dist2 < = ( tmax ( ( g_autocloseTolerance = = c_oldAutocloseTolerance ) ? 9.09 : 2.0 , ( g_autocloseTolerance + 0.7 ) * ( p0 . thick + p1 . thick ) * ( p0 . thick + p1 . thick ) ) ) ) //0.01 tiene conto di quando thick==0
{
//if (areAlmostEqual(dist2, 0.0))
// return;
double w = getWfromChunkAndT ( s [ jj ] - > m_s , index , t ) ;
addAutocloseIntersection ( intData , s , ii , jj , w0 , w , strokeSize ) ;
}
}
}
//-----------------------------------------------------------------------------
void autoclose ( vector < VIStroke * > & s , int ii , int jj , IntersectionData & IntData ,
int strokeSize )
{
bool ret1 = false , ret2 = false , ret3 = false , ret4 = false ;
if ( ! s [ ii ] - > m_s - > isSelfLoop ( ) & & ! s [ jj ] - > m_s - > isSelfLoop ( ) ) {
ret1 = makeEndPointConnections ( s , ii , true , jj , false , IntData , strokeSize ) ;
if ( ii ! = jj ) {
ret2 = makeEndPointConnections ( s , ii , true , jj , true , IntData , strokeSize ) ;
ret3 = makeEndPointConnections ( s , ii , false , jj , true , IntData , strokeSize ) ;
ret4 = makeEndPointConnections ( s , ii , false , jj , false , IntData , strokeSize ) ;
}
}
if ( ! ret1 & & ! ret2 )
makeConnection ( s , ii , jj , true , IntData , strokeSize ) ;
if ( ! ret1 & & ! ret4 )
makeConnection ( s , jj , ii , false , IntData , strokeSize ) ;
if ( ii ! = jj ) {
if ( ! ret2 & & ! ret3 )
makeConnection ( s , jj , ii , true , IntData , strokeSize ) ;
if ( ! ret3 & & ! ret4 )
makeConnection ( s , ii , jj , false , IntData , strokeSize ) ;
}
}
//-----------------------------------------------------------------------------
TPointD inline getTangent ( const IntersectedStroke & item )
{
return ( item . m_gettingOut ? 1 : - 1 ) * item . m_edge . m_s - > getSpeed ( item . m_edge . m_w0 , item . m_gettingOut ) ;
}
//-----------------------------------------------------------------------------
void addBranch ( IntersectionData & intData , list < IntersectedStroke > & strokeList ,
const vector < VIStroke * > & s , int ii , double w , int strokeSize , bool gettingOut )
{
list < IntersectedStroke > : : iterator it1 , it2 ;
TPointD tanRef , lastTan ;
IntersectedStroke item ( intData . m_intList . end ( ) , strokeList . end ( ) ) ;
if ( ii < 0 ) {
item . m_edge . m_s = intData . m_autocloseMap [ ii ] ;
item . m_edge . m_index = ii ;
} else {
item . m_edge . m_s = s [ ii ] - > m_s ;
if ( ii < strokeSize )
item . m_edge . m_index = ii ;
else {
item . m_edge . m_index = - ( ii + intData . maxAutocloseId * 100000 ) ;
intData . m_autocloseMap [ item . m_edge . m_index ] = item . m_edge . m_s ;
}
}
item . m_edge . m_w0 = w ;
item . m_gettingOut = gettingOut ;
/*
if ( strokeList . size ( ) = = 2 ) //potrebbero essere orientati male; due branch possono stare come vogliono, ma col terzo no.
{
TPointD tan2 = getTangent ( strokeList . back ( ) ) ;
TPointD aux = getTangent ( * ( strokeList . begin ( ) ) ) ;
double crossVal = cross ( aux , tan2 ) ;
if ( areAlmostEqual ( aux , tan2 , 1e-3 ) )
return ;
if ( crossVal > 0 )
{
std : : reverse ( strokeList . begin ( ) , strokeList . end ( ) ) ;
//tan2 = getTangent(strokeList.back());
}
}
*/
/*
if ( areAlmostEqual ( lastCross , 0.0 ) & & tan1 . x * tan2 . x > = 0 & & tan1 . y * tan2 . y > = 0 ) //significa angolo tra tangenti nullo
{
crossVal = nearCrossVal ( item . m_edge . m_s , item . m_edge . m_w0 , strokeList . back ( ) . m_edge . m_s , strokeList . back ( ) . m_edge . m_w0 ) ;
if ( areAlmostEqual ( crossVal , 0.0 ) )
return ;
if ( ! strokeList . back ( ) . m_gettingOut )
crossVal = - crossVal ;
}
*/
tanRef = getTangent ( item ) ;
lastTan = getTangent ( strokeList . back ( ) ) ;
/*
for ( it = strokeList . begin ( ) ; it ! = strokeList . end ( ) ; + + it )
{
TPointD curTan = getTangent ( * it ) ;
double angle0 = getAngle ( lastTan , curTan ) ;
double angle1 = getAngle ( lastTan , tanRef ) ;
if ( areAlmostEqual ( angle0 , angle1 , 1e-8 ) )
{
double angle = getNearAngle ( it - > m_edge . m_s , it - > m_edge . m_w0 , it - > m_gettingOut ,
item . m_edge . m_s , item . m_edge . m_w0 , item . m_gettingOut ) ;
angle1 + = angle ; if ( angle1 > 360 ) angle1 - = 360 ;
}
if ( angle1 < angle0 )
{
strokeList . insert ( it , item ) ;
return ;
}
lastTan = curTan ;
} */
it2 = strokeList . end ( ) ;
it2 - - ;
for ( it1 = strokeList . begin ( ) ; it1 ! = strokeList . end ( ) ; + + it1 ) {
TPointD curTan = getTangent ( * it1 ) ;
double angle0 = getAngle ( lastTan , curTan ) ;
double angle1 = getAngle ( lastTan , tanRef ) ;
if ( areAlmostEqual ( angle1 , 0 , 1e-8 ) ) {
double angle = getNearAngle ( it2 - > m_edge . m_s , it2 - > m_edge . m_w0 , it2 - > m_gettingOut ,
item . m_edge . m_s , item . m_edge . m_w0 , item . m_gettingOut ) ;
angle1 + = angle ;
if ( angle1 > 360 )
angle1 - = 360 ;
}
if ( areAlmostEqual ( angle0 , angle1 , 1e-8 ) ) {
double angle = getNearAngle ( it1 - > m_edge . m_s , it1 - > m_edge . m_w0 , it1 - > m_gettingOut ,
item . m_edge . m_s , item . m_edge . m_w0 , item . m_gettingOut ) ;
angle1 + = angle ;
if ( angle1 > 360 )
angle1 - = 360 ;
}
if ( angle1 < angle0 ) {
strokeList . insert ( it1 , item ) ;
return ;
}
lastTan = curTan ;
it2 = it1 ;
}
//assert(!"add branch: can't find where to insert!");
strokeList . push_back ( item ) ;
}
//-----------------------------------------------------------------------------
void addBranches ( IntersectionData & intData , Intersection & intersection , const vector < VIStroke * > & s , int ii , int jj ,
DoublePair intersectionPair , int strokeSize )
{
bool foundS1 = false , foundS2 = false ;
list < IntersectedStroke > : : iterator it ;
assert ( ! intersection . m_strokeList . empty ( ) ) ;
for ( it = intersection . m_strokeList . begin ( ) ; it ! = intersection . m_strokeList . end ( ) ; it + + ) {
if ( ( ii > = 0 & & ( * it ) . m_edge . m_s = = s [ ii ] - > m_s & & it - > m_edge . m_w0 = = intersectionPair . first ) | |
( ii < 0 & & ( * it ) . m_edge . m_index = = ii & & it - > m_edge . m_w0 = = intersectionPair . first ) )
foundS1 = true ;
if ( ( jj > = 0 & & ( * it ) . m_edge . m_s = = s [ jj ] - > m_s & & it - > m_edge . m_w0 = = intersectionPair . second ) | |
( jj < 0 & & ( * it ) . m_edge . m_index = = jj & & it - > m_edge . m_w0 = = intersectionPair . second ) )
foundS2 = true ;
}
if ( foundS1 & & foundS2 ) {
/*
//errore!(vedi commento sotto) possono essere un sacco di intersezioni coincidenti se passano per l'estremo di una quad
//significa che ci sono due intersezioni coincidenti. cioe' due stroke tangenti. quindi devo invertire l'ordine di due branch enlla rosa dei branch.
list < IntersectedStroke > : : iterator it1 , it2 ;
it1 = intersection . m_strokeList . begin ( ) ;
it2 = it1 ; it2 + + ;
for ( ; it2 ! = intersection . m_strokeList . end ( ) ; + + it1 , + + it2 )
{
if ( ( * it1 ) . m_gettingOut ! = ( * it2 ) . m_gettingOut & & ( ( * it1 ) . m_edge . m_index = = jj & & ( * it2 ) . m_edge . m_index = = ii ) | |
( ( * it1 ) . m_edge . m_index = = ii & & ( * it2 ) . m_edge . m_index = = jj ) )
{
IntersectedStroke & el1 = ( * it1 ) ;
IntersectedStroke & el2 = ( * it2 ) ;
IntersectedStroke app ;
app = el1 ;
el1 = el2 ;
el2 = app ;
break ;
}
}
*/
return ;
}
if ( ! foundS1 ) {
if ( intersectionPair . first ! = 1 )
addBranch ( intData , intersection . m_strokeList , s , ii , intersectionPair . first , strokeSize , true ) ;
if ( intersectionPair . first ! = 0 )
addBranch ( intData , intersection . m_strokeList , s , ii , intersectionPair . first , strokeSize , false ) ;
//assert(intersection.m_strokeList.size()-size>0);
}
if ( ! foundS2 ) {
if ( intersectionPair . second ! = 1 )
addBranch ( intData , intersection . m_strokeList , s , jj , intersectionPair . second , strokeSize , true ) ;
if ( intersectionPair . second ! = 0 )
addBranch ( intData , intersection . m_strokeList , s , jj , intersectionPair . second , strokeSize , false ) ;
//intersection.m_numInter+=intersection.m_strokeList.size()-size;
//assert(intersection.m_strokeList.size()-size>0);
}
}
//-----------------------------------------------------------------------------
void addIntersections ( IntersectionData & intData ,
const vector < VIStroke * > & s , int ii , int jj ,
vector < DoublePair > & intersections , int strokeSize )
{
for ( int k = 0 ; k < ( int ) intersections . size ( ) ; k + + ) {
if ( ii > = strokeSize & &
( areAlmostEqual ( intersections [ k ] . first , 0.0 ) | | areAlmostEqual ( intersections [ k ] . first , 1.0 ) ) )
continue ;
if ( jj > = strokeSize & &
( areAlmostEqual ( intersections [ k ] . second , 0.0 ) | | areAlmostEqual ( intersections [ k ] . second , 1.0 ) ) )
continue ;
addIntersection ( intData , s , ii , jj , intersections [ k ] , strokeSize ) ;
}
}
//-----------------------------------------------------------------------------
inline double truncate ( double x )
{
x + = 1.0 ;
unsigned long * l = ( unsigned long * ) & x ;
# if TNZ_LITTLE_ENDIAN
l [ 0 ] & = 0xFFE00000 ;
# else
l [ 1 ] & = 0xFFE00000 ;
# endif
return x - 1.0 ;
}
//-----------------------------------------------------------------------------
void addIntersection ( IntersectionData & intData ,
const vector < VIStroke * > & s , int ii , int jj ,
DoublePair intersection , int strokeSize )
{
list < Intersection > : : iterator it ;
TPointD p ;
//UINT iw;
//iw = ((UINT)(intersection.first*0x3fffffff));
//intersection.first = truncate(intersection.first);
//iw = (UINT)(intersection.second*0x3fffffff);
//intersection.second = truncate(intersection.second);
if ( areAlmostEqual ( intersection . first , 0.0 , 1e-8 ) )
intersection . first = 0.0 ;
else if ( areAlmostEqual ( intersection . first , 1.0 , 1e-8 ) )
intersection . first = 1.0 ;
if ( areAlmostEqual ( intersection . second , 0.0 , 1e-8 ) )
intersection . second = 0.0 ;
else if ( areAlmostEqual ( intersection . second , 1.0 , 1e-8 ) )
intersection . second = 1.0 ;
p = s [ ii ] - > m_s - > getPoint ( intersection . first ) ;
for ( it = intData . m_intList . begin ( ) ; it ! = intData . m_intList . end ( ) ; it + + )
if ( ( * it ) . m_intersection = = p ) //devono essere rigorosamente uguali, altrimenti
// il calcolo dell'ordine dei rami con le tangenti sballa
{
addBranches ( intData , * it , s , ii , jj , intersection , strokeSize ) ;
return ;
}
intData . m_intList . push_back ( Intersection ( ) ) ;
if ( ! makeIntersection ( intData , s , ii , jj , intersection , strokeSize , intData . m_intList . back ( ) ) ) {
list < Intersection > : : iterator it = intData . m_intList . begin ( ) ;
advance ( it , intData . m_intList . size ( ) - 1 ) ;
intData . m_intList . erase ( it ) ;
}
}
//-----------------------------------------------------------------------------
void TVectorImage : : Imp : : findIntersections ( )
{
vector < VIStroke * > & strokeArray = m_strokes ;
IntersectionData & intData = m_intersectionData ;
int strokeSize = ( int ) strokeArray . size ( ) ;
int i , j ;
assert ( intData . m_intersectedStrokeArray . empty ( ) ) ;
intData . maxAutocloseId + + ;
map < int , TStroke * > : : iterator it , it_b = intData . m_autocloseMap . begin ( ) ;
map < int , TStroke * > : : iterator it_e = intData . m_autocloseMap . end ( ) ;
//prima cerco le intersezioni tra nuove strokes e vecchi autoclose
for ( i = 0 ; i < strokeSize ; i + + ) {
TStroke * s1 = strokeArray [ i ] - > m_s ;
if ( ! strokeArray [ i ] - > m_isNewForFill | | strokeArray [ i ] - > m_isPoint )
continue ;
TRectD bBox = s1 - > getBBox ( ) ;
double thick2 = s1 - > getThickPoint ( 0 ) . thick * 2 ;
if ( bBox . getLx ( ) < = thick2 & & bBox . getLy ( ) < = thick2 ) {
strokeArray [ i ] - > m_isPoint = true ;
continue ;
}
for ( int j = 0 ; j < ( int ) s1 - > getControlPointCount ( ) ; j + + ) {
TThickPoint p = s1 - > getControlPoint ( j ) ;
s1 - > setControlPoint ( j , myRound ( p ) ) ;
}
for ( it = it_b ; it ! = it_e ; + + it ) {
TStroke * s2 = it - > second ;
vector < DoublePair > parIntersections ;
if ( intersect ( s1 , s2 , parIntersections , true ) )
addIntersections ( intData , strokeArray , i , it - > first , parIntersections , strokeSize ) ;
}
}
//poi, intersezioni tra stroke, in cui almeno uno dei due deve essere nuovo
for ( i = 0 ; i < strokeSize ; i + + ) {
TStroke * s1 = strokeArray [ i ] - > m_s ;
if ( strokeArray [ i ] - > m_isPoint )
continue ;
for ( j = i ; j < strokeSize /*&& (strokeArray[i]->getBBox().x1>= strokeArray[j]->getBBox().x0)*/ ; j + + ) {
TStroke * s2 = strokeArray [ j ] - > m_s ;
if ( strokeArray [ j ] - > m_isPoint )
continue ;
if ( ! ( strokeArray [ i ] - > m_isNewForFill | | strokeArray [ j ] - > m_isNewForFill ) )
continue ;
vector < DoublePair > parIntersections ;
if ( s1 - > getBBox ( ) . overlaps ( s2 - > getBBox ( ) ) ) {
UINT size = intData . m_intList . size ( ) ;
if ( intersect ( s1 , s2 , parIntersections , false ) ) {
//if (i==0 && j==1) parIntersections.erase(parIntersections.begin());
addIntersections ( intData , strokeArray , i , j , parIntersections , strokeSize ) ;
}
//autoclose(strokeArray, i, j, intData, strokeSize);
if ( ! strokeArray [ i ] - > m_isNewForFill & & size ! = intData . m_intList . size ( ) & & ! strokeArray [ i ] - > m_edgeList . empty ( ) ) //aggiunte nuove intersezioni
{
intData . m_intersectedStrokeArray . push_back ( IntersectedStrokeEdges ( i ) ) ;
list < TEdge * > & _list = intData . m_intersectedStrokeArray . back ( ) . m_edgeList ;
list < TEdge * > : : const_iterator it ;
for ( it = strokeArray [ i ] - > m_edgeList . begin ( ) ; it ! = strokeArray [ i ] - > m_edgeList . end ( ) ; + + it )
_list . push_back ( new TEdge ( * * it , false ) ) ;
}
}
}
//strokeArray[i]->m_isNewForFill = false;
}
for ( i = 0 ; i < strokeSize ; i + + ) {
TStroke * s1 = strokeArray [ i ] - > m_s ;
if ( strokeArray [ i ] - > m_isPoint )
continue ;
for ( j = i ; j < strokeSize ; j + + ) {
TStroke * s2 = strokeArray [ j ] - > m_s ;
if ( strokeArray [ j ] - > m_isPoint )
continue ;
if ( ! ( strokeArray [ i ] - > m_isNewForFill | | strokeArray [ j ] - > m_isNewForFill ) )
continue ;
if ( s1 - > getBBox ( ) . overlaps ( s2 - > getBBox ( ) ) )
autoclose ( strokeArray , i , j , intData , strokeSize ) ;
}
strokeArray [ i ] - > m_isNewForFill = false ;
}
for ( i = 0 ; i < strokeSize ; i + + ) {
list < TEdge * > : : iterator it , it_b = strokeArray [ i ] - > m_edgeList . begin ( ) , it_e = strokeArray [ i ] - > m_edgeList . end ( ) ;
for ( it = it_b ; it ! = it_e ; + + it )
if ( ( * it ) - > m_toBeDeleted = = 1 )
delete * it ;
strokeArray [ i ] - > m_edgeList . clear ( ) ;
}
//si devono cercare le intersezioni con i segmenti aggiunti per l'autoclose
for ( i = strokeSize ; i < ( int ) strokeArray . size ( ) ; + + i ) {
TStroke * s1 = strokeArray [ i ] - > m_s ;
for ( j = i + 1 ; j < ( int ) strokeArray . size ( ) ; + + j ) //intersezione segmento-segmento
{
TStroke * s2 = strokeArray [ j ] - > m_s ;
vector < DoublePair > parIntersections ;
if ( intersect ( s1 , s2 , parIntersections , true ) )
addIntersections ( intData , strokeArray , i , j , parIntersections , strokeSize ) ;
}
for ( j = 0 ; j < strokeSize ; + + j ) //intersezione segmento-curva
{
if ( strokeArray [ j ] - > m_isPoint )
continue ;
TStroke * s2 = strokeArray [ j ] - > m_s ;
vector < DoublePair > parIntersections ;
if ( intersect ( s1 , s2 , parIntersections , true ) )
addIntersections ( intData , strokeArray , i , j , parIntersections , strokeSize ) ;
}
}
}
//la struttura delle intersezioni viene poi visitata per trovare
// i link tra un'intersezione e la successiva
//-----------------------------------------------------------------------------
int TVectorImage : : Imp : : computeIntersections ( )
{
list < Intersection > : : iterator it1 ;
list < IntersectedStroke > : : iterator it2 ;
IntersectionData & intData = m_intersectionData ;
int strokeSize = ( int ) m_strokes . size ( ) ;
findIntersections ( ) ;
findNearestIntersection ( intData . m_intList ) ;
//for (it1=intData.m_intList.begin(); it1!=intData.m_intList.end();) //la faccio qui, e non nella eraseIntersection. vedi commento li'.
eraseDeadIntersections ( ) ;
for ( it1 = intData . m_intList . begin ( ) ; it1 ! = intData . m_intList . end ( ) ; it1 + + )
markDeadIntersections ( intData . m_intList , it1 ) ;
//checkInterList(intData.m_intList);
return strokeSize ;
}
//-----------------------------------------------------------------------------
/*
void endPointIntersect ( const TStroke * s0 , const TStroke * s1 , vector < DoublePair > & parIntersections )
{
TPointD p00 = s0 - > getPoint ( 0 ) ;
TPointD p11 = s1 - > getPoint ( 1 ) ;
if ( tdistance2 ( p00 , p11 ) < 2 * 0.06 * 0.06 )
parIntersections . push_back ( DoublePair ( 0 , 1 ) ) ;
if ( s0 = = s1 )
return ;
TPointD p01 = s0 - > getPoint ( 1 ) ;
TPointD p10 = s1 - > getPoint ( 0 ) ;
if ( tdistance2 ( p00 , p10 ) < 2 * 0.06 * 0.06 )
parIntersections . push_back ( DoublePair ( 0 , 0 ) ) ;
if ( tdistance2 ( p01 , p10 ) < 2 * 0.06 * 0.06 )
parIntersections . push_back ( DoublePair ( 1 , 0 ) ) ;
if ( tdistance2 ( p01 , p11 ) < 2 * 0.06 * 0.06 )
parIntersections . push_back ( DoublePair ( 1 , 1 ) ) ;
}
*/
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Trova una possibile regione data una lista di punti di intersezione
TRegion * findRegion (
list < Intersection > & intList ,
list < Intersection > : : iterator it1 ,
list < IntersectedStroke > : : iterator it2 )
{
TRegion * r = new TRegion ( ) ;
int currStyle = 0 ;
list < IntersectedStroke > : : iterator itStart = it2 ;
list < Intersection > : : iterator nextIt1 ;
list < IntersectedStroke > : : iterator nextIt2 ;
//Cicla finche' t2 non punta ad uno stroke gia' visitato
while ( ! it2 - > m_visited ) {
it2 - > m_visited = true ;
// Ciclo finche' lo stroke puntato da it2 non ha un successivo punto di intersezione
do {
it2 + + ;
if ( it2 = = it1 - > m_strokeList . end ( ) ) // uso la lista come se fosse circolare
it2 = it1 - > m_strokeList . begin ( ) ;
} while ( it2 - > m_nextIntersection = = intList . end ( ) ) ;
nextIt1 = it2 - > m_nextIntersection ;
nextIt2 = it2 - > m_nextStroke ;
// Viene controllato e sistemato lo stile degli stroke
if ( it2 - > m_edge . m_styleId ! = 0 ) {
if ( currStyle = = 0 )
currStyle = it2 - > m_edge . m_styleId ;
else if ( it2 - > m_edge . m_styleId ! = currStyle ) {
currStyle = it2 - > m_edge . m_styleId ;
for ( UINT i = 0 ; i < r - > getEdgeCount ( ) ; i + + )
r - > getEdge ( i ) - > m_styleId = currStyle ;
}
} else
it2 - > m_edge . m_styleId = currStyle ;
//Aggiunge lo stroke puntato da p2 alla regione
r - > addEdge ( & it2 - > m_edge ) ;
if ( nextIt2 = = itStart )
return r ;
it1 = nextIt1 ;
it2 = nextIt2 ;
}
delete r ;
return 0 ;
}
//-----------------------------------------------------------------------------
/*
bool areEqualRegions ( const TRegion & r1 , const TRegion & r2 )
{
if ( r1 . getBBox ( ) ! = r2 . getBBox ( ) )
return false ;
if ( r1 . getEdgeCount ( ) ! = r2 . getEdgeCount ( ) )
return false ;
for ( UINT i = 0 ; i < r1 . getEdgeCount ( ) ; i + + )
{
TEdge * e1 = r1 . getEdge ( i ) ;
for ( j = 0 ; j < r2 . getEdgeCount ( ) ; j + + )
{
TEdge * e2 = r2 . getEdge ( j ) ;
if ( e1 - > m_s = = e2 - > m_s & &
tmin ( e1 - > m_w0 , e1 - > m_w1 ) = = tmin ( e2 - > m_w0 , e2 - > m_w1 ) & &
tmax ( e1 - > m_w0 , e1 - > m_w1 ) = = tmax ( e2 - > m_w0 , e2 - > m_w1 ) )
{
if ( e1 - > m_styleId & & ! e2 - > m_styleId )
e2 - > m_styleId = e1 - > m_styleId ;
else if ( e2 - > m_styleId & & ! e1 - > m_styleId )
e1 - > m_styleId = e2 - > m_styleId ;
break ;
}
}
if ( j = = r2 . getEdgeCount ( ) ) //e1 non e' uguale a nessun edge di r2
return false ;
}
return true ;
}
*/
//-----------------------------------------------------------------------------
/*
bool isMetaRegion ( const TRegion & r1 , const TRegion & r2 )
{
if ( areEqualRegions ( r1 , r2 ) )
return true ;
for ( UINT i = 0 ; i < r1 . getRegionCount ( ) ; i + + )
{
if ( isMetaRegion ( * r1 . getRegion ( i ) , r2 ) )
return true ;
}
return false ;
}
//-----------------------------------------------------------------------------
bool isMetaRegion ( const vector < TRegion * > & m_regions , const TRegion & r )
{
for ( UINT i = 0 ; i < m_regions . size ( ) ; i + + )
if ( isMetaRegion ( * ( m_regions [ i ] ) , r ) )
return true ;
return false ;
}
//-----------------------------------------------------------------------------
*/
bool isValidArea ( const vector < TRegion * > & regions , const TRegion & r )
{
double area = 0.0 ;
TPointD p , pOld /*, pAux*/ ;
int pointAdded = 0 ;
int size = r . getEdgeCount ( ) ;
if ( size = = 0 )
return false ;
//if (size<2)
// return !isMetaRegion(regions, r);
int firstControlPoint ;
int lastControlPoint ;
TEdge * e = r . getEdge ( size - 1 ) ;
pOld = e - > m_s - > getPoint ( e - > m_w1 ) ;
for ( int i = 0 ; i < size ; i + + ) {
TEdge * e = r . getEdge ( i ) ;
TStroke * s = e - > m_s ;
firstControlPoint = s - > getControlPointIndexAfterParameter ( e - > m_w0 ) ;
lastControlPoint = s - > getControlPointIndexAfterParameter ( e - > m_w1 ) ;
p = s - > getPoint ( e - > m_w0 ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
if ( firstControlPoint < = lastControlPoint ) {
if ( firstControlPoint & 0x1 )
firstControlPoint + + ;
if ( lastControlPoint - firstControlPoint < = 2 ) ///per evitare di avere troppi pochi punti....
{
p = s - > getPoint ( 0.333333 * e - > m_w0 + 0.666666 * e - > m_w1 ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
p = s - > getPoint ( 0.666666 * e - > m_w0 + 0.333333 * e - > m_w1 ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
} else
for ( int j = firstControlPoint ; j < lastControlPoint ; j + = 2 ) {
p = s - > getControlPoint ( j ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
}
} else {
firstControlPoint - - ; //this case, getControlPointIndexBEFOREParameter
lastControlPoint - - ;
if ( firstControlPoint & 0x1 )
firstControlPoint - - ;
if ( firstControlPoint - lastControlPoint < = 2 ) ///per evitare di avere troppi pochi punti....
{
p = s - > getPoint ( 0.333333 * e - > m_w0 + 0.666666 * e - > m_w1 ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
p = s - > getPoint ( 0.666666 * e - > m_w0 + 0.333333 * e - > m_w1 ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
} else
for ( int j = firstControlPoint ; j > lastControlPoint ; j - = 2 ) {
p = s - > getControlPoint ( j ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
}
}
p = s - > getPoint ( e - > m_w1 ) ;
area + = ( p . y + pOld . y ) * ( pOld . x - p . x ) ;
pOld = p ;
pointAdded + + ;
}
assert ( pointAdded > = 4 ) ;
return area > 0.5 ;
}
//-----------------------------------------------------------------------------
void transferColors ( const list < TEdge * > & oldList , const list < TEdge * > & newList , bool isStrokeChanged , bool isFlipped , bool overwriteColor ) ;
//-----------------------------------------------------------------------------
void printStrokes1 ( vector < VIStroke * > & v , int size )
{
UINT i = 0 ;
ofstream of ( " C: \\ temp \\ strokes.txt " ) ;
for ( i = 0 ; i < ( UINT ) size ; i + + ) {
TStroke * s = v [ i ] - > m_s ;
of < < " ***stroke " < < i < < endl ;
for ( UINT j = 0 ; j < ( UINT ) s - > getChunkCount ( ) ; j + + ) {
const TThickQuadratic * q = s - > getChunk ( j ) ;
of < < " s0 " < < q - > getP0 ( ) < < endl ;
of < < " s1 " < < q - > getP1 ( ) < < endl ;
of < < " s2 " < < q - > getP2 ( ) < < endl ;
of < < " ****** " < < endl ;
}
of < < endl ;
}
for ( i = size ; i < v . size ( ) ; i + + ) {
TStroke * s = v [ i ] - > m_s ;
of < < " ***Autostroke " < < i < < endl ;
of < < " s0 " < < s - > getPoint ( 0.0 ) < < endl ;
of < < " s1 " < < s - > getPoint ( 1.0 ) < < endl ;
of < < endl ;
}
}
//-----------------------------------------------------------------------------
# ifdef _DEBUG
static void printTime ( TStopWatch & sw , string name )
{
2016-04-19 01:16:18 +12:00
ostrstream ss ;
2016-03-19 06:57:51 +13:00
ss < < name < < " : " ;
sw . print ( ss ) ;
ss < < ' \n ' < < ' \0 ' ;
string s = ss . str ( ) ;
ss . freeze ( false ) ;
//TSystem::outputDebug(s);
}
# endif
//-----------------------------------------------------------------------------
void printStrokes1 ( vector < VIStroke * > & v , int size ) ;
// Trova le regioni in una TVectorImage
int TVectorImage : : Imp : : computeRegions ( )
{
# if defined(_DEBUG) && !defined(MACOSX)
TStopWatch stopWatch ;
stopWatch . start ( true ) ;
# endif
if ( ! m_computeRegions )
return 0 ;
/*if (m_intersectionData.m_computedAlmostOnce)
{
UINT i , n = m_strokes . size ( ) ;
vector < int > vv ( n ) ;
for ( i = 0 ; i < n ; + + i ) vv [ i ] = i ;
m_intersectionData . m_computedAlmostOnce = true ;
notifyChangedStrokes ( vv , vector < TStroke * > ( ) , false ) ;
return true ;
} */
g_autocloseTolerance = m_autocloseTolerance ;
//Cancella le regioni gia' esistenti per ricalcolarle
clearPointerContainer ( m_regions ) ;
m_regions . clear ( ) ;
// Controlla che ci siano degli stroke
if ( m_strokes . empty ( ) ) {
# if defined(_DEBUG) && !defined(MACOSX)
stopWatch . stop ( ) ;
# endif
return 0 ;
}
//Inizializza la lista di intersezioni intList
m_intersectionData . m_computedAlmostOnce = true ;
list < Intersection > & intList = m_intersectionData . m_intList ;
cleanIntersectionMarks ( intList ) ;
//calcolo struttura delle intersezioni
int added = 0 , notAdded = 0 ;
int strokeSize ;
strokeSize = computeIntersections ( ) ;
list < Intersection > : : iterator it1 ;
list < IntersectedStroke > : : iterator it2 ;
for ( it1 = intList . begin ( ) ; it1 ! = intList . end ( ) ; it1 + + )
for ( it2 = ( * it1 ) . m_strokeList . begin ( ) ; it2 ! = ( * it1 ) . m_strokeList . end ( ) ; it2 + + )
it2 - > m_edge . m_r = 0 ;
for ( it1 = intList . begin ( ) ; it1 ! = intList . end ( ) ; it1 + + ) {
// Controlla che il punto in questione non sia isolato
if ( it1 - > m_numInter = = 0 )
continue ;
for ( it2 = it1 - > m_strokeList . begin ( ) ; it2 ! = it1 - > m_strokeList . end ( ) ; it2 + + ) {
TRegion * region ;
// se lo stroke non unisce due punti di intersezione
// non lo considero e vado avanti con un altro stroke
if ( it2 - > m_nextIntersection = = intList . end ( ) )
continue ;
//Se lo stroke puntato da t2 non e' stato ancora visitato, trova una regione
if ( ! it2 - > m_visited & & ( region = findRegion ( intList , it1 , it2 ) ) ) {
// Se la regione e' valida la aggiunge al vettore delle regioni
if ( isValidArea ( m_regions , * region ) ) {
added + + ;
addRegion ( m_regions , region ) ;
//Lega ogni ramo della regione alla regione di appartenenza
for ( UINT i = 0 ; i < region - > getEdgeCount ( ) ; i + + ) {
TEdge * e = region - > getEdge ( i ) ;
e - > m_r = region ;
if ( e - > m_index > = 0 )
m_strokes [ e - > m_index ] - > addEdge ( e ) ;
}
} else // Se la regione non e' valida viene scartata
{
notAdded + + ;
delete region ;
}
}
}
}
if ( ! m_notIntersectingStrokes ) {
UINT i ;
for ( i = 0 ; i < m_intersectionData . m_intersectedStrokeArray . size ( ) ; i + + ) {
if ( ! m_strokes [ m_intersectionData . m_intersectedStrokeArray [ i ] . m_index ] - > m_edgeList . empty ( ) )
transferColors ( m_intersectionData . m_intersectedStrokeArray [ i ] . m_edgeList ,
m_strokes [ m_intersectionData . m_intersectedStrokeArray [ i ] . m_index ] - > m_edgeList , false , false , true ) ;
clearPointerContainer ( m_intersectionData . m_intersectedStrokeArray [ i ] . m_edgeList ) ;
m_intersectionData . m_intersectedStrokeArray [ i ] . m_edgeList . clear ( ) ;
}
m_intersectionData . m_intersectedStrokeArray . clear ( ) ;
}
assert ( m_intersectionData . m_intersectedStrokeArray . empty ( ) ) ;
//tolgo i segmenti aggiunti con l'autoclose
vector < VIStroke * > : : iterator it = m_strokes . begin ( ) ;
advance ( it , strokeSize ) ;
m_strokes . erase ( it , m_strokes . end ( ) ) ;
m_areValidRegions = true ;
# if defined(_DEBUG) && !defined(MACOSX)
# endif
return 0 ;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/*
class Branch
{
TEdge m_edge ;
bool m_out , m_visited ;
Branch * m_next ;
Branch * m_nextBranch ;
Intersection * m_intersection ;
public :
Branch * next ( )
{
assert ( m_intersection ) ;
return m_next ? m_next : m_intersection - > m_branchList ;
}
}
class Intersection
{
private :
TPointD m_intersectionPoint ;
int m_intersectionCount ;
Branch * m_branchList ;
Intersection * m_next ;
list < IntersectedStroke > m_strokeList ;
public :
AddIntersection ( int index0 , int index1 , DoublePair intersectionValues ) ;
}
*/