2017-11-30 16:22:45 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2021-08-14 20:05:21 +00:00
|
|
|
#ifndef ZONE_FILLER_H
|
|
|
|
#define ZONE_FILLER_H
|
2017-11-30 16:22:45 +00:00
|
|
|
|
|
|
|
#include <vector>
|
2020-11-11 23:05:59 +00:00
|
|
|
#include <zone.h>
|
2017-11-30 16:22:45 +00:00
|
|
|
|
2021-08-14 20:05:21 +00:00
|
|
|
class PROGRESS_REPORTER;
|
2017-11-30 16:22:45 +00:00
|
|
|
class BOARD;
|
|
|
|
class COMMIT;
|
2017-12-04 18:06:47 +00:00
|
|
|
class SHAPE_POLY_SET;
|
|
|
|
class SHAPE_LINE_CHAIN;
|
2017-11-30 16:22:45 +00:00
|
|
|
|
2019-06-23 18:22:34 +00:00
|
|
|
|
2017-11-30 16:22:45 +00:00
|
|
|
class ZONE_FILLER
|
|
|
|
{
|
|
|
|
public:
|
2020-08-12 16:39:57 +00:00
|
|
|
ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit );
|
2017-11-30 16:22:45 +00:00
|
|
|
~ZONE_FILLER();
|
|
|
|
|
2020-09-16 15:03:55 +00:00
|
|
|
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
|
2022-02-17 12:48:29 +00:00
|
|
|
PROGRESS_REPORTER* GetProgressReporter() const { return m_progressReporter; }
|
Fix issues with zone filling connectivity locking
Two issues found with the locking system used to prevent access to
stale connectivity data during the zone fill process:
1) a std::mutex has undefined behavior if you try to use it to guard
against access from the same thread. Because of the use of wx event
loops (and coroutines) it is entirely possible, and in some situations
inevitable, that the same thread will try to redraw the ratsnest in the
middle of zone refilling.
2) The mutex was only guarding the ZONE_FILLER::Fill method, but the callers
of that method also do connectivity updates as part of the COMMIT::Push.
Redrawing the ratsnest after the Fill but before the Push will result in
stale connectivity pointers to zone filled areas.
Fixed (1) by switching to a trivial spinlock implementation. Spinlocks would
generally not be desirable if the contention for the connectivity data crossed
thread boundaries, but at the moment I believe it's guaranteed that the reads
and writes to connectivity that are guarded by this lock happen from the main
UI thread. The writes are also quite rare compared to reads, and reads are
generally fast, so I'm not really worried about the UI thread spinning for any
real amount of time.
Fixed (2) by moving the locking location up to the call sites of
ZONE_FILLER::Fill.
This issue was quite difficult to reproduce, but I found a fairly reliable way:
It only happens (for me) on Windows, MSYS2 build, with wxWidgets 3.0
It also only happens if I restrict PcbNew to use 2 CPU cores.
With those conditions, I can reproduce the issue described in #6471 by
repeatedly editing a zone properties and changing its net. The crash is
especially easy to trigger if you press some keys (such as 'e' for edit)
while the progress dialog is displayed. It's easiest to do this in a debug
build as the slower KiCad is running, the bigger the window is to trigger this
bug.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/6471
Fixes https://gitlab.com/kicad/code/kicad/-/issues/7048
2021-01-18 17:24:07 +00:00
|
|
|
|
|
|
|
/**
|
2022-09-29 16:07:42 +00:00
|
|
|
* Fills the given list of zones.
|
|
|
|
*
|
|
|
|
* NB: Invalidates connectivity - it is up to the caller to obtain a lock on the connectivity
|
|
|
|
* data before calling Fill to prevent access to stale data by other coroutines (for example,
|
|
|
|
* ratsnest redraw). This will generally be required if a UI-based progress reporter has been
|
|
|
|
* installed.
|
|
|
|
*
|
|
|
|
* Caller is also responsible for re-building connectivity afterwards.
|
Fix issues with zone filling connectivity locking
Two issues found with the locking system used to prevent access to
stale connectivity data during the zone fill process:
1) a std::mutex has undefined behavior if you try to use it to guard
against access from the same thread. Because of the use of wx event
loops (and coroutines) it is entirely possible, and in some situations
inevitable, that the same thread will try to redraw the ratsnest in the
middle of zone refilling.
2) The mutex was only guarding the ZONE_FILLER::Fill method, but the callers
of that method also do connectivity updates as part of the COMMIT::Push.
Redrawing the ratsnest after the Fill but before the Push will result in
stale connectivity pointers to zone filled areas.
Fixed (1) by switching to a trivial spinlock implementation. Spinlocks would
generally not be desirable if the contention for the connectivity data crossed
thread boundaries, but at the moment I believe it's guaranteed that the reads
and writes to connectivity that are guarded by this lock happen from the main
UI thread. The writes are also quite rare compared to reads, and reads are
generally fast, so I'm not really worried about the UI thread spinning for any
real amount of time.
Fixed (2) by moving the locking location up to the call sites of
ZONE_FILLER::Fill.
This issue was quite difficult to reproduce, but I found a fairly reliable way:
It only happens (for me) on Windows, MSYS2 build, with wxWidgets 3.0
It also only happens if I restrict PcbNew to use 2 CPU cores.
With those conditions, I can reproduce the issue described in #6471 by
repeatedly editing a zone properties and changing its net. The crash is
especially easy to trigger if you press some keys (such as 'e' for edit)
while the progress dialog is displayed. It's easiest to do this in a debug
build as the slower KiCad is running, the bigger the window is to trigger this
bug.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/6471
Fixes https://gitlab.com/kicad/code/kicad/-/issues/7048
2021-01-18 17:24:07 +00:00
|
|
|
*/
|
2020-11-11 23:05:59 +00:00
|
|
|
bool Fill( std::vector<ZONE*>& aZones, bool aCheck = false, wxWindow* aParent = nullptr );
|
2017-11-30 16:22:45 +00:00
|
|
|
|
2020-10-29 21:17:57 +00:00
|
|
|
bool IsDebug() const { return m_debugZoneFiller; }
|
|
|
|
|
2017-11-30 16:22:45 +00:00
|
|
|
private:
|
2017-12-04 18:06:47 +00:00
|
|
|
|
2020-11-12 22:30:02 +00:00
|
|
|
void addKnockout( PAD* aPad, PCB_LAYER_ID aLayer, int aGap, SHAPE_POLY_SET& aHoles );
|
2019-06-20 22:35:01 +00:00
|
|
|
|
2020-08-12 21:18:13 +00:00
|
|
|
void addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap, bool aIgnoreLineWidth,
|
|
|
|
SHAPE_POLY_SET& aHoles );
|
2019-06-20 22:35:01 +00:00
|
|
|
|
2021-08-09 21:25:16 +00:00
|
|
|
void addHoleKnockout( PAD* aPad, int aGap, SHAPE_POLY_SET& aHoles );
|
|
|
|
|
2021-08-08 13:37:14 +00:00
|
|
|
void knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aFill,
|
|
|
|
std::vector<PAD*>& aThermalConnectionPads,
|
|
|
|
std::vector<PAD*>& aNoConnectionPads );
|
2019-06-20 22:35:01 +00:00
|
|
|
|
2020-11-11 23:05:59 +00:00
|
|
|
void buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
2021-08-08 13:37:14 +00:00
|
|
|
const std::vector<PAD*> aNoConnectionPads,
|
2020-06-24 02:19:08 +00:00
|
|
|
SHAPE_POLY_SET& aHoles );
|
2017-12-04 18:06:47 +00:00
|
|
|
|
2020-11-11 23:05:59 +00:00
|
|
|
void subtractHigherPriorityZones( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
2020-10-24 15:32:37 +00:00
|
|
|
SHAPE_POLY_SET& aRawFill );
|
|
|
|
|
2017-12-04 18:06:47 +00:00
|
|
|
/**
|
2022-02-16 15:33:12 +00:00
|
|
|
* Function fillCopperZone
|
2017-12-04 18:06:47 +00:00
|
|
|
* Add non copper areas polygons (pads and tracks with clearance)
|
|
|
|
* to a filled copper area
|
|
|
|
* used in BuildFilledSolidAreasPolygons when calculating filled areas in a zone
|
|
|
|
* Non copper areas are pads and track and their clearance area
|
|
|
|
* The filled copper area must be computed before
|
|
|
|
* BuildFilledSolidAreasPolygons() call this function just after creating the
|
|
|
|
* filled copper area polygon (without clearance areas
|
|
|
|
* @param aPcb: the current board
|
|
|
|
*/
|
2022-02-16 15:33:12 +00:00
|
|
|
bool fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LAYER_ID aDebugLayer,
|
|
|
|
const SHAPE_POLY_SET& aSmoothedOutline,
|
2022-03-08 18:06:05 +00:00
|
|
|
const SHAPE_POLY_SET& aMaxExtents, SHAPE_POLY_SET& aFillPolys );
|
2017-12-04 18:06:47 +00:00
|
|
|
|
2022-03-08 18:06:05 +00:00
|
|
|
bool fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
|
|
|
const SHAPE_POLY_SET& aSmoothedOutline, SHAPE_POLY_SET& aFillPolys );
|
2017-12-13 23:33:20 +00:00
|
|
|
/**
|
2019-06-20 22:35:01 +00:00
|
|
|
* Function buildThermalSpokes
|
2019-06-22 14:03:17 +00:00
|
|
|
* Constructs a list of all thermal spokes for the given zone.
|
2017-12-13 23:33:20 +00:00
|
|
|
*/
|
2022-10-01 18:05:42 +00:00
|
|
|
void buildThermalSpokes( const ZONE* box, PCB_LAYER_ID aLayer,
|
2021-08-08 13:37:14 +00:00
|
|
|
const std::vector<PAD*>& aSpokedPadsList,
|
2020-06-24 02:19:08 +00:00
|
|
|
std::deque<SHAPE_LINE_CHAIN>& aSpokes );
|
2017-12-13 23:33:20 +00:00
|
|
|
|
2017-12-04 18:06:47 +00:00
|
|
|
/**
|
|
|
|
* Build the filled solid areas polygons from zone outlines (stored in m_Poly)
|
|
|
|
* The solid areas can be more than one on copper layers, and do not have holes
|
|
|
|
* ( holes are linked by overlapping segments to the main outline)
|
|
|
|
* in order to have drawable (and plottable) filled polygons.
|
|
|
|
* @return true if OK, false if the solid polygons cannot be built
|
2018-01-14 08:51:32 +00:00
|
|
|
* @param aZone is the zone to fill
|
2022-02-16 15:33:12 +00:00
|
|
|
* @param aFillPolys: A reference to a SHAPE_POLY_SET buffer to store polygons with no holes
|
2021-06-09 19:32:58 +00:00
|
|
|
* (holes are linked to main outline by overlapping segments, and these polygons are shrunk
|
2018-01-14 08:51:32 +00:00
|
|
|
* by aZone->GetMinThickness() / 2 to be drawn with a outline thickness = aZone->GetMinThickness()
|
2022-03-08 18:06:05 +00:00
|
|
|
* aFillPolys are polygons that will be drawn on screen and plotted
|
2017-12-04 18:06:47 +00:00
|
|
|
*/
|
2022-02-16 15:33:12 +00:00
|
|
|
bool fillSingleZone( ZONE* aZone, PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aFillPolys );
|
2017-12-04 18:06:47 +00:00
|
|
|
|
2018-02-18 09:09:13 +00:00
|
|
|
/**
|
2019-12-20 14:11:39 +00:00
|
|
|
* for zones having the ZONE_FILL_MODE::ZONE_FILL_MODE::HATCH_PATTERN, create a grid pattern
|
2018-02-18 09:09:13 +00:00
|
|
|
* in filled areas of aZone, giving to the filled polygons a fill style like a grid
|
|
|
|
* @param aZone is the zone to modify
|
2022-03-08 18:06:05 +00:00
|
|
|
* @param aFillPolys: A reference to a SHAPE_POLY_SET buffer containing the initial
|
2018-02-18 09:09:13 +00:00
|
|
|
* filled areas, and after adding the grid pattern, the modified filled areas with holes
|
|
|
|
*/
|
2020-11-11 23:05:59 +00:00
|
|
|
bool addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LAYER_ID aDebugLayer,
|
2022-03-08 18:06:05 +00:00
|
|
|
SHAPE_POLY_SET& aFillPolys );
|
2018-02-18 09:09:13 +00:00
|
|
|
|
2020-09-14 17:54:14 +00:00
|
|
|
BOARD* m_board;
|
|
|
|
SHAPE_POLY_SET m_boardOutline; // the board outlines, if exists
|
|
|
|
bool m_brdOutlinesValid; // true if m_boardOutline is well-formed
|
|
|
|
COMMIT* m_commit;
|
2020-09-16 15:03:55 +00:00
|
|
|
PROGRESS_REPORTER* m_progressReporter;
|
2020-09-14 17:54:14 +00:00
|
|
|
|
|
|
|
int m_maxError;
|
2020-10-24 15:32:37 +00:00
|
|
|
int m_worstClearance;
|
2020-09-23 09:35:13 +00:00
|
|
|
|
|
|
|
bool m_debugZoneFiller;
|
2017-11-30 16:22:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|