diff --git a/libs/kimath/src/geometry/shape_line_chain.cpp b/libs/kimath/src/geometry/shape_line_chain.cpp index 53359dc8a1..4b69855302 100644 --- a/libs/kimath/src/geometry/shape_line_chain.cpp +++ b/libs/kimath/src/geometry/shape_line_chain.cpp @@ -1162,8 +1162,14 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) if( aStartIndex < 0 ) aStartIndex += PointCount(); - int numPoints = static_cast( m_points.size() ); + // Bad programmer checks + wxCHECK( aStartIndex >= 0, SHAPE_LINE_CHAIN() ); + wxCHECK( aEndIndex >= 0, SHAPE_LINE_CHAIN() ); + wxCHECK( aStartIndex < PointCount(), SHAPE_LINE_CHAIN() ); + wxCHECK( aEndIndex < PointCount(), SHAPE_LINE_CHAIN() ); + wxCHECK( aEndIndex >= aStartIndex, SHAPE_LINE_CHAIN() ); + int numPoints = static_cast( m_points.size() ); if( IsArcSegment( aStartIndex ) && !IsArcStart( aStartIndex ) ) { @@ -1199,12 +1205,11 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) if( i == -1 ) return rv; // NextShape reached the end - int nextShape = NextShape( i ); + int nextShape = NextShape( i ); + bool isLastShape = nextShape < 0; if( IsArcStart( i ) ) { - bool isLastShape = nextShape < 0; - if( ( isLastShape && aEndIndex != ( numPoints - 1 ) ) || ( nextShape > aEndIndex ) ) { @@ -1260,9 +1265,11 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) wxT( "Still on an arc segment, we missed something..." ) ); if( i == aStartIndex ) - rv.Append( GetSegment( i ).A ); + rv.Append( m_points[i] ); - if( !IsArcStart( nextShape ) && nextShape <= aEndIndex ) + bool nextPointIsArc = isLastShape ? false : IsArcSegment( nextShape ); + + if( !nextPointIsArc && i < SegmentCount() && i < aEndIndex ) rv.Append( GetSegment( i ).B ); } diff --git a/qa/tests/libs/kimath/geometry/test_shape_line_chain.cpp b/qa/tests/libs/kimath/geometry/test_shape_line_chain.cpp index d2c2279e79..eee0581a48 100644 --- a/qa/tests/libs/kimath/geometry/test_shape_line_chain.cpp +++ b/qa/tests/libs/kimath/geometry/test_shape_line_chain.cpp @@ -881,8 +881,30 @@ BOOST_AUTO_TEST_CASE( Slice ) chainCopy.Append( VECTOR2I( 400000, 400000 ) ); SHAPE_LINE_CHAIN sliceResult = chainCopy.Slice( 11, -1 ); + BOOST_CHECK( GEOM_TEST::IsOutlineValid( sliceResult ) ); BOOST_CHECK_EQUAL( sliceResult.GetPoint( -1 ), VECTOR2I( 400000, 400000 ) ); } + + BOOST_TEST_CONTEXT( "Case 6: Start to end, chain with one point" ) + { + SHAPE_LINE_CHAIN chainCopy = SLC_CASES().OnePoint; + + SHAPE_LINE_CHAIN sliceResult = chainCopy.Slice( 0, -1 ); + BOOST_CHECK_EQUAL( sliceResult.PointCount(), 1 ); + BOOST_CHECK_EQUAL( sliceResult.GetPoint( 0 ), VECTOR2I( 233450000, 228360000 ) ); + BOOST_CHECK_EQUAL( sliceResult.GetPoint( -1 ), VECTOR2I( 233450000, 228360000 ) ); // Same as index 0 + } + + BOOST_TEST_CONTEXT( "Case 7: Start to end, chain with two points" ) + { + SHAPE_LINE_CHAIN chainCopy = SLC_CASES().TwoPoints; + + SHAPE_LINE_CHAIN sliceResult = chainCopy.Slice( 0, -1 ); + BOOST_CHECK_EQUAL( sliceResult.PointCount(), 2 ); + BOOST_CHECK_EQUAL( sliceResult.GetPoint( 0 ), VECTOR2I( 233450000, 228360000 ) ); + BOOST_CHECK_EQUAL( sliceResult.GetPoint( 1 ), VECTOR2I( 263450000, 258360000 ) ); + BOOST_CHECK_EQUAL( sliceResult.GetPoint( -1 ), VECTOR2I( 263450000, 258360000 ) ); // Same as index 1 + } }