ADDED: Orthogonal dimension object

This commit is contained in:
Jon Evans 2020-09-21 22:32:40 -04:00
parent e345e7d17a
commit acf13a1869
17 changed files with 437 additions and 76 deletions

View File

@ -792,6 +792,8 @@ static struct EDA_ITEM_DESC
.Map( PCB_VIA_T, _( "Via" ) )
.Map( PCB_MARKER_T, _( "Board Marker" ) )
.Map( PCB_DIM_ALIGNED_T, _( "Aligned Dimension" ) )
.Map( PCB_DIM_ORTHOGONAL_T, _( "Orthogonal Dimension" ) )
.Map( PCB_DIM_CENTER_T, _( "Center Dimension" ) )
.Map( PCB_DIM_LEADER_T, _( "Leader" ) )
.Map( PCB_TARGET_T, _( "Target" ) )
.Map( PCB_ZONE_AREA_T, _( "Zone" ) )

View File

@ -184,6 +184,8 @@ np_thru_hole
offset
opacity
options
orientation
orthogonal
other_layers_line_width
other_layers_text_dims
oval

View File

@ -456,8 +456,8 @@ static struct DIMENSION_DESC
} _DIMENSION_DESC;
ALIGNED_DIMENSION::ALIGNED_DIMENSION( BOARD_ITEM* aParent ) :
DIMENSION( aParent, PCB_DIM_ALIGNED_T ),
ALIGNED_DIMENSION::ALIGNED_DIMENSION( BOARD_ITEM* aParent, KICAD_T aType ) :
DIMENSION( aParent, aType ),
m_height( 0 )
{
// To preserve look of old dimensions, initialize extension height based on default arrow length
@ -634,6 +634,176 @@ void ALIGNED_DIMENSION::updateText()
}
ORTHOGONAL_DIMENSION::ORTHOGONAL_DIMENSION( BOARD_ITEM* aParent ) :
ALIGNED_DIMENSION( aParent, PCB_DIM_ORTHOGONAL_T )
{
// To preserve look of old dimensions, initialize extension height based on default arrow length
m_extensionHeight = static_cast<int>( m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) ) );
}
EDA_ITEM* ORTHOGONAL_DIMENSION::Clone() const
{
return new ORTHOGONAL_DIMENSION( *this );
}
void ORTHOGONAL_DIMENSION::SwapData( BOARD_ITEM* aImage )
{
assert( aImage->Type() == PCB_DIM_ORTHOGONAL_T );
m_shapes.clear();
static_cast<ORTHOGONAL_DIMENSION*>( aImage )->m_shapes.clear();
std::swap( *static_cast<ORTHOGONAL_DIMENSION*>( this ),
*static_cast<ORTHOGONAL_DIMENSION*>( aImage ) );
Update();
}
BITMAP_DEF ORTHOGONAL_DIMENSION::GetMenuImage() const
{
return add_orthogonal_dimension_xpm;
}
void ORTHOGONAL_DIMENSION::updateGeometry()
{
m_shapes.clear();
int measurement = ( m_orientation == DIR::HORIZONTAL ? m_end.x - m_start.x :
m_end.y - m_start.y );
m_measuredValue = KiROUND( std::abs( measurement ) );
VECTOR2I extension;
if( m_orientation == DIR::HORIZONTAL )
extension = VECTOR2I( 0, m_height );
else
extension = VECTOR2I( m_height, 0 );
// Add first extension line
int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
VECTOR2I extStart( m_start );
extStart += extension.Resize( m_extensionOffset );
addShape( new SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
// Add crossbar
VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
m_crossBarStart = m_start + wxPoint( crossBarDistance );
if( m_orientation == DIR::HORIZONTAL )
m_crossBarEnd = wxPoint( m_end.x, m_crossBarStart.y );
else
m_crossBarEnd = wxPoint( m_crossBarStart.x, m_end.y );
// Add second extension line (m_end to crossbar end)
if( m_orientation == DIR::HORIZONTAL )
extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
else
extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
extStart = VECTOR2I( m_crossBarEnd );
extStart -= extension.Resize( m_extensionHeight );
addShape( new SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
// Update text after calculating crossbar position but before adding crossbar lines
updateText();
// Now that we have the text updated, we can determine how to draw the crossbar.
// First we need to create an appropriate bounding polygon to collide with
EDA_RECT textBox = m_text.GetTextBox().Inflate( m_text.GetTextWidth() / 2,
m_text.GetEffectiveTextPenWidth() );
SHAPE_POLY_SET polyBox;
polyBox.NewOutline();
polyBox.Append( textBox.GetOrigin() );
polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
polyBox.Append( textBox.GetEnd() );
polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
// The ideal crossbar, if the text doesn't collide
SEG crossbar( m_crossBarStart, m_crossBarEnd );
// Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
bool containsA = polyBox.Contains( crossbar.A );
bool containsB = polyBox.Contains( crossbar.B );
OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
if( endpointA )
m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
if( endpointB )
m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
if( !containsA && !containsB && !endpointA && !endpointB )
m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
// Add arrows
VECTOR2I crossBarAngle( m_crossBarEnd - m_crossBarStart );
VECTOR2I arrowEnd( m_arrowLength, 0 );
double arrowRotPos = crossBarAngle.Angle() + DEG2RAD( s_arrowAngle );
double arrowRotNeg = crossBarAngle.Angle() - DEG2RAD( s_arrowAngle );
m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
}
void ORTHOGONAL_DIMENSION::updateText()
{
VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
{
int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
double rotation = sign( m_height ) * DEG2RAD( -90 );
VECTOR2I textOffset = crossbarCenter.Rotate( rotation ).Resize( textOffsetDistance );
textOffset += crossbarCenter;
m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
}
else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
{
m_text.SetTextPos( m_crossBarStart + wxPoint( crossbarCenter ) );
}
if( m_keepTextAligned )
{
double textAngle = 3600 - RAD2DECIDEG( crossbarCenter.Angle() );
NORMALIZE_ANGLE_POS( textAngle );
if( textAngle > 900 && textAngle < 2700 )
textAngle -= 1800;
m_text.SetTextAngle( textAngle );
}
DIMENSION::updateText();
}
LEADER::LEADER( BOARD_ITEM* aParent ) :
DIMENSION( aParent, PCB_DIM_LEADER_T ),
m_textFrame( DIM_TEXT_FRAME::NONE )

View File

@ -347,6 +347,7 @@ protected:
*/
class ALIGNED_DIMENSION : public DIMENSION
{
protected:
// Geometry
int m_height; ///< Perpendicular distance from features to crossbar
int m_extensionHeight; ///< Length of extension lines past the crossbar
@ -355,7 +356,7 @@ class ALIGNED_DIMENSION : public DIMENSION
wxPoint m_crossBarEnd; ///< Crossbar end control point
public:
ALIGNED_DIMENSION( BOARD_ITEM* aParent );
ALIGNED_DIMENSION( BOARD_ITEM* aParent, KICAD_T aType = PCB_DIM_ALIGNED_T );
// Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
@ -418,6 +419,59 @@ protected:
};
/**
* An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the
* X or Y axes, and the measurement is only taken in the X or Y direction.
*/
class ORTHOGONAL_DIMENSION : public ALIGNED_DIMENSION
{
public:
enum class DIR
{
HORIZONTAL, // Aligned with x-axis
VERTICAL // Aligned with y-axis
};
private:
// Geometry
DIR m_orientation; ///< What axis to lock the dimension line to
public:
ORTHOGONAL_DIMENSION( BOARD_ITEM* aParent );
~ORTHOGONAL_DIMENSION() = default;
static inline bool ClassOf( const EDA_ITEM* aItem )
{
return aItem && PCB_DIM_ORTHOGONAL_T == aItem->Type();
}
EDA_ITEM* Clone() const override;
void SwapData( BOARD_ITEM* aImage ) override;
BITMAP_DEF GetMenuImage() const override;
/**
* Sets the orientation of the dimension line (so, perpendicular to the feature lines)
* @param aOrientation is the orientation the dimension should take
*/
void SetOrientation( DIR aOrientation ) { m_orientation = aOrientation; }
DIR GetOrientation() const { return m_orientation; }
wxString GetClass() const override
{
return wxT( "ORTHOGONAL_DIMENSION" );
}
protected:
void updateGeometry() override;
void updateText() override;
};
/**
* A leader is a dimension-like object pointing to a specific point.
*

View File

@ -71,6 +71,8 @@ const KICAD_T GENERAL_COLLECTOR::BoardLevelItems[] = {
PCB_TEXT_T,
PCB_LINE_T,
PCB_DIM_ALIGNED_T,
PCB_DIM_ORTHOGONAL_T,
PCB_DIM_CENTER_T,
PCB_DIM_LEADER_T,
PCB_TARGET_T,
PCB_VIA_T,
@ -88,6 +90,8 @@ const KICAD_T GENERAL_COLLECTOR::AllButZones[] = {
PCB_TEXT_T,
PCB_LINE_T,
PCB_DIM_ALIGNED_T,
PCB_DIM_ORTHOGONAL_T,
PCB_DIM_CENTER_T,
PCB_DIM_LEADER_T,
PCB_TARGET_T,
PCB_VIA_T,
@ -171,6 +175,8 @@ const KICAD_T GENERAL_COLLECTOR::Zones[] = {
const KICAD_T GENERAL_COLLECTOR::Dimensions[] = {
PCB_DIM_ALIGNED_T,
PCB_DIM_LEADER_T,
PCB_DIM_ORTHOGONAL_T,
PCB_DIM_CENTER_T,
EOT
};

View File

@ -664,9 +664,10 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
{
ALIGNED_DIMENSION* aligned = dynamic_cast<ALIGNED_DIMENSION*>( aDimension );
CENTER_DIMENSION* center = dynamic_cast<CENTER_DIMENSION*>( aDimension );
LEADER* leader = dynamic_cast<LEADER*>( aDimension );
ALIGNED_DIMENSION* aligned = dynamic_cast<ALIGNED_DIMENSION*>( aDimension );
ORTHOGONAL_DIMENSION* ortho = dynamic_cast<ORTHOGONAL_DIMENSION*>( aDimension );
CENTER_DIMENSION* center = dynamic_cast<CENTER_DIMENSION*>( aDimension );
LEADER* leader = dynamic_cast<LEADER*>( aDimension );
m_out->Print( aNestLevel, "(dimension" );
@ -676,6 +677,8 @@ void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
m_out->Print( 0, " (type leader)" );
else if( aDimension->Type() == PCB_DIM_CENTER_T )
m_out->Print( 0, " (type center)" );
else if( aDimension->Type() == PCB_DIM_ORTHOGONAL_T )
m_out->Print( 0, " (type orthogonal)" );
else
wxFAIL_MSG( wxT( "Cannot format unknown dimension type!" ) );
@ -695,6 +698,10 @@ void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(height %s)\n",
FormatInternalUnits( aligned->GetHeight() ).c_str() );
if( ortho )
m_out->Print( aNestLevel+1, "(orientation %d)\n",
static_cast<int>( ortho->GetOrientation() ) );
if( !center )
{
Format( &aDimension->Text(), aNestLevel + 1 );

View File

@ -85,7 +85,8 @@ class TEXTE_PCB;
//#define SEXPR_BOARD_FILE_VERSION 20200829 // Remove library name from exported footprints
//#define SEXPR_BOARD_FILE_VERSION 20200909 // Change DIMENSION format
//#define SEXPR_BOARD_FILE_VERSION 20200913 // Add leader dimension
#define SEXPR_BOARD_FILE_VERSION 20200916 // Add center dimension
//#define SEXPR_BOARD_FILE_VERSION 20200916 // Add center dimension
#define SEXPR_BOARD_FILE_VERSION 20200921 // Add orthogonal dimension
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag

View File

@ -321,6 +321,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
placeMenu->AppendSeparator();
placeMenu->Add( PCB_ACTIONS::drawAlignedDimension );
placeMenu->Add( PCB_ACTIONS::drawOrthogonalDimension );
placeMenu->Add( PCB_ACTIONS::drawCenterDimension );
placeMenu->Add( PCB_ACTIONS::drawLeader );

View File

@ -742,6 +742,7 @@ void PCB_EDIT_FRAME::setupUIConditions()
CURRENT_EDIT_TOOL( PCB_ACTIONS::drawPolygon );
CURRENT_EDIT_TOOL( PCB_ACTIONS::placeText );
CURRENT_EDIT_TOOL( PCB_ACTIONS::drawAlignedDimension );
CURRENT_EDIT_TOOL( PCB_ACTIONS::drawOrthogonalDimension );
CURRENT_EDIT_TOOL( PCB_ACTIONS::drawCenterDimension );
CURRENT_EDIT_TOOL( PCB_ACTIONS::drawLeader );
CURRENT_EDIT_TOOL( PCB_ACTIONS::placeTarget );

View File

@ -2383,6 +2383,10 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
dimension = std::make_unique<ALIGNED_DIMENSION>( nullptr );
break;
case T_orthogonal:
dimension = std::make_unique<ORTHOGONAL_DIMENSION>( nullptr );
break;
case T_leader:
dimension = std::make_unique<LEADER>( nullptr );
break;
@ -2458,7 +2462,8 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
case T_height:
{
wxCHECK_MSG( dimension->Type() == PCB_DIM_ALIGNED_T, nullptr,
wxCHECK_MSG( dimension->Type() == PCB_DIM_ALIGNED_T ||
dimension->Type() == PCB_DIM_ORTHOGONAL_T, nullptr,
wxT( "Invalid height token" ) );
ALIGNED_DIMENSION* aligned = static_cast<ALIGNED_DIMENSION*>( dimension.get() );
aligned->SetHeight( parseBoardUnits( "dimension height value" ) );
@ -2466,6 +2471,19 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
break;
}
case T_orientation:
{
wxCHECK_MSG( dimension->Type() == PCB_DIM_ORTHOGONAL_T, nullptr,
wxT( "Invalid orientation token" ) );
ORTHOGONAL_DIMENSION* ortho = static_cast<ORTHOGONAL_DIMENSION*>( dimension.get() );
int orientation = parseInt( "orthogonal dimension orientation" );
orientation = std::max( 0, std::min( 1, orientation ) );
ortho->SetOrientation( static_cast<ORTHOGONAL_DIMENSION::DIR>( orientation ) );
NeedRIGHT();
break;
}
case T_format:
{
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
@ -2562,9 +2580,8 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
case T_extension_height:
{
wxCHECK_MSG( dimension->Type() == PCB_DIM_ALIGNED_T, nullptr,
wxT( "Invalid extension_height token" ) );
ALIGNED_DIMENSION* aligned = static_cast<ALIGNED_DIMENSION*>( dimension.get() );
ALIGNED_DIMENSION* aligned = dynamic_cast<ALIGNED_DIMENSION*>( dimension.get() );
wxCHECK_MSG( aligned, nullptr, wxT( "Invalid extension_height token" ) );
aligned->SetExtensionHeight( parseBoardUnits( "extension height" ) );
NeedRIGHT();
break;

View File

@ -49,6 +49,7 @@
%{
class TEXTE_PCB;
class ALIGNED_DIMENSION;
class ORTHOGONAL_DIMENSION;
class LEADER;
class CENTER_DIMENSION;
class MODULE;
@ -70,22 +71,23 @@ class PCB_TARGET;
extern "C" {
#endif
static TEXTE_PCB* Cast_to_TEXTE_PCB( BOARD_ITEM* );
static ALIGNED_DIMENSION* Cast_to_ALIGNED_DIMENSION( BOARD_ITEM* );
static LEADER* Cast_to_LEADER( BOARD_ITEM* );
static CENTER_DIMENSION* Cast_to_CENTER_DIMENSION( BOARD_ITEM* );
static MODULE* Cast_to_MODULE( BOARD_ITEM* );
static PCB_GROUP* Cast_to_PCB_GROUP( BOARD_ITEM* );
static TEXTE_MODULE* Cast_to_TEXTE_MODULE( BOARD_ITEM* );
static DRAWSEGMENT* Cast_to_DRAWSEGMENT( BOARD_ITEM* );
static MARKER_PCB* Cast_to_MARKER_PCB( BOARD_ITEM* );
static BOARD* Cast_to_BOARD( BOARD_ITEM* );
static EDGE_MODULE* Cast_to_EDGE_MODULE( BOARD_ITEM* );
static D_PAD* Cast_to_D_PAD( BOARD_ITEM* );
static TRACK* Cast_to_TRACK( BOARD_ITEM* );
static VIA* Cast_to_VIA( BOARD_ITEM* );
static ZONE_CONTAINER* Cast_to_ZONE_CONTAINER( BOARD_ITEM* );
static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
static TEXTE_PCB* Cast_to_TEXTE_PCB( BOARD_ITEM* );
static ALIGNED_DIMENSION* Cast_to_ALIGNED_DIMENSION( BOARD_ITEM* );
static ORTHOGONAL_DIMENSION* Cast_to_ORTHOGONAL_DIMENSION( BOARD_ITEM* );
static LEADER* Cast_to_LEADER( BOARD_ITEM* );
static CENTER_DIMENSION* Cast_to_CENTER_DIMENSION( BOARD_ITEM* );
static MODULE* Cast_to_MODULE( BOARD_ITEM* );
static PCB_GROUP* Cast_to_PCB_GROUP( BOARD_ITEM* );
static TEXTE_MODULE* Cast_to_TEXTE_MODULE( BOARD_ITEM* );
static DRAWSEGMENT* Cast_to_DRAWSEGMENT( BOARD_ITEM* );
static MARKER_PCB* Cast_to_MARKER_PCB( BOARD_ITEM* );
static BOARD* Cast_to_BOARD( BOARD_ITEM* );
static EDGE_MODULE* Cast_to_EDGE_MODULE( BOARD_ITEM* );
static D_PAD* Cast_to_D_PAD( BOARD_ITEM* );
static TRACK* Cast_to_TRACK( BOARD_ITEM* );
static VIA* Cast_to_VIA( BOARD_ITEM* );
static ZONE_CONTAINER* Cast_to_ZONE_CONTAINER( BOARD_ITEM* );
static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
#ifdef __cplusplus
} // extern "C"
@ -93,22 +95,23 @@ static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
%}
static TEXTE_PCB* Cast_to_TEXTE_PCB( BOARD_ITEM* );
static ALIGNED_DIMENSION* Cast_to_ALIGNED_DIMENSION( BOARD_ITEM* );
static LEADER* Cast_to_LEADER( BOARD_ITEM* );
static CENTER_DIMENSION* Cast_to_CENTER_DIMENSION( BOARD_ITEM* );
static MODULE* Cast_to_MODULE( BOARD_ITEM* );
static PCB_GROUP* Cast_to_PCB_GROUP( BOARD_ITEM* );
static TEXTE_MODULE* Cast_to_TEXTE_MODULE( BOARD_ITEM* );
static DRAWSEGMENT* Cast_to_DRAWSEGMENT( BOARD_ITEM* );
static MARKER_PCB* Cast_to_MARKER_PCB( BOARD_ITEM* );
static BOARD* Cast_to_BOARD( BOARD_ITEM* );
static EDGE_MODULE* Cast_to_EDGE_MODULE( BOARD_ITEM* );
static D_PAD* Cast_to_D_PAD( BOARD_ITEM* );
static TRACK* Cast_to_TRACK( BOARD_ITEM* );
static VIA* Cast_to_VIA( BOARD_ITEM* );
static ZONE_CONTAINER* Cast_to_ZONE_CONTAINER( BOARD_ITEM* );
static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
static TEXTE_PCB* Cast_to_TEXTE_PCB( BOARD_ITEM* );
static ALIGNED_DIMENSION* Cast_to_ALIGNED_DIMENSION( BOARD_ITEM* );
static ORTHOGONAL_DIMENSION* Cast_to_ORTHOGONAL_DIMENSION( BOARD_ITEM* );
static LEADER* Cast_to_LEADER( BOARD_ITEM* );
static CENTER_DIMENSION* Cast_to_CENTER_DIMENSION( BOARD_ITEM* );
static MODULE* Cast_to_MODULE( BOARD_ITEM* );
static PCB_GROUP* Cast_to_PCB_GROUP( BOARD_ITEM* );
static TEXTE_MODULE* Cast_to_TEXTE_MODULE( BOARD_ITEM* );
static DRAWSEGMENT* Cast_to_DRAWSEGMENT( BOARD_ITEM* );
static MARKER_PCB* Cast_to_MARKER_PCB( BOARD_ITEM* );
static BOARD* Cast_to_BOARD( BOARD_ITEM* );
static EDGE_MODULE* Cast_to_EDGE_MODULE( BOARD_ITEM* );
static D_PAD* Cast_to_D_PAD( BOARD_ITEM* );
static TRACK* Cast_to_TRACK( BOARD_ITEM* );
static VIA* Cast_to_VIA( BOARD_ITEM* );
static ZONE_CONTAINER* Cast_to_ZONE_CONTAINER( BOARD_ITEM* );
static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
%extend BOARD_ITEM
@ -129,6 +132,8 @@ static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
return Cast_to_LEADER(self)
elif ct=="CENTER_DIMENSION":
return Cast_to_CENTER_DIMENSION(self)
elif ct=="ORTHOGONAL_DIMENSION":
return Cast_to_ORTHOGONAL_DIMENSION(self)
elif ct=="DRAWSEGMENT":
return Cast_to_DRAWSEGMENT(self)
elif ct=="MGRAPHIC":
@ -177,20 +182,21 @@ static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* );
// classes and therefore will C++ compile due to the respective headers which will go into
// the %header section. See section 5.6.2 of SWIG 3.0 documentation.
%wrapper %{
static TEXTE_PCB* Cast_to_TEXTE_PCB( BOARD_ITEM* self ) { return dynamic_cast<TEXTE_PCB*>(self); }
static ALIGNED_DIMENSION* Cast_to_ALIGNED_DIMENSION( BOARD_ITEM* self ) { return dynamic_cast<ALIGNED_DIMENSION*>(self); }
static LEADER* Cast_to_LEADER( BOARD_ITEM* self ) { return dynamic_cast<LEADER*>(self); }
static CENTER_DIMENSION* Cast_to_CENTER_DIMENSION( BOARD_ITEM* self ) { return dynamic_cast<CENTER_DIMENSION*>(self); }
static MODULE* Cast_to_MODULE( BOARD_ITEM* self ) { return dynamic_cast<MODULE*>(self); }
static PCB_GROUP* Cast_to_PCB_GROUP( BOARD_ITEM* self ) { return dynamic_cast<PCB_GROUP*>(self); }
static TEXTE_MODULE* Cast_to_TEXTE_MODULE( BOARD_ITEM* self ) { return dynamic_cast<TEXTE_MODULE*>(self); }
static DRAWSEGMENT* Cast_to_DRAWSEGMENT( BOARD_ITEM* self ) { return dynamic_cast<DRAWSEGMENT*>(self); }
static MARKER_PCB* Cast_to_MARKER_PCB( BOARD_ITEM* self ) { return dynamic_cast<MARKER_PCB*>(self); }
static BOARD* Cast_to_BOARD( BOARD_ITEM* self ) { return dynamic_cast<BOARD*>(self); }
static EDGE_MODULE* Cast_to_EDGE_MODULE( BOARD_ITEM* self ) { return dynamic_cast<EDGE_MODULE*>(self); }
static D_PAD* Cast_to_D_PAD( BOARD_ITEM* self ) { return dynamic_cast<D_PAD*>(self); }
static TRACK* Cast_to_TRACK( BOARD_ITEM* self ) { return dynamic_cast<TRACK*>(self); }
static VIA* Cast_to_VIA( BOARD_ITEM* self ) { return dynamic_cast<VIA*>(self); }
static ZONE_CONTAINER* Cast_to_ZONE_CONTAINER( BOARD_ITEM* self ) { return dynamic_cast<ZONE_CONTAINER*>(self); }
static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* self ) { return dynamic_cast<PCB_TARGET*>(self); }
static TEXTE_PCB* Cast_to_TEXTE_PCB( BOARD_ITEM* self ) { return dynamic_cast<TEXTE_PCB*>(self); }
static ALIGNED_DIMENSION* Cast_to_ALIGNED_DIMENSION( BOARD_ITEM* self ) { return dynamic_cast<ALIGNED_DIMENSION*>(self); }
static ORTHOGONAL_DIMENSION* Cast_to_ORTHOGONAL_DIMENSION( BOARD_ITEM* self ) { return dynamic_cast<ORTHOGONAL_DIMENSION*>(self); }
static LEADER* Cast_to_LEADER( BOARD_ITEM* self ) { return dynamic_cast<LEADER*>(self); }
static CENTER_DIMENSION* Cast_to_CENTER_DIMENSION( BOARD_ITEM* self ) { return dynamic_cast<CENTER_DIMENSION*>(self); }
static MODULE* Cast_to_MODULE( BOARD_ITEM* self ) { return dynamic_cast<MODULE*>(self); }
static PCB_GROUP* Cast_to_PCB_GROUP( BOARD_ITEM* self ) { return dynamic_cast<PCB_GROUP*>(self); }
static TEXTE_MODULE* Cast_to_TEXTE_MODULE( BOARD_ITEM* self ) { return dynamic_cast<TEXTE_MODULE*>(self); }
static DRAWSEGMENT* Cast_to_DRAWSEGMENT( BOARD_ITEM* self ) { return dynamic_cast<DRAWSEGMENT*>(self); }
static MARKER_PCB* Cast_to_MARKER_PCB( BOARD_ITEM* self ) { return dynamic_cast<MARKER_PCB*>(self); }
static BOARD* Cast_to_BOARD( BOARD_ITEM* self ) { return dynamic_cast<BOARD*>(self); }
static EDGE_MODULE* Cast_to_EDGE_MODULE( BOARD_ITEM* self ) { return dynamic_cast<EDGE_MODULE*>(self); }
static D_PAD* Cast_to_D_PAD( BOARD_ITEM* self ) { return dynamic_cast<D_PAD*>(self); }
static TRACK* Cast_to_TRACK( BOARD_ITEM* self ) { return dynamic_cast<TRACK*>(self); }
static VIA* Cast_to_VIA( BOARD_ITEM* self ) { return dynamic_cast<VIA*>(self); }
static ZONE_CONTAINER* Cast_to_ZONE_CONTAINER( BOARD_ITEM* self ) { return dynamic_cast<ZONE_CONTAINER*>(self); }
static PCB_TARGET* Cast_to_PCB_TARGET( BOARD_ITEM* self ) { return dynamic_cast<PCB_TARGET*>(self); }
%}

View File

@ -380,6 +380,7 @@ void PCB_EDIT_FRAME::ReCreateVToolbar()
m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE );
m_drawToolBar->Add( PCB_ACTIONS::drawAlignedDimension, ACTION_TOOLBAR::TOGGLE );
// TODO: re-insert when we have a multi-select tool button
// m_drawToolBar->Add( PCB_ACTIONS::drawOrthogonalDimension, ACTION_TOOLBAR::TOGGLE );
// m_drawToolBar->Add( PCB_ACTIONS::drawCenterDimension, ACTION_TOOLBAR::TOGGLE );
// m_drawToolBar->Add( PCB_ACTIONS::drawLeader, ACTION_TOOLBAR::TOGGLE );
m_drawToolBar->Add( PCB_ACTIONS::placeTarget, ACTION_TOOLBAR::TOGGLE );

View File

@ -731,19 +731,29 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
layer = Dwgs_User;
// Init the new item attributes
auto setMeasurementAttributes =
[&]( DIMENSION* aDim )
{
aDim->SetUnitsMode( boardSettings.m_DimensionUnitsMode );
aDim->SetUnitsFormat( boardSettings.m_DimensionUnitsFormat );
aDim->SetPrecision( boardSettings.m_DimensionPrecision );
aDim->SetSuppressZeroes( boardSettings.m_DimensionSuppressZeroes );
aDim->SetTextPositionMode( boardSettings.m_DimensionTextPosition );
aDim->SetKeepTextAligned( boardSettings.m_DimensionKeepTextAligned );
if( boardSettings.m_DimensionUnitsMode == DIM_UNITS_MODE::AUTOMATIC )
aDim->SetUnits( m_frame->GetUserUnits(), false );
};
if( originalEvent.IsAction( &PCB_ACTIONS::drawAlignedDimension ) )
{
dimension = new ALIGNED_DIMENSION( m_board );
dimension->SetUnitsMode( boardSettings.m_DimensionUnitsMode );
dimension->SetUnitsFormat( boardSettings.m_DimensionUnitsFormat );
dimension->SetPrecision( boardSettings.m_DimensionPrecision );
dimension->SetSuppressZeroes( boardSettings.m_DimensionSuppressZeroes );
dimension->SetTextPositionMode( boardSettings.m_DimensionTextPosition );
dimension->SetKeepTextAligned( boardSettings.m_DimensionKeepTextAligned );
if( boardSettings.m_DimensionUnitsMode == DIM_UNITS_MODE::AUTOMATIC )
dimension->SetUnits( m_frame->GetUserUnits(), false );
setMeasurementAttributes( dimension );
}
else if( originalEvent.IsAction( &PCB_ACTIONS::drawOrthogonalDimension ) )
{
dimension = new ORTHOGONAL_DIMENSION( m_board );
setMeasurementAttributes( dimension );
}
else if( originalEvent.IsAction( &PCB_ACTIONS::drawCenterDimension ) )
{
@ -863,10 +873,32 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
double height = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) );
aligned->SetHeight( height );
}
else if( dimension->Type() != PCB_DIM_CENTER_T )
else if( dimension->Type() == PCB_DIM_ORTHOGONAL_T )
{
wxASSERT( dimension->Type() == PCB_DIM_LEADER_T );
ORTHOGONAL_DIMENSION* ortho = static_cast<ORTHOGONAL_DIMENSION*>( dimension );
BOX2I bounds( dimension->GetStart(),
dimension->GetEnd() - dimension->GetStart() );
VECTOR2I direction( cursorPos - bounds.Centre() );
bool vert = std::abs( direction.y ) < std::abs( direction.x );
// Only change the orientation when we move outside the bounds
if( !bounds.Contains( cursorPos ) )
{
ortho->SetOrientation( vert ? ORTHOGONAL_DIMENSION::DIR::VERTICAL :
ORTHOGONAL_DIMENSION::DIR::HORIZONTAL );
}
else
{
vert = ortho->GetOrientation() == ORTHOGONAL_DIMENSION::DIR::VERTICAL;
}
VECTOR2I heightVector( cursorPos - dimension->GetStart() );
ortho->SetHeight( vert ? heightVector.x : heightVector.y );
}
else if( dimension->Type() == PCB_DIM_LEADER_T )
{
// Leader: SET_HEIGHT actually sets the text position directly
VECTOR2I lineVector( cursorPos - dimension->GetEnd() );
dimension->Text().SetPosition( wxPoint( VECTOR2I( dimension->GetEnd() ) +
GetVectorSnapped45( lineVector ) ) );
@ -2176,6 +2208,7 @@ void DRAWING_TOOL::setTransitions()
Go( &DRAWING_TOOL::DrawCircle, PCB_ACTIONS::drawCircle.MakeEvent() );
Go( &DRAWING_TOOL::DrawArc, PCB_ACTIONS::drawArc.MakeEvent() );
Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawAlignedDimension.MakeEvent() );
Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawOrthogonalDimension.MakeEvent() );
Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawCenterDimension.MakeEvent() );
Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawLeader.MakeEvent() );
Go( &DRAWING_TOOL::DrawZone, PCB_ACTIONS::drawZone.MakeEvent() );

View File

@ -547,6 +547,7 @@ void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bo
}
case PCB_DIM_ALIGNED_T:
case PCB_DIM_ORTHOGONAL_T:
{
const ALIGNED_DIMENSION* dim = static_cast<const ALIGNED_DIMENSION*>( aItem );
addAnchor( dim->GetCrossbarStart(), CORNER | SNAPPABLE, aItem );

View File

@ -127,6 +127,11 @@ TOOL_ACTION PCB_ACTIONS::drawCenterDimension( "pcbnew.InteractiveDrawing.centerD
_( "Add Center Dimension" ), _( "Add a center dimension" ),
add_center_dimension_xpm, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::drawOrthogonalDimension( "pcbnew.InteractiveDrawing.orthogonalDimension",
AS_GLOBAL, 0, "",
_( "Add Orthogonal Dimension" ), _( "Add an orthogonal dimension" ),
add_orthogonal_dimension_xpm, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::drawLeader( "pcbnew.InteractiveDrawing.leader",
AS_GLOBAL, 0, "",
_( "Add Leader" ), _( "Add a leader dimension" ),

View File

@ -144,6 +144,7 @@ public:
static TOOL_ACTION placeText;
static TOOL_ACTION drawAlignedDimension;
static TOOL_ACTION drawCenterDimension;
static TOOL_ACTION drawOrthogonalDimension;
static TOOL_ACTION drawLeader;
static TOOL_ACTION drawZone;
static TOOL_ACTION drawVia;

View File

@ -245,6 +245,7 @@ public:
break;
case PCB_DIM_ALIGNED_T:
case PCB_DIM_ORTHOGONAL_T:
{
const ALIGNED_DIMENSION* dimension = static_cast<const ALIGNED_DIMENSION*>( aItem );
@ -254,11 +255,16 @@ public:
points->AddPoint( dimension->GetCrossbarStart() );
points->AddPoint( dimension->GetCrossbarEnd() );
// Dimension height setting - edit points should move only along the feature lines
points->Point( DIM_CROSSBARSTART ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARSTART ),
points->Point( DIM_START ) ) );
points->Point( DIM_CROSSBAREND ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBAREND ),
points->Point( DIM_END ) ) );
if( aItem->Type() == PCB_DIM_ALIGNED_T )
{
// Dimension height setting - edit points should move only along the feature lines
points->Point( DIM_CROSSBARSTART )
.SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARSTART ),
points->Point( DIM_START ) ) );
points->Point( DIM_CROSSBAREND )
.SetConstraint( new EC_LINE( points->Point( DIM_CROSSBAREND ),
points->Point( DIM_END ) ) );
}
break;
}
@ -1336,6 +1342,52 @@ void POINT_EDITOR::updateItem() const
break;
}
case PCB_DIM_ORTHOGONAL_T:
{
ORTHOGONAL_DIMENSION* dimension = static_cast<ORTHOGONAL_DIMENSION*>( item );
BOX2I bounds( dimension->GetStart(),
dimension->GetEnd() - dimension->GetStart() );
VECTOR2I direction( m_editedPoint->GetPosition() - bounds.Centre() );
bool vert = std::abs( direction.y ) < std::abs( direction.x );
VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetStart() );
if( isModified( m_editPoints->Point( DIM_CROSSBARSTART ) ) ||
isModified( m_editPoints->Point( DIM_CROSSBAREND ) ) )
{
// Only change the orientation when we move outside the bounds
if( !bounds.Contains( m_editedPoint->GetPosition() ) )
{
dimension->SetOrientation( vert ? ORTHOGONAL_DIMENSION::DIR::VERTICAL :
ORTHOGONAL_DIMENSION::DIR::HORIZONTAL );
}
vert = dimension->GetOrientation() == ORTHOGONAL_DIMENSION::DIR::VERTICAL;
dimension->SetHeight( vert ? featureLine.x : featureLine.y );
}
else if( isModified( m_editPoints->Point( DIM_START ) ) )
{
dimension->SetStart( wxPoint( m_editedPoint->GetPosition().x,
m_editedPoint->GetPosition().y ) );
}
else if( isModified( m_editPoints->Point( DIM_END ) ) )
{
dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x,
m_editedPoint->GetPosition().y ) );
}
else if( isModified( m_editPoints->Point(DIM_TEXT ) ) )
{
// Force manual mode if we weren't already in it
dimension->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
dimension->Text().SetPosition( wxPoint( m_editedPoint->GetPosition() ) );
dimension->Update();
}
break;
}
case PCB_DIM_CENTER_T:
{
CENTER_DIMENSION* dimension = static_cast<CENTER_DIMENSION*>( item );
@ -1601,6 +1653,7 @@ void POINT_EDITOR::updatePoints()
}
case PCB_DIM_ALIGNED_T:
case PCB_DIM_ORTHOGONAL_T:
{
const ALIGNED_DIMENSION* dimension = static_cast<const ALIGNED_DIMENSION*>( item );