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)
 Function get_pin_side Return the side that a pin is on. More...
 
unsigned pins_on_side (SIDE aSide)
 Function pins_on_side Count the number of pins on a side of the component. More...
 
void get_possible_colliders (std::vector< SCH_ITEM * > &aItems)
 Function get_possible_colliders Populate a list of all drawing items that may collide with the fields. More...
 
std::vector< SCH_ITEM * > filtered_colliders (const EDA_RECT &aRect)
 Function filtered_colliders 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 ()
 Function get_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 ()
 Function get_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)
 Function choose_side_filtered Choose a side for the fields, filtered on only one side collision type. More...
 
SIDE choose_side_for_fields (bool aAvoidCollisions)
 Function choose_side_for_fields 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)
 Function justify_field 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)
 Function field_box_placement Returns the position of the field bounding box. More...
 
bool fit_fields_between_wires (EDA_RECT *aBox, SIDE aSide)
 Function fit_fields_between_wires 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)
 Function field_horiz_placement 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)
 Function field_vert_placement Place a field vertically. More...
 
int get_field_padding ()
 Function 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 98 of file autoplace_fields.cpp.

Member Typedef Documentation

◆ SIDE

typedef wxPoint AUTOPLACER::SIDE

Definition at line 110 of file autoplace_fields.cpp.

Member Enumeration Documentation

◆ COLLISION

Constructor & Destructor Documentation

◆ AUTOPLACER()

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

Definition at line 127 of file autoplace_fields.cpp.

128  :m_screen( aScreen ), m_component( aComponent )
129  {
130  m_component->GetFields( m_fields, /* aVisibleOnly */ true );
133 
135  m_fbox_size = ComputeFBoxSize( /* aDynamic */ true );
136 
138 
139  if( aScreen )
141  }
wxSize ComputeFBoxSize(bool aDynamic)
Compute and return the size of the fields' bounding box.
std::vector< SCH_FIELD * > m_fields
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
SCH_COMPONENT * m_component
bool IsInNetlist() const
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
SCH_SCREEN * m_screen
const wxChar AutoplaceAlignEntry[]
std::vector< SCH_ITEM * > m_colliders
EDA_RECT GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the fields.
EDA_RECT m_comp_bbox
void get_possible_colliders(std::vector< SCH_ITEM * > &aItems)
Function get_possible_colliders Populate a list of all drawing items that may collide with the fields...
const wxChar AutoplaceJustifyEntry[]

References AutoplaceAlignEntry, AutoplaceJustifyEntry, ComputeFBoxSize(), get_possible_colliders(), SCH_COMPONENT::GetBodyBoundingBox(), SCH_COMPONENT::GetFields(), SCH_COMPONENT::IsInNetlist(), Kiface(), KIFACE_I::KifaceSettings(), 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

Function choose_side_filtered 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 428 of file autoplace_fields.cpp.

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

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

Function choose_side_for_fields 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 = get_preferred_sides();
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 = get_colliding_sides();
475  side = choose_side_filtered( sides, colliding_sides, COLLIDE_OBJECTS, side );
476  side = choose_side_filtered( 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_COLL > get_colliding_sides()
Function get_colliding_sides Return a list of the sides where a field set would collide with another ...
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)
Function choose_side_filtered Choose a side for the fields, filtered on only one side collision type.
static void reverse(privcurve_t *curve)
Definition: trace.cpp:1025
std::vector< SIDE_AND_NPINS > get_preferred_sides()
Function get_preferred_sides Return a list with the preferred field sides for the component,...

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

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 188 of file autoplace_fields.cpp.

189  {
190  int max_field_width = 0;
191  int total_height = 0;
192 
193  for( SCH_FIELD* field : m_fields )
194  {
195  int field_width;
196  int field_height;
197 
198  if( m_component->GetTransform().y1 )
199  {
200  field->SetTextAngle( TEXT_ANGLE_VERT );
201  }
202  else
203  {
204  field->SetTextAngle( TEXT_ANGLE_HORIZ );
205  }
206 
207  field_width = field->GetBoundingBox().GetWidth();
208  field_height = field->GetBoundingBox().GetHeight();
209 
210  max_field_width = std::max( max_field_width, field_width );
211 
212  if( aDynamic )
213  total_height += field_height + get_field_padding();
214  else
215  total_height += WIRE_V_SPACING;
216 
217  }
218 
219  return wxSize( max_field_width, total_height );
220  }
#define TEXT_ANGLE_HORIZ
Class 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
SCH_COMPONENT * m_component
#define WIRE_V_SPACING
int y1
Definition: transform.h:49
TRANSFORM & GetTransform() const
#define max(a, b)
Definition: auxiliary.h:86
int get_field_padding()
Function get_field_padding Return the desired padding between fields.

References get_field_padding(), SCH_COMPONENT::GetTransform(), m_component, m_fields, max, 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 149 of file autoplace_fields.cpp.

150  {
151  bool force_wire_spacing = false;
152  SIDE field_side = choose_side_for_fields( aManual );
153  wxPoint fbox_pos = field_box_placement( field_side );
154  EDA_RECT field_box( fbox_pos, m_fbox_size );
155 
156  if( aManual )
157  force_wire_spacing = fit_fields_between_wires( &field_box, field_side );
158 
159  // Move the fields
160  int last_y_coord = field_box.GetTop();
161  for( unsigned field_idx = 0; field_idx < m_fields.size(); ++field_idx )
162  {
163  SCH_FIELD* field = m_fields[field_idx];
164 
165  if( m_allow_rejustify )
166  justify_field( field, field_side );
167 
168  wxPoint pos(
169  field_horiz_placement( field, field_box ),
170  field_vert_placement( field, field_box, &last_y_coord, !force_wire_spacing ) );
171 
172  if( m_align_to_grid )
173  {
174  pos.x = round_n( pos.x, 50, field_side.x >= 0 );
175  pos.y = round_n( pos.y, 50, field_side.y == 1 );
176  }
177 
178  field->SetPosition( pos );
179  }
180  }
void justify_field(SCH_FIELD *aField, SIDE aFieldSide)
Function justify_field Set the justification of a field based on the side it's supposed to be on,...
Class 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)
Function field_box_placement Returns the position of the field bounding box.
T round_n(const T &value, const T &n, bool aRoundUp)
Function round_n Round up/down to the nearest multiple of n.
bool fit_fields_between_wires(EDA_RECT *aBox, SIDE aSide)
Function fit_fields_between_wires Shift a field box up or down a bit to make the fields fit between s...
int field_horiz_placement(SCH_FIELD *aField, const EDA_RECT &aFieldBox)
Function field_horiz_placement Place a field horizontally, taking into account the field width and ju...
int field_vert_placement(SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum, bool aDynamic)
Function field_vert_placement Place a field vertically.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
SIDE choose_side_for_fields(bool aAvoidCollisions)
Function choose_side_for_fields 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:535

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(), and SCH_FIELD::SetPosition().

Referenced by SCH_COMPONENT::AutoplaceFields().

◆ field_box_placement()

wxPoint AUTOPLACER::field_box_placement ( SIDE  aFieldSide)
inlineprotected

Function field_box_placement Returns the position of the field bounding box.

Definition at line 517 of file autoplace_fields.cpp.

518  {
519  wxPoint fbox_center = m_comp_bbox.Centre();
520  int offs_x = ( m_comp_bbox.GetWidth() + m_fbox_size.GetWidth() ) / 2 + HPADDING;
521  int offs_y = ( m_comp_bbox.GetHeight() + m_fbox_size.GetHeight() ) / 2 + VPADDING;
522 
523  fbox_center.x += aFieldSide.x * offs_x;
524  fbox_center.y += aFieldSide.y * offs_y;
525 
526  wxPoint fbox_pos(
527  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:117
EDA_RECT m_comp_bbox
int GetHeight() const
Definition: eda_rect.h:118
wxPoint Centre() const
Definition: eda_rect.h:60

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

Referenced by DoAutoplace(), and get_colliding_sides().

◆ field_horiz_placement()

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

Function field_horiz_placement 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 600 of file autoplace_fields.cpp.

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

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().

◆ field_vert_placement()

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

Function field_vert_placement 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 641 of file autoplace_fields.cpp.

643  {
644  int field_height;
645  int padding;
646 
647  if( aDynamic )
648  {
649  field_height = aField->GetBoundingBox().GetHeight();
650 
651  padding = get_field_padding();
652  }
653  else
654  {
655  field_height = WIRE_V_SPACING / 2;
656  padding = WIRE_V_SPACING / 2;
657  }
658 
659  int placement = *aPosAccum + padding / 2 + field_height / 2;
660 
661  *aPosAccum += padding + field_height;
662 
663  return placement;
664  }
#define WIRE_V_SPACING
int GetHeight() const
Definition: eda_rect.h:118
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: sch_field.cpp:236
int get_field_padding()
Function 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

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

Returns the new vector.

Definition at line 296 of file autoplace_fields.cpp.

297  {
298  std::vector<SCH_ITEM*> filtered;
299  for( SCH_ITEM* item : m_colliders )
300  {
301  EDA_RECT item_box;
302  if( SCH_COMPONENT* item_comp = dynamic_cast<SCH_COMPONENT*>( item ) )
303  item_box = item_comp->GetBodyBoundingBox();
304  else
305  item_box = item->GetBoundingBox();
306 
307  if( item_box.Intersects( aRect ) )
308  filtered.push_back( item );
309  }
310  return filtered;
311  }
std::vector< SCH_ITEM * > m_colliders
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Definition: sch_item.h:114

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

Function fit_fields_between_wires 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 539 of file autoplace_fields.cpp.

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

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, and WIRE_V_SPACING.

Referenced by DoAutoplace().

◆ get_colliding_sides()

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

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

Definition at line 388 of file autoplace_fields.cpp.

389  {
390  SIDE sides_init[] = { SIDE_RIGHT, SIDE_TOP, SIDE_LEFT, SIDE_BOTTOM };
391  std::vector<SIDE> sides( sides_init, sides_init + arrayDim( sides_init ) );
392  std::vector<SIDE_AND_COLL> colliding;
393 
394  // Iterate over all sides and find the ones that collide
395  for( SIDE side : sides )
396  {
397  EDA_RECT box( field_box_placement( side ), m_fbox_size );
398 
399  COLLISION collision = COLLIDE_NONE;
400  for( SCH_ITEM* collider : filtered_colliders( box ) )
401  {
402  SCH_LINE* line = dynamic_cast<SCH_LINE*>( collider );
403  if( line && !side.x )
404  {
405  wxPoint start = line->GetStartPoint(), end = line->GetEndPoint();
406  if( start.y == end.y && collision != COLLIDE_OBJECTS )
407  collision = COLLIDE_H_WIRES;
408  else
409  collision = COLLIDE_OBJECTS;
410  }
411  else
412  collision = COLLIDE_OBJECTS;
413  }
414 
415  if( collision != COLLIDE_NONE )
416  colliding.push_back( { side, collision } );
417  }
418 
419  return colliding;
420  }
wxPoint GetStartPoint() const
Definition: sch_line.h:90
wxPoint field_box_placement(SIDE aFieldSide)
Function field_box_placement Returns 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:107
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
static const SIDE SIDE_BOTTOM
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static const SIDE SIDE_TOP
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Definition: sch_item.h:114
std::vector< SCH_ITEM * > filtered_colliders(const EDA_RECT &aRect)
Function filtered_colliders Filter a list of possible colliders to include only those that actually c...
wxPoint GetEndPoint() const
Definition: sch_line.h:93

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, and SIDE_TOP.

Referenced by choose_side_for_fields().

◆ get_field_padding()

int AUTOPLACER::get_field_padding ( )
inlineprotected

Function get_field_padding Return the desired padding between fields.

Definition at line 670 of file autoplace_fields.cpp.

671  {
672  if( m_align_to_grid )
673  return FIELD_PADDING_ALIGNED;
674  else
675  return FIELD_PADDING;
676  }
#define FIELD_PADDING_ALIGNED
#define FIELD_PADDING

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

Function get_pin_side Return the side that a pin is on.

Definition at line 227 of file autoplace_fields.cpp.

228  {
229  int pin_orient = aPin->PinDrawOrient( m_component->GetTransform() );
230  switch( pin_orient )
231  {
232  case PIN_RIGHT: return SIDE_LEFT;
233  case PIN_LEFT: return SIDE_RIGHT;
234  case PIN_UP: return SIDE_BOTTOM;
235  case PIN_DOWN: return SIDE_TOP;
236  default:
237  wxFAIL_MSG( "Invalid pin orientation" );
238  return SIDE_LEFT;
239  }
240  }
SCH_COMPONENT * m_component
Definition: lib_pin.h:55
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:1253
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

Function get_possible_colliders 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 272 of file autoplace_fields.cpp.

273  {
274  wxASSERT_MSG( m_screen, "get_possible_colliders() with null m_screen" );
275  for( SCH_ITEM* item = m_screen->GetDrawItems(); item; item = item->Next() )
276  {
277  if( SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( item ) )
278  {
279  if( comp == m_component ) continue;
280 
281  std::vector<SCH_FIELD*> fields;
282  comp->GetFields( fields, /* aVisibleOnly */ true );
283  for( SCH_FIELD* field : fields )
284  aItems.push_back( field );
285  }
286  aItems.push_back( item );
287  }
288  }
Class SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
SCH_ITEM * Next() const
Definition: sch_item.h:153
SCH_COMPONENT * m_component
SCH_SCREEN * m_screen
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Definition: sch_item.h:114
SCH_ITEM * GetDrawItems() const
Definition: sch_screen.h:153

References SCH_SCREEN::GetDrawItems(), m_component, m_screen, and SCH_ITEM::Next().

Referenced by AUTOPLACER().

◆ get_preferred_sides()

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

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

Definition at line 319 of file autoplace_fields.cpp.

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

Function justify_field 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 503 of file autoplace_fields.cpp.

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

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

Referenced by DoAutoplace().

◆ pins_on_side()

unsigned AUTOPLACER::pins_on_side ( SIDE  aSide)
inlineprotected

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

Definition at line 247 of file autoplace_fields.cpp.

248  {
249  unsigned pin_count = 0;
250 
251  std::vector<LIB_PIN*> pins;
252  m_component->GetPins( pins );
253 
254  for( LIB_PIN* each_pin : pins )
255  {
256  if( !each_pin->IsVisible() && !m_power_symbol )
257  continue;
258  if( get_pin_side( each_pin ) == aSide )
259  ++pin_count;
260  }
261 
262  return pin_count;
263  }
SCH_COMPONENT * m_component
SIDE get_pin_side(LIB_PIN *aPin)
Function get_pin_side 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 106 of file autoplace_fields.cpp.

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

◆ m_allow_rejustify

bool AUTOPLACER::m_allow_rejustify
private

Definition at line 106 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), and DoAutoplace().

◆ m_colliders

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

Definition at line 103 of file autoplace_fields.cpp.

Referenced by AUTOPLACER(), and filtered_colliders().

◆ m_comp_bbox

EDA_RECT AUTOPLACER::m_comp_bbox
private

◆ m_component

SCH_COMPONENT* AUTOPLACER::m_component
private

◆ m_fbox_size

wxSize AUTOPLACER::m_fbox_size
private

◆ m_fields

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

Definition at line 102 of file autoplace_fields.cpp.

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

◆ m_power_symbol

bool AUTOPLACER::m_power_symbol
private

Definition at line 107 of file autoplace_fields.cpp.

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

◆ m_screen

SCH_SCREEN* AUTOPLACER::m_screen
private

Definition at line 100 of file 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

Definition at line 111 of file autoplace_fields.cpp.

Referenced by get_colliding_sides(), get_pin_side(), and get_preferred_sides().

◆ SIDE_RIGHT

const AUTOPLACER::SIDE AUTOPLACER::SIDE_RIGHT
static

Definition at line 111 of file autoplace_fields.cpp.

Referenced by get_colliding_sides(), get_pin_side(), and get_preferred_sides().

◆ SIDE_TOP

const AUTOPLACER::SIDE AUTOPLACER::SIDE_TOP
static

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