KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_cache_generator.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <common.h>
26#include <footprint.h>
27#include <thread_pool.h>
28#include <zone.h>
30#include <drc/drc_engine.h>
31#include <drc/drc_rtree.h>
33#include <mutex>
34
36{
38
39 int& largestClearance = m_board->m_DRCMaxClearance;
40 int& largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
41 DRC_CONSTRAINT worstConstraint;
42 LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
44
45 largestClearance = std::max( largestClearance, m_board->GetMaxClearanceValue() );
46
48 largestPhysicalClearance = worstConstraint.GetValue().Min();
49
51 largestPhysicalClearance = std::max( largestPhysicalClearance, worstConstraint.GetValue().Min() );
52
53 // Ensure algorithmic safety
54 largestClearance = std::min( largestClearance, INT_MAX / 3 );
55 largestPhysicalClearance = std::min( largestPhysicalClearance, INT_MAX / 3 );
56
57 std::set<ZONE*> allZones;
58
59 auto cacheBBoxes =
60 []( ZONE* zone, const LSET& copperLayers )
61 {
62 zone->Outline()->BuildBBoxCaches();
63
64 for( PCB_LAYER_ID layer : copperLayers )
65 {
66 if( SHAPE_POLY_SET* fill = zone->GetFill( layer ) )
67 fill->BuildBBoxCaches();
68 }
69 };
70
71 for( ZONE* zone : m_board->Zones() )
72 {
73 allZones.insert( zone );
74
75 if( !zone->GetIsRuleArea() )
76 {
77 m_board->m_DRCZones.push_back( zone );
78
79 LSET zoneCopperLayers = zone->GetLayerSet() & boardCopperLayers;
80
81 if( zoneCopperLayers.any() )
82 {
83 cacheBBoxes( zone, zoneCopperLayers );
84 m_board->m_DRCCopperZones.push_back( zone );
85 }
86 }
87 }
88
89 for( FOOTPRINT* footprint : m_board->Footprints() )
90 {
91 for( ZONE* zone : footprint->Zones() )
92 {
93 allZones.insert( zone );
94
95 if( !zone->GetIsRuleArea() )
96 {
97 m_board->m_DRCZones.push_back( zone );
98
99 LSET zoneCopperLayers = zone->GetLayerSet() & boardCopperLayers;
100
101 if( zoneCopperLayers.any() )
102 {
103 cacheBBoxes( zone, zoneCopperLayers );
104 m_board->m_DRCCopperZones.push_back( zone );
105 }
106 }
107 }
108 }
109
110 size_t count = 0;
111 std::atomic<size_t> done( 1 );
112
113 auto countItems =
114 [&]( BOARD_ITEM* item ) -> bool
115 {
116 ++count;
117 return true;
118 };
119
120 auto addToCopperTree =
121 [&]( BOARD_ITEM* item ) -> bool
122 {
123 if( m_drcEngine->IsCancelled() )
124 return false;
125
126 LSET copperLayers = item->GetLayerSet() & boardCopperLayers;
127
128 // Special-case pad holes which pierce all the copper layers
129 if( item->Type() == PCB_PAD_T )
130 {
131 PAD* pad = static_cast<PAD*>( item );
132
133 if( pad->HasHole() )
134 copperLayers = boardCopperLayers;
135 }
136
137 copperLayers.RunOnLayers(
138 [&]( PCB_LAYER_ID layer )
139 {
140 m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance );
141 } );
142
143 done.fetch_add( 1 );
144 return true;
145 };
146
147 if( !reportPhase( _( "Gathering copper items..." ) ) )
148 return false; // DRC cancelled
149
150 static const std::vector<KICAD_T> itemTypes = {
152 PCB_PAD_T,
157 };
158
159 forEachGeometryItem( itemTypes, boardCopperLayers, countItems );
160
161 std::future<void> retn = tp.submit(
162 [&]()
163 {
164 std::unique_lock<std::shared_mutex> writeLock( m_board->m_CachesMutex );
165
167 m_board->m_CopperItemRTreeCache = std::make_shared<DRC_RTREE>();
168
169 forEachGeometryItem( itemTypes, boardCopperLayers, addToCopperTree );
170 } );
171
172 std::future_status status = retn.wait_for( std::chrono::milliseconds( 250 ) );
173
174 while( status != std::future_status::ready )
175 {
176 reportProgress( done, count );
177 status = retn.wait_for( std::chrono::milliseconds( 250 ) );
178 }
179
180 if( !reportPhase( _( "Tessellating copper zones..." ) ) )
181 return false; // DRC cancelled
182
183 // Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards
184 // before we start.
185
186 for( FOOTPRINT* footprint : m_board->Footprints() )
187 {
188 footprint->BuildCourtyardCaches();
189 footprint->BuildNetTieCache();
190 }
191
192 std::vector<std::future<size_t>> returns;
193
194 returns.reserve( allZones.size() );
195
196 auto cache_zones =
197 [this, &done]( ZONE* aZone ) -> size_t
198 {
199 if( m_drcEngine->IsCancelled() )
200 return 0;
201
202 aZone->CacheBoundingBox();
203 aZone->CacheTriangulation();
204
205 if( !aZone->GetIsRuleArea() && aZone->IsOnCopperLayer() )
206 {
207 std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
208
209 aZone->GetLayerSet().RunOnLayers(
210 [&]( PCB_LAYER_ID layer )
211 {
212 if( IsCopperLayer( layer ) )
213 rtree->Insert( aZone, layer );
214 } );
215
216 {
217 std::unique_lock<std::shared_mutex> writeLock( m_board->m_CachesMutex );
218 m_board->m_CopperZoneRTreeCache[ aZone ] = std::move( rtree );
219 }
220
221 done.fetch_add( 1 );
222 }
223
224 return 1;
225 };
226
227 for( ZONE* zone : allZones )
228 returns.emplace_back( tp.submit( cache_zones, zone ) );
229
230 done.store( 1 );
231
232 for( const std::future<size_t>& ret : returns )
233 {
234 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
235
236 while( status != std::future_status::ready )
237 {
238 reportProgress( done, allZones.size() );
239 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
240 }
241 }
242
244
245 for( ZONE* zone : m_board->Zones() )
246 {
247 if( !zone->GetIsRuleArea() && !zone->IsTeardropArea() )
248 {
249 zone->GetLayerSet().RunOnLayers(
250 [&]( PCB_LAYER_ID layer )
251 {
253 } );
254 }
255 }
256
257 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
258
259 connectivity->ClearRatsnest();
260 connectivity->Build( m_board, m_drcEngine->GetProgressReporter() );
261 connectivity->FillIsolatedIslandsMap( m_board->m_ZoneIsolatedIslandsMap, true );
262
263 return !m_drcEngine->IsCancelled();
264}
265
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition: board.h:1386
std::vector< ZONE * > m_DRCCopperZones
Definition: board.h:1382
const ZONES & Zones() const
Definition: board.h:362
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:1036
int GetCopperLayerCount() const
Definition: board.cpp:859
const FOOTPRINTS & Footprints() const
Definition: board.h:358
int m_DRCMaxPhysicalClearance
Definition: board.h:1384
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition: board.h:1376
int m_DRCMaxClearance
Definition: board.h:1383
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition: board.h:1375
std::vector< ZONE * > m_DRCZones
Definition: board.h:1381
std::shared_mutex m_CachesMutex
Definition: board.h:1368
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:522
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:160
BOARD * GetBoard() const
Definition: drc_engine.h:100
PROGRESS_REPORTER * GetProgressReporter() const
Definition: drc_engine.h:135
bool IsCancelled() const
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
virtual bool reportPhase(const wxString &aStageName)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
DRC_ENGINE * m_drcEngine
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
Definition: lset.h:260
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition: lset.cpp:591
T Min() const
Definition: minoptmax.h:33
Definition: pad.h:54
Represent a set of closed polygons.
void BuildBBoxCaches() const
Construct BBoxCaches for Contains(), below.
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:704
SHAPE_POLY_SET * Outline()
Definition: zone.h:335
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
Definition: zone.h:606
bool IsTeardropArea() const
Definition: zone.h:679
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:136
The common library.
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:78
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:77
#define _(s)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:665
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
A struct recording the isolated and single-pad islands within a zone.
Definition: zone.h:61
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Definition: thread_pool.cpp:30
static thread_pool * tp
Definition: thread_pool.cpp:28
BS::thread_pool thread_pool
Definition: thread_pool.h:31
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition: typeinfo.h:95
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition: typeinfo.h:94
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96