VECTOR2I GRID_HELPER::AlignToSegment ( const VECTOR2I& aPoint, const SEG& aSeg ) { OPT_VECTOR2I pts[6]; const VECTOR2D gridOffset( GetOrigin() ); const VECTOR2D gridSize( GetGrid() ); VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x, KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y ); pts[0] = aSeg.A; pts[1] = aSeg.B; pts[2] = aSeg.IntersectLines( SEG( nearest, nearest + VECTOR2I( 1, 0 ) ) ); pts[3] = aSeg.IntersectLines( SEG( nearest, nearest + VECTOR2I( 0, 1 ) ) ); int min_d = std::numeric_limits<int>::max(); for( int i = 0; i < 4; i++ ) { if( pts[i] && aSeg.Contains( *pts[i] ) ) { int d = (*pts[i] - aPoint).EuclideanNorm(); if( d < min_d ) { min_d = d; nearest = *pts[i]; } } } return nearest; }
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 ); }
OPT_BOX2I PNS_LINE::ChangedArea( const PNS_LINE* aOther ) const { BOX2I area; bool areaDefined = false; int i_start = -1; int i_end_self = -1, i_end_other = -1; SHAPE_LINE_CHAIN self( m_line ); self.Simplify(); SHAPE_LINE_CHAIN other( aOther->m_line ); other.Simplify(); int np_self = self.PointCount(); int np_other = other.PointCount(); int n = std::min( np_self, np_other ); for( int i = 0; i < n; i++ ) { const VECTOR2I p1 = self.CPoint( i ); const VECTOR2I p2 = other.CPoint( i ); if( p1 != p2 ) { if( i != n - 1 ) { SEG s = self.CSegment( i ); if( !s.Contains( p2 ) ) { i_start = i; break; } } else { i_start = i; break; } } } for( int i = 0; i < n; i++ ) { const VECTOR2I p1 = self.CPoint( np_self - 1 - i ); const VECTOR2I p2 = other.CPoint( np_other - 1 - i ); if( p1 != p2 ) { i_end_self = np_self - 1 - i; i_end_other = np_other - 1 - i; break; } } if( i_start < 0 ) i_start = n; if( i_end_self < 0 ) i_end_self = np_self - 1; if( i_end_other < 0 ) i_end_other = np_other - 1; for( int i = i_start; i <= i_end_self; i++ ) extendBox( area, areaDefined, self.CPoint( i ) ); for( int i = i_start; i <= i_end_other; i++ ) extendBox( area, areaDefined, other.CPoint( i ) ); if( areaDefined ) { area.Inflate( std::max( Width(), aOther->Width() ) ); return area; } return OPT_BOX2I(); }