Added new constraint for EDIT_POINTs (EPC_LINE).

Dimensions have EDIT_POINTs.
Different handling of 45 degree mode in POINT_EDITOR.
This commit is contained in:
Maciej Suminski 2014-03-12 10:46:11 +01:00
parent 66fcb84f92
commit e6571f6862
6 changed files with 235 additions and 40 deletions

View File

@ -47,13 +47,9 @@
DIMENSION::DIMENSION( BOARD_ITEM* aParent ) :
BOARD_ITEM( aParent, PCB_DIMENSION_T ),
m_Text( this )
m_Width( Millimeter2iu( 0.2 ) ), m_Unit( INCHES ), m_Value( 0 ), m_Height( 0 ), m_Text( this )
{
m_Layer = DRAW_N;
m_Width = Millimeter2iu( 0.2 );
m_Value = 0;
m_Shape = 0;
m_Unit = INCHES;
}
@ -99,6 +95,7 @@ void DIMENSION::Copy( DIMENSION* source )
SetLayer( source->GetLayer() );
m_Width = source->m_Width;
m_Shape = source->m_Shape;
m_Height = source->m_Height;
m_Unit = source->m_Unit;
SetTimeStamp( GetNewTimeStamp() );
m_Text.Copy( &source->m_Text );
@ -195,7 +192,6 @@ void DIMENSION::Mirror( const wxPoint& axis_pos )
void DIMENSION::SetOrigin( const wxPoint& aOrigin )
{
m_crossBarO = aOrigin;
m_featureLineGO = aOrigin;
AdjustDimensionDetails();
@ -204,29 +200,32 @@ void DIMENSION::SetOrigin( const wxPoint& aOrigin )
void DIMENSION::SetEnd( const wxPoint& aEnd )
{
m_crossBarF = aEnd;
m_featureLineDO = aEnd;
AdjustDimensionDetails();
}
void DIMENSION::SetHeight( double aHeight )
void DIMENSION::SetHeight( int aHeight )
{
/* Calculating the direction of travel perpendicular to the selected axis. */
double angle = GetAngle() + ( M_PI / 2 );
int dx = KiROUND( aHeight * cos( angle ) );
int dy = KiROUND( aHeight * sin( angle ) );
m_crossBarO.x = m_featureLineGO.x + dx;
m_crossBarO.y = m_featureLineGO.y + dy;
m_crossBarF.x = m_featureLineDO.x + dx;
m_crossBarF.y = m_featureLineDO.y + dy;
m_Height = aHeight;
AdjustDimensionDetails();
}
void DIMENSION::UpdateHeight()
{
VECTOR2D featureLine( m_crossBarO - m_featureLineGO );
VECTOR2D crossBar( m_featureLineDO - m_featureLineGO );
if( featureLine.Cross( crossBar ) > 0 )
m_Height = -featureLine.EuclideanNorm();
else
m_Height = featureLine.EuclideanNorm();
}
void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText )
{
const int arrowz = DMils2iu( 500 ); // size of arrows
@ -281,6 +280,13 @@ void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText )
arrow_dw_Y = wxRound( arrowz * sin( angle_f ) );
}
int dx = KiROUND( m_Height * cos( angle + M_PI / 2 ) );
int dy = KiROUND( m_Height * sin( angle + M_PI / 2 ) );
m_crossBarO.x = m_featureLineGO.x + dx;
m_crossBarO.y = m_featureLineGO.y + dy;
m_crossBarF.x = m_featureLineDO.x + dx;
m_crossBarF.y = m_featureLineDO.y + dy;
m_arrowG1F.x = m_crossBarO.x + arrow_up_X;
m_arrowG1F.y = m_crossBarO.y + arrow_up_Y;

View File

@ -61,14 +61,13 @@ class MSG_PANEL_ITEM;
*/
class DIMENSION : public BOARD_ITEM
{
int m_Width;
int m_Shape; // / Currently always 0.
int m_Unit; // / 0 = inches, 1 = mm
int m_Value; // / value of PCB dimensions.
int m_Width; ///< Line width
int m_Shape; ///< Currently always 0.
EDA_UNITS_T m_Unit; ///< 0 = inches, 1 = mm
int m_Value; ///< value of PCB dimensions.
int m_Height; ///< length of feature lines
TEXTE_PCB m_Text;
public:
// TODO private: These member should be private. they are public only due to legacy code
wxPoint m_crossBarO, m_crossBarF;
@ -117,7 +116,7 @@ public:
*/
const wxPoint& GetOrigin() const
{
return m_crossBarO;
return m_featureLineGO;
}
/**
@ -133,7 +132,7 @@ public:
*/
const wxPoint& GetEnd()
{
return m_crossBarF;
return m_featureLineDO;
}
/**
@ -141,12 +140,27 @@ public:
* Sets the length of feature lines.
* @param aHeight is the new height.
*/
void SetHeight( double aHeight );
void SetHeight( int aHeight );
/**
* Function GetHeight
* Returns the length of feature lines.
*/
int GetHeight() const
{
return m_Height;
}
/**
* Function UpdateHeight
* Updates stored height basing on points coordinates.
*/
void UpdateHeight();
/**
* Function GetAngle
* Returns angle of the crossbar.
* @return Angle of the crossbar line.
* @return Angle of the crossbar line expressed in radians.
*/
double GetAngle() const
{

View File

@ -1438,6 +1438,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR )
parseXY( &dimension->m_featureLineDO.x, &dimension->m_featureLineDO.y );
parseXY( &dimension->m_featureLineDF.x, &dimension->m_featureLineDF.y );
dimension->UpdateHeight();
NeedRIGHT();
NeedRIGHT();
break;
@ -1451,6 +1452,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR )
parseXY( &dimension->m_featureLineGO.x, &dimension->m_featureLineGO.y );
parseXY( &dimension->m_featureLineGF.x, &dimension->m_featureLineGF.y );
dimension->UpdateHeight();
NeedRIGHT();
NeedRIGHT();
break;
@ -1465,6 +1467,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR )
parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
dimension->UpdateHeight();
NeedRIGHT();
NeedRIGHT();
break;

View File

@ -31,7 +31,7 @@
bool EDIT_POINT::WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const
{
// Corners of the square
// Corners of the EDIT_POINT square
VECTOR2I topLeft = GetPosition() - aSize;
VECTOR2I bottomRight = GetPosition() + aSize;
@ -162,6 +162,42 @@ void EPC_45DEGREE::Apply()
}
EPC_LINE::EPC_LINE( EDIT_POINT& aConstrained, EDIT_POINT& aConstrainer ) :
EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer )
{
Update();
}
void EPC_LINE::Apply()
{
VECTOR2I position = m_constrained.GetPosition();
if( std::isfinite( m_coefA ) )
{
if( abs( m_coefA ) < 1 )
position.y = m_coefA * position.x + m_coefB;
else
position.x = ( position.y - m_coefB ) / m_coefA;
}
else // vertical line
{
position.x = m_constrainer.GetX();
}
m_constrained.SetPosition( position );
}
void EPC_LINE::Update()
{
// Compute line coefficients
VECTOR2D delta = m_constrainer.GetPosition() - m_constrained.GetPosition();
m_coefA = delta.y / delta.x;
m_coefB = m_constrainer.GetY() - m_coefA * m_constrainer.GetX();
}
void EPC_CIRCLE::Apply()
{
VECTOR2I centerToEnd = m_end.GetPosition() - m_center.GetPosition();

View File

@ -97,6 +97,26 @@ public:
return m_position;
}
/**
* Function GetX()
*
* Returns X coordinate of an EDIT_POINT.
*/
int GetX() const
{
return GetPosition().x;
}
/**
* Function GetX()
*
* Returns Y coordinate of an EDIT_POINT.
*/
int GetY() const
{
return GetPosition().y;
}
/**
* Function SetPosition()
*
@ -132,6 +152,17 @@ public:
m_constraint = aConstraint;
}
/**
* Function GetConstraint()
*
* Returns the constraint imposed on an EDIT_POINT. If there are no constraints, NULL is
* returned.
*/
EDIT_POINT_CONSTRAINT* GetConstraint() const
{
return m_constraint;
}
/**
* Function ClearConstraint()
*
@ -468,6 +499,32 @@ private:
};
/**
* Class EPC_LINE
*
* EDIT_POINT_CONSTRAINT that imposes a constraint that a point has to lie on a line (determined
* by 2 points).
*/
class EPC_LINE : public EDIT_POINT_CONSTRAINT
{
public:
EPC_LINE( EDIT_POINT& aConstrained, EDIT_POINT& aConstrainer );
///> @copydoc EDIT_POINT_CONSTRAINT::Apply()
virtual void Apply();
/**
* Function Update()
* Updates line coefficients that make the constraining line.
*/
void Update();
private:
EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
double m_coefA, m_coefB;
};
/**
* Class EPC_CIRCLE.
*

View File

@ -35,6 +35,7 @@
#include <wxPcbStruct.h>
#include <class_drawsegment.h>
#include <class_dimension.h>
#include <class_zone.h>
/**
@ -60,8 +61,8 @@ public:
switch( segment->GetShape() )
{
case S_SEGMENT:
points->AddPoint( segment->GetStart() );
points->AddPoint( segment->GetEnd() );
points->AddPoint( segment->GetStart() ); // points[0]
points->AddPoint( segment->GetEnd() ); // points[1]
break;
case S_ARC:
@ -75,8 +76,8 @@ public:
break;
case S_CIRCLE:
points->AddPoint( segment->GetCenter() );
points->AddPoint( segment->GetEnd() );
points->AddPoint( segment->GetCenter() ); // points[0]
points->AddPoint( segment->GetEnd() ); // points[1]
break;
default: // suppress warnings
@ -98,8 +99,23 @@ public:
for( int i = 0; i < cornersCount - 1; ++i )
points->AddLine( (*points)[i], (*points)[i + 1] );
// The one missing line
// The last missing line, connecting the last and the first polygon point
points->AddLine( (*points)[cornersCount - 1], (*points)[0] );
break;
}
case PCB_DIMENSION_T:
{
const DIMENSION* dimension = static_cast<const DIMENSION*>( aItem );
points->AddPoint( dimension->m_featureLineGO );
points->AddPoint( dimension->m_featureLineDO );
points->AddPoint( dimension->m_crossBarO );
points->AddPoint( dimension->m_crossBarF );
// Dimension height setting - edit points should move only along the feature lines
(*points)[2].SetConstraint( new EPC_LINE( (*points)[2], (*points)[0] ) );
(*points)[3].SetConstraint( new EPC_LINE( (*points)[3], (*points)[1] ) );
break;
}
@ -118,7 +134,7 @@ private:
POINT_EDITOR::POINT_EDITOR() :
TOOL_INTERACTIVE( "pcbnew.PointEditor" ), m_selectionTool( NULL )
TOOL_INTERACTIVE( "pcbnew.PointEditor" ), m_selectionTool( NULL ), m_dragPoint( NULL )
{
}
@ -159,6 +175,7 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent )
PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
EDA_ITEM* item = selection.items.GetPickedItem( 0 );
EDIT_POINT constrainer( VECTOR2I( 0, 0 ) );
bool degree45 = false; // 45 degree mode
m_editPoints = EDIT_POINTS_FACTORY::Make( item );
if( !m_editPoints )
@ -218,19 +235,21 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent )
modified = true;
}
if( evt->Modifier( MD_CTRL ) ) // 45 degrees mode
if( evt->Modifier( MD_CTRL ) != degree45 ) // 45 degrees mode
{
if( !m_dragPoint->IsConstrained() )
degree45 = evt->Modifier( MD_CTRL );
if( degree45 )
{
// Find a proper constraining point for 45 degrees mode
constrainer = get45DegConstrainer();
m_dragPoint->SetConstraint( new EPC_45DEGREE( *m_dragPoint, constrainer ) );
}
}
else
{
m_dragPoint->ClearConstraint();
}
}
m_dragPoint->SetPosition( controls->GetCursorPosition() );
m_dragPoint->ApplyConstraint();
@ -387,6 +406,47 @@ void POINT_EDITOR::updateItem() const
break;
}
case PCB_DIMENSION_T:
{
DIMENSION* dimension = static_cast<DIMENSION*>( item );
// Check which point is currently modified and updated dimension's points respectively
if( isModified( (*m_editPoints)[0] ) )
{
dimension->SetOrigin( wxPoint( m_dragPoint->GetPosition().x, m_dragPoint->GetPosition().y ) );
static_cast<EPC_LINE*>( (*m_editPoints)[2].GetConstraint() )->Update();
static_cast<EPC_LINE*>( (*m_editPoints)[3].GetConstraint() )->Update();
}
else if( isModified( (*m_editPoints)[1] ) )
{
dimension->SetEnd( wxPoint( m_dragPoint->GetPosition().x, m_dragPoint->GetPosition().y ) );
static_cast<EPC_LINE*>( (*m_editPoints)[2].GetConstraint() )->Update();
static_cast<EPC_LINE*>( (*m_editPoints)[3].GetConstraint() )->Update();
}
else if( isModified( (*m_editPoints)[2] ) )
{
VECTOR2D featureLine( m_dragPoint->GetPosition() - dimension->GetOrigin() );
VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
if( featureLine.Cross( crossBar ) > 0 )
dimension->SetHeight( -featureLine.EuclideanNorm() );
else
dimension->SetHeight( featureLine.EuclideanNorm() );
}
else if( isModified( (*m_editPoints)[3] ) )
{
VECTOR2D featureLine( m_dragPoint->GetPosition() - dimension->GetEnd() );
VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
if( featureLine.Cross( crossBar ) > 0 )
dimension->SetHeight( -featureLine.EuclideanNorm() );
else
dimension->SetHeight( featureLine.EuclideanNorm() );
}
break;
}
default:
break;
}
@ -454,6 +514,17 @@ void POINT_EDITOR::updatePoints() const
break;
}
case PCB_DIMENSION_T:
{
const DIMENSION* dimension = static_cast<const DIMENSION*>( item );
(*m_editPoints)[0].SetPosition( dimension->m_featureLineGO );
(*m_editPoints)[1].SetPosition( dimension->m_featureLineDO );
(*m_editPoints)[2].SetPosition( dimension->m_crossBarO );
(*m_editPoints)[3].SetPosition( dimension->m_crossBarF );
break;
}
default:
break;
}
@ -482,6 +553,14 @@ EDIT_POINT POINT_EDITOR::get45DegConstrainer() const
}
}
}
else if( item->Type() == PCB_DIMENSION_T )
{
// Constraint for crossbar
if( isModified( (*m_editPoints)[0] ) )
return (*m_editPoints)[1];
else if( isModified( (*m_editPoints)[1] ) )
return (*m_editPoints)[0];
}
// In any other case we may align item to the current cursor position.
return EDIT_POINT( getViewControls()->GetCursorPosition() );