KiCad PCB EDA Suite
test_board_item.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) 2021 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 
25 #include <eda_item_test_utils.h>
26 #include <core/typeinfo.h>
27 
28 // Code under test
29 #include <board.h>
30 #include <board_item.h>
31 #include <footprint.h>
32 #include <pad.h>
33 #include <pcb_shape.h>
34 #include <pcb_text.h>
35 #include <fp_text.h>
36 #include <fp_shape.h>
37 #include <zone.h>
38 #include <pcb_track.h>
39 #include <pcb_marker.h>
40 #include <pcb_dimension.h>
41 #include <pcb_target.h>
42 #include <netinfo.h>
43 #include <pcb_group.h>
44 
46 {
47 public:
50  std::shared_ptr<DRC_ITEM> m_drcItem;
52 
54  m_board(),
55  m_footprint( &m_board ),
57  m_text( &m_board )
58  {
59  }
60 
62  {
63  if( !IsPcbnewType( aType ) )
64  return nullptr;
65 
66  if( !IsInstantiableType( aType ) )
67  return nullptr;
68 
69  switch( aType )
70  {
71  case PCB_FOOTPRINT_T: return new FOOTPRINT( &m_board );
72  case PCB_PAD_T: return new PAD( &m_footprint );
73  case PCB_SHAPE_T: return new PCB_SHAPE( &m_board );
74  case PCB_TEXT_T: return new PCB_TEXT( &m_board );
75  case PCB_FP_TEXT_T: return new FP_TEXT( &m_footprint );
76  case PCB_FP_SHAPE_T: return new FP_SHAPE( &m_footprint );
77  case PCB_FP_ZONE_T:
78  {
79  FP_ZONE* fpZone = new FP_ZONE( &m_footprint );
80 
81  fpZone->AppendCorner( wxPoint( Millimeter2iu( -100 ), Millimeter2iu( -50 ) ), -1 );
82  fpZone->AppendCorner( wxPoint( Millimeter2iu( -100 ), Millimeter2iu( 50 ) ), -1 );
83  fpZone->AppendCorner( wxPoint( Millimeter2iu( 100 ), Millimeter2iu( 50 ) ), -1 );
84  fpZone->AppendCorner( wxPoint( Millimeter2iu( 100 ), Millimeter2iu( -50 ) ), -1 );
85 
86  return fpZone;
87  }
88 
89  case PCB_TRACE_T: return new PCB_TRACK( &m_board );
90  case PCB_VIA_T: return new PCB_VIA( &m_board );
91  case PCB_ARC_T: return new PCB_ARC( &m_board );
92  case PCB_MARKER_T: return new PCB_MARKER( m_drcItem, wxPoint( 0, 0 ) );
93  case PCB_DIM_ALIGNED_T: return new PCB_DIM_ALIGNED( &m_board );
94  case PCB_DIM_LEADER_T: return new PCB_DIM_LEADER( &m_board );
95  case PCB_DIM_CENTER_T: return new PCB_DIM_CENTER( &m_board );
96  case PCB_DIM_ORTHOGONAL_T: return new PCB_DIM_ORTHOGONAL( &m_board );
97  case PCB_TARGET_T: return new PCB_TARGET( &m_board );
98  case PCB_ZONE_T:
99  {
100  ZONE* zone = new ZONE( &m_board );
101 
102  zone->AppendCorner( wxPoint( Millimeter2iu( -100 ), Millimeter2iu( -50 ) ), -1 );
103  zone->AppendCorner( wxPoint( Millimeter2iu( -100 ), Millimeter2iu( 50 ) ), -1 );
104  zone->AppendCorner( wxPoint( Millimeter2iu( 100 ), Millimeter2iu( 50 ) ), -1 );
105  zone->AppendCorner( wxPoint( Millimeter2iu( 100 ), Millimeter2iu( -50 ) ), -1 );
106 
107  return zone;
108  }
109  case PCB_GROUP_T:
110  {
111  PCB_GROUP* group = new PCB_GROUP( &m_board );
112 
113  // Group position only makes sense if there's at least one item in the group.
114  group->AddItem( &m_text );
115 
116  return group;
117  }
118 
119  case PCB_T:
120  case PCB_ITEM_LIST_T:
121  case PCB_NETINFO_T:
122  return nullptr;
123 
124  default:
125  BOOST_FAIL( wxString::Format(
126  "Unhandled type: %d "
127  "(if you created a new type you need to handle it in this switch statement)",
128  aType ) );
129  return nullptr;
130  }
131  }
132 
133  static void CompareItems( BOARD_ITEM* aItem, BOARD_ITEM* aOriginalItem )
134  {
135  BOOST_CHECK_EQUAL( aItem->GetPosition(), aOriginalItem->GetPosition() );
136  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetTop(),
137  aOriginalItem->GetBoundingBox().GetTop() );
138  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetLeft(),
139  aOriginalItem->GetBoundingBox().GetLeft() );
140  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetBottom(),
141  aOriginalItem->GetBoundingBox().GetBottom() );
142  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetRight(),
143  aOriginalItem->GetBoundingBox().GetRight() );
144  }
145 };
146 
147 
148 BOOST_FIXTURE_TEST_SUITE( PcbItem, TEST_BOARD_ITEM_FIXTURE )
149 
150 
152 {
153  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
154  {
155  KICAD_T type = static_cast<KICAD_T>( i );
156 
157  auto item = std::unique_ptr<BOARD_ITEM>( Instantiate( type ) );
158 
159  if( item == nullptr )
160  continue;
161 
162  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
163  {
164  IterateOverPositionsAndReferences<BOARD_ITEM>(
165  item.get(),
166  []( BOARD_ITEM* aOriginalItem, wxPoint aRef )
167  {
168  FP_SHAPE* originalFpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
169 
170  if( originalFpShape != nullptr )
171  originalFpShape->SetDrawCoord();
172 
173  // FIXME: Update() has to be called after SetPosition() to update dimension
174  // shapes.
175  PCB_DIMENSION_BASE* originalDimension =
176  dynamic_cast<PCB_DIMENSION_BASE*>( aOriginalItem );
177 
178  if( originalDimension != nullptr )
179  originalDimension->Update();
180 
181  auto item = std::unique_ptr<BOARD_ITEM>( aOriginalItem->Duplicate() );
182  wxPoint originalPos = item->GetPosition();
183 
184  // Move to a point, then go back.
185  // This has to be an identity transformation.
186 
187  item->Move( aRef );
188 
189  FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( item.get() );
190  if( fpShape != nullptr )
191  fpShape->SetDrawCoord();
192 
193  BOOST_CHECK_EQUAL( item->GetPosition(), originalPos + aRef );
194 
195  item->Move( -aRef );
196 
197  if( fpShape != nullptr )
198  fpShape->SetDrawCoord();
199 
200  CompareItems( item.get(), aOriginalItem );
201  } );
202  }
203  }
204 }
205 
206 
208 {
209  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
210  {
211  KICAD_T type = static_cast<KICAD_T>( i );
212 
213  auto item = std::unique_ptr<BOARD_ITEM>( Instantiate( type ) );
214 
215  if( item == nullptr )
216  continue;
217 
218  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
219  {
220  // Four same 90 degree rotations are an identity.
221 
222  IterateOverPositionsAndReferences<BOARD_ITEM>(
223  item.get(),
224  []( BOARD_ITEM* aOriginalItem, wxPoint aRef )
225  {
226  FP_SHAPE* originalFpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
227 
228  if( originalFpShape != nullptr )
229  originalFpShape->SetDrawCoord();
230 
231  // FIXME: Update() has to be called after SetPosition() to update dimension
232  // shapes.
233  PCB_DIMENSION_BASE* originalDimension =
234  dynamic_cast<PCB_DIMENSION_BASE*>( aOriginalItem );
235 
236  if( originalDimension != nullptr )
237  originalDimension->Update();
238 
239  auto item = std::unique_ptr<BOARD_ITEM>( aOriginalItem->Duplicate() );
240 
241  // Four equivalent 90 degree rotations are an identity.
242 
243  item->Rotate( aRef, 900 );
244  item->Rotate( aRef, 900 );
245  item->Rotate( aRef, 900 );
246  item->Rotate( aRef, 900 );
247 
248  FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
249 
250  if( fpShape != nullptr )
251  fpShape->SetDrawCoord();
252 
253  CompareItems( item.get(), aOriginalItem );
254  } );
255  }
256  }
257 }
258 
259 
260 BOOST_AUTO_TEST_CASE( FlipLeftRight )
261 {
262  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
263  {
264  KICAD_T type = static_cast<KICAD_T>( i );
265 
266  auto item = std::unique_ptr<BOARD_ITEM>( Instantiate( type ) );
267 
268  if( item == nullptr )
269  continue;
270 
271  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
272  {
273  IterateOverPositionsAndReferences<BOARD_ITEM>(
274  item.get(),
275  []( BOARD_ITEM* aOriginalItem, wxPoint aRef )
276  {
277  FP_SHAPE* originalFpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
278 
279  if( originalFpShape != nullptr )
280  originalFpShape->SetDrawCoord();
281 
282  // FIXME: Update() has to be called after SetPosition() to update dimension
283  // shapes.
284  PCB_DIMENSION_BASE* originalDimension =
285  dynamic_cast<PCB_DIMENSION_BASE*>( aOriginalItem );
286 
287  if( originalDimension != nullptr )
288  originalDimension->Update();
289 
290  auto item = std::unique_ptr<BOARD_ITEM>( aOriginalItem->Duplicate() );
291 
292  // Two equivalent flips are an identity.
293 
294  item->Flip( aRef, true );
295  item->Flip( aRef, true );
296 
297  FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
298 
299  if( fpShape != nullptr )
300  fpShape->SetDrawCoord();
301 
302  CompareItems( item.get(), aOriginalItem );
303  } );
304  }
305  }
306 }
307 
308 
309 BOOST_AUTO_TEST_CASE( FlipUpDown )
310 {
311  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
312  {
313  KICAD_T type = static_cast<KICAD_T>( i );
314 
315  auto item = std::unique_ptr<BOARD_ITEM>( Instantiate( type ) );
316 
317  if( item == nullptr )
318  continue;
319 
320  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
321  {
322  IterateOverPositionsAndReferences<BOARD_ITEM>(
323  item.get(),
324  []( BOARD_ITEM* aOriginalItem, wxPoint aRef )
325  {
326  FP_SHAPE* originalFpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
327 
328  if( originalFpShape != nullptr )
329  originalFpShape->SetDrawCoord();
330 
331  // FIXME: Update() has to be called after SetPosition() to update dimension
332  // shapes.
333  PCB_DIMENSION_BASE* originalDimension =
334  dynamic_cast<PCB_DIMENSION_BASE*>( aOriginalItem );
335 
336  if( originalDimension != nullptr )
337  originalDimension->Update();
338 
339  auto item = std::unique_ptr<BOARD_ITEM>( aOriginalItem->Duplicate() );
340 
341  // Two equivalent flips are an identity.
342 
343  item->Flip( aRef, false );
344  item->Flip( aRef, false );
345 
346  FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );
347 
348  if( fpShape != nullptr )
349  fpShape->SetDrawCoord();
350 
351  CompareItems( item.get(), aOriginalItem );
352  } );
353  }
354  }
355 }
356 
357 
358 BOOST_AUTO_TEST_SUITE_END()
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:100
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:101
Definition: typeinfo.h:84
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
BOARD_ITEM * Instantiate(KICAD_T aType)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
int GetTop() const
Definition: eda_rect.h:122
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:102
std::shared_ptr< DRC_ITEM > m_drcItem
int GetLeft() const
Definition: eda_rect.h:121
static void CompareItems(BOARD_ITEM *aItem, BOARD_ITEM *aOriginalItem)
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
constexpr bool IsPcbnewType(const KICAD_T aType)
Definition: typeinfo.h:374
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
Abstract dimension API.
Definition: pcb_dimension.h:95
virtual wxPoint GetPosition() const
Definition: eda_item.h:251
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
int GetBottom() const
Definition: eda_rect.h:123
For better understanding of the points that make a dimension:
int GetRight() const
Definition: eda_rect.h:120
Mark the center of a circle or arc with a cross shape.
class BOARD_ITEM_LIST, a list of board items
Definition: typeinfo.h:106
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
class ZONE, a copper pour area
Definition: typeinfo.h:105
#define BOOST_TEST_CONTEXT(A)
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
Definition: fp_shape.cpp:81
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:104
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: zone.cpp:815
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:107
class ZONE, managed by a footprint
Definition: typeinfo.h:94
constexpr bool IsInstantiableType(const KICAD_T aType)
Definition: typeinfo.h:274
A leader is a dimension-like object pointing to a specific point.
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:103
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:75
BOOST_AUTO_TEST_CASE(Move)
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
static constexpr int Millimeter2iu(double mm)
A specialization of ZONE for use in footprints.
Definition: zone.h:947
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.cpp:144
void Update()
Update the dimension's cached text and geometry.