PNS: Add a setting to disable posture solver

PNS: Prevent autoposture flutter when trail has little area

Fixes https://gitlab.com/kicad/code/kicad/-/issues/6797
This commit is contained in:
Jon Evans 2020-12-23 17:02:29 -05:00
parent eb1f07bade
commit 8c247fc97c
8 changed files with 111 additions and 11 deletions

View File

@ -48,6 +48,8 @@ DIALOG_PNS_SETTINGS::DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS::ROUTING_SETTIN
m_freeAngleMode->SetValue( m_settings.GetFreeAngleMode() );
m_dragToolMode->SetSelection ( m_settings.InlineDragEnabled() ? 1 : 0 );
m_optimizeDraggedTrack->SetValue( m_settings.GetOptimizeDraggedTrack() );
m_autoPosture->SetValue( m_settings.GetAutoPosture() );
// Enable/disable some options
wxCommandEvent event;
onModeChange( event );
@ -75,6 +77,7 @@ void DIALOG_PNS_SETTINGS::OnOkClick( wxCommandEvent& aEvent )
m_settings.SetSmoothDraggedSegments( m_smoothDragged->GetValue() );
m_settings.SetInlineDragEnabled( m_dragToolMode->GetSelection () ? true : false );
m_settings.SetOptimizeDraggedTrack( m_optimizeDraggedTrack->GetValue() );
m_settings.SetAutoPosture( m_autoPosture->GetValue() );
if( m_mode->GetSelection() == PNS::RM_MarkObstacles )
{

View File

@ -86,6 +86,11 @@ DIALOG_PNS_SETTINGS_BASE::DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID
m_optimizeDraggedTrack = new wxCheckBox( bOptions->GetStaticBox(), wxID_ANY, _("Optimize track being dragged"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_optimizeDraggedTrack, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_autoPosture = new wxCheckBox( bOptions->GetStaticBox(), wxID_ANY, _("Use mouse path to set track posture"), wxDefaultPosition, wxDefaultSize, 0 );
m_autoPosture->SetToolTip( _("When enabled, the posture of tracks will be guided by how the mouse is moved from the starting location") );
bOptions->Add( m_autoPosture, 0, wxALL, 5 );
wxBoxSizer* bEffort;
bEffort = new wxBoxSizer( wxHORIZONTAL );

View File

@ -857,6 +857,70 @@
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Use mouse path to set track posture</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_autoPosture</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">When enabled, the posture of tracks will be guided by how the mouse is moved from the starting location</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>

View File

@ -49,6 +49,7 @@ class DIALOG_PNS_SETTINGS_BASE : public DIALOG_SHIM
wxCheckBox* m_violateDrc;
wxCheckBox* m_suggestEnding;
wxCheckBox* m_optimizeDraggedTrack;
wxCheckBox* m_autoPosture;
wxStaticText* m_effortLabel;
wxSlider* m_effort;
wxStaticText* m_lowLabel;

View File

@ -1408,7 +1408,7 @@ bool LINE_PLACER::buildInitialLine( const VECTOR2I& aP, LINE& aHead )
initial_radius = Settings().GetMaxRadius();
if( !m_tail.PointCount() )
if( !m_tail.PointCount() && Settings().GetAutoPosture() )
l = guessedDir.BuildInitialTrace( m_p_start, aP, false, initial_radius );
else
l = m_direction.BuildInitialTrace( m_p_start, aP, false, initial_radius );
@ -1571,8 +1571,17 @@ void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
{
// Tuning factor for how good the "fit" of the trail must be to the posture
const double areaRatioThreshold = 1.5;
// Tuning factor to minimize flutter
const double areaRatioEpsilon = 0.3;
// Minimum distance factor of the trail before the min area test is used to lock the solver
const double minAreaCutoffDistanceFactor = 6;
// Adjusts how far away from p0 we get before whatever posture we solved is locked in
const int lockDistanceFactor = 40;
const int lockDistanceFactor = 25;
// Adjusts how close to p0 we unlock the posture again if one was locked already
const int unlockDistanceFactor = 4;
@ -1589,17 +1598,19 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
SHAPE_LINE_CHAIN straight( DIRECTION_45().BuildInitialTrace( p0, aP, false ) );
straight.SetClosed( true );
straight.Append( m_trail.Reverse() );
straight.Simplify();
dbg->AddLine( straight, m_forced ? 3 : 2, 100000 );
double areaS = straight.Area();
double areaS = std::abs( straight.Area() );
SHAPE_LINE_CHAIN diag( DIRECTION_45().BuildInitialTrace( p0, aP, true ) );
diag.Append( m_trail.Reverse() );
diag.SetClosed( true );
diag.Simplify();
dbg->AddLine( diag, 1, 100000 );
double areaDiag = diag.Area();
double ratio = abs( areaS ) / ( fabs( areaDiag ) + 1.0 );
double areaDiag = std::abs( diag.Area() );
double ratio = areaS / ( areaDiag + 1.0 );
// heuristic to detect that the user dragged back the cursor to the beginning of the trace
// in this case, we cancel any forced posture and restart the trail
@ -1611,15 +1622,29 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
m_trail.Append( start );
}
bool areaOk = true;
// Check the actual trail area against the cutoff. This prevents flutter when the trail is
// very close to a straight line.
if( !m_forced && refLength > minAreaCutoffDistanceFactor * m_tolerance )
{
double areaCutoff = m_tolerance * refLength;
SHAPE_LINE_CHAIN trail( m_trail );
trail.SetClosed( true );
if( std::abs( trail.Area() ) < areaCutoff )
areaOk = false;
}
// If we get far away from the initial point, lock in the current solution to prevent flutter
if( !m_forced && refLength > lockDistanceFactor * m_tolerance )
m_forced = true;
if( m_forced )
return m_direction;
else if( ratio > areaRatioThreshold + areaRatioEpsilon )
else if( areaOk && ratio > areaRatioThreshold + areaRatioEpsilon )
m_direction = DIRECTION_45::NE;
else if( ratio < ( 1.0 / areaRatioThreshold ) - areaRatioEpsilon )
else if( areaOk && ratio < ( 1.0 / areaRatioThreshold ) - areaRatioEpsilon )
m_direction = DIRECTION_45::N;
else if( m_lastSegDirection != DIRECTION_45::UNDEFINED )
m_direction = m_lastSegDirection;
@ -1634,6 +1659,5 @@ void POSTURE_SOLVER::FlipPosture()
m_forced = true;
}
}

View File

@ -94,9 +94,6 @@ public:
void FlipPosture();
private:
const double areaRatioThreshold = 1.5;
const double areaRatioEpsilon = 0.2;
SHAPE_LINE_CHAIN m_trail;
int m_tolerance;
DIRECTION_45 m_direction;

View File

@ -54,6 +54,7 @@ ROUTING_SETTINGS::ROUTING_SETTINGS( JSON_SETTINGS* aParent, const std::string& a
m_minRadius = 0;
m_maxRadius = 1000000;
m_roundedCorners = false;
m_autoPosture = true;
m_params.emplace_back( new PARAM<int>( "mode", reinterpret_cast<int*>( &m_routingMode ),
static_cast<int>( RM_Walkaround ) ) );
@ -95,6 +96,7 @@ ROUTING_SETTINGS::ROUTING_SETTINGS( JSON_SETTINGS* aParent, const std::string& a
m_params.emplace_back( new PARAM<int>( "min_radius", &m_minRadius, 0 ) );
m_params.emplace_back( new PARAM<int>( "max_radius", &m_maxRadius, 1000000 ) );
m_params.emplace_back( new PARAM<bool>( "use_rounded", &m_roundedCorners, false ) );
m_params.emplace_back( new PARAM<bool>( "auto_posture", &m_autoPosture, true ) );
LoadFromFile();
}

View File

@ -147,6 +147,9 @@ public:
bool GetOptimizeDraggedTrack() const { return m_optimizeDraggedTrack; }
void SetOptimizeDraggedTrack( bool aEnable ) { m_optimizeDraggedTrack = aEnable; }
bool GetAutoPosture() const { return m_autoPosture; }
void SetAutoPosture( bool aEnable ) { m_autoPosture = aEnable; }
void SetMinRadius( int aRadius )
{
m_minRadius = aRadius;
@ -182,6 +185,7 @@ private:
bool m_snapToPads;
bool m_roundedCorners;
bool m_optimizeDraggedTrack;
bool m_autoPosture;
int m_minRadius;
int m_maxRadius;