Don't truncate polar coordinates in position relative dialog/move exact dialog

This commit is contained in:
Andrew Downing 2020-02-29 02:21:18 +00:00 committed by Seth Hillbrand
parent 3f31d48b5e
commit 2f7ac2b5b4
6 changed files with 163 additions and 61 deletions

View File

@ -195,6 +195,12 @@ void UNIT_BINDER::SetValue( int aValue )
}
void UNIT_BINDER::SetDoubleValue( double aValue )
{
SetValue( StringFromValue( m_units, aValue, false, m_useMils ) );
}
void UNIT_BINDER::SetValue( wxString aValue )
{
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
@ -257,6 +263,28 @@ long long int UNIT_BINDER::GetValue()
}
double UNIT_BINDER::GetDoubleValue()
{
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
auto staticText = dynamic_cast<wxStaticText*>( m_value );
wxString value;
if( textEntry )
{
if( m_needsEval && m_eval.Process( textEntry->GetValue() ) )
value = m_eval.Result();
else
value = textEntry->GetValue();
}
else if( staticText )
value = staticText->GetLabel();
else
return 0.0;
return DoubleValueFromString( m_units, value, m_useMils );
}
bool UNIT_BINDER::IsIndeterminate() const
{
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );

View File

@ -71,6 +71,13 @@ public:
void SetValue( wxString aValue );
/**
* Function SetDoubleValue
* Sets new value (in Internal Units) for the text field, taking care of units conversion.
* @param aValue is the new value.
*/
virtual void SetDoubleValue( double aValue );
/**
* Function ChangeValue
* Changes the value (in Internal Units) for the text field, taking care of units conversion
@ -87,6 +94,12 @@ public:
*/
virtual long long int GetValue();
/**
* Function GetValue
* Returns the current value in Internal Units.
*/
virtual double GetDoubleValue();
/**
* Function IsIndeterminate
* Returns true if the control holds the indeterminate value (for instance, if it

View File

@ -41,7 +41,11 @@ DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT( PCB_BASE_FRAME *aParent, wxPoint& aTransla
m_bbox( aBbox ),
m_moveX( aParent, m_xLabel, m_xEntry, m_xUnit ),
m_moveY( aParent, m_yLabel, m_yEntry, m_yUnit ),
m_rotate( aParent, m_rotLabel, m_rotEntry, m_rotUnit )
m_rotate( aParent, m_rotLabel, m_rotEntry, m_rotUnit ),
m_stateX( 0.0 ),
m_stateY( 0.0 ),
m_stateRadius( 0.0 ),
m_stateTheta( 0.0 )
{
// We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
// implementation on MSW
@ -66,8 +70,8 @@ DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT( PCB_BASE_FRAME *aParent, wxPoint& aTransla
// and set up the entries according to the saved options
m_polarCoords->SetValue( m_options.polarCoords );
m_moveX.SetValue( m_options.entry1 );
m_moveY.SetValue( m_options.entry2 );
m_moveX.SetDoubleValue( m_options.entry1 );
m_moveY.SetDoubleValue( m_options.entry2 );
m_rotate.SetUnits( EDA_UNITS::DEGREES );
m_rotate.SetValue( m_options.entryRotation );
@ -115,12 +119,12 @@ void DIALOG_MOVE_EXACT::ToPolarDeg( double x, double y, double& r, double& q )
}
bool DIALOG_MOVE_EXACT::GetTranslationInIU ( wxPoint& val, bool polar )
bool DIALOG_MOVE_EXACT::GetTranslationInIU( wxRealPoint& val, bool polar )
{
if( polar )
{
const int r = m_moveX.GetValue();
const double q = m_moveY.GetValue();
const double r = m_moveX.GetDoubleValue();
const double q = m_moveY.GetDoubleValue();
val.x = r * cos( DEG2RAD( q / 10.0 ) );
val.y = r * sin( DEG2RAD( q / 10.0 ) );
@ -128,8 +132,8 @@ bool DIALOG_MOVE_EXACT::GetTranslationInIU ( wxPoint& val, bool polar )
else
{
// direct read
val.x = m_moveX.GetValue();
val.y = m_moveY.GetValue();
val.x = m_moveX.GetDoubleValue();
val.y = m_moveY.GetDoubleValue();
}
// no validation to do here, but in future, you could return false here
@ -140,33 +144,50 @@ bool DIALOG_MOVE_EXACT::GetTranslationInIU ( wxPoint& val, bool polar )
void DIALOG_MOVE_EXACT::OnPolarChanged( wxCommandEvent& event )
{
bool newPolar = m_polarCoords->IsChecked();
wxPoint val;
// get the value as previously stored
GetTranslationInIU( val, !newPolar );
// now switch the controls to the new representations
double moveX = m_moveX.GetDoubleValue();
double moveY = m_moveY.GetDoubleValue();
updateDialogControls( newPolar );
if( newPolar )
{
// convert to polar coordinates
double r, q;
ToPolarDeg( val.x, val.y, r, q );
if( moveX != m_stateX || moveY != m_stateY )
{
m_stateX = moveX;
m_stateY = moveY;
ToPolarDeg( m_stateX, m_stateY, m_stateRadius, m_stateTheta );
m_stateTheta *= 10.0;
m_moveX.SetValue( KiROUND( r / 10.0) * 10 );
m_moveY.SetValue( q * 10 );
m_moveX.SetDoubleValue( m_stateRadius );
m_stateRadius = m_moveX.GetDoubleValue();
m_moveY.SetDoubleValue( m_stateTheta );
m_stateTheta = m_moveY.GetDoubleValue();
}
else
{
// vector is already in Cartesian, so just render out
// note - round off the last decimal place (10nm) to prevent
// (some) rounding causing errors when round-tripping
// you can never eliminate entirely, however
m_moveX.SetValue( KiROUND( val.x / 10.0 ) * 10 );
m_moveY.SetValue( KiROUND( val.y / 10.0 ) * 10 );
m_moveX.SetDoubleValue( m_stateRadius );
m_moveY.SetDoubleValue( m_stateTheta );
}
}
else
{
if( moveX != m_stateRadius || moveY != m_stateTheta )
{
m_stateRadius = moveX;
m_stateTheta = moveY;
m_stateX = m_stateRadius * cos( DEG2RAD( m_stateTheta / 10.0 ) );
m_stateY = m_stateRadius * sin( DEG2RAD( m_stateTheta / 10.0 ) );
m_moveX.SetDoubleValue( m_stateX );
m_stateX = m_moveX.GetDoubleValue();
m_moveY.SetDoubleValue( m_stateY );
m_stateY = m_moveY.GetDoubleValue();
}
else
{
m_moveX.SetDoubleValue( m_stateX );
m_moveY.SetDoubleValue( m_stateY );
}
}
}
@ -214,7 +235,10 @@ void DIALOG_MOVE_EXACT::OnClear( wxCommandEvent& event )
bool DIALOG_MOVE_EXACT::TransferDataFromWindow()
{
// for the output, we only deliver a Cartesian vector
bool ok = GetTranslationInIU( m_translation, m_polarCoords->IsChecked() );
wxRealPoint translation;
bool ok = GetTranslationInIU( translation, m_polarCoords->IsChecked() );
m_translation.x = KiROUND(translation.x);
m_translation.y = KiROUND(translation.y);
m_rotation = m_rotate.GetValue();
m_rotationAnchor = m_menuIDs[ m_anchorOptions->GetSelection() ];
@ -222,8 +246,8 @@ bool DIALOG_MOVE_EXACT::TransferDataFromWindow()
{
// save the settings
m_options.polarCoords = m_polarCoords->GetValue();
m_options.entry1 = m_moveX.GetValue();
m_options.entry2 = m_moveY.GetValue();
m_options.entry1 = m_moveX.GetDoubleValue();
m_options.entry2 = m_moveY.GetDoubleValue();
m_options.entryRotation = m_rotate.GetValue();
m_options.entryAnchorSelection = (size_t) std::max( m_anchorOptions->GetSelection(), 0 );
return true;
@ -247,8 +271,8 @@ void DIALOG_MOVE_EXACT::OnTextFocusLost( wxFocusEvent& event )
void DIALOG_MOVE_EXACT::OnTextChanged( wxCommandEvent& event )
{
double delta_x = m_moveX.GetValue();
double delta_y = m_moveY.GetValue();
double delta_x = m_moveX.GetDoubleValue();
double delta_y = m_moveY.GetDoubleValue();
double max_border = std::numeric_limits<int>::max() * 0.7071;
if( m_bbox.GetLeft() + delta_x < -max_border ||

View File

@ -57,6 +57,12 @@ private:
std::vector<ROTATION_ANCHOR> m_menuIDs;
double m_stateX;
double m_stateY;
double m_stateRadius;
double m_stateTheta;
public:
// Constructor and destructor
DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, wxPoint& aTranslate,
@ -92,7 +98,7 @@ private:
* @param polar interpret as polar coords
* @return false if error (though the text conversion functions don't report errors)
*/
bool GetTranslationInIU ( wxPoint& val, bool polar );
bool GetTranslationInIU( wxRealPoint& val, bool polar );
void buildRotationAnchorMenu();

View File

@ -38,7 +38,11 @@ DIALOG_POSITION_RELATIVE::DIALOG_POSITION_RELATIVE( PCB_BASE_FRAME* aParent, wxP
m_translation( translation ),
m_anchor_position( anchor ),
m_xOffset( aParent, m_xLabel, m_xEntry, m_xUnit ),
m_yOffset( aParent, m_yLabel, m_yEntry, m_yUnit )
m_yOffset( aParent, m_yLabel, m_yEntry, m_yUnit ),
m_stateX( 0.0 ),
m_stateY( 0.0 ),
m_stateRadius( 0.0 ),
m_stateTheta( 0.0 )
{
// We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
// implementation on MSW
@ -55,8 +59,8 @@ DIALOG_POSITION_RELATIVE::DIALOG_POSITION_RELATIVE( PCB_BASE_FRAME* aParent, wxP
m_polarCoords->SetValue( m_options.polarCoords );
updateDialogControls( m_polarCoords->IsChecked() );
m_xOffset.SetValue( m_options.entry1 );
m_yOffset.SetValue( m_options.entry2 );
m_xOffset.SetDoubleValue( m_options.entry1 );
m_yOffset.SetDoubleValue( m_options.entry2 );
m_stdButtonsOK->SetDefault();
@ -73,12 +77,12 @@ void DIALOG_POSITION_RELATIVE::ToPolarDeg( double x, double y, double& r, double
}
bool DIALOG_POSITION_RELATIVE::GetTranslationInIU ( wxPoint& val, bool polar )
bool DIALOG_POSITION_RELATIVE::GetTranslationInIU( wxRealPoint& val, bool polar )
{
if( polar )
{
const int r = m_xOffset.GetValue();
const double q = m_yOffset.GetValue();
const double r = m_xOffset.GetDoubleValue();
const double q = m_yOffset.GetDoubleValue();
val.x = r * cos( DEG2RAD( q / 10.0 ) );
val.y = r * sin( DEG2RAD( q / 10.0 ) );
@ -86,8 +90,8 @@ bool DIALOG_POSITION_RELATIVE::GetTranslationInIU ( wxPoint& val, bool polar )
else
{
// direct read
val.x = m_xOffset.GetValue();
val.y = m_yOffset.GetValue();
val.x = m_xOffset.GetDoubleValue();
val.y = m_yOffset.GetDoubleValue();
}
// no validation to do here, but in future, you could return false here
@ -98,31 +102,49 @@ bool DIALOG_POSITION_RELATIVE::GetTranslationInIU ( wxPoint& val, bool polar )
void DIALOG_POSITION_RELATIVE::OnPolarChanged( wxCommandEvent& event )
{
bool newPolar = m_polarCoords->IsChecked();
wxPoint val;
// get the value as previously stored
GetTranslationInIU( val, !newPolar );
// now switch the controls to the new representations
double xOffset = m_xOffset.GetDoubleValue();
double yOffset = m_yOffset.GetDoubleValue();
updateDialogControls( newPolar );
if( newPolar )
{
// convert to polar coordinates
double r, q;
ToPolarDeg( val.x, val.y, r, q );
if( xOffset != m_stateX || yOffset != m_stateY )
{
m_stateX = xOffset;
m_stateY = yOffset;
ToPolarDeg( m_stateX, m_stateY, m_stateRadius, m_stateTheta );
m_stateTheta *= 10.0;
m_xOffset.SetValue( KiROUND( r / 10.0) * 10 );
m_yOffset.SetValue( q * 10 );
m_xOffset.SetDoubleValue( m_stateRadius );
m_stateRadius = m_xOffset.GetDoubleValue();
m_yOffset.SetDoubleValue( m_stateTheta );
m_stateTheta = m_yOffset.GetDoubleValue();
}
else
{
// vector is already in Cartesian, so just render out
// note - round off the last decimal place (10nm) to prevent
// (some) rounding causing errors when round-tripping
// you can never eliminate entirely, however
m_xOffset.SetValue( KiROUND( val.x / 10.0 ) * 10 );
m_yOffset.SetValue( KiROUND( val.y / 10.0 ) * 10 );
m_xOffset.SetDoubleValue( m_stateRadius );
m_yOffset.SetDoubleValue( m_stateTheta );
}
}
else
{
if( xOffset != m_stateRadius || yOffset != m_stateTheta )
{
m_stateRadius = xOffset;
m_stateTheta = yOffset;
m_stateX = m_stateRadius * cos( DEG2RAD( m_stateTheta / 10.0 ) );
m_stateY = m_stateRadius * sin( DEG2RAD( m_stateTheta / 10.0 ) );
m_xOffset.SetDoubleValue( m_stateX );
m_stateX = m_xOffset.GetDoubleValue();
m_yOffset.SetDoubleValue( m_stateY );
m_stateY = m_yOffset.GetDoubleValue();
}
else
{
m_xOffset.SetDoubleValue( m_stateX );
m_yOffset.SetDoubleValue( m_stateY );
}
}
}
@ -209,14 +231,17 @@ void DIALOG_POSITION_RELATIVE::UpdateAnchor( EDA_ITEM* aItem )
void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event )
{
// for the output, we only deliver a Cartesian vector
bool ok = GetTranslationInIU( m_translation, m_polarCoords->IsChecked() );
wxRealPoint translation;
bool ok = GetTranslationInIU( translation, m_polarCoords->IsChecked() );
m_translation.x = KiROUND( translation.x );
m_translation.y = KiROUND( translation.y );
if( ok )
{
// save the settings
m_options.polarCoords = m_polarCoords->GetValue();
m_options.entry1 = m_xOffset.GetValue();
m_options.entry2 = m_yOffset.GetValue();
m_options.entry1 = m_xOffset.GetDoubleValue();
m_options.entry2 = m_yOffset.GetDoubleValue();
POSITION_RELATIVE_TOOL* posrelTool = m_toolMgr->GetTool<POSITION_RELATIVE_TOOL>();
wxASSERT( posrelTool );

View File

@ -43,6 +43,12 @@ private:
UNIT_BINDER m_xOffset;
UNIT_BINDER m_yOffset;
double m_stateX;
double m_stateY;
double m_stateRadius;
double m_stateTheta;
public:
// Constructor and destructor
DIALOG_POSITION_RELATIVE( PCB_BASE_FRAME* aParent, wxPoint& translation, wxPoint& anchor );
@ -79,7 +85,7 @@ private:
* @param polar interpret as polar coords
* @return false if error (though the text conversion functions don't report errors)
*/
bool GetTranslationInIU( wxPoint& val, bool polar );
bool GetTranslationInIU( wxRealPoint& val, bool polar );
// Update controls and their labels after changing the coordinates type (polar/cartesian)
void updateDialogControls( bool aPolar );