Optimize DRC calculation for copper texts. fix also a bug in SHAPE_POLY_SET::Distance( const SEG& aSegment, int aSegmentWidth ).

This bug calculate incorrectly the distance between aSegment and the SHAPE_POLY_SET for the first segment of the SHAPE_POLY_SET.
This commit is contained in:
jean-pierre charras 2019-01-26 13:01:48 +01:00
parent b8cfabd22e
commit 90178eb681
2 changed files with 23 additions and 7 deletions

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2015-2017 CERN * Copyright (C) 2015-2019 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com> * @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
* *
@ -1593,7 +1593,7 @@ int SHAPE_POLY_SET::Distance( VECTOR2I aPoint )
int SHAPE_POLY_SET::Distance( const SEG& aSegment, int aSegmentWidth ) int SHAPE_POLY_SET::Distance( const SEG& aSegment, int aSegmentWidth )
{ {
int currentDistance; int currentDistance;
int minDistance = DistanceToPolygon( aSegment, 0 ); int minDistance = DistanceToPolygon( aSegment, 0, aSegmentWidth );
// Iterate through all the polygons and get the minimum distance. // Iterate through all the polygons and get the minimum distance.
for( unsigned int polygonIdx = 1; polygonIdx < m_polys.size(); polygonIdx++ ) for( unsigned int polygonIdx = 1; polygonIdx < m_polys.size(); polygonIdx++ )

View File

@ -1,9 +1,9 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com * Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2017-2018 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 2017-2019 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -1135,6 +1135,9 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( textShape.size() == 0 ) // Should not happen (empty text?) if( textShape.size() == 0 ) // Should not happen (empty text?)
return; return;
EDA_RECT bbox = text->GetTextBox();
SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
// Test tracks and vias // Test tracks and vias
for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() ) for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
{ {
@ -1144,6 +1147,10 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL ); int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
SEG trackAsSeg( track->GetStart(), track->GetEnd() ); SEG trackAsSeg( track->GetStart(), track->GetEnd() );
// Fast test to detect a trach segment candidate inside the text bounding box
if( !rect_area.Collide( trackAsSeg, minDist ) )
continue;
for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
{ {
SEG textSeg( textShape[jj], textShape[jj+1] ); SEG textSeg( textShape[jj], textShape[jj+1] );
@ -1167,19 +1174,27 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( !pad->IsOnLayer( aTextItem->GetLayer() ) ) if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
continue; continue;
// Fast test to detect a pad candidate inside the text bounding box
// Finer test (time consumming) is made only for pads near the text.
int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
VECTOR2I shape_pos( pad->ShapePos() );
if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
continue;
const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount ); double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
SHAPE_POLY_SET padOutline; SHAPE_POLY_SET padOutline;
// We incorporate "minDist" into the pad's outline int minDist = textWidth/2 + pad->GetClearance( NULL );
pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ), pad->TransformShapeWithClearanceToPolygon( padOutline, 0,
segmentCount, correctionFactor ); segmentCount, correctionFactor );
for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
{ {
SEG textSeg( textShape[jj], textShape[jj+1] ); SEG textSeg( textShape[jj], textShape[jj+1] );
if( padOutline.Distance( textSeg, textWidth ) == 0 ) if( padOutline.Distance( textSeg, 0 ) <= minDist )
{ {
addMarkerToPcb( m_markerFactory.NewMarker( pad, aTextItem, DRCE_PAD_NEAR_COPPER ) ); addMarkerToPcb( m_markerFactory.NewMarker( pad, aTextItem, DRCE_PAD_NEAR_COPPER ) );
break; break;
@ -1192,6 +1207,7 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
void DRC::testOutline() void DRC::testOutline()
{ {
wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() ); wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) ) if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
{ {
addMarkerToPcb( m_markerFactory.NewMarker( error_loc, m_pcb, DRCE_INVALID_OUTLINE ) ); addMarkerToPcb( m_markerFactory.NewMarker( error_loc, m_pcb, DRCE_INVALID_OUTLINE ) );