KiCad PCB EDA Suite
create_layer_poly.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 (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
33 #include "cinfo3d_visu.h"
35 #include <class_edge_mod.h>
36 #include <class_module.h>
37 
38 
39 // This is the same function as in board_items_to_polygon_shape_transform.cpp
40 // but it adds the rect/trapezoid shapes with a different winding
42  SHAPE_POLY_SET& aCornerBuffer,
43  wxSize aInflateValue,
44  int aSegmentsPerCircle,
45  double aCorrectionFactor ) const
46 {
47  wxPoint corners[4];
48  wxPoint PadShapePos = aPad->ShapePos(); /* Note: for pad having a shape offset,
49  * the pad position is NOT the shape position */
50  switch( aPad->GetShape() )
51  {
52  case PAD_SHAPE_CIRCLE:
53  case PAD_SHAPE_OVAL:
56  {
57  // We are using TransformShapeWithClearanceToPolygon to build the shape.
58  // Currently, this method uses only the same inflate value for X and Y dirs.
59  // so because here this is not the case, we use a inflated dummy pad to build
60  // the polygonal shape
61  // TODO: remove this dummy pad when TransformShapeWithClearanceToPolygon will use
62  // a wxSize to inflate the pad size
63  D_PAD dummy( *aPad );
64  wxSize new_size = aPad->GetSize() + aInflateValue + aInflateValue;
65  dummy.SetSize( new_size );
66  dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0,
67  aSegmentsPerCircle, aCorrectionFactor );
68  }
69  break;
70 
72  case PAD_SHAPE_RECT:
73  {
74  SHAPE_LINE_CHAIN aLineChain;
75 
76  aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
77 
78  for( int ii = 0; ii < 4; ++ii )
79  {
80  corners[3-ii] += PadShapePos; // Shift origin to position
81  aLineChain.Append( corners[3-ii].x, corners[3-ii].y );
82  }
83 
84  aLineChain.SetClosed( true );
85 
86  aCornerBuffer.AddOutline( aLineChain );
87  }
88  break;
89 
90  case PAD_SHAPE_CUSTOM:
91  {
92  SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
93  polyList.Append( aPad->GetCustomShapeAsPolygon() );
94  aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
95  aCornerBuffer.Append( polyList );
96  }
97  break;
98  }
99 }
100 
101 
103  SHAPE_POLY_SET& aCornerBuffer,
104  int aWidth ) const
105 {
106  if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
107  {
108  unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 +
109  aWidth / 2 ) * 2 );
110 
111  TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
112  aPad->GetSize().x / 2, nr_sides_per_circle, aWidth );
113  return;
114  }
115 
116 
117  // For other shapes, draw polygon outlines
118  SHAPE_POLY_SET corners;
119 
120  unsigned int nr_sides_per_circle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
121  aPad->GetSize().y) );
122  buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ),
123  nr_sides_per_circle,
124  GetCircleCorrectionFactor( nr_sides_per_circle ) );
125 
126  // Add outlines as thick segments in polygon buffer
127 
128  const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
129 
130  for( int ii = 0; ii < path.PointCount(); ++ii )
131  {
132  const VECTOR2I& a = path.CPoint( ii );
133  const VECTOR2I& b = path.CPoint( ii + 1 );
134 
136  wxPoint( a.x, a.y ),
137  wxPoint( b.x, b.y ),
138  nr_sides_per_circle,
139  aWidth );
140  }
141 }
142 
143 
144 // Based on the same function name in board_items_to_polyshape_transform.cpp
145 // It was implemented here to allow dynamic segments count per pad shape
147  SHAPE_POLY_SET& aCornerBuffer,
148  int aInflateValue,
149  bool aSkipNPTHPadsWihNoCopper ) const
150 {
151  const D_PAD* pad = aPads;
152 
153  wxSize margin;
154  for( ; pad != NULL; pad = pad->Next() )
155  {
156  if( !pad->IsOnLayer(aLayer) )
157  continue;
158 
159  // NPTH pads are not drawn on layers if the shape size and pos is the same
160  // as their hole:
161  if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
162  {
163  if( (pad->GetDrillSize() == pad->GetSize()) &&
164  (pad->GetOffset() == wxPoint( 0, 0 )) )
165  {
166  switch( pad->GetShape() )
167  {
168  case PAD_SHAPE_CIRCLE:
169  if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
170  continue;
171  break;
172 
173  case PAD_SHAPE_OVAL:
174  if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
175  continue;
176  break;
177 
178  default:
179  break;
180  }
181  }
182  }
183 
184  switch( aLayer )
185  {
186  case F_Mask:
187  case B_Mask:
188  margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
189  break;
190 
191  case F_Paste:
192  case B_Paste:
193  margin = pad->GetSolderPasteMargin();
194  margin.x += aInflateValue;
195  margin.y += aInflateValue;
196  break;
197 
198  default:
199  margin.x = margin.y = aInflateValue;
200  break;
201  }
202 
203  unsigned int aCircleToSegmentsCount = GetNrSegmentsCircle( pad->GetSize().x );
204  double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
205 
206  buildPadShapePolygon( pad, aCornerBuffer, margin,
207  aCircleToSegmentsCount, aCorrectionFactor );
208  }
209 }
210 
212  PCB_LAYER_ID aLayer,
213  SHAPE_POLY_SET& aCornerBuffer ) const
214 {
215  for( const EDA_ITEM* item = aModule->GraphicalItemsList();
216  item != NULL;
217  item = item->Next() )
218  {
219  switch( item->Type() )
220  {
221  case PCB_MODULE_EDGE_T:
222  {
223  EDGE_MODULE*outline = (EDGE_MODULE*) item;
224 
225  if( outline->GetLayer() != aLayer )
226  break;
227 
228  unsigned int aCircleToSegmentsCount =
230 
231  double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
232 
233  outline->TransformShapeWithClearanceToPolygon( aCornerBuffer,
234  0,
235  aCircleToSegmentsCount,
236  aCorrectionFactor );
237  }
238  break;
239 
240  default:
241  break;
242  }
243  }
244 }
void TransformRoundedEndsSegmentToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aCircleToSegmentsCount, int aWidth)
Function TransformRoundedEndsSegmentToPolygon convert a segment with rounded ends to a polygon Conver...
D_PAD * Next() const
Definition: class_pad.h:162
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
void transformPadsShapesWithClearanceToPolygon(const DLIST< D_PAD > &aPads, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aCornerBuffer, int aInflateValue, bool aSkipNPTHPadsWihNoCopper) const
unsigned int GetNrSegmentsCircle(float aDiameter3DU) const
GetNrSegmentsCircle.
Handles data related with the board to be visualized.
int PointCount() const
Function PointCount()
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:417
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
void SetClosed(bool aClosed)
Function SetClosed()
int GetSolderMaskMargin() const
Function GetSolderMaskMargin.
Definition: class_pad.cpp:639
PCB_LAYER_ID
A quick note on layer IDs:
double GetCircleCorrectionFactor(int aNrSides) const
GetCircleCorrectionFactor - computes a angle correction factor used when creating circles.
Class SHAPE_POLY_SET.
const wxPoint & GetOffset() const
Definition: class_pad.h:280
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:400
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearanceValue, int aCircleToSegmentsCount, double aCorrectionFactor, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the draw segment to a closed polygon Used in fi...
void TransformRingToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCentre, int aRadius, int aCircleToSegmentsCount, int aWidth)
Function TransformRingToPolygon Creates a polygon from a ring Convert arcs to multiple straight segme...
wxSize GetSolderPasteMargin() const
Function GetSolderPasteMargin.
Definition: class_pad.cpp:685
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
Class SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:394
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const wxSize & GetDrillSize() const
Definition: class_pad.h:277
wxPoint ShapePos() const
Definition: class_pad.cpp:562
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:346
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:157
void transformGraphicModuleEdgeToPolygonSet(const MODULE *aModule, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aCornerBuffer) const
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:165
void buildPadShapeThickOutlineAsPolygon(const D_PAD *aPad, SHAPE_POLY_SET &aCornerBuffer, int aWidth) const
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:218
Module description (excepted pads)
void buildPadShapePolygon(const D_PAD *aPad, SHAPE_POLY_SET &aCornerBuffer, wxSize aInflateValue, int aSegmentsPerCircle, double aCorrectionFactor) const
const wxSize & GetSize() const
Definition: class_pad.h:271
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:717
EDGE_MODULE class definition.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetSizeMax() const
GetSizeMax.
Definition: eda_rect.h:107
#define min(a, b)
Definition: auxiliary.h:85
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)
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.