#6377 changed a bit in the vicinity of this patch, so here's an updated one to preempt any merge conflicts.
On Sun, Dec 13, 2015 at 12:53:53PM -0500, Chris Pavlina wrote: > Okay, here's a patch to make the autoplacement grid for fields flexible, > so fields are positioned sanely when they have different heights. Just > finished this an hour ago, as opposed to the main autoplacement patch > which got months of testing, so somebody else might want to try this > out. > > I'm going to prepare one more patch, to handle a slightly quirky field > placement in a specific arrangement with a long component symbol > sandwiched between wires. That should be it. > > -- > Chris > commit b8fdf66034c0028ae33a3d372937279919427916 > Author: Chris Pavlina <cpavl...@binghamton.edu> > Date: Sat Dec 12 16:29:19 2015 -0500 > > Make vertical autoplacement grid flexible > > diff --git a/eeschema/autoplace_fields.cpp b/eeschema/autoplace_fields.cpp > index 001127a..5849309 100644 > --- a/eeschema/autoplace_fields.cpp > +++ b/eeschema/autoplace_fields.cpp > @@ -63,9 +63,11 @@ > #include <vector> > #include <algorithm> > > -#define FIELD_V_SPACING 100 > +#define FIELD_PADDING 10 // arbitrarily chosen for aesthetics > +#define FIELD_PADDING_ALIGNED 18 // aligns 50 mil text to a 100 mil grid > +#define WIRE_V_SPACING 100 > #define HPADDING 25 > -#define VPADDING 50 > +#define VPADDING 25 > > /** > * Function round_n > @@ -127,7 +129,7 @@ public: > Kiface().KifaceSettings()->Read( AUTOPLACE_ALIGN_KEY, > &m_align_to_grid, false ); > > m_comp_bbox = m_component->GetBodyBoundingBox(); > - m_fbox_size = ComputeFBoxSize(); > + m_fbox_size = ComputeFBoxSize( /* aDynamic */ true ); > > m_power_symbol = ! m_component->IsInNetlist(); > > @@ -143,17 +145,16 @@ public: > */ > void DoAutoplace( bool aManual ) > { > + bool force_wire_spacing = false; > SIDE field_side = choose_side_for_fields( aManual ); > wxPoint fbox_pos = field_box_placement( field_side ); > EDA_RECT field_box( fbox_pos, m_fbox_size ); > > if( aManual ) > - { > - fbox_pos = fit_fields_between_wires( field_box, field_side ); > - field_box.SetOrigin( fbox_pos ); > - } > + force_wire_spacing = fit_fields_between_wires( &field_box, > field_side ); > > // Move the fields > + int last_y_coord = field_box.GetTop(); > for( int field_idx = 0; field_idx < m_fields.size(); ++field_idx ) > { > SCH_FIELD* field = m_fields[field_idx]; > @@ -163,7 +164,7 @@ public: > > wxPoint pos( > field_horiz_placement( field, field_box ), > - field_box.GetY() + (FIELD_V_SPACING * field_idx) ); > + field_vert_placement( field, field_box, &last_y_coord, > !force_wire_spacing ) ); > > if( m_align_to_grid ) > { > @@ -179,29 +180,40 @@ public: > protected: > /** > * Compute and return the size of the fields' bounding box. > + * @param aDynamic - if true, use dynamic spacing > */ > - wxSize ComputeFBoxSize() > + wxSize ComputeFBoxSize( bool aDynamic ) > { > int max_field_width = 0; > + int total_height = 0; > + > BOOST_FOREACH( SCH_FIELD* field, m_fields ) > { > int field_width; > + int field_height; > > if( m_component->GetTransform().y1 ) > { > field->SetOrientation( TEXT_ORIENT_VERT ); > - field_width = field->GetBoundingBox().GetHeight(); > } > else > { > field->SetOrientation( TEXT_ORIENT_HORIZ ); > - field_width = field->GetBoundingBox().GetWidth(); > } > > + field_width = field->GetBoundingBox().GetWidth(); > + field_height = field->GetBoundingBox().GetHeight(); > + > max_field_width = std::max( max_field_width, field_width ); > + > + if( aDynamic ) > + total_height += field_height + get_field_padding(); > + else > + total_height += WIRE_V_SPACING; > + > } > > - return wxSize( max_field_width, int( FIELD_V_SPACING * > (m_fields.size() - 1) ) ); > + return wxSize( max_field_width, total_height ); > } > > > @@ -519,16 +531,16 @@ protected: > /** > * Function fit_fields_between_wires > * Shift a field box up or down a bit to make the fields fit between > some wires. > - * Returns the new position of the field bounding box. > + * Returns true if a shift was made. > */ > - wxPoint fit_fields_between_wires( const EDA_RECT& aBox, SIDE aSide ) > + bool fit_fields_between_wires( EDA_RECT* aBox, SIDE aSide ) > { > if( aSide != SIDE_TOP && aSide != SIDE_BOTTOM ) > - return aBox.GetPosition(); > + return false; > > - std::vector<SCH_ITEM*> colliders = filtered_colliders( aBox ); > + std::vector<SCH_ITEM*> colliders = filtered_colliders( *aBox ); > if( colliders.empty() ) > - return aBox.GetPosition(); > + return false; > > // Find the offset of the wires for proper positioning > int offset = 0; > @@ -537,24 +549,28 @@ protected: > { > SCH_LINE* line = dynamic_cast<SCH_LINE*>( item ); > if( !line ) > - return aBox.GetPosition(); > + return false; > wxPoint start = line->GetStartPoint(), end = line->GetEndPoint(); > if( start.y != end.y ) > - return aBox.GetPosition(); > + return false; > > - int this_offset = (3 * FIELD_V_SPACING / 2) - ( start.y % > FIELD_V_SPACING ); > + int this_offset = (3 * WIRE_V_SPACING / 2) - ( start.y % > WIRE_V_SPACING ); > if( offset == 0 ) > offset = this_offset; > else if( offset != this_offset ) > - return aBox.GetPosition(); > + return false; > } > > if( aSide == SIDE_TOP ) > offset = -offset; > > - wxPoint pos = aBox.GetPosition(); > - pos.y = round_n( pos.y - offset, FIELD_V_SPACING, aSide == > SIDE_BOTTOM ) + offset; > - return pos; > + wxPoint pos = aBox->GetPosition(); > + pos.y = round_n( pos.y - offset, WIRE_V_SPACING, aSide == > SIDE_BOTTOM ) + offset; > + > + // Compensate for padding > + pos.y += WIRE_V_SPACING / 2; > + aBox->SetOrigin( pos ); > + return true; > } > > > @@ -597,6 +613,59 @@ protected: > return field_xcoord; > } > > + /** > + * Function field_vert_placement > + * Place a field vertically. Because field vertical placements > accumulate, > + * this takes a pointer to a vertical position accumulator. > + * > + * @param aField - the field to place. > + * @param aFieldBox - box in which fields will be placed. > + * @param aPosAccum - pointer to a position accumulator > + * @param aDynamic - use dynamic spacing > + * > + * @return Correct field vertical position > + */ > + int field_vert_placement( SCH_FIELD *aField, const EDA_RECT &aFieldBox, > int *aPosAccum, > + bool aDynamic ) > + { > + int field_height; > + int padding; > + > + if( aDynamic ) > + { > + if( m_component->GetTransform().y1 ) > + field_height = aField->GetBoundingBox().GetWidth(); > + else > + field_height = aField->GetBoundingBox().GetHeight(); > + field_height = aField->GetBoundingBox().GetHeight(); > + > + padding = get_field_padding(); > + } > + else > + { > + field_height = WIRE_V_SPACING / 2; > + padding = WIRE_V_SPACING / 2; > + } > + > + int placement = *aPosAccum + padding / 2 + field_height / 2; > + > + *aPosAccum += padding + field_height; > + > + return placement; > + } > + > + /** > + * Function get_field_padding > + * Return the desired padding between fields. > + */ > + int get_field_padding() > + { > + if( m_align_to_grid ) > + return FIELD_PADDING_ALIGNED; > + else > + return FIELD_PADDING; > + } > + > }; > > const AUTOPLACER::SIDE AUTOPLACER::SIDE_TOP( 0, -1 );
diff --git a/eeschema/autoplace_fields.cpp b/eeschema/autoplace_fields.cpp index 1efd40e..c8a7aa6 100644 --- a/eeschema/autoplace_fields.cpp +++ b/eeschema/autoplace_fields.cpp @@ -63,9 +63,11 @@ #include <vector> #include <algorithm> -#define FIELD_V_SPACING 100 +#define FIELD_PADDING 10 // arbitrarily chosen for aesthetics +#define FIELD_PADDING_ALIGNED 18 // aligns 50 mil text to a 100 mil grid +#define WIRE_V_SPACING 100 #define HPADDING 25 -#define VPADDING 50 +#define VPADDING 25 /** * Function round_n @@ -127,7 +129,7 @@ public: Kiface().KifaceSettings()->Read( AUTOPLACE_ALIGN_KEY, &m_align_to_grid, false ); m_comp_bbox = m_component->GetBodyBoundingBox(); - m_fbox_size = ComputeFBoxSize(); + m_fbox_size = ComputeFBoxSize( /* aDynamic */ true ); m_power_symbol = ! m_component->IsInNetlist(); @@ -143,17 +145,16 @@ public: */ void DoAutoplace( bool aManual ) { + bool force_wire_spacing = false; SIDE field_side = choose_side_for_fields( aManual ); wxPoint fbox_pos = field_box_placement( field_side ); EDA_RECT field_box( fbox_pos, m_fbox_size ); if( aManual ) - { - fbox_pos = fit_fields_between_wires( field_box, field_side ); - field_box.SetOrigin( fbox_pos ); - } + force_wire_spacing = fit_fields_between_wires( &field_box, field_side ); // Move the fields + int last_y_coord = field_box.GetTop(); for( unsigned field_idx = 0; field_idx < m_fields.size(); ++field_idx ) { SCH_FIELD* field = m_fields[field_idx]; @@ -163,7 +164,7 @@ public: wxPoint pos( field_horiz_placement( field, field_box ), - field_box.GetY() + (FIELD_V_SPACING * field_idx) ); + field_vert_placement( field, field_box, &last_y_coord, !force_wire_spacing ) ); if( m_align_to_grid ) { @@ -179,29 +180,40 @@ public: protected: /** * Compute and return the size of the fields' bounding box. + * @param aDynamic - if true, use dynamic spacing */ - wxSize ComputeFBoxSize() + wxSize ComputeFBoxSize( bool aDynamic ) { int max_field_width = 0; + int total_height = 0; + BOOST_FOREACH( SCH_FIELD* field, m_fields ) { int field_width; + int field_height; if( m_component->GetTransform().y1 ) { field->SetOrientation( TEXT_ORIENT_VERT ); - field_width = field->GetBoundingBox().GetHeight(); } else { field->SetOrientation( TEXT_ORIENT_HORIZ ); - field_width = field->GetBoundingBox().GetWidth(); } + field_width = field->GetBoundingBox().GetWidth(); + field_height = field->GetBoundingBox().GetHeight(); + max_field_width = std::max( max_field_width, field_width ); + + if( aDynamic ) + total_height += field_height + get_field_padding(); + else + total_height += WIRE_V_SPACING; + } - return wxSize( max_field_width, int( FIELD_V_SPACING * (m_fields.size() - 1) ) ); + return wxSize( max_field_width, total_height ); } @@ -519,16 +531,16 @@ protected: /** * Function fit_fields_between_wires * Shift a field box up or down a bit to make the fields fit between some wires. - * Returns the new position of the field bounding box. + * Returns true if a shift was made. */ - wxPoint fit_fields_between_wires( const EDA_RECT& aBox, SIDE aSide ) + bool fit_fields_between_wires( EDA_RECT* aBox, SIDE aSide ) { if( aSide != SIDE_TOP && aSide != SIDE_BOTTOM ) - return aBox.GetPosition(); + return false; - std::vector<SCH_ITEM*> colliders = filtered_colliders( aBox ); + std::vector<SCH_ITEM*> colliders = filtered_colliders( *aBox ); if( colliders.empty() ) - return aBox.GetPosition(); + return false; // Find the offset of the wires for proper positioning int offset = 0; @@ -537,24 +549,28 @@ protected: { SCH_LINE* line = dynamic_cast<SCH_LINE*>( item ); if( !line ) - return aBox.GetPosition(); + return false; wxPoint start = line->GetStartPoint(), end = line->GetEndPoint(); if( start.y != end.y ) - return aBox.GetPosition(); + return false; - int this_offset = (3 * FIELD_V_SPACING / 2) - ( start.y % FIELD_V_SPACING ); + int this_offset = (3 * WIRE_V_SPACING / 2) - ( start.y % WIRE_V_SPACING ); if( offset == 0 ) offset = this_offset; else if( offset != this_offset ) - return aBox.GetPosition(); + return false; } if( aSide == SIDE_TOP ) offset = -offset; - wxPoint pos = aBox.GetPosition(); - pos.y = round_n( pos.y - offset, FIELD_V_SPACING, aSide == SIDE_BOTTOM ) + offset; - return pos; + wxPoint pos = aBox->GetPosition(); + pos.y = round_n( pos.y - offset, WIRE_V_SPACING, aSide == SIDE_BOTTOM ) + offset; + + // Compensate for padding + pos.y += WIRE_V_SPACING / 2; + aBox->SetOrigin( pos ); + return true; } @@ -597,6 +613,59 @@ protected: return field_xcoord; } + /** + * Function field_vert_placement + * Place a field vertically. Because field vertical placements accumulate, + * this takes a pointer to a vertical position accumulator. + * + * @param aField - the field to place. + * @param aFieldBox - box in which fields will be placed. + * @param aPosAccum - pointer to a position accumulator + * @param aDynamic - use dynamic spacing + * + * @return Correct field vertical position + */ + int field_vert_placement( SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum, + bool aDynamic ) + { + int field_height; + int padding; + + if( aDynamic ) + { + if( m_component->GetTransform().y1 ) + field_height = aField->GetBoundingBox().GetWidth(); + else + field_height = aField->GetBoundingBox().GetHeight(); + field_height = aField->GetBoundingBox().GetHeight(); + + padding = get_field_padding(); + } + else + { + field_height = WIRE_V_SPACING / 2; + padding = WIRE_V_SPACING / 2; + } + + int placement = *aPosAccum + padding / 2 + field_height / 2; + + *aPosAccum += padding + field_height; + + return placement; + } + + /** + * Function get_field_padding + * Return the desired padding between fields. + */ + int get_field_padding() + { + if( m_align_to_grid ) + return FIELD_PADDING_ALIGNED; + else + return FIELD_PADDING; + } + }; const AUTOPLACER::SIDE AUTOPLACER::SIDE_TOP( 0, -1 );
_______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : kicad-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp