int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
{
    int sum = 0;

    for( int i = 0; i < SegmentCount(); i++ )
    {
        const SEG seg = CSegment( i );
        int d = seg.Distance( aP );

        if( d <= 1 )
        {
            sum += ( aP - seg.A ).EuclideanNorm();
            return sum;
        }
        else
            sum += seg.Length();
    }

    return -1;
}
void PNS_MEANDERED_LINE::MeanderSegment( const SEG& aBase, int aBaseIndex )
{
    double base_len = aBase.Length();

    SHAPE_LINE_CHAIN lc;

    bool side = true;
    VECTOR2D dir( aBase.B - aBase.A );

    if( !m_dual )
        AddCorner( aBase.A );

    bool turning = false;
    bool started = false;

    m_last = aBase.A;

    do
    {
        PNS_MEANDER_SHAPE* m = new PNS_MEANDER_SHAPE( m_placer, m_width, m_dual );
        m->SetBaselineOffset( m_baselineOffset );
        m->SetBaseIndex( aBaseIndex );

        double thr = (double) m->spacing();

        bool fail = false;
        double remaining = base_len - ( m_last - aBase.A ).EuclideanNorm();

        if( remaining < Settings( ).m_step )
            break;

        if( remaining > 3.0 * thr )
        {
            if( !turning )
            {
                for( int i = 0; i < 2; i++ )
                {
                    if ( m->Fit( MT_CHECK_START, aBase, m_last, i ) )
                    {
                        turning = true;
                        AddMeander( m );
                        side = !i;
                        started = true;
                        break;
                    }
                }

                if( !turning )
                {
                    fail = true;

                    for( int i = 0; i < 2; i++ )
                    {
                        if ( m->Fit ( MT_SINGLE, aBase, m_last, i ) )
                        {
                            AddMeander( m );
                            fail = false;
                            started = false;
                            side = !i;
                            break;
                        }
                    }
                }
            } else {
                bool rv = m->Fit( MT_CHECK_FINISH, aBase, m_last, side );

                if( rv )
                {
                    m->Fit( MT_TURN, aBase, m_last, side );
                    AddMeander( m );
                    started = true;
                } else {
                    m->Fit( MT_FINISH, aBase, m_last, side );
                    started = false;
                    AddMeander( m );
                    turning = false;
                }

                side = !side;
            }
        } else if( started )
        {
            bool rv = m->Fit( MT_FINISH, aBase, m_last, side );
            if( rv )
                AddMeander( m );

            break;

        } else {
           fail = true;
        }

        remaining = base_len - ( m_last - aBase.A ).EuclideanNorm( );

        if( remaining < Settings( ).m_step )
            break;

        if( fail )
        {
            PNS_MEANDER_SHAPE tmp( m_placer, m_width, m_dual );
            tmp.SetBaselineOffset( m_baselineOffset );
            tmp.SetBaseIndex( aBaseIndex );

            int nextP = tmp.spacing() - 2 * tmp.cornerRadius() + Settings().m_step;
            VECTOR2I pn = m_last + dir.Resize( nextP );

            if( aBase.Contains( pn ) && !m_dual )
            {
                AddCorner( pn );
            } else
                break;
        }


    } while( true );

    if( !m_dual )
        AddCorner( aBase.B );
}