KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_drc_creepage_issue24524.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
39
40#include <vector>
41
43
44#include <board.h>
45#include <board_item.h>
46#include <pcb_shape.h>
47#include <base_units.h>
48#include <geometry/eda_angle.h>
49
51
52
53namespace
54{
55// Build a horizontal stadium slot: 20 mm wide, 2 mm tall, 1 mm corner radius.
56// The left cap is centered at (1, 1) mm and the right cap at (19, 1) mm.
57PCB_SHAPE MakeHorizontalStadium()
58{
59 PCB_SHAPE slot( nullptr, SHAPE_T::RECTANGLE );
60
61 slot.SetStart( VECTOR2I( 0, 0 ) );
62 slot.SetEnd( VECTOR2I( pcbIUScale.mmToIU( 20 ), pcbIUScale.mmToIU( 2 ) ) );
63 slot.SetCornerRadius( pcbIUScale.mmToIU( 1 ) );
64
65 return slot;
66}
67} // namespace
68
69
70// A path segment crossing the outer apex of a cap must be reported as crossing
71// the board edge (return value false), while a segment grazing the inner half
72// of the same circle stays inside the slot and must read as clear (true).
73BOOST_AUTO_TEST_CASE( CreepageStadiumCapsBlockOuterSide )
74{
75 PCB_SHAPE slot = MakeHorizontalStadium();
76 std::vector<BOARD_ITEM*> edges = { &slot };
77 std::vector<const BOARD_ITEM*> dontTest;
78
79 const int oneMM = pcbIUScale.mmToIU( 1 );
80 const int halfMM = pcbIUScale.mmToIU( 0.5 );
81
82 // Left cap apex sits at (0, 1) mm. A horizontal probe through it must be blocked.
83 VECTOR2I leftOuterA( -halfMM, oneMM );
84 VECTOR2I leftOuterB( halfMM, oneMM );
85 BOOST_CHECK( !SegmentIntersectsBoard( leftOuterA, leftOuterB, edges, dontTest, 0 ) );
86
87 // Right cap apex sits at (20, 1). A horizontal probe through it must be blocked.
88 VECTOR2I rightOuterA( pcbIUScale.mmToIU( 19.5 ), oneMM );
89 VECTOR2I rightOuterB( pcbIUScale.mmToIU( 20.5 ), oneMM );
90 BOOST_CHECK( !SegmentIntersectsBoard( rightOuterA, rightOuterB, edges, dontTest, 0 ) );
91
92 // A probe across the inner half of the left cap's circle (around (2, 1)) lies
93 // inside the slot, away from any real boundary, so it must read as clear. A cap
94 // mistakenly swept over the inner half would model a boundary here and block it.
95 VECTOR2I innerA( pcbIUScale.mmToIU( 1.5 ), oneMM );
96 VECTOR2I innerB( pcbIUScale.mmToIU( 2.5 ), oneMM );
97 BOOST_CHECK( SegmentIntersectsBoard( innerA, innerB, edges, dontTest, 0 ) );
98}
99
100
101// The decomposition feeding the routing graph must emit two cap arcs whose
102// swept midpoints fall on the outer side of each cap center.
103BOOST_AUTO_TEST_CASE( CreepageStadiumCapsArcOutward )
104{
105 BOARD board;
106 CREEPAGE_GRAPH graph( board );
107 PCB_SHAPE slot = MakeHorizontalStadium();
108
109 graph.m_boardEdge.push_back( &slot );
111
112 std::vector<CREEP_SHAPE*> arcs;
113
114 for( CREEP_SHAPE* shape : graph.m_shapeCollection )
115 {
116 if( shape && shape->GetType() == CREEP_SHAPE::TYPE::ARC )
117 arcs.push_back( shape );
118 }
119
120 BOOST_REQUIRE_EQUAL( arcs.size(), 2u );
121
122 const int oneMM = pcbIUScale.mmToIU( 1 );
123
124 for( CREEP_SHAPE* arc : arcs )
125 {
126 VECTOR2I center = arc->GetPos();
127 EDA_ANGLE midAngle = ( arc->GetStartAngle() + arc->GetEndAngle() ) / 2.0;
128 double apexX = center.x + arc->GetRadius() * midAngle.Cos();
129
130 BOOST_CHECK_EQUAL( arc->GetRadius(), oneMM );
131
132 if( center.x < pcbIUScale.mmToIU( 10 ) )
133 BOOST_CHECK_LT( apexX, center.x ); // left cap bulges left
134 else
135 BOOST_CHECK_GT( apexX, center.x ); // right cap bulges right
136 }
137}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
A graph with nodes and connections for creepage calculation.
std::vector< CREEP_SHAPE * > m_shapeCollection
std::vector< BOARD_ITEM * > m_boardEdge
A class used to represent the shapes for creepage calculation.
CREEP_SHAPE::TYPE GetType() const
double Cos() const
Definition eda_angle.h:197
bool SegmentIntersectsBoard(const VECTOR2I &aP1, const VECTOR2I &aP2, const std::vector< BOARD_ITEM * > &aBe, const std::vector< const BOARD_ITEM * > &aDontTestAgainst, int aMinGrooveWidth)
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
BOOST_AUTO_TEST_CASE(CreepageStadiumCapsBlockOuterSide)
VECTOR2I center
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683