Fix bug: Impossible to rescale 3D models

This commit is contained in:
jean-pierre charras 2016-08-05 21:30:23 +02:00
parent 86496d3141
commit 7bc8cb56e0
4 changed files with 104 additions and 45 deletions

View File

@ -133,7 +133,7 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent,
wxStaticBoxSizer* vbox = new wxStaticBoxSizer( wxVERTICAL, this, _( "3D Preview" ) ); wxStaticBoxSizer* vbox = new wxStaticBoxSizer( wxVERTICAL, this, _( "3D Preview" ) );
wxFloatingPointValidator< float > valScale( 4 ); wxFloatingPointValidator< float > valScale( 4 );
valScale.SetRange( 0.0001f, 9999.0f ); valScale.SetRange( 0.0f, 9999.0f );
wxFloatingPointValidator< float > valRotate( 2 ); wxFloatingPointValidator< float > valRotate( 2 );
valRotate.SetRange( -180.0f, 180.0f ); valRotate.SetRange( -180.0f, 180.0f );
wxFloatingPointValidator< float > valOffset( 4 ); wxFloatingPointValidator< float > valOffset( 4 );
@ -157,11 +157,11 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent,
wxStaticText* txtS2 = new wxStaticText( modScale, -1, wxT( "Y:" ) ); wxStaticText* txtS2 = new wxStaticText( modScale, -1, wxT( "Y:" ) );
wxStaticText* txtS3 = new wxStaticText( modScale, -1, wxT( "Z:" ) ); wxStaticText* txtS3 = new wxStaticText( modScale, -1, wxT( "Z:" ) );
xscale = new wxTextCtrl( modScale, ID_SCALEX, "1.0", wxDefaultPosition, wxDefaultSize, xscale = new wxTextCtrl( modScale, ID_SCALEX, "1", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valScale ); wxTE_PROCESS_ENTER, valScale );
yscale = new wxTextCtrl( modScale, ID_SCALEY, "1.0", wxDefaultPosition, wxDefaultSize, yscale = new wxTextCtrl( modScale, ID_SCALEY, "1", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valScale ); wxTE_PROCESS_ENTER, valScale );
zscale = new wxTextCtrl( modScale, ID_SCALEZ, "1.0", wxDefaultPosition, wxDefaultSize, zscale = new wxTextCtrl( modScale, ID_SCALEZ, "1", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valScale ); wxTE_PROCESS_ENTER, valScale );
xscale->SetMaxLength( 9 ); xscale->SetMaxLength( 9 );
@ -184,11 +184,11 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent,
wxStaticText* txtR2 = new wxStaticText( modRotate, -1, wxT( "Y:" ) ); wxStaticText* txtR2 = new wxStaticText( modRotate, -1, wxT( "Y:" ) );
wxStaticText* txtR3 = new wxStaticText( modRotate, -1, wxT( "Z:" ) ); wxStaticText* txtR3 = new wxStaticText( modRotate, -1, wxT( "Z:" ) );
xrot = new wxTextCtrl( modRotate, ID_ROTX, "0.0", wxDefaultPosition, wxDefaultSize, xrot = new wxTextCtrl( modRotate, ID_ROTX, "0", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valRotate ); wxTE_PROCESS_ENTER, valRotate );
yrot = new wxTextCtrl( modRotate, ID_ROTY, "0.0", wxDefaultPosition, wxDefaultSize, yrot = new wxTextCtrl( modRotate, ID_ROTY, "0", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valRotate ); wxTE_PROCESS_ENTER, valRotate );
zrot = new wxTextCtrl( modRotate, ID_ROTZ, "0.0", wxDefaultPosition, wxDefaultSize, zrot = new wxTextCtrl( modRotate, ID_ROTZ, "0", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valRotate ); wxTE_PROCESS_ENTER, valRotate );
xrot->SetMaxLength( 9 ); xrot->SetMaxLength( 9 );
@ -211,11 +211,12 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent,
wxStaticText* txtO2 = new wxStaticText( modOffset, -1, wxT( "Y:" ) ); wxStaticText* txtO2 = new wxStaticText( modOffset, -1, wxT( "Y:" ) );
wxStaticText* txtO3 = new wxStaticText( modOffset, -1, wxT( "Z:" ) ); wxStaticText* txtO3 = new wxStaticText( modOffset, -1, wxT( "Z:" ) );
xoff = new wxTextCtrl( modOffset, ID_OFFX, "0.0", wxDefaultPosition, wxDefaultSize, // The default offset is 0.0 or 0,0, depending on floating point separator:
xoff = new wxTextCtrl( modOffset, ID_OFFX, "0", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valOffset ); wxTE_PROCESS_ENTER, valOffset );
yoff = new wxTextCtrl( modOffset, ID_OFFY, "0.0", wxDefaultPosition, wxDefaultSize, yoff = new wxTextCtrl( modOffset, ID_OFFY, "0", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valOffset ); wxTE_PROCESS_ENTER, valOffset );
zoff = new wxTextCtrl( modOffset, ID_OFFZ, "0.0", wxDefaultPosition, wxDefaultSize, zoff = new wxTextCtrl( modOffset, ID_OFFZ, "0", wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER, valOffset ); wxTE_PROCESS_ENTER, valOffset );
xoff->SetMaxLength( 10 ); xoff->SetMaxLength( 10 );
yoff->SetMaxLength( 10 ); yoff->SetMaxLength( 10 );
@ -442,26 +443,26 @@ void PANEL_PREV_3D::SetModelDataIdx( int idx, bool aReloadPreviewModule )
const S3D_INFO *aModel = (const S3D_INFO *)&((*m_parentInfoList)[idx]); const S3D_INFO *aModel = (const S3D_INFO *)&((*m_parentInfoList)[idx]);
xscale->SetValue( wxString::FromDouble( aModel->m_Scale.x ) ); xscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.x ) );
yscale->SetValue( wxString::FromDouble( aModel->m_Scale.y ) ); yscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.y ) );
zscale->SetValue( wxString::FromDouble( aModel->m_Scale.z ) ); zscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.z ) );
xrot->SetValue( wxString::FromDouble( aModel->m_Rotation.x ) ); xrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.x ) );
yrot->SetValue( wxString::FromDouble( aModel->m_Rotation.y ) ); yrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.y ) );
zrot->SetValue( wxString::FromDouble( aModel->m_Rotation.z ) ); zrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.z ) );
switch( g_UserUnit ) switch( g_UserUnit )
{ {
case MILLIMETRES: case MILLIMETRES:
xoff->SetValue( wxString::FromDouble( aModel->m_Offset.x * 25.4 ) ); xoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.x * 25.4 ) );
yoff->SetValue( wxString::FromDouble( aModel->m_Offset.y * 25.4 ) ); yoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.y * 25.4 ) );
zoff->SetValue( wxString::FromDouble( aModel->m_Offset.z * 25.4 ) ); zoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.z * 25.4 ) );
break; break;
case INCHES: case INCHES:
xoff->SetValue( wxString::FromDouble( aModel->m_Offset.x ) ); xoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.x ) );
yoff->SetValue( wxString::FromDouble( aModel->m_Offset.y ) ); yoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.y ) );
zoff->SetValue( wxString::FromDouble( aModel->m_Offset.z ) ); zoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.z ) );
break; break;
case DEGREES: case DEGREES:
@ -613,9 +614,6 @@ void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
if( m_previewPane ) if( m_previewPane )
m_previewPane->Refresh(); m_previewPane->Refresh();
} }
event.Skip();
return;
} }
@ -667,34 +665,72 @@ void PANEL_PREV_3D::getOrientationVars( SGPOINT& aScale, SGPOINT& aRotation, SGP
} }
void PANEL_PREV_3D::updateListOnModelCopy() bool PANEL_PREV_3D::Validate( wxString& aErrorMessage )
{ {
bool gotAnInvalidScale = false; bool invalidScale = false;
#define MIN_SCALE 0.001
#define MAX_SCALE 1000.0
for( unsigned int idx = 0; idx < m_parentInfoList->size(); ++idx ) for( unsigned int idx = 0; idx < m_parentInfoList->size(); ++idx )
{ {
SGPOINT scale = (*m_parentInfoList)[idx].m_Scale; wxString msg;
bool addError = false;
S3D_INFO& s3dshape = (*m_parentInfoList)[idx];
gotAnInvalidScale |= ( 0.0001 > scale.x || 0.0001 > scale.y || 0.0001 > scale.z ); SGPOINT scale = s3dshape.m_Scale;
if( 0.0001 > scale.x ) if( MIN_SCALE > scale.x || MAX_SCALE < scale.x )
scale.x = 1.0; {
invalidScale = true;
addError = true;
msg += _( "Invalid X scale" );
}
if( 0.0001 > scale.y ) if( MIN_SCALE > scale.y || MAX_SCALE < scale.y )
scale.y = 1.0; {
invalidScale = true;
addError = true;
if( 0.0001 > scale.y ) if( !msg.IsEmpty() )
scale.y = 1.0; msg += "\n";
(*m_parentInfoList)[idx].m_Scale = scale; msg += _( "Invalid Y scale" );
}
if( MIN_SCALE > scale.z || MAX_SCALE < scale.z )
{
invalidScale = true;
addError = true;
if( !msg.IsEmpty() )
msg += "\n";
msg += _( "Invalid Z scale" );
}
if( addError )
{
msg.Prepend( s3dshape.m_Filename + "\n" );
if( !aErrorMessage.IsEmpty() )
aErrorMessage += "\n\n";
aErrorMessage += msg;
}
} }
if( gotAnInvalidScale ) if( !aErrorMessage.IsEmpty() )
{ {
wxString errmsg = _("[INFO] invalid scale values; setting invalid to 1.0"); aErrorMessage += "\n\n";
wxLogMessage( "%s", errmsg.ToUTF8() ); aErrorMessage += wxString::Format( "Min value = %.4f and max value = %.4f",
MIN_SCALE, MAX_SCALE );
} }
return invalidScale == false;
}
void PANEL_PREV_3D::updateListOnModelCopy()
{
std::list<S3D_INFO>* draw3D = &m_copyModule->Models(); std::list<S3D_INFO>* draw3D = &m_copyModule->Models();
draw3D->clear(); draw3D->clear();
draw3D->insert( draw3D->end(), m_parentInfoList->begin(), m_parentInfoList->end() ); draw3D->insert( draw3D->end(), m_parentInfoList->begin(), m_parentInfoList->end() );

View File

@ -94,6 +94,13 @@ public:
void UpdateModelName( wxString const& aModel ); void UpdateModelName( wxString const& aModel );
/**
* @brief verify X,Y and Z scale factors are acceptable (> 0.001 and < 1000.0)
* @return false if one (or more) value is not acceptable.
* @param aErrorMessage is a wxString to store error messages, if any
*/
bool Validate( wxString& aErrorMessage );
private: private:
wxString currentModelFile; ///< Used to check if the model file was changed wxString currentModelFile; ///< Used to check if the model file was changed
S3D_FILENAME_RESOLVER *m_resolver; ///< Used to get the full path name S3D_FILENAME_RESOLVER *m_resolver; ///< Used to get the full path name

View File

@ -84,7 +84,7 @@ DIALOG_MODULE_BOARD_EDITOR::DIALOG_MODULE_BOARD_EDITOR( PCB_EDIT_FRAME* aParent
m_OrientValidator.SetWindow( m_OrientValueCtrl ); m_OrientValidator.SetWindow( m_OrientValueCtrl );
aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() ); aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() );
m_PreviewPane = new PANEL_PREV_3D( m_Panel3D, m_PreviewPane = new PANEL_PREV_3D( m_Panel3D,
aParent->Prj().Get3DCacheManager(), aParent->Prj().Get3DCacheManager(),
m_currentModuleCopy, m_currentModuleCopy,
@ -538,7 +538,7 @@ void DIALOG_MODULE_BOARD_EDITOR::BrowseAndAdd3DShapeFile()
long tmp; long tmp;
sidx.ToLong( &tmp ); sidx.ToLong( &tmp );
if( tmp > 0 && tmp <= 0x7FFFFFFF ) if( tmp > 0 && tmp <= INT_MAX )
filter = (int) tmp; filter = (int) tmp;
} }
@ -715,6 +715,14 @@ bool DIALOG_MODULE_BOARD_EDITOR::TransferDataFromWindow()
m_CurrentModule->Flip( m_CurrentModule->GetPosition() ); m_CurrentModule->Flip( m_CurrentModule->GetPosition() );
// This will update the S3D_INFO list into the current module // This will update the S3D_INFO list into the current module
msg.Clear();
if( !m_PreviewPane->Validate( msg ) ) // Verify the validity of 3D parameters
{
DisplayError( this, msg );
return false;
}
std::list<S3D_INFO>* draw3D = &m_CurrentModule->Models(); std::list<S3D_INFO>* draw3D = &m_CurrentModule->Models();
draw3D->clear(); draw3D->clear();
draw3D->insert( draw3D->end(), m_shapes3D_list.begin(), m_shapes3D_list.end() ); draw3D->insert( draw3D->end(), m_shapes3D_list.begin(), m_shapes3D_list.end() );

View File

@ -71,7 +71,7 @@ DIALOG_MODULE_MODULE_EDITOR::DIALOG_MODULE_MODULE_EDITOR( FOOTPRINT_EDIT_FRAME*
SetIcon( icon ); SetIcon( icon );
aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() ); aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() );
m_currentModuleCopy = new MODULE( *aModule ); m_currentModuleCopy = new MODULE( *aModule );
m_PreviewPane = new PANEL_PREV_3D( m_Panel3D, m_PreviewPane = new PANEL_PREV_3D( m_Panel3D,
@ -438,6 +438,8 @@ void DIALOG_MODULE_MODULE_EDITOR::OnCancelClick( wxCommandEvent& event )
void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
{ {
wxString msg;
// First, test for invalid chars in module name // First, test for invalid chars in module name
wxString footprintName = m_FootprintNameCtrl->GetValue(); wxString footprintName = m_FootprintNameCtrl->GetValue();
@ -445,16 +447,22 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
{ {
if( ! MODULE::IsLibNameValid( footprintName ) ) if( ! MODULE::IsLibNameValid( footprintName ) )
{ {
wxString msg;
msg.Printf( _( "Error:\none of invalid chars <%s> found\nin <%s>" ), msg.Printf( _( "Error:\none of invalid chars <%s> found\nin <%s>" ),
MODULE::StringLibNameInvalidChars( true ), MODULE::StringLibNameInvalidChars( true ),
GetChars( footprintName ) ); GetChars( footprintName ) );
DisplayError( NULL, msg ); DisplayError( NULL, msg );
return;
return;
} }
} }
if( !m_PreviewPane->Validate( msg ) ) // Verify the validity of 3D parameters
{
DisplayError( NULL, msg );
return;
}
m_parent->SaveCopyInUndoList( m_currentModule, UR_MODEDIT ); m_parent->SaveCopyInUndoList( m_currentModule, UR_MODEDIT );
m_currentModule->SetLocked( m_AutoPlaceCtrl->GetSelection() == 1 ); m_currentModule->SetLocked( m_AutoPlaceCtrl->GetSelection() == 1 );
@ -491,7 +499,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
m_currentModule->SetLocalSolderMaskMargin( ValueFromTextCtrl( *m_SolderMaskMarginCtrl ) ); m_currentModule->SetLocalSolderMaskMargin( ValueFromTextCtrl( *m_SolderMaskMarginCtrl ) );
m_currentModule->SetLocalSolderPasteMargin( ValueFromTextCtrl( *m_SolderPasteMarginCtrl ) ); m_currentModule->SetLocalSolderPasteMargin( ValueFromTextCtrl( *m_SolderPasteMarginCtrl ) );
double dtmp; double dtmp;
wxString msg = m_SolderPasteMarginRatioCtrl->GetValue(); msg = m_SolderPasteMarginRatioCtrl->GetValue();
msg.ToDouble( &dtmp ); msg.ToDouble( &dtmp );
// A -50% margin ratio means no paste on a pad, the ratio must be >= -50 % // A -50% margin ratio means no paste on a pad, the ratio must be >= -50 %