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 <pcb_board_outline.h>
27#include <footprint.h>
28#include <thread_pool.h>
29#include <zone.h>
31#include <drc/drc_engine.h>
32#include <drc/drc_rtree.h>
34#include <mutex>
35
37{
38 m_board = m_drcEngine->GetBoard();
39
40 int& largestClearance = m_board->m_DRCMaxClearance;
41 int& largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
42 DRC_CONSTRAINT worstConstraint;
43 LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
45
46 largestClearance = std::max( largestClearance, m_board->GetMaxClearanceValue() );
47
48 if( m_drcEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, worstConstraint ) )
49 largestPhysicalClearance = worstConstraint.GetValue().Min();
50
51 if( m_drcEngine->QueryWorstConstraint( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, worstConstraint ) )
52 largestPhysicalClearance = std::max( largestPhysicalClearance, worstConstraint.GetValue().Min() );
53
54 // Ensure algorithmic safety
55 largestClearance = std::min( largestClearance, INT_MAX / 3 );
56 largestPhysicalClearance = std::min( largestPhysicalClearance, INT_MAX / 3 );
57
58 std::set<ZONE*> allZones;
59
60 auto cacheBBoxes =
61 []( ZONE* zone, const LSET& copperLayers )
62 {
63 zone->Outline()->BuildBBoxCaches();
64
65 for( PCB_LAYER_ID layer : copperLayers )
66 {
67 if( SHAPE_POLY_SET* fill = zone->GetFill( layer ) )
68 fill->BuildBBoxCaches();
69 }
70 };
71
72 for( ZONE* zone : m_board->Zones() )
73 {
74 allZones.insert( zone );
75
76 if( !zone->GetIsRuleArea() )
77 {
78 m_board->m_DRCZones.push_back( zone );
79
80 LSET zoneCopperLayers = zone->GetLayerSet() & boardCopperLayers;
81
82 if( zoneCopperLayers.any() )
83 {
84 cacheBBoxes( zone, zoneCopperLayers );
85 m_board->m_DRCCopperZones.push_back( zone );
86 }
87 }
88 }
89
90 for( FOOTPRINT* footprint : m_board->Footprints() )
91 {
92 for( ZONE* zone : footprint->Zones() )
93 {
94 allZones.insert( zone );
95
96 if( !zone->GetIsRuleArea() )
97 {
98 m_board->m_DRCZones.push_back( zone );
99
100 LSET zoneCopperLayers = zone->GetLayerSet() & boardCopperLayers;
101
102 if( zoneCopperLayers.any() )
103 {
104 cacheBBoxes( zone, zoneCopperLayers );
105 m_board->m_DRCCopperZones.push_back( zone );
106 }
107 }
108 }
109 }
110
111 size_t count = 0;
112 std::atomic<size_t> done( 1 );
113
114 auto countItems =
115 [&]( BOARD_ITEM* item ) -> bool
116 {
117 ++count;
118 return true;
119 };
120
121 auto addToCopperTree =
122 [&]( BOARD_ITEM* item ) -> bool
123 {
124 if( m_drcEngine->IsCancelled() )
125 return false;
126
127 LSET copperLayers = item->GetLayerSet() & boardCopperLayers;
128
129 // Special-case pad holes which pierce all the copper layers
130 if( item->Type() == PCB_PAD_T )
131 {
132 PAD* pad = static_cast<PAD*>( item );
133
134 if( pad->HasHole() )
135 copperLayers = boardCopperLayers;
136 }
137
138 copperLayers.RunOnLayers(
139 [&]( PCB_LAYER_ID layer )
140 {
141 m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance );
142 } );
143
144 done.fetch_add( 1 );
145 return true;
146 };
147
148 if( !reportPhase( _( "Gathering copper items..." ) ) )
149 return false; // DRC cancelled
150
151 static const std::vector<KICAD_T> itemTypes = {
153 PCB_PAD_T,
159 };
160
161 forEachGeometryItem( itemTypes, boardCopperLayers, countItems );
162
163 std::future<void> retn = tp.submit_task(
164 [&]()
165 {
166 std::unique_lock<std::shared_mutex> writeLock( m_board->m_CachesMutex );
167
168 if( !m_board->m_CopperItemRTreeCache )
169 m_board->m_CopperItemRTreeCache = std::make_shared<DRC_RTREE>();
170
171 forEachGeometryItem( itemTypes, boardCopperLayers, addToCopperTree );
172 } );
173
174 std::future_status status = retn.wait_for( std::chrono::milliseconds( 250 ) );
175
176 while( status != std::future_status::ready )
177 {
178 reportProgress( done, count );
179 status = retn.wait_for( std::chrono::milliseconds( 250 ) );
180 }
181
182 if( !reportPhase( _( "Tessellating copper zones..." ) ) )
183 return false; // DRC cancelled
184
185 // Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards
186 // before we start.
187
188 for( FOOTPRINT* footprint : m_board->Footprints() )
189 {
190 footprint->BuildCourtyardCaches();
191 footprint->BuildNetTieCache();
192 }
193
194 std::vector<std::future<size_t>> returns;
195
196 returns.reserve( allZones.size() );
197
198 auto cache_zones =
199 [this, &done]( ZONE* aZone ) -> size_t
200 {
201 if( m_drcEngine->IsCancelled() )
202 return 0;
203
204 aZone->CacheBoundingBox();
205 aZone->CacheTriangulation();
206
207 if( !aZone->GetIsRuleArea() && aZone->IsOnCopperLayer() )
208 {
209 std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
210
211 aZone->GetLayerSet().RunOnLayers(
212 [&]( PCB_LAYER_ID layer )
213 {
214 if( IsCopperLayer( layer ) )
215 rtree->Insert( aZone, layer );
216 } );
217
218 {
219 std::unique_lock<std::shared_mutex> writeLock( m_board->m_CachesMutex );
220 m_board->m_CopperZoneRTreeCache[ aZone ] = std::move( rtree );
221 }
222
223 done.fetch_add( 1 );
224 }
225
226 return 1;
227 };
228
229 for( ZONE* zone : allZones )
230 {
231 returns.emplace_back( tp.submit_task(
232 [cache_zones, zone]
233 {
234 return cache_zones( zone );
235 } ) );
236 }
237
238 done.store( 1 );
239
240 for( const std::future<size_t>& ret : returns )
241 {
242 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
243
244 while( status != std::future_status::ready )
245 {
246 reportProgress( done, allZones.size() );
247 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
248 }
249 }
250
251 m_board->m_ZoneIsolatedIslandsMap.clear();
252
253 for( ZONE* zone : m_board->Zones() )
254 {
255 if( !zone->GetIsRuleArea() && !zone->IsTeardropArea() )
256 {
257 zone->GetLayerSet().RunOnLayers(
258 [&]( PCB_LAYER_ID layer )
259 {
260 m_board->m_ZoneIsolatedIslandsMap[ zone ][ layer ] = ISOLATED_ISLANDS();
261 } );
262 }
263 }
264
265 m_board->UpdateBoardOutline();
266
267 if( m_board->BoardOutline() )
268 m_board->BoardOutline()->GetOutline().BuildBBoxCaches();
269
270 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
271
272 connectivity->ClearRatsnest();
273 connectivity->Build( m_board, m_drcEngine->GetProgressReporter() );
274 connectivity->FillIsolatedIslandsMap( m_board->m_ZoneIsolatedIslandsMap, true );
275
276 return !m_drcEngine->IsCancelled();
277}
278
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
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:186
virtual bool reportPhase(const wxString &aStageName)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
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:252
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
T Min() const
Definition minoptmax.h:33
Definition pad.h:55
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:701
SHAPE_POLY_SET * Outline()
Definition zone.h:331
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
Definition zone.h:602
bool IsTeardropArea() const
Definition zone.h:676
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:677
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.
static thread_pool * tp
BS::priority_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_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ 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