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 (C) 2022 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
35{
37
38 int& m_largestClearance = m_board->m_DRCMaxClearance;
39 int& m_largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
40 DRC_CONSTRAINT worstConstraint;
41 LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
42
44 m_largestClearance = worstConstraint.GetValue().Min();
45
47 m_largestClearance = std::max( m_largestClearance, worstConstraint.GetValue().Min() );
48
50 m_largestPhysicalClearance = worstConstraint.GetValue().Min();
51
53 m_largestPhysicalClearance = std::max( m_largestPhysicalClearance, worstConstraint.GetValue().Min() );
54
55 std::set<ZONE*> allZones;
56
57 for( ZONE* zone : m_board->Zones() )
58 {
59 allZones.insert( zone );
60
61 if( !zone->GetIsRuleArea() )
62 {
63 m_board->m_DRCZones.push_back( zone );
64
65 if( ( zone->GetLayerSet() & boardCopperLayers ).any() )
66 {
67 m_board->m_DRCCopperZones.push_back( zone );
68 m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
69 }
70 }
71 }
72
73 for( FOOTPRINT* footprint : m_board->Footprints() )
74 {
75 for( PAD* pad : footprint->Pads() )
76 m_largestClearance = std::max( m_largestClearance, pad->GetLocalClearance() );
77
78 for( ZONE* zone : footprint->Zones() )
79 {
80 allZones.insert( zone );
81
82 if( !zone->GetIsRuleArea() )
83 {
84 m_board->m_DRCZones.push_back( zone );
85
86 if( ( zone->GetLayerSet() & boardCopperLayers ).any() )
87 {
88 m_board->m_DRCCopperZones.push_back( zone );
89 m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
90 }
91 }
92 }
93 }
94
95 // This is the number of tests between 2 calls to the progress bar
96 size_t progressDelta = 200;
97 size_t count = 0;
98 size_t ii = 0;
99
100 auto countItems =
101 [&]( BOARD_ITEM* item ) -> bool
102 {
103 ++count;
104 return true;
105 };
106
107 auto addToCopperTree =
108 [&]( BOARD_ITEM* item ) -> bool
109 {
110 if( !reportProgress( ii++, count, progressDelta ) )
111 return false;
112
113 LSET copperLayers = item->GetLayerSet() & boardCopperLayers;
114
115 // Special-case pad holes which pierce all the copper layers
116 if( item->Type() == PCB_PAD_T )
117 {
118 PAD* pad = static_cast<PAD*>( item );
119
120 if( pad->HasHole() )
121 copperLayers = boardCopperLayers;
122 }
123
124 for( PCB_LAYER_ID layer : copperLayers.Seq() )
125 {
126 if( IsCopperLayer( layer ) )
127 m_board->m_CopperItemRTreeCache->Insert( item, layer, m_largestClearance );
128 }
129
130 return true;
131 };
132
133 if( !reportPhase( _( "Gathering copper items..." ) ) )
134 return false; // DRC cancelled
135
136 static const std::vector<KICAD_T> itemTypes = {
138 PCB_PAD_T,
142 };
143
144 forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );
145
146 {
147 std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
148
150 m_board->m_CopperItemRTreeCache = std::make_shared<DRC_RTREE>();
151
152 forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree );
153 }
154
155 if( !reportPhase( _( "Tessellating copper zones..." ) ) )
156 return false; // DRC cancelled
157
158 // Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards
159 // before we start.
160
161 for( FOOTPRINT* footprint : m_board->Footprints() )
162 footprint->BuildCourtyardCaches();
163
165 std::vector<std::future<size_t>> returns;
166 std::atomic<size_t> done( 1 );
167
168 returns.reserve( allZones.size() );
169
170 auto cache_zones =
171 [this, &done]( ZONE* aZone ) -> size_t
172 {
173 if( m_drcEngine->IsCancelled() )
174 return 0;
175
176 aZone->CacheBoundingBox();
177 aZone->CacheTriangulation();
178
179 if( !aZone->GetIsRuleArea() && aZone->IsOnCopperLayer() )
180 {
181 std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
182
183 for( PCB_LAYER_ID layer : aZone->GetLayerSet().Seq() )
184 {
185 if( IsCopperLayer( layer ) )
186 rtree->Insert( aZone, layer );
187 }
188
189 std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
190 m_board->m_CopperZoneRTreeCache[ aZone ] = std::move( rtree );
191
192 done.fetch_add( 1 );
193 }
194
195 return 1;
196 };
197
198 for( ZONE* zone : allZones )
199 returns.emplace_back( tp.submit( cache_zones, zone ) );
200
201 for( const std::future<size_t>& ret : returns )
202 {
203 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
204
205 while( status != std::future_status::ready )
206 {
207 m_drcEngine->ReportProgress( static_cast<double>( done ) / allZones.size() );
208 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
209 }
210 }
211
213
214 for( ZONE* zone : m_board->Zones() )
215 {
216 if( !zone->GetIsRuleArea() && !zone->IsTeardropArea() )
217 {
218 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
220 }
221 }
222
223 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
224
225 connectivity->ClearRatsnest();
226 connectivity->Build( m_board, m_drcEngine->GetProgressReporter() );
227 connectivity->FillIsolatedIslandsMap( m_board->m_ZoneIsolatedIslandsMap, true );
228
229 return !m_drcEngine->IsCancelled();
230}
231
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:71
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition: board.h:1193
std::vector< ZONE * > m_DRCCopperZones
Definition: board.h:1189
ZONES & Zones()
Definition: board.h:318
FOOTPRINTS & Footprints()
Definition: board.h:312
int GetCopperLayerCount() const
Definition: board.cpp:587
int m_DRCMaxPhysicalClearance
Definition: board.h:1191
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition: board.h:1184
int m_DRCMaxClearance
Definition: board.h:1190
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition: board.h:1183
std::vector< ZONE * > m_DRCZones
Definition: board.h:1188
std::mutex m_CachesMutex
Definition: board.h:1176
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:432
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:141
BOARD * GetBoard() const
Definition: drc_engine.h:89
bool ReportProgress(double aProgress)
PROGRESS_REPORTER * GetProgressReporter() const
Definition: drc_engine.h:124
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, LSET aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
virtual bool reportProgress(int aCount, int aSize, int aDelta)
DRC_ENGINE * m_drcEngine
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:536
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
T Min() const
Definition: minoptmax.h:33
Definition: pad.h:59
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
The common library.
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:71
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:47
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:70
#define _(s)
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:831
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
A struct recording the isolated and single-pad islands within a zone.
Definition: zone.h:59
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Definition: thread_pool.cpp:32
static thread_pool * tp
Definition: thread_pool.cpp:30
BS::thread_pool thread_pool
Definition: thread_pool.h:30
@ 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:93
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ 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:94
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:96
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:92