Ensure dangling test takes track width into account

When running a hit test to check if the anchors are connected, we should
loosen the check for tracks to account for the width.  Otherwise
connected anchors can be connected in the system but test positive for
IsDangling()

Fixes https://gitlab.com/kicad/code/kicad/issues/5027
This commit is contained in:
Seth Hillbrand 2020-08-05 13:15:27 -07:00
parent b26ced820c
commit 8a0be64ad4
6 changed files with 21 additions and 12 deletions

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-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
@ -528,17 +528,19 @@ int ZONE_CONTAINER::GetLocalClearance( wxString* aSource ) const
}
bool ZONE_CONTAINER::HitTestFilledArea( PCB_LAYER_ID aLayer, const wxPoint& aRefPos ) const
bool ZONE_CONTAINER::HitTestFilledArea( PCB_LAYER_ID aLayer, const wxPoint &aRefPos,
int aAccuracy ) const
{
// Keepouts have no filled area, but it's generally nice to treat their interior as if it were
// filled so that people don't have to select keepouts by their outline (which is min-width)
if( GetIsKeepout() )
return m_Poly->Contains( VECTOR2I( aRefPos.x, aRefPos.y ) );
return m_Poly->Contains( VECTOR2I( aRefPos.x, aRefPos.y ), -1, aAccuracy );
if( !m_FilledPolysList.count( aLayer ) )
return false;
return m_FilledPolysList.at( aLayer ).Contains( VECTOR2I( aRefPos.x, aRefPos.y ) );
return m_FilledPolysList.at( aLayer ).Contains( VECTOR2I( aRefPos.x, aRefPos.y ), -1,
aAccuracy );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-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
@ -291,9 +291,10 @@ public:
* tests if the given wxPoint is within the bounds of a filled area of this zone.
* @param aLayer is the layer to test on
* @param aRefPos A wxPoint to test
* @param aAccuracy Expand the distance by which the areas are expanded for the hittest
* @return bool - true if a hit, else false
*/
bool HitTestFilledArea( PCB_LAYER_ID aLayer, const wxPoint& aRefPos ) const;
bool HitTestFilledArea( PCB_LAYER_ID aLayer, const wxPoint &aRefPos, int aAccuracy = 0 ) const;
/**
* Tests if the given point is contained within a cutout of the zone.

View File

@ -560,7 +560,9 @@ bool CONNECTIVITY_DATA::TestTrackEndpointDangling( TRACK* aTrack, wxPoint* aPos
{
if( anchor->IsDangling() )
{
*aPos = (wxPoint) anchor->Pos();
if( aPos )
*aPos = static_cast<wxPoint>( anchor->Pos() );
return true;
}
}

View File

@ -187,7 +187,7 @@ public:
void GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges ) const;
bool TestTrackEndpointDangling( TRACK* aTrack, wxPoint* aPos );
bool TestTrackEndpointDangling( TRACK* aTrack, wxPoint* aPos = nullptr );
/**
* Function ClearDynamicRatsnest()

View File

@ -340,6 +340,8 @@ bool CN_ANCHOR::Valid() const
bool CN_ANCHOR::IsDangling() const
{
int accuracy = 0;
if( !m_cluster )
return true;
@ -355,6 +357,9 @@ bool CN_ANCHOR::IsDangling() const
if( m_item->AnchorCount() == 1 )
return connected_count < minimal_count;
if( Parent()->Type() == PCB_TRACE_T || Parent()->Type() == PCB_ARC_T )
accuracy = ( static_cast<const TRACK*>( Parent() )->GetWidth() + 1 )/ 2;
// Items with multiple anchors have usually items connected to each anchor.
// We want only the item count of this anchor point
connected_count = 0;
@ -365,10 +370,10 @@ bool CN_ANCHOR::IsDangling() const
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item->Parent() );
if( zone->HitTestFilledArea( static_cast<PCB_LAYER_ID>( item->Layer() ),
static_cast<wxPoint>( Pos() ) ) )
wxPoint( Pos() ), accuracy ) )
connected_count++;
}
else if( item->Parent()->HitTest( (wxPoint) Pos() ) )
else if( item->Parent()->HitTest( wxPoint( Pos() ), accuracy ) )
connected_count++;
}

View File

@ -252,7 +252,6 @@ bool TRACKS_CLEANER::deleteDanglingTracks( bool aVia )
for( TRACK* track : temp_tracks )
{
bool flag_erase = false; // Start without a good reason to erase it
wxPoint pos;
if( aVia && track->Type() != PCB_VIA_T )
continue;
@ -260,7 +259,7 @@ bool TRACKS_CLEANER::deleteDanglingTracks( bool aVia )
continue;
// Tst if a track (or a via) endpoint is not connected to another track or to a zone.
if( m_brd->GetConnectivity()->TestTrackEndpointDangling( track, &pos ) )
if( m_brd->GetConnectivity()->TestTrackEndpointDangling( track ) )
flag_erase = true;
if( flag_erase )