Allow deletion of zone cutout areas

ADDED: Ability to delete zone cutout areas

Fixes https://gitlab.com/kicad/code/kicad/issues/4188
This commit is contained in:
Ian McInerney 2020-04-14 17:57:18 +01:00
parent 7068b6453e
commit 37a4dd927b
5 changed files with 123 additions and 0 deletions

View File

@ -437,6 +437,13 @@ class SHAPE_POLY_SET : public SHAPE
SHAPE_POLY_SET(); SHAPE_POLY_SET();
/**
* Construct a SHAPE_POLY_SET with the first outline given by aOutline.
*
* @param aOutline is a closed outline
*/
SHAPE_POLY_SET( const SHAPE_LINE_CHAIN& aOutline );
/** /**
* Copy constructor SHAPE_POLY_SET * Copy constructor SHAPE_POLY_SET
* Performs a deep copy of \p aOther into \p this. * Performs a deep copy of \p aOther into \p this.

View File

@ -60,6 +60,13 @@ SHAPE_POLY_SET::SHAPE_POLY_SET() :
} }
SHAPE_POLY_SET::SHAPE_POLY_SET( const SHAPE_LINE_CHAIN& aOutline ) :
SHAPE( SH_POLY_SET )
{
AddOutline( aOutline );
}
SHAPE_POLY_SET::SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther, bool aDeepCopy ) : SHAPE_POLY_SET::SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther, bool aDeepCopy ) :
SHAPE( SH_POLY_SET ), m_polys( aOther.m_polys ) SHAPE( SH_POLY_SET ), m_polys( aOther.m_polys )
{ {

View File

@ -689,6 +689,31 @@ bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos ) const
} }
bool ZONE_CONTAINER::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
{
// Iterate over each outline polygon in the zone and then iterate over
// each hole it has to see if the point is in it.
for( int i = 0; i < m_Poly->OutlineCount(); i++ )
{
for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
{
if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
{
if( aOutlineIdx )
*aOutlineIdx = i;
if( aHoleIdx )
*aHoleIdx = j;
return true;
}
}
}
return false;
}
void ZONE_CONTAINER::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) void ZONE_CONTAINER::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
{ {
wxString msg; wxString msg;
@ -887,6 +912,21 @@ ZONE_CONNECTION ZONE_CONTAINER::GetPadConnection( D_PAD* aPad ) const
} }
void ZONE_CONTAINER::RemoveCutout( int aOutlineIdx, int aHoleIdx )
{
// Ensure the requested cutout is valid
if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
return;
SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
// Add the cutout back to the zone
m_Poly->BooleanAdd( cutPoly, SHAPE_POLY_SET::PM_FAST );
SetNeedRefill( true );
}
void ZONE_CONTAINER::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon ) void ZONE_CONTAINER::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
{ {
wxASSERT( aPolygon.IsClosed() ); wxASSERT( aPolygon.IsClosed() );

View File

@ -283,6 +283,24 @@ public:
*/ */
bool HitTestFilledArea( const wxPoint& aRefPos ) const; bool HitTestFilledArea( const wxPoint& aRefPos ) const;
/**
* Tests if the given point is contained within a cutout of the zone.
*
* @param aRefPos is the point to test
* @param aOutlineIdx is the index of the outline containing the cutout
* @param aHoleIdx is the index of the hole
* @return true if aRefPos is inside a zone cutout
*/
bool HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx = nullptr,
int* aHoleIdx = nullptr ) const;
bool HitTestCutout( const wxPoint& aRefPos, int* aOutlineIdx = nullptr,
int* aHoleIdx = nullptr ) const
{
return HitTestCutout( VECTOR2I( aRefPos.x, aRefPos.y ), aOutlineIdx, aHoleIdx );
}
/** /**
* Some intersecting zones, despite being on the same layer with the same net, cannot be * Some intersecting zones, despite being on the same layer with the same net, cannot be
* merged due to other parameters such as fillet radius. The copper pour will end up * merged due to other parameters such as fillet radius. The copper pour will end up
@ -618,6 +636,14 @@ public:
void SetFilledPolysUseThickness( bool aOption ) { m_FilledPolysUseThickness = aOption; } void SetFilledPolysUseThickness( bool aOption ) { m_FilledPolysUseThickness = aOption; }
/**
* Remove a cutout from the zone.
*
* @param aOutlineIdx is the zone outline the hole belongs to
* @param aHoleIdx is the hole in the outline to remove
*/
void RemoveCutout( int aOutlineIdx, int aHoleIdx );
/** /**
* add a polygon to the zone outline * add a polygon to the zone outline
* if the zone outline is empty, this is the main outline * if the zone outline is empty, this is the main outline

View File

@ -55,6 +55,7 @@ using namespace std::placeholders;
#include <dialogs/dialog_track_via_properties.h> #include <dialogs/dialog_track_via_properties.h>
#include <preview_items/ruler_item.h> #include <preview_items/ruler_item.h>
#include <board_commit.h> #include <board_commit.h>
#include <zone_filler.h>
void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags ) void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags )
@ -925,6 +926,48 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
} }
break; break;
case PCB_ZONE_AREA_T:
// We process the zones special so that cutouts can be deleted when the delete tool
// is called from inside a cutout when the zone is selected.
{
// Only interact with cutouts when deleting and a single item is selected
if( !isCut && selectionCopy.GetSize() == 1 )
{
VECTOR2I curPos = getViewControls()->GetCursorPosition();
auto zone = static_cast<ZONE_CONTAINER*>( item );
int outlineIdx, holeIdx;
if( zone->HitTestCutout( curPos, &outlineIdx, &holeIdx ) )
{
// Remove the cutout
m_commit->Modify( zone );
zone->RemoveCutout( outlineIdx, holeIdx );
std::vector<ZONE_CONTAINER*> toFill;
toFill.emplace_back( zone );
// Fill the modified zone
ZONE_FILLER filler( board() );
filler.InstallNewProgressReporter( frame(), _( "Fill Zone" ), 4 );
filler.Fill( toFill );
// Update the display
zone->Hatch();
canvas()->Refresh();
// Restore the selection on the original zone
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, zone );
break;
}
}
// Remove the entire zone otherwise
m_commit->Remove( item );
}
break;
default: default:
m_commit->Remove( item ); m_commit->Remove( item );
break; break;