KiCad PCB EDA Suite
AUTOPLACER Class Reference

Classes

struct  SIDE_AND_COLL
 
struct  SIDE_AND_NPINS
 

Public Types

enum  COLLISION { COLLIDE_NONE, COLLIDE_OBJECTS, COLLIDE_H_WIRES }
 
typedef wxPoint SIDE
 

Public Member Functions

 AUTOPLACER (SCH_COMPONENT *aSymbol, SCH_SCREEN *aScreen)
 
void DoAutoplace (bool aManual)
 Do the actual autoplacement. More...
 

Static Public Attributes

static const SIDE SIDE_TOP
 
static const SIDE SIDE_BOTTOM
 
static const SIDE SIDE_LEFT
 
static const SIDE SIDE_RIGHT
 

Protected Member Functions

wxSize computeFBoxSize (bool aDynamic)
 Compute and return the size of the fields' bounding box. More...
 
SIDE getPinSide (SCH_PIN *aPin)
 Return the side that a pin is on. More...
 
unsigned pinsOnSide (SIDE aSide)
 Count the number of pins on a side of the component. More...
 
void getPossibleCollisions (std::vector< SCH_ITEM * > &aItems)
 Populate a list of all drawing items that may collide with the fields. More...
 
std::vector< SCH_ITEM * > filterCollisions (const EDA_RECT &aRect)
 Filter a list of possible colliders to include only those that actually collide with a given rectangle. More...
 
std::vector< SIDE_AND_NPINSgetPreferredSides ()
 Return a list with the preferred field sides for the component, in decreasing order of preference. More...
 
std::vector< SIDE_AND_COLLgetCollidingSides ()
 Return a list of the sides where a field set would collide with another item. More...
 
SIDE_AND_NPINS chooseSideFiltered (std::vector< SIDE_AND_NPINS > &aSides, const std::vector< SIDE_AND_COLL > &aCollidingSides, COLLISION aCollision, SIDE_AND_NPINS aLastSelection)
 Choose a side for the fields, filtered on only one side collision type. More...
 
SIDE chooseSideForFields (bool aAvoidCollisions)
 Look where a component's pins are to pick a side to put the fields on. More...
 
void justifyField (SCH_FIELD *aField, SIDE aFieldSide)
 Set the justification of a field based on the side it's supposed to be on, taking into account whether the field will be displayed with flipped justification due to mirroring. More...
 
wxPoint fieldBoxPlacement (SIDE aFieldSide)
 Return the position of the field bounding box. More...
 
bool fitFieldsBetweenWires (EDA_RECT *aBox, SIDE aSide)
 Shift a field box up or down a bit to make the fields fit between some wires. More...
 
int fieldHorizPlacement (SCH_FIELD *aField, const EDA_RECT &aFieldBox)
 Place a field horizontally, taking into account the field width and justification. More...
 
int fieldVertPlacement (SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum, bool aDynamic)
 Place a field vertically. More...
 

Private Attributes

SCH_SCREENm_screen
 
SCH_COMPONENTm_symbol
 
std::vector< SCH_FIELD * > m_fields
 
std::vector< SCH_ITEM * > m_colliders
 
EDA_RECT m_symbol_bbox
 
wxSize m_fbox_size
 
bool m_allow_rejustify
 
bool m_align_to_grid
 
bool m_is_power_symbol
 

Detailed Description

Definition at line 95 of file autoplace_fields.cpp.

Member Typedef Documentation

◆ SIDE

typedef wxPoint AUTOPLACER::SIDE

Definition at line 98 of file autoplace_fields.cpp.

Member Enumeration Documentation

◆ COLLISION

Constructor & Destructor Documentation

◆ AUTOPLACER()

AUTOPLACER::AUTOPLACER ( SCH_COMPONENT aSymbol,
SCH_SCREEN aScreen 
)
inline

Definition at line 114 of file autoplace_fields.cpp.

114  :
115  m_screen( aScreen ),
116  m_symbol( aSymbol )
117  {
118  m_symbol->GetFields( m_fields, /* aVisibleOnly */ true );
119 
120  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
121  wxASSERT( cfg );
122 
123  m_allow_rejustify = false;
124  m_align_to_grid = true;
125 
126  if( cfg )
127  {
128  m_allow_rejustify = cfg->m_AutoplaceFields.allow_rejustify;
129  m_align_to_grid = cfg->m_AutoplaceFields.align_to_grid;
130  }
131 
133  m_fbox_size = computeFBoxSize( /* aDynamic */ true );
134 
136 
137  if( aScreen )
139  }
std::vector< SCH_FIELD * > m_fields
bool IsInNetlist() const
EDA_RECT m_symbol_bbox
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:729
SCH_SCREEN * m_screen
std::vector< SCH_ITEM * > m_colliders
EDA_RECT GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the fields.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
wxSize computeFBoxSize(bool aDynamic)
Compute and return the size of the fields' bounding box.
SCH_COMPONENT * m_symbol
void getPossibleCollisions(std::vector< SCH_ITEM * > &aItems)
Populate a list of all drawing items that may collide with the fields.

References computeFBoxSize(), SCH_COMPONENT::GetBodyBoundingBox(), SCH_COMPONENT::GetFields(), getPossibleCollisions(), SCH_COMPONENT::IsInNetlist(), Kiface(), m_align_to_grid, m_allow_rejustify, m_colliders, m_fbox_size, m_fields, m_is_power_symbol, m_symbol, and m_symbol_bbox.

Member Function Documentation

◆ chooseSideFiltered()

SIDE_AND_NPINS AUTOPLACER::chooseSideFiltered ( std::vector< SIDE_AND_NPINS > &  aSides,
const std::vector< SIDE_AND_COLL > &  aCollidingSides,
COLLISION  aCollision,
SIDE_AND_NPINS  aLastSelection 
)
inlineprotected

Choose a side for the fields, filtered on only one side collision type.

Removes the sides matching the filter from the list.

Definition at line 422 of file autoplace_fields.cpp.

426  {
427  SIDE_AND_NPINS sel = aLastSelection;
428 
429  std::vector<SIDE_AND_NPINS>::iterator it = aSides.begin();
430 
431  while( it != aSides.end() )
432  {
433  bool collide = false;
434 
435  for( SIDE_AND_COLL collision : aCollidingSides )
436  {
437  if( collision.side == it->side && collision.collision == aCollision )
438  collide = true;
439  }
440 
441  if( !collide )
442  {
443  ++it;
444  }
445  else
446  {
447  if( it->pins <= sel.pins )
448  {
449  sel.pins = it->pins;
450  sel.side = it->side;
451  }
452 
453  it = aSides.erase( it );
454  }
455  }
456 
457  return sel;
458  }
bool collide(T aObject, U aAnotherObject, int aMinDistance)
collide template method
Definition: shape_index.h:92

References collide(), AUTOPLACER::SIDE_AND_NPINS::pins, and AUTOPLACER::SIDE_AND_NPINS::side.

Referenced by chooseSideForFields().

◆ chooseSideForFields()

SIDE AUTOPLACER::chooseSideForFields ( bool  aAvoidCollisions)
inlineprotected

Look where a component's pins are to pick a side to put the fields on.

Parameters
aAvoidCollisions- if true, pick last the sides where the label will collide with other items.

Definition at line 465 of file autoplace_fields.cpp.

466  {
467  std::vector<SIDE_AND_NPINS> sides = getPreferredSides();
468 
469  std::reverse( sides.begin(), sides.end() );
470  SIDE_AND_NPINS side = { wxPoint( 1, 0 ), UINT_MAX };
471 
472  if( aAvoidCollisions )
473  {
474  std::vector<SIDE_AND_COLL> colliding_sides = getCollidingSides();
475  side = chooseSideFiltered( sides, colliding_sides, COLLIDE_OBJECTS, side );
476  side = chooseSideFiltered( sides, colliding_sides, COLLIDE_H_WIRES, side );
477  }
478 
479  for( SIDE_AND_NPINS& each_side : sides | boost::adaptors::reversed )
480  {
481  if( !each_side.pins ) return each_side.side;
482  }
483 
484  for( SIDE_AND_NPINS& each_side : sides )
485  {
486  if( each_side.pins <= side.pins )
487  {
488  side.pins = each_side.pins;
489  side.side = each_side.side;
490  }
491  }
492 
493  return side.side;
494  }
std::vector< SIDE_AND_NPINS > getPreferredSides()
Return a list with the preferred field sides for the component, in decreasing order of preference.
std::vector< SIDE_AND_COLL > getCollidingSides()
Return a list of the sides where a field set would collide with another item.
SIDE_AND_NPINS chooseSideFiltered(std::vector< SIDE_AND_NPINS > &aSides, const std::vector< SIDE_AND_COLL > &aCollidingSides, COLLISION aCollision, SIDE_AND_NPINS aLastSelection)
Choose a side for the fields, filtered on only one side collision type.

References chooseSideFiltered(), COLLIDE_H_WIRES, COLLIDE_OBJECTS, getCollidingSides(), and getPreferredSides().

Referenced by DoAutoplace().

◆ computeFBoxSize()

wxSize AUTOPLACER::computeFBoxSize ( bool  aDynamic)
inlineprotected

Compute and return the size of the fields' bounding box.

Parameters
aDynamic- if true, use dynamic spacing

Definition at line 187 of file autoplace_fields.cpp.

188  {
189  int max_field_width = 0;
190  int total_height = 0;
191 
192  for( SCH_FIELD* field : m_fields )
193  {
194  if( m_symbol->GetTransform().y1 )
195  field->SetTextAngle( TEXT_ANGLE_VERT );
196  else
197  field->SetTextAngle( TEXT_ANGLE_HORIZ );
198 
199  EDA_RECT bbox = field->GetBoundingBox();
200  int field_width = bbox.GetWidth();
201  int field_height = bbox.GetHeight();
202 
203  max_field_width = std::max( max_field_width, field_width );
204 
205  // Remove interline spacing from field_height for last line.
206  if( field == m_fields[ m_fields.size() - 1 ] )
207  field_height *= 0.62;
208 
209  if( !aDynamic )
210  total_height += WIRE_V_SPACING;
211  else if( m_align_to_grid )
212  total_height += round_n( field_height, Mils2iu( 50 ), true );
213  else
214  total_height += field_height + FIELD_PADDING;
215  }
216 
217  return wxSize( max_field_width, total_height );
218  }
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: eda_text.h:50
Instances are attached to a symbol or sheet and provide a place for the component's value,...
Definition: sch_field.h:50
std::vector< SCH_FIELD * > m_fields
int GetWidth() const
Definition: eda_rect.h:114
#define WIRE_V_SPACING
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
int y1
Definition: transform.h:49
TRANSFORM & GetTransform()
Definition: sch_symbol.h:231
#define FIELD_PADDING
int GetHeight() const
Definition: eda_rect.h:115
SCH_COMPONENT * m_symbol
Handle the component boundary box.
Definition: eda_rect.h:42
#define TEXT_ANGLE_VERT
Definition: eda_text.h:51

References FIELD_PADDING, EDA_RECT::GetHeight(), SCH_COMPONENT::GetTransform(), EDA_RECT::GetWidth(), m_align_to_grid, m_fields, m_symbol, round_n(), TEXT_ANGLE_HORIZ, TEXT_ANGLE_VERT, WIRE_V_SPACING, and TRANSFORM::y1.

Referenced by AUTOPLACER(), and fitFieldsBetweenWires().

◆ DoAutoplace()

void AUTOPLACER::DoAutoplace ( bool  aManual)
inline

Do the actual autoplacement.

Parameters
aManual- if true, use extra heuristics for smarter placement when manually called up.

Definition at line 146 of file autoplace_fields.cpp.

147  {
148  bool force_wire_spacing = false;
149  SIDE field_side = chooseSideForFields( aManual );
150  wxPoint fbox_pos = fieldBoxPlacement( field_side );
151  EDA_RECT field_box( fbox_pos, m_fbox_size );
152 
153  if( aManual )
154  force_wire_spacing = fitFieldsBetweenWires( &field_box, field_side );
155 
156  // Move the fields
157  int last_y_coord = field_box.GetTop();
158 
159  for( unsigned field_idx = 0; field_idx < m_fields.size(); ++field_idx )
160  {
161  SCH_FIELD* field = m_fields[field_idx];
162 
163  if( m_allow_rejustify )
164  justifyField( field, field_side );
165 
166  wxPoint pos( fieldHorizPlacement( field, field_box ),
167  fieldVertPlacement( field, field_box, &last_y_coord, !force_wire_spacing ) );
168 
169  if( m_align_to_grid )
170  {
171  if( abs( field_side.x ) > 0 )
172  pos.x = round_n( pos.x, Mils2iu( 50 ), field_side.x >= 0 );
173 
174  if( abs( field_side.y ) > 0 )
175  pos.y = round_n( pos.y, Mils2iu( 50 ), field_side.y >= 0 );
176  }
177 
178  field->SetPosition( pos );
179  }
180  }
Instances are attached to a symbol or sheet and provide a place for the component's value,...
Definition: sch_field.h:50
std::vector< SCH_FIELD * > m_fields
bool fitFieldsBetweenWires(EDA_RECT *aBox, SIDE aSide)
Shift a field box up or down a bit to make the fields fit between some wires.
wxPoint fieldBoxPlacement(SIDE aFieldSide)
Return the position of the field bounding box.
int fieldHorizPlacement(SCH_FIELD *aField, const EDA_RECT &aFieldBox)
Place a field horizontally, taking into account the field width and justification.
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
int fieldVertPlacement(SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum, bool aDynamic)
Place a field vertically.
SIDE chooseSideForFields(bool aAvoidCollisions)
Look where a component's pins are to pick a side to put the fields on.
Handle the component boundary box.
Definition: eda_rect.h:42
void SetPosition(const wxPoint &aPosition) override
Definition: sch_field.cpp:664
void justifyField(SCH_FIELD *aField, SIDE aFieldSide)
Set the justification of a field based on the side it's supposed to be on, taking into account whethe...

References chooseSideForFields(), fieldBoxPlacement(), fieldHorizPlacement(), fieldVertPlacement(), fitFieldsBetweenWires(), EDA_RECT::GetTop(), justifyField(), m_align_to_grid, m_allow_rejustify, m_fbox_size, m_fields, round_n(), and SCH_FIELD::SetPosition().

Referenced by SCH_COMPONENT::AutoplaceFields().

◆ fieldBoxPlacement()

wxPoint AUTOPLACER::fieldBoxPlacement ( SIDE  aFieldSide)
inlineprotected

Return the position of the field bounding box.

Definition at line 513 of file autoplace_fields.cpp.

514  {
515  wxPoint fbox_center = m_symbol_bbox.Centre();
516  int offs_x = ( m_symbol_bbox.GetWidth() + m_fbox_size.GetWidth() ) / 2;
517  int offs_y = ( m_symbol_bbox.GetHeight() + m_fbox_size.GetHeight() ) / 2;
518 
519  if( aFieldSide.x != 0 )
520  offs_x += HPADDING;
521  else if( aFieldSide.y != 0 )
522  offs_y += VPADDING;
523 
524  fbox_center.x += aFieldSide.x * offs_x;
525  fbox_center.y += aFieldSide.y * offs_y;
526 
527  wxPoint fbox_pos( fbox_center.x - m_fbox_size.GetWidth() / 2,
528  fbox_center.y - m_fbox_size.GetHeight() / 2 );
529 
530  return fbox_pos;
531  }
#define VPADDING
#define HPADDING
int GetWidth() const
Definition: eda_rect.h:114
EDA_RECT m_symbol_bbox
int GetHeight() const
Definition: eda_rect.h:115
wxPoint Centre() const
Definition: eda_rect.h:60

References EDA_RECT::Centre(), EDA_RECT::GetHeight(), EDA_RECT::GetWidth(), HPADDING, m_fbox_size, m_symbol_bbox, and VPADDING.

Referenced by DoAutoplace(), and getCollidingSides().

◆ fieldHorizPlacement()

int AUTOPLACER::fieldHorizPlacement ( SCH_FIELD aField,
const EDA_RECT aFieldBox 
)
inlineprotected

Place a field horizontally, taking into account the field width and justification.

Parameters
aField- the field to place.
aFieldBox- box in which fields will be placed
Returns
Correct field horizontal position

Definition at line 590 of file autoplace_fields.cpp.

591  {
592  int field_hjust;
593  int field_xcoord;
594 
595  if( aField->IsHorizJustifyFlipped() )
596  field_hjust = -aField->GetHorizJustify();
597  else
598  field_hjust = aField->GetHorizJustify();
599 
600  switch( field_hjust )
601  {
603  field_xcoord = aFieldBox.GetLeft();
604  break;
606  field_xcoord = aFieldBox.Centre().x;
607  break;
609  field_xcoord = aFieldBox.GetRight();
610  break;
611  default:
612  wxFAIL_MSG( "Unexpected value for SCH_FIELD::GetHorizJustify()" );
613  field_xcoord = aFieldBox.Centre().x; // Most are centered
614  }
615 
616  return field_xcoord;
617  }
int GetLeft() const
Definition: eda_rect.h:117
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:205
int GetRight() const
Definition: eda_rect.h:116
wxPoint Centre() const
Definition: eda_rect.h:60
bool IsHorizJustifyFlipped() const
Return whether the field will be rendered with the horizontal justification inverted due to rotation ...
Definition: sch_field.cpp:305

References EDA_RECT::Centre(), EDA_TEXT::GetHorizJustify(), EDA_RECT::GetLeft(), EDA_RECT::GetRight(), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, and SCH_FIELD::IsHorizJustifyFlipped().

Referenced by DoAutoplace().

◆ fieldVertPlacement()

int AUTOPLACER::fieldVertPlacement ( SCH_FIELD aField,
const EDA_RECT aFieldBox,
int *  aPosAccum,
bool  aDynamic 
)
inlineprotected

Place a field vertically.

Because field vertical placements accumulate, this takes a pointer to a vertical position accumulator.

Parameters
aField- the field to place.
aFieldBox- box in which fields will be placed.
aPosAccum- pointer to a position accumulator
aDynamic- use dynamic spacing
Returns
Correct field vertical position

Definition at line 630 of file autoplace_fields.cpp.

632  {
633  int field_height;
634  int padding;
635 
636  if( !aDynamic )
637  {
638  field_height = WIRE_V_SPACING / 2;
639  padding = WIRE_V_SPACING / 2;
640  }
641  else if( m_align_to_grid )
642  {
643  field_height = aField->GetBoundingBox().GetHeight();
644  padding = round_n( field_height, Mils2iu( 50 ), true ) - field_height;
645  }
646  else
647  {
648  field_height = aField->GetBoundingBox().GetHeight();
649  padding = FIELD_PADDING;
650  }
651 
652  int placement = *aPosAccum + padding / 2 + field_height / 2;
653 
654  *aPosAccum += padding + field_height;
655 
656  return placement;
657  }
#define WIRE_V_SPACING
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
#define FIELD_PADDING
int GetHeight() const
Definition: eda_rect.h:115
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:263

References FIELD_PADDING, SCH_FIELD::GetBoundingBox(), EDA_RECT::GetHeight(), m_align_to_grid, round_n(), and WIRE_V_SPACING.

Referenced by DoAutoplace().

◆ filterCollisions()

std::vector<SCH_ITEM*> AUTOPLACER::filterCollisions ( const EDA_RECT aRect)
inlineprotected

Filter a list of possible colliders to include only those that actually collide with a given rectangle.

Returns the new vector.

Definition at line 289 of file autoplace_fields.cpp.

290  {
291  std::vector<SCH_ITEM*> filtered;
292 
293  for( SCH_ITEM* item : m_colliders )
294  {
295  EDA_RECT item_box;
296 
297  if( SCH_COMPONENT* item_comp = dynamic_cast<SCH_COMPONENT*>( item ) )
298  item_box = item_comp->GetBodyBoundingBox();
299  else
300  item_box = item->GetBoundingBox();
301 
302  if( item_box.Intersects( aRect ) )
303  filtered.push_back( item );
304  }
305  return filtered;
306  }
std::vector< SCH_ITEM * > m_colliders
Handle the component boundary box.
Definition: eda_rect.h:42
Schematic symbol object.
Definition: sch_symbol.h:78
bool Intersects(const EDA_RECT &aRect) const
Test for a common area between rectangles.
Definition: eda_rect.cpp:150
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197

References EDA_RECT::Intersects(), and m_colliders.

Referenced by fitFieldsBetweenWires(), and getCollidingSides().

◆ fitFieldsBetweenWires()

bool AUTOPLACER::fitFieldsBetweenWires ( EDA_RECT aBox,
SIDE  aSide 
)
inlineprotected

Shift a field box up or down a bit to make the fields fit between some wires.

Returns true if a shift was made.

Definition at line 537 of file autoplace_fields.cpp.

538  {
539  if( aSide != SIDE_TOP && aSide != SIDE_BOTTOM )
540  return false;
541 
542  std::vector<SCH_ITEM*> colliders = filterCollisions( *aBox );
543 
544  if( colliders.empty() )
545  return false;
546 
547  // Find the offset of the wires for proper positioning
548  int offset = 0;
549 
550  for( SCH_ITEM* item : colliders )
551  {
552  SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
553 
554  if( !line )
555  return false;
556 
557  wxPoint start = line->GetStartPoint(), end = line->GetEndPoint();
558 
559  if( start.y != end.y )
560  return false;
561 
562  int this_offset = (3 * WIRE_V_SPACING / 2) - ( start.y % WIRE_V_SPACING );
563 
564  if( offset == 0 )
565  offset = this_offset;
566  else if( offset != this_offset )
567  return false;
568  }
569 
570  // At this point we are recomputing the field box size. Do not
571  // return false after this point.
572  m_fbox_size = computeFBoxSize( /* aDynamic */ false );
573 
574  wxPoint pos = aBox->GetPosition();
575 
576  pos.y = round_n( pos.y, WIRE_V_SPACING, aSide == SIDE_BOTTOM );
577 
578  aBox->SetOrigin( pos );
579  return true;
580  }
wxPoint GetStartPoint() const
Definition: sch_line.h:90
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:126
#define WIRE_V_SPACING
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
std::vector< SCH_ITEM * > filterCollisions(const EDA_RECT &aRect)
Filter a list of possible colliders to include only those that actually collide with a given rectangl...
const wxPoint GetPosition() const
Definition: eda_rect.h:107
wxSize computeFBoxSize(bool aDynamic)
Compute and return the size of the fields' bounding box.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
static const SIDE SIDE_BOTTOM
static const SIDE SIDE_TOP
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197
wxPoint GetEndPoint() const
Definition: sch_line.h:93

References computeFBoxSize(), filterCollisions(), SCH_LINE::GetEndPoint(), EDA_RECT::GetPosition(), SCH_LINE::GetStartPoint(), m_fbox_size, round_n(), EDA_RECT::SetOrigin(), SIDE_BOTTOM, SIDE_TOP, and WIRE_V_SPACING.

Referenced by DoAutoplace().

◆ getCollidingSides()

std::vector<SIDE_AND_COLL> AUTOPLACER::getCollidingSides ( )
inlineprotected

Return a list of the sides where a field set would collide with another item.

Definition at line 379 of file autoplace_fields.cpp.

380  {
381  SIDE sides_init[] = { SIDE_RIGHT, SIDE_TOP, SIDE_LEFT, SIDE_BOTTOM };
382  std::vector<SIDE> sides( sides_init, sides_init + arrayDim( sides_init ) );
383  std::vector<SIDE_AND_COLL> colliding;
384 
385  // Iterate over all sides and find the ones that collide
386  for( SIDE side : sides )
387  {
388  EDA_RECT box( fieldBoxPlacement( side ), m_fbox_size );
389 
390  COLLISION collision = COLLIDE_NONE;
391 
392  for( SCH_ITEM* collider : filterCollisions( box ) )
393  {
394  SCH_LINE* line = dynamic_cast<SCH_LINE*>( collider );
395 
396  if( line && !side.x )
397  {
398  wxPoint start = line->GetStartPoint(), end = line->GetEndPoint();
399 
400  if( start.y == end.y && collision != COLLIDE_OBJECTS )
401  collision = COLLIDE_H_WIRES;
402  else
403  collision = COLLIDE_OBJECTS;
404  }
405  else
406  {
407  collision = COLLIDE_OBJECTS;
408  }
409  }
410 
411  if( collision != COLLIDE_NONE )
412  colliding.push_back( { side, collision } );
413  }
414 
415  return colliding;
416  }
wxPoint GetStartPoint() const
Definition: sch_line.h:90
wxPoint fieldBoxPlacement(SIDE aFieldSide)
Return the position of the field bounding box.
std::vector< SCH_ITEM * > filterCollisions(const EDA_RECT &aRect)
Filter a list of possible colliders to include only those that actually collide with a given rectangl...
static const SIDE SIDE_LEFT
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
static const SIDE SIDE_RIGHT
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
static const SIDE SIDE_BOTTOM
Handle the component boundary box.
Definition: eda_rect.h:42
static const SIDE SIDE_TOP
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197
wxPoint GetEndPoint() const
Definition: sch_line.h:93

References arrayDim(), COLLIDE_H_WIRES, COLLIDE_NONE, COLLIDE_OBJECTS, fieldBoxPlacement(), filterCollisions(), SCH_LINE::GetEndPoint(), SCH_LINE::GetStartPoint(), m_fbox_size, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT, and SIDE_TOP.

Referenced by chooseSideForFields().

◆ getPinSide()

SIDE AUTOPLACER::getPinSide ( SCH_PIN aPin)
inlineprotected

Return the side that a pin is on.

Definition at line 223 of file autoplace_fields.cpp.

224  {
225  int pin_orient = aPin->GetLibPin()->PinDrawOrient( m_symbol->GetTransform() );
226 
227  switch( pin_orient )
228  {
229  case PIN_RIGHT: return SIDE_LEFT;
230  case PIN_LEFT: return SIDE_RIGHT;
231  case PIN_UP: return SIDE_BOTTOM;
232  case PIN_DOWN: return SIDE_TOP;
233  default:
234  wxFAIL_MSG( "Invalid pin orientation" );
235  return SIDE_LEFT;
236  }
237  }
LIB_PIN * GetLibPin() const
Definition: sch_pin.h:58
Definition: lib_pin.h:50
int PinDrawOrient(const TRANSFORM &aTransform) const
Return the pin real orientation (PIN_UP, PIN_DOWN, PIN_RIGHT, PIN_LEFT), according to its orientation...
Definition: lib_pin.cpp:791
static const SIDE SIDE_LEFT
TRANSFORM & GetTransform()
Definition: sch_symbol.h:231
SCH_COMPONENT * m_symbol
static const SIDE SIDE_RIGHT
static const SIDE SIDE_BOTTOM
static const SIDE SIDE_TOP

References SCH_PIN::GetLibPin(), SCH_COMPONENT::GetTransform(), m_symbol, PIN_DOWN, PIN_LEFT, PIN_RIGHT, PIN_UP, LIB_PIN::PinDrawOrient(), SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT, and SIDE_TOP.

Referenced by pinsOnSide().

◆ getPossibleCollisions()

void AUTOPLACER::getPossibleCollisions ( std::vector< SCH_ITEM * > &  aItems)
inlineprotected

Populate a list of all drawing items that may collide with the fields.

That is, all drawing items, including other fields, that are not the current component or its own fields.

Definition at line 263 of file autoplace_fields.cpp.

264  {
265  wxCHECK_RET( m_screen, "getPossibleCollisions() with null m_screen" );
266 
267  for( SCH_ITEM* item : m_screen->Items().Overlapping( m_symbol->GetBoundingBox() ) )
268  {
269  if( SCH_COMPONENT* candidate = dynamic_cast<SCH_COMPONENT*>( item ) )
270  {
271  if( candidate == m_symbol )
272  continue;
273 
274  std::vector<SCH_FIELD*> fields;
275  candidate->GetFields( fields, /* aVisibleOnly */ true );
276 
277  for( SCH_FIELD* field : fields )
278  aItems.push_back( field );
279  }
280 
281  aItems.push_back( item );
282  }
283  }
Instances are attached to a symbol or sheet and provide a place for the component's value,...
Definition: sch_field.h:50
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
SCH_SCREEN * m_screen
SCH_COMPONENT * m_symbol
EE_TYPE Overlapping(const EDA_RECT &aRect) const
Definition: sch_rtree.h:221
EE_RTREE & Items()
Definition: sch_screen.h:103
Schematic symbol object.
Definition: sch_symbol.h:78
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197

References SCH_COMPONENT::GetBoundingBox(), SCH_SCREEN::Items(), m_screen, m_symbol, and EE_RTREE::Overlapping().

Referenced by AUTOPLACER().

◆ getPreferredSides()

std::vector<SIDE_AND_NPINS> AUTOPLACER::getPreferredSides ( )
inlineprotected

Return a list with the preferred field sides for the component, in decreasing order of preference.

Definition at line 312 of file autoplace_fields.cpp.

313  {
314  SIDE_AND_NPINS sides_init[] = {
316  { SIDE_TOP, pinsOnSide( SIDE_TOP ) },
319  };
320  std::vector<SIDE_AND_NPINS> sides( sides_init, sides_init + arrayDim( sides_init ) );
321 
322  int orient = m_symbol->GetOrientation();
323  int orient_angle = orient & 0xff; // enum is a bitmask
324  bool h_mirrored = ( ( orient & CMP_MIRROR_X )
325  && ( orient_angle == CMP_ORIENT_0 || orient_angle == CMP_ORIENT_180 ) );
326  double w = double( m_symbol_bbox.GetWidth() );
327  double h = double( m_symbol_bbox.GetHeight() );
328 
329  // The preferred-sides heuristics are a bit magical. These were determined mostly
330  // by trial and error.
331 
332  if( m_is_power_symbol )
333  {
334  // For power symbols, we generally want the label at the top first.
335  switch( orient_angle )
336  {
337  case CMP_ORIENT_0:
338  std::swap( sides[0], sides[1] );
339  std::swap( sides[1], sides[3] );
340  // TOP, BOTTOM, RIGHT, LEFT
341  break;
342  case CMP_ORIENT_90:
343  std::swap( sides[0], sides[2] );
344  std::swap( sides[1], sides[2] );
345  // LEFT, RIGHT, TOP, BOTTOM
346  break;
347  case CMP_ORIENT_180:
348  std::swap( sides[0], sides[3] );
349  // BOTTOM, TOP, LEFT, RIGHT
350  break;
351  case CMP_ORIENT_270:
352  std::swap( sides[1], sides[2] );
353  // RIGHT, LEFT, TOP, BOTTOM
354  break;
355  }
356  }
357  else
358  {
359  // If the component is horizontally mirrored, swap left and right
360  if( h_mirrored )
361  {
362  std::swap( sides[0], sides[2] );
363  }
364 
365  // If the component is very long or is a power symbol, swap H and V
366  if( w/h > 3.0 )
367  {
368  std::swap( sides[0], sides[1] );
369  std::swap( sides[1], sides[3] );
370  }
371  }
372 
373  return sides;
374  }
int GetOrientation()
Get the display symbol orientation.
int GetWidth() const
Definition: eda_rect.h:114
EDA_RECT m_symbol_bbox
static const SIDE SIDE_LEFT
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
unsigned pinsOnSide(SIDE aSide)
Count the number of pins on a side of the component.
int GetHeight() const
Definition: eda_rect.h:115
SCH_COMPONENT * m_symbol
static const SIDE SIDE_RIGHT
static const SIDE SIDE_BOTTOM
static const SIDE SIDE_TOP

References arrayDim(), CMP_MIRROR_X, CMP_ORIENT_0, CMP_ORIENT_180, CMP_ORIENT_270, CMP_ORIENT_90, EDA_RECT::GetHeight(), SCH_COMPONENT::GetOrientation(), EDA_RECT::GetWidth(), m_is_power_symbol, m_symbol, m_symbol_bbox, pinsOnSide(), SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT, and SIDE_TOP.

Referenced by chooseSideForFields().

◆ justifyField()

void AUTOPLACER::justifyField ( SCH_FIELD aField,
SIDE  aFieldSide 
)
inlineprotected

Set the justification of a field based on the side it's supposed to be on, taking into account whether the field will be displayed with flipped justification due to mirroring.

Definition at line 501 of file autoplace_fields.cpp.

502  {
503  // Justification is set twice to allow IsHorizJustifyFlipped() to work correctly.
504  aField->SetHorizJustify( TO_HJUSTIFY( -aFieldSide.x ) );
505  aField->SetHorizJustify( TO_HJUSTIFY( -aFieldSide.x
506  * ( aField->IsHorizJustifyFlipped() ? -1 : 1 ) ) );
508  }
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
EDA_TEXT_HJUSTIFY_T TO_HJUSTIFY(int x)
Convert an integer to a horizontal justification; neg=L zero=C pos=R.
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
bool IsHorizJustifyFlipped() const
Return whether the field will be rendered with the horizontal justification inverted due to rotation ...
Definition: sch_field.cpp:305

References GR_TEXT_VJUSTIFY_CENTER, SCH_FIELD::IsHorizJustifyFlipped(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetVertJustify(), and TO_HJUSTIFY().

Referenced by DoAutoplace().

◆ pinsOnSide()

unsigned AUTOPLACER::pinsOnSide ( SIDE  aSide)
inlineprotected

Count the number of pins on a side of the component.

Definition at line 242 of file autoplace_fields.cpp.

243  {
244  unsigned pin_count = 0;
245 
246  for( SCH_PIN* each_pin : m_symbol->GetPins() )
247  {
248  if( !each_pin->IsVisible() && !m_is_power_symbol )
249  continue;
250 
251  if( getPinSide( each_pin ) == aSide )
252  ++pin_count;
253  }
254 
255  return pin_count;
256  }
SIDE getPinSide(SCH_PIN *aPin)
Return the side that a pin is on.
SCH_COMPONENT * m_symbol
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
Definition: sch_symbol.cpp:884

References SCH_COMPONENT::GetPins(), getPinSide(), m_is_power_symbol, and m_symbol.

Referenced by getPreferredSides().

Member Data Documentation

◆ m_align_to_grid

bool AUTOPLACER::m_align_to_grid
private

Definition at line 667 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), computeFBoxSize(), DoAutoplace(), and fieldVertPlacement().

◆ m_allow_rejustify

bool AUTOPLACER::m_allow_rejustify
private

Definition at line 666 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), and DoAutoplace().

◆ m_colliders

std::vector<SCH_ITEM*> AUTOPLACER::m_colliders
private

Definition at line 663 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), and filterCollisions().

◆ m_fbox_size

wxSize AUTOPLACER::m_fbox_size
private

◆ m_fields

std::vector<SCH_FIELD*> AUTOPLACER::m_fields
private

Definition at line 662 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), computeFBoxSize(), and DoAutoplace().

◆ m_is_power_symbol

bool AUTOPLACER::m_is_power_symbol
private

Definition at line 668 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), getPreferredSides(), and pinsOnSide().

◆ m_screen

SCH_SCREEN* AUTOPLACER::m_screen
private

Definition at line 660 of file autoplace_fields.cpp.

Referenced by getPossibleCollisions().

◆ m_symbol

SCH_COMPONENT* AUTOPLACER::m_symbol
private

◆ m_symbol_bbox

EDA_RECT AUTOPLACER::m_symbol_bbox
private

Definition at line 664 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), fieldBoxPlacement(), and getPreferredSides().

◆ SIDE_BOTTOM

const AUTOPLACER::SIDE AUTOPLACER::SIDE_BOTTOM
static

◆ SIDE_LEFT

const AUTOPLACER::SIDE AUTOPLACER::SIDE_LEFT
static

Definition at line 99 of file autoplace_fields.cpp.

Referenced by getCollidingSides(), getPinSide(), and getPreferredSides().

◆ SIDE_RIGHT

const AUTOPLACER::SIDE AUTOPLACER::SIDE_RIGHT
static

Definition at line 99 of file autoplace_fields.cpp.

Referenced by getCollidingSides(), getPinSide(), and getPreferredSides().

◆ SIDE_TOP

const AUTOPLACER::SIDE AUTOPLACER::SIDE_TOP
static

The documentation for this class was generated from the following file: