53#include <boost/range/adaptor/reversed.hpp>
62#define FIELD_PADDING schIUScale.MilsToIU( 15 )
63#define WIRE_V_SPACING schIUScale.MilsToIU( 100 )
64#define HPADDING schIUScale.MilsToIU( 25 )
65#define VPADDING schIUScale.MilsToIU( 15 )
70template<
typename T> T
round_n(
const T& value,
const T& n,
bool aRoundUp )
73 return n * (value / n + (aRoundUp ? 1 : 0));
134 bool forceWireSpacing =
false;
144 int last_y_coord = field_box.
GetTop();
148 if( !field->IsVisible() || !field->CanAutoplace() )
153 if( sideandpins.
pins > 0 )
167 fieldVPlacement( field, field_box, &last_y_coord, !forceWireSpacing ) );
171 if( abs( field_side.
x ) > 0 )
174 if( abs( field_side.
y ) > 0 )
178 field->SetPosition( pos );
189 int max_field_width = 0;
190 int total_height = 0;
194 if( !field->IsVisible() || !field->CanAutoplace() )
204 BOX2I bbox = field->GetBoundingBox();
208 max_field_width = std::max( max_field_width, field_width );
218 return VECTOR2I( max_field_width, total_height );
230 case PIN_ORIENTATION::PIN_RIGHT:
return SIDE_LEFT;
231 case PIN_ORIENTATION::PIN_LEFT:
return SIDE_RIGHT;
233 case PIN_ORIENTATION::PIN_DOWN:
return SIDE_TOP;
235 wxFAIL_MSG( wxS(
"Invalid pin orientation" ) );
245 unsigned pin_count = 0;
265 wxCHECK_RET(
m_screen, wxS(
"getPossibleCollisions() with null m_screen" ) );
273 box.
Merge( symbolBox );
282 std::vector<SCH_FIELD*> fields;
283 candidate->GetFields( fields,
true );
286 aItems.push_back( field );
289 aItems.push_back( item );
300 std::vector<SCH_ITEM*> filtered;
307 item_box = item_comp->GetBodyAndPinsBoundingBox();
309 item_box = item->GetBoundingBox();
312 filtered.push_back( item );
330 std::vector<SIDE_AND_NPINS> sides( sides_init, sides_init +
arrayDim( sides_init ) );
333 int orient_angle = orient & 0xff;
345 switch( orient_angle )
348 std::swap( sides[0], sides[1] );
349 std::swap( sides[1], sides[3] );
353 std::swap( sides[0], sides[2] );
354 std::swap( sides[1], sides[2] );
358 std::swap( sides[0], sides[3] );
362 std::swap( sides[1], sides[2] );
372 std::swap( sides[0], sides[2] );
378 std::swap( sides[0], sides[1] );
379 std::swap( sides[1], sides[3] );
392 std::vector<SIDE> sides( sides_init, sides_init +
arrayDim( sides_init ) );
393 std::vector<SIDE_AND_COLL> colliding;
396 for(
SIDE side : sides )
399 sideandpins.
side = side;
410 if( line && !side.x )
426 colliding.push_back( { side, collision } );
437 const std::vector<SIDE_AND_COLL>& aCollidingSides,
443 std::vector<SIDE_AND_NPINS>::iterator it = aSides.begin();
445 while( it != aSides.end() )
451 if( collision.side == it->side && collision.collision == aCollision )
461 if( it->pins <= sel.
pins )
467 it = aSides.erase( it );
483 std::reverse( sides.begin(), sides.end() );
486 if( aAvoidCollisions )
493 for(
SIDE_AND_NPINS& each_side : sides | boost::adaptors::reversed )
495 if( !each_side.pins )
return each_side;
500 if( each_side.pins <= side.
pins )
502 side.
pins = each_side.pins;
503 side.
side = each_side.side;
534 if( aFieldSideAndPins.
side.
x != 0 )
536 else if( aFieldSideAndPins.
side.
y != 0 )
539 fbox_center.
x += aFieldSideAndPins.
side.
x * offs_x;
540 fbox_center.
y += aFieldSideAndPins.
side.
y * offs_y;
556 pinsBox.
Merge( each_pin->GetBoundingBox() );
562 if( aFieldSideAndPins.
pins > 0 )
564 BOX2I pinsBox = getPinsBox( aFieldSideAndPins.
side );
590 if( colliders.empty() )
605 if( start.
y !=
end.
y )
611 offset = this_offset;
612 else if( offset != this_offset )
646 switch( field_hjust )
649 field_xcoord = aFieldBox.
GetLeft();
652 field_xcoord = aFieldBox.
Centre().
x;
655 field_xcoord = aFieldBox.
GetRight();
658 wxFAIL_MSG( wxS(
"Unexpected value for SCH_FIELD::GetHorizJustify()" ) );
659 field_xcoord = aFieldBox.
Centre().
x;
698 int placement = *aAccumulatedPosition + padding / 2 + field_height / 2;
700 *aAccumulatedPosition += padding + field_height;
727 wxASSERT_MSG( aScreen, wxS(
"A SCH_SCREEN ptr must be given for manual autoplacement" ) );
736 default: wxFAIL_MSG(
"Unknown autoplace algorithm" );
break;
744 wxFAIL_MSG( wxS(
"Manual autoplacement not supported for LIB_SYMBOLs" ) );
753 default: wxFAIL_MSG(
"Unknown autoplace algorithm" );
break;
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
T round_n(const T &value, const T &n, bool aRoundUp)
Round up/down to the nearest multiple of n.
constexpr EDA_IU_SCALE schIUScale
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
VECTOR2I computeFBoxSize(bool aDynamic)
Compute and return the size of the fields' bounding box.
VECTOR2I fieldBoxPlacement(SIDE_AND_NPINS aFieldSideAndPins)
Return the position of the field bounding box.
SIDE getPinSide(SCH_PIN *aPin)
Return the side that a pin is on.
int fieldVPlacement(SCH_FIELD *aField, const BOX2I &aFieldBox, int *aAccumulatedPosition, bool aDynamic)
Place a field vertically.
void getPossibleCollisions(std::vector< SCH_ITEM * > &aItems)
Populate a list of all drawing items that may collide with the fields.
static const SIDE SIDE_TOP
static const SIDE SIDE_BOTTOM
unsigned pinsOnSide(SIDE aSide)
Count the number of pins on a side of the symbol.
std::vector< SCH_FIELD * > m_fields
SIDE_AND_NPINS chooseSideForFields(bool aAvoidCollisions)
Look where a symbol's pins are to pick a side to put the fields on.
bool fitFieldsBetweenWires(BOX2I *aBox, SIDE aSide)
Shift a field box up or down a bit to make the fields fit between some wires.
int fieldHPlacement(SCH_FIELD *aField, const BOX2I &aFieldBox)
Place a field horizontally, taking into account the field width and justification.
std::vector< SCH_ITEM * > m_colliders
static const SIDE SIDE_RIGHT
std::vector< SCH_ITEM * > filterCollisions(const BOX2I &aRect)
Filter a list of possible colliders to include only those that actually collide with a given rectangl...
std::vector< SIDE_AND_NPINS > getPreferredSides()
Return a list with the preferred field sides for the symbol, 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.
AUTOPLACER(SYMBOL *aSymbol, SCH_SCREEN *aScreen)
static const SIDE SIDE_LEFT
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.
void DoAutoplace(AUTOPLACE_ALGO aAlgo)
Do the actual autoplacement.
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...
constexpr const Vec & GetPosition() const
constexpr void SetOrigin(const Vec &pos)
constexpr size_type GetWidth() const
constexpr Vec Centre() const
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr size_type GetHeight() const
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
EE_TYPE Overlapping(const BOX2I &aRect) const
APP_SETTINGS_BASE * KifaceSettings() const
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Automatically orient all the fields in the symbol.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
bool IsHorizJustifyFlipped() const
Return whether the field will be rendered with the horizontal justification inverted due to rotation ...
Base class for any item which can be embedded within the SCHEMATIC container class,...
AUTOPLACE_ALGO m_fieldsAutoplaced
Segment description base class to describe items which have 2 end points (track, wire,...
VECTOR2I GetEndPoint() const
VECTOR2I GetStartPoint() const
PIN_ORIENTATION PinDrawOrient(const TRANSFORM &aTransform) const
Return the pin real orientation (PIN_UP, PIN_DOWN, PIN_RIGHT, PIN_LEFT), according to its orientation...
EE_RTREE & Items()
Get the full RTree, usually for iterating.
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Automatically orient all the fields in the symbol.
A base class for LIB_SYMBOL and SCH_SYMBOL.
virtual BOX2I GetBodyAndPinsBoundingBox() const =0
Return a bounding box for the symbol body and pins but not the fields.
virtual void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const =0
const TRANSFORM & GetTransform() const
virtual BOX2I GetBodyBoundingBox() const =0
Return a bounding box for the symbol body but not the pins or fields.
virtual std::vector< SCH_PIN * > GetPins() const =0
virtual int GetOrientation() const
static constexpr EDA_ANGLE ANGLE_VERTICAL
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
PIN_ORIENTATION
The symbol library pin object orientations.
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
constexpr int MilsToIU(int mils) const
constexpr GR_TEXT_H_ALIGN_T GetFlippedAlignment(GR_TEXT_H_ALIGN_T aAlign)
Get the reverse alignment: left-right are swapped, others are unchanged.
constexpr GR_TEXT_H_ALIGN_T ToHAlignment(int x)
Convert an integral value to horizontal alignment.
VECTOR2< int32_t > VECTOR2I