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;
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<SHAPE*> 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<SHAPE*> EDA_SHAPE::makeEffectiveShapes( bool aEdgeOnly, bool aLineCh
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 )
{

View File

@ -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() )

View File

@ -142,8 +142,11 @@ std::vector<VECTOR2I> 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
{

View File

@ -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 ) )
{

View File

@ -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<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;
return true;
}

View File

@ -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 ) );