diff --git a/qa/drc_proto/drc_test_provider_clearance_base.cpp b/qa/drc_proto/drc_test_provider_clearance_base.cpp index 96aec7d954..958d96e820 100644 --- a/qa/drc_proto/drc_test_provider_clearance_base.cpp +++ b/qa/drc_proto/drc_test_provider_clearance_base.cpp @@ -152,230 +152,37 @@ bool test::DRC_TEST_PROVIDER_CLEARANCE_BASE::checkClearanceSegmToPad( const SEG& bool test::DRC_TEST_PROVIDER_CLEARANCE_BASE::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance, int* aActual ) { - // relativePadPos is the aPad shape position relative to the aRefPad shape position - wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos(); - - int center2center = KiROUND( EuclideanNorm( relativePadPos ) ); + int center2center = KiROUND( EuclideanNorm( aPad->ShapePos() - aRefPad->ShapePos() ) ); // Quick test: Clearance is OK if the bounding circles are further away than aMinClearance if( center2center - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance ) return true; - /* Here, pads are near and DRC depends on the pad shapes. We must compare distance using - * a fine shape analysis. - * Because a circle or oval shape is the easier shape to test, swap pads to have aRefPad be - * a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL. If aRefPad = TRAPEZOID and aPad = RECT, also swap. - */ - bool swap_pads; - swap_pads = false; + // JEY TODO: + // TOM TODO: MTV only works as a proxy for actual-distance for convex shapes - // swap pads to make comparisons easier - // Note also a ROUNDRECT pad with a corner radius = r can be considered as - // a smaller RECT (size - 2*r) with a clearance increased by r - // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other - if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE ) + VECTOR2I mtv; + VECTOR2I maxMtv( 0, 0 ); + + for( const std::shared_ptr& aShape : aRefPad->GetEffectiveShapes() ) { - // pad ref shape is here oval, rect, roundrect, chamfered rect, trapezoid or custom - switch( aPad->GetShape() ) + for( const std::shared_ptr& bShape : aPad->GetEffectiveShapes() ) { - case PAD_SHAPE_CIRCLE: - swap_pads = true; - break; - - case PAD_SHAPE_OVAL: - swap_pads = true; - break; - - case PAD_SHAPE_RECT: - case PAD_SHAPE_ROUNDRECT: - if( aRefPad->GetShape() != PAD_SHAPE_OVAL ) - swap_pads = true; - break; - - case PAD_SHAPE_TRAPEZOID: - case PAD_SHAPE_CHAMFERED_RECT: - case PAD_SHAPE_CUSTOM: - break; + if( aShape->Collide( bShape.get(), aMinClearance, mtv ) ) + { + if( mtv.SquaredEuclideanNorm() > maxMtv.SquaredEuclideanNorm() ) + maxMtv = mtv; + } } } - if( swap_pads ) + if( maxMtv.x > 0 || maxMtv.y > 0 ) { - std::swap( aRefPad, aPad ); - relativePadPos = -relativePadPos; + *aActual = std::max( 0, aMinClearance - maxMtv.EuclideanNorm() ); + return false; } - bool diag = true; - - if( ( aRefPad->GetShape() == PAD_SHAPE_CIRCLE || aRefPad->GetShape() == PAD_SHAPE_OVAL ) ) - { - /* Treat an oval pad as a line segment along the hole's major axis, - * shortened by half its minor axis. - * A circular pad is just a degenerate case of an oval hole. - */ - wxPoint refPadStart, refPadEnd; - int refPadWidth; - - aRefPad->GetOblongGeometry( aRefPad->GetSize(), &refPadStart, &refPadEnd, &refPadWidth ); - refPadStart += aRefPad->ShapePos(); - refPadEnd += aRefPad->ShapePos(); - - SEG refPadSeg( refPadStart, refPadEnd ); - diag = checkClearanceSegmToPad( refPadSeg, refPadWidth, aPad, aMinClearance, aActual ); - } - else - { - int dist_extra = 0; - - // corners of aRefPad (used only for rect/roundrect/trap pad) - wxPoint polyref[4]; - // corners of aRefPad (used only for custom pad) - SHAPE_POLY_SET polysetref; - - if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT ) - { - int padRadius = aRefPad->GetRoundRectCornerRadius(); - dist_extra = padRadius; - GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ), aRefPad->GetSize(), - aRefPad->GetOrientation() ); - } - else if( aRefPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT ) - { - BOARD* board = aRefPad->GetBoard(); - int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; - - // The reference pad can be rotated. Calculate the rotated coordinates. - // (note, the ref pad position is the origin of coordinates for this drc test) - int padRadius = aRefPad->GetRoundRectCornerRadius(); - - TransformRoundChamferedRectToPolygon( polysetref, wxPoint( 0, 0 ), aRefPad->GetSize(), - aRefPad->GetOrientation(), - padRadius, aRefPad->GetChamferRectRatio(), - aRefPad->GetChamferPositions(), maxError ); - } - else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM ) - { - polysetref.Append( aRefPad->GetCustomShapeAsPolygon() ); - - // The reference pad can be rotated. Calculate the rotated coordinates. - // (note, the ref pad position is the origin of coordinates for this drc test) - aRefPad->CustomShapeAsPolygonToBoardPosition( &polysetref, wxPoint( 0, 0 ), - aRefPad->GetOrientation() ); - } - else - { - // BuildPadPolygon has meaning for rect a trapeziod shapes and returns the 4 corners. - aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() ); - } - - // corners of aPad (used only for rect/roundrect/trap pad) - wxPoint polycompare[4]; - // corners of aPad (used only custom pad) - SHAPE_POLY_SET polysetcompare; - - switch( aPad->GetShape() ) - { - case PAD_SHAPE_ROUNDRECT: - case PAD_SHAPE_RECT: - case PAD_SHAPE_CHAMFERED_RECT: - case PAD_SHAPE_TRAPEZOID: - case PAD_SHAPE_CUSTOM: - if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT ) - { - int padRadius = aPad->GetRoundRectCornerRadius(); - dist_extra = padRadius; - GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos, aPad->GetSize(), - aPad->GetOrientation() ); - } - else if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT ) - { - BOARD* board = aRefPad->GetBoard(); - int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; - - // The pad to compare can be rotated. Calculate the rotated coordinates. - // ( note, the pad to compare position is the relativePadPos for this drc test) - int padRadius = aPad->GetRoundRectCornerRadius(); - - TransformRoundChamferedRectToPolygon( polysetcompare, relativePadPos, - aPad->GetSize(), aPad->GetOrientation(), - padRadius, aPad->GetChamferRectRatio(), - aPad->GetChamferPositions(), maxError ); - } - else if( aPad->GetShape() == PAD_SHAPE_CUSTOM ) - { - polysetcompare.Append( aPad->GetCustomShapeAsPolygon() ); - - // The pad to compare can be rotated. Calculate the rotated coordinates. - // ( note, the pad to compare position is the relativePadPos for this drc test) - aPad->CustomShapeAsPolygonToBoardPosition( &polysetcompare, relativePadPos, - aPad->GetOrientation() ); - } - else - { - aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() ); - - // Move aPad shape to relativePadPos - for( int ii = 0; ii < 4; ii++ ) - polycompare[ii] += relativePadPos; - } - - // And now test polygons: We have 3 cases: - // one poly is complex and the other is basic (has only 4 corners) - // both polys are complex - // both polys are basic (have only 4 corners) the most usual case - if( polysetref.OutlineCount() && polysetcompare.OutlineCount() == 0) - { - const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 ); - // And now test polygons: - if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(), - polycompare, 4, aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - else if( polysetref.OutlineCount() == 0 && polysetcompare.OutlineCount()) - { - const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 ); - // And now test polygons: - if( !poly2polyDRC((wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), - polyref, 4, aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - else if( polysetref.OutlineCount() && polysetcompare.OutlineCount() ) - { - const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 ); - const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 ); - - // And now test polygons: - if( !poly2polyDRC((wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(), - (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), - aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - else - { - if( !poly2polyDRC( polyref, 4, polycompare, 4, aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - break; - - default: - wxLogDebug( wxT( "DRC::checkClearancePadToPad: unexpected pad shape %d" ), aPad->GetShape() ); - break; - } - } - - return diag; + return true; } diff --git a/qa/drc_proto/drc_test_provider_copper_clearance.cpp b/qa/drc_proto/drc_test_provider_copper_clearance.cpp index 036d82c73c..4adf7202f9 100644 --- a/qa/drc_proto/drc_test_provider_copper_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_copper_clearance.cpp @@ -61,7 +61,18 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run() { auto bds = m_drcEngine->GetDesignSettings(); m_board = m_drcEngine->GetBoard(); - m_largestClearance = bds->GetBiggestClearanceValue(); + + m_largestClearance = 0; + + for( auto rule : m_drcEngine->QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE ) ) + { + if( rule->GetConstraint().m_Value.HasMin() ) + m_largestClearance = std::max( m_largestClearance, rule->GetConstraint().m_Value.Min() ); + } + + ReportAux( "Worst clearance : %d nm", m_largestClearance ); + + //m_largestClearance = ReportStage( ("Testing pad copper clerances"), 0, 2 ); testPadClearances(); @@ -895,5 +906,5 @@ std::set test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::GetMatch namespace detail { - //static test::DRC_REGISTER_TEST_PROVIDER dummy; + static test::DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_test_provider_hole_clearance.cpp b/qa/drc_proto/drc_test_provider_hole_clearance.cpp index 4712c9214d..7bd93ef27d 100644 --- a/qa/drc_proto/drc_test_provider_hole_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_hole_clearance.cpp @@ -56,7 +56,16 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run() { auto bds = m_drcEngine->GetDesignSettings(); m_board = m_drcEngine->GetBoard(); - m_largestClearance = bds->GetBiggestClearanceValue(); + + m_largestClearance = 0; + + for( auto rule : m_drcEngine->QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_HOLE_CLEARANCE ) ) + { + if( rule->GetConstraint().m_Value.HasMin() ) + m_largestClearance = std::max( m_largestClearance, rule->GetConstraint().m_Value.Min() ); + } + + ReportAux( "Worst clearance : %d nm", m_largestClearance ); ReportStage( ("Testing pad/hole clearances"), 0, 2 ); testPadHoles();