Add hole-to-hole-minimum checking to via placement.

Courtesy of Frank Severinsen.

Fixes: lp:1833214
* https://bugs.launchpad.net/kicad/+bug/1833214
This commit is contained in:
Jeff Young 2019-07-21 21:19:55 -06:00
parent 2ca379b281
commit 1808d8bd40
2 changed files with 42 additions and 27 deletions

View File

@ -23,11 +23,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/**
* @file board_connected_item.h
* @brief Class BOARD_CONNECTED_ITEM.
*/
#ifndef BOARD_CONNECTED_ITEM_H #ifndef BOARD_CONNECTED_ITEM_H
#define BOARD_CONNECTED_ITEM_H #define BOARD_CONNECTED_ITEM_H

View File

@ -1557,8 +1557,10 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
TRACK* findTrack( VIA* aVia ) TRACK* findTrack( VIA* aVia )
{ {
const LSET lset = aVia->GetLayerSet(); const LSET lset = aVia->GetLayerSet();
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items; wxPoint position = aVia->GetPosition();
BOX2I bbox = aVia->GetBoundingBox(); BOX2I bbox = aVia->GetBoundingBox();
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
auto view = m_frame->GetCanvas()->GetView(); auto view = m_frame->GetCanvas()->GetView();
std::vector<TRACK*> possible_tracks; std::vector<TRACK*> possible_tracks;
@ -1573,7 +1575,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
if( auto track = dyn_cast<TRACK*>( item ) ) if( auto track = dyn_cast<TRACK*>( item ) )
{ {
if( TestSegmentHit( aVia->GetPosition(), track->GetStart(), track->GetEnd(), if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
( track->GetWidth() + aVia->GetWidth() ) / 2 ) ) ( track->GetWidth() + aVia->GetWidth() ) / 2 ) )
possible_tracks.push_back( track ); possible_tracks.push_back( track );
} }
@ -1584,8 +1586,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
for( auto track : possible_tracks ) for( auto track : possible_tracks )
{ {
SEG test( track->GetStart(), track->GetEnd() ); SEG test( track->GetStart(), track->GetEnd() );
auto dist = ( test.NearestPoint( aVia->GetPosition() ) - auto dist = ( test.NearestPoint( position ) - position ).EuclideanNorm();
VECTOR2I( aVia->GetPosition() ) ).EuclideanNorm();
if( dist < min_d ) if( dist < min_d )
{ {
@ -1601,11 +1602,15 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
bool hasDRCViolation( VIA* aVia ) bool hasDRCViolation( VIA* aVia )
{ {
const LSET lset = aVia->GetLayerSet(); const LSET lset = aVia->GetLayerSet();
wxPoint position = aVia->GetPosition();
int drillRadius = aVia->GetDrillValue() / 2;
BOX2I bbox = aVia->GetBoundingBox();
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items; std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
int net = 0; int net = 0;
int clearance = 0; int clearance = 0;
BOX2I bbox = aVia->GetBoundingBox();
auto view = m_frame->GetCanvas()->GetView(); auto view = m_frame->GetCanvas()->GetView();
int holeToHoleMin = m_frame->GetBoard()->GetDesignSettings().m_HoleToHoleMin;
view->Query( bbox, items ); view->Query( bbox, items );
@ -1620,7 +1625,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
{ {
int max_clearance = std::max( clearance, track->GetClearance() ); int max_clearance = std::max( clearance, track->GetClearance() );
if( TestSegmentHit( aVia->GetPosition(), track->GetStart(), track->GetEnd(), if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) ) ( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) )
{ {
if( net && track->GetNetCode() != net ) if( net && track->GetNetCode() != net )
@ -1631,9 +1636,17 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
} }
} }
if( auto via = dyn_cast<VIA*>( item ) )
{
int dist = KiROUND( GetLineLength( position, via->GetPosition() ) );
if( dist < drillRadius + via->GetDrillValue() / 2 + holeToHoleMin )
return true;
}
if( auto mod = dyn_cast<MODULE*>( item ) ) if( auto mod = dyn_cast<MODULE*>( item ) )
{ {
for( auto pad : mod->Pads() ) for( D_PAD* pad : mod->Pads() )
{ {
int max_clearance = std::max( clearance, pad->GetClearance() ); int max_clearance = std::max( clearance, pad->GetClearance() );
@ -1645,6 +1658,14 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
net = pad->GetNetCode(); net = pad->GetNetCode();
clearance = pad->GetClearance(); clearance = pad->GetClearance();
} }
if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
{
int dist = KiROUND( GetLineLength( position, pad->GetPosition() ) );
if( dist < drillRadius + pad->GetDrillSize().x / 2 + holeToHoleMin )
return true;
}
} }
} }
} }
@ -1655,42 +1676,41 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
int findStitchedZoneNet( VIA* aVia ) int findStitchedZoneNet( VIA* aVia )
{ {
const auto pos = aVia->GetPosition(); const wxPoint position = aVia->GetPosition();
const auto lset = aVia->GetLayerSet(); const LSET lset = aVia->GetLayerSet();
for( auto mod : m_board->Modules() ) for( auto mod : m_board->Modules() )
{ {
for( D_PAD* pad : mod->Pads() ) for( D_PAD* pad : mod->Pads() )
{ {
if( pad->HitTest( pos ) && ( pad->GetLayerSet() & lset ).any() ) if( pad->HitTest( position ) && ( pad->GetLayerSet() & lset ).any() )
return -1; return -1;
} }
} }
std::vector<ZONE_CONTAINER*> foundZones; std::vector<ZONE_CONTAINER*> foundZones;
for( auto zone : m_board->Zones() ) for( ZONE_CONTAINER* zone : m_board->Zones() )
{ {
if( zone->HitTestFilledArea( pos ) ) if( zone->HitTestFilledArea( position ) )
{
foundZones.push_back( zone ); foundZones.push_back( zone );
}
} }
std::sort( foundZones.begin(), foundZones.end(), std::sort( foundZones.begin(), foundZones.end(),
[] ( const ZONE_CONTAINER* a, const ZONE_CONTAINER* b ) { [] ( const ZONE_CONTAINER* a, const ZONE_CONTAINER* b )
return a->GetLayer() < b->GetLayer(); {
} ); return a->GetLayer() < b->GetLayer();
} );
// first take the net of the active layer // first take the net of the active layer
for( auto z : foundZones ) for( ZONE_CONTAINER* z : foundZones )
{ {
if( m_frame->GetActiveLayer() == z->GetLayer() ) if( m_frame->GetActiveLayer() == z->GetLayer() )
return z->GetNetCode(); return z->GetNetCode();
} }
// none? take the topmost visible layer // none? take the topmost visible layer
for( auto z : foundZones ) for( ZONE_CONTAINER* z : foundZones )
{ {
if( m_board->IsLayerVisible( z->GetLayer() ) ) if( m_board->IsLayerVisible( z->GetLayer() ) )
return z->GetNetCode(); return z->GetNetCode();
@ -1709,13 +1729,13 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
m_gridHelper.SetSnap( !( m_modifiers & MD_SHIFT ) ); m_gridHelper.SetSnap( !( m_modifiers & MD_SHIFT ) );
auto via = static_cast<VIA*>( aItem ); auto via = static_cast<VIA*>( aItem );
wxPoint pos = via->GetPosition(); wxPoint position = via->GetPosition();
TRACK* track = findTrack( via ); TRACK* track = findTrack( via );
if( track ) if( track )
{ {
SEG trackSeg( track->GetStart(), track->GetEnd() ); SEG trackSeg( track->GetStart(), track->GetEnd() );
VECTOR2I snap = m_gridHelper.AlignToSegment( pos, trackSeg ); VECTOR2I snap = m_gridHelper.AlignToSegment( position, trackSeg );
aItem->SetPosition( (wxPoint) snap ); aItem->SetPosition( (wxPoint) snap );
} }