KiCad PCB EDA Suite
test_ee_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 #include <eda_item.h>
29 #include <sch_item.h>
30 #include <lib_item.h>
31 
32 #include <sch_marker.h>
33 #include <sch_junction.h>
34 #include <sch_no_connect.h>
35 #include <sch_bus_entry.h>
36 #include <sch_line.h>
37 #include <sch_bitmap.h>
38 #include <sch_text.h>
39 #include <sch_field.h>
40 #include <sch_symbol.h>
41 #include <sch_sheet_pin.h>
42 #include <sch_sheet.h>
43 
44 #include <lib_shape.h>
45 #include <lib_text.h>
46 #include <lib_pin.h>
47 #include <lib_field.h>
48 
49 #include <erc_settings.h>
50 
52 {
53 public:
57  std::shared_ptr<ERC_ITEM> m_ercItem;
58 
60  m_sheet(),
61  m_symbol( "test symbol" ),
62  m_pin( &m_symbol ),
64  {
65  m_sheet.SetPosition( wxPoint( Millimeter2iu( 5 ), Millimeter2iu( 10 ) ) );
66  m_sheet.SetSize( wxSize( Millimeter2iu( 50 ), Millimeter2iu( 100 ) ) );
67  }
68 
70  {
71  if( !IsEeschemaType( aType ) )
72  return nullptr;
73 
74  if( !IsInstantiableType( aType ) )
75  return nullptr;
76 
77  switch( aType )
78  {
79  case SCH_MARKER_T: return new SCH_MARKER( m_ercItem, wxPoint( 0, 0 ) );
80  case SCH_JUNCTION_T: return new SCH_JUNCTION();
81  case SCH_NO_CONNECT_T: return new SCH_NO_CONNECT();
82  case SCH_BUS_WIRE_ENTRY_T: return new SCH_BUS_WIRE_ENTRY();
83  case SCH_BUS_BUS_ENTRY_T: return new SCH_BUS_BUS_ENTRY();
84  case SCH_LINE_T: return new SCH_LINE();
85  case SCH_BITMAP_T: return new SCH_BITMAP();
86  case SCH_TEXT_T: return new SCH_TEXT( wxPoint( 0, 0 ), "test text" );
87  case SCH_LABEL_T: return new SCH_LABEL( wxPoint( 0, 0 ), "test label" );
88  case SCH_GLOBAL_LABEL_T: return new SCH_GLOBALLABEL();
89  case SCH_HIER_LABEL_T: return new SCH_HIERLABEL();
90  case SCH_FIELD_T: return new SCH_FIELD( wxPoint( 0, 0 ), 0, nullptr );
91  case SCH_SYMBOL_T: return new SCH_SYMBOL();
92 
93  case SCH_SHEET_PIN_T:
94  // XXX: m_sheet pins currently have to have their initial positions calculated manually.
95  return new SCH_SHEET_PIN( &m_sheet,
96  wxPoint( m_sheet.GetPosition().x,
97  m_sheet.GetPosition().y + Millimeter2iu( 40 ) ),
98  "test aPin" );
99 
100  case SCH_SHEET_T: return new SCH_SHEET();
101  case LIB_SHAPE_T: return new LIB_SHAPE( &m_symbol, SHAPE_T::ARC );
102  case LIB_TEXT_T: return new LIB_TEXT( &m_symbol );
103  case LIB_PIN_T: return new LIB_PIN( &m_symbol );
104  case LIB_FIELD_T: return new LIB_FIELD( &m_symbol );
105 
106  case SCHEMATIC_T:
107  case SCH_PIN_T:
108  case LIB_SYMBOL_T:
109  case LIB_ALIAS_T:
110  return nullptr;
111 
112  default:
113  BOOST_FAIL( wxString::Format(
114  "Unhandled type: %d "
115  "(if you created a new type you need to handle it in this switch statement)",
116  aType ) );
117  return nullptr;
118  }
119  }
120 
121  static void CompareItems( EDA_ITEM* aItem, EDA_ITEM* aOriginalItem )
122  {
123  BOOST_CHECK_EQUAL( aItem->GetPosition(), aOriginalItem->GetPosition() );
124  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetTop(),
125  aOriginalItem->GetBoundingBox().GetTop() );
126  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetLeft(),
127  aOriginalItem->GetBoundingBox().GetLeft() );
128  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetBottom(),
129  aOriginalItem->GetBoundingBox().GetBottom() );
130  BOOST_CHECK_EQUAL( aItem->GetBoundingBox().GetRight(),
131  aOriginalItem->GetBoundingBox().GetRight() );
132  }
133 };
134 
135 
136 BOOST_FIXTURE_TEST_SUITE( EeItem, TEST_EE_ITEM_FIXTURE )
137 
138 
140 {
141  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
142  {
143  KICAD_T type = static_cast<KICAD_T>( i );
144 
145  auto item = std::unique_ptr<EDA_ITEM>( Instantiate( type ) );
146 
147  if( item == nullptr )
148  continue;
149 
150  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
151  {
152  IterateOverPositionsAndReferences<EDA_ITEM>(
153  item.get(),
154  []( EDA_ITEM* aOriginalItem, wxPoint aRef )
155  {
156  auto item = std::unique_ptr<EDA_ITEM>( aOriginalItem->Clone() );
157  wxPoint originalPos = item->GetPosition();
158 
159  SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item.get() );
160  LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( item.get() );
161 
162  // Move to a point, then go back.
163  // This has to be an identity transformation.
164 
165  if( schItem != nullptr )
166  {
167  schItem->Move( aRef );
168  BOOST_CHECK_EQUAL( schItem->GetPosition(), originalPos + aRef );
169 
170  schItem->Move( -aRef );
171  }
172 
173  if( libItem != nullptr )
174  {
175  libItem->MoveTo( libItem->GetPosition() + aRef );
176  BOOST_CHECK_EQUAL( libItem->GetPosition(), originalPos + aRef );
177 
178  libItem->MoveTo( libItem->GetPosition() - aRef );
179  }
180 
181  CompareItems( item.get(), aOriginalItem );
182  } );
183  }
184  }
185 }
186 
187 
189 {
190  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
191  {
192  KICAD_T type = static_cast<KICAD_T>( i );
193 
194  auto item = std::unique_ptr<EDA_ITEM>( Instantiate( type ) );
195 
196  if( item == nullptr )
197  continue;
198 
199  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
200  {
201  // Four equivalent 90 degree rotations are an identity.
202 
203  if( item->GetClass() == "SCH_SHEET_PIN" )
204  {
205  auto newItem = std::unique_ptr<EDA_ITEM>( item->Clone() );
206 
207  SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( newItem.get() );
208  LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( newItem.get() );
209 
210  if( schItem != nullptr )
211  {
212  schItem->ClearFieldsAutoplaced();
213  // Only rotating pins around the center of parent sheet works.
214  schItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
215  schItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
216  schItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
217  schItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
218  }
219 
220  if( libItem != nullptr )
221  {
222  libItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
223  libItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
224  libItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
225  libItem->Rotate( m_sheet.GetBodyBoundingBox().GetCenter() );
226  }
227 
228  CompareItems( newItem.get(), item.get() );
229  }
230  else
231  {
232  IterateOverPositionsAndReferences<EDA_ITEM>(
233  item.get(),
234  []( EDA_ITEM* aOriginalItem, wxPoint aRef )
235  {
236  auto item = std::unique_ptr<EDA_ITEM>( aOriginalItem->Clone() );
237 
238  SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item.get() );
239  LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( item.get() );
240 
241  if( schItem != nullptr )
242  {
243  schItem->Rotate( aRef );
244  schItem->Rotate( aRef );
245  schItem->Rotate( aRef );
246  schItem->Rotate( aRef );
247  }
248 
249  if( libItem != nullptr )
250  {
251  libItem->Rotate( aRef );
252  libItem->Rotate( aRef );
253  libItem->Rotate( aRef );
254  libItem->Rotate( aRef );
255  }
256 
257  CompareItems( item.get(), aOriginalItem );
258  } );
259  }
260  }
261  }
262 }
263 
264 
265 BOOST_AUTO_TEST_CASE( MirrorHorizontally )
266 {
267  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
268  {
269  KICAD_T type = static_cast<KICAD_T>( i );
270 
271  auto item = std::unique_ptr<EDA_ITEM>( Instantiate( type ) );
272 
273  if( item == nullptr )
274  continue;
275 
276  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
277  {
278  IterateOverPositionsAndReferences<EDA_ITEM>(
279  item.get(),
280  []( EDA_ITEM* aOriginalItem, wxPoint aRef )
281  {
282  auto item = std::unique_ptr<EDA_ITEM>( aOriginalItem->Clone() );
283 
284  SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item.get() );
285  LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( item.get() );
286 
287  // Two mirrorings are an identity.
288 
289  if( schItem != nullptr )
290  {
291  schItem->ClearFieldsAutoplaced();
292  schItem->MirrorHorizontally( aRef.x );
293  schItem->MirrorHorizontally( aRef.x );
294  }
295 
296  if( libItem != nullptr )
297  {
298  libItem->MirrorHorizontal( aRef );
299  libItem->MirrorHorizontal( aRef );
300  }
301 
302  CompareItems( item.get(), aOriginalItem );
303  } );
304  }
305  }
306 }
307 
308 
309 BOOST_AUTO_TEST_CASE( MirrorVertically )
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<EDA_ITEM>( Instantiate( type ) );
316 
317  if( item == nullptr )
318  continue;
319 
320  BOOST_TEST_CONTEXT( "Class: " << item->GetClass() )
321  {
322  IterateOverPositionsAndReferences<EDA_ITEM>(
323  item.get(),
324  []( EDA_ITEM* aOriginalItem, wxPoint aRef )
325  {
326  auto item = std::unique_ptr<EDA_ITEM>( aOriginalItem->Clone() );
327 
328  SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item.get() );
329  LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( item.get() );
330 
331  // Two mirrorings are an identity.
332 
333  if( schItem != nullptr )
334  {
335  schItem->ClearFieldsAutoplaced();
336  schItem->MirrorVertically( aRef.y );
337  schItem->MirrorVertically( aRef.y );
338  }
339 
340  if( libItem != nullptr )
341  {
342  libItem->MirrorVertical( aRef );
343  libItem->MirrorVertical( aRef );
344  }
345 
346  CompareItems( item.get(), aOriginalItem );
347  } );
348  }
349  }
350 }
351 
352 BOOST_AUTO_TEST_SUITE_END()
Class for a bus to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
constexpr bool IsEeschemaType(const KICAD_T aType)
Definition: typeinfo.h:321
EDA_ITEM * Instantiate(KICAD_T aType)
BOOST_AUTO_TEST_CASE(Move)
Define a symbol library graphical text item.
Definition: lib_text.h:39
int GetTop() const
Definition: eda_rect.h:122
int GetLeft() const
Definition: eda_rect.h:121
Field object used in symbol libraries.
Definition: lib_field.h:59
virtual void MirrorHorizontal(const wxPoint &aCenter)=0
Mirror the draw object along the horizontal (X) axis about aCenter point.
virtual wxPoint GetPosition() const
Definition: eda_item.h:251
Define a library symbol object.
Definition: lib_symbol.h:96
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:83
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
int GetBottom() const
Definition: eda_rect.h:123
std::shared_ptr< ERC_ITEM > m_ercItem
int GetRight() const
Definition: eda_rect.h:120
virtual void Rotate(const wxPoint &aCenter, bool aRotateCCW=true)=0
Rotate the object about aCenter point.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
virtual void MirrorVertical(const wxPoint &aCenter)=0
Mirror the draw object along the MirrorVertical (Y) axis about aCenter point.
#define BOOST_TEST_CONTEXT(A)
wxPoint GetPosition() const override
Definition: sch_sheet.h:379
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:105
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
Schematic symbol object.
Definition: sch_symbol.h:78
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
void SetPosition(const wxPoint &aPosition) override
Definition: sch_sheet.cpp:879
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
constexpr bool IsInstantiableType(const KICAD_T aType)
Definition: typeinfo.h:274
Class for a wire to bus entry.
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:75
Conflicting drivers (labels, etc) on a subgraph.
Definition: erc_settings.h:56
static constexpr int Millimeter2iu(double mm)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:182
static void CompareItems(EDA_ITEM *aItem, EDA_ITEM *aOriginalItem)
virtual void Move(const wxPoint &aMoveVector)=0
Move the item by aMoveVector to a new position.