Commit 061660e9 authored by Tomasz Włostowski's avatar Tomasz Włostowski

Long-awaited new version of the P&S router

parent e9afb10a
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router settings dialog.
*/
#include "dialog_pns_settings.h"
#include <router/pns_routing_settings.h>
DIALOG_PNS_SETTINGS::DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) :
DIALOG_PNS_SETTINGS_BASE( aParent ), m_settings( aSettings )
{
// "Figure out what's best" is not available yet
m_mode->Enable( RM_Smart, false );
// Load widgets' values from settings
m_mode->SetSelection( m_settings.Mode() );
m_shoveVias->SetValue( m_settings.ShoveVias() );
m_backPressure->SetValue( m_settings.JumpOverObstacles() );
m_removeLoops->SetValue( m_settings.RemoveLoops() );
m_suggestEnding->SetValue( m_settings.SuggestFinish() );
m_autoNeckdown->SetValue( m_settings.SmartPads() );
m_effort->SetValue( m_settings.OptimizerEffort() );
m_smoothDragged->SetValue( m_settings.SmoothDraggedSegments() );
m_violateDrc->SetValue( m_settings.CanViolateDRC() );
}
void DIALOG_PNS_SETTINGS::OnClose( wxCloseEvent& aEvent )
{
// Do nothing, it is result of ESC pressing
EndModal( 0 );
}
void DIALOG_PNS_SETTINGS::OnOkClick( wxCommandEvent& aEvent )
{
// Save widgets' values to settings
m_settings.SetMode( (PNS_MODE) m_mode->GetSelection() );
m_settings.SetShoveVias( m_shoveVias->GetValue() );
m_settings.SetJumpOverObstacles( m_backPressure->GetValue() );
m_settings.SetRemoveLoops( m_removeLoops->GetValue() );
m_settings.SetSuggestFinish ( m_suggestEnding->GetValue() );
m_settings.SetSmartPads( m_autoNeckdown->GetValue() );
m_settings.SetOptimizerEffort( (PNS_OPTIMIZATION_EFFORT) m_effort->GetValue() );
m_settings.SetSmoothDraggedSegments( m_smoothDragged->GetValue() );
m_settings.SetCanViolateDRC( m_violateDrc->GetValue() );
EndModal( 1 );
}
void DIALOG_PNS_SETTINGS::OnCancelClick( wxCommandEvent& aEvent )
{
// Do nothing
EndModal( 0 );
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router settings dialog.
*/
#ifndef __dialog_pns_settings__
#define __dialog_pns_settings__
#include "dialog_pns_settings_base.h"
class PNS_ROUTING_SETTINGS;
class DIALOG_PNS_SETTINGS : public DIALOG_PNS_SETTINGS_BASE
{
public:
DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings );
virtual void OnClose( wxCloseEvent& aEvent );
virtual void OnOkClick( wxCommandEvent& aEvent );
virtual void OnCancelClick( wxCommandEvent& aEvent );
private:
PNS_ROUTING_SETTINGS& m_settings;
};
#endif // __dialog_pns_settings__
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 30 2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_pns_settings_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_PNS_SETTINGS_BASE::DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxString m_modeChoices[] = { _("Highlight collisions"), _("Shove"), _("Walk around"), _("Figure out what's best") };
int m_modeNChoices = sizeof( m_modeChoices ) / sizeof( wxString );
m_mode = new wxRadioBox( this, wxID_ANY, _("Mode"), wxDefaultPosition, wxDefaultSize, m_modeNChoices, m_modeChoices, 1, wxRA_SPECIFY_COLS );
m_mode->SetSelection( 1 );
bMainSizer->Add( m_mode, 0, wxALL, 5 );
wxStaticBoxSizer* bOptions;
bOptions = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL );
m_shoveVias = new wxCheckBox( this, wxID_ANY, _("Shove vias"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_shoveVias, 0, wxALL, 5 );
m_backPressure = new wxCheckBox( this, wxID_ANY, _("Jump over obstacles"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_backPressure, 0, wxALL, 5 );
m_removeLoops = new wxCheckBox( this, wxID_ANY, _("Remove redundant tracks"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_removeLoops, 0, wxALL, 5 );
m_autoNeckdown = new wxCheckBox( this, wxID_ANY, _("Automatic neckdown"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_autoNeckdown, 0, wxALL, 5 );
m_smoothDragged = new wxCheckBox( this, wxID_ANY, _("Smooth dragged segments"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_smoothDragged, 0, wxALL, 5 );
m_violateDrc = new wxCheckBox( this, wxID_ANY, _("Allow DRC violations"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_violateDrc, 0, wxALL, 5 );
m_suggestEnding = new wxCheckBox( this, wxID_ANY, _("Suggest track finish"), wxDefaultPosition, wxDefaultSize, 0 );
m_suggestEnding->Enable( false );
bOptions->Add( m_suggestEnding, 0, wxALL, 5 );
wxBoxSizer* bEffort;
bEffort = new wxBoxSizer( wxHORIZONTAL );
m_effortLabel = new wxStaticText( this, wxID_ANY, _("Optimizer effort"), wxDefaultPosition, wxDefaultSize, 0 );
m_effortLabel->Wrap( -1 );
bEffort->Add( m_effortLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bEffort->Add( 0, 0, 0, wxEXPAND, 5 );
wxBoxSizer* bSlider;
bSlider = new wxBoxSizer( wxVERTICAL );
m_effort = new wxSlider( this, wxID_ANY, 1, 0, 2, wxDefaultPosition, wxDefaultSize, wxSL_AUTOTICKS|wxSL_BOTTOM|wxSL_HORIZONTAL|wxSL_TOP );
bSlider->Add( m_effort, 1, wxEXPAND, 5 );
wxBoxSizer* bSliderLabels;
bSliderLabels = new wxBoxSizer( wxHORIZONTAL );
m_lowLabel = new wxStaticText( this, wxID_ANY, _("low"), wxDefaultPosition, wxDefaultSize, 0 );
m_lowLabel->Wrap( -1 );
m_lowLabel->SetFont( wxFont( 8, 70, 90, 90, false, wxEmptyString ) );
bSliderLabels->Add( m_lowLabel, 0, 0, 5 );
bSliderLabels->Add( 0, 0, 1, wxEXPAND, 5 );
m_highLabel = new wxStaticText( this, wxID_ANY, _("high"), wxDefaultPosition, wxDefaultSize, 0 );
m_highLabel->Wrap( -1 );
m_highLabel->SetFont( wxFont( 8, 70, 90, 90, false, wxEmptyString ) );
bSliderLabels->Add( m_highLabel, 0, 0, 5 );
bSlider->Add( bSliderLabels, 1, wxEXPAND, 5 );
bEffort->Add( bSlider, 1, wxEXPAND, 5 );
bOptions->Add( bEffort, 1, wxALL|wxEXPAND, 5 );
wxBoxSizer* bButtons;
bButtons = new wxBoxSizer( wxHORIZONTAL );
m_ok = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
m_ok->SetDefault();
bButtons->Add( m_ok, 1, wxALL, 5 );
m_cancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
bButtons->Add( m_cancel, 1, wxALL, 5 );
bOptions->Add( bButtons, 1, wxEXPAND, 5 );
bMainSizer->Add( bOptions, 1, wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PNS_SETTINGS_BASE::OnClose ) );
m_ok->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnOkClick ), NULL, this );
m_cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnCancelClick ), NULL, this );
}
DIALOG_PNS_SETTINGS_BASE::~DIALOG_PNS_SETTINGS_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PNS_SETTINGS_BASE::OnClose ) );
m_ok->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnOkClick ), NULL, this );
m_cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnCancelClick ), NULL, this );
}
This source diff could not be displayed because it is too large. You can view the blob instead.
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 30 2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_PNS_SETTINGS_BASE_H__
#define __DIALOG_PNS_SETTINGS_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include <wx/string.h>
#include <wx/radiobox.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/checkbox.h>
#include <wx/stattext.h>
#include <wx/slider.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/statbox.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_PNS_SETTINGS_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_PNS_SETTINGS_BASE : public wxDialog
{
private:
protected:
wxRadioBox* m_mode;
wxCheckBox* m_shoveVias;
wxCheckBox* m_backPressure;
wxCheckBox* m_removeLoops;
wxCheckBox* m_autoNeckdown;
wxCheckBox* m_smoothDragged;
wxCheckBox* m_violateDrc;
wxCheckBox* m_suggestEnding;
wxStaticText* m_effortLabel;
wxSlider* m_effort;
wxStaticText* m_lowLabel;
wxStaticText* m_highLabel;
wxButton* m_ok;
wxButton* m_cancel;
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Interactive Router settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 289,504 ), long style = wxDEFAULT_DIALOG_STYLE );
~DIALOG_PNS_SETTINGS_BASE();
};
#endif //__DIALOG_PNS_SETTINGS_BASE_H__
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router track width and via size dialog.
*/
#include "dialog_track_via_size.h"
#include <router/pns_routing_settings.h>
#include <base_units.h>
#include <confirm.h>
DIALOG_TRACK_VIA_SIZE::DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) :
DIALOG_TRACK_VIA_SIZE_BASE( aParent ),
m_settings( aSettings )
{
// Load router settings to dialog fields
m_trackWidth->SetValue( To_User_Unit( m_trackWidth->GetUnits(), m_settings.GetTrackWidth() ) );
m_viaDiameter->SetValue( To_User_Unit( m_viaDiameter->GetUnits(), m_settings.GetViaDiameter() ) );
m_viaDrill->SetValue( To_User_Unit( m_viaDrill->GetUnits(), m_settings.GetViaDrill() ) );
m_trackWidth->SetFocus();
// Pressing ENTER when any of the text input fields is active applies changes
#if wxCHECK_VERSION( 3, 0, 0 )
Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE::onOkClick ), NULL, this );
#else
Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE::onOkClick ), NULL, this );
#endif
}
bool DIALOG_TRACK_VIA_SIZE::check()
{
// Wrong input
if( !m_trackWidth->GetValue() || !m_viaDiameter->GetValue() || !m_viaDrill->GetValue() )
return false;
// Via drill should be smaller than via diameter
if( *m_viaDrill->GetValue() >= m_viaDiameter->GetValue() )
return false;
return true;
}
void DIALOG_TRACK_VIA_SIZE::onClose( wxCloseEvent& aEvent )
{
EndModal( 0 );
}
void DIALOG_TRACK_VIA_SIZE::onOkClick( wxCommandEvent& aEvent )
{
if( check() )
{
// Store dialog values to the router settings
m_settings.SetTrackWidth( From_User_Unit( m_trackWidth->GetUnits(), *m_trackWidth->GetValue() ) );
m_settings.SetViaDiameter( From_User_Unit( m_viaDiameter->GetUnits(), *m_viaDiameter->GetValue() ) );
m_settings.SetViaDrill( From_User_Unit( m_viaDrill->GetUnits(), *m_viaDrill->GetValue() ) );
EndModal( 1 );
}
else
{
DisplayError( GetParent(), _( "Settings are incorrect" ) );
m_trackWidth->SetFocus();
}
}
void DIALOG_TRACK_VIA_SIZE::onCancelClick( wxCommandEvent& aEvent )
{
EndModal( 0 );
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router track width and via size dialog.
*/
#ifndef __dialog_track_via_size__
#define __dialog_track_via_size__
#include "dialog_track_via_size_base.h"
class PNS_ROUTING_SETTINGS;
/** Implementing DIALOG_TRACK_VIA_SIZE_BASE */
class DIALOG_TRACK_VIA_SIZE : public DIALOG_TRACK_VIA_SIZE_BASE
{
public:
/** Constructor */
DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings );
protected:
// Routings settings that are modified by the dialog.
PNS_ROUTING_SETTINGS& m_settings;
///> Checks if values given in the dialog are sensible.
bool check();
// Handlers for DIALOG_TRACK_VIA_SIZE_BASE events.
void onClose( wxCloseEvent& aEvent );
void onOkClick( wxCommandEvent& aEvent );
void onCancelClick( wxCommandEvent& aEvent );
};
#endif // __dialog_track_via_size__
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 30 2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_track_via_size_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_TRACK_VIA_SIZE_BASE::DIALOG_TRACK_VIA_SIZE_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizes;
bSizes = new wxBoxSizer( wxVERTICAL );
m_trackWidth = new WX_UNIT_TEXT( this, _("Track width:") );
bSizes->Add( m_trackWidth, 0, wxALL, 5 );
m_viaDiameter = new WX_UNIT_TEXT( this, _("Via diameter:") );
bSizes->Add( m_viaDiameter, 0, wxALL, 5 );
m_viaDrill = new WX_UNIT_TEXT( this, _("Via drill:") );
bSizes->Add( m_viaDrill, 0, wxALL, 5 );
wxBoxSizer* bButtons;
bButtons = new wxBoxSizer( wxHORIZONTAL );
m_ok = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
bButtons->Add( m_ok, 1, wxALL, 5 );
m_cancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
bButtons->Add( m_cancel, 1, wxALL, 5 );
bSizes->Add( bButtons, 0, wxEXPAND, 5 );
this->SetSizer( bSizes );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onClose ) );
m_ok->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onOkClick ), NULL, this );
m_cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onCancelClick ), NULL, this );
}
DIALOG_TRACK_VIA_SIZE_BASE::~DIALOG_TRACK_VIA_SIZE_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onClose ) );
m_ok->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onOkClick ), NULL, this );
m_cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE_BASE::onCancelClick ), NULL, this );
}
This diff is collapsed.
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 30 2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_TRACK_VIA_SIZE_BASE_H__
#define __DIALOG_TRACK_VIA_SIZE_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include <wxunittext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_TRACK_VIA_SIZE_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_TRACK_VIA_SIZE_BASE : public wxDialog
{
private:
protected:
WX_UNIT_TEXT* m_trackWidth;
WX_UNIT_TEXT* m_viaDiameter;
WX_UNIT_TEXT* m_viaDrill;
wxButton* m_ok;
wxButton* m_cancel;
// Virtual event handlers, overide them in your derived class
virtual void onClose( wxCloseEvent& event ) { event.Skip(); }
virtual void onOkClick( wxCommandEvent& event ) { event.Skip(); }
virtual void onCancelClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_TRACK_VIA_SIZE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Track width and via size"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 388,164 ), long style = wxDEFAULT_DIALOG_STYLE );
~DIALOG_TRACK_VIA_SIZE_BASE();
};
#endif //__DIALOG_TRACK_VIA_SIZE_BASE_H__
...@@ -11,40 +11,50 @@ include_directories( ...@@ -11,40 +11,50 @@ include_directories(
set( PCBNEW_PNS_SRCS set( PCBNEW_PNS_SRCS
direction.h direction.h
pns_via.h time_limit.h
pns_routing_settings.h time_limit.cpp
pns_shove.cpp
pns_line.cpp
pns_utils.h
pns_layerset.h
trace.h trace.h
pns_algo_base.h
pns_algo_base.cpp
pns_dragger.cpp
pns_dragger.h
pns_index.h
pns_item.h
pns_item.cpp
pns_itemset.h
pns_itemset.cpp
pns_joint.h
pns_layerset.h
pns_line.h pns_line.h
pns_walkaround.cpp pns_line.cpp
pns_node.h pns_line_placer.h
pns_line_placer.cpp pns_line_placer.cpp
pns_utils.cpp pns_logger.h
pns_solid.h pns_logger.cpp
pns_item.cpp pns_node.h
pns_via.cpp
pns_node.cpp pns_node.cpp
pns_solid.cpp
pns_line_placer.h
pns_optimizer.h pns_optimizer.h
pns_walkaround.h pns_optimizer.cpp
pns_shove.h
pns_router.h pns_router.h
pns_router.cpp pns_router.cpp
pns_index.h pns_routing_settings.h
pns_item.h pns_routing_settings.cpp
pns_optimizer.cpp
pns_joint.h
pns_segment.h pns_segment.h
pns_itemset.h pns_shove.h
pns_itemset.cpp pns_shove.cpp
router_tool.cpp pns_solid.h
router_tool.h pns_solid.cpp
pns_utils.h
pns_utils.cpp
pns_via.h
pns_via.cpp
pns_walkaround.h
pns_walkaround.cpp
router_preview_item.cpp router_preview_item.cpp
router_preview_item.h router_preview_item.h
router_tool.cpp
router_tool.h
) )
add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -180,6 +180,11 @@ public: ...@@ -180,6 +180,11 @@ public:
return ( m_dir % 2 ) == 1; return ( m_dir % 2 ) == 1;
} }
bool IsDefined() const
{
return m_dir != UNDEFINED;
}
/** /**
* Function BuildInitialTrace() * Function BuildInitialTrace()
* *
...@@ -244,32 +249,75 @@ public: ...@@ -244,32 +249,75 @@ public:
return aOther.m_dir != m_dir; return aOther.m_dir != m_dir;
} }
/**
* Function Right()
*
* Returns the direction on the right side of this (i.e. turns right
* by 45 deg)
*/
const DIRECTION_45 Right() const const DIRECTION_45 Right() const
{ {
DIRECTION_45 r; DIRECTION_45 r;
r.m_dir = (Directions) (m_dir + 1); if ( m_dir != UNDEFINED )
r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % 8 );
if( r.m_dir == NW )
r.m_dir = N;
return r; return r;
} }
private: /**
* Function Left()
*
* Returns the direction on the left side of this (i.e. turns left
* by 45 deg)
*/
const DIRECTION_45 Left() const
{
DIRECTION_45 l;
if (m_dir == UNDEFINED)
return l;
if(m_dir == N)
l.m_dir = NW;
else
l.m_dir = static_cast<Directions> (m_dir - 1);
template <typename T> return l;
int sign( T val ) const }
/**
* Function ToVector()
*
* Returns a unit vector corresponding to our direction.
*/
const VECTOR2I ToVector() const
{ {
return (T( 0 ) < val) - ( val < T( 0 ) ); switch(m_dir)
{
case N: return VECTOR2I(0, 1);
case S: return VECTOR2I(0, -1);
case E: return VECTOR2I(1, 0);
case W: return VECTOR2I(-1, 0);
case NE: return VECTOR2I(1, 1);
case NW: return VECTOR2I(-1, 1);
case SE: return VECTOR2I(1, -1);
case SW: return VECTOR2I(-1, -1);
default:
return VECTOR2I(0, 0);
}
} }
private:
/** /**
* Function construct() * Function construct()
* Calculates the direction from a vector. If the vector's angle is not a multiple of 45 * Calculates the direction from a vector. If the vector's angle is not a multiple of 45
* degrees, the direction is rounded to the nearest octant. * degrees, the direction is rounded to the nearest octant.
* @param aVec our vector * @param aVec our vector */
*/
void construct( const VECTOR2I& aVec ) void construct( const VECTOR2I& aVec )
{ {
m_dir = UNDEFINED; m_dir = UNDEFINED;
...@@ -322,7 +370,8 @@ private: ...@@ -322,7 +370,8 @@ private:
} }
} }
Directions m_dir; ///> our actual direction ///> our actual direction
Directions m_dir;
}; };
#endif // __DIRECTION_H #endif // __DIRECTION_H
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pns_algo_base.h"
#include "pns_router.h"
PNS_ROUTING_SETTINGS& PNS_ALGO_BASE::Settings() const
{
return m_router->Settings();
}
PNS_LOGGER *PNS_ALGO_BASE::Logger()
{
return NULL;
}
\ No newline at end of file
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PNS_ALGO_BASE_H
#define __PNS_ALGO_BASE_H
#include "pns_routing_settings.h"
class PNS_ROUTER;
class PNS_LOGGER;
/**
* Class PNS_ALGO_BASE
*
* Base class for all P&S algorithms (shoving, walkaround, line placement, dragging, etc.)
* Holds a bunch of objects commonly used by all algorithms (P&S settings, parent router instance, logging)
**/
class PNS_ALGO_BASE {
public:
PNS_ALGO_BASE ( PNS_ROUTER *aRouter ):
m_router ( aRouter )
{};
virtual ~PNS_ALGO_BASE() {}
///> Returns the instance of our router
PNS_ROUTER *Router() const {
return m_router;
}
///> Returns current router settings
PNS_ROUTING_SETTINGS& Settings() const;
///> Returns the logger object, allowing to dump geometry to a file.
virtual PNS_LOGGER *Logger();
private:
PNS_ROUTER *m_router;
};
#endif
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <boost/foreach.hpp>
#include "pns_dragger.h"
#include "pns_shove.h"
#include "pns_router.h"
PNS_DRAGGER::PNS_DRAGGER( PNS_ROUTER* aRouter ) :
PNS_ALGO_BASE ( aRouter )
{
m_world = NULL;
m_shove = NULL;
};
PNS_DRAGGER::~PNS_DRAGGER()
{
if( m_shove )
delete m_shove;
}
void PNS_DRAGGER::SetWorld ( PNS_NODE *aWorld )
{
m_world = aWorld;
}
bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg )
{
int w2 = aSeg->Width() / 2;
m_draggedLine = m_world->AssembleLine ( aSeg, &m_draggedSegmentIndex );
m_shove->SetInitialLine (m_draggedLine);
m_lastValidDraggedLine = *m_draggedLine;
m_lastValidDraggedLine.ClearSegmentLinks();
if( (aP - aSeg->Seg().A).EuclideanNorm() <= w2 )
m_mode = CORNER;
else if( (aP - aSeg->Seg().B).EuclideanNorm() <= w2 )
{
m_draggedSegmentIndex ++;
m_mode = CORNER;
} else
m_mode = SEGMENT;
return true;
}
bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA *aVia )
{
m_draggedVia = aVia;
m_initialVia = aVia;
m_mode = VIA;
VECTOR2I p0 ( aVia->Pos() );
PNS_JOINT *jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() );
BOOST_FOREACH(PNS_ITEM *item, jt->LinkList() )
{
if(item->OfKind( PNS_ITEM::SEGMENT ))
{
int segIndex;
PNS_SEGMENT *seg = (PNS_SEGMENT *) item;
std::auto_ptr<PNS_LINE> l ( m_world->AssembleLine(seg, &segIndex) );
if(segIndex != 0)
l->Reverse();
m_origViaConnections.push_back (*l);
}
}
return true;
}
bool PNS_DRAGGER::Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem )
{
m_shove = new PNS_SHOVE ( m_world, Router() );
m_lastNode = NULL;
m_draggedItems.Clear();
m_currentMode = Settings().Mode();
TRACE(2, "StartDragging: item %p [kind %d]", aStartItem % aStartItem->Kind());
switch( aStartItem->Kind() )
{
case PNS_ITEM::SEGMENT:
return startDragSegment ( aP, static_cast<PNS_SEGMENT *> (aStartItem) );
case PNS_ITEM::VIA:
return startDragVia ( aP, static_cast<PNS_VIA *> (aStartItem) );
default:
return false;
}
}
bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP)
{
if(m_lastNode)
{
delete m_lastNode;
m_lastNode = NULL;
}
switch(m_mode)
{
case SEGMENT:
case CORNER:
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0;
PNS_LINE tmp (*m_draggedLine);
if(m_mode == SEGMENT)
tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh );
else
tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh );
m_lastNode = m_shove->CurrentNode()->Branch();
m_lastValidDraggedLine = tmp;
m_lastValidDraggedLine.ClearSegmentLinks();
m_lastValidDraggedLine.Unmark();
m_lastNode->Add ( &m_lastValidDraggedLine );
m_draggedItems = PNS_ITEMSET ( &m_lastValidDraggedLine );
break;
}
case VIA: // fixme...
{
m_lastNode = m_shove->CurrentNode()->Branch();
dumbDragVia ( m_initialVia, m_lastNode, aP );
break;
}
}
if (Settings().CanViolateDRC())
m_dragStatus = true;
else
m_dragStatus = !m_world->CheckColliding( m_draggedItems );
return true;
}
void PNS_DRAGGER::dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP )
{
// fixme: this is awful.
m_draggedVia = aVia->Clone();
m_draggedVia->SetPos( aP );
m_draggedItems.Clear();
m_draggedItems.Add(m_draggedVia);
m_lastNode->Remove ( aVia );
m_lastNode->Add ( m_draggedVia );
BOOST_FOREACH(PNS_LINE &l, m_origViaConnections)
{
PNS_LINE origLine (l);
PNS_LINE *draggedLine = l.Clone();
draggedLine->DragCorner( aP, 0 );
draggedLine->ClearSegmentLinks();
m_draggedItems.AddOwned( draggedLine );
m_lastNode->Remove ( &origLine );
m_lastNode->Add ( draggedLine );
}
}
bool PNS_DRAGGER::dragShove(const VECTOR2I& aP)
{
bool ok = false;
if(m_lastNode)
{
delete m_lastNode;
m_lastNode = NULL;
}
switch(m_mode)
{
case SEGMENT:
case CORNER:
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0;
PNS_LINE tmp (*m_draggedLine);
if(m_mode == SEGMENT)
tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh );
else
tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh );
PNS_SHOVE::ShoveStatus st = m_shove->ShoveLines( tmp );
if(st == PNS_SHOVE::SH_OK)
ok = true;
else if (st == PNS_SHOVE::SH_HEAD_MODIFIED)
{
tmp = m_shove->NewHead();
ok = true;
}
m_lastNode = m_shove->CurrentNode()->Branch();
if(ok)
m_lastValidDraggedLine = tmp;
m_lastValidDraggedLine.ClearSegmentLinks();
m_lastValidDraggedLine.Unmark();
m_lastNode->Add ( &m_lastValidDraggedLine );
m_draggedItems = PNS_ITEMSET ( &m_lastValidDraggedLine );
break;
}
case VIA:
{
PNS_VIA *newVia;
PNS_SHOVE::ShoveStatus st = m_shove -> ShoveDraggingVia ( m_draggedVia, aP, &newVia );
if(st == PNS_SHOVE::SH_OK || st == PNS_SHOVE::SH_HEAD_MODIFIED)
ok = true;
m_lastNode = m_shove->CurrentNode()->Branch();
if( ok )
{
m_draggedVia = newVia;
m_draggedItems.Clear();
}
break;
}
}
m_dragStatus = ok;
return ok;
}
bool PNS_DRAGGER::FixRoute( )
{
if(m_dragStatus)
{
Router()->CommitRouting( CurrentNode() );
return true;
}
return false;
}
bool PNS_DRAGGER::Drag ( const VECTOR2I& aP )
{
switch ( m_currentMode )
{
case RM_MarkObstacles:
return dragMarkObstacles (aP);
case RM_Shove:
case RM_Walkaround:
case RM_Smart:
return dragShove ( aP );
default:
return false;
}
}
PNS_NODE *PNS_DRAGGER::CurrentNode() const
{
return m_lastNode;
}
const PNS_ITEMSET PNS_DRAGGER::Traces()
{
return m_draggedItems;
}
PNS_LOGGER *PNS_DRAGGER::Logger()
{
if(m_shove)
return m_shove->Logger();
return NULL;
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PNS_DRAGGER_H
#define __PNS_DRAGGER_H
#include <math/vector2d.h>
#include "pns_node.h"
#include "pns_via.h"
#include "pns_line.h"
#include "pns_algo_base.h"
#include "pns_itemset.h"
class PNS_ROUTER;
class PNS_SHOVE;
class PNS_OPTIMIZER;
class PNS_ROUTER_BASE;
/**
* Class PNS_DRAGGER
*
* Via, segment and corner dragging algorithm.
*/
class PNS_DRAGGER : public PNS_ALGO_BASE
{
public:
PNS_DRAGGER( PNS_ROUTER *aRouter );
~PNS_DRAGGER();
/**
* Function SetWorld()
*
* Sets the board to work on.
*/
void SetWorld ( PNS_NODE *aWorld );
/**
* Function Start()
*
* Starts routing a single track at point aP, taking item aStartItem as anchor
* (unless NULL). Returns true if a dragging operation has started.
*/
bool Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem );
/**
* Function Drag()
*
* Drags the current segment/corner/via to the point aP.
* @return true, if dragging finished with success.
*/
bool Drag ( const VECTOR2I& aP );
/**
* Function FixRoute()
*
* Checks if the result of current dragging operation is correct
* and eventually commits it to the world.
* @return true, if dragging finished with success.
*/
bool FixRoute ( );
/**
* Function CurrentNode()
*
* Returns the most recent world state, including all
* items changed due to dragging operation.
*/
PNS_NODE* CurrentNode() const;
/**
* Function Traces()
*
* Returns the set of dragged items.
*/
const PNS_ITEMSET Traces();
/// @copydoc PNS_ALGO_BASE::Logger()
virtual PNS_LOGGER *Logger();
private:
typedef std::pair <PNS_LINE *, PNS_LINE *> LinePair;
typedef std::vector<LinePair> LinePairVec;
enum DragMode {
CORNER = 0,
SEGMENT,
VIA
};
bool dragMarkObstacles(const VECTOR2I& aP);
bool dragShove(const VECTOR2I& aP);
bool startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg );
bool startDragVia( const VECTOR2D& aP, PNS_VIA *aVia );
void dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP );
PNS_NODE * m_world;
PNS_NODE * m_lastNode;
DragMode m_mode;
PNS_LINE * m_draggedLine;
PNS_VIA * m_draggedVia;
PNS_LINE m_lastValidDraggedLine;
PNS_SHOVE * m_shove;
int m_draggedSegmentIndex;
bool m_dragStatus;
PNS_MODE m_currentMode;
std::vector<PNS_LINE> m_origViaConnections;
std::vector<PNS_LINE> m_draggedViaConnections;
PNS_VIA * m_initialVia;
PNS_ITEMSET m_draggedItems;
};
#endif
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,12 +15,15 @@ ...@@ -15,12 +15,15 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PNS_INDEX_H #ifndef __PNS_INDEX_H
#define __PNS_INDEX_H #define __PNS_INDEX_H
#include <layers_id_colors_and_visibility.h>
#include <map>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
...@@ -33,7 +36,7 @@ ...@@ -33,7 +36,7 @@
* Class PNS_INDEX * Class PNS_INDEX
* *
* Custom spatial index, holding our board items and allowing for very fast searches. Items * Custom spatial index, holding our board items and allowing for very fast searches. Items
* are assigned to separate R-Tree subundices depending on their type and spanned layers, reducing * are assigned to separate R-Tree subindices depending on their type and spanned layers, reducing
* overlap and improving search time. * overlap and improving search time.
**/ **/
...@@ -47,30 +50,93 @@ public: ...@@ -47,30 +50,93 @@ public:
PNS_INDEX(); PNS_INDEX();
~PNS_INDEX(); ~PNS_INDEX();
/**
* Function Add()
*
* Adds item to the spatial index.
*/
void Add( PNS_ITEM* aItem ); void Add( PNS_ITEM* aItem );
/**
* Function Remove()
*
* Removes an item from the spatial index.
*/
void Remove( PNS_ITEM* aItem ); void Remove( PNS_ITEM* aItem );
/**
* Function Add()
*
* Replaces one item with another.
*/
void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
/**
* Function Query()
*
* Searches items in the index that are in proximity of aItem.
* For each item, function object aVisitor is called. Only items on
* overlapping layers are considered.
*
* @param aItem item to search against
* @param aMinDistance proximity distance (wrs to the item's shape)
* @param aVisitor function object called on each found item. Return
false from the visitor to stop searching.
* @return number of items found.
*/
template<class Visitor> template<class Visitor>
int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& aVisitor );
/**
* Function Query()
*
* Searches items in the index that are in proximity of aShape.
* For each item, function object aVisitor is called. Treats all
* layers as colliding.
*
* @param aShape shape to search against
* @param aMinDistance proximity distance (wrs to the item's shape)
* @param aVisitor function object called on each found item. Return
false from the visitor to stop searching.
* @return number of items found.
*/
template<class Visitor> template<class Visitor>
int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); int Query( const SHAPE* aShape, int aMinDistance, Visitor& aVisitor );
/**
* Function Clear()
*
* Removes all items from the index.
*/
void Clear(); void Clear();
/**
* Function GetItemsForNet()
*
* Returns list of all items in a given net.
*/
NetItemsList* GetItemsForNet( int aNet ); NetItemsList* GetItemsForNet( int aNet );
ItemSet::iterator begin() { return m_allItems.begin(); } /**
ItemSet::iterator end() { return m_allItems.end(); } * Function Contains()
*
* Returns true if item aItem exists in the index.
*/
bool Contains( PNS_ITEM* aItem ) const bool Contains( PNS_ITEM* aItem ) const
{ {
return m_allItems.find( aItem ) != m_allItems.end(); return m_allItems.find( aItem ) != m_allItems.end();
} }
/**
* Function Size()
*
* Returns number of items stored in the index.
*/
int Size() const { return m_allItems.size(); } int Size() const { return m_allItems.size(); }
ItemSet::iterator begin() { return m_allItems.begin(); }
ItemSet::iterator end() { return m_allItems.end(); }
private: private:
static const int MaxSubIndices = 64; static const int MaxSubIndices = 64;
static const int SI_Multilayer = 2; static const int SI_Multilayer = 2;
...@@ -81,7 +147,7 @@ private: ...@@ -81,7 +147,7 @@ private:
static const int SI_PadsBottom = 1; static const int SI_PadsBottom = 1;
template <class Visitor> template <class Visitor>
int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ); int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor );
ItemShapeIndex* getSubindex( const PNS_ITEM* aItem ); ItemShapeIndex* getSubindex( const PNS_ITEM* aItem );
...@@ -101,9 +167,9 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) ...@@ -101,9 +167,9 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
{ {
int idx_n = -1; int idx_n = -1;
const PNS_LAYERSET l = aItem->GetLayers(); const PNS_LAYERSET l = aItem->Layers();
switch( aItem->GetKind() ) switch( aItem->Kind() )
{ {
case PNS_ITEM::VIA: case PNS_ITEM::VIA:
idx_n = SI_Multilayer; idx_n = SI_Multilayer;
...@@ -113,9 +179,9 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) ...@@ -113,9 +179,9 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
{ {
if( l.IsMultilayer() ) if( l.IsMultilayer() )
idx_n = SI_Multilayer; idx_n = SI_Multilayer;
else if( l.Start() == 0 ) // fixme: use kicad layer codes else if( l.Start() == LAYER_N_BACK) // fixme: use kicad layer codes
idx_n = SI_PadsTop; idx_n = SI_PadsTop;
else if( l.Start() == 15 ) else if( l.Start() == LAYER_N_FRONT )
idx_n = SI_PadsBottom; idx_n = SI_PadsBottom;
break; break;
...@@ -143,9 +209,11 @@ void PNS_INDEX::Add( PNS_ITEM* aItem ) ...@@ -143,9 +209,11 @@ void PNS_INDEX::Add( PNS_ITEM* aItem )
{ {
ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem );
idx->Add( aItem ); idx->Add( aItem );
m_allItems.insert( aItem ); m_allItems.insert( aItem );
int net = aItem->GetNet(); int net = aItem->Net();
if( net >= 0 ) if( net >= 0 )
{ {
...@@ -161,7 +229,7 @@ void PNS_INDEX::Remove( PNS_ITEM* aItem ) ...@@ -161,7 +229,7 @@ void PNS_INDEX::Remove( PNS_ITEM* aItem )
idx->Remove( aItem ); idx->Remove( aItem );
m_allItems.erase( aItem ); m_allItems.erase( aItem );
int net = aItem->GetNet(); int net = aItem->Net();
if( net >= 0 && m_netMap.find( net ) != m_netMap.end() ) if( net >= 0 && m_netMap.find( net ) != m_netMap.end() )
m_netMap[net].remove( aItem ); m_netMap[net].remove( aItem );
...@@ -176,43 +244,43 @@ void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) ...@@ -176,43 +244,43 @@ void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem )
template<class Visitor> template<class Visitor>
int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor )
{ {
if( !m_subIndices[index] ) if( !m_subIndices[index] )
return 0; return 0;
return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); return m_subIndices[index]->Query( aShape, aMinDistance, aVisitor, false );
} }
template<class Visitor> template<class Visitor>
int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& aVisitor )
{ {
const SHAPE* shape = aItem->GetShape(); const SHAPE* shape = aItem->Shape();
int total = 0; int total = 0;
total += querySingle( SI_Multilayer, shape, aMinDistance, v ); total += querySingle( SI_Multilayer, shape, aMinDistance, aVisitor );
const PNS_LAYERSET layers = aItem->GetLayers(); const PNS_LAYERSET layers = aItem->Layers();
if( layers.IsMultilayer() ) if( layers.IsMultilayer() )
{ {
total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, aVisitor );
total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, aVisitor );
for( int i = layers.Start(); i <= layers.End(); ++i ) for( int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, aVisitor );
} }
else else
{ {
int l = layers.Start(); int l = layers.Start();
if( l == 0 ) if( l == LAYER_N_BACK )
total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, aVisitor );
else if( l == 15 ) else if( l == LAYER_N_FRONT )
total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, aVisitor );
total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, aVisitor );
} }
return total; return total;
...@@ -220,12 +288,12 @@ int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) ...@@ -220,12 +288,12 @@ int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v )
template<class Visitor> template<class Visitor>
int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& aVisitor )
{ {
int total = 0; int total = 0;
for( int i = 0; i < MaxSubIndices; i++ ) for( int i = 0; i < MaxSubIndices; i++ )
total += querySingle( i, aShape, aMinDistance, v ); total += querySingle( i, aShape, aMinDistance, aVisitor );
return total; return total;
} }
......
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "pns_item.h" #include "pns_item.h"
...@@ -32,7 +32,7 @@ bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeed ...@@ -32,7 +32,7 @@ bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeed
if( !m_layers.Overlaps( aOther->m_layers ) ) if( !m_layers.Overlaps( aOther->m_layers ) )
return false; return false;
return GetShape()->Collide( aOther->GetShape(), aClearance ); return Shape()->Collide( aOther->Shape(), aClearance );
// fixme: MTV // fixme: MTV
} }
...@@ -50,7 +50,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, ...@@ -50,7 +50,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther ); const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
if( line->EndsWithVia() ) if( line->EndsWithVia() )
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV,
aMTV ); aMTV );
} }
...@@ -58,7 +58,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, ...@@ -58,7 +58,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
} }
const std::string PNS_ITEM::GetKindStr() const const std::string PNS_ITEM::KindStr() const
{ {
switch( m_kind ) switch( m_kind )
{ {
...@@ -85,4 +85,5 @@ const std::string PNS_ITEM::GetKindStr() const ...@@ -85,4 +85,5 @@ const std::string PNS_ITEM::GetKindStr() const
PNS_ITEM::~PNS_ITEM() PNS_ITEM::~PNS_ITEM()
{ {
} }
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PNS_ITEM_H #ifndef __PNS_ITEM_H
...@@ -26,18 +26,25 @@ ...@@ -26,18 +26,25 @@
#include <geometry/shape.h> #include <geometry/shape.h>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
#include "trace.h"
#include "pns_layerset.h" #include "pns_layerset.h"
class BOARD_CONNECTED_ITEM; class BOARD_CONNECTED_ITEM;
class PNS_NODE; class PNS_NODE;
enum LineMarker {
MK_HEAD = ( 1 << 0 ),
MK_VIOLATION = ( 1 << 3 ),
MK_LOCKED = ( 1 << 4 )
};
/** /**
* Class PNS_ITEM * Class PNS_ITEM
* *
* Base class for PNS router board items. Implements the shared properties of all PCB items - * Base class for PNS router board items. Implements the shared properties of all PCB items -
* net, spanned layers, geometric shape & refererence to owning model. * net, spanned layers, geometric shape & refererence to owning model.
*/ */
class PNS_ITEM class PNS_ITEM
{ {
public: public:
...@@ -60,8 +67,9 @@ public: ...@@ -60,8 +67,9 @@ public:
m_movable = true; m_movable = true;
m_kind = aKind; m_kind = aKind;
m_parent = NULL; m_parent = NULL;
m_world = NULL;
m_owner = NULL; m_owner = NULL;
m_marker = 0;
m_rank = -1;
} }
PNS_ITEM( const PNS_ITEM& aOther ) PNS_ITEM( const PNS_ITEM& aOther )
...@@ -70,61 +78,203 @@ public: ...@@ -70,61 +78,203 @@ public:
m_net = aOther.m_net; m_net = aOther.m_net;
m_movable = aOther.m_movable; m_movable = aOther.m_movable;
m_kind = aOther.m_kind; m_kind = aOther.m_kind;
m_world = aOther.m_world;
m_parent = aOther.m_parent; m_parent = aOther.m_parent;
m_owner = NULL; m_owner = NULL;
m_marker = aOther.m_marker;
m_rank = aOther.m_rank;
} }
virtual ~PNS_ITEM(); virtual ~PNS_ITEM();
virtual PNS_ITEM* Clone() const = 0; /**
* Function Clone()
*
* Returns a deep copy of the item
*/
virtual PNS_ITEM* Clone( ) const = 0;
///> Returns a convex polygon "hull" of a the item, that is used as the walkaround /*
/// path. * Function Hull()
/// aClearance defines how far from the body of the item the hull should be, *
/// aWalkaroundThickness is the width of the line that walks around this hull. * Returns a convex polygon "hull" of a the item, that is used as the walk-around
* path.
* @param aClearance defines how far from the body of the item the hull should be,
* @param aWalkaroundThickness is the width of the line that walks around this hull.
*/
virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const
{ {
return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN();
}; };
PnsKind GetKind() const { return m_kind; } /**
bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } * Function Kind()
*
* Returns the type (kind) of the item
*/
PnsKind Kind() const
{
return m_kind;
}
/**
* Function OfKind()
*
* Returns true if the item's type matches the mask aKindMask.
*/
bool OfKind( int aKindMask ) const
{
return (aKindMask & m_kind) != 0;
}
/**
* Function KindStr()
*
* Returns the kind of the item, as string
*/
const std::string KindStr() const;
/**
* Function SetParent()
*
* Sets the corresponding parent object in the host application's model.
*/
void SetParent( BOARD_CONNECTED_ITEM* aParent )
{
m_parent = aParent;
}
/**
* Function Parent()
*
* Returns the corresponding parent object in the host application's model.
*/
BOARD_CONNECTED_ITEM* Parent() const
{
return m_parent;
}
const std::string GetKindStr() const; /**
* Function SetNet()
*
* Sets the item's net to aNet
*/
void SetNet( int aNet )
{
m_net = aNet;
}
///> Gets/Sets the corresponding parent object in the host application's model (pcbnew) /**
void SetParent( BOARD_CONNECTED_ITEM* aParent ) { m_parent = aParent; } * Function Net()
BOARD_CONNECTED_ITEM* GetParent() const { return m_parent; } *
* Returns the item's net.
*/
int Net() const
{
return m_net;
}
///> Net accessors /**
int GetNet() const { return m_net; } * Function SetLayers()
void SetNet( int aNet ) { m_net = aNet; } *
* Sets the layers spanned by the item to aLayers.
*/
void SetLayers( const PNS_LAYERSET& aLayers )
{
m_layers = aLayers;
}
///> Layers accessors /**
const PNS_LAYERSET& GetLayers() const { return m_layers; } * Function SetLayer()
void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } *
* Sets the layers spanned by the item to a single layer aLayer.
*/
void SetLayer( int aLayer ) void SetLayer( int aLayer )
{ {
m_layers = PNS_LAYERSET( aLayer, aLayer ); m_layers = PNS_LAYERSET( aLayer, aLayer );
} }
///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. /**
void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } * Function Layers()
bool BelongsTo( PNS_NODE* aNode ) const { return m_owner == aNode; } *
PNS_NODE* GetOwner() const { return m_owner; } * Returns the contiguous set of layers spanned by the item.
*/
const PNS_LAYERSET& Layers() const
{
return m_layers;
}
/**
* Function Layer()
*
* Returns the item's layer, for single-layered items only.
*/
virtual int Layer() const
{
return Layers().Start();
}
/**
* Function LayersOverlap()
*
* Returns true if the set of layers spanned by aOther overlaps our
* layers.
*/
bool LayersOverlap( const PNS_ITEM *aOther ) const
{
return Layers().Overlaps( aOther->Layers() );
}
///> Sets the world that is used for collision resolution. /**
void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } * Functon SetOwner()
PNS_NODE* GetWorld() const { return m_world; } *
* Sets the node that owns this item. An item can belong to a single
* PNS_NODE or stay unowned.
*/
void SetOwner( PNS_NODE* aOwner )
{
m_owner = aOwner;
}
///> Collision function. Checks if the item aOther is closer to us than /**
/// aClearance and returns true if so. It can also calculate a minimum translation vector that * Function BelongsTo()
/// resolves the collision if needed. *
* Returns true if the item is owned by the node aNode.
*/
bool BelongsTo( PNS_NODE* aNode ) const
{
return m_owner == aNode;
}
/**
* Function Owner()
*
* Returns the owner of this item, or NULL if there's none.
*/
PNS_NODE* Owner() const { return m_owner; }
/**
* Function Collide()
*
* Checks for a collision (clearance violation) with between us and item aOther.
* Collision checking takes all PCB stuff into accound (layers, nets, DRC rules).
* Optionally returns a minimum translation vector for force propagation
* algorithm.
*
* @param aOther item to check collision against
* @param aClearance desired clearance
* @param aNeedMTV when true, the minimum translation vector is calculated
* @param aMTV the minimum translation vector
* @param true, if a collision was found.
*/
virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const; VECTOR2I& aMTV ) const;
///> A shortcut without MTV calculation /**
* Function Collide()
*
* A shortcut for PNS_ITEM::Colllide() without MTV stuff.
*/
bool Collide( const PNS_ITEM* aOther, int aClearance ) const bool Collide( const PNS_ITEM* aOther, int aClearance ) const
{ {
VECTOR2I dummy; VECTOR2I dummy;
...@@ -132,26 +282,68 @@ public: ...@@ -132,26 +282,68 @@ public:
return Collide( aOther, aClearance, false, dummy ); return Collide( aOther, aClearance, false, dummy );
} }
///> Returns the geometric shape of the item /**
virtual const SHAPE* GetShape() const * Function Shape()
*
* Returns the geometrical shape of the item. Used
* for collision detection & spatial indexing.
*/
virtual const SHAPE* Shape() const
{ {
return NULL; return NULL;
} }
virtual void Mark(int aMarker)
{
m_marker = aMarker;
}
virtual void Unmark ()
{
m_marker = 0;
}
virtual int Marker() const
{
return m_marker;
}
virtual void SetRank ( int aRank )
{
m_rank = aRank;
}
virtual int Rank() const
{
return m_rank;
}
virtual VECTOR2I Anchor(int n) const
{
return VECTOR2I ();
};
virtual int AnchorCount() const
{
return 0;
}
private: private:
bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const; VECTOR2I& aMTV ) const;
protected: protected:
PnsKind m_kind; PnsKind m_kind;
BOARD_CONNECTED_ITEM* m_parent; BOARD_CONNECTED_ITEM *m_parent;
PNS_NODE* m_world; PNS_NODE *m_owner;
PNS_NODE* m_owner;
PNS_LAYERSET m_layers; PNS_LAYERSET m_layers;
bool m_movable; bool m_movable;
int m_net; int m_net;
int m_marker;
int m_rank;
}; };
#endif // __PNS_ITEM_H #endif // __PNS_ITEM_H
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
...@@ -23,16 +23,30 @@ ...@@ -23,16 +23,30 @@
#include "pns_itemset.h" #include "pns_itemset.h"
PNS_ITEMSET::PNS_ITEMSET() PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM *aInitialItem )
{ {
if(aInitialItem)
m_items.push_back(aInitialItem);
} }
PNS_ITEMSET::~PNS_ITEMSET() PNS_ITEMSET::~PNS_ITEMSET()
{ {
Clear();
} }
void PNS_ITEMSET::Clear()
{
BOOST_FOREACH(PNS_ITEM *item, m_ownedItems)
{
delete item;
}
m_items.clear();
m_ownedItems.clear();
}
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
{ {
ItemVector newItems; ItemVector newItems;
...@@ -45,7 +59,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) ...@@ -45,7 +59,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
BOOST_FOREACH( PNS_ITEM * item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetLayers().Overlaps( l ) ) if( item->Layers().Overlaps( l ) )
newItems.push_back( item ); newItems.push_back( item );
m_items = newItems; m_items = newItems;
...@@ -59,7 +73,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask ) ...@@ -59,7 +73,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask )
BOOST_FOREACH( PNS_ITEM * item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetKind() & aKindMask ) if( item->OfKind ( aKindMask ) )
newItems.push_back( item ); newItems.push_back( item );
m_items = newItems; m_items = newItems;
...@@ -73,7 +87,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet ) ...@@ -73,7 +87,7 @@ PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
BOOST_FOREACH( PNS_ITEM * item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetNet() == aNet ) if( item->Net() == aNet )
newItems.push_back( item ); newItems.push_back( item );
m_items = newItems; m_items = newItems;
......
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PNS_ITEMSET_H #ifndef __PNS_ITEMSET_H
...@@ -37,10 +37,25 @@ class PNS_ITEMSET ...@@ -37,10 +37,25 @@ class PNS_ITEMSET
public: public:
typedef std::vector<PNS_ITEM*> ItemVector; typedef std::vector<PNS_ITEM*> ItemVector;
PNS_ITEMSET(); PNS_ITEMSET( PNS_ITEM *aInitialItem = NULL );
PNS_ITEMSET (const PNS_ITEMSET &aOther )
{
m_items = aOther.m_items;
m_ownedItems = ItemVector();
}
const PNS_ITEMSET& operator= (const PNS_ITEMSET &aOther)
{
m_items = aOther.m_items;
m_ownedItems = ItemVector();
return *this;
}
~PNS_ITEMSET(); ~PNS_ITEMSET();
ItemVector& Items() { return m_items; } ItemVector& Items() { return m_items; }
const ItemVector& CItems() const { return m_items; }
PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 ); PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 );
PNS_ITEMSET& FilterKinds( int aKindMask ); PNS_ITEMSET& FilterKinds( int aKindMask );
...@@ -55,8 +70,17 @@ public: ...@@ -55,8 +70,17 @@ public:
PNS_ITEM* Get( int index ) const { return m_items[index]; } PNS_ITEM* Get( int index ) const { return m_items[index]; }
void Clear();
void AddOwned ( PNS_ITEM *aItem )
{
m_items.push_back( aItem );
m_ownedItems.push_back( aItem );
}
private: private:
ItemVector m_items; ItemVector m_items;
ItemVector m_ownedItems;
}; };
#endif #endif
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PNS_JOINT_H #ifndef __PNS_JOINT_H
...@@ -72,7 +72,7 @@ public: ...@@ -72,7 +72,7 @@ public:
m_layers = b.m_layers; m_layers = b.m_layers;
} }
PNS_ITEM* Clone() const PNS_ITEM* Clone ( ) const
{ {
assert( false ); assert( false );
return NULL; return NULL;
...@@ -85,15 +85,15 @@ public: ...@@ -85,15 +85,15 @@ public:
if( m_linkedItems.size() != 2 ) if( m_linkedItems.size() != 2 )
return false; return false;
if( m_linkedItems[0]->GetKind() != SEGMENT || if( m_linkedItems[0]->Kind() != SEGMENT ||
m_linkedItems[1]->GetKind() != SEGMENT ) m_linkedItems[1]->Kind() != SEGMENT )
return false; return false;
PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*>( m_linkedItems[0] ); PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*>( m_linkedItems[0] );
PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*>( m_linkedItems[1] ); PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*>( m_linkedItems[1] );
// joints between segments of different widths are not trivial. // joints between segments of different widths are not considered trivial.
return seg1->GetWidth() == seg2->GetWidth(); return seg1->Width() == seg2->Width();
} }
///> Links the joint to a given board item (when it's added to the PNS_NODE) ///> Links the joint to a given board item (when it's added to the PNS_NODE)
...@@ -131,11 +131,35 @@ public: ...@@ -131,11 +131,35 @@ public:
return static_cast<PNS_SEGMENT*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] ); return static_cast<PNS_SEGMENT*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
} }
PNS_VIA *Via()
{
for( LinkedItems::iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i )
if( (*i)->Kind() == PNS_ITEM::VIA )
return (PNS_VIA *)(*i);
return NULL;
}
/// trivial accessors /// trivial accessors
const HashTag& GetTag() const { return m_tag; } const HashTag& Tag() const
const VECTOR2I& GetPos() const { return m_tag.pos; } {
int GetNet() const { return m_tag.net; } return m_tag;
LinkedItems& GetLinkList() { return m_linkedItems; }; }
const VECTOR2I& Pos() const
{
return m_tag.pos;
}
int Net() const
{
return m_tag.net;
}
LinkedItems& LinkList()
{
return m_linkedItems;
}
///> Returns the number of linked items of types listed in aMask. ///> Returns the number of linked items of types listed in aMask.
int LinkCount( int aMask = -1 ) const int LinkCount( int aMask = -1 ) const
...@@ -144,7 +168,7 @@ public: ...@@ -144,7 +168,7 @@ public:
for( LinkedItems::const_iterator i = m_linkedItems.begin(); for( LinkedItems::const_iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i ) i != m_linkedItems.end(); ++i )
if( (*i)->GetKind() & aMask ) if( (*i)->Kind() & aMask )
n++; n++;
return n; return n;
......
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PNS_LAYERSET_H #ifndef __PNS_LAYERSET_H
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pns_logger.h"
#include "pns_item.h"
#include "pns_via.h"
#include "pns_line.h"
#include "pns_segment.h"
#include "pns_solid.h"
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_circle.h>
PNS_LOGGER::PNS_LOGGER( )
{
m_groupOpened = false;
}
PNS_LOGGER::~PNS_LOGGER()
{
}
void PNS_LOGGER::Clear()
{
m_theLog.str(std::string());
m_groupOpened = false;
}
void PNS_LOGGER::NewGroup ( const std::string& name, int iter)
{
if(m_groupOpened)
m_theLog << "endgroup" << std::endl;
m_theLog << "group " << name << " " << iter << std::endl;
m_groupOpened = true;
}
void PNS_LOGGER::EndGroup()
{
if(!m_groupOpened)
return;
m_groupOpened = false;
m_theLog << "endgroup" << std::endl;
}
void PNS_LOGGER::Log ( const PNS_ITEM *item, int kind, const std::string name )
{
m_theLog << "item " << kind << " " << name << " ";
m_theLog << item->Net() << " " << item->Layers().Start() << " " << item->Layers().End() << " " << item->Marker() << " " << item->Rank();
switch(item->Kind())
{
case PNS_ITEM::LINE:
{
PNS_LINE *l = (PNS_LINE *) item;
m_theLog << " line ";
m_theLog << l->Width() << " " << (l->EndsWithVia() ? 1 : 0) << " ";
dumpShape ( l->Shape() );
m_theLog << std::endl;
break;
}
case PNS_ITEM::VIA:
{
m_theLog << " via 0 0 ";
dumpShape ( item->Shape() );
m_theLog << std::endl;
break;
}
case PNS_ITEM::SEGMENT:
{
PNS_SEGMENT *s =(PNS_SEGMENT *) item;
m_theLog << " line ";
m_theLog << s->Width() << " 0 linechain 2 0 " << s->Seg().A.x << " " <<s->Seg().A.y << " " << s->Seg().B.x << " " <<s->Seg().B.y << std::endl;
break;
}
case PNS_ITEM::SOLID:
{
PNS_SOLID *s = (PNS_SOLID*) item;
m_theLog << " solid 0 0 ";
dumpShape ( s->Shape() );
m_theLog << std::endl;
break;
}
default:
break;
}
}
void PNS_LOGGER::Log ( const SHAPE_LINE_CHAIN *l, int kind, const std::string name )
{
m_theLog << "item " << kind << " " << name << " ";
m_theLog << 0 << " " << 0 << " " << 0 << " " << 0 << " " << 0;
m_theLog << " line ";
m_theLog << 0 << " " << 0 << " ";
dumpShape ( l );
m_theLog << std::endl;
}
void PNS_LOGGER::Log ( const VECTOR2I& start, const VECTOR2I& end, int kind , const std::string name)
{
}
void PNS_LOGGER::dumpShape ( const SHAPE * sh )
{
switch(sh->Type())
{
case SH_LINE_CHAIN:
{
const SHAPE_LINE_CHAIN *lc = (const SHAPE_LINE_CHAIN *) sh;
m_theLog << "linechain " << lc->PointCount() << " " << (lc->IsClosed() ? 1 : 0) << " ";
for(int i = 0; i < lc->PointCount(); i++)
m_theLog << lc->CPoint(i).x << " " << lc->CPoint(i).y << " ";
break;
}
case SH_CIRCLE:
{
const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) sh;
m_theLog << "circle " << c->GetCenter().x << " " << c->GetCenter().y << " " << c->GetRadius();
break;
}
case SH_RECT:
{
const SHAPE_RECT *r = (const SHAPE_RECT *) sh;
m_theLog << "rect " << r->GetPosition().x << " " << r->GetPosition().y << " " << r->GetSize().x << " " <<r->GetSize().y;
break;
}
case SH_SEGMENT:
{
const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) sh;
m_theLog << "linechain 2 0 " << s->GetSeg().A.x << " " << s->GetSeg().A.y << " " << s->GetSeg().B.x << " " << s->GetSeg().B.y;
break;
}
default:
break;
}
}
void PNS_LOGGER::Save ( const std::string& filename )
{
EndGroup();
FILE *f=fopen(filename.c_str(),"wb");
printf("Saving to '%s' [%p]\n", filename.c_str(), f);
const std::string s = m_theLog.str();
fwrite(s.c_str(), 1, s.length(), f);
fclose(f);
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PNS_LOGGER_H
#define __PNS_LOGGER_H
#include <cstdio>
#include <vector>
#include <string>
#include <sstream>
#include <math/vector2d.h>
class PNS_ITEM;
class SHAPE_LINE_CHAIN;
class SHAPE;
class PNS_LOGGER {
public:
PNS_LOGGER();
~PNS_LOGGER();
void Save ( const std::string& filename );
void Clear();
void NewGroup ( const std::string& name, int iter = 0);
void EndGroup();
void Log ( const PNS_ITEM *item, int kind = 0, const std::string name = std::string () );
void Log ( const SHAPE_LINE_CHAIN *l, int kind = 0, const std::string name = std::string () );
void Log ( const VECTOR2I& start, const VECTOR2I& end, int kind = 0, const std::string name = std::string () );
private:
void dumpShape ( const SHAPE* sh );
bool m_groupOpened;
std::stringstream m_theLog;
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PNS_OPTIMIZER_H #ifndef __PNS_OPTIMIZER_H
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <geometry/shape_index_list.h> #include <geometry/shape_index_list.h>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
#include "range.h"
class PNS_NODE; class PNS_NODE;
class PNS_LINE; class PNS_LINE;
class PNS_ROUTER; class PNS_ROUTER;
...@@ -90,17 +92,17 @@ public: ...@@ -90,17 +92,17 @@ public:
{ {
MERGE_SEGMENTS = 0x01, MERGE_SEGMENTS = 0x01,
SMART_PADS = 0x02, SMART_PADS = 0x02,
MERGE_OBTUSE = 0x04 MERGE_OBTUSE = 0x04,
FANOUT_CLEANUP = 0x08
}; };
PNS_OPTIMIZER( PNS_NODE* aWorld ); PNS_OPTIMIZER( PNS_NODE* aWorld );
~PNS_OPTIMIZER(); ~PNS_OPTIMIZER();
///> a quick shortcut to optmize a line without creating and setting up an optimizer ///> a quick shortcut to optmize a line without creating and setting up an optimizer
static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld = NULL ); static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld);
bool Optimize( PNS_LINE* aLine, PNS_LINE* aResult = NULL, bool Optimize( PNS_LINE* aLine, PNS_LINE* aResult = NULL );
int aStartVertex = 0, int aEndVertex = -1 );
void SetWorld( PNS_NODE* aNode ) { m_world = aNode; } void SetWorld( PNS_NODE* aNode ) { m_world = aNode; }
void CacheStaticItem( PNS_ITEM* aItem ); void CacheStaticItem( PNS_ITEM* aItem );
...@@ -135,6 +137,7 @@ private: ...@@ -135,6 +137,7 @@ private:
bool removeUglyCorners( PNS_LINE* aLine ); bool removeUglyCorners( PNS_LINE* aLine );
bool runSmartPads( PNS_LINE* aLine ); bool runSmartPads( PNS_LINE* aLine );
bool mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step ); bool mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step );
bool fanoutCleanup( PNS_LINE * aLine );
bool checkColliding( PNS_ITEM* aItem, bool aUpdateCache = true ); bool checkColliding( PNS_ITEM* aItem, bool aUpdateCache = true );
bool checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath ); bool checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath );
......
This diff is collapsed.
This diff is collapsed.
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pns_routing_settings.h"
PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS()
{
m_routingMode = RM_Walkaround;
m_optimizerEffort = OE_Full;
m_removeLoops = true;
m_smartPads = true;
m_shoveVias = true;
m_suggestFinish = false;
m_followMouse = true;
m_startDiagonal = false;
m_shoveIterationLimit = 250;
m_shoveTimeLimit = 1000;
m_walkaroundIterationLimit = 40;
m_jumpOverObstacles = false;
m_smoothDraggedSegments = true;
m_canViolateDRC = false;
}
TIME_LIMIT PNS_ROUTING_SETTINGS::ShoveTimeLimit() const
{
return TIME_LIMIT ( m_shoveTimeLimit );
}
int PNS_ROUTING_SETTINGS::ShoveIterationLimit() const
{
return m_shoveIterationLimit;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment