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 *aComponent, 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 get_pin_side (LIB_PIN *aPin)
 Return the side that a pin is on. More...
 
unsigned pins_on_side (SIDE aSide)
 Count the number of pins on a side of the component. More...
 
void get_possible_colliders (std::vector< SCH_ITEM * > &aItems)
 Populate a list of all drawing items that may collide with the fields. More...
 
std::vector< SCH_ITEM * > filtered_colliders (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_NPINSget_preferred_sides ()
 Return a list with the preferred field sides for the component, in decreasing order of preference. More...
 
std::vector< SIDE_AND_COLLget_colliding_sides ()
 Return a list of the sides where a field set would collide with another item. More...
 
SIDE_AND_NPINS choose_side_filtered (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 choose_side_for_fields (bool aAvoidCollisions)
 Look where a component's pins are to pick a side to put the fields on. More...
 
void justify_field (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 field_box_placement (SIDE aFieldSide)
 Return the position of the field bounding box. More...
 
bool fit_fields_between_wires (EDA_RECT *aBox, SIDE aSide)
 Shift a field box up or down a bit to make the fields fit between some wires. More...
 
int field_horiz_placement (SCH_FIELD *aField, const EDA_RECT &aFieldBox)
 Place a field horizontally, taking into account the field width and justification. More...
 
int field_vert_placement (SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum, bool aDynamic)
 Place a field vertically. More...
 
int get_field_padding ()
 Return the desired padding between fields. More...
 

Private Attributes

SCH_SCREENm_screen
 
SCH_COMPONENTm_component
 
std::vector< SCH_FIELD * > m_fields
 
std::vector< SCH_ITEM * > m_colliders
 
EDA_RECT m_comp_bbox
 
wxSize m_fbox_size
 
bool m_allow_rejustify
 
bool m_align_to_grid
 
bool m_power_symbol
 

Detailed Description

Definition at line 97 of file eeschema/autoplace_fields.cpp.

Member Typedef Documentation

◆ SIDE

Definition at line 109 of file eeschema/autoplace_fields.cpp.

Member Enumeration Documentation

◆ COLLISION

Constructor & Destructor Documentation

◆ AUTOPLACER()

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

Definition at line 126 of file eeschema/autoplace_fields.cpp.

126  :
127  m_screen( aScreen ), m_component( aComponent )
128  {
129  m_component->GetFields( m_fields, /* aVisibleOnly */ true );
130 
131  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
132  wxASSERT( cfg );
133 
134  m_allow_rejustify = false;
135  m_align_to_grid = true;
136 
137  if( cfg )
138  {
139  m_allow_rejustify = cfg->m_AutoplaceFields.allow_rejustify;
140  m_align_to_grid = cfg->m_AutoplaceFields.align_to_grid;
141  }
142 
144  m_fbox_size = ComputeFBoxSize( /* aDynamic */ true );
145 
147 
148  if( aScreen )
150  }
wxSize ComputeFBoxSize(bool aDynamic)
Compute and return the size of the fields' bounding box.
std::vector< SCH_FIELD * > m_fields
SCH_COMPONENT * m_component
bool IsInNetlist() const
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
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.
void get_possible_colliders(std::vector< SCH_ITEM * > &aItems)
Populate a list of all drawing items that may collide with the fields.

References ComputeFBoxSize(), get_possible_colliders(), SCH_COMPONENT::GetBodyBoundingBox(), SCH_COMPONENT::GetFields(), SCH_COMPONENT::IsInNetlist(), Kiface(), m_align_to_grid, m_allow_rejustify, m_colliders, m_comp_bbox, m_component, m_fbox_size, m_fields, and m_power_symbol.

Member Function Documentation

◆ choose_side_filtered()

SIDE_AND_NPINS AUTOPLACER::choose_side_filtered ( 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 433 of file eeschema/autoplace_fields.cpp.

436  {
437  SIDE_AND_NPINS sel = aLastSelection;
438 
439  std::vector<SIDE_AND_NPINS>::iterator it = aSides.begin();
440  while( it != aSides.end() )
441  {
442  bool collide = false;
443  for( SIDE_AND_COLL collision : aCollidingSides )
444  {
445  if( collision.side == it->side && collision.collision == aCollision )
446  collide = true;
447  }
448  if( !collide )
449  ++it;
450  else
451  {
452  if( it->pins <= sel.pins )
453  {
454  sel.pins = it->pins;
455  sel.side = it->side;
456  }
457  it = aSides.erase( it );
458  }
459  }
460  return sel;
461  }
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 choose_side_for_fields().

◆ choose_side_for_fields()

SIDE AUTOPLACER::choose_side_for_fields ( 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 469 of file eeschema/autoplace_fields.cpp.

470  {
471  std::vector<SIDE_AND_NPINS> sides = get_preferred_sides();
472 
473  std::reverse( sides.begin(), sides.end() );
474  SIDE_AND_NPINS side = { wxPoint( 1, 0 ), UINT_MAX };
475 
476  if( aAvoidCollisions )
477  {
478  std::vector<SIDE_AND_COLL> colliding_sides = get_colliding_sides();
479  side = choose_side_filtered( sides, colliding_sides, COLLIDE_OBJECTS, side );
480  side = choose_side_filtered( sides, colliding_sides, COLLIDE_H_WIRES, side );
481  }
482 
483  for( SIDE_AND_NPINS& each_side : sides | boost::adaptors::reversed )
484  {
485  if( !each_side.pins ) return each_side.side;
486  }
487 
488  for( SIDE_AND_NPINS& each_side : sides )
489  {
490  if( each_side.pins <= side.pins )
491  {
492  side.pins = each_side.pins;
493  side.side = each_side.side;
494  }
495  }
496 
497  return side.side;
498  }
std::vector< SIDE_AND_COLL > get_colliding_sides()
Return a list of the sides where a field set would collide with another item.
SIDE_AND_NPINS choose_side_filtered(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.
std::vector< SIDE_AND_NPINS > get_preferred_sides()
Return a list with the preferred field sides for the component, in decreasing order of preference.

References choose_side_filtered(), COLLIDE_H_WIRES, COLLIDE_OBJECTS, get_colliding_sides(), and get_preferred_sides().

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 197 of file eeschema/autoplace_fields.cpp.

198  {
199  int max_field_width = 0;
200  int total_height = 0;
201 
202  for( SCH_FIELD* field : m_fields )
203  {
204  int field_width;
205  int field_height;
206 
207  if( m_component->GetTransform().y1 )
208  {
209  field->SetTextAngle( TEXT_ANGLE_VERT );
210  }
211  else
212  {
213  field->SetTextAngle( TEXT_ANGLE_HORIZ );
214  }
215 
216  field_width = field->GetBoundingBox().GetWidth();
217  field_height = field->GetBoundingBox().GetHeight();
218 
219  max_field_width = std::max( max_field_width, field_width );
220 
221  if( aDynamic )
222  total_height += field_height + get_field_padding();
223  else
224  total_height += WIRE_V_SPACING;
225 
226  }
227 
228  return wxSize( max_field_width, total_height );
229  }
#define TEXT_ANGLE_HORIZ
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
std::vector< SCH_FIELD * > m_fields
#define TEXT_ANGLE_VERT
#define WIRE_V_SPACING
SCH_COMPONENT * m_component
int y1
Definition: transform.h:49
TRANSFORM & GetTransform() const
int get_field_padding()
Return the desired padding between fields.

References get_field_padding(), SCH_COMPONENT::GetTransform(), m_component, m_fields, TEXT_ANGLE_HORIZ, TEXT_ANGLE_VERT, WIRE_V_SPACING, and TRANSFORM::y1.

Referenced by AUTOPLACER(), and fit_fields_between_wires().

◆ 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 158 of file eeschema/autoplace_fields.cpp.

159  {
160  bool force_wire_spacing = false;
161  SIDE field_side = choose_side_for_fields( aManual );
162  wxPoint fbox_pos = field_box_placement( field_side );
163  EDA_RECT field_box( fbox_pos, m_fbox_size );
164 
165  if( aManual )
166  force_wire_spacing = fit_fields_between_wires( &field_box, field_side );
167 
168  // Move the fields
169  int last_y_coord = field_box.GetTop();
170  for( unsigned field_idx = 0; field_idx < m_fields.size(); ++field_idx )
171  {
172  SCH_FIELD* field = m_fields[field_idx];
173 
174  if( m_allow_rejustify )
175  justify_field( field, field_side );
176 
177  wxPoint pos(
178  field_horiz_placement( field, field_box ),
179  field_vert_placement( field, field_box, &last_y_coord, !force_wire_spacing ) );
180 
181  if( m_align_to_grid )
182  {
183  pos.x = round_n( pos.x, Mils2iu( 50 ), field_side.x >= 0 );
184  pos.y = round_n( pos.y, Mils2iu( 50 ), field_side.y == 1 );
185  }
186 
187  field->SetPosition( pos );
188  }
189  }
void justify_field(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...
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
std::vector< SCH_FIELD * > m_fields
wxPoint field_box_placement(SIDE aFieldSide)
Return the position of the field bounding box.
bool fit_fields_between_wires(EDA_RECT *aBox, SIDE aSide)
Shift a field box up or down a bit to make the fields fit between some wires.
int field_horiz_placement(SCH_FIELD *aField, const EDA_RECT &aFieldBox)
Place a field horizontally, taking into account the field width and justification.
int field_vert_placement(SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum, bool aDynamic)
Place a field vertically.
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
SIDE choose_side_for_fields(bool aAvoidCollisions)
Look where a component's pins are to pick a side to put the fields on.
void SetPosition(const wxPoint &aPosition) override
Function SetPosition set the schematic item position to aPosition.
Definition: sch_field.cpp:558

References choose_side_for_fields(), field_box_placement(), field_horiz_placement(), field_vert_placement(), fit_fields_between_wires(), EDA_RECT::GetTop(), justify_field(), m_align_to_grid, m_allow_rejustify, m_fbox_size, m_fields, round_n(), SCH_FIELD::SetPosition(), wxPoint::x, and wxPoint::y.

Referenced by SCH_COMPONENT::AutoplaceFields().

◆ field_box_placement()

wxPoint AUTOPLACER::field_box_placement ( SIDE  aFieldSide)
inlineprotected

Return the position of the field bounding box.

Definition at line 519 of file eeschema/autoplace_fields.cpp.

520  {
521  wxPoint fbox_center = m_comp_bbox.Centre();
522  int offs_x = ( m_comp_bbox.GetWidth() + m_fbox_size.GetWidth() ) / 2 + HPADDING;
523  int offs_y = ( m_comp_bbox.GetHeight() + m_fbox_size.GetHeight() ) / 2 + VPADDING;
524 
525  fbox_center.x += aFieldSide.x * offs_x;
526  fbox_center.y += aFieldSide.y * offs_y;
527 
528  wxPoint fbox_pos(
529  fbox_center.x - m_fbox_size.GetWidth() / 2,
530  fbox_center.y - m_fbox_size.GetHeight() / 2 );
531 
532  return fbox_pos;
533  }
#define VPADDING
int GetWidth() const
Definition: eda_rect.h:119
#define HPADDING
int GetHeight() const
Definition: eda_rect.h:120
wxPoint Centre() const
Definition: eda_rect.h:62

References EDA_RECT::Centre(), EDA_RECT::GetHeight(), EDA_RECT::GetWidth(), HPADDING, m_comp_bbox, m_fbox_size, VPADDING, wxPoint::x, and wxPoint::y.

Referenced by DoAutoplace(), and get_colliding_sides().

◆ field_horiz_placement()

int AUTOPLACER::field_horiz_placement ( 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 599 of file eeschema/autoplace_fields.cpp.

600  {
601  int field_hjust;
602  int field_xcoord;
603 
604  if( aField->IsHorizJustifyFlipped() )
605  field_hjust = -aField->GetHorizJustify();
606  else
607  field_hjust = aField->GetHorizJustify();
608 
609  switch( field_hjust )
610  {
612  field_xcoord = aFieldBox.GetLeft();
613  break;
615  field_xcoord = aFieldBox.Centre().x;
616  break;
618  field_xcoord = aFieldBox.GetRight();
619  break;
620  default:
621  wxFAIL_MSG( "Unexpected value for SCH_FIELD::GetHorizJustify()" );
622  field_xcoord = aFieldBox.Centre().x; // Most are centered
623  }
624 
625  return field_xcoord;
626  }
int GetLeft() const
Definition: eda_rect.h:122
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:198
int GetRight() const
Definition: eda_rect.h:121
wxPoint Centre() const
Definition: eda_rect.h:62
bool IsHorizJustifyFlipped() const
Function IsHorizJustifyFlipped Returns whether the field will be rendered with the horizontal justifi...
Definition: sch_field.cpp:276

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, SCH_FIELD::IsHorizJustifyFlipped(), and wxPoint::x.

Referenced by DoAutoplace().

◆ field_vert_placement()

int AUTOPLACER::field_vert_placement ( 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 639 of file eeschema/autoplace_fields.cpp.

641  {
642  int field_height;
643  int padding;
644 
645  if( aDynamic )
646  {
647  field_height = aField->GetBoundingBox().GetHeight();
648 
649  padding = get_field_padding();
650  }
651  else
652  {
653  field_height = WIRE_V_SPACING / 2;
654  padding = WIRE_V_SPACING / 2;
655  }
656 
657  int placement = *aPosAccum + padding / 2 + field_height / 2;
658 
659  *aPosAccum += padding + field_height;
660 
661  return placement;
662  }
#define WIRE_V_SPACING
int GetHeight() const
Definition: eda_rect.h:120
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: sch_field.cpp:234
int get_field_padding()
Return the desired padding between fields.

References get_field_padding(), SCH_FIELD::GetBoundingBox(), EDA_RECT::GetHeight(), and WIRE_V_SPACING.

Referenced by DoAutoplace().

◆ filtered_colliders()

std::vector<SCH_ITEM*> AUTOPLACER::filtered_colliders ( 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 304 of file eeschema/autoplace_fields.cpp.

305  {
306  std::vector<SCH_ITEM*> filtered;
307  for( SCH_ITEM* item : m_colliders )
308  {
309  EDA_RECT item_box;
310  if( SCH_COMPONENT* item_comp = dynamic_cast<SCH_COMPONENT*>( item ) )
311  item_box = item_comp->GetBodyBoundingBox();
312  else
313  item_box = item->GetBoundingBox();
314 
315  if( item_box.Intersects( aRect ) )
316  filtered.push_back( item );
317  }
318  return filtered;
319  }
std::vector< SCH_ITEM * > m_colliders
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Schematic symbol object.
Definition: sch_component.h:88
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:151

References EDA_RECT::Intersects(), and m_colliders.

Referenced by fit_fields_between_wires(), and get_colliding_sides().

◆ fit_fields_between_wires()

bool AUTOPLACER::fit_fields_between_wires ( 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 540 of file eeschema/autoplace_fields.cpp.

541  {
542  if( aSide != SIDE_TOP && aSide != SIDE_BOTTOM )
543  return false;
544 
545  std::vector<SCH_ITEM*> colliders = filtered_colliders( *aBox );
546  if( colliders.empty() )
547  return false;
548 
549  // Find the offset of the wires for proper positioning
550  int offset = 0;
551 
552  for( SCH_ITEM* item : colliders )
553  {
554  SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
555  if( !line )
556  return false;
557  wxPoint start = line->GetStartPoint(), end = line->GetEndPoint();
558  if( start.y != end.y )
559  return false;
560 
561  int this_offset = (3 * WIRE_V_SPACING / 2) - ( start.y % WIRE_V_SPACING );
562  if( offset == 0 )
563  offset = this_offset;
564  else if( offset != this_offset )
565  return false;
566  }
567 
568  // At this point we are recomputing the field box size. Do not
569  // return false after this point.
570  m_fbox_size = ComputeFBoxSize( /* aDynamic */ false );
571 
572  wxPoint pos = aBox->GetPosition();
573 
574  // Remove the existing padding to get a bit more space to work with
575  if( aSide == SIDE_BOTTOM )
576  {
578  }
579  else
580  {
582  }
583 
584  pos.y = round_n( pos.y, WIRE_V_SPACING, aSide == SIDE_BOTTOM );
585 
586  aBox->SetOrigin( pos );
587  return true;
588  }
wxSize ComputeFBoxSize(bool aDynamic)
Compute and return the size of the fields' bounding box.
wxPoint GetStartPoint() const
Definition: sch_line.h:97
int GetTop() const
Definition: eda_rect.h:123
#define WIRE_V_SPACING
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:131
int GetBottom() const
Definition: eda_rect.h:124
const wxPoint GetPosition() const
Definition: eda_rect.h:115
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:38
static const SIDE SIDE_BOTTOM
int get_field_padding()
Return the desired padding between fields.
static const SIDE SIDE_TOP
SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:151
std::vector< SCH_ITEM * > filtered_colliders(const EDA_RECT &aRect)
Filter a list of possible colliders to include only those that actually collide with a given rectangl...
wxPoint GetEndPoint() const
Definition: sch_line.h:100

References ComputeFBoxSize(), filtered_colliders(), get_field_padding(), EDA_RECT::GetBottom(), SCH_LINE::GetEndPoint(), EDA_RECT::GetPosition(), SCH_LINE::GetStartPoint(), EDA_RECT::GetTop(), m_comp_bbox, m_fbox_size, round_n(), EDA_RECT::SetOrigin(), SIDE_BOTTOM, SIDE_TOP, WIRE_V_SPACING, and wxPoint::y.

Referenced by DoAutoplace().

◆ get_colliding_sides()

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

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

Definition at line 394 of file eeschema/autoplace_fields.cpp.

395  {
396  SIDE sides_init[] = { SIDE_RIGHT, SIDE_TOP, SIDE_LEFT, SIDE_BOTTOM };
397  std::vector<SIDE> sides( sides_init, sides_init + arrayDim( sides_init ) );
398  std::vector<SIDE_AND_COLL> colliding;
399 
400  // Iterate over all sides and find the ones that collide
401  for( SIDE side : sides )
402  {
403  EDA_RECT box( field_box_placement( side ), m_fbox_size );
404 
405  COLLISION collision = COLLIDE_NONE;
406  for( SCH_ITEM* collider : filtered_colliders( box ) )
407  {
408  SCH_LINE* line = dynamic_cast<SCH_LINE*>( collider );
409  if( line && !side.x )
410  {
411  wxPoint start = line->GetStartPoint(), end = line->GetEndPoint();
412  if( start.y == end.y && collision != COLLIDE_OBJECTS )
413  collision = COLLIDE_H_WIRES;
414  else
415  collision = COLLIDE_OBJECTS;
416  }
417  else
418  collision = COLLIDE_OBJECTS;
419  }
420 
421  if( collision != COLLIDE_NONE )
422  colliding.push_back( { side, collision } );
423  }
424 
425  return colliding;
426  }
wxPoint GetStartPoint() const
Definition: sch_line.h:97
wxPoint field_box_placement(SIDE aFieldSide)
Return the position of the field bounding box.
static const SIDE SIDE_LEFT
static const SIDE SIDE_RIGHT
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:38
static const SIDE SIDE_BOTTOM
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static const SIDE SIDE_TOP
SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:151
std::vector< SCH_ITEM * > filtered_colliders(const EDA_RECT &aRect)
Filter a list of possible colliders to include only those that actually collide with a given rectangl...
wxPoint GetEndPoint() const
Definition: sch_line.h:100

References arrayDim(), COLLIDE_H_WIRES, COLLIDE_NONE, COLLIDE_OBJECTS, field_box_placement(), filtered_colliders(), SCH_LINE::GetEndPoint(), SCH_LINE::GetStartPoint(), m_fbox_size, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT, SIDE_TOP, and wxPoint::y.

Referenced by choose_side_for_fields().

◆ get_field_padding()

int AUTOPLACER::get_field_padding ( )
inlineprotected

Return the desired padding between fields.

Definition at line 667 of file eeschema/autoplace_fields.cpp.

668  {
669  if( m_align_to_grid )
670  return FIELD_PADDING_ALIGNED;
671  else
672  return FIELD_PADDING;
673  }
#define FIELD_PADDING
#define FIELD_PADDING_ALIGNED

References FIELD_PADDING, FIELD_PADDING_ALIGNED, and m_align_to_grid.

Referenced by ComputeFBoxSize(), field_vert_placement(), and fit_fields_between_wires().

◆ get_pin_side()

SIDE AUTOPLACER::get_pin_side ( LIB_PIN aPin)
inlineprotected

Return the side that a pin is on.

Definition at line 235 of file eeschema/autoplace_fields.cpp.

236  {
237  int pin_orient = aPin->PinDrawOrient( m_component->GetTransform() );
238  switch( pin_orient )
239  {
240  case PIN_RIGHT: return SIDE_LEFT;
241  case PIN_LEFT: return SIDE_RIGHT;
242  case PIN_UP: return SIDE_BOTTOM;
243  case PIN_DOWN: return SIDE_TOP;
244  default:
245  wxFAIL_MSG( "Invalid pin orientation" );
246  return SIDE_LEFT;
247  }
248  }
SCH_COMPONENT * m_component
Definition: lib_pin.h:58
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:1232
static const SIDE SIDE_LEFT
TRANSFORM & GetTransform() const
static const SIDE SIDE_RIGHT
static const SIDE SIDE_BOTTOM
static const SIDE SIDE_TOP

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

Referenced by pins_on_side().

◆ get_possible_colliders()

void AUTOPLACER::get_possible_colliders ( 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 278 of file eeschema/autoplace_fields.cpp.

279  {
280  wxCHECK_RET( m_screen, "get_possible_colliders() with null m_screen" );
281 
282  for( auto item : m_screen->Items().Overlapping( m_component->GetBoundingBox() ) )
283  {
284  if( SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( item ) )
285  {
286  if( comp == m_component )
287  continue;
288 
289  std::vector<SCH_FIELD*> fields;
290  comp->GetFields( fields, /* aVisibleOnly */ true );
291  for( SCH_FIELD* field : fields )
292  aItems.push_back( field );
293  }
294 
295  aItems.push_back( item );
296  }
297  }
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
EE_TYPE Overlapping(const EDA_RECT &aRect)
Definition: sch_rtree.h:224
SCH_COMPONENT * m_component
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
EE_RTREE & Items()
Definition: sch_screen.h:162
Schematic symbol object.
Definition: sch_component.h:88

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

Referenced by AUTOPLACER().

◆ get_preferred_sides()

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

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

Definition at line 326 of file eeschema/autoplace_fields.cpp.

327  {
328  SIDE_AND_NPINS sides_init[] = {
333  };
334  std::vector<SIDE_AND_NPINS> sides( sides_init, sides_init + arrayDim( sides_init ) );
335 
336  int orient = m_component->GetOrientation();
337  int orient_angle = orient & 0xff; // enum is a bitmask
338  bool h_mirrored = ( ( orient & CMP_MIRROR_X )
339  && ( orient_angle == CMP_ORIENT_0 || orient_angle == CMP_ORIENT_180 ) );
340  double w = double( m_comp_bbox.GetWidth() );
341  double h = double( m_comp_bbox.GetHeight() );
342 
343  // The preferred-sides heuristics are a bit magical. These were determined mostly
344  // by trial and error.
345 
346  if( m_power_symbol )
347  {
348  // For power symbols, we generally want the label at the top first.
349  switch( orient_angle )
350  {
351  case CMP_ORIENT_0:
352  std::swap( sides[0], sides[1] );
353  std::swap( sides[1], sides[3] );
354  // TOP, BOTTOM, RIGHT, LEFT
355  break;
356  case CMP_ORIENT_90:
357  std::swap( sides[0], sides[2] );
358  std::swap( sides[1], sides[2] );
359  // LEFT, RIGHT, TOP, BOTTOM
360  break;
361  case CMP_ORIENT_180:
362  std::swap( sides[0], sides[3] );
363  // BOTTOM, TOP, LEFT, RIGHT
364  break;
365  case CMP_ORIENT_270:
366  std::swap( sides[1], sides[2] );
367  // RIGHT, LEFT, TOP, BOTTOM
368  break;
369  }
370  }
371  else
372  {
373  // If the component is horizontally mirrored, swap left and right
374  if( h_mirrored )
375  {
376  std::swap( sides[0], sides[2] );
377  }
378 
379  // If the component is very long or is a power symbol, swap H and V
380  if( w/h > 3.0 )
381  {
382  std::swap( sides[0], sides[1] );
383  std::swap( sides[1], sides[3] );
384  }
385  }
386 
387  return sides;
388  }
unsigned pins_on_side(SIDE aSide)
Count the number of pins on a side of the component.
int GetOrientation()
Get the display symbol orientation.
SCH_COMPONENT * m_component
int GetWidth() const
Definition: eda_rect.h:119
static const SIDE SIDE_LEFT
int GetHeight() const
Definition: eda_rect.h:120
static const SIDE SIDE_RIGHT
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
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_comp_bbox, m_component, m_power_symbol, pins_on_side(), SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT, and SIDE_TOP.

Referenced by choose_side_for_fields().

◆ justify_field()

void AUTOPLACER::justify_field ( 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 506 of file eeschema/autoplace_fields.cpp.

507  {
508  // Justification is set twice to allow IsHorizJustifyFlipped() to work correctly.
509  aField->SetHorizJustify( TO_HJUSTIFY( -aFieldSide.x ) );
510  aField->SetHorizJustify( TO_HJUSTIFY( -aFieldSide.x *
511  ( aField->IsHorizJustifyFlipped() ? -1 : 1 ) ) );
513  }
EDA_TEXT_HJUSTIFY_T TO_HJUSTIFY(int x)
Convert an integer to a horizontal justification; neg=L zero=C pos=R.
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:202
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
bool IsHorizJustifyFlipped() const
Function IsHorizJustifyFlipped Returns whether the field will be rendered with the horizontal justifi...
Definition: sch_field.cpp:276

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

Referenced by DoAutoplace().

◆ pins_on_side()

unsigned AUTOPLACER::pins_on_side ( SIDE  aSide)
inlineprotected

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

Definition at line 254 of file eeschema/autoplace_fields.cpp.

255  {
256  unsigned pin_count = 0;
257 
258  std::vector<LIB_PIN*> pins;
259  m_component->GetPins( pins );
260 
261  for( LIB_PIN* each_pin : pins )
262  {
263  if( !each_pin->IsVisible() && !m_power_symbol )
264  continue;
265  if( get_pin_side( each_pin ) == aSide )
266  ++pin_count;
267  }
268 
269  return pin_count;
270  }
SCH_COMPONENT * m_component
SIDE get_pin_side(LIB_PIN *aPin)
Return the side that a pin is on.
void GetPins(std::vector< LIB_PIN * > &aPinsList)
Populate a vector with all the pins from the library object.

References get_pin_side(), SCH_COMPONENT::GetPins(), m_component, and m_power_symbol.

Referenced by get_preferred_sides().

Member Data Documentation

◆ m_align_to_grid

bool AUTOPLACER::m_align_to_grid
private

Definition at line 105 of file eeschema/autoplace_fields.cpp.

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

◆ m_allow_rejustify

bool AUTOPLACER::m_allow_rejustify
private

Definition at line 105 of file eeschema/autoplace_fields.cpp.

Referenced by AUTOPLACER(), and DoAutoplace().

◆ m_colliders

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

Definition at line 102 of file eeschema/autoplace_fields.cpp.

Referenced by AUTOPLACER(), and filtered_colliders().

◆ m_comp_bbox

EDA_RECT AUTOPLACER::m_comp_bbox
private

◆ m_component

◆ m_fbox_size

wxSize AUTOPLACER::m_fbox_size
private

◆ m_fields

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

Definition at line 101 of file eeschema/autoplace_fields.cpp.

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

◆ m_power_symbol

bool AUTOPLACER::m_power_symbol
private

Definition at line 106 of file eeschema/autoplace_fields.cpp.

Referenced by AUTOPLACER(), get_preferred_sides(), and pins_on_side().

◆ m_screen

SCH_SCREEN* AUTOPLACER::m_screen
private

Definition at line 99 of file eeschema/autoplace_fields.cpp.

Referenced by get_possible_colliders().

◆ SIDE_BOTTOM

const AUTOPLACER::SIDE AUTOPLACER::SIDE_BOTTOM
static

◆ SIDE_LEFT

const AUTOPLACER::SIDE AUTOPLACER::SIDE_LEFT
static

◆ SIDE_RIGHT

const AUTOPLACER::SIDE AUTOPLACER::SIDE_RIGHT
static

◆ SIDE_TOP

const AUTOPLACER::SIDE AUTOPLACER::SIDE_TOP
static

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