53#include <boost/range/adaptor/reversed.hpp>
63#define FIELD_PADDING schIUScale.MilsToIU( 15 )
64#define WIRE_V_SPACING schIUScale.MilsToIU( 100 )
65#define HPADDING schIUScale.MilsToIU( 25 )
66#define VPADDING schIUScale.MilsToIU( 15 )
71template<
typename T>
T round_n(
const T& value,
const T& n,
bool aRoundUp )
74 return n * (value / n + (aRoundUp ? 1 : 0));
140 bool forceWireSpacing =
false;
150 int last_y_coord = field_box.
GetTop();
154 if( !field->IsVisible() || !field->CanAutoplace() )
161 if( sideandpins.
pins > 0 )
175 fieldVPlacement( field, field_box, &last_y_coord, !forceWireSpacing ) );
179 if( abs( field_side.
x ) > 0 )
182 if( abs( field_side.
y ) > 0 )
186 field->SetPosition( pos );
197 int max_field_width = 0;
198 int total_height = 0;
202 if( !field->IsVisible() || !field->CanAutoplace() )
211 EDA_ANGLE savedAngle = field->GetTextAngle();
213 BOX2I bbox = field->GetBoundingBox();
214 field->SetTextAngle( savedAngle );
218 max_field_width = std::max( max_field_width, field_width );
228 return VECTOR2I( max_field_width, total_height );
245 wxFAIL_MSG( wxS(
"Invalid pin orientation" ) );
255 unsigned pin_count = 0;
275 wxCHECK_RET(
m_screen, wxS(
"getPossibleCollisions() with null m_screen" ) );
283 box.
Merge( symbolBox );
292 std::vector<SCH_FIELD*> fields;
293 candidate->GetFields( fields,
true );
296 aItems.push_back( field );
299 aItems.push_back( item );
310 std::vector<SCH_ITEM*> filtered;
317 item_box = item_comp->GetBodyAndPinsBoundingBox();
319 item_box = item->GetBoundingBox();
322 filtered.push_back( item );
340 std::vector<SIDE_AND_NPINS> sides( sides_init, sides_init +
arrayDim( sides_init ) );
342 int orient =
m_symbol->GetOrientation();
343 int orient_angle = orient & 0xff;
355 switch( orient_angle )
358 std::swap( sides[0], sides[1] );
359 std::swap( sides[1], sides[3] );
363 std::swap( sides[0], sides[2] );
364 std::swap( sides[1], sides[2] );
368 std::swap( sides[0], sides[3] );
372 std::swap( sides[1], sides[2] );
382 std::swap( sides[0], sides[2] );
388 std::swap( sides[0], sides[1] );
389 std::swap( sides[1], sides[3] );
416 drawableArea.
SetOrigin( leftMargin, topMargin );
417 drawableArea.
SetEnd( pageWidth - rightMargin, pageHeight - bottomMargin );
428 std::vector<SIDE> sides( sides_init, sides_init +
arrayDim( sides_init ) );
429 std::vector<SIDE_AND_COLL> colliding;
432 bool checkDrawableArea = ( drawableArea.
GetWidth() > 0 && drawableArea.
GetHeight() > 0 );
435 for(
SIDE side : sides )
438 sideandpins.
side = side;
446 if( checkDrawableArea && !drawableArea.
Contains( box ) )
453 if( line && !side.x )
469 colliding.push_back( { side, collision } );
480 const std::vector<SIDE_AND_COLL>& aCollidingSides,
486 std::vector<SIDE_AND_NPINS>::iterator it = aSides.begin();
488 while( it != aSides.end() )
494 if( collision.side == it->side && collision.collision == aCollision )
504 if( it->pins <= sel.
pins )
510 it = aSides.erase( it );
526 std::reverse( sides.begin(), sides.end() );
529 if( aAvoidCollisions )
536 for(
SIDE_AND_NPINS& each_side : sides | boost::adaptors::reversed )
538 if( !each_side.pins )
return each_side;
543 if( each_side.pins <= side.
pins )
545 side.
pins = each_side.pins;
546 side.
side = each_side.side;
577 if( aFieldSideAndPins.
side.
x != 0 )
579 else if( aFieldSideAndPins.
side.
y != 0 )
582 fbox_center.
x += aFieldSideAndPins.
side.
x * offs_x;
583 fbox_center.
y += aFieldSideAndPins.
side.
y * offs_y;
599 pinsBox.
Merge( each_pin->GetBoundingBox() );
605 if( aFieldSideAndPins.
pins > 0 )
607 BOX2I pinsBox = getPinsBox( aFieldSideAndPins.
side );
633 if( colliders.empty() )
648 if( start.
y !=
end.y )
654 offset = this_offset;
655 else if( offset != this_offset )
689 switch( field_hjust )
692 field_xcoord = aFieldBox.
GetLeft();
695 field_xcoord = aFieldBox.
Centre().
x;
698 field_xcoord = aFieldBox.
GetRight();
701 wxFAIL_MSG( wxS(
"Unexpected value for SCH_FIELD::GetHorizJustify()" ) );
702 field_xcoord = aFieldBox.
Centre().
x;
733 padding =
round_n( field_height,
schIUScale.MilsToIU( 50 ),
true ) - field_height;
741 int placement = *aAccumulatedPosition + padding / 2 + field_height / 2;
743 *aAccumulatedPosition += padding + field_height;
771 wxASSERT_MSG( aScreen, wxS(
"A SCH_SCREEN ptr must be given for manual autoplacement" ) );
780 default: wxFAIL_MSG(
"Unknown autoplace algorithm" );
break;
788 wxFAIL_MSG( wxS(
"Manual autoplacement not supported for LIB_SYMBOLs" ) );
797 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
BOX2I getDrawableArea()
Compute the drawable area (inside the drawing sheet border) for collision detection.
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 bool Contains(const Vec &aPoint) const
constexpr coord_type GetRight() const
constexpr void SetEnd(coord_type x, coord_type y)
constexpr coord_type GetTop() const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Handle the graphic items list to draw/plot the frame and title block.
static DS_DATA_MODEL & GetTheInstance()
Return the instance of DS_DATA_MODEL used in the application.
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
APP_SETTINGS_BASE * KifaceSettings() const
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Automatically orient all the fields in the symbol.
Describe the page size and margins of a paper page on which to eventually print or plot.
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
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...
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.
static constexpr EDA_ANGLE ANGLE_VERTICAL
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
PIN_ORIENTATION
The symbol library pin object orientations.
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
@ PIN_RIGHT
The pin extends rightwards from the connection point.
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
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