More caching for DRC.
Also fixes a bug where some physical clearance tests would be run even if the clearance was 0 (or if the rule was set to IGNORE).
This commit is contained in:
parent
f20cb0fda8
commit
97b0005780
|
@ -511,6 +511,7 @@ set( PCB_COMMON_SRCS
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/connectivity/from_to_cache.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/connectivity/from_to_cache.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/convert_shape_list_to_polygon.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/convert_shape_list_to_polygon.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_engine.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_engine.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_cache_generator.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_item.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_item.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_rule.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_rule.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_rule_condition.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_rule_condition.cpp
|
||||||
|
|
|
@ -216,9 +216,14 @@ void BOARD::IncrementTimeStamp()
|
||||||
m_InsideFCourtyardCache.clear();
|
m_InsideFCourtyardCache.clear();
|
||||||
m_InsideBCourtyardCache.clear();
|
m_InsideBCourtyardCache.clear();
|
||||||
m_LayerExpressionCache.clear();
|
m_LayerExpressionCache.clear();
|
||||||
}
|
|
||||||
|
|
||||||
m_CopperZoneRTrees.clear();
|
m_DRCMaxClearance = 0;
|
||||||
|
m_DRCMaxPhysicalClearance = 0;
|
||||||
|
m_DRCZones.clear();
|
||||||
|
m_DRCCopperZones.clear();
|
||||||
|
m_CopperZoneRTreeCache.clear();
|
||||||
|
m_CopperItemRTreeCache = std::make_unique<DRC_RTREE>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
|
std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
|
||||||
|
|
|
@ -1077,10 +1077,15 @@ public:
|
||||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideBCourtyardCache;
|
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideBCourtyardCache;
|
||||||
std::map< std::tuple<BOARD_ITEM*, BOARD_ITEM*, PCB_LAYER_ID>, bool > m_InsideAreaCache;
|
std::map< std::tuple<BOARD_ITEM*, BOARD_ITEM*, PCB_LAYER_ID>, bool > m_InsideAreaCache;
|
||||||
std::map< wxString, LSET > m_LayerExpressionCache;
|
std::map< wxString, LSET > m_LayerExpressionCache;
|
||||||
|
std::map< ZONE*, std::unique_ptr<DRC_RTREE> > m_CopperZoneRTreeCache;
|
||||||
|
std::unique_ptr<DRC_RTREE> m_CopperItemRTreeCache;
|
||||||
|
|
||||||
std::map< ZONE*, std::unique_ptr<DRC_RTREE> > m_CopperZoneRTrees;
|
// ------------ DRC caches -------------
|
||||||
|
std::vector<ZONE*> m_DRCZones;
|
||||||
ZONE* m_SolderMask;
|
std::vector<ZONE*> m_DRCCopperZones;
|
||||||
|
int m_DRCMaxClearance;
|
||||||
|
int m_DRCMaxPhysicalClearance;
|
||||||
|
ZONE* m_SolderMask;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The default copy constructor & operator= are inadequate,
|
// The default copy constructor & operator= are inadequate,
|
||||||
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 KiCad Developers.
|
||||||
|
*
|
||||||
|
* 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 <common.h>
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
#include <board_design_settings.h>
|
||||||
|
#include <footprint.h>
|
||||||
|
#include <zone.h>
|
||||||
|
|
||||||
|
#include <drc/drc_engine.h>
|
||||||
|
#include <drc/drc_rtree.h>
|
||||||
|
#include <drc/drc_cache_generator.h>
|
||||||
|
|
||||||
|
bool DRC_CACHE_GENERATOR::Run()
|
||||||
|
{
|
||||||
|
m_board = m_drcEngine->GetBoard();
|
||||||
|
|
||||||
|
int& m_largestClearance = m_board->m_DRCMaxClearance;
|
||||||
|
int& m_largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
|
||||||
|
DRC_CONSTRAINT worstConstraint;
|
||||||
|
|
||||||
|
if( m_drcEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, worstConstraint ) )
|
||||||
|
m_largestClearance = worstConstraint.GetValue().Min();
|
||||||
|
|
||||||
|
if( m_drcEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
||||||
|
m_largestClearance = std::max( m_largestClearance, worstConstraint.GetValue().Min() );
|
||||||
|
|
||||||
|
if( m_drcEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
||||||
|
m_largestPhysicalClearance = worstConstraint.GetValue().Min();
|
||||||
|
|
||||||
|
if( m_drcEngine->QueryWorstConstraint( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
||||||
|
m_largestPhysicalClearance = std::max( m_largestPhysicalClearance, worstConstraint.GetValue().Min() );
|
||||||
|
|
||||||
|
std::vector<ZONE*> allZones;
|
||||||
|
|
||||||
|
for( ZONE* zone : m_board->Zones() )
|
||||||
|
{
|
||||||
|
allZones.push_back( zone );
|
||||||
|
|
||||||
|
if( !zone->GetIsRuleArea() )
|
||||||
|
{
|
||||||
|
m_board->m_DRCZones.push_back( zone );
|
||||||
|
|
||||||
|
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() )
|
||||||
|
{
|
||||||
|
m_board->m_DRCCopperZones.push_back( zone );
|
||||||
|
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||||
|
{
|
||||||
|
for( PAD* pad : footprint->Pads() )
|
||||||
|
m_largestClearance = std::max( m_largestClearance, pad->GetLocalClearance() );
|
||||||
|
|
||||||
|
for( ZONE* zone : footprint->Zones() )
|
||||||
|
{
|
||||||
|
allZones.push_back( zone );
|
||||||
|
|
||||||
|
if( !zone->GetIsRuleArea() )
|
||||||
|
{
|
||||||
|
m_board->m_DRCZones.push_back( zone );
|
||||||
|
|
||||||
|
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() )
|
||||||
|
{
|
||||||
|
m_board->m_DRCCopperZones.push_back( zone );
|
||||||
|
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the number of tests between 2 calls to the progress bar
|
||||||
|
size_t delta = 50;
|
||||||
|
size_t count = 0;
|
||||||
|
size_t ii = 0;
|
||||||
|
|
||||||
|
auto countItems =
|
||||||
|
[&]( BOARD_ITEM* item ) -> bool
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto addToCopperTree =
|
||||||
|
[&]( BOARD_ITEM* item ) -> bool
|
||||||
|
{
|
||||||
|
if( !reportProgress( ii++, count, delta ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LSET layers = item->GetLayerSet();
|
||||||
|
|
||||||
|
// Special-case pad holes which pierce all the copper layers
|
||||||
|
if( item->Type() == PCB_PAD_T )
|
||||||
|
{
|
||||||
|
PAD* pad = static_cast<PAD*>( item );
|
||||||
|
|
||||||
|
if( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||||
|
layers |= LSET::AllCuMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( PCB_LAYER_ID layer : layers.Seq() )
|
||||||
|
{
|
||||||
|
if( IsCopperLayer( layer ) )
|
||||||
|
m_board->m_CopperItemRTreeCache->Insert( item, layer, m_largestClearance );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( !reportPhase( _( "Gathering copper items..." ) ) )
|
||||||
|
return false; // DRC cancelled
|
||||||
|
|
||||||
|
static const std::vector<KICAD_T> itemTypes = {
|
||||||
|
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
|
||||||
|
PCB_PAD_T,
|
||||||
|
PCB_SHAPE_T, PCB_FP_SHAPE_T,
|
||||||
|
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_TEXTBOX_T, PCB_FP_TEXTBOX_T,
|
||||||
|
PCB_DIMENSION_T
|
||||||
|
};
|
||||||
|
|
||||||
|
forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );
|
||||||
|
forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree );
|
||||||
|
|
||||||
|
if( !reportPhase( _( "Tessellating copper zones..." ) ) )
|
||||||
|
return false; // DRC cancelled
|
||||||
|
|
||||||
|
// Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards
|
||||||
|
// before we start.
|
||||||
|
//
|
||||||
|
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||||
|
footprint->BuildPolyCourtyards();
|
||||||
|
|
||||||
|
count = allZones.size();
|
||||||
|
std::atomic<size_t> next( 0 );
|
||||||
|
std::atomic<size_t> done( 0 );
|
||||||
|
std::atomic<size_t> threads_finished( 0 );
|
||||||
|
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
|
||||||
|
|
||||||
|
for( ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
|
{
|
||||||
|
std::thread t = std::thread(
|
||||||
|
[ this, &allZones, &done, &threads_finished, &next, count ]( )
|
||||||
|
{
|
||||||
|
for( size_t i = next.fetch_add( 1 ); i < count; i = next.fetch_add( 1 ) )
|
||||||
|
{
|
||||||
|
ZONE* zone = allZones[ i ];
|
||||||
|
|
||||||
|
zone->CacheBoundingBox();
|
||||||
|
zone->CacheTriangulation();
|
||||||
|
|
||||||
|
if( !zone->GetIsRuleArea() && zone->IsOnCopperLayer() )
|
||||||
|
{
|
||||||
|
std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
|
||||||
|
|
||||||
|
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||||
|
{
|
||||||
|
if( IsCopperLayer( layer ) )
|
||||||
|
rtree->Insert( zone, layer );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
|
||||||
|
m_board->m_CopperZoneRTreeCache[ zone ] = std::move( rtree );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_drcEngine->IsCancelled() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
done.fetch_add( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
threads_finished.fetch_add( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
t.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
while( threads_finished < parallelThreadCount )
|
||||||
|
{
|
||||||
|
reportProgress( done, count, 1 );
|
||||||
|
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return !m_drcEngine->IsCancelled();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
|
||||||
|
* Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 DRC_CACHE_GENERATOR__H
|
||||||
|
#define DRC_CACHE_GENERATOR__H
|
||||||
|
|
||||||
|
#include <drc/drc_test_provider_clearance_base.h>
|
||||||
|
|
||||||
|
|
||||||
|
class DRC_CACHE_GENERATOR : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DRC_CACHE_GENERATOR() :
|
||||||
|
DRC_TEST_PROVIDER_CLEARANCE_BASE()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~DRC_CACHE_GENERATOR()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Run() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DRC_CACHE_GENERATOR__H
|
|
@ -36,6 +36,7 @@
|
||||||
#include <drc/drc_rule_condition.h>
|
#include <drc/drc_rule_condition.h>
|
||||||
#include <drc/drc_test_provider.h>
|
#include <drc/drc_test_provider.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
|
#include <drc/drc_cache_generator.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
#include <pad.h>
|
#include <pad.h>
|
||||||
#include <pcb_track.h>
|
#include <pcb_track.h>
|
||||||
|
@ -594,76 +595,14 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
||||||
|
|
||||||
DRC_TEST_PROVIDER::Init();
|
DRC_TEST_PROVIDER::Init();
|
||||||
|
|
||||||
m_board->IncrementTimeStamp(); // Invalidate all caches
|
m_board->IncrementTimeStamp(); // Invalidate all caches...
|
||||||
|
|
||||||
if( !ReportPhase( _( "Tessellating copper zones..." ) ) )
|
DRC_CACHE_GENERATOR cacheGenerator;
|
||||||
|
cacheGenerator.SetDRCEngine( this );
|
||||||
|
|
||||||
|
if( !cacheGenerator.Run() ) // ... and regenerate them.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards
|
|
||||||
// before we start.
|
|
||||||
//
|
|
||||||
std::vector<ZONE*> allZones = m_board->Zones();
|
|
||||||
|
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
|
||||||
{
|
|
||||||
for( ZONE* zone : footprint->Zones() )
|
|
||||||
allZones.push_back( zone );
|
|
||||||
|
|
||||||
footprint->BuildPolyCourtyards();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t count = allZones.size();
|
|
||||||
std::atomic<size_t> next( 0 );
|
|
||||||
std::atomic<size_t> done( 0 );
|
|
||||||
std::atomic<size_t> threads_finished( 0 );
|
|
||||||
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
|
||||||
{
|
|
||||||
std::thread t = std::thread(
|
|
||||||
[ this, &allZones, &done, &threads_finished, &next, count ]( )
|
|
||||||
{
|
|
||||||
for( size_t i = next.fetch_add( 1 ); i < count; i = next.fetch_add( 1 ) )
|
|
||||||
{
|
|
||||||
ZONE* zone = allZones[ i ];
|
|
||||||
|
|
||||||
zone->CacheBoundingBox();
|
|
||||||
zone->CacheTriangulation();
|
|
||||||
|
|
||||||
if( !zone->GetIsRuleArea() && zone->IsOnCopperLayer() )
|
|
||||||
{
|
|
||||||
std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
|
|
||||||
|
|
||||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
|
||||||
{
|
|
||||||
if( IsCopperLayer( layer ) )
|
|
||||||
rtree->Insert( zone, layer );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
|
|
||||||
m_board->m_CopperZoneRTrees[ zone ] = std::move( rtree );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( IsCancelled() )
|
|
||||||
break;
|
|
||||||
|
|
||||||
done.fetch_add( 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
threads_finished.fetch_add( 1 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
t.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
while( threads_finished < parallelThreadCount )
|
|
||||||
{
|
|
||||||
ReportProgress( (double) done / (double) count );
|
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now run the tests.
|
|
||||||
//
|
|
||||||
for( DRC_TEST_PROVIDER* provider : m_testProviders )
|
for( DRC_TEST_PROVIDER* provider : m_testProviders )
|
||||||
{
|
{
|
||||||
ReportAux( wxString::Format( wxT( "Run DRC provider: '%s'" ), provider->GetName() ) );
|
ReportAux( wxString::Format( wxT( "Run DRC provider: '%s'" ), provider->GetName() ) );
|
||||||
|
|
|
@ -38,7 +38,6 @@ public:
|
||||||
DRC_TEST_PROVIDER_CLEARANCE_BASE () :
|
DRC_TEST_PROVIDER_CLEARANCE_BASE () :
|
||||||
DRC_TEST_PROVIDER(),
|
DRC_TEST_PROVIDER(),
|
||||||
m_board( nullptr ),
|
m_board( nullptr ),
|
||||||
m_largestClearance( 0 ),
|
|
||||||
m_boardOutlineValid( false )
|
m_boardOutlineValid( false )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -49,7 +48,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
int m_largestClearance;
|
|
||||||
bool m_boardOutlineValid;
|
bool m_boardOutlineValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -93,25 +93,15 @@ private:
|
||||||
void testItemAgainstZone( BOARD_ITEM* aItem, ZONE* aZone, PCB_LAYER_ID aLayer );
|
void testItemAgainstZone( BOARD_ITEM* aItem, ZONE* aZone, PCB_LAYER_ID aLayer );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DRC_RTREE m_copperTree;
|
int m_drcEpsilon;
|
||||||
int m_drcEpsilon;
|
|
||||||
|
|
||||||
std::vector<ZONE*> m_copperZones;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
||||||
{
|
{
|
||||||
m_board = m_drcEngine->GetBoard();
|
m_board = m_drcEngine->GetBoard();
|
||||||
DRC_CONSTRAINT worstConstraint;
|
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, worstConstraint ) )
|
if( m_board->m_DRCMaxClearance <= 0 )
|
||||||
m_largestClearance = worstConstraint.GetValue().Min();
|
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
|
||||||
m_largestClearance = std::max( m_largestClearance, worstConstraint.GetValue().Min() );
|
|
||||||
|
|
||||||
if( m_largestClearance <= 0 )
|
|
||||||
{
|
{
|
||||||
reportAux( wxT( "No Clearance constraints found. Tests not run." ) );
|
reportAux( wxT( "No Clearance constraints found. Tests not run." ) );
|
||||||
return true; // continue with other tests
|
return true; // continue with other tests
|
||||||
|
@ -119,90 +109,6 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
||||||
|
|
||||||
m_drcEpsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
m_drcEpsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
||||||
|
|
||||||
m_copperZones.clear();
|
|
||||||
|
|
||||||
for( ZONE* zone : m_board->Zones() )
|
|
||||||
{
|
|
||||||
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() && !zone->GetIsRuleArea() )
|
|
||||||
{
|
|
||||||
m_copperZones.push_back( zone );
|
|
||||||
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
|
||||||
{
|
|
||||||
for( PAD* pad : footprint->Pads() )
|
|
||||||
m_largestClearance = std::max( m_largestClearance, pad->GetLocalClearance() );
|
|
||||||
|
|
||||||
for( ZONE* zone : footprint->Zones() )
|
|
||||||
{
|
|
||||||
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() && !zone->GetIsRuleArea() )
|
|
||||||
{
|
|
||||||
m_copperZones.push_back( zone );
|
|
||||||
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reportAux( wxT( "Worst clearance : %d nm" ), m_largestClearance );
|
|
||||||
|
|
||||||
// This is the number of tests between 2 calls to the progress bar
|
|
||||||
size_t delta = 50;
|
|
||||||
size_t count = 0;
|
|
||||||
size_t ii = 0;
|
|
||||||
|
|
||||||
m_copperTree.clear();
|
|
||||||
|
|
||||||
auto countItems =
|
|
||||||
[&]( BOARD_ITEM* item ) -> bool
|
|
||||||
{
|
|
||||||
++count;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto addToCopperTree =
|
|
||||||
[&]( BOARD_ITEM* item ) -> bool
|
|
||||||
{
|
|
||||||
if( !reportProgress( ii++, count, delta ) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
LSET layers = item->GetLayerSet();
|
|
||||||
|
|
||||||
// Special-case pad holes which pierce all the copper layers
|
|
||||||
if( item->Type() == PCB_PAD_T )
|
|
||||||
{
|
|
||||||
PAD* pad = static_cast<PAD*>( item );
|
|
||||||
|
|
||||||
if( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
|
||||||
layers |= LSET::AllCuMask();
|
|
||||||
}
|
|
||||||
|
|
||||||
for( PCB_LAYER_ID layer : layers.Seq() )
|
|
||||||
{
|
|
||||||
if( IsCopperLayer( layer ) )
|
|
||||||
m_copperTree.Insert( item, layer, m_largestClearance );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if( !reportPhase( _( "Gathering copper items..." ) ) )
|
|
||||||
return false; // DRC cancelled
|
|
||||||
|
|
||||||
static const std::vector<KICAD_T> itemTypes = {
|
|
||||||
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
|
|
||||||
PCB_PAD_T,
|
|
||||||
PCB_SHAPE_T, PCB_FP_SHAPE_T,
|
|
||||||
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_TEXTBOX_T, PCB_FP_TEXTBOX_T,
|
|
||||||
PCB_DIMENSION_T
|
|
||||||
};
|
|
||||||
|
|
||||||
forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );
|
|
||||||
forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree );
|
|
||||||
|
|
||||||
reportAux( wxT( "Testing %d copper items and %d zones..." ), count, m_copperZones.size() );
|
|
||||||
|
|
||||||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) )
|
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) )
|
||||||
{
|
{
|
||||||
if( !reportPhase( _( "Checking track & via clearances..." ) ) )
|
if( !reportPhase( _( "Checking track & via clearances..." ) ) )
|
||||||
|
@ -399,7 +305,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem,
|
||||||
if( !testClearance && !testHoles )
|
if( !testClearance && !testHoles )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTrees[ aZone ].get();
|
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTreeCache[ aZone ].get();
|
||||||
EDA_RECT itemBBox = aItem->GetBoundingBox();
|
EDA_RECT itemBBox = aItem->GetBoundingBox();
|
||||||
DRC_CONSTRAINT constraint;
|
DRC_CONSTRAINT constraint;
|
||||||
DRC_CONSTRAINT_T constraintType = CLEARANCE_CONSTRAINT;
|
DRC_CONSTRAINT_T constraintType = CLEARANCE_CONSTRAINT;
|
||||||
|
@ -538,7 +444,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||||
{
|
{
|
||||||
std::shared_ptr<SHAPE> trackShape = track->GetEffectiveShape( layer );
|
std::shared_ptr<SHAPE> trackShape = track->GetEffectiveShape( layer );
|
||||||
|
|
||||||
m_copperTree.QueryColliding( track, layer, layer,
|
m_board->m_CopperItemRTreeCache->QueryColliding( track, layer, layer,
|
||||||
// Filter:
|
// Filter:
|
||||||
[&]( BOARD_ITEM* other ) -> bool
|
[&]( BOARD_ITEM* other ) -> bool
|
||||||
{
|
{
|
||||||
|
@ -575,9 +481,9 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||||
{
|
{
|
||||||
return testTrackAgainstItem( track, trackShape.get(), layer, other );
|
return testTrackAgainstItem( track, trackShape.get(), layer, other );
|
||||||
},
|
},
|
||||||
m_largestClearance );
|
m_board->m_DRCMaxClearance );
|
||||||
|
|
||||||
for( ZONE* zone : m_copperZones )
|
for( ZONE* zone : m_board->m_DRCCopperZones )
|
||||||
{
|
{
|
||||||
testItemAgainstZone( track, zone, layer );
|
testItemAgainstZone( track, zone, layer );
|
||||||
|
|
||||||
|
@ -819,7 +725,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
|
||||||
{
|
{
|
||||||
std::shared_ptr<SHAPE> padShape = pad->GetEffectiveShape( layer );
|
std::shared_ptr<SHAPE> padShape = pad->GetEffectiveShape( layer );
|
||||||
|
|
||||||
m_copperTree.QueryColliding( pad, layer, layer,
|
m_board->m_CopperItemRTreeCache->QueryColliding( pad, layer, layer,
|
||||||
// Filter:
|
// Filter:
|
||||||
[&]( BOARD_ITEM* other ) -> bool
|
[&]( BOARD_ITEM* other ) -> bool
|
||||||
{
|
{
|
||||||
|
@ -846,9 +752,9 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
|
||||||
{
|
{
|
||||||
return testPadAgainstItem( pad, padShape.get(), layer, other );
|
return testPadAgainstItem( pad, padShape.get(), layer, other );
|
||||||
},
|
},
|
||||||
m_largestClearance );
|
m_board->m_DRCMaxClearance );
|
||||||
|
|
||||||
for( ZONE* zone : m_copperZones )
|
for( ZONE* zone : m_board->m_DRCCopperZones )
|
||||||
{
|
{
|
||||||
testItemAgainstZone( pad, zone, layer );
|
testItemAgainstZone( pad, zone, layer );
|
||||||
|
|
||||||
|
@ -883,32 +789,38 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
||||||
{
|
{
|
||||||
PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( layer_id );
|
PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( layer_id );
|
||||||
std::vector<SHAPE_POLY_SET> smoothed_polys;
|
std::vector<SHAPE_POLY_SET> smoothed_polys;
|
||||||
smoothed_polys.resize( m_copperZones.size() );
|
smoothed_polys.resize( m_board->m_DRCCopperZones.size() );
|
||||||
|
|
||||||
// Skip over layers not used on the current board
|
// Skip over layers not used on the current board
|
||||||
if( !m_board->IsLayerEnabled( layer ) )
|
if( !m_board->IsLayerEnabled( layer ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for( size_t ii = 0; ii < m_copperZones.size(); ii++ )
|
for( size_t ii = 0; ii < m_board->m_DRCCopperZones.size(); ii++ )
|
||||||
{
|
{
|
||||||
if( m_copperZones[ii]->IsOnLayer( layer ) )
|
if( m_board->m_DRCCopperZones[ii]->IsOnLayer( layer ) )
|
||||||
m_copperZones[ii]->BuildSmoothedPoly( smoothed_polys[ii], layer, boardOutline );
|
{
|
||||||
|
m_board->m_DRCCopperZones[ii]->BuildSmoothedPoly( smoothed_polys[ii], layer,
|
||||||
|
boardOutline );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through all areas
|
// iterate through all areas
|
||||||
for( size_t ia = 0; ia < m_copperZones.size(); ia++ )
|
for( size_t ia = 0; ia < m_board->m_DRCCopperZones.size(); ia++ )
|
||||||
{
|
{
|
||||||
if( !reportProgress( layer_id * m_copperZones.size() + ia, B_Cu * m_copperZones.size(), delta ) )
|
if( !reportProgress( layer_id * m_board->m_DRCCopperZones.size() + ia,
|
||||||
|
B_Cu * m_board->m_DRCCopperZones.size(), delta ) )
|
||||||
|
{
|
||||||
return; // DRC cancelled
|
return; // DRC cancelled
|
||||||
|
}
|
||||||
|
|
||||||
ZONE* zoneA = m_copperZones[ia];
|
ZONE* zoneA = m_board->m_DRCCopperZones[ia];
|
||||||
|
|
||||||
if( !zoneA->IsOnLayer( layer ) )
|
if( !zoneA->IsOnLayer( layer ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for( size_t ia2 = ia + 1; ia2 < m_copperZones.size(); ia2++ )
|
for( size_t ia2 = ia + 1; ia2 < m_board->m_DRCCopperZones.size(); ia2++ )
|
||||||
{
|
{
|
||||||
ZONE* zoneB = m_copperZones[ia2];
|
ZONE* zoneB = m_board->m_DRCCopperZones[ia2];
|
||||||
|
|
||||||
// test for same layer
|
// test for same layer
|
||||||
if( !zoneB->IsOnLayer( layer ) )
|
if( !zoneB->IsOnLayer( layer ) )
|
||||||
|
|
|
@ -43,7 +43,9 @@
|
||||||
class DRC_TEST_PROVIDER_COURTYARD_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
class DRC_TEST_PROVIDER_COURTYARD_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DRC_TEST_PROVIDER_COURTYARD_CLEARANCE ()
|
DRC_TEST_PROVIDER_COURTYARD_CLEARANCE () :
|
||||||
|
DRC_TEST_PROVIDER_CLEARANCE_BASE(),
|
||||||
|
m_largestCourtyardClearance( 0 )
|
||||||
{
|
{
|
||||||
m_isRuleDriven = false;
|
m_isRuleDriven = false;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +70,9 @@ private:
|
||||||
bool testFootprintCourtyardDefinitions();
|
bool testFootprintCourtyardDefinitions();
|
||||||
|
|
||||||
bool testCourtyardClearances();
|
bool testCourtyardClearances();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_largestCourtyardClearance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,8 +182,8 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
|
||||||
BOX2I frontBBox = frontA.BBoxFromCaches();
|
BOX2I frontBBox = frontA.BBoxFromCaches();
|
||||||
BOX2I backBBox = backA.BBoxFromCaches();
|
BOX2I backBBox = backA.BBoxFromCaches();
|
||||||
|
|
||||||
frontBBox.Inflate( m_largestClearance );
|
frontBBox.Inflate( m_largestCourtyardClearance );
|
||||||
backBBox.Inflate( m_largestClearance );
|
backBBox.Inflate( m_largestCourtyardClearance );
|
||||||
|
|
||||||
EDA_RECT fpABBox = fpA->GetBoundingBox();
|
EDA_RECT fpABBox = fpA->GetBoundingBox();
|
||||||
|
|
||||||
|
@ -315,9 +320,9 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::Run()
|
||||||
DRC_CONSTRAINT constraint;
|
DRC_CONSTRAINT constraint;
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( COURTYARD_CLEARANCE_CONSTRAINT, constraint ) )
|
if( m_drcEngine->QueryWorstConstraint( COURTYARD_CLEARANCE_CONSTRAINT, constraint ) )
|
||||||
m_largestClearance = constraint.GetValue().Min();
|
m_largestCourtyardClearance = constraint.GetValue().Min();
|
||||||
|
|
||||||
reportAux( wxT( "Worst courtyard clearance : %d nm" ), m_largestClearance );
|
reportAux( wxT( "Worst courtyard clearance : %d nm" ), m_largestCourtyardClearance );
|
||||||
|
|
||||||
if( !testFootprintCourtyardDefinitions() )
|
if( !testFootprintCourtyardDefinitions() )
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -169,6 +169,7 @@ struct DIFF_PAIR_COUPLED_SEGMENTS
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DIFF_PAIR_ITEMS
|
struct DIFF_PAIR_ITEMS
|
||||||
{
|
{
|
||||||
std::set<BOARD_CONNECTED_ITEM*> itemsP, itemsN;
|
std::set<BOARD_CONNECTED_ITEM*> itemsP, itemsN;
|
||||||
|
@ -178,7 +179,8 @@ struct DIFF_PAIR_ITEMS
|
||||||
int totalLengthP;
|
int totalLengthP;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void extractDiffPairCoupledItems( DIFF_PAIR_ITEMS& aDp, DRC_RTREE& aTree )
|
|
||||||
|
static void extractDiffPairCoupledItems( DIFF_PAIR_ITEMS& aDp )
|
||||||
{
|
{
|
||||||
for( BOARD_CONNECTED_ITEM* itemP : aDp.itemsP )
|
for( BOARD_CONNECTED_ITEM* itemP : aDp.itemsP )
|
||||||
{
|
{
|
||||||
|
@ -250,12 +252,13 @@ static void extractDiffPairCoupledItems( DIFF_PAIR_ITEMS& aDp, DRC_RTREE& aTree
|
||||||
|
|
||||||
SHAPE_SEGMENT checkSegStart( bestCoupled->coupledP.A, bestCoupled->coupledN.A );
|
SHAPE_SEGMENT checkSegStart( bestCoupled->coupledP.A, bestCoupled->coupledN.A );
|
||||||
SHAPE_SEGMENT checkSegEnd( bestCoupled->coupledP.B, bestCoupled->coupledN.B );
|
SHAPE_SEGMENT checkSegEnd( bestCoupled->coupledP.B, bestCoupled->coupledN.B );
|
||||||
|
DRC_RTREE* tree = bestCoupled->parentP->GetBoard()->m_CopperItemRTreeCache.get();
|
||||||
|
|
||||||
// check if there's anything in between the segments suspected to be coupled. If
|
// check if there's anything in between the segments suspected to be coupled. If
|
||||||
// there's nothing, assume they are really coupled.
|
// there's nothing, assume they are really coupled.
|
||||||
|
|
||||||
if( !aTree.CheckColliding( &checkSegStart, sp->GetLayer(), 0, excludeSelf )
|
if( !tree->CheckColliding( &checkSegStart, sp->GetLayer(), 0, excludeSelf )
|
||||||
&& !aTree.CheckColliding( &checkSegEnd, sp->GetLayer(), 0, excludeSelf ) )
|
&& !tree->CheckColliding( &checkSegEnd, sp->GetLayer(), 0, excludeSelf ) )
|
||||||
{
|
{
|
||||||
aDp.coupled.push_back( *bestCoupled );
|
aDp.coupled.push_back( *bestCoupled );
|
||||||
}
|
}
|
||||||
|
@ -319,25 +322,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
|
||||||
drc_dbg( 10, wxT( "dp rule matches %d\n" ), (int) dpRuleMatches.size() );
|
drc_dbg( 10, wxT( "dp rule matches %d\n" ), (int) dpRuleMatches.size() );
|
||||||
|
|
||||||
|
|
||||||
DRC_RTREE copperTree;
|
reportAux( wxT( "DPs evaluated:" ) );
|
||||||
|
|
||||||
auto addToTree =
|
|
||||||
[&copperTree]( BOARD_ITEM *item ) -> bool
|
|
||||||
{
|
|
||||||
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
|
|
||||||
{
|
|
||||||
if( IsCopperLayer( layer ) )
|
|
||||||
copperTree.Insert( item, layer );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T },
|
|
||||||
LSET::AllCuMask(), addToTree );
|
|
||||||
|
|
||||||
|
|
||||||
reportAux( wxString::Format( _("DPs evaluated:") ) );
|
|
||||||
|
|
||||||
for( auto& it : dpRuleMatches )
|
for( auto& it : dpRuleMatches )
|
||||||
{
|
{
|
||||||
|
@ -355,7 +340,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
|
||||||
nameP,
|
nameP,
|
||||||
nameN ) );
|
nameN ) );
|
||||||
|
|
||||||
extractDiffPairCoupledItems( it.second, copperTree );
|
extractDiffPairCoupledItems( it.second );
|
||||||
|
|
||||||
it.second.totalCoupled = 0;
|
it.second.totalCoupled = 0;
|
||||||
it.second.totalLengthN = 0;
|
it.second.totalLengthN = 0;
|
||||||
|
|
|
@ -133,7 +133,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
|
||||||
SHAPE_POLY_SET areaPoly = ruleArea->Outline()->CloneDropTriangulation();
|
SHAPE_POLY_SET areaPoly = ruleArea->Outline()->CloneDropTriangulation();
|
||||||
areaPoly.Deflate( epsilon, 0, SHAPE_POLY_SET::ALLOW_ACUTE_CORNERS );
|
areaPoly.Deflate( epsilon, 0, SHAPE_POLY_SET::ALLOW_ACUTE_CORNERS );
|
||||||
|
|
||||||
DRC_RTREE* zoneRTree = board->m_CopperZoneRTrees[ copperZone ].get();
|
DRC_RTREE* zoneRTree = board->m_CopperZoneRTreeCache[ copperZone ].get();
|
||||||
|
|
||||||
if( zoneRTree )
|
if( zoneRTree )
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,7 +50,8 @@ class DRC_TEST_PROVIDER_EDGE_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DRC_TEST_PROVIDER_EDGE_CLEARANCE () :
|
DRC_TEST_PROVIDER_EDGE_CLEARANCE () :
|
||||||
DRC_TEST_PROVIDER_CLEARANCE_BASE()
|
DRC_TEST_PROVIDER_CLEARANCE_BASE(),
|
||||||
|
m_largestEdgeClearance( 0 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PAD*> m_castellatedPads;
|
std::vector<PAD*> m_castellatedPads;
|
||||||
|
int m_largestEdgeClearance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,9 +162,9 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||||
DRC_CONSTRAINT worstClearanceConstraint;
|
DRC_CONSTRAINT worstClearanceConstraint;
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, worstClearanceConstraint ) )
|
if( m_drcEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, worstClearanceConstraint ) )
|
||||||
m_largestClearance = worstClearanceConstraint.GetValue().Min();
|
m_largestEdgeClearance = worstClearanceConstraint.GetValue().Min();
|
||||||
|
|
||||||
reportAux( wxT( "Worst clearance : %d nm" ), m_largestClearance );
|
reportAux( wxT( "Worst clearance : %d nm" ), m_largestEdgeClearance );
|
||||||
|
|
||||||
std::vector<std::unique_ptr<PCB_SHAPE>> edges;
|
std::vector<std::unique_ptr<PCB_SHAPE>> edges;
|
||||||
DRC_RTREE edgesTree;
|
DRC_RTREE edgesTree;
|
||||||
|
@ -222,7 +224,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||||
for( PCB_LAYER_ID layer : { Edge_Cuts, Margin } )
|
for( PCB_LAYER_ID layer : { Edge_Cuts, Margin } )
|
||||||
{
|
{
|
||||||
if( edge->IsOnLayer( layer ) )
|
if( edge->IsOnLayer( layer ) )
|
||||||
edgesTree.Insert( edge.get(), layer, m_largestClearance );
|
edgesTree.Insert( edge.get(), layer, m_largestEdgeClearance );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +233,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||||
for( PAD* pad : footprint->Pads() )
|
for( PAD* pad : footprint->Pads() )
|
||||||
{
|
{
|
||||||
if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||||
edgesTree.Insert( pad, Edge_Cuts, m_largestClearance );
|
edgesTree.Insert( pad, Edge_Cuts, m_largestEdgeClearance );
|
||||||
|
|
||||||
if( pad->GetProperty() == PAD_PROP::CASTELLATED )
|
if( pad->GetProperty() == PAD_PROP::CASTELLATED )
|
||||||
m_castellatedPads.push_back( pad );
|
m_castellatedPads.push_back( pad );
|
||||||
|
@ -278,25 +280,25 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||||
if( testCopper && item->IsOnCopperLayer() )
|
if( testCopper && item->IsOnCopperLayer() )
|
||||||
{
|
{
|
||||||
edgesTree.QueryColliding( item, UNDEFINED_LAYER, testLayer, nullptr,
|
edgesTree.QueryColliding( item, UNDEFINED_LAYER, testLayer, nullptr,
|
||||||
[&]( BOARD_ITEM* edge ) -> bool
|
[&]( BOARD_ITEM* edge ) -> bool
|
||||||
{
|
{
|
||||||
return testAgainstEdge( item, itemShape.get(), edge,
|
return testAgainstEdge( item, itemShape.get(), edge,
|
||||||
EDGE_CLEARANCE_CONSTRAINT,
|
EDGE_CLEARANCE_CONSTRAINT,
|
||||||
DRCE_EDGE_CLEARANCE );
|
DRCE_EDGE_CLEARANCE );
|
||||||
},
|
},
|
||||||
m_largestClearance );
|
m_largestEdgeClearance );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( testSilk && ( item->IsOnLayer( F_SilkS ) || item->IsOnLayer( B_SilkS ) ) )
|
if( testSilk && ( item->IsOnLayer( F_SilkS ) || item->IsOnLayer( B_SilkS ) ) )
|
||||||
{
|
{
|
||||||
if( edgesTree.QueryColliding( item, UNDEFINED_LAYER, testLayer, nullptr,
|
if( edgesTree.QueryColliding( item, UNDEFINED_LAYER, testLayer, nullptr,
|
||||||
[&]( BOARD_ITEM* edge ) -> bool
|
[&]( BOARD_ITEM* edge ) -> bool
|
||||||
{
|
{
|
||||||
return testAgainstEdge( item, itemShape.get(), edge,
|
return testAgainstEdge( item, itemShape.get(), edge,
|
||||||
SILK_CLEARANCE_CONSTRAINT,
|
SILK_CLEARANCE_CONSTRAINT,
|
||||||
DRCE_SILK_EDGE_CLEARANCE );
|
DRCE_SILK_EDGE_CLEARANCE );
|
||||||
},
|
},
|
||||||
m_largestClearance ) )
|
m_largestEdgeClearance ) )
|
||||||
{
|
{
|
||||||
// violations reported during QueryColliding
|
// violations reported during QueryColliding
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,9 @@ class DRC_TEST_PROVIDER_HOLE_TO_HOLE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DRC_TEST_PROVIDER_HOLE_TO_HOLE () :
|
DRC_TEST_PROVIDER_HOLE_TO_HOLE () :
|
||||||
DRC_TEST_PROVIDER_CLEARANCE_BASE(),
|
DRC_TEST_PROVIDER_CLEARANCE_BASE(),
|
||||||
m_board( nullptr )
|
m_board( nullptr ),
|
||||||
|
m_largestHoleToHoleClearance( 0 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ private:
|
||||||
|
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
DRC_RTREE m_holeTree;
|
DRC_RTREE m_holeTree;
|
||||||
|
int m_largestHoleToHoleClearance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,8 +108,8 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, worstClearanceConstraint ) )
|
if( m_drcEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, worstClearanceConstraint ) )
|
||||||
{
|
{
|
||||||
m_largestClearance = worstClearanceConstraint.GetValue().Min();
|
m_largestHoleToHoleClearance = worstClearanceConstraint.GetValue().Min();
|
||||||
reportAux( wxT( "Worst hole to hole : %d nm" ), m_largestClearance );
|
reportAux( wxT( "Worst hole to hole : %d nm" ), m_largestHoleToHoleClearance );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -146,7 +148,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
||||||
|
|
||||||
// We only care about drilled (ie: round) holes
|
// We only care about drilled (ie: round) holes
|
||||||
if( pad->GetDrillSize().x && pad->GetDrillSize().x == pad->GetDrillSize().y )
|
if( pad->GetDrillSize().x && pad->GetDrillSize().x == pad->GetDrillSize().y )
|
||||||
m_holeTree.Insert( item, F_Cu, m_largestClearance );
|
m_holeTree.Insert( item, F_Cu, m_largestHoleToHoleClearance );
|
||||||
}
|
}
|
||||||
else if( item->Type() == PCB_VIA_T )
|
else if( item->Type() == PCB_VIA_T )
|
||||||
{
|
{
|
||||||
|
@ -154,7 +156,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
||||||
|
|
||||||
// We only care about mechanically drilled (ie: non-laser) holes
|
// We only care about mechanically drilled (ie: non-laser) holes
|
||||||
if( via->GetViaType() == VIATYPE::THROUGH )
|
if( via->GetViaType() == VIATYPE::THROUGH )
|
||||||
m_holeTree.Insert( item, F_Cu, m_largestClearance );
|
m_holeTree.Insert( item, F_Cu, m_largestHoleToHoleClearance );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -204,7 +206,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
||||||
{
|
{
|
||||||
return testHoleAgainstHole( via, holeShape.get(), other );
|
return testHoleAgainstHole( via, holeShape.get(), other );
|
||||||
},
|
},
|
||||||
m_largestClearance );
|
m_largestHoleToHoleClearance );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +251,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
||||||
{
|
{
|
||||||
return testHoleAgainstHole( pad, holeShape.get(), other );
|
return testHoleAgainstHole( pad, holeShape.get(), other );
|
||||||
},
|
},
|
||||||
m_largestClearance );
|
m_largestHoleToHoleClearance );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DRC_RTREE m_itemTree;
|
DRC_RTREE m_itemTree;
|
||||||
std::vector<ZONE*> m_zones;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,56 +90,23 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
|
||||||
{
|
{
|
||||||
m_board = m_drcEngine->GetBoard();
|
m_board = m_drcEngine->GetBoard();
|
||||||
m_itemTree.clear();
|
m_itemTree.clear();
|
||||||
m_zones.clear();
|
|
||||||
m_zones.reserve( m_board->Zones().size() );
|
|
||||||
|
|
||||||
int errorMax = m_board->GetDesignSettings().m_MaxError;
|
int errorMax = m_board->GetDesignSettings().m_MaxError;
|
||||||
DRC_CONSTRAINT worstConstraint;
|
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
if( m_board->m_DRCMaxPhysicalClearance <= 0 )
|
||||||
m_largestClearance = worstConstraint.GetValue().Min();
|
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
|
||||||
m_largestClearance = std::max( m_largestClearance, worstConstraint.GetValue().Min() );
|
|
||||||
|
|
||||||
if( m_largestClearance <= 0 )
|
|
||||||
{
|
{
|
||||||
reportAux( wxT( "No Clearance constraints found. Tests not run." ) );
|
reportAux( wxT( "No physical clearance constraints found. Tests not run." ) );
|
||||||
return true; // continue with other tests
|
return true; // continue with other tests
|
||||||
}
|
}
|
||||||
|
|
||||||
for( ZONE* zone : m_board->Zones() )
|
reportAux( wxT( "Largest physical clearance : %d nm" ), m_board->m_DRCMaxPhysicalClearance );
|
||||||
{
|
|
||||||
if( !zone->GetIsRuleArea() )
|
|
||||||
{
|
|
||||||
m_zones.push_back( zone );
|
|
||||||
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
|
||||||
{
|
|
||||||
for( PAD* pad : footprint->Pads() )
|
|
||||||
m_largestClearance = std::max( m_largestClearance, pad->GetLocalClearance() );
|
|
||||||
|
|
||||||
for( ZONE* zone : footprint->Zones() )
|
|
||||||
{
|
|
||||||
if( !zone->GetIsRuleArea() )
|
|
||||||
{
|
|
||||||
m_zones.push_back( zone );
|
|
||||||
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reportAux( wxT( "Worst clearance : %d nm" ), m_largestClearance );
|
|
||||||
|
|
||||||
// This is the number of tests between 2 calls to the progress bar
|
// This is the number of tests between 2 calls to the progress bar
|
||||||
size_t delta = 100;
|
size_t delta = 100;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t ii = 0;
|
size_t ii = 0;
|
||||||
|
|
||||||
if( !reportPhase( _( "Gathering items..." ) ) )
|
if( !reportPhase( _( "Gathering physical items..." ) ) )
|
||||||
return false; // DRC cancelled
|
return false; // DRC cancelled
|
||||||
|
|
||||||
static const std::vector<KICAD_T> itemTypes = {
|
static const std::vector<KICAD_T> itemTypes = {
|
||||||
|
@ -194,7 +160,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
for( PCB_LAYER_ID layer : layers.Seq() )
|
for( PCB_LAYER_ID layer : layers.Seq() )
|
||||||
m_itemTree.Insert( item, layer, m_largestClearance );
|
m_itemTree.Insert( item, layer, m_board->m_DRCMaxPhysicalClearance );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} );
|
} );
|
||||||
|
@ -251,7 +217,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
|
||||||
return testItemAgainstItem( item, itemShape.get(), layer,
|
return testItemAgainstItem( item, itemShape.get(), layer,
|
||||||
other );
|
other );
|
||||||
},
|
},
|
||||||
m_largestClearance );
|
m_board->m_DRCMaxPhysicalClearance );
|
||||||
|
|
||||||
testItemAgainstZones( item, layer );
|
testItemAgainstZones( item, layer );
|
||||||
}
|
}
|
||||||
|
@ -391,6 +357,9 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testShapeLineChain( const SHAPE_LINE_
|
||||||
int count = aOutline.SegmentCount();
|
int count = aOutline.SegmentCount();
|
||||||
int clearance = aConstraint.GetValue().Min();
|
int clearance = aConstraint.GetValue().Min();
|
||||||
|
|
||||||
|
if( aConstraint.GetSeverity() == RPT_SEVERITY_IGNORE || clearance - epsilon <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
// Trigonometry is not cheap; cache seg angles
|
// Trigonometry is not cheap; cache seg angles
|
||||||
std::vector<double> angles;
|
std::vector<double> angles;
|
||||||
angles.reserve( count );
|
angles.reserve( count );
|
||||||
|
@ -508,17 +477,21 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testShapeLineChain( const SHAPE_LINE_
|
||||||
{
|
{
|
||||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
VECTOR2I pt = collision.first;
|
||||||
|
|
||||||
msg.Printf( _( "(%s clearance %s; actual %s)" ),
|
if( aParentItem->GetParentFootprint() )
|
||||||
|
pt += aParentItem->GetParentFootprint()->GetPosition();
|
||||||
|
|
||||||
|
msg.Printf( _( "Internal clearance violation (%s clearance %s; actual %s)" ),
|
||||||
aConstraint.GetName(),
|
aConstraint.GetName(),
|
||||||
MessageTextFromValue( userUnits(), clearance ),
|
MessageTextFromValue( userUnits(), clearance ),
|
||||||
MessageTextFromValue( userUnits(), collision.second ) );
|
MessageTextFromValue( userUnits(), collision.second ) );
|
||||||
|
|
||||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
drce->SetErrorMessage( msg );
|
||||||
drce->SetItems( aParentItem );
|
drce->SetItems( aParentItem );
|
||||||
drce->SetViolatingRule( aConstraint.GetParentRule() );
|
drce->SetViolatingRule( aConstraint.GetParentRule() );
|
||||||
|
|
||||||
reportViolation( drce, collision.first, aLayer );
|
reportViolation( drce, pt, aLayer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,13 +499,14 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testShapeLineChain( const SHAPE_LINE_
|
||||||
void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAYER_ID aLayer,
|
void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAYER_ID aLayer,
|
||||||
DRC_CONSTRAINT& aConstraint )
|
DRC_CONSTRAINT& aConstraint )
|
||||||
{
|
{
|
||||||
int epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
int epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
||||||
int clearance = aConstraint.GetValue().Min();
|
int clearance = aConstraint.GetValue().Min();
|
||||||
SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
|
|
||||||
|
|
||||||
if( aConstraint.GetSeverity() == RPT_SEVERITY_IGNORE || clearance - epsilon <= 0 )
|
if( aConstraint.GetSeverity() == RPT_SEVERITY_IGNORE || clearance - epsilon <= 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
|
||||||
|
|
||||||
// Turn fractured fill into outlines and holes
|
// Turn fractured fill into outlines and holes
|
||||||
fill.Simplify( SHAPE_POLY_SET::PM_FAST );
|
fill.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||||
|
|
||||||
|
@ -717,7 +691,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstItem( BOARD_ITEM* item
|
||||||
void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aItem,
|
void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aItem,
|
||||||
PCB_LAYER_ID aLayer )
|
PCB_LAYER_ID aLayer )
|
||||||
{
|
{
|
||||||
for( ZONE* zone : m_zones )
|
for( ZONE* zone : m_board->m_DRCZones )
|
||||||
{
|
{
|
||||||
if( !zone->GetLayerSet().test( aLayer ) )
|
if( !zone->GetLayerSet().test( aLayer ) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -730,7 +704,7 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aIt
|
||||||
if( !testClearance && !testHoles )
|
if( !testClearance && !testHoles )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTrees[ zone ].get();
|
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTreeCache[ zone ].get();
|
||||||
EDA_RECT itemBBox = aItem->GetBoundingBox();
|
EDA_RECT itemBBox = aItem->GetBoundingBox();
|
||||||
DRC_CONSTRAINT constraint;
|
DRC_CONSTRAINT constraint;
|
||||||
bool colliding;
|
bool colliding;
|
||||||
|
|
|
@ -512,7 +512,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskItemAgainstZones( BOARD_ITEM* aItem,
|
||||||
|
|
||||||
if( aItem->GetBoundingBox().Intersects( zone->GetCachedBoundingBox() ) )
|
if( aItem->GetBoundingBox().Intersects( zone->GetCachedBoundingBox() ) )
|
||||||
{
|
{
|
||||||
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTrees[ zone ].get();
|
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTreeCache[ zone ].get();
|
||||||
int clearance = m_board->GetDesignSettings().m_SolderMaskToCopperClearance;
|
int clearance = m_board->GetDesignSettings().m_SolderMaskToCopperClearance;
|
||||||
int actual;
|
int actual;
|
||||||
VECTOR2I pos;
|
VECTOR2I pos;
|
||||||
|
@ -659,7 +659,7 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::Run()
|
||||||
m_largestClearance = std::max( m_largestClearance, pad->GetSolderMaskExpansion() );
|
m_largestClearance = std::max( m_largestClearance, pad->GetSolderMaskExpansion() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order is important here: m_webWidth must be added in before m_largestClearance is maxed
|
// Order is important here: m_webWidth must be added in before m_largestCourtyardClearance is maxed
|
||||||
// with the various SILK_CLEARANCE_CONSTRAINTS.
|
// with the various SILK_CLEARANCE_CONSTRAINTS.
|
||||||
m_largestClearance += m_largestClearance + m_webWidth;
|
m_largestClearance += m_largestClearance + m_webWidth;
|
||||||
|
|
||||||
|
|
|
@ -547,7 +547,7 @@ bool calcIsInsideArea( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox, PCB_EXPR_CO
|
||||||
if( !zone->IsFilled() )
|
if( !zone->IsFilled() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
DRC_RTREE* zoneRTree = board->m_CopperZoneRTrees[ zone ].get();
|
DRC_RTREE* zoneRTree = board->m_CopperZoneRTreeCache[ zone ].get();
|
||||||
|
|
||||||
if( zoneRTree )
|
if( zoneRTree )
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,8 +74,18 @@ HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints)
|
||||||
// Do not wrap internal-only structures
|
// Do not wrap internal-only structures
|
||||||
%ignore BOARD::m_CachesMutex;
|
%ignore BOARD::m_CachesMutex;
|
||||||
%ignore BOARD::m_InsideCourtyardCache;
|
%ignore BOARD::m_InsideCourtyardCache;
|
||||||
|
%ignore BOARD::m_InsideFCourtyardCache;
|
||||||
|
%ignore BOARD::m_InsideBCourtyardCache;
|
||||||
%ignore BOARD::m_InsideAreaCache;
|
%ignore BOARD::m_InsideAreaCache;
|
||||||
%ignore BOARD::m_CopperZoneRTrees;
|
%ignore BOARD::m_LayerExpressionCache;
|
||||||
|
%ignore BOARD::m_CopperZoneRTreeCache;
|
||||||
|
%ignore BOARD::m_CopperItemRTreeCache;
|
||||||
|
%ignore BOARD::m_DRCZones;
|
||||||
|
%ignore BOARD::m_DRCCopperZones;
|
||||||
|
%ignore BOARD::m_DRCMaxClearance;
|
||||||
|
%ignore BOARD::m_DRCMaxPhysicalClearance;
|
||||||
|
%ignore BOARD::m_SolderMask;
|
||||||
|
|
||||||
|
|
||||||
%include board.h
|
%include board.h
|
||||||
%{
|
%{
|
||||||
|
|
|
@ -77,7 +77,9 @@ using namespace std::placeholders;
|
||||||
class DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
class DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE()
|
DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE() :
|
||||||
|
DRC_TEST_PROVIDER_CLEARANCE_BASE(),
|
||||||
|
m_largestCourtyardClearance( 0 )
|
||||||
{
|
{
|
||||||
m_isRuleDriven = false;
|
m_isRuleDriven = false;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +110,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void testCourtyardClearances();
|
void testCourtyardClearances();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_largestCourtyardClearance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,8 +134,8 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances()
|
||||||
BOX2I frontBBox = frontA.BBoxFromCaches();
|
BOX2I frontBBox = frontA.BBoxFromCaches();
|
||||||
BOX2I backBBox = backA.BBoxFromCaches();
|
BOX2I backBBox = backA.BBoxFromCaches();
|
||||||
|
|
||||||
frontBBox.Inflate( m_largestClearance );
|
frontBBox.Inflate( m_largestCourtyardClearance );
|
||||||
backBBox.Inflate( m_largestClearance );
|
backBBox.Inflate( m_largestCourtyardClearance );
|
||||||
|
|
||||||
EDA_RECT fpABBox = fpA->GetBoundingBox();
|
EDA_RECT fpABBox = fpA->GetBoundingBox();
|
||||||
|
|
||||||
|
@ -256,15 +261,12 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::Init( BOARD* aBoard )
|
||||||
bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::Run()
|
bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::Run()
|
||||||
{
|
{
|
||||||
m_FpInConflict.clear();
|
m_FpInConflict.clear();
|
||||||
m_largestClearance = 0;
|
m_largestCourtyardClearance = 0;
|
||||||
|
|
||||||
// Currently, do not use DRC engine for calculation time reasons
|
|
||||||
#if 0
|
|
||||||
DRC_CONSTRAINT constraint;
|
DRC_CONSTRAINT constraint;
|
||||||
|
|
||||||
if( m_drcEngine->QueryWorstConstraint( COURTYARD_CLEARANCE_CONSTRAINT, constraint ) )
|
if( m_drcEngine->QueryWorstConstraint( COURTYARD_CLEARANCE_CONSTRAINT, constraint ) )
|
||||||
m_largestClearance = constraint.GetValue().Min();
|
m_largestCourtyardClearance = constraint.GetValue().Min();
|
||||||
#endif
|
|
||||||
|
|
||||||
testCourtyardClearances();
|
testCourtyardClearances();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue