2016-03-19 06:57:51 +13:00
# ifndef _TVECTORIMAGEP_H_
# define _TVECTORIMAGEP_H_
# include "tstroke.h"
# include "tvectorimage.h"
# include "tregion.h"
# include "tcurves.h"
//-----------------------------------------------------------------------------
class IntersectedStroke ;
class VIStroke ;
//=============================================================================
class VIStroke ;
class TGroupId
{
public :
2016-04-19 19:32:17 +12:00
std : : vector < int > m_id ; //m_id[i-1] e' parent di m_id[i]
2016-03-19 06:57:51 +13:00
TGroupId ( )
: m_id ( ) { }
//ghost group sono i gruppi impliciti: tutti gli stroke che non fanno parte di nessun gruppo ma
//che stanno tra due gruppi fanno parte di un gruppo implicito. per convenzione un ghostGroup ha id<0
TGroupId ( TVectorImage * vi , bool isGhost ) ;
TGroupId ( const TGroupId & strokeGroup ) : m_id ( strokeGroup . m_id ) { } ;
//costruisce un gruppo partendo da un parent e da un id esistente.
TGroupId ( const TGroupId & parent , const TGroupId & id ) ;
bool operator = = ( const TGroupId & id ) const ;
bool operator ! = ( const TGroupId & id ) const { return ! ( * this = = id ) ; }
//TGroupId makeGroup(vector<VIStroke*> strokes, bool recomputeRegions=false);
//void unmakeGroup(vector<VIStroke*> strokes);
//ritrona la depth del gruppo. (0->not grouped)
int isGrouped ( bool implicit = false ) const ;
//toglie il parent; se nera gruppo semplice, gli assegna il parametro id.
void ungroup ( const TGroupId & id ) ;
//bool sameParent(const TGroupId& id) const;
bool operator ! ( ) const { return m_id . empty ( ) | | m_id [ 0 ] = = 0 ; } ;
bool operator < ( const TGroupId & id ) const ;
int getDepth ( ) const { return m_id . size ( ) ; }
int getCommonParentDepth ( const TGroupId & id ) const ;
TGroupId getParent ( ) const ;
int isParentOf ( const TGroupId & id ) const { return getCommonParentDepth ( id ) = = getDepth ( ) ; }
} ;
class VIStroke
{
public :
TStroke * m_s ;
bool m_isPoint ;
bool m_isNewForFill ;
2016-04-19 19:32:17 +12:00
std : : list < TEdge * > m_edgeList ;
2016-03-19 06:57:51 +13:00
TGroupId m_groupId ;
VIStroke ( TStroke * s , const TGroupId & StrokeId )
: m_s ( s ) , m_isPoint ( false ) , m_isNewForFill ( true ) , m_groupId ( StrokeId ) { } ;
VIStroke ( const VIStroke & s , bool sameId = true ) ;
~ VIStroke ( )
{
delete m_s ;
2016-04-19 19:32:17 +12:00
std : : list < TEdge * > : : iterator it , it_b = m_edgeList . begin ( ) , it_e = m_edgeList . end ( ) ;
2016-03-19 06:57:51 +13:00
for ( it = it_b ; it ! = it_e ; + + it )
if ( ( * it ) - > m_toBeDeleted )
delete * it ;
}
void inline addEdge ( TEdge * e ) { m_edgeList . push_back ( e ) ; }
bool inline removeEdge ( TEdge * e )
{
2016-04-19 19:32:17 +12:00
std : : list < TEdge * > : : iterator it = m_edgeList . begin ( ) ;
2016-03-19 06:57:51 +13:00
while ( it ! = m_edgeList . end ( ) & & * it ! = e )
it + + ;
if ( * it = = e ) {
m_edgeList . erase ( it ) ;
return true ;
}
return false ;
}
} ;
//-----------------------------------------------------------------------------
class IntersectionData ;
class Intersection ;
//class IntersectStroke;
# ifdef LEVO
class TAutocloseEdge : public TGeneralEdge
{
public :
TSegment m_segment ;
int m_nextStrokeIndex ;
double m_nextStrokeW ;
TAutocloseEdge ( const TSegment & segment , int nextStrokeIndex , double nextStrokeW )
: TGeneralEdge ( eAutoclose ) , m_segment ( segment ) , m_nextStrokeIndex ( nextStrokeIndex ) , m_nextStrokeW ( nextStrokeW )
{
}
} ;
# endif
//---------------------------------------------------------------------------------------------------
class TRegionFinder ;
class TVectorImage : : Imp
{
TVectorImage * m_vi ;
public :
int m_maxGroupId ;
int m_maxGhostGroupId ;
bool m_areValidRegions ;
bool m_computedAlmostOnce ;
bool m_justLoaded ;
bool m_minimizeEdges ;
bool m_notIntersectingStrokes , m_computeRegions ;
TGroupId m_insideGroup ;
2016-04-19 19:32:17 +12:00
std : : vector < VIStroke * > m_strokes ;
2016-03-19 06:57:51 +13:00
double m_autocloseTolerance ;
IntersectionData * m_intersectionData ;
2016-04-19 19:32:17 +12:00
std : : vector < TRegion * > m_regions ;
2016-03-19 06:57:51 +13:00
TThread : : Mutex * m_mutex ;
Imp ( TVectorImage * vi ) ;
~ Imp ( ) ;
void initRegionsData ( ) ;
void deleteRegionsData ( ) ;
TRegion * getRegion ( const TPointD & p ) ;
int fill ( const TPointD & p , int styleId ) ;
bool selectFill ( const TRectD & selectArea , TStroke * s , int styleId , bool onlyUnfilled , bool fillAreas , bool fillLines ) ;
void addStrokeRegionRef ( UINT strokeIndex , TRegion * region ) ;
int computeRegions ( ) ;
void reindexEdges ( UINT strokeIndex ) ;
2016-04-19 19:32:17 +12:00
void reindexEdges ( const std : : vector < int > & indexes , bool areAdded ) ;
2016-03-19 06:57:51 +13:00
void checkRegionDbConsistency ( ) ;
void cloneRegions ( TVectorImage : : Imp & out , bool doComputeRegions = true ) ;
void eraseIntersection ( int index ) ;
2016-04-15 19:44:40 +12:00
UINT getFillData ( std : : unique_ptr < TVectorImage : : IntersectionBranch [ ] > & v ) ;
void setFillData ( std : : unique_ptr < TVectorImage : : IntersectionBranch [ ] > const & v , UINT branchCount , bool doComputeRegions = true ) ;
2016-04-19 19:32:17 +12:00
void notifyChangedStrokes ( const std : : vector < int > & strokeIndexArray , const std : : vector < TStroke * > & oldVectorStrokeArray , bool areFlipped ) ;
2016-03-19 06:57:51 +13:00
void insertStrokeAt ( VIStroke * stroke , int strokeIndex , bool recomputeRegions = true ) ;
void moveStroke ( int fromIndex , int toIndex ) ;
void autoFill ( int styleId , bool oddLevel ) ;
TRegion * getRegion ( TRegionId regId , int index ) const ;
TRegion * getRegionFromLoopStroke ( int strokeIndex ) const ;
VIStroke * joinStroke ( int index1 , int index2 , int cpIndex1 , int cpIndex2 ) ;
VIStroke * joinStrokeSmoothly ( int index1 , int index2 , int cpIndex1 , int cpIndex2 ) ;
VIStroke * extendStroke ( int index , const TThickPoint & p , int cpIndex ) ;
VIStroke * extendStrokeSmoothly ( int index , const TThickPoint & p , int cpIndex ) ;
2016-04-19 19:32:17 +12:00
void removeStrokes ( const std : : vector < int > & toBeRemoved , bool deleteThem , bool recomputeRegions ) ;
2016-03-19 06:57:51 +13:00
TStroke * removeStroke ( int index , bool doComputeRegions ) ;
2016-04-19 19:32:17 +12:00
void splitStroke ( int strokeIndex , const std : : vector < DoublePair > & sortedWRanges ) ;
2016-03-19 06:57:51 +13:00
void moveStrokes ( int fromIndex , int count , int moveBefore , bool regroup ) ;
TStroke * removeEndpoints ( int strokeIndex ) ;
void restoreEndpoints ( int index , TStroke * oldStroke ) ;
int areDifferentGroup ( UINT index1 , bool isRegion1 , UINT index2 , bool isRegion2 ) const ;
void rearrangeMultiGroup ( ) ;
void reindexGroups ( Imp & img ) ;
void addRegion ( TRegion * region ) ;
2016-04-19 19:32:17 +12:00
void regroupGhosts ( std : : vector < int > & changedStrokes ) ;
2016-03-19 06:57:51 +13:00
bool inCurrentGroup ( int strokeIndex ) const ;
bool canMoveStrokes ( int strokeIndex , int count , int moveBefore ) const ;
# ifdef _DEBUG
void checkIntersections ( ) ;
2016-04-19 19:32:17 +12:00
void checkRegions ( const std : : vector < TRegion * > & regions ) ;
void printStrokes ( std : : ofstream & os ) ;
2016-03-19 06:57:51 +13:00
void checkGroups ( ) ;
# endif
# ifdef NEW_REGION_FILL
TRegionFinder * m_regionFinder ;
void resetRegionFinder ( ) ;
# endif
private :
void findRegions ( const TRectD & rect ) ;
int computeIntersections ( ) ;
void findIntersections ( ) ;
int computeEndpointsIntersections ( ) ;
//Imp(const TVectorImage::Imp &);
//Imp & operator=(const TVectorImage::Imp &);
void eraseDeadIntersections ( ) ;
IntersectedStroke * eraseBranch ( Intersection * in , IntersectedStroke * is ) ;
2016-04-19 19:32:17 +12:00
void doEraseIntersection ( int index , std : : vector < int > * toBeDeleted = 0 ) ;
2016-03-19 06:57:51 +13:00
void eraseEdgeFromStroke ( IntersectedStroke * is ) ;
2016-04-19 19:32:17 +12:00
bool areWholeGroups ( const std : : vector < int > & indexes ) const ;
2016-03-19 06:57:51 +13:00
//accorpa tutti i gruppi ghost adiacenti in uno solo, e rinomina gruppi ghost separati con lo stesso id; si usa questa funzione dopo ula creazione di un gruppo o il move di strokes
//--------------------NUOVO CALCOLO REGIONI------------------------------------------------
public :
# ifdef LEVO
vector < TRegion * > existingRegions ;
TRegion * findRegionFromStroke ( const IntersectStroke & stroke , const TPointD & p ) ;
2016-04-19 19:32:17 +12:00
bool findNextStrokes ( const TEdge & currEdge , std : : multimap < double , TGeneralEdge * > & nextEdges ) ;
2016-03-19 06:57:51 +13:00
bool addNextEdge ( TEdge & edge , TRegion & region , TRegion * & existingRegion , bool isStartingEdge = false ) ;
bool addNextEdge ( TAutocloseEdge & edge , TRegion & region , TRegion * & existingRegion ) ;
bool storeRegion ( TRegion * region , const TPointD & p ) ;
bool exploreAndAddNextEdge ( TEdge & edge , TEdge & nextEdge , TRegion & region , TRegion * & existingRegion ) ;
bool addNextAutocloseEdge ( TEdge & edge , TAutocloseEdge & nextEdge , TRegion & region , TRegion * & existingRegion ) ;
bool addNextAutocloseEdge ( TAutocloseEdge & edge , TEdge & nextEdge , TRegion & region , TRegion * & existingRegion ) ;
2016-04-19 19:32:17 +12:00
void computeAutocloseSegments ( const TEdge & currEdge , int strokeIndex , std : : multimap < double , TAutocloseEdge > & segments ) ;
void computeAutocloseSegmentsSameStroke ( const TEdge & currEdge , std : : multimap < double , TAutocloseEdge > & segments ) ;
2016-03-19 06:57:51 +13:00
# endif
//--------------------------------------------------------------------------------------
private :
// not implemented
Imp ( const Imp & ) ;
Imp & operator = ( const Imp & ) ;
} ;
2016-04-19 19:32:17 +12:00
void addRegion ( std : : vector < TRegion * > & regionArray , TRegion * region ) ;
2016-03-19 06:57:51 +13:00
//=============================================================================
# endif