KiCad PCB EDA Suite
Loading...
Searching...
No Matches
fab_pad_geometry.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * 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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "fab_pad_geometry.h"
21
23
24
26 m_pad( std::make_unique<PAD>( aPad ) ),
27 m_layer( aLayer )
28{
29}
30
31
33{
34 SHAPE_POLY_SET polygon;
35
36 if( !m_empty )
37 m_pad->TransformShapeToPolygon( polygon, m_layer, 0, m_maxError, ERROR_INSIDE );
38
39 return polygon;
41
42
44{
45 if( aLayer == F_Mask || aLayer == B_Mask )
46 {
47 int expansion = aPad.GetSolderMaskExpansion( aLayer );
48 return VECTOR2I( expansion, expansion );
49 }
50
51 if( aLayer == F_Paste || aLayer == B_Paste )
52 return aPad.GetSolderPasteMargin( aLayer );
53
54 return VECTOR2I( 0, 0 );
55}
56
57
58PAD_LAYER_GEOMETRY ResolvePadLayer( const PAD& aPad, PCB_LAYER_ID aLayer, int aMaxError )
59{
60 PAD_LAYER_GEOMETRY result( aPad, aLayer );
61 result.m_maxError = aMaxError;
62 result.m_margin = ResolvePadMargin( aPad, aLayer );
63
64 const VECTOR2I adjustedSize = aPad.GetSize( aLayer ) + 2 * result.m_margin;
65 const int clearance = result.m_margin.x;
66 const bool sameMargin = result.m_margin.x == result.m_margin.y;
67 const PAD_SHAPE shape = aPad.GetShape( aLayer );
68 PAD& resolved = *result.m_pad;
69 auto makePolygonPad = [&]( const SHAPE_POLY_SET& aOutline )
70 {
71 resolved.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
72 resolved.SetShape( aLayer, PAD_SHAPE::CUSTOM );
73 resolved.DeletePrimitivesList();
74 resolved.AddPrimitivePoly( aLayer, aOutline, 0, true );
75 resolved.SetSize( aLayer, VECTOR2I( 0, 0 ) );
76 };
77
78 if( shape != PAD_SHAPE::CUSTOM && ( adjustedSize.x <= 0 || adjustedSize.y <= 0 ) )
79 result.m_empty = true;
80
81 switch( shape )
82 {
84 case PAD_SHAPE::OVAL: resolved.SetSize( aLayer, adjustedSize ); break;
85
87 resolved.SetSize( aLayer, adjustedSize );
88
89 if( clearance > 0 )
90 {
91 result.m_cornerRadius = clearance;
92 resolved.SetShape( aLayer, PAD_SHAPE::ROUNDRECT );
93 resolved.SetRoundRectCornerRadius( aLayer, clearance );
94 }
95
96 break;
97
99 {
100 const double ratio = aPad.GetRoundRectRadiusRatio( aLayer );
101 resolved.SetSize( aLayer, adjustedSize );
102
103 // Equal margins offset the corner radius; unequal margins keep the ratio as the plotter does
104 if( sameMargin )
105 {
106 result.m_cornerRadius = std::max( 0, aPad.GetRoundRectCornerRadius( aLayer ) + clearance );
107 resolved.SetRoundRectCornerRadius( aLayer, result.m_cornerRadius );
108 }
109 else
110 {
111 result.m_cornerRadius =
112 KiROUND( ratio * std::min( std::abs( adjustedSize.x ), std::abs( adjustedSize.y ) ) );
113 }
114
115 break;
116 }
117
119 {
120 if( clearance <= 0 )
121 {
122 resolved.SetSize( aLayer, adjustedSize );
123 break;
124 }
125
126 PAD dummy( aPad );
127 dummy.SetPosition( VECTOR2I( 0, 0 ) );
128 dummy.SetOffset( aLayer, VECTOR2I( 0, 0 ) );
129 dummy.SetOrientation( ANGLE_0 );
130
131 if( !sameMargin )
132 dummy.SetSize( aLayer, adjustedSize );
133
134 SHAPE_POLY_SET outline;
135 dummy.TransformShapeToPolygon( outline, aLayer, 0, aMaxError, ERROR_INSIDE );
136
137 if( sameMargin )
139
140 makePolygonPad( outline );
141 result.m_contour = std::move( outline );
142 break;
143 }
144
146 {
147 const VECTOR2I halfSize = aPad.GetSize( aLayer ) / 2;
148 const VECTOR2I halfDelta = aPad.GetDelta( aLayer ) / 2;
149 SHAPE_POLY_SET outline;
150 outline.NewOutline();
151 outline.Append( -halfSize.x - halfDelta.y, halfSize.y + halfDelta.x );
152 outline.Append( halfSize.x + halfDelta.y, halfSize.y - halfDelta.x );
153 outline.Append( halfSize.x - halfDelta.y, -halfSize.y + halfDelta.x );
154 outline.Append( -halfSize.x + halfDelta.y, -halfSize.y - halfDelta.x );
155
156 // Linked-hole inflation preserves deflated contours that contain holes
157 if( clearance != 0 )
159
160 result.m_contour = std::move( outline );
161
162 if( clearance == 0 )
163 break;
164
165 makePolygonPad( result.m_contour );
166 break;
167 }
168
170 {
171 SHAPE_POLY_SET outline;
172 aPad.MergePrimitivesAsPolygon( aLayer, &outline );
173
174 if( clearance != 0 )
176
177 resolved.DeletePrimitivesList();
178 resolved.AddPrimitivePoly( aLayer, outline, 0, true );
179 result.m_contour = std::move( outline );
180
181 // The anchor is merged into the shape, so it must fit inside a deflated outline
182 if( clearance < 0 )
183 resolved.SetSize( aLayer, VECTOR2I( std::max( 0, adjustedSize.x ), std::max( 0, adjustedSize.y ) ) );
184
185 break;
186 }
187
188 default: result.m_empty = true; break;
189 }
190
191 return result;
192}
@ ERROR_INSIDE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
PAD_LAYER_GEOMETRY(const PAD &aPad, PCB_LAYER_ID aLayer)
SHAPE_POLY_SET Polygon() const
std::unique_ptr< PAD > m_pad
Definition pad.h:61
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition pad.h:249
void MergePrimitivesAsPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
Definition pad.cpp:3751
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1182
void AddPrimitivePoly(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPoly, int aThickness, bool aFilled)
Has meaning only for custom shape pads.
Definition pad.cpp:3645
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
Definition pad.h:307
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
Definition pad.h:196
double GetRoundRectRadiusRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:811
void DeletePrimitivesList(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Clear the basic shapes list.
Definition pad.cpp:3732
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1998
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:298
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition pad.cpp:265
void SetRoundRectCornerRadius(PCB_LAYER_ID aLayer, double aRadius)
Definition pad.cpp:1188
VECTOR2I GetSolderPasteMargin(PCB_LAYER_ID aLayer) const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition pad.cpp:2061
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
PAD_LAYER_GEOMETRY ResolvePadLayer(const PAD &aPad, PCB_LAYER_ID aLayer, int aMaxError)
Artwork on one layer as plotted by PlotStandardLayer; keep the plotter independent as the parity orac...
VECTOR2I ResolvePadMargin(const PAD &aPad, PCB_LAYER_ID aLayer)
Per-side mask or paste margin as PlotStandardLayer applies it.
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_Paste
Definition layer_ids.h:100
@ B_Mask
Definition layer_ids.h:94
@ F_Mask
Definition layer_ids.h:93
@ B_Paste
Definition layer_ids.h:101
STL namespace.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:437
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition padstack.h:51
@ CHAMFERED_RECT
Definition padstack.h:59
@ ROUNDRECT
Definition padstack.h:56
@ TRAPEZOID
Definition padstack.h:55
@ RECTANGLE
Definition padstack.h:53
std::vector< FAB_LAYER_COLOR > dummy
int clearance
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708