void POLYGON_GEOM_MANAGER::updateLeaderPoints( const VECTOR2I& aEndPoint ) { SHAPE_LINE_CHAIN newChain; if( m_leaderMode == LEADER_MODE::DEG45 ) { // get a restricted 45/H/V line from the last fixed point to the cursor DIRECTION_45 direction( m_lockedPoints.back() - aEndPoint ); newChain = direction.BuildInitialTrace( m_lockedPoints.back(), aEndPoint ); // Can also add chain back to start, but this rearely produces // usable result //DIRECTION_45 directionToStart( aEndPoint - m_lockedPoints.front() ); //newChain.Append( directionToStart.BuildInitialTrace( aEndPoint, m_lockedPoints.front() ) ); } else { // direct segment newChain = SHAPE_LINE_CHAIN( m_lockedPoints.back(), aEndPoint ); } // rebuild leader point list from the chain m_leaderPts.clear(); for( int i = 0; i < newChain.PointCount(); ++i ) { m_leaderPts.push_back( newChain.Point( i ) ); } m_client.OnGeometryChange( *this ); }
/** * Function TestLineChainEqualCPolyLine * tests the equality between a SHAPE_LINE_CHAIN polygon and a polygon inside a * CPolyLine object using Boost test suite. * @param lineChain is a SHAPE_LINE_CHAIN polygon object. * @param polyLine is a CPolyLine polygon object. * @param contourIdx is the index of the contour inside polyLine that has to be tested * against lineChain. */ void TestLineChainEqualCPolyLine(SHAPE_LINE_CHAIN& lineChain, CPolyLine& polyLine, int contourIdx = 0) { // Arrays to store the polygon points lexicographically ordered std::vector<VECTOR2I> chainPoints; std::vector<VECTOR2I> polyPoints; // Populate the array storing the new data with the lineChain corners for (int pointIdx = 0; pointIdx < lineChain.PointCount(); pointIdx++) { chainPoints.push_back(lineChain.Point(pointIdx)); } int start = polyLine.GetContourStart(contourIdx); int end = polyLine.GetContourEnd(contourIdx); // Populate the array storing the legacy data with the polyLine corners for (int pointIdx = start; pointIdx <= end; pointIdx++) { polyPoints.push_back( VECTOR2I(polyLine.GetX(pointIdx), polyLine.GetY(pointIdx)) ); } // Order the vectors in a lexicographic way std::sort(chainPoints.begin(), chainPoints.end(), lexicographicOrder); std::sort(polyPoints.begin(), polyPoints.end(), lexicographicOrder); // Compare every point coordinate to check the equality BOOST_CHECK_EQUAL_COLLECTIONS(chainPoints.begin(), chainPoints.end(), polyPoints.begin(), polyPoints.end()); }
bool PNS_LINE_PLACER::buildInitialLine( const VECTOR2I& aP, PNS_LINE& aHead ) { SHAPE_LINE_CHAIN l; if( m_p_start == aP ) { l.Clear(); } else { if( Settings().GetFreeAngleMode() && Settings().Mode() == RM_MarkObstacles ) { l = SHAPE_LINE_CHAIN( m_p_start, aP ); } else { l = m_direction.BuildInitialTrace( m_p_start, aP ); } if( l.SegmentCount() > 1 && m_orthoMode ) { VECTOR2I newLast = l.CSegment( 0 ).LineProject( l.CPoint( -1 ) ); l.Remove( -1, -1 ); l.Point( 1 ) = newLast; } } aHead.SetShape( l ); if( !m_placingVia ) return true; PNS_VIA v( makeVia( aP ) ); v.SetNet( aHead.Net() ); if( m_currentMode == RM_MarkObstacles ) { aHead.AppendVia( v ); return true; } VECTOR2I force; VECTOR2I lead = aP - m_p_start; bool solidsOnly = ( m_currentMode != RM_Walkaround ); if( v.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) ) { SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP + force ); aHead = PNS_LINE( aHead, line ); v.SetPos( v.Pos() + force ); return true; } return false; // via placement unsuccessful }
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const { VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I origin( aSegment->GetStart() ); DIRECTION_45 direction( origin - cursorPos ); SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos ); if( newChain.PointCount() > 2 ) { aSegment->SetEnd( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) ); aHelper->SetStart( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) ); aHelper->SetEnd( wxPoint( newChain.Point( -1 ).x, newChain.Point( -1 ).y ) ); } else { aSegment->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); aHelper->SetStart( wxPoint( cursorPos.x, cursorPos.y ) ); aHelper->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); } }
SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::genMeanderShape( VECTOR2D aP, VECTOR2D aDir, bool aSide, PNS_MEANDER_TYPE aType, int aAmpl, int aBaselineOffset ) { const PNS_MEANDER_SETTINGS& st = Settings(); int cr = cornerRadius(); int offset = aBaselineOffset; int spc = spacing(); if( aSide ) offset *= -1; VECTOR2D dir_u_b( aDir.Resize( offset ) ); VECTOR2D dir_v_b( dir_u_b.Perpendicular() ); if( 2 * cr > aAmpl ) { cr = aAmpl / 2; } if( 2 * cr > spc ) { cr = spc / 2; } SHAPE_LINE_CHAIN lc; start( &lc, aP + dir_v_b, aDir ); switch( aType ) { case MT_EMPTY: { lc.Append( aP + dir_v_b + aDir ); break; } case MT_START: { arc( cr - offset, false ); uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr ); forward( std::min( cr - offset, cr + offset ) ); forward( std::abs( offset ) ); break; } case MT_FINISH: { start( &lc, aP - dir_u_b, aDir ); turn ( 90 ); forward( std::min( cr - offset, cr + offset ) ); forward( std::abs( offset ) ); uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr ); arc( cr - offset, false ); break; } case MT_TURN: { start( &lc, aP - dir_u_b, aDir ); turn( 90 ); forward( std::abs( offset ) ); uShape ( aAmpl - cr, cr + offset, spc - 2 * cr ); forward( std::abs( offset ) ); break; } case MT_SINGLE: { arc( cr - offset, false ); uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr ); arc( cr - offset, false ); lc.Append( aP + dir_v_b + aDir.Resize ( 2 * st.m_spacing ) ); break; } default: break; } if( aSide ) { SEG axis ( aP, aP + aDir ); for( int i = 0; i < lc.PointCount(); i++ ) lc.Point( i ) = reflect( lc.CPoint( i ), axis ); } return lc; }