pcbnew: factored out ZONE_FILLER to a separate file

This commit is contained in:
Tomasz Włostowski 2017-11-30 17:22:45 +01:00
parent 56336fdafe
commit fdd5023aee
9 changed files with 273 additions and 281 deletions

View File

@ -280,7 +280,7 @@ set( PCBNEW_CLASS_SRCS
tracepcb.cpp
tr_modif.cpp
undo_redo.cpp
zones_convert_brd_items_to_polygons_with_Boost.cpp
zone_filler.cpp
zones_convert_to_polygons_aux_functions.cpp
zones_by_polygon.cpp
zones_by_polygon_fill_functions.cpp

View File

@ -56,6 +56,8 @@
#include <array_creator.h>
#include <connectivity_data.h>
#include <zone_filler.h>
#include <dialog_move_exact.h>
#include <tool/tool_manager.h>
@ -674,11 +676,14 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break;
case ID_POPUP_PCB_FILL_ZONE:
{
m_canvas->MoveCursorToCrossHair();
Fill_Zone( (ZONE_CONTAINER*) GetCurItem() );
ZONE_FILLER filler( GetBoard() );
filler.Fill( { (ZONE_CONTAINER*) GetCurItem() } );
SetMsgPanel( GetBoard() );
m_canvas->Refresh();
break;
}
case ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST:
StartMoveTextePcb( (TEXTE_PCB*) GetCurItem(), &dc );

View File

@ -34,6 +34,7 @@
#include <tools/pcb_actions.h>
#include <tools/selection_tool.h>
#include <zone_filler.h>
ZONE_CREATE_HELPER::ZONE_CREATE_HELPER( DRAWING_TOOL& aTool,
const PARAMS& aParams ):
@ -133,8 +134,8 @@ void ZONE_CREATE_HELPER::performZoneCutout( ZONE_CONTAINER& aExistingZone,
// Re-fill if needed
if( aExistingZone.IsFilled() )
{
PCB_EDIT_FRAME* frame = m_tool.getEditFrame<PCB_EDIT_FRAME>();
frame->Fill_Zone( &aExistingZone );
ZONE_FILLER filler( board );
filler.Fill( { &aExistingZone } );
}
}
@ -142,6 +143,7 @@ void ZONE_CREATE_HELPER::performZoneCutout( ZONE_CONTAINER& aExistingZone,
void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE_CONTAINER> aZone )
{
auto& frame = *m_tool.getEditFrame<PCB_EDIT_FRAME>();
auto board = m_tool.getModel<BOARD>();
BOARD_COMMIT bCommit( &m_tool );
@ -160,7 +162,10 @@ void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE_CONTAINER> aZone )
aZone->Hatch();
if( !m_params.m_keepout )
frame.Fill_Zone( aZone.get() );
{
ZONE_FILLER filler( board );
filler.Fill( { aZone.get() } );
}
bCommit.Add( aZone.release() );
bCommit.Push( _( "Add a zone" ) );

View File

@ -26,13 +26,7 @@
#include <thread>
#include <mutex>
#include <painter.h>
#include <project.h>
#include <pcbnew_id.h>
#include <wxPcbStruct.h>
#include <class_board.h>
#include <class_zone.h>
#include <pcb_draw_panel_gal.h>
#include <class_module.h>
#include <connectivity_data.h>
#include <board_commit.h>
@ -45,10 +39,7 @@
#include "pcb_actions.h"
#include "selection_tool.h"
#include "zone_filler_tool.h"
#ifdef USE_OPENMP
#include <omp.h>
#endif /* USE_OPENMP */
#include "zone_filler.h"
// Zone actions
TOOL_ACTION PCB_ACTIONS::zoneFill( "pcbnew.ZoneFiller.zoneFill",
@ -67,135 +58,6 @@ TOOL_ACTION PCB_ACTIONS::zoneUnfillAll( "pcbnew.ZoneFiller.zoneUnfillAll",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_REMOVE_FILLED ),
_( "Unfill All" ), _( "Unfill all zones" ) );
class ZONE_FILLER
{
public:
ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit );
~ZONE_FILLER();
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
void Fill( std::vector<ZONE_CONTAINER*> aZones );
void Unfill( std::vector<ZONE_CONTAINER*> aZones );
private:
COMMIT* m_commit;
PROGRESS_REPORTER* m_progressReporter;
BOARD* m_board;
};
ZONE_FILLER::ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit ) :
m_commit( aCommit ),
m_board( aBoard )
{
}
ZONE_FILLER::~ZONE_FILLER()
{
}
void ZONE_FILLER::SetProgressReporter( PROGRESS_REPORTER* aReporter )
{
m_progressReporter = aReporter;
}
void ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones )
{
std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> toFill;
assert( m_commit );
// Remove segment zones
m_board->m_Zone.DeleteAll();
int ii;
for( auto zone : aZones )
{
// Keepout zones are not filled
if( zone->GetIsKeepout() )
continue;
CN_ZONE_ISOLATED_ISLAND_LIST l;
l.m_zone = zone;
toFill.push_back( l );
}
int zoneCount = m_board->GetAreaCount();
for( int i = 0; i < toFill.size(); i++ )
{
m_commit->Modify( toFill[i].m_zone );
}
if( m_progressReporter )
{
m_progressReporter->Report( _( "Calculating zone fills..." ) );
m_progressReporter->SetMaxProgress( toFill.size() );
}
#ifdef USE_OPENMP
#pragma omp parallel for schedule(dynamic)
#endif
for( int i = 0; i < toFill.size(); i++ )
{
toFill[i].m_zone->BuildFilledSolidAreasPolygons( m_board );
m_progressReporter->AdvanceProgress();
}
if( m_progressReporter )
{
m_progressReporter->AdvancePhase();
m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
}
m_board->GetConnectivity()->SetProgressReporter( m_progressReporter );
m_board->GetConnectivity()->FindIsolatedCopperIslands( toFill );
for( auto& zone : toFill )
{
std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
for( auto idx : zone.m_islands )
{
poly.DeletePolygon( idx );
}
zone.m_zone->AddFilledPolysList( poly );
}
if( m_progressReporter )
{
m_progressReporter->AdvancePhase();
m_progressReporter->Report( _( "Caching polygon triangulations..." ) );
m_progressReporter->SetMaxProgress( toFill.size() );
}
#ifdef USE_OPENMP
#pragma omp parallel for schedule(dynamic)
#endif
for( int i = 0; i < toFill.size(); i++ )
{
m_progressReporter->AdvanceProgress();
toFill[i].m_zone->CacheTriangulation();
}
m_progressReporter->AdvancePhase();
m_progressReporter->Report( _( "Committing changes..." ) );
m_commit->Push( _( "Fill Zones" ), false );
}
ZONE_FILLER_TOOL::ZONE_FILLER_TOOL() :
PCB_TOOL( "pcbnew.ZoneFiller" )
{
@ -214,13 +76,11 @@ void ZONE_FILLER_TOOL::Reset( RESET_REASON aReason )
// Zone actions
int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
{
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
const auto& selection = selTool->GetSelection();
std::vector<ZONE_CONTAINER*> toFill;
BOARD_COMMIT commit( this );
for( auto item : selection )
for( auto item : selection() )
{
assert( item->Type() == PCB_ZONE_AREA_T );
@ -230,7 +90,7 @@ int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
}
std::unique_ptr<WX_PROGRESS_REPORTER> progressReporter(
new WX_PROGRESS_REPORTER( frame(), _( "Fill Zones" ), 3 )
new WX_PROGRESS_REPORTER( frame(), _( "Fill Zone" ), 3 )
);
ZONE_FILLER filler( board(), &commit );
@ -266,13 +126,9 @@ int ZONE_FILLER_TOOL::ZoneFillAll( const TOOL_EVENT& aEvent )
int ZONE_FILLER_TOOL::ZoneUnfill( const TOOL_EVENT& aEvent )
{
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
const auto& selection = selTool->GetSelection();
auto connectivity = getModel<BOARD>()->GetConnectivity();
BOARD_COMMIT commit( this );
for( auto item : selection )
for( auto item : selection() )
{
assert( item->Type() == PCB_ZONE_AREA_T );
@ -286,23 +142,16 @@ int ZONE_FILLER_TOOL::ZoneUnfill( const TOOL_EVENT& aEvent )
commit.Push( _( "Unfill Zone" ) );
connectivity->RecalculateRatsnest();
return 0;
}
int ZONE_FILLER_TOOL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
{
BOARD* board = getModel<BOARD>();
auto connectivity = getModel<BOARD>()->GetConnectivity();
BOARD_COMMIT commit( this );
for( int i = 0; i < board->GetAreaCount(); ++i )
for ( auto zone : board()->Zones() )
{
ZONE_CONTAINER* zone = board->GetArea( i );
commit.Modify( zone );
zone->SetIsFilled( false );
@ -311,8 +160,6 @@ int ZONE_FILLER_TOOL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
commit.Push( _( "Unfill All Zones" ) );
connectivity->RecalculateRatsnest();
return 0;
}

173
pcbnew/zone_filler.cpp Normal file
View File

@ -0,0 +1,173 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014-2017 CERN
* Copyright (C) 2014-2017 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Włostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <cstdint>
#include <thread>
#include <mutex>
#include <class_board.h>
#include <class_zone.h>
#include <class_module.h>
#include <connectivity_data.h>
#include <board_commit.h>
#include <widgets/progress_reporter.h>
#include "zone_filler.h"
#ifdef USE_OPENMP
#include <omp.h>
#endif /* USE_OPENMP */
ZONE_FILLER::ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit ) :
m_commit( aCommit ),
m_board( aBoard ),
m_progressReporter( nullptr )
{
}
ZONE_FILLER::~ZONE_FILLER()
{
}
void ZONE_FILLER::SetProgressReporter( PROGRESS_REPORTER* aReporter )
{
m_progressReporter = aReporter;
}
void ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones )
{
std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> toFill;
auto connectivity = m_board->GetConnectivity();
// Remove segment zones
m_board->m_Zone.DeleteAll();
int ii;
for( auto zone : aZones )
{
// Keepout zones are not filled
if( zone->GetIsKeepout() )
continue;
CN_ZONE_ISOLATED_ISLAND_LIST l;
l.m_zone = zone;
toFill.push_back( l );
}
int zoneCount = m_board->GetAreaCount();
for( int i = 0; i < toFill.size(); i++ )
{
if (m_commit)
{
m_commit->Modify( toFill[i].m_zone );
}
}
if( m_progressReporter )
{
m_progressReporter->Report( _( "Calculating zone fills..." ) );
m_progressReporter->SetMaxProgress( toFill.size() );
}
#ifdef USE_OPENMP
#pragma omp parallel for schedule(dynamic)
#endif
for( int i = 0; i < toFill.size(); i++ )
{
toFill[i].m_zone->BuildFilledSolidAreasPolygons( m_board );
if( m_progressReporter )
{
m_progressReporter->AdvanceProgress();
}
}
if( m_progressReporter )
{
m_progressReporter->AdvancePhase();
m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
}
connectivity->SetProgressReporter( m_progressReporter );
connectivity->FindIsolatedCopperIslands( toFill );
for( auto& zone : toFill )
{
std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
for( auto idx : zone.m_islands )
{
poly.DeletePolygon( idx );
}
zone.m_zone->AddFilledPolysList( poly );
}
if( m_progressReporter )
{
m_progressReporter->AdvancePhase();
m_progressReporter->Report( _( "Caching polygon triangulations..." ) );
m_progressReporter->SetMaxProgress( toFill.size() );
}
#ifdef USE_OPENMP
#pragma omp parallel for schedule(dynamic)
#endif
for( int i = 0; i < toFill.size(); i++ )
{
if( m_progressReporter )
{
m_progressReporter->AdvanceProgress();
}
toFill[i].m_zone->CacheTriangulation();
}
if( m_progressReporter )
{
m_progressReporter->AdvancePhase();
m_progressReporter->Report( _( "Committing changes..." ) );
}
connectivity->SetProgressReporter( nullptr );
if( m_commit )
{
m_commit->Push( _( "Fill Zone(s)" ), false );
} else {
for( int i = 0; i < toFill.size(); i++ )
{
connectivity->Update( toFill[i].m_zone );
}
}
}

52
pcbnew/zone_filler.h Normal file
View File

@ -0,0 +1,52 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014-2017 CERN
* Copyright (C) 2014-2017 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Włostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __ZONE_FILLER_H
#define __ZONE_FILLER_H
#include <vector>
class PROGRESS_REPORTER;
class BOARD;
class COMMIT;
class ZONE_CONTAINER;
class ZONE_FILLER
{
public:
ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit = nullptr );
~ZONE_FILLER();
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
void Fill( std::vector<ZONE_CONTAINER*> aZones );
void Unfill( std::vector<ZONE_CONTAINER*> aZones );
private:
COMMIT* m_commit;
PROGRESS_REPORTER* m_progressReporter;
BOARD* m_board;
};
#endif

View File

@ -47,6 +47,8 @@
#include <drc_stuff.h>
#include <connectivity_data.h>
#include <zone_filler.h>
// Outline creation:
static void Abort_Zone_Create_Outline( EDA_DRAW_PANEL* Panel, wxDC* DC );
static void Show_New_Edge_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
@ -954,7 +956,8 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone )
if( zone->IsFilled() )
{
Fill_Zone( zone );
ZONE_FILLER filler ( GetBoard() );
filler.Fill( { zone } );
}
}

View File

@ -46,7 +46,8 @@
#include <connectivity_data.h>
#include <board_commit.h>
#define FORMAT_STRING _( "Filling zone %d out of %d (net %s)..." )
#include <widgets/progress_reporter.h>
#include <zone_filler.h>
/**
@ -89,118 +90,24 @@ void PCB_EDIT_FRAME::Delete_OldZone_Fill( SEGZONE* aZone, time_t aTimestamp )
}
}
int PCB_EDIT_FRAME::Fill_Zone( ZONE_CONTAINER* aZone )
int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose )
{
aZone->ClearFilledPolysList();
aZone->UnFill();
// Cannot fill keepout zones:
if( aZone->GetIsKeepout() )
return 1;
wxString msg;
ClearMsgPanel();
// Shows the net
ZONE_SETTINGS zoneInfo = GetZoneSettings();
zoneInfo.m_NetcodeSelection = aZone->GetNetCode();
SetZoneSettings( zoneInfo );
msg = aZone->GetNetname();
if( msg.IsEmpty() )
msg = wxT( "No net" );
AppendMsgPanel( _( "NetName" ), msg, RED );
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
std::vector<ZONE_CONTAINER*> toFill;
BOARD_COMMIT commit( this );
commit.Modify( aZone );
aZone->BuildFilledSolidAreasPolygons( GetBoard() );
commit.Push( _( "Fill Zone" ), false );
//GetGalCanvas()->GetView()->Update( aZone, KIGFX::ALL );
//GetBoard()->GetConnectivity()->Update( aZone );
for( auto zone : GetBoard()->Zones() )
{
toFill.push_back(zone);
}
//OnModify();
std::unique_ptr<WX_PROGRESS_REPORTER> progressReporter(
new WX_PROGRESS_REPORTER( aActiveWindow, _( "Fill All Zones" ), 3 )
);
ZONE_FILLER filler( GetBoard() );
filler.SetProgressReporter( progressReporter.get() );
filler.Fill( toFill );
return 0;
}
int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose )
{
return 0;
}
/*
int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose )
{
int errorLevel = 0;
int areaCount = GetBoard()->GetAreaCount();
wxBusyCursor dummyCursor;
wxString msg;
wxProgressDialog * progressDialog = NULL;
// Create a message with a long net name, and build a wxProgressDialog
// with a correct size to show this long net name
msg.Printf( FORMAT_STRING, 000, areaCount, wxT("XXXXXXXXXXXXXXXXX" ) );
if( aActiveWindow )
progressDialog = new wxProgressDialog( _( "Fill All Zones" ), msg,
areaCount+2, aActiveWindow,
wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
// Display the actual message
if( progressDialog )
progressDialog->Update( 0, _( "Starting zone fill..." ) );
// Remove segment zones
GetBoard()->m_Zone.DeleteAll();
int ii;
for( ii = 0; ii < areaCount; ii++ )
{
ZONE_CONTAINER* zoneContainer = GetBoard()->GetArea( ii );
// Keepout zones are not filled
if( zoneContainer->GetIsKeepout() )
continue;
msg.Printf( FORMAT_STRING, ii + 1, areaCount, GetChars( zoneContainer->GetNetname() ) );
if( progressDialog )
{
if( !progressDialog->Update( ii+1, msg ) )
break; // Aborted by user
}
errorLevel = Fill_Zone( zoneContainer );
if( errorLevel && !aVerbose )
break;
}
if( progressDialog )
{
progressDialog->Update( ii+2, _( "Updating ratsnest..." ) );
#ifdef __WXMAC__
// Work around a dialog z-order issue on OS X
aActiveWindow->Raise();
#endif
}
//TestConnections();
// Recalculate the active ratsnest, i.e. the unconnected links
//TestForActiveLinksInRatsnest( 0 );
if( progressDialog )
progressDialog->Destroy();
return errorLevel;
}
*/