Commit 3f320e4d authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Some more comments and code formatting.

parent 6e0c7a93
Loading
Loading
Loading
Loading
+0 −11
Original line number Original line Diff line number Diff line
@@ -121,11 +121,6 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
    m_pendingRefresh = false;
    m_pendingRefresh = false;
    m_lastRefresh = wxGetLocalTimeMillis();
    m_lastRefresh = wxGetLocalTimeMillis();


#ifdef __WXDEBUG__
    prof_counter time;
    prof_start( &time, false );
#endif /* __WXDEBUG__ */

    m_gal->BeginDrawing();
    m_gal->BeginDrawing();
    m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
    m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
    m_gal->ClearScreen();
    m_gal->ClearScreen();
@@ -138,12 +133,6 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
    m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
    m_gal->DrawCursor( m_viewControls->GetCursorPosition() );


    m_gal->EndDrawing();
    m_gal->EndDrawing();

#ifdef __WXDEBUG__
    prof_end( &time );
    wxLogDebug( wxT( "EDA_DRAW_PANEL_GAL::Refresh: %.0f ms (%.0f fps)" ),
        static_cast<double>( time.value ) / 1000.0, 1000000.0 / static_cast<double>( time.value ) );
#endif /* __WXDEBUG__ */
}
}




+63 −61
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ template <typename T> int sgn(T val) {
    return ( T( 0 ) < val ) - ( val < T( 0 ) );
    return ( T( 0 ) < val ) - ( val < T( 0 ) );
}
}



bool SEG::PointCloserThan( const VECTOR2I& aP, int dist ) const
bool SEG::PointCloserThan( const VECTOR2I& aP, int dist ) const
{
{
	VECTOR2I   	  d = b - a;
	VECTOR2I   	  d = b - a;
@@ -37,13 +38,11 @@ bool SEG::PointCloserThan (const VECTOR2I& aP, int dist) const
 	SEG::ecoord l_squared = d.Dot( d );
 	SEG::ecoord l_squared = d.Dot( d );
    SEG::ecoord t = d.Dot( aP - a );
    SEG::ecoord t = d.Dot( aP - a );



    if( t <= 0 || !l_squared )
    if( t <= 0 || !l_squared )
    	return ( aP - a ).SquaredEuclideanNorm() < dist_sq;
    	return ( aP - a ).SquaredEuclideanNorm() < dist_sq;
    else if( t >= l_squared ) 
    else if( t >= l_squared ) 
    	return ( aP - b ).SquaredEuclideanNorm() < dist_sq;
    	return ( aP - b ).SquaredEuclideanNorm() < dist_sq;



	int dxdy = abs( d.x ) - abs( d.y );
	int dxdy = abs( d.x ) - abs( d.y );


    if( ( dxdy >= -1 && dxdy <= 1 ) || abs( d.x ) <= 1 || abs( d.y ) <= 1 )
    if( ( dxdy >= -1 && dxdy <= 1 ) || abs( d.x ) <= 1 || abs( d.y ) <= 1 )
@@ -71,6 +70,7 @@ bool SEG::PointCloserThan (const VECTOR2I& aP, int dist) const
    return ( nearest - aP ).SquaredEuclideanNorm() <= dist_sq;
    return ( nearest - aP ).SquaredEuclideanNorm() <= dist_sq;
}
}



SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const 
SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const 
{
{
    // fixme: rather inefficient....
    // fixme: rather inefficient....
@@ -88,9 +88,11 @@ SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const
    ecoord m = VECTOR2I::ECOORD_MAX;
    ecoord m = VECTOR2I::ECOORD_MAX;
    for( int i = 0; i < 4; i++ )
    for( int i = 0; i < 4; i++ )
        m = std::min( m, pts[i].SquaredEuclideanNorm() );
        m = std::min( m, pts[i].SquaredEuclideanNorm() );

    return m;
    return m;
}
}
	
	

OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const
OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const
{
{
	const VECTOR2I e ( b - a );
	const VECTOR2I e ( b - a );
@@ -110,7 +112,6 @@ OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines
	if ( !aLines && aIgnoreEndpoints && ( q == 0 || q == d ) && ( p == 0 || p == d ) )
	if ( !aLines && aIgnoreEndpoints && ( q == 0 || q == d ) && ( p == 0 || p == d ) )
		return OPT_VECTOR2I();
		return OPT_VECTOR2I();
	
	
	
	 VECTOR2I ip( aSeg.a.x + rescale( q, (ecoord)f.x, d ),
	 VECTOR2I ip( aSeg.a.x + rescale( q, (ecoord)f.x, d ),
	              aSeg.a.y + rescale( q, (ecoord)f.y, d ) );
	              aSeg.a.y + rescale( q, (ecoord)f.y, d ) );


@@ -123,11 +124,13 @@ bool SEG::ccw ( const VECTOR2I& a, const VECTOR2I& b, const VECTOR2I &c ) const
	return (ecoord)( c.y - a.y ) * ( b.x - a.x ) > (ecoord)( b.y - a.y ) * ( c.x - a.x );
	return (ecoord)( c.y - a.y ) * ( b.x - a.x ) > (ecoord)( b.y - a.y ) * ( c.x - a.x );
}
}



bool SEG::Collide( const SEG& aSeg, int aClearance ) const 
bool SEG::Collide( const SEG& aSeg, int aClearance ) const 
{
{
	// check for intersection 
	// check for intersection 
	// fixme: move to a method
	// fixme: move to a method
	if( ccw(a,aSeg.a,aSeg.b) != ccw(b,aSeg.a,aSeg.b) && ccw(a,b,aSeg.a) != ccw(a,b,aSeg.b) )
	if( ccw( a, aSeg.a, aSeg.b ) != ccw( b, aSeg.a, aSeg.b ) &&
	        ccw( a, b, aSeg.a ) != ccw( a, b, aSeg.b ) )
		return true;
		return true;


#define CHK(_seg, _pt) \
#define CHK(_seg, _pt) \
@@ -137,14 +140,13 @@ bool SEG::Collide( const SEG& aSeg, int aClearance ) const
	CHK( *this, aSeg.b );
	CHK( *this, aSeg.b );
	CHK( aSeg, a );
	CHK( aSeg, a );
	CHK( aSeg, b );
	CHK( aSeg, b );

#undef CHK
#undef CHK


	return false;
	return false;
}
}



bool SEG::Contains( const VECTOR2I& aP ) const
bool SEG::Contains( const VECTOR2I& aP ) const
{
{
	return PointCloserThan( aP, 1 );
	return PointCloserThan( aP, 1 );
}
}
+71 −48
Original line number Original line Diff line number Diff line
@@ -31,7 +31,8 @@


typedef VECTOR2I::extended_type ecoord;
typedef VECTOR2I::extended_type ecoord;


static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_CIRCLE& b, int clearance, bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_CIRCLE& b, int clearance,
                            bool needMTV, VECTOR2I& aMTV )
{
{
	ecoord min_dist = clearance + a.GetRadius() + b.GetRadius();
	ecoord min_dist = clearance + a.GetRadius() + b.GetRadius();
	ecoord min_dist_sq = min_dist * min_dist;
	ecoord min_dist_sq = min_dist * min_dist;
@@ -49,7 +50,8 @@ static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_CIRCLE& b, int cl
	return true;
	return true;
}
}


static inline  bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int clearance, bool needMTV, VECTOR2I& aMTV )
static inline  bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int clearance,
                             bool needMTV, VECTOR2I& aMTV )
{
{
	const VECTOR2I c = b.GetCenter();
	const VECTOR2I c = b.GetCenter();
	const VECTOR2I p0 = a.GetPosition();
	const VECTOR2I p0 = a.GetPosition();
@@ -82,7 +84,6 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
			const SEG seg( vts[i], vts[i+1] );
			const SEG seg( vts[i], vts[i+1] );
			ecoord dist_sq = seg.SquaredDistance( c );
			ecoord dist_sq = seg.SquaredDistance( c );
		
		

			if( dist_sq < min_dist_sq )
			if( dist_sq < min_dist_sq )
			{
			{
				if( !needMTV )
				if( !needMTV )
@@ -112,7 +113,9 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
	return true;
	return true;
}
}


static inline  bool Collide( const SHAPE_CIRCLE& a, const SHAPE_LINE_CHAIN& b, int clearance, bool needMTV, VECTOR2I& aMTV )

static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_LINE_CHAIN& b, int clearance,
                            bool needMTV, VECTOR2I& aMTV )
{
{
	for( int s = 0; s < b.SegmentCount(); s++ )
	for( int s = 0; s < b.SegmentCount(); s++ )
	{
	{
@@ -123,7 +126,9 @@ static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_LINE_CHAIN& b, i
	return false;	
	return false;	
}
}


static inline bool Collide( const SHAPE_LINE_CHAIN& a, const SHAPE_LINE_CHAIN& b, int clearance, bool needMTV, VECTOR2I& aMTV )

static inline bool Collide( const SHAPE_LINE_CHAIN& a, const SHAPE_LINE_CHAIN& b, int clearance,
                            bool needMTV, VECTOR2I& aMTV )
{
{
	for( int i = 0; i < b.SegmentCount(); i++ )
	for( int i = 0; i < b.SegmentCount(); i++ )
		if( a.Collide( b.CSegment(i), clearance ) )
		if( a.Collide( b.CSegment(i), clearance ) )
@@ -132,7 +137,8 @@ static inline bool Collide( const SHAPE_LINE_CHAIN& a, const SHAPE_LINE_CHAIN& b
}
}




static inline bool Collide( const SHAPE_RECT& a, const SHAPE_LINE_CHAIN& b, int clearance, bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_RECT& a, const SHAPE_LINE_CHAIN& b, int clearance,
                            bool needMTV, VECTOR2I& aMTV )
{
{
	for( int s = 0; s < b.SegmentCount(); s++ )
	for( int s = 0; s < b.SegmentCount(); s++ )
	{
	{
@@ -145,7 +151,6 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_LINE_CHAIN& b, int
}
}





bool CollideShapes( const SHAPE* a, const SHAPE* b, int clearance, bool needMTV, VECTOR2I& aMTV )
bool CollideShapes( const SHAPE* a, const SHAPE* b, int clearance, bool needMTV, VECTOR2I& aMTV )
{
{
	switch( a->Type() )
	switch( a->Type() )
@@ -154,9 +159,13 @@ bool CollideShapes ( const SHAPE *a, const SHAPE *b, int clearance, bool needMTV
			switch( b->Type() )
			switch( b->Type() )
			{
			{
				case SH_CIRCLE:
				case SH_CIRCLE:
					return Collide( *static_cast<const SHAPE_RECT *> (a), *static_cast<const SHAPE_CIRCLE *> (b), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_RECT*>( a ),
					        *static_cast<const SHAPE_CIRCLE*>( b ), clearance, needMTV, aMTV );

				case SH_LINE_CHAIN:
				case SH_LINE_CHAIN:
					return Collide( *static_cast<const SHAPE_RECT *> (a), *static_cast<const SHAPE_LINE_CHAIN *> (b), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_RECT*>( a ),
					        *static_cast<const SHAPE_LINE_CHAIN*>( b ), clearance, needMTV, aMTV );

				default:
				default:
					break;
					break;
			}
			}
@@ -165,11 +174,17 @@ bool CollideShapes ( const SHAPE *a, const SHAPE *b, int clearance, bool needMTV
			switch( b->Type() )
			switch( b->Type() )
			{
			{
				case SH_RECT:
				case SH_RECT:
					return Collide( *static_cast<const SHAPE_RECT *> (b), *static_cast<const SHAPE_CIRCLE *> (a), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_RECT*>( b ),
					        *static_cast<const SHAPE_CIRCLE*>( a ), clearance, needMTV, aMTV );

				case SH_CIRCLE:
				case SH_CIRCLE:
					return Collide( *static_cast<const SHAPE_CIRCLE *> (a), *static_cast<const SHAPE_CIRCLE *> (b), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_CIRCLE*>( a ),
					        *static_cast<const SHAPE_CIRCLE*>( b ), clearance, needMTV, aMTV );

				case SH_LINE_CHAIN:
				case SH_LINE_CHAIN:
					return Collide( *static_cast<const SHAPE_CIRCLE *> (a), *static_cast<const SHAPE_LINE_CHAIN *> (b), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_CIRCLE*>( a ),
					        *static_cast<const SHAPE_LINE_CHAIN *>( b ), clearance, needMTV, aMTV );

				default:
				default:
					break;
					break;
			}
			}
@@ -178,14 +193,21 @@ bool CollideShapes ( const SHAPE *a, const SHAPE *b, int clearance, bool needMTV
			switch( b->Type() )
			switch( b->Type() )
			{
			{
				case SH_RECT:
				case SH_RECT:
					return Collide( *static_cast<const SHAPE_RECT *> (b), *static_cast<const SHAPE_LINE_CHAIN *> (a), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_RECT*>( b ),
					        *static_cast<const SHAPE_LINE_CHAIN*>( a ), clearance, needMTV, aMTV );

				case SH_CIRCLE:
				case SH_CIRCLE:
					return Collide( *static_cast<const SHAPE_CIRCLE *> (b), *static_cast<const SHAPE_LINE_CHAIN *> (a), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_CIRCLE*>( b ),
					        *static_cast<const SHAPE_LINE_CHAIN*>( a ), clearance, needMTV, aMTV );

				case SH_LINE_CHAIN:
				case SH_LINE_CHAIN:
					return Collide( *static_cast<const SHAPE_LINE_CHAIN *> (a), *static_cast<const SHAPE_LINE_CHAIN *> (b), clearance, needMTV, aMTV );
					return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( a ),
					        *static_cast<const SHAPE_LINE_CHAIN*>( b ), clearance, needMTV, aMTV );

				default:
				default:
					break;
					break;
			}
			}

		default:
		default:
			break;
			break;
	}
	}
@@ -193,6 +215,7 @@ bool CollideShapes ( const SHAPE *a, const SHAPE *b, int clearance, bool needMTV
	bool unsupported_collision = true;
	bool unsupported_collision = true;


	assert( unsupported_collision == false );
	assert( unsupported_collision == false );

	return false;
	return false;
}
}


@@ -202,9 +225,9 @@ bool SHAPE::Collide ( const SHAPE *aShape, int aClerance, VECTOR2I& aMTV ) const
	return CollideShapes( this, aShape, aClerance, true, aMTV);
	return CollideShapes( this, aShape, aClerance, true, aMTV);
}
}



bool SHAPE::Collide ( const SHAPE* aShape, int aClerance ) const
bool SHAPE::Collide ( const SHAPE* aShape, int aClerance ) const
{
{
	VECTOR2I dummy;
	VECTOR2I dummy;
	return CollideShapes( this, aShape, aClerance, false, dummy );
	return CollideShapes( this, aShape, aClerance, false, dummy );
}
}
+0 −1
Original line number Original line Diff line number Diff line
@@ -30,4 +30,3 @@ const SHAPE* shapeFunctor( SHAPE* aItem )
{
{
    return aItem;
    return aItem;
}
}
+225 −170
Original line number Original line Diff line number Diff line
@@ -34,12 +34,14 @@ bool SHAPE_LINE_CHAIN::Collide ( const VECTOR2I& aP, int aClearance ) const
	return false;
	return false;
}
}



bool SHAPE_LINE_CHAIN::Collide( const BOX2I& aBox, int aClearance ) const
bool SHAPE_LINE_CHAIN::Collide( const BOX2I& aBox, int aClearance ) const
{
{
	assert( false );
	assert( false );
	return false;
	return false;
}
}



bool SHAPE_LINE_CHAIN::Collide( const SEG& aSeg, int aClearance ) const
bool SHAPE_LINE_CHAIN::Collide( const SEG& aSeg, int aClearance ) const
{
{
	BOX2I box_a( aSeg.a, aSeg.b - aSeg.a );
	BOX2I box_a( aSeg.a, aSeg.b - aSeg.a );
@@ -58,6 +60,7 @@ bool SHAPE_LINE_CHAIN::Collide ( const SEG& aSeg, int aClearance ) const
				return true;
				return true;
		}
		}
	}
	}

	return false;
	return false;
}
}


@@ -76,53 +79,61 @@ int SHAPE_LINE_CHAIN::Length() const
	int l = 0;
	int l = 0;
	for( int i = 0; i < SegmentCount(); i++ )
	for( int i = 0; i < SegmentCount(); i++ )
		l += CSegment( i ).Length();
		l += CSegment( i ).Length();

	return l;
	return l;
}
}


void SHAPE_LINE_CHAIN::Replace( int start_index, int end_index, const VECTOR2I& aP)				

void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP )
{
{
	if(end_index < 0)
	if( aEndIndex < 0 )
		end_index += PointCount();
		aEndIndex += PointCount();
	if(start_index < 0)
	if( aStartIndex < 0 )
		start_index += PointCount();
		aStartIndex += PointCount();


	if (start_index == end_index)
	if( aStartIndex == aEndIndex )
		m_points [start_index] = aP;
		m_points [aStartIndex] = aP;
	else {
	else
		m_points.erase (m_points.begin() + start_index + 1, m_points.begin() + end_index + 1);
	{
		m_points [start_index] = aP;
		m_points.erase( m_points.begin() + aStartIndex + 1, m_points.begin() + aEndIndex + 1 );
		m_points[aStartIndex] = aP;
	}
	}
}
}


void SHAPE_LINE_CHAIN::Replace( int start_index, int end_index, const SHAPE_LINE_CHAIN& aLine)				

void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine )
{
{
	if(end_index < 0)
	if( aEndIndex < 0 )
		end_index += PointCount();
		aEndIndex += PointCount();
	if(start_index < 0)
	if( aStartIndex < 0 )
		start_index += PointCount();
		aStartIndex += PointCount();


	m_points.erase (m_points.begin() + start_index, m_points.begin() + end_index + 1);
	m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
	m_points.insert (m_points.begin() + start_index, aLine.m_points.begin(), aLine.m_points.end());
	m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() );
}
}


void SHAPE_LINE_CHAIN::Remove( int start_index, int end_index)				

void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
{
{
	if(end_index < 0)
	if(aEndIndex < 0)
		end_index += PointCount();
		aEndIndex += PointCount();
	if(start_index < 0)
	if(aStartIndex < 0)
		start_index += PointCount();
		aStartIndex += PointCount();


	m_points.erase (m_points.begin() + start_index, m_points.begin() + end_index + 1);
	m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
}
}



int SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP ) const
int SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP ) const
{
{
	int d = INT_MAX;
	int d = INT_MAX;
	for( int s = 0; s < SegmentCount(); s++ )
	for( int s = 0; s < SegmentCount(); s++ )
		d = min( d, CSegment( s ).Distance( aP ) );
		d = min( d, CSegment( s ).Distance( aP ) );

	return d;
	return d;
}
}



int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP )
int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP )
{
{
	int ii = -1;
	int ii = -1;
@@ -150,41 +161,49 @@ int SHAPE_LINE_CHAIN::Split( const VECTOR2I & aP )
	if( ii >= 0 )
	if( ii >= 0 )
	{
	{
		m_points.insert( m_points.begin() + ii + 1, aP );
		m_points.insert( m_points.begin() + ii + 1, aP );

		return ii + 1;
		return ii + 1;
	}
	}


	return -1;
	return -1;
}
}



int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
{
{
	for( int s = 0; s< PointCount(); s++ )
	for( int s = 0; s< PointCount(); s++ )
		if( CPoint( s ) == aP )
		if( CPoint( s ) == aP )
			return s;
			return s;

	return -1;
	return -1;
}
}


const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int start_index, int end_index ) const

const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
{
{
	SHAPE_LINE_CHAIN rv;
	SHAPE_LINE_CHAIN rv;
	
	
	if(end_index < 0)
	if( aEndIndex < 0 )
		end_index += PointCount();
		aEndIndex += PointCount();
	if(start_index < 0)
	if( aStartIndex < 0 )
		start_index += PointCount();
		aStartIndex += PointCount();


	for(int i = start_index; i<= end_index; i++)
	for( int i = aStartIndex; i <= aEndIndex; i++ )
		rv.Append( m_points[i] );
		rv.Append( m_points[i] );

	return rv;
	return rv;
}
}


struct compareOriginDistance {

struct compareOriginDistance
{
	compareOriginDistance( VECTOR2I& aOrigin ):
	compareOriginDistance( VECTOR2I& aOrigin ):
		m_origin( aOrigin ) {};
		m_origin( aOrigin ) {};


	bool operator()(const SHAPE_LINE_CHAIN::Intersection &a, const SHAPE_LINE_CHAIN::Intersection& b) 
	bool operator()( const SHAPE_LINE_CHAIN::Intersection& aA,
	                 const SHAPE_LINE_CHAIN::Intersection& aB )
	{
	{
		return (m_origin - a.p).EuclideanNorm() < (m_origin - b.p).EuclideanNorm();
		return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm();
	}
	}


	VECTOR2I m_origin;
	VECTOR2I m_origin;
@@ -208,8 +227,10 @@ int SHAPE_LINE_CHAIN::Intersect ( const SEG& aSeg, Intersections& aIp ) const


	compareOriginDistance comp( aSeg.a );
	compareOriginDistance comp( aSeg.a );
	sort( aIp.begin(), aIp.end(), comp );
	sort( aIp.begin(), aIp.end(), comp );

	return aIp.size();
	return aIp.size();
};
}



int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, Intersections& aIp ) const
int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, Intersections& aIp ) const
{
{
@@ -228,14 +249,15 @@ BOX2I bb_other = aChain.BBox();
			const SEG& b = aChain.CSegment( s2 );
			const SEG& b = aChain.CSegment( s2 );
			Intersection is;
			Intersection is;
			
			
			
			if( a.Collinear( b ) )
			if( a.Collinear( b ) )
			{
			{
				if( a.Contains( b.a ) ) { is.p = b.a; aIp.push_back( is ); }
				if( a.Contains( b.a ) ) { is.p = b.a; aIp.push_back( is ); }
				if( a.Contains( b.b ) ) { is.p = b.b; aIp.push_back( is ); }
				if( a.Contains( b.b ) ) { is.p = b.b; aIp.push_back( is ); }
				if( b.Contains( a.a ) ) { is.p = a.a; aIp.push_back( is ); }
				if( b.Contains( a.a ) ) { is.p = a.a; aIp.push_back( is ); }
				if( b.Contains( a.b ) ) { is.p = a.b; aIp.push_back( is ); }
				if( b.Contains( a.b ) ) { is.p = a.b; aIp.push_back( is ); }
			} else {
			}
			else
			{
				OPT_VECTOR2I p = a.Intersect( b );
				OPT_VECTOR2I p = a.Intersect( b );
				
				
				if( p )
				if( p )
@@ -252,6 +274,7 @@ BOX2I bb_other = aChain.BBox();
	return aIp.size();
	return aIp.size();


	for( int s1 = 0; s1 < SegmentCount(); s1++ )
	for( int s1 = 0; s1 < SegmentCount(); s1++ )
	{
		for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
		for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
		{
		{
			const SEG& a = CSegment( s1 );
			const SEG& a = CSegment( s1 );
@@ -265,7 +288,8 @@ BOX2I bb_other = aChain.BBox();
				is.our = a;
				is.our = a;
				is.their = b;
				is.their = b;
				aIp.push_back( is );
				aIp.push_back( is );
			} else if (a.Collinear(b))
			}
			else if( a.Collinear( b ) )
			{
			{
				if( a.a != b.a && a.a != b.b && b.Contains( a.a ) )
				if( a.a != b.a && a.a != b.b && b.Contains( a.a ) )
				{
				{
@@ -284,9 +308,12 @@ BOX2I bb_other = aChain.BBox();


			}
			}
		}
		}
	}

	return aIp.size();
	return aIp.size();
}
}



int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
{
{
	int sum = 0;
	int sum = 0;
@@ -294,6 +321,7 @@ int SHAPE_LINE_CHAIN::PathLength (const VECTOR2I& aP ) const
	{
	{
		const SEG seg = CSegment( i );
		const SEG seg = CSegment( i );
		int d = seg.Distance( aP );
		int d = seg.Distance( aP );

		if( d <= 1 )
		if( d <= 1 )
		{
		{
			sum += ( aP - seg.a ).EuclideanNorm();
			sum += ( aP - seg.a ).EuclideanNorm();
@@ -302,29 +330,36 @@ int SHAPE_LINE_CHAIN::PathLength (const VECTOR2I& aP ) const
		else
		else
			sum += seg.Length();
			sum += seg.Length();
	}
	}

	return -1;
	return -1;
}
}



bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
{
{
	if( !m_closed || SegmentCount() < 3 )
	if( !m_closed || SegmentCount() < 3 )
		return false;
		return false;


	int cur = CSegment(0).Side( aP );
	int cur = CSegment(0).Side( aP );

	if( cur == 0 )
	if( cur == 0 )
		return false;
		return false;


	for( int i = 1; i < SegmentCount(); i++ )
	for( int i = 1; i < SegmentCount(); i++ )
	{
	{
		const SEG s = CSegment( i );
		const SEG s = CSegment( i );

		if( aP == s.a || aP == s.b ) // edge does not belong to the interior!
		if( aP == s.a || aP == s.b ) // edge does not belong to the interior!
			return false;
			return false;

		if( s.Side(aP) != cur )
		if( s.Side(aP) != cur )
			return false;
			return false;
    }
    }

	return true;
	return true;
}
}
	
	

bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
{
{
	if( SegmentCount() < 1 )
	if( SegmentCount() < 1 )
@@ -333,18 +368,22 @@ bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP) const
	for( int i = 1; i < SegmentCount(); i++ )
	for( int i = 1; i < SegmentCount(); i++ )
	{
	{
		const SEG s = CSegment( i );
		const SEG s = CSegment( i );
		
		if( s.a == aP || s.b == aP )
		if( s.a == aP || s.b == aP )
			return true;
			return true;


		if( s.Distance(aP) <= 1 )
		if( s.Distance(aP) <= 1 )
			return true;
			return true;
	}
	}

	return false;
	return false;
}
}



const optional<SHAPE_LINE_CHAIN::Intersection> SHAPE_LINE_CHAIN::SelfIntersecting() const
const optional<SHAPE_LINE_CHAIN::Intersection> SHAPE_LINE_CHAIN::SelfIntersecting() const
{
{
	for( int s1 = 0; s1 < SegmentCount(); s1++ )
	for( int s1 = 0; s1 < SegmentCount(); s1++ )
	{
		for( int s2 = s1 + 1; s2 < SegmentCount(); s2++ )
		for( int s2 = s1 + 1; s2 < SegmentCount(); s2++ )
		{
		{
			const VECTOR2I s2a = CSegment( s2 ).a, s2b = CSegment( s2 ).b;
			const VECTOR2I s2a = CSegment( s2 ).a, s2b = CSegment( s2 ).b;
@@ -355,14 +394,17 @@ const optional<SHAPE_LINE_CHAIN::Intersection> SHAPE_LINE_CHAIN::SelfIntersectin
				is.their = CSegment( s2 );
				is.their = CSegment( s2 );
				is.p = s2a;
				is.p = s2a;
				return is;
				return is;
			} else if (CSegment(s1).Contains(s2b)) {
			}
			else if( CSegment( s1 ).Contains(s2b ) )
			{
				Intersection is;
				Intersection is;
				is.our = CSegment( s1 );
				is.our = CSegment( s1 );
				is.their = CSegment( s2 );
				is.their = CSegment( s2 );
				is.p = s2b;
				is.p = s2b;
				return is;
				return is;

			}
			} else {
			else
			{
				OPT_VECTOR2I p = CSegment( s1 ).Intersect( CSegment( s2 ), true );
				OPT_VECTOR2I p = CSegment( s1 ).Intersect( CSegment( s2 ), true );
			
			
				if( p )
				if( p )
@@ -375,6 +417,8 @@ const optional<SHAPE_LINE_CHAIN::Intersection> SHAPE_LINE_CHAIN::SelfIntersectin
				}
				}
			}
			}
		}
		}
	}

	return optional<Intersection>();
	return optional<Intersection>();
}
}
		
		
@@ -386,9 +430,12 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
	if( PointCount() < 2 )
	if( PointCount() < 2 )
	{
	{
		return *this;
		return *this;
	} else if (PointCount() == 2) {
	}
	else if( PointCount() == 2 )
	{
		if( m_points[0] == m_points[1] )
		if( m_points[0] == m_points[1] )
			m_points.erase( m_points.end() );
			m_points.erase( m_points.end() );

		return *this;
		return *this;
	}
	}


@@ -401,6 +448,7 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
		int j = i + 1;
		int j = i + 1;
		while( j < np && CPoint(i) == CPoint( j ) )
		while( j < np && CPoint(i) == CPoint( j ) )
			j++;
			j++;

		pts_unique.push_back( CPoint( i ) );
		pts_unique.push_back( CPoint( i ) );
		i = j;
		i = j;
	}
	}
@@ -415,27 +463,32 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
		const VECTOR2I p0 = pts_unique[i];
		const VECTOR2I p0 = pts_unique[i];
		const VECTOR2I p1 = pts_unique[i+1];
		const VECTOR2I p1 = pts_unique[i+1];
		int n = i;
		int n = i;

		while( n < np - 2 && SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1 )
		while( n < np - 2 && SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1 )
			n++;
			n++;
		
		
		m_points.push_back( p0 );
		m_points.push_back( p0 );
		if( n > i )
		if( n > i )
			i = n;
			i = n;

		if( n == np )
		if( n == np )
		{
		{
			m_points.push_back( pts_unique[n - 1] );
			m_points.push_back( pts_unique[n - 1] );
			return *this;
			return *this;
		}
		}

		i++;
		i++;
	}
	}


	if( np > 1 )
	if( np > 1 )
		m_points.push_back( pts_unique[np - 2] );
		m_points.push_back( pts_unique[np - 2] );

	m_points.push_back( pts_unique[np - 1] );
	m_points.push_back( pts_unique[np - 1] );


	return *this;
	return *this;
}
}



const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const
const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const
{
{
	int min_d = INT_MAX;
	int min_d = INT_MAX;
@@ -449,9 +502,11 @@ const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint(const VECTOR2I& aP) const
			nearest = i;
			nearest = i;
		}
		}
	}
	}

	return CSegment( nearest ).NearestPoint( aP );
	return CSegment( nearest ).NearestPoint( aP );
}
}



const string SHAPE_LINE_CHAIN::Format() const
const string SHAPE_LINE_CHAIN::Format() const
{
{
	stringstream ss;
	stringstream ss;
Loading