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
This commit is contained in:
Seth Hillbrand 2022-11-08 16:03:59 -08:00
parent ffd578ef70
commit 056f45cd70
6 changed files with 72 additions and 89 deletions

View File

@ -201,10 +201,13 @@ void EDA_SHAPE::scale( double aScale )
{ {
std::vector<VECTOR2I> pts; std::vector<VECTOR2I> pts;
for( const VECTOR2I& pt : m_poly.Outline( 0 ).CPoints() ) for( int ii = 0; ii < m_poly.OutlineCount(); ++ ii )
{ {
pts.emplace_back( pt ); for( const VECTOR2I& pt : m_poly.Outline( ii ).CPoints() )
scalePt( pts.back() ); {
pts.emplace_back( pt );
scalePt( pts.back() );
}
} }
SetPolyPoints( pts ); 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. // to the actual location in the board.
VECTOR2I offset = getParentPosition(); VECTOR2I offset = getParentPosition();
SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 ); for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
poly.Rotate( getParentOrientation() );
poly.Move( offset );
int count = poly.GetPointCount();
for( int ii = 0; ii < count; 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 int count = poly.GetPointCount();
if( arect.Contains( vertex ) )
return true;
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 // Test if the point is within aRect
if( arect.Intersects( vertex, vertexNext ) ) if( arect.Contains( vertex ) )
return true; return true;
}
else if( poly.IsClosed() )
{
VECTOR2I vertexNext = poly.GetPoint( 0 );
// Test if this edge intersects aRect if( jj + 1 < count )
if( arect.Intersects( vertex, vertexNext ) ) {
return true; 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<SHAPE*> EDA_SHAPE::makeEffectiveShapes( bool aEdgeOnly, bool aLineCh
if( GetPolyShape().OutlineCount() == 0 ) // malformed/empty polygon if( GetPolyShape().OutlineCount() == 0 ) // malformed/empty polygon
break; break;
SHAPE_LINE_CHAIN l = GetPolyShape().COutline( 0 ); for( int ii = 0; ii < GetPolyShape().OutlineCount(); ++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 i = 0; i < l.SegmentCount(); i++ ) SHAPE_LINE_CHAIN l = GetPolyShape().COutline( ii );
effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), width ) );
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; break;
@ -1169,9 +1178,9 @@ std::vector<SHAPE*> EDA_SHAPE::makeEffectiveShapes( bool aEdgeOnly, bool aLineCh
void EDA_SHAPE::DupPolyPointsList( std::vector<VECTOR2I>& aBuffer ) const void EDA_SHAPE::DupPolyPointsList( std::vector<VECTOR2I>& 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 ) if( pointCount )
{ {

View File

@ -1417,6 +1417,8 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
if( poly->PointCount() < 2 ) // Careful of empty pads if( poly->PointCount() < 2 ) // Careful of empty pads
break; break;
if( poly->)
if( margin.x < 0 ) // The poly shape must be deflated if( margin.x < 0 ) // The poly shape must be deflated
{ {
int numSegs = GetArcToSegmentCount( -margin.x, m_maxError, FULL_CIRCLE ); 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 ) 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 else
{ {
@ -1688,7 +1691,8 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
if( thickness > 0 ) 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() ) 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 * polygon so each contour is draw as a simple polygon
*/ */
// Draw the main contour // Draw the main contour(s?)
m_gal->DrawPolyline( outline->COutline( 0 ) ); for( int ii = 0; ii < outline->OutlineCount(); ++ii )
{
m_gal->DrawPolyline( outline->COutline( ii ) );
// Draw holes // Draw holes
int holes_count = outline->HoleCount( 0 ); int holes_count = outline->HoleCount( ii );
for( int ii = 0; ii < holes_count; ++ii ) for( int jj = 0; ii < holes_count; ++jj )
m_gal->DrawPolyline( outline->CHole( 0, ii ) ); m_gal->DrawPolyline( outline->CHole( ii, jj ) );
}
// Draw hatch lines // Draw hatch lines
for( const SEG& hatchLine : aZone->GetHatchLines() ) for( const SEG& hatchLine : aZone->GetHatchLines() )

View File

@ -142,8 +142,11 @@ std::vector<VECTOR2I> PCB_SHAPE::GetCorners() const
{ {
VECTOR2I offset = getParentPosition(); VECTOR2I offset = getParentPosition();
for( const VECTOR2I& pt : GetPolyShape().Outline( 0 ).CPoints() ) for( int ii = 0; ii < GetPolyShape().OutlineCount(); ++ii )
pts.emplace_back( pt + offset ); {
for( const VECTOR2I& pt : GetPolyShape().Outline( ii ).CPoints() )
pts.emplace_back( pt + offset );
}
} }
else else
{ {

View File

@ -2505,10 +2505,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool ); POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool );
bool started = false; bool started = false;
PCB_GRID_HELPER grid( m_toolMgr, m_frame->GetMagneticItemsSettings() ); 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 ); m_frame->PushTool( aEvent );
@ -2660,17 +2656,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
&& ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) ) && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
{ {
polyGeomMgr.SetCursorPosition( cursorPos ); 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 ) ) else if( evt->IsAction( &PCB_ACTIONS::properties ) )
{ {

View File

@ -1663,27 +1663,7 @@ void PCB_POINT_EDITOR::updateItem() const
bool PCB_POINT_EDITOR::validatePolygon( SHAPE_POLY_SET& aPoly ) const bool PCB_POINT_EDITOR::validatePolygon( SHAPE_POLY_SET& aPoly ) const
{ {
bool valid = !aPoly.IsSelfIntersecting(); return true;
if( !m_statusPopup )
{
m_statusPopup.reset( new STATUS_TEXT_POPUP( getEditFrame<PCB_BASE_EDIT_FRAME>() ) );
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;
} }

View File

@ -355,8 +355,7 @@ void ZONE_CREATE_HELPER::OnComplete( const POLYGON_GEOM_MANAGER& aMgr )
} }
outline->Outline( 0 ).SetClosed( true ); outline->Outline( 0 ).SetClosed( true );
outline->RemoveNullSegments(); outline->Outline( 0 ).Simplify( true );
outline->Simplify( SHAPE_POLY_SET::PM_FAST );
// hand the zone over to the committer // hand the zone over to the committer
commitZone( std::move( m_zone ) ); commitZone( std::move( m_zone ) );