From 056f45cd70bf0cf73d034849db59d454cc32e1bd Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 8 Nov 2022 16:03:59 -0800 Subject: [PATCH] Fixup most intersecting polygon points Remaining is the intersecting complex pad, so this keeps the error message when drawing Fixes https://gitlab.com/kicad/code/kicad/issues/12806 --- common/eda_shape.cpp | 91 ++++++++++++++++------------- pcbnew/pcb_painter.cpp | 23 +++++--- pcbnew/pcb_shape.cpp | 7 ++- pcbnew/tools/drawing_tool.cpp | 15 ----- pcbnew/tools/pcb_point_editor.cpp | 22 +------ pcbnew/tools/zone_create_helper.cpp | 3 +- 6 files changed, 72 insertions(+), 89 deletions(-) diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp index 771818aac2..72bba8ef35 100644 --- a/common/eda_shape.cpp +++ b/common/eda_shape.cpp @@ -201,10 +201,13 @@ void EDA_SHAPE::scale( double aScale ) { std::vector pts; - for( const VECTOR2I& pt : m_poly.Outline( 0 ).CPoints() ) + for( int ii = 0; ii < m_poly.OutlineCount(); ++ ii ) { - pts.emplace_back( pt ); - scalePt( pts.back() ); + for( const VECTOR2I& pt : m_poly.Outline( ii ).CPoints() ) + { + pts.emplace_back( pt ); + scalePt( pts.back() ); + } } SetPolyPoints( pts ); @@ -905,35 +908,38 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co // to the actual location in the board. VECTOR2I offset = getParentPosition(); - SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 ); - poly.Rotate( getParentOrientation() ); - poly.Move( offset ); - - int count = poly.GetPointCount(); - - for( int ii = 0; ii < count; ii++ ) + for( int ii = 0; ii < m_poly.OutlineCount(); ++ii ) { - VECTOR2I vertex = poly.GetPoint( ii ); + SHAPE_LINE_CHAIN poly = m_poly.Outline( ii ); + poly.Rotate( getParentOrientation() ); + poly.Move( offset ); - // Test if the point is within aRect - if( arect.Contains( vertex ) ) - return true; + int count = poly.GetPointCount(); - if( ii + 1 < count ) + for( int jj = 0; jj < count; jj++ ) { - VECTOR2I vertexNext = poly.GetPoint( ii + 1 ); + VECTOR2I vertex = poly.GetPoint( jj ); - // Test if this edge intersects aRect - if( arect.Intersects( vertex, vertexNext ) ) + // Test if the point is within aRect + if( arect.Contains( vertex ) ) return true; - } - else if( poly.IsClosed() ) - { - VECTOR2I vertexNext = poly.GetPoint( 0 ); - // Test if this edge intersects aRect - if( arect.Intersects( vertex, vertexNext ) ) - return true; + if( jj + 1 < count ) + { + VECTOR2I vertexNext = poly.GetPoint( jj + 1 ); + + // Test if this edge intersects aRect + if( arect.Intersects( vertex, vertexNext ) ) + return true; + } + else if( poly.IsClosed() ) + { + VECTOR2I vertexNext = poly.GetPoint( 0 ); + + // Test if this edge intersects aRect + if( arect.Intersects( vertex, vertexNext ) ) + return true; + } } } @@ -1139,21 +1145,24 @@ std::vector EDA_SHAPE::makeEffectiveShapes( bool aEdgeOnly, bool aLineCh if( GetPolyShape().OutlineCount() == 0 ) // malformed/empty polygon break; - SHAPE_LINE_CHAIN l = GetPolyShape().COutline( 0 ); - - if( aLineChainOnly ) - l.SetClosed( false ); - - l.Rotate( getParentOrientation() ); - l.Move( getParentPosition() ); - - if( IsFilled() && !aEdgeOnly ) - effectiveShapes.emplace_back( new SHAPE_SIMPLE( l ) ); - - if( width > 0 || !IsFilled() || aEdgeOnly ) + for( int ii = 0; ii < GetPolyShape().OutlineCount(); ++ii ) { - for( int i = 0; i < l.SegmentCount(); i++ ) - effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), width ) ); + SHAPE_LINE_CHAIN l = GetPolyShape().COutline( ii ); + + if( aLineChainOnly ) + l.SetClosed( false ); + + l.Rotate( getParentOrientation() ); + l.Move( getParentPosition() ); + + if( IsFilled() && !aEdgeOnly ) + effectiveShapes.emplace_back( new SHAPE_SIMPLE( l ) ); + + if( width > 0 || !IsFilled() || aEdgeOnly ) + { + for( int jj = 0; jj < l.SegmentCount(); jj++ ) + effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( jj ), width ) ); + } } } break; @@ -1169,9 +1178,9 @@ std::vector EDA_SHAPE::makeEffectiveShapes( bool aEdgeOnly, bool aLineCh void EDA_SHAPE::DupPolyPointsList( std::vector& aBuffer ) const { - if( m_poly.OutlineCount() ) + for( int ii = 0; ii < m_poly.OutlineCount(); ++ii ) { - int pointCount = m_poly.COutline( 0 ).PointCount(); + int pointCount = m_poly.COutline( ii ).PointCount(); if( pointCount ) { diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 882364eec8..c42110f79e 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -1417,6 +1417,8 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer ) if( poly->PointCount() < 2 ) // Careful of empty pads break; + if( poly->) + if( margin.x < 0 ) // The poly shape must be deflated { int numSegs = GetArcToSegmentCount( -margin.x, m_maxError, FULL_CIRCLE ); @@ -1679,7 +1681,8 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer ) if( outline_mode ) { - m_gal->DrawSegmentChain( shape.Outline( 0 ), thickness ); + for( int ii = 0; ii < shape.OutlineCount(); ++ii ) + m_gal->DrawSegmentChain( shape.Outline( ii ), thickness ); } else { @@ -1688,7 +1691,8 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer ) if( thickness > 0 ) { - m_gal->DrawSegmentChain( shape.Outline( 0 ), thickness ); + for( int ii = 0; ii < shape.OutlineCount(); ++ii ) + m_gal->DrawSegmentChain( shape.Outline( ii ), thickness ); } if( aShape->IsFilled() ) @@ -2367,14 +2371,17 @@ void PCB_PAINTER::draw( const ZONE* aZone, int aLayer ) * polygon so each contour is draw as a simple polygon */ - // Draw the main contour - m_gal->DrawPolyline( outline->COutline( 0 ) ); + // Draw the main contour(s?) + for( int ii = 0; ii < outline->OutlineCount(); ++ii ) + { + m_gal->DrawPolyline( outline->COutline( ii ) ); - // Draw holes - int holes_count = outline->HoleCount( 0 ); + // Draw holes + int holes_count = outline->HoleCount( ii ); - for( int ii = 0; ii < holes_count; ++ii ) - m_gal->DrawPolyline( outline->CHole( 0, ii ) ); + for( int jj = 0; ii < holes_count; ++jj ) + m_gal->DrawPolyline( outline->CHole( ii, jj ) ); + } // Draw hatch lines for( const SEG& hatchLine : aZone->GetHatchLines() ) diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp index caab8db19d..8b30cbb582 100644 --- a/pcbnew/pcb_shape.cpp +++ b/pcbnew/pcb_shape.cpp @@ -142,8 +142,11 @@ std::vector PCB_SHAPE::GetCorners() const { VECTOR2I offset = getParentPosition(); - for( const VECTOR2I& pt : GetPolyShape().Outline( 0 ).CPoints() ) - pts.emplace_back( pt + offset ); + for( int ii = 0; ii < GetPolyShape().OutlineCount(); ++ii ) + { + for( const VECTOR2I& pt : GetPolyShape().Outline( ii ).CPoints() ) + pts.emplace_back( pt + offset ); + } } else { diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index fafaf6d394..8bbe41d15b 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -2505,10 +2505,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent ) POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool ); bool started = false; PCB_GRID_HELPER grid( m_toolMgr, m_frame->GetMagneticItemsSettings() ); - STATUS_TEXT_POPUP status( m_frame ); - - status.SetTextColor( wxColour( 255, 0, 0 ) ); - status.SetText( _( "Self-intersecting polygons are not allowed" ) ); m_frame->PushTool( aEvent ); @@ -2660,17 +2656,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent ) && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) ) { polyGeomMgr.SetCursorPosition( cursorPos ); - - if( polyGeomMgr.IsSelfIntersecting( true ) ) - { - VECTOR2I p = wxGetMousePosition() + wxPoint( 20, 20 ); - status.Move( p ); - status.PopupFor( 1500 ); - } - else - { - status.Hide(); - } } else if( evt->IsAction( &PCB_ACTIONS::properties ) ) { diff --git a/pcbnew/tools/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp index 6a1e431f32..964a90bb18 100644 --- a/pcbnew/tools/pcb_point_editor.cpp +++ b/pcbnew/tools/pcb_point_editor.cpp @@ -1663,27 +1663,7 @@ void PCB_POINT_EDITOR::updateItem() const bool PCB_POINT_EDITOR::validatePolygon( SHAPE_POLY_SET& aPoly ) const { - bool valid = !aPoly.IsSelfIntersecting(); - - if( !m_statusPopup ) - { - m_statusPopup.reset( new STATUS_TEXT_POPUP( getEditFrame() ) ); - m_statusPopup->SetTextColor( wxColour( 255, 0, 0 ) ); - m_statusPopup->SetText( _( "Self-intersecting polygons are not allowed." ) ); - } - - if( valid ) - { - m_statusPopup->Hide(); - } - else - { - wxPoint p = wxGetMousePosition() + wxPoint( 20, 20 ); - m_statusPopup->Move( p ); - m_statusPopup->PopupFor( 1500 ); - } - - return valid; + return true; } diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp index e49aca463f..96bfef6d8c 100644 --- a/pcbnew/tools/zone_create_helper.cpp +++ b/pcbnew/tools/zone_create_helper.cpp @@ -355,8 +355,7 @@ void ZONE_CREATE_HELPER::OnComplete( const POLYGON_GEOM_MANAGER& aMgr ) } outline->Outline( 0 ).SetClosed( true ); - outline->RemoveNullSegments(); - outline->Simplify( SHAPE_POLY_SET::PM_FAST ); + outline->Outline( 0 ).Simplify( true ); // hand the zone over to the committer commitZone( std::move( m_zone ) );