Fix segfault when removing the last corner of a cutout
Fixes: lp:1736147 * https://bugs.launchpad.net/kicad/+bug/1736147
This commit is contained in:
parent
1e88695001
commit
f44d4d01ea
|
@ -784,19 +784,46 @@ bool POINT_EDITOR::addCornerCondition( const SELECTION& aSelection )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Finds a corresponding vertex in a polygon set
|
||||||
|
static std::pair<bool, SHAPE_POLY_SET::VERTEX_INDEX>
|
||||||
|
findVertex( SHAPE_POLY_SET& aPolySet, const EDIT_POINT& aPoint )
|
||||||
|
{
|
||||||
|
for( auto it = aPolySet.IterateWithHoles(); it; ++it )
|
||||||
|
{
|
||||||
|
auto vertexIdx = it.GetIndex();
|
||||||
|
|
||||||
|
if( aPolySet.Vertex( vertexIdx ) == aPoint.GetPosition() )
|
||||||
|
return std::make_pair( true, vertexIdx );
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair( false, SHAPE_POLY_SET::VERTEX_INDEX() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool POINT_EDITOR::removeCornerCondition( const SELECTION& )
|
bool POINT_EDITOR::removeCornerCondition( const SELECTION& )
|
||||||
{
|
{
|
||||||
if( !m_editPoints )
|
if( !m_editPoints || !m_editedPoint )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
EDA_ITEM* item = m_editPoints->GetParent();
|
EDA_ITEM* item = m_editPoints->GetParent();
|
||||||
|
|
||||||
if( item->Type() != PCB_ZONE_AREA_T )
|
if( !item || item->Type() != PCB_ZONE_AREA_T )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
|
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
|
||||||
|
auto& polyset = *zone->Outline();
|
||||||
|
auto vertex = findVertex( polyset, *m_editedPoint );
|
||||||
|
|
||||||
if( zone->GetNumCorners() <= 3 )
|
if( !vertex.first )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& vertexIdx = vertex.second;
|
||||||
|
|
||||||
|
// Check if there are enough vertices so one can be removed without
|
||||||
|
// degenerating the polygon.
|
||||||
|
// The first condition allows to remove all corners from holes (when there
|
||||||
|
// are only 2 vertices left, a hole is removed).
|
||||||
|
if( vertexIdx.m_contour == 0 && polyset.Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour].PointCount() <= 3 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove corner does not work with lines
|
// Remove corner does not work with lines
|
||||||
|
@ -931,44 +958,60 @@ int POINT_EDITOR::removeCorner( const TOOL_EVENT& aEvent )
|
||||||
if( !item )
|
if( !item )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SHAPE_POLY_SET *outline = nullptr;
|
SHAPE_POLY_SET* polygon = nullptr;
|
||||||
|
|
||||||
if( item->Type() == PCB_ZONE_AREA_T)
|
if( item->Type() == PCB_ZONE_AREA_T)
|
||||||
{
|
{
|
||||||
auto zone = static_cast<ZONE_CONTAINER*>( item );
|
auto zone = static_cast<ZONE_CONTAINER*>( item );
|
||||||
outline = zone->Outline();
|
polygon = zone->Outline();
|
||||||
}
|
}
|
||||||
else if ( item->Type() == PCB_LINE_T )
|
else if( item->Type() == PCB_LINE_T )
|
||||||
{
|
{
|
||||||
auto ds = static_cast<DRAWSEGMENT*>( item );
|
auto ds = static_cast<DRAWSEGMENT*>( item );
|
||||||
|
|
||||||
if( ds->GetShape() == S_POLYGON )
|
if( ds->GetShape() == S_POLYGON )
|
||||||
{
|
polygon = &ds->GetPolyShape();
|
||||||
outline = &ds->GetPolyShape();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !outline )
|
if( !polygon )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
|
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
|
||||||
BOARD_COMMIT commit( frame );
|
BOARD_COMMIT commit( frame );
|
||||||
|
auto vertex = findVertex( *polygon, *m_editedPoint );
|
||||||
|
|
||||||
commit.Modify( item );
|
if( vertex.first )
|
||||||
|
|
||||||
for( int i = 0; i < outline->TotalVertices(); ++i )
|
|
||||||
{
|
{
|
||||||
if( outline->Vertex( i ) == m_editedPoint->GetPosition() )
|
const auto& vertexIdx = vertex.second;
|
||||||
|
auto& outline = polygon->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour];
|
||||||
|
|
||||||
|
if( outline.PointCount() > 3 )
|
||||||
{
|
{
|
||||||
outline->RemoveVertex( i );
|
// the usual case: remove just the corner when there are >3 vertices
|
||||||
setEditedPoint( NULL );
|
commit.Modify( item );
|
||||||
commit.Push( _( "Remove a zone/polygon corner" ) );
|
polygon->RemoveVertex( vertexIdx );
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// either remove a hole or the polygon when there are <= 3 corners
|
||||||
|
if( vertexIdx.m_contour > 0 )
|
||||||
|
{
|
||||||
|
// remove hole
|
||||||
|
commit.Modify( item );
|
||||||
|
polygon->RemoveContour( vertexIdx.m_contour );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||||
|
commit.Remove( item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setEditedPoint( nullptr );
|
||||||
|
commit.Push( _( "Remove a zone/polygon corner" ) );
|
||||||
|
updatePoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePoints();
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue