← Back to team overview

kicad-developers team mailing list archive

[patch] bring (back) the autoplacer to GAL

 

Hi all,

The patch set in the attachment brings back the legacy autoplacement
tool in a GALified version since many people were asking for it. Now it
can either place selected set of components or all off-board components
through Place->Autoplace menu.

Testing & feedback - as always - is more than welcome :)

Best,
Tom

>From 0b62ad598efca634c19eafd89b38b35860b4e498 Mon Sep 17 00:00:00 2001
From: Tomasz Wlostowski <tomasz.wlostowski@xxxxxxx>
Date: Thu, 9 Aug 2018 16:01:18 +0200
Subject: [PATCH 1/3] pcbnew: renaming of autorouter/autoplacer files

---
 pcbnew/autorouter/ar_autoplacer.cpp         | 1298 +++++++++++++++++++++++++++
 pcbnew/autorouter/ar_cell.h                 |  116 +++
 pcbnew/autorouter/ar_matrix.cpp             |  547 +++++++++++
 pcbnew/autorouter/auto_place_footprints.cpp | 1298 ---------------------------
 pcbnew/autorouter/cell.h                    |  116 ---
 pcbnew/autorouter/routing_matrix.cpp        |  547 -----------
 6 files changed, 1961 insertions(+), 1961 deletions(-)
 create mode 100644 pcbnew/autorouter/ar_autoplacer.cpp
 create mode 100644 pcbnew/autorouter/ar_cell.h
 create mode 100644 pcbnew/autorouter/ar_matrix.cpp
 delete mode 100644 pcbnew/autorouter/auto_place_footprints.cpp
 delete mode 100644 pcbnew/autorouter/cell.h
 delete mode 100644 pcbnew/autorouter/routing_matrix.cpp

diff --git a/pcbnew/autorouter/ar_autoplacer.cpp b/pcbnew/autorouter/ar_autoplacer.cpp
new file mode 100644
index 0000000..289c9db
--- /dev/null
+++ b/pcbnew/autorouter/ar_autoplacer.cpp
@@ -0,0 +1,1298 @@
+/**
+ * @file auto_place_footprints.cpp
+ * @brief Functions to automatically place Footprints on a board.
+ */
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
+ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ *
+ * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <fctsys.h>
+#include <class_drawpanel.h>
+#include <confirm.h>
+#include <pcbnew.h>
+#include <pcb_edit_frame.h>
+#include <gr_basic.h>
+#include <macros.h>
+#include <msgpanel.h>
+
+#include <autorout.h>
+#include <cell.h>
+
+#include <class_board.h>
+#include <class_module.h>
+#include <class_track.h>
+#include <class_drawsegment.h>
+#include <convert_to_biu.h>
+#include <base_units.h>
+#include <protos.h>
+
+
+#define GAIN            16
+#define KEEP_OUT_MARGIN 500
+
+
+/* Penalty (cost) for CntRot90 and CntRot180:
+ * CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed)
+ */
+static const double OrientPenality[11] =
+{
+    2.0,        // CntRot = 0 rotation prohibited
+    1.9,        // CntRot = 1
+    1.8,        // CntRot = 2
+    1.7,        // CntRot = 3
+    1.6,        // CntRot = 4
+    1.5,        // CntRot = 5
+    1.4,        // CntRot = 5
+    1.3,        // CntRot = 7
+    1.2,        // CntRot = 8
+    1.1,        // CntRot = 9
+    1.0         // CntRot = 10 rotation authorized, no penalty
+};
+
+// Cell states.
+#define OUT_OF_BOARD        -2
+#define OCCUPED_By_MODULE   -1
+#define FREE_CELL   0
+
+
+static wxPoint  CurrPosition; // Current position of the current module placement
+double          MinCout;
+
+
+/* generates the Routing matrix, used to fing the best placement
+ * of a footprint.
+ * Allocate a "bitmap" which is an image of the real board
+ * the bitmap handles:
+ * - The free areas
+ * - penalties (cell not occupied, but near occupied areas)
+ * - cells occupied by footprints, board cutout ...
+ */
+int             genPlacementRoutingMatrix(  BOARD* aBrd, EDA_MSG_PANEL* messagePanel );
+
+/* searches for the optimal position of aModule.
+ * return 1 if placement impossible or 0 if OK.
+ */
+static int      getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame,
+                                           MODULE* aModule, wxDC* aDC );
+
+/*
+ * Function compute_Ratsnest_PlaceModule
+ * displays the module's ratsnest during displacement, and assess the "cost"
+ * of the position.
+ *
+ * The cost is the longest ratsnest distance with penalty for connections
+ * approaching 45 degrees.
+ */
+static double   compute_Ratsnest_PlaceModule( BOARD* aBrd );
+
+/* Place a footprint on the Routing matrix.
+ */
+void            genModuleOnRoutingMatrix( MODULE* Module );
+/*
+ * Displays the Placement/Routing matrix on the screen
+ */
+static void     drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC );
+
+static int      TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide );
+
+static void     CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
+                                        int marge, int aKeepOut, LSET aLayerMask );
+
+static MODULE*  PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC );
+static int      propagate();
+
+void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
+{
+    MODULE*             currModule = NULL;
+    wxPoint             PosOK;
+    wxPoint             memopos;
+    int                 error;
+    PCB_LAYER_ID            lay_tmp_TOP, lay_tmp_BOTTOM;
+
+    // Undo: init list
+    PICKED_ITEMS_LIST   newList;
+
+    newList.m_Status = UR_CHANGED;
+    ITEM_PICKER         picker( NULL, UR_CHANGED );
+
+    if( GetBoard()->m_Modules == NULL )
+        return;
+
+    m_canvas->SetAbortRequest( false );
+
+    switch( place_mode )
+    {
+    case PLACE_1_MODULE:
+        currModule = Module;
+
+        if( currModule == NULL )
+            return;
+
+        currModule->SetIsPlaced( false );
+        currModule->SetNeedsPlaced( false );
+        break;
+
+    case PLACE_OUT_OF_BOARD:
+        break;
+
+    case PLACE_ALL:
+
+        if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) )
+            return;
+
+        break;
+
+    case PLACE_INCREMENTAL:
+
+        if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) )
+            return;
+
+        break;
+    }
+
+    memopos = CurrPosition;
+    lay_tmp_BOTTOM  = g_Route_Layer_BOTTOM;
+    lay_tmp_TOP     = g_Route_Layer_TOP;
+
+    RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x;
+
+    // Ensure Board.m_GridRouting has a reasonable value:
+    if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) )
+        RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 );
+
+    // Compute module parameters used in auto place
+    if( genPlacementRoutingMatrix( GetBoard(), m_messagePanel ) == 0 )
+        return;
+
+    int moduleCount = 0;
+    Module = GetBoard()->m_Modules;
+
+    for( ; Module != NULL; Module = Module->Next() )
+    {
+        Module->SetNeedsPlaced( false );
+
+        switch( place_mode )
+        {
+        case PLACE_1_MODULE:
+
+            if( currModule == Module )
+            {
+                // Module will be placed, add to undo.
+                picker.SetItem( currModule );
+                newList.PushItem( picker );
+                Module->SetNeedsPlaced( true );
+            }
+
+            break;
+
+        case PLACE_OUT_OF_BOARD:
+            Module->SetIsPlaced( false );
+
+            if( Module->IsLocked() )
+                break;
+
+            if( !RoutingMatrix.m_BrdBox.Contains( Module->GetPosition() ) )
+            {
+                // Module will be placed, add to undo.
+                picker.SetItem( Module );
+                newList.PushItem( picker );
+                Module->SetNeedsPlaced( true );
+            }
+
+            break;
+
+        case PLACE_ALL:
+            Module->SetIsPlaced( false );
+
+            if( Module->IsLocked() )
+                break;
+
+            // Module will be placed, add to undo.
+            picker.SetItem( Module );
+            newList.PushItem( picker );
+            Module->SetNeedsPlaced( true );
+            break;
+
+        case PLACE_INCREMENTAL:
+
+            if( Module->IsLocked() )
+            {
+                Module->SetIsPlaced( false );
+                break;
+            }
+
+            if( !Module->NeedsPlaced() )
+            {
+                // Module will be placed, add to undo.
+                picker.SetItem( Module );
+                newList.PushItem( picker );
+                Module->SetNeedsPlaced( true );
+            }
+
+            break;
+        }
+
+        if( Module->NeedsPlaced() )    // Erase from screen
+        {
+            moduleCount++;
+            Module->Draw( m_canvas, DC, GR_XOR );
+        }
+        else
+        {
+            genModuleOnRoutingMatrix( Module );
+        }
+    }
+
+    // Undo command: prepare list
+    if( newList.GetCount() )
+        SaveCopyInUndoList( newList, UR_CHANGED );
+
+    int         cnt = 0;
+    wxString    msg;
+
+    while( ( Module = PickModule( this, DC ) ) != NULL )
+    {
+        // Display some info about activity, module placement can take a while:
+        msg.Printf( _( "Place footprint %d of %d" ), cnt, moduleCount );
+        SetStatusText( msg );
+
+        double initialOrient = Module->GetOrientation();
+        // Display fill area of interest, barriers, penalties.
+        drawPlacementRoutingMatrix( GetBoard(), DC );
+
+        error = getOptimalModulePlacement( this, Module, DC );
+        double bestScore = MinCout;
+        double bestRotation = 0.0;
+        int rotAllowed;
+        PosOK = CurrPosition;
+
+        if( error == ESC )
+            goto end_of_tst;
+
+        // Try orientations 90, 180, 270 degrees from initial orientation
+        rotAllowed = Module->GetPlacementCost180();
+
+        if( rotAllowed != 0 )
+        {
+            Rotate_Module( DC, Module, 1800.0, true );
+            error   = getOptimalModulePlacement( this, Module, DC );
+            MinCout *= OrientPenality[rotAllowed];
+
+            if( bestScore > MinCout )    // This orientation is better.
+            {
+                PosOK       = CurrPosition;
+                bestScore   = MinCout;
+                bestRotation = 1800.0;
+            }
+            else
+            {
+                Rotate_Module( DC, Module, initialOrient, false );
+            }
+
+            if( error == ESC )
+                goto end_of_tst;
+        }
+
+        // Determine if the best orientation of a module is 90.
+        rotAllowed = Module->GetPlacementCost90();
+
+        if( rotAllowed != 0 )
+        {
+            Rotate_Module( DC, Module, 900.0, true );
+            error   = getOptimalModulePlacement( this, Module, DC );
+            MinCout *= OrientPenality[rotAllowed];
+
+            if( bestScore > MinCout )    // This orientation is better.
+            {
+                PosOK       = CurrPosition;
+                bestScore   = MinCout;
+                bestRotation = 900.0;
+            }
+            else
+            {
+                Rotate_Module( DC, Module, initialOrient, false );
+            }
+
+            if( error == ESC )
+                goto end_of_tst;
+        }
+
+        // Determine if the best orientation of a module is -90.
+        if( rotAllowed != 0 )
+        {
+            Rotate_Module( DC, Module, 2700.0, true );
+            error   = getOptimalModulePlacement( this, Module, DC );
+            MinCout *= OrientPenality[rotAllowed];
+
+            if( bestScore > MinCout )    // This orientation is better.
+            {
+                PosOK       = CurrPosition;
+                bestScore   = MinCout;
+                bestRotation = 2700.0;
+            }
+            else
+            {
+                Rotate_Module( DC, Module, initialOrient, false );
+            }
+
+            if( error == ESC )
+                goto end_of_tst;
+        }
+
+end_of_tst:
+
+        if( error == ESC )
+            break;
+
+        // Place module.
+        CurrPosition = GetCrossHairPosition();
+        SetCrossHairPosition( PosOK );
+
+        PlaceModule( Module, DC );
+
+        bestRotation += initialOrient;
+
+        if( bestRotation != Module->GetOrientation() )
+            Rotate_Module( DC, Module, bestRotation, false );
+
+        SetCrossHairPosition( CurrPosition );
+
+        Module->CalculateBoundingBox();
+
+        genModuleOnRoutingMatrix( Module );
+        Module->SetIsPlaced( true );
+        Module->SetNeedsPlaced( false );
+    }
+
+    CurrPosition = memopos;
+
+    RoutingMatrix.UnInitRoutingMatrix();
+
+    g_Route_Layer_TOP       = lay_tmp_TOP;
+    g_Route_Layer_BOTTOM    = lay_tmp_BOTTOM;
+
+    Module = GetBoard()->m_Modules;
+
+    for( ; Module != NULL; Module = Module->Next() )
+    {
+        Module->CalculateBoundingBox();
+    }
+
+    GetBoard()->m_Status_Pcb = 0;
+    Compile_Ratsnest( DC, true );
+    m_canvas->ReDraw( DC, true );
+}
+
+
+void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC )
+{
+    int         ii, jj;
+    COLOR4D     color;
+    int         ox, oy;
+    MATRIX_CELL top_state, bottom_state;
+
+    GRSetDrawMode( DC, GR_COPY );
+
+    for( ii = 0; ii < RoutingMatrix.m_Nrows; ii++ )
+    {
+        oy = RoutingMatrix.m_BrdBox.GetY() + ( ii * RoutingMatrix.m_GridRouting );
+
+        for( jj = 0; jj < RoutingMatrix.m_Ncols; jj++ )
+        {
+            ox      = RoutingMatrix.m_BrdBox.GetX() + (jj * RoutingMatrix.m_GridRouting);
+            color   = COLOR4D::BLACK;
+
+            top_state       = RoutingMatrix.GetCell( ii, jj, TOP );
+            bottom_state    = RoutingMatrix.GetCell( ii, jj, BOTTOM );
+
+            if( top_state & CELL_is_ZONE )
+                color = COLOR4D( BLUE );
+
+            // obstacles
+            if( ( top_state & CELL_is_EDGE ) || ( bottom_state & CELL_is_EDGE ) )
+                color = COLOR4D::WHITE;
+            else if( top_state & ( HOLE | CELL_is_MODULE ) )
+                color = COLOR4D( LIGHTRED );
+            else if( bottom_state & (HOLE | CELL_is_MODULE) )
+                color = COLOR4D( LIGHTGREEN );
+            else    // Display the filling and keep out regions.
+            {
+                if( RoutingMatrix.GetDist( ii, jj, TOP )
+                    || RoutingMatrix.GetDist( ii, jj, BOTTOM ) )
+                    color = DARKGRAY;
+            }
+
+            GRPutPixel( NULL, DC, ox, oy, color );
+        }
+    }
+}
+
+
+int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel )
+{
+    wxString msg;
+
+    RoutingMatrix.UnInitRoutingMatrix();
+
+    EDA_RECT bbox = aBrd->GetBoardEdgesBoundingBox();
+
+    if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
+    {
+        DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) );
+        return 0;
+    }
+
+    RoutingMatrix.ComputeMatrixSize( aBrd, true );
+    int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows;
+
+    messagePanel->EraseMsgBox();
+    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols );
+    messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN );
+    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows );
+    messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN );
+    msg.Printf( wxT( "%d" ), nbCells );
+    messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW );
+
+    // Choose the number of board sides.
+    RoutingMatrix.m_RoutingLayersCount = 2;
+
+    RoutingMatrix.InitRoutingMatrix();
+
+    // Display memory usage.
+    msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 );
+    messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN );
+
+    g_Route_Layer_BOTTOM = F_Cu;
+
+    if( RoutingMatrix.m_RoutingLayersCount > 1 )
+        g_Route_Layer_BOTTOM = B_Cu;
+
+    g_Route_Layer_TOP = F_Cu;
+
+    // Place the edge layer segments
+    TRACK TmpSegm( NULL );
+
+    TmpSegm.SetLayer( UNDEFINED_LAYER );
+    TmpSegm.SetNetCode( -1 );
+    TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 );
+
+    for( auto PtStruct : aBrd->Drawings() )
+    {
+        DRAWSEGMENT* DrawSegm;
+
+        switch( PtStruct->Type() )
+        {
+        case PCB_LINE_T:
+            DrawSegm = (DRAWSEGMENT*) PtStruct;
+
+            if( DrawSegm->GetLayer() != Edge_Cuts )
+                break;
+
+            TraceSegmentPcb( DrawSegm, HOLE | CELL_is_EDGE,
+                             RoutingMatrix.m_GridRouting, WRITE_CELL );
+            break;
+
+        case PCB_TEXT_T:
+        default:
+            break;
+        }
+    }
+
+    // Mark cells of the routing matrix to CELL_is_ZONE
+    // (i.e. availlable cell to place a module )
+    // Init a starting point of attachment to the area.
+    RoutingMatrix.OrCell( RoutingMatrix.m_Nrows / 2, RoutingMatrix.m_Ncols / 2,
+                          BOTTOM, CELL_is_ZONE );
+
+    // find and mark all other availlable cells:
+    for( int ii = 1; ii != 0; )
+        ii = propagate();
+
+    // Initialize top layer. to the same value as the bottom layer
+    if( RoutingMatrix.m_BoardSide[TOP] )
+        memcpy( RoutingMatrix.m_BoardSide[TOP], RoutingMatrix.m_BoardSide[BOTTOM],
+                nbCells * sizeof(MATRIX_CELL) );
+
+    return 1;
+}
+
+
+/* Place module on Routing matrix.
+ */
+void genModuleOnRoutingMatrix( MODULE* Module )
+{
+    int         ox, oy, fx, fy;
+    LSET        layerMask;
+    D_PAD*      Pad;
+
+    EDA_RECT    fpBBox = Module->GetBoundingBox();
+
+    fpBBox.Inflate( RoutingMatrix.m_GridRouting / 2 );
+    ox  = fpBBox.GetX();
+    fx  = fpBBox.GetRight();
+    oy  = fpBBox.GetY();
+    fy  = fpBBox.GetBottom();
+
+    if( ox < RoutingMatrix.m_BrdBox.GetX() )
+        ox = RoutingMatrix.m_BrdBox.GetX();
+
+    if( ox > RoutingMatrix.m_BrdBox.GetRight() )
+        ox = RoutingMatrix.m_BrdBox.GetRight();
+
+    if( fx < RoutingMatrix.m_BrdBox.GetX() )
+        fx = RoutingMatrix.m_BrdBox.GetX();
+
+    if( fx > RoutingMatrix.m_BrdBox.GetRight() )
+        fx = RoutingMatrix.m_BrdBox.GetRight();
+
+    if( oy < RoutingMatrix.m_BrdBox.GetY() )
+        oy = RoutingMatrix.m_BrdBox.GetY();
+
+    if( oy > RoutingMatrix.m_BrdBox.GetBottom() )
+        oy = RoutingMatrix.m_BrdBox.GetBottom();
+
+    if( fy < RoutingMatrix.m_BrdBox.GetY() )
+        fy = RoutingMatrix.m_BrdBox.GetY();
+
+    if( fy > RoutingMatrix.m_BrdBox.GetBottom() )
+        fy = RoutingMatrix.m_BrdBox.GetBottom();
+
+    if( Module->GetLayer() == F_Cu )
+        layerMask.set( F_Cu );
+
+    if( Module->GetLayer() == B_Cu )
+        layerMask.set( B_Cu );
+
+    TraceFilledRectangle( ox, oy, fx, fy, layerMask,
+                          CELL_is_MODULE, WRITE_OR_CELL );
+
+    // Trace pads + clearance areas.
+    for( Pad = Module->Pads(); Pad != NULL; Pad = Pad->Next() )
+    {
+        int margin = (RoutingMatrix.m_GridRouting / 2) + Pad->GetClearance();
+        ::PlacePad( Pad, CELL_is_MODULE, margin, WRITE_OR_CELL );
+    }
+
+    // Trace clearance.
+    int margin = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN;
+    CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask );
+}
+
+
+// A minor helper function to draw a bounding box:
+inline void draw_FootprintRect( EDA_RECT* aClipBox, wxDC* aDC, EDA_RECT& fpBBox, COLOR4D aColor )
+{
+#ifndef USE_WX_OVERLAY
+    GRRect( aClipBox, aDC, fpBBox, 0, aColor );
+#endif
+}
+
+
+int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC )
+{
+    int     error = 1;
+    wxPoint LastPosOK;
+    double  min_cost, curr_cost, Score;
+    bool    TstOtherSide;
+    auto displ_opts = (PCB_DISPLAY_OPTIONS*)aFrame->GetDisplayOptions();
+    BOARD*  brd = aFrame->GetBoard();
+
+    aModule->CalculateBoundingBox();
+
+    bool showRats = displ_opts->m_Show_Module_Ratsnest;
+    displ_opts->m_Show_Module_Ratsnest = false;
+
+    brd->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
+    aFrame->SetMsgPanel( aModule );
+
+    LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin();
+
+    wxPoint     mod_pos = aModule->GetPosition();
+    EDA_RECT    fpBBox  = aModule->GetFootprintRect();
+
+    // Move fpBBox to have the footprint position at (0,0)
+    fpBBox.Move( -mod_pos );
+    wxPoint fpBBoxOrg = fpBBox.GetOrigin();
+
+    // Calculate the limit of the footprint position, relative
+    // to the routing matrix area
+    wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
+
+    wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
+
+    // Stay on grid.
+    initialPos.x    -= initialPos.x % RoutingMatrix.m_GridRouting;
+    initialPos.y    -= initialPos.y % RoutingMatrix.m_GridRouting;
+
+    CurrPosition = initialPos;
+
+    // Undraw the current footprint
+    aModule->DrawOutlinesWhenMoving( aFrame->GetCanvas(), aDC, wxPoint( 0, 0 ) );
+
+    g_Offset_Module = mod_pos - CurrPosition;
+
+    /* Examine pads, and set TstOtherSide to true if a footprint
+     * has at least 1 pad through.
+     */
+    TstOtherSide = false;
+
+    if( RoutingMatrix.m_RoutingLayersCount > 1 )
+    {
+        LSET    other( aModule->GetLayer() == B_Cu  ? F_Cu : B_Cu );
+
+        for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
+        {
+            if( !( pad->GetLayerSet() & other ).any() )
+                continue;
+
+            TstOtherSide = true;
+            break;
+        }
+    }
+
+    // Draw the initial bounding box position
+    COLOR4D color = COLOR4D( BROWN );
+    fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
+    draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color);
+
+    min_cost = -1.0;
+    aFrame->SetStatusText( wxT( "Score ??, pos ??" ) );
+
+    for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting )
+    {
+        wxYield();
+
+        if( aFrame->GetCanvas()->GetAbortRequest() )
+        {
+            if( IsOK( aFrame, _( "OK to abort?" ) ) )
+            {
+                displ_opts->m_Show_Module_Ratsnest = showRats;
+                return ESC;
+            }
+            else
+                aFrame->GetCanvas()->SetAbortRequest( false );
+        }
+
+        CurrPosition.y = initialPos.y;
+
+        for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting )
+        {
+            // Erase traces.
+            draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
+
+            fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
+            g_Offset_Module = mod_pos - CurrPosition;
+            int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide );
+
+            // Draw at new place
+            color = keepOutCost >= 0 ? BROWN : RED;
+            draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
+
+            if( keepOutCost >= 0 )    // i.e. if the module can be put here
+            {
+                error = 0;
+                aFrame->build_ratsnest_module( aModule );
+                curr_cost   = compute_Ratsnest_PlaceModule( brd );
+                Score       = curr_cost + keepOutCost;
+
+                if( (min_cost >= Score ) || (min_cost < 0 ) )
+                {
+                    LastPosOK   = CurrPosition;
+                    min_cost    = Score;
+                    wxString msg;
+                    msg.Printf( wxT( "Score %g, pos %s, %s" ),
+                                min_cost,
+                                GetChars( ::CoordinateToString( LastPosOK.x ) ),
+                                GetChars( ::CoordinateToString( LastPosOK.y ) ) );
+                    aFrame->SetStatusText( msg );
+                }
+            }
+        }
+    }
+
+    // erasing the last traces
+    GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
+
+    displ_opts->m_Show_Module_Ratsnest = showRats;
+
+    // Regeneration of the modified variable.
+    CurrPosition = LastPosOK;
+
+    brd->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK );
+
+    MinCout = min_cost;
+    return error;
+}
+
+
+/* Test if the rectangular area (ux, ux .. y0, y1):
+ * - is a free zone (except OCCUPED_By_MODULE returns)
+ * - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
+ *
+ * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
+ */
+int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
+{
+    EDA_RECT rect = aRect;
+
+    rect.Inflate( RoutingMatrix.m_GridRouting / 2 );
+
+    wxPoint start   = rect.GetOrigin();
+    wxPoint end     = rect.GetEnd();
+
+    start   -= RoutingMatrix.m_BrdBox.GetOrigin();
+    end     -= RoutingMatrix.m_BrdBox.GetOrigin();
+
+    int row_min = start.y / RoutingMatrix.m_GridRouting;
+    int row_max = end.y / RoutingMatrix.m_GridRouting;
+    int col_min = start.x / RoutingMatrix.m_GridRouting;
+    int col_max = end.x / RoutingMatrix.m_GridRouting;
+
+    if( start.y > row_min * RoutingMatrix.m_GridRouting )
+        row_min++;
+
+    if( start.x > col_min * RoutingMatrix.m_GridRouting )
+        col_min++;
+
+    if( row_min < 0 )
+        row_min = 0;
+
+    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
+        row_max = RoutingMatrix.m_Nrows - 1;
+
+    if( col_min < 0 )
+        col_min = 0;
+
+    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
+        col_max = RoutingMatrix.m_Ncols - 1;
+
+    for( int row = row_min; row <= row_max; row++ )
+    {
+        for( int col = col_min; col <= col_max; col++ )
+        {
+            unsigned int data = RoutingMatrix.GetCell( row, col, side );
+
+            if( ( data & CELL_is_ZONE ) == 0 )
+                return OUT_OF_BOARD;
+
+            if( (data & CELL_is_MODULE) )
+                return OCCUPED_By_MODULE;
+        }
+    }
+
+    return FREE_CELL;
+}
+
+
+/* Calculates and returns the clearance area of the rectangular surface
+ * aRect):
+ * (Sum of cells in terms of distance)
+ */
+unsigned int CalculateKeepOutArea( const EDA_RECT& aRect, int side )
+{
+    wxPoint start   = aRect.GetOrigin();
+    wxPoint end     = aRect.GetEnd();
+
+    start   -= RoutingMatrix.m_BrdBox.GetOrigin();
+    end     -= RoutingMatrix.m_BrdBox.GetOrigin();
+
+    int row_min = start.y / RoutingMatrix.m_GridRouting;
+    int row_max = end.y / RoutingMatrix.m_GridRouting;
+    int col_min = start.x / RoutingMatrix.m_GridRouting;
+    int col_max = end.x / RoutingMatrix.m_GridRouting;
+
+    if( start.y > row_min * RoutingMatrix.m_GridRouting )
+        row_min++;
+
+    if( start.x > col_min * RoutingMatrix.m_GridRouting )
+        col_min++;
+
+    if( row_min < 0 )
+        row_min = 0;
+
+    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
+        row_max = RoutingMatrix.m_Nrows - 1;
+
+    if( col_min < 0 )
+        col_min = 0;
+
+    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
+        col_max = RoutingMatrix.m_Ncols - 1;
+
+    unsigned int keepOutCost = 0;
+
+    for( int row = row_min; row <= row_max; row++ )
+    {
+        for( int col = col_min; col <= col_max; col++ )
+        {
+            // RoutingMatrix.GetDist returns the "cost" of the cell
+            // at position (row, col)
+            // in autoplace this is the cost of the cell, if it is
+            // inside aRect
+            keepOutCost += RoutingMatrix.GetDist( row, col, side );
+        }
+    }
+
+    return keepOutCost;
+}
+
+
+/* Test if the module can be placed on the board.
+ * Returns the value TstRectangle().
+ * Module is known by its bounding box
+ */
+int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide )
+{
+    int side = TOP;
+    int otherside = BOTTOM;
+
+    if( aModule->GetLayer() == B_Cu )
+    {
+        side = BOTTOM; otherside = TOP;
+    }
+
+    EDA_RECT    fpBBox = aModule->GetFootprintRect();
+    fpBBox.Move( -g_Offset_Module );
+
+    int         diag = TstRectangle( Pcb, fpBBox, side );
+
+    if( diag != FREE_CELL )
+        return diag;
+
+    if( TstOtherSide )
+    {
+        diag = TstRectangle( Pcb, fpBBox, otherside );
+
+        if( diag != FREE_CELL )
+            return diag;
+    }
+
+    int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN;
+
+    fpBBox.Inflate( marge );
+    return CalculateKeepOutArea( fpBBox, side );
+}
+
+
+double compute_Ratsnest_PlaceModule( BOARD* aBrd )
+{
+    double  curr_cost;
+    wxPoint start;      // start point of a ratsnest
+    wxPoint end;        // end point of a ratsnest
+    int     dx, dy;
+
+    if( ( aBrd->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 )
+        return -1;
+
+    curr_cost = 0;
+
+    for( unsigned ii = 0; ii < aBrd->m_LocalRatsnest.size(); ii++ )
+    {
+        RATSNEST_ITEM* pt_local_rats_nest = &aBrd->m_LocalRatsnest[ii];
+
+        if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) )
+            continue; // Skip ratsnest between 2 pads of the current module
+
+        // Skip modules not inside the board area
+        MODULE* module = pt_local_rats_nest->m_PadEnd->GetParent();
+
+        if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) )
+            continue;
+
+        start   = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module;
+        end     = pt_local_rats_nest->m_PadEnd->GetPosition();
+
+        // Cost of the ratsnest.
+        dx  = end.x - start.x;
+        dy  = end.y - start.y;
+
+        dx  = abs( dx );
+        dy  = abs( dy );
+
+        // ttry to have always dx >= dy to calculate the cost of the rastsnet
+        if( dx < dy )
+            std::swap( dx, dy );
+
+        // Cost of the connection = length + penalty due to the slope
+        // dx is the biggest length relative to the X or Y axis
+        // the penalty is max for 45 degrees ratsnests,
+        // and 0 for horizontal or vertical ratsnests.
+        // For Horizontal and Vertical ratsnests, dy = 0;
+        double conn_cost = hypot( dx, dy * 2.0 );
+        curr_cost += conn_cost;    // Total cost = sum of costs of each connection
+    }
+
+    return curr_cost;
+}
+
+
+/**
+ * Function CreateKeepOutRectangle
+ * builds the cost map:
+ * Cells ( in Dist map ) inside the rect x0,y0 a x1,y1 are
+ *  incremented by value aKeepOut
+ *  Cell outside this rectangle, but inside the rectangle
+ *  x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value
+ *  (aKeepOut ... 0). The decreasing value depends on the distance to the first rectangle
+ *  Therefore the cost is high in rect x0,y0 to x1,y1, and decrease outside this rectangle
+ */
+void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
+                             int marge, int aKeepOut, LSET aLayerMask )
+{
+    int         row, col;
+    int         row_min, row_max, col_min, col_max, pmarge;
+    int         trace = 0;
+    DIST_CELL   data, LocalKeepOut;
+    int         lgain, cgain;
+
+    if( aLayerMask[g_Route_Layer_BOTTOM] )
+        trace = 1; // Trace on bottom layer.
+
+    if( aLayerMask[g_Route_Layer_TOP] && RoutingMatrix.m_RoutingLayersCount )
+        trace |= 2; // Trace on top layer.
+
+    if( trace == 0 )
+        return;
+
+    ux0 -= RoutingMatrix.m_BrdBox.GetX();
+    uy0 -= RoutingMatrix.m_BrdBox.GetY();
+    ux1 -= RoutingMatrix.m_BrdBox.GetX();
+    uy1 -= RoutingMatrix.m_BrdBox.GetY();
+
+    ux0 -= marge; ux1 += marge;
+    uy0 -= marge; uy1 += marge;
+
+    pmarge = marge / RoutingMatrix.m_GridRouting;
+
+    if( pmarge < 1 )
+        pmarge = 1;
+
+    // Calculate the coordinate limits of the rectangle.
+    row_max = uy1 / RoutingMatrix.m_GridRouting;
+    col_max = ux1 / RoutingMatrix.m_GridRouting;
+    row_min = uy0 / RoutingMatrix.m_GridRouting;
+
+    if( uy0 > row_min * RoutingMatrix.m_GridRouting )
+        row_min++;
+
+    col_min = ux0 / RoutingMatrix.m_GridRouting;
+
+    if( ux0 > col_min * RoutingMatrix.m_GridRouting )
+        col_min++;
+
+    if( row_min < 0 )
+        row_min = 0;
+
+    if( row_max >= (RoutingMatrix.m_Nrows - 1) )
+        row_max = RoutingMatrix.m_Nrows - 1;
+
+    if( col_min < 0 )
+        col_min = 0;
+
+    if( col_max >= (RoutingMatrix.m_Ncols - 1) )
+        col_max = RoutingMatrix.m_Ncols - 1;
+
+    for( row = row_min; row <= row_max; row++ )
+    {
+        lgain = 256;
+
+        if( row < pmarge )
+            lgain = ( 256 * row ) / pmarge;
+        else if( row > row_max - pmarge )
+            lgain = ( 256 * ( row_max - row ) ) / pmarge;
+
+        for( col = col_min; col <= col_max; col++ )
+        {
+            // RoutingMatrix Dist map containt the "cost" of the cell
+            // at position (row, col)
+            // in autoplace this is the cost of the cell, when
+            // a footprint overlaps it, near a "master" footprint
+            // this cost is hight near the "master" footprint
+            // and decrease with the distance
+            cgain = 256;
+            LocalKeepOut = aKeepOut;
+
+            if( col < pmarge )
+                cgain = ( 256 * col ) / pmarge;
+            else if( col > col_max - pmarge )
+                cgain = ( 256 * ( col_max - col ) ) / pmarge;
+
+            cgain = ( cgain * lgain ) / 256;
+
+            if( cgain != 256 )
+                LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
+
+            if( trace & 1 )
+            {
+                data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut;
+                RoutingMatrix.SetDist( row, col, BOTTOM, data );
+            }
+
+            if( trace & 2 )
+            {
+                data    = RoutingMatrix.GetDist( row, col, TOP );
+                data    = std::max( data, LocalKeepOut );
+                RoutingMatrix.SetDist( row, col, TOP, data );
+            }
+        }
+    }
+}
+
+
+// Sort routines
+static bool Tri_PlaceModules( MODULE* ref, MODULE* compare )
+{
+    double ff1, ff2;
+
+    ff1 = ref->GetArea() * ref->GetPadCount();
+    ff2 = compare->GetArea() * compare->GetPadCount();
+
+    return ff2 < ff1;
+}
+
+
+static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare )
+{
+    double ff1, ff2;
+
+    ff1 = ref->GetArea() * ref->GetFlag();
+    ff2 = compare->GetArea() * compare->GetFlag();
+    return ff2 < ff1;
+}
+
+
+/**
+ * Function PickModule
+ * find the "best" module place
+ * The criteria are:
+ * - Maximum ratsnest with modules already placed
+ * - Max size, and number of pads max
+ */
+static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
+{
+    MODULE* Module;
+    std::vector <MODULE*> moduleList;
+
+    // Build sorted footprints list (sort by decreasing size )
+    Module = pcbframe->GetBoard()->m_Modules;
+
+    for( ; Module != NULL; Module = Module->Next() )
+    {
+        Module->CalculateBoundingBox();
+        moduleList.push_back( Module );
+    }
+
+    sort( moduleList.begin(), moduleList.end(), Tri_PlaceModules );
+
+    for( unsigned kk = 0; kk < moduleList.size(); kk++ )
+    {
+        Module = moduleList[kk];
+        Module->SetFlag( 0 );
+
+        if( !Module->NeedsPlaced() )
+            continue;
+
+        pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
+        pcbframe->SetMsgPanel( Module );
+        pcbframe->build_ratsnest_module( Module );
+
+        // Calculate external ratsnest.
+        for( unsigned ii = 0; ii < pcbframe->GetBoard()->m_LocalRatsnest.size(); ii++ )
+        {
+            if( ( pcbframe->GetBoard()->m_LocalRatsnest[ii].m_Status &
+                  LOCAL_RATSNEST_ITEM ) == 0 )
+                Module->IncrementFlag();
+        }
+    }
+
+    pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
+
+    sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize );
+
+    // Search for "best" module.
+    MODULE* bestModule  = NULL;
+    MODULE* altModule   = NULL;
+
+    for( unsigned ii = 0; ii < moduleList.size(); ii++ )
+    {
+        Module = moduleList[ii];
+
+        if( !Module->NeedsPlaced() )
+            continue;
+
+        altModule = Module;
+
+        if( Module->GetFlag() == 0 )
+            continue;
+
+        bestModule = Module;
+        break;
+    }
+
+    if( bestModule )
+        return bestModule;
+    else
+        return altModule;
+}
+
+
+/**
+ * Function propagate
+ * Used only in autoplace calculations
+ * Uses the routing matrix to fill the cells within the zone
+ * Search and mark cells within the zone, and agree with DRC options.
+ * Requirements:
+ * Start from an initial point, to fill zone
+ * The zone must have no "copper island"
+ *  Algorithm:
+ *  If the current cell has a neighbor flagged as "cell in the zone", it
+ *  become a cell in the zone
+ *  The first point in the zone is the starting point
+ *  4 searches within the matrix are made:
+ *          1 - Left to right and top to bottom
+ *          2 - Right to left and top to bottom
+ *          3 - bottom to top and Right to left
+ *          4 - bottom to top and Left to right
+ *  Given the current cell, for each search, we consider the 2 neighbor cells
+ *  the previous cell on the same line and the previous cell on the same column.
+ *
+ *  This function can request some iterations
+ *  Iterations are made until no cell is added to the zone.
+ *  @return added cells count (i.e. which the attribute CELL_is_ZONE is set)
+ */
+int propagate()
+{
+    int     row, col;
+    long    current_cell, old_cell_H;
+    std::vector<long> pt_cell_V;
+    int     nbpoints = 0;
+
+#define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
+
+    pt_cell_V.reserve( std::max( RoutingMatrix.m_Nrows, RoutingMatrix.m_Ncols ) );
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+
+    // Search from left to right and top to bottom.
+    for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
+    {
+        old_cell_H = 0;
+
+        for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
+        {
+            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+
+            if( current_cell == 0 )    // a free cell is found
+            {
+                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
+                {
+                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
+                    current_cell = CELL_is_ZONE;
+                    nbpoints++;
+                }
+            }
+
+            pt_cell_V[col] = old_cell_H = current_cell;
+        }
+    }
+
+    // Search from right to left and top to bottom/
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+
+    for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
+    {
+        old_cell_H = 0;
+
+        for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
+        {
+            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+
+            if( current_cell == 0 )    // a free cell is found
+            {
+                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
+                {
+                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
+                    current_cell = CELL_is_ZONE;
+                    nbpoints++;
+                }
+            }
+
+            pt_cell_V[col] = old_cell_H = current_cell;
+        }
+    }
+
+    // Search from bottom to top and right to left.
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+
+    for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
+    {
+        old_cell_H = 0;
+
+        for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
+        {
+            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+
+            if( current_cell == 0 )    // a free cell is found
+            {
+                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
+                {
+                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
+                    current_cell = CELL_is_ZONE;
+                    nbpoints++;
+                }
+            }
+
+            pt_cell_V[row] = old_cell_H = current_cell;
+        }
+    }
+
+    // Search from bottom to top and left to right.
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+
+    for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
+    {
+        old_cell_H = 0;
+
+        for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
+        {
+            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+
+            if( current_cell == 0 )    // a free cell is found
+            {
+                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
+                {
+                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
+                    current_cell = CELL_is_ZONE;
+                    nbpoints++;
+                }
+            }
+
+            pt_cell_V[row] = old_cell_H = current_cell;
+        }
+    }
+
+    return nbpoints;
+}
diff --git a/pcbnew/autorouter/ar_cell.h b/pcbnew/autorouter/ar_cell.h
new file mode 100644
index 0000000..63b76ae
--- /dev/null
+++ b/pcbnew/autorouter/ar_cell.h
@@ -0,0 +1,116 @@
+/**
+ * @file cell.h
+ */
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
+ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ *
+ * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
+ *
+ * First copyright (C) Randy Nevin, 1989 (see PCBCA package)
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+
+#ifndef _CELL_H_
+#define _CELL_H_
+
+
+/* Bits characterizing cell */
+#define HOLE           0x01  /* a conducting hole or obstacle */
+#define CELL_is_MODULE 0x02  /* auto placement occupied by a module */
+#define CELL_is_EDGE   0x20  /* Area and auto-placement: limiting cell contour (Board, Zone) */
+#define CELL_is_FRIEND 0x40  /* Area and auto-placement: cell part of the net */
+#define CELL_is_ZONE   0x80  /* Area and auto-placement: cell available */
+
+/* Bit masks for presence of obstacles to autorouting */
+#define OCCUPE            1  /* Autorouting: obstacle tracks and vias. */
+#define VIA_IMPOSSIBLE    2  /* Autorouting: obstacle for vias. */
+#define CURRENT_PAD       4
+
+
+/* traces radiating outward from a hole to a side or corner */
+#define HOLE_NORTH        0x00000002L /* upward       */
+#define HOLE_NORTHEAST    0x00000004L /* upward and right */
+#define HOLE_EAST         0x00000008L /* to the right     */
+#define HOLE_SOUTHEAST    0x00000010L /* downward and right   */
+#define HOLE_SOUTH        0x00000020L /* downward     */
+#define HOLE_SOUTHWEST    0x00000040L /* downward and left    */
+#define HOLE_WEST         0x00000080L /* to the left      */
+#define HOLE_NORTHWEST    0x00000100L /* upward and left  */
+
+/* straight lines through the center */
+#define LINE_HORIZONTAL   0x00000002L /* left-to-right line   */
+#define LINE_VERTICAL     0x00000004L /* top-to-bottom line   */
+
+/* lines cutting across a corner, connecting adjacent sides */
+#define CORNER_NORTHEAST  0x00000008L /* upper right corner   */
+#define CORNER_SOUTHEAST  0x00000010L /* lower right corner   */
+#define CORNER_SOUTHWEST  0x00000020L /* lower left corner    */
+#define CORNER_NORTHWEST  0x00000040L /* upper left corner    */
+
+/* diagonal lines through the center */
+#define DIAG_NEtoSW       0x00000080L /* northeast to southwest */
+#define DIAG_SEtoNW       0x00000100L /* southeast to northwest */
+
+/* 135 degree angle side-to-far-corner lines */
+#define BENT_NtoSE        0x00000200L /* north to southeast   */
+#define BENT_NtoSW        0x00000400L /* north to southwest   */
+#define BENT_EtoSW        0x00000800L /* east to southwest    */
+#define BENT_EtoNW        0x00001000L /* east to northwest    */
+#define BENT_StoNW        0x00002000L /* south to northwest   */
+#define BENT_StoNE        0x00004000L /* south to northeast   */
+#define BENT_WtoNE        0x00008000L /* west to northeast    */
+#define BENT_WtoSE        0x00010000L /* west to southeast    */
+
+/* 90 degree corner-to-adjacent-corner lines */
+#define ANGLE_NEtoSE      0x00020000L /* northeast to southeast */
+#define ANGLE_SEtoSW      0x00040000L /* southeast to southwest */
+#define ANGLE_SWtoNW      0x00080000L /* southwest to northwest */
+#define ANGLE_NWtoNE      0x00100000L /* northwest to northeast */
+
+/* 45 degree angle side-to-near-corner lines */
+#define SHARP_NtoNE       0x00200000L /* north to northeast   */
+#define SHARP_EtoNE       0x00400000L /* east to northeast    */
+#define SHARP_EtoSE       0x00800000L /* east to southeast    */
+#define SHARP_StoSE       0x01000000L /* south to southeast   */
+#define SHARP_StoSW       0x02000000L /* south to southwest   */
+#define SHARP_WtoSW       0x04000000L /* west to southwest    */
+#define SHARP_WtoNW       0x08000000L /* west to northwest    */
+#define SHARP_NtoNW       0x10000000L /* north to northwest   */
+
+/* directions the cell can be reached from (point to previous cell) */
+#define FROM_NOWHERE      0
+#define FROM_NORTH        1
+#define FROM_NORTHEAST    2
+#define FROM_EAST         3
+#define FROM_SOUTHEAST    4
+#define FROM_SOUTH        5
+#define FROM_SOUTHWEST    6
+#define FROM_WEST         7
+#define FROM_NORTHWEST    8
+#define FROM_OTHERSIDE    9
+
+
+#endif    // _CELL_H_
+
diff --git a/pcbnew/autorouter/ar_matrix.cpp b/pcbnew/autorouter/ar_matrix.cpp
new file mode 100644
index 0000000..856dead
--- /dev/null
+++ b/pcbnew/autorouter/ar_matrix.cpp
@@ -0,0 +1,547 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
+ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ *
+ * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * @file routing_matrix.cpp
+ * @brief Functions to create autorouting maps
+ */
+
+#include <fctsys.h>
+#include <common.h>
+
+#include <pcbnew.h>
+#include <cell.h>
+#include <autorout.h>
+
+#include <class_eda_rect.h>
+#include <class_board.h>
+#include <class_module.h>
+#include <class_track.h>
+#include <class_drawsegment.h>
+#include <class_edge_mod.h>
+#include <class_pcb_text.h>
+
+
+MATRIX_ROUTING_HEAD::MATRIX_ROUTING_HEAD()
+{
+    m_BoardSide[0] = m_BoardSide[1] = NULL;
+    m_DistSide[0] = m_DistSide[1] = NULL;
+    m_DirSide[0] = m_DirSide[1] = NULL;
+    m_opWriteCell        = NULL;
+    m_InitMatrixDone     = false;
+    m_Nrows              = 0;
+    m_Ncols              = 0;
+    m_MemSize            = 0;
+    m_RoutingLayersCount = 1;
+    m_GridRouting        = 0;
+    m_RouteCount         = 0;
+}
+
+
+MATRIX_ROUTING_HEAD::~MATRIX_ROUTING_HEAD()
+{
+}
+
+
+bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly )
+{
+    // The boundary box must have its start point on routing grid:
+    m_BrdBox = aUseBoardEdgesOnly ? aPcb->GetBoardEdgesBoundingBox() : aPcb->GetBoundingBox();
+
+    m_BrdBox.SetX( m_BrdBox.GetX() - ( m_BrdBox.GetX() % m_GridRouting ) );
+    m_BrdBox.SetY( m_BrdBox.GetY() - ( m_BrdBox.GetY() % m_GridRouting ) );
+
+    // The boundary box must have its end point on routing grid:
+    wxPoint end = m_BrdBox.GetEnd();
+
+    end.x -= end.x % m_GridRouting;
+    end.x += m_GridRouting;
+
+    end.y -= end.y % m_GridRouting;
+    end.y += m_GridRouting;
+
+    m_BrdBox.SetEnd( end );
+
+    m_Nrows = m_BrdBox.GetHeight() / m_GridRouting;
+    m_Ncols = m_BrdBox.GetWidth() / m_GridRouting;
+
+    // gives a small margin
+    m_Ncols += 1;
+    m_Nrows += 1;
+
+    return true;
+}
+
+
+int MATRIX_ROUTING_HEAD::InitRoutingMatrix()
+{
+    if( m_Nrows <= 0 || m_Ncols <= 0 )
+        return 0;
+
+    m_InitMatrixDone = true;     // we have been called
+
+    // give a small margin for memory allocation:
+    int ii = (RoutingMatrix.m_Nrows + 1) * (RoutingMatrix.m_Ncols + 1);
+
+    int side = BOTTOM;
+    for( int jj = 0; jj < m_RoutingLayersCount; jj++ )  // m_RoutingLayersCount = 1 or 2
+    {
+        m_BoardSide[side] = NULL;
+        m_DistSide[side]  = NULL;
+        m_DirSide[side]   = NULL;
+
+        // allocate matrix & initialize everything to empty
+        m_BoardSide[side] = (MATRIX_CELL*) operator new( ii * sizeof(MATRIX_CELL) );
+        memset( m_BoardSide[side], 0, ii * sizeof(MATRIX_CELL) );
+
+        if( m_BoardSide[side] == NULL )
+            return -1;
+
+        // allocate Distances
+        m_DistSide[side] = (DIST_CELL*) operator new( ii * sizeof(DIST_CELL) );
+        memset( m_DistSide[side], 0, ii * sizeof(DIST_CELL) );
+
+        if( m_DistSide[side] == NULL )
+            return -1;
+
+        // allocate Dir (chars)
+        m_DirSide[side] = (char*) operator new( ii );
+        memset( m_DirSide[side], 0, ii );
+
+        if( m_DirSide[side] == NULL )
+            return -1;
+
+        side = TOP;
+    }
+
+    m_MemSize = m_RouteCount * ii * ( sizeof(MATRIX_CELL)
+                + sizeof(DIST_CELL) + sizeof(char) );
+
+    return m_MemSize;
+}
+
+
+void MATRIX_ROUTING_HEAD::UnInitRoutingMatrix()
+{
+    int ii;
+
+    m_InitMatrixDone = false;
+
+    for( ii = 0; ii < MAX_ROUTING_LAYERS_COUNT; ii++ )
+    {
+        // de-allocate Dir matrix
+        if( m_DirSide[ii] )
+        {
+            delete m_DirSide[ii];
+            m_DirSide[ii] = NULL;
+        }
+
+        // de-allocate Distances matrix
+        if( m_DistSide[ii] )
+        {
+            delete m_DistSide[ii];
+            m_DistSide[ii] = NULL;
+        }
+
+        // de-allocate cells matrix
+        if( m_BoardSide[ii] )
+        {
+            delete m_BoardSide[ii];
+            m_BoardSide[ii] = NULL;
+        }
+    }
+
+    m_Nrows = m_Ncols = 0;
+}
+
+
+/**
+ * Function PlaceCells
+ * Initialize the matrix routing by setting obstacles for each occupied cell
+ * a cell set to HOLE is an obstacle for tracks and vias
+ * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only.
+ * a cell set to CELL_is_EDGE is a frontier.
+ * Tracks and vias having the same net code as net_code are skipped
+ * (htey do not are obstacles)
+ *
+ * For single-sided Routing 1:
+ * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP
+ *
+ * If flag == FORCE_PADS: all pads will be put in matrix as obstacles.
+ */
+void PlaceCells( BOARD* aPcb, int net_code, int flag )
+{
+    int     ux0 = 0, uy0 = 0, ux1, uy1, dx, dy;
+    int     marge, via_marge;
+    LSET    layerMask;
+
+    // use the default NETCLASS?
+    NETCLASSPTR nc = aPcb->GetDesignSettings().GetDefault();
+
+    int     trackWidth = nc->GetTrackWidth();
+    int     clearance  = nc->GetClearance();
+    int     viaSize    = nc->GetViaDiameter();
+
+    marge     = clearance + (trackWidth / 2);
+    via_marge = clearance + (viaSize / 2);
+
+    // Place PADS on matrix routing:
+    for( unsigned i = 0; i < aPcb->GetPadCount(); ++i )
+    {
+        D_PAD* pad = aPcb->GetPad( i );
+
+        if( net_code != pad->GetNetCode() || (flag & FORCE_PADS) )
+        {
+            ::PlacePad( pad, HOLE, marge, WRITE_CELL );
+        }
+
+        ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
+    }
+
+    // Place outlines of modules on matrix routing, if they are on a copper layer
+    // or on the edge layer
+
+    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
+    {
+        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
+        {
+            switch( item->Type() )
+            {
+            case PCB_MODULE_EDGE_T:
+            {
+                EDGE_MODULE* edge = (EDGE_MODULE*) item;
+                EDGE_MODULE tmpEdge( *edge );
+
+                if( tmpEdge.GetLayer() == Edge_Cuts )
+                    tmpEdge.SetLayer( UNDEFINED_LAYER );
+
+                TraceSegmentPcb( &tmpEdge, HOLE, marge, WRITE_CELL );
+                TraceSegmentPcb( &tmpEdge, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
+            }
+            break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+    // Place board outlines and texts on copper layers:
+    for( auto item : aPcb->Drawings() )
+    {
+        switch( item->Type() )
+        {
+        case PCB_LINE_T:
+            {
+                DRAWSEGMENT* DrawSegm;
+
+                int          type_cell = HOLE;
+                DrawSegm = (DRAWSEGMENT*) item;
+                DRAWSEGMENT tmpSegm( DrawSegm );
+
+                if( DrawSegm->GetLayer() == Edge_Cuts )
+                {
+                    tmpSegm.SetLayer( UNDEFINED_LAYER );
+                    type_cell |= CELL_is_EDGE;
+                }
+
+                TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL );
+            }
+            break;
+
+        case PCB_TEXT_T:
+            {
+                TEXTE_PCB* PtText = (TEXTE_PCB*) item;
+
+                if( PtText->GetText().Length() == 0 )
+                    break;
+
+                EDA_RECT textbox = PtText->GetTextBox( -1 );
+                ux0 = textbox.GetX();
+                uy0 = textbox.GetY();
+                dx  = textbox.GetWidth();
+                dy  = textbox.GetHeight();
+
+                // Put bounding box (rectangle) on matrix
+                dx /= 2;
+                dy /= 2;
+
+                ux1 = ux0 + dx;
+                uy1 = uy0 + dy;
+
+                ux0 -= dx;
+                uy0 -= dy;
+
+                layerMask = LSET( PtText->GetLayer() );
+
+                TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge,
+                                      uy1 + marge, PtText->GetTextAngle(),
+                                      layerMask, HOLE, WRITE_CELL );
+
+                TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge,
+                                      ux1 + via_marge, uy1 + via_marge,
+                                      PtText->GetTextAngle(),
+                                      layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL );
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    // Put tracks and vias on matrix
+    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
+    {
+        if( net_code == track->GetNetCode() )
+            continue;
+
+        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
+        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
+    }
+}
+
+
+int Build_Work( BOARD* Pcb )
+{
+    RATSNEST_ITEM*  pt_rats;
+    D_PAD*          pt_pad;
+    int             r1, r2, c1, c2, current_net_code;
+    RATSNEST_ITEM*  pt_ch;
+    int             demi_pas = RoutingMatrix.m_GridRouting / 2;
+    wxString        msg;
+
+    InitWork(); // clear work list
+    int cellCount = 0;
+
+    for( unsigned ii = 0; ii < Pcb->GetRatsnestsCount(); ii++ )
+    {
+        pt_rats = &Pcb->m_FullRatsnest[ii];
+
+        /* We consider here only ratsnest that are active ( obviously not yet routed)
+         * and routables (that are not yet attempt to be routed and fail
+         */
+        if( (pt_rats->m_Status & CH_ACTIF) == 0 )
+            continue;
+
+        if( pt_rats->m_Status & CH_UNROUTABLE )
+            continue;
+
+        if( (pt_rats->m_Status & CH_ROUTE_REQ) == 0 )
+            continue;
+
+        pt_pad = pt_rats->m_PadStart;
+
+        current_net_code = pt_pad->GetNetCode();
+        pt_ch = pt_rats;
+
+        r1 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY() + demi_pas )
+            / RoutingMatrix.m_GridRouting;
+
+        if( r1 < 0 || r1 >= RoutingMatrix.m_Nrows )
+        {
+            msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r1,
+                        pt_pad->GetPosition().y, RoutingMatrix.m_BrdBox.GetY() );
+            wxMessageBox( msg );
+            return 0;
+        }
+
+        c1 = ( pt_pad->GetPosition().x - RoutingMatrix.m_BrdBox.GetX() + demi_pas ) / RoutingMatrix.m_GridRouting;
+
+        if( c1 < 0 || c1 >= RoutingMatrix.m_Ncols )
+        {
+            msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c1,
+                        pt_pad->GetPosition().x, RoutingMatrix.m_BrdBox.GetX() );
+            wxMessageBox( msg );
+            return 0;
+        }
+
+        pt_pad = pt_rats->m_PadEnd;
+
+        r2 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY()
+               + demi_pas ) / RoutingMatrix.m_GridRouting;
+
+        if( r2 < 0 || r2 >= RoutingMatrix.m_Nrows )
+        {
+            msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r2,
+                        pt_pad->GetPosition().y, RoutingMatrix.m_BrdBox.GetY() );
+            wxMessageBox( msg );
+            return 0;
+        }
+
+        c2 = ( pt_pad->GetPosition().x - RoutingMatrix.m_BrdBox.GetX() + demi_pas )
+             / RoutingMatrix.m_GridRouting;
+
+        if( c2 < 0 || c2 >= RoutingMatrix.m_Ncols )
+        {
+            msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c2,
+                        pt_pad->GetPosition().x, RoutingMatrix.m_BrdBox.GetX() );
+            wxMessageBox( msg );
+            return 0;
+        }
+
+        SetWork( r1, c1, current_net_code, r2, c2, pt_ch, 0 );
+        cellCount++;
+    }
+
+    SortWork();
+    return cellCount;
+}
+
+// Initialize m_opWriteCell member to make the aLogicOp
+void MATRIX_ROUTING_HEAD::SetCellOperation( int aLogicOp )
+{
+    switch( aLogicOp )
+    {
+    default:
+    case WRITE_CELL:
+        m_opWriteCell = &MATRIX_ROUTING_HEAD::SetCell;
+        break;
+
+    case WRITE_OR_CELL:
+        m_opWriteCell = &MATRIX_ROUTING_HEAD::OrCell;
+        break;
+
+    case WRITE_XOR_CELL:
+        m_opWriteCell = &MATRIX_ROUTING_HEAD::XorCell;
+        break;
+
+    case WRITE_AND_CELL:
+        m_opWriteCell = &MATRIX_ROUTING_HEAD::AndCell;
+        break;
+
+    case WRITE_ADD_CELL:
+        m_opWriteCell = &MATRIX_ROUTING_HEAD::AddCell;
+        break;
+    }
+}
+
+
+/* return the value stored in a cell
+ */
+MATRIX_CELL MATRIX_ROUTING_HEAD::GetCell( int aRow, int aCol, int aSide )
+{
+    MATRIX_CELL* p;
+
+    p = RoutingMatrix.m_BoardSide[aSide];
+    return p[aRow * m_Ncols + aCol];
+}
+
+
+/* basic cell operation : WRITE operation
+ */
+void MATRIX_ROUTING_HEAD::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = RoutingMatrix.m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] = x;
+}
+
+
+/* basic cell operation : OR operation
+ */
+void MATRIX_ROUTING_HEAD::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = RoutingMatrix.m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] |= x;
+}
+
+
+/* basic cell operation : XOR operation
+ */
+void MATRIX_ROUTING_HEAD::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = RoutingMatrix.m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] ^= x;
+}
+
+
+/* basic cell operation : AND operation
+ */
+void MATRIX_ROUTING_HEAD::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = RoutingMatrix.m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] &= x;
+}
+
+
+/* basic cell operation : ADD operation
+ */
+void MATRIX_ROUTING_HEAD::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = RoutingMatrix.m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] += x;
+}
+
+
+// fetch distance cell
+DIST_CELL MATRIX_ROUTING_HEAD::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
+{
+    DIST_CELL* p;
+
+    p = RoutingMatrix.m_DistSide[aSide];
+    return p[aRow * m_Ncols + aCol];
+}
+
+
+// store distance cell
+void MATRIX_ROUTING_HEAD::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
+{
+    DIST_CELL* p;
+
+    p = RoutingMatrix.m_DistSide[aSide];
+    p[aRow * m_Ncols + aCol] = x;
+}
+
+
+// fetch direction cell
+int MATRIX_ROUTING_HEAD::GetDir( int aRow, int aCol, int aSide )
+{
+    DIR_CELL* p;
+
+    p = RoutingMatrix.m_DirSide[aSide];
+    return (int) (p[aRow * m_Ncols + aCol]);
+}
+
+
+// store direction cell
+void MATRIX_ROUTING_HEAD::SetDir( int aRow, int aCol, int aSide, int x )
+{
+    DIR_CELL* p;
+
+    p = RoutingMatrix.m_DirSide[aSide];
+    p[aRow * m_Ncols + aCol] = (char) x;
+}
diff --git a/pcbnew/autorouter/auto_place_footprints.cpp b/pcbnew/autorouter/auto_place_footprints.cpp
deleted file mode 100644
index 289c9db..0000000
--- a/pcbnew/autorouter/auto_place_footprints.cpp
+++ /dev/null
@@ -1,1298 +0,0 @@
-/**
- * @file auto_place_footprints.cpp
- * @brief Functions to automatically place Footprints on a board.
- */
-
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
- * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
- * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
- *
- * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
- *
- * 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#include <fctsys.h>
-#include <class_drawpanel.h>
-#include <confirm.h>
-#include <pcbnew.h>
-#include <pcb_edit_frame.h>
-#include <gr_basic.h>
-#include <macros.h>
-#include <msgpanel.h>
-
-#include <autorout.h>
-#include <cell.h>
-
-#include <class_board.h>
-#include <class_module.h>
-#include <class_track.h>
-#include <class_drawsegment.h>
-#include <convert_to_biu.h>
-#include <base_units.h>
-#include <protos.h>
-
-
-#define GAIN            16
-#define KEEP_OUT_MARGIN 500
-
-
-/* Penalty (cost) for CntRot90 and CntRot180:
- * CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed)
- */
-static const double OrientPenality[11] =
-{
-    2.0,        // CntRot = 0 rotation prohibited
-    1.9,        // CntRot = 1
-    1.8,        // CntRot = 2
-    1.7,        // CntRot = 3
-    1.6,        // CntRot = 4
-    1.5,        // CntRot = 5
-    1.4,        // CntRot = 5
-    1.3,        // CntRot = 7
-    1.2,        // CntRot = 8
-    1.1,        // CntRot = 9
-    1.0         // CntRot = 10 rotation authorized, no penalty
-};
-
-// Cell states.
-#define OUT_OF_BOARD        -2
-#define OCCUPED_By_MODULE   -1
-#define FREE_CELL   0
-
-
-static wxPoint  CurrPosition; // Current position of the current module placement
-double          MinCout;
-
-
-/* generates the Routing matrix, used to fing the best placement
- * of a footprint.
- * Allocate a "bitmap" which is an image of the real board
- * the bitmap handles:
- * - The free areas
- * - penalties (cell not occupied, but near occupied areas)
- * - cells occupied by footprints, board cutout ...
- */
-int             genPlacementRoutingMatrix(  BOARD* aBrd, EDA_MSG_PANEL* messagePanel );
-
-/* searches for the optimal position of aModule.
- * return 1 if placement impossible or 0 if OK.
- */
-static int      getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame,
-                                           MODULE* aModule, wxDC* aDC );
-
-/*
- * Function compute_Ratsnest_PlaceModule
- * displays the module's ratsnest during displacement, and assess the "cost"
- * of the position.
- *
- * The cost is the longest ratsnest distance with penalty for connections
- * approaching 45 degrees.
- */
-static double   compute_Ratsnest_PlaceModule( BOARD* aBrd );
-
-/* Place a footprint on the Routing matrix.
- */
-void            genModuleOnRoutingMatrix( MODULE* Module );
-/*
- * Displays the Placement/Routing matrix on the screen
- */
-static void     drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC );
-
-static int      TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide );
-
-static void     CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
-                                        int marge, int aKeepOut, LSET aLayerMask );
-
-static MODULE*  PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC );
-static int      propagate();
-
-void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
-{
-    MODULE*             currModule = NULL;
-    wxPoint             PosOK;
-    wxPoint             memopos;
-    int                 error;
-    PCB_LAYER_ID            lay_tmp_TOP, lay_tmp_BOTTOM;
-
-    // Undo: init list
-    PICKED_ITEMS_LIST   newList;
-
-    newList.m_Status = UR_CHANGED;
-    ITEM_PICKER         picker( NULL, UR_CHANGED );
-
-    if( GetBoard()->m_Modules == NULL )
-        return;
-
-    m_canvas->SetAbortRequest( false );
-
-    switch( place_mode )
-    {
-    case PLACE_1_MODULE:
-        currModule = Module;
-
-        if( currModule == NULL )
-            return;
-
-        currModule->SetIsPlaced( false );
-        currModule->SetNeedsPlaced( false );
-        break;
-
-    case PLACE_OUT_OF_BOARD:
-        break;
-
-    case PLACE_ALL:
-
-        if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) )
-            return;
-
-        break;
-
-    case PLACE_INCREMENTAL:
-
-        if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) )
-            return;
-
-        break;
-    }
-
-    memopos = CurrPosition;
-    lay_tmp_BOTTOM  = g_Route_Layer_BOTTOM;
-    lay_tmp_TOP     = g_Route_Layer_TOP;
-
-    RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x;
-
-    // Ensure Board.m_GridRouting has a reasonable value:
-    if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) )
-        RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 );
-
-    // Compute module parameters used in auto place
-    if( genPlacementRoutingMatrix( GetBoard(), m_messagePanel ) == 0 )
-        return;
-
-    int moduleCount = 0;
-    Module = GetBoard()->m_Modules;
-
-    for( ; Module != NULL; Module = Module->Next() )
-    {
-        Module->SetNeedsPlaced( false );
-
-        switch( place_mode )
-        {
-        case PLACE_1_MODULE:
-
-            if( currModule == Module )
-            {
-                // Module will be placed, add to undo.
-                picker.SetItem( currModule );
-                newList.PushItem( picker );
-                Module->SetNeedsPlaced( true );
-            }
-
-            break;
-
-        case PLACE_OUT_OF_BOARD:
-            Module->SetIsPlaced( false );
-
-            if( Module->IsLocked() )
-                break;
-
-            if( !RoutingMatrix.m_BrdBox.Contains( Module->GetPosition() ) )
-            {
-                // Module will be placed, add to undo.
-                picker.SetItem( Module );
-                newList.PushItem( picker );
-                Module->SetNeedsPlaced( true );
-            }
-
-            break;
-
-        case PLACE_ALL:
-            Module->SetIsPlaced( false );
-
-            if( Module->IsLocked() )
-                break;
-
-            // Module will be placed, add to undo.
-            picker.SetItem( Module );
-            newList.PushItem( picker );
-            Module->SetNeedsPlaced( true );
-            break;
-
-        case PLACE_INCREMENTAL:
-
-            if( Module->IsLocked() )
-            {
-                Module->SetIsPlaced( false );
-                break;
-            }
-
-            if( !Module->NeedsPlaced() )
-            {
-                // Module will be placed, add to undo.
-                picker.SetItem( Module );
-                newList.PushItem( picker );
-                Module->SetNeedsPlaced( true );
-            }
-
-            break;
-        }
-
-        if( Module->NeedsPlaced() )    // Erase from screen
-        {
-            moduleCount++;
-            Module->Draw( m_canvas, DC, GR_XOR );
-        }
-        else
-        {
-            genModuleOnRoutingMatrix( Module );
-        }
-    }
-
-    // Undo command: prepare list
-    if( newList.GetCount() )
-        SaveCopyInUndoList( newList, UR_CHANGED );
-
-    int         cnt = 0;
-    wxString    msg;
-
-    while( ( Module = PickModule( this, DC ) ) != NULL )
-    {
-        // Display some info about activity, module placement can take a while:
-        msg.Printf( _( "Place footprint %d of %d" ), cnt, moduleCount );
-        SetStatusText( msg );
-
-        double initialOrient = Module->GetOrientation();
-        // Display fill area of interest, barriers, penalties.
-        drawPlacementRoutingMatrix( GetBoard(), DC );
-
-        error = getOptimalModulePlacement( this, Module, DC );
-        double bestScore = MinCout;
-        double bestRotation = 0.0;
-        int rotAllowed;
-        PosOK = CurrPosition;
-
-        if( error == ESC )
-            goto end_of_tst;
-
-        // Try orientations 90, 180, 270 degrees from initial orientation
-        rotAllowed = Module->GetPlacementCost180();
-
-        if( rotAllowed != 0 )
-        {
-            Rotate_Module( DC, Module, 1800.0, true );
-            error   = getOptimalModulePlacement( this, Module, DC );
-            MinCout *= OrientPenality[rotAllowed];
-
-            if( bestScore > MinCout )    // This orientation is better.
-            {
-                PosOK       = CurrPosition;
-                bestScore   = MinCout;
-                bestRotation = 1800.0;
-            }
-            else
-            {
-                Rotate_Module( DC, Module, initialOrient, false );
-            }
-
-            if( error == ESC )
-                goto end_of_tst;
-        }
-
-        // Determine if the best orientation of a module is 90.
-        rotAllowed = Module->GetPlacementCost90();
-
-        if( rotAllowed != 0 )
-        {
-            Rotate_Module( DC, Module, 900.0, true );
-            error   = getOptimalModulePlacement( this, Module, DC );
-            MinCout *= OrientPenality[rotAllowed];
-
-            if( bestScore > MinCout )    // This orientation is better.
-            {
-                PosOK       = CurrPosition;
-                bestScore   = MinCout;
-                bestRotation = 900.0;
-            }
-            else
-            {
-                Rotate_Module( DC, Module, initialOrient, false );
-            }
-
-            if( error == ESC )
-                goto end_of_tst;
-        }
-
-        // Determine if the best orientation of a module is -90.
-        if( rotAllowed != 0 )
-        {
-            Rotate_Module( DC, Module, 2700.0, true );
-            error   = getOptimalModulePlacement( this, Module, DC );
-            MinCout *= OrientPenality[rotAllowed];
-
-            if( bestScore > MinCout )    // This orientation is better.
-            {
-                PosOK       = CurrPosition;
-                bestScore   = MinCout;
-                bestRotation = 2700.0;
-            }
-            else
-            {
-                Rotate_Module( DC, Module, initialOrient, false );
-            }
-
-            if( error == ESC )
-                goto end_of_tst;
-        }
-
-end_of_tst:
-
-        if( error == ESC )
-            break;
-
-        // Place module.
-        CurrPosition = GetCrossHairPosition();
-        SetCrossHairPosition( PosOK );
-
-        PlaceModule( Module, DC );
-
-        bestRotation += initialOrient;
-
-        if( bestRotation != Module->GetOrientation() )
-            Rotate_Module( DC, Module, bestRotation, false );
-
-        SetCrossHairPosition( CurrPosition );
-
-        Module->CalculateBoundingBox();
-
-        genModuleOnRoutingMatrix( Module );
-        Module->SetIsPlaced( true );
-        Module->SetNeedsPlaced( false );
-    }
-
-    CurrPosition = memopos;
-
-    RoutingMatrix.UnInitRoutingMatrix();
-
-    g_Route_Layer_TOP       = lay_tmp_TOP;
-    g_Route_Layer_BOTTOM    = lay_tmp_BOTTOM;
-
-    Module = GetBoard()->m_Modules;
-
-    for( ; Module != NULL; Module = Module->Next() )
-    {
-        Module->CalculateBoundingBox();
-    }
-
-    GetBoard()->m_Status_Pcb = 0;
-    Compile_Ratsnest( DC, true );
-    m_canvas->ReDraw( DC, true );
-}
-
-
-void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC )
-{
-    int         ii, jj;
-    COLOR4D     color;
-    int         ox, oy;
-    MATRIX_CELL top_state, bottom_state;
-
-    GRSetDrawMode( DC, GR_COPY );
-
-    for( ii = 0; ii < RoutingMatrix.m_Nrows; ii++ )
-    {
-        oy = RoutingMatrix.m_BrdBox.GetY() + ( ii * RoutingMatrix.m_GridRouting );
-
-        for( jj = 0; jj < RoutingMatrix.m_Ncols; jj++ )
-        {
-            ox      = RoutingMatrix.m_BrdBox.GetX() + (jj * RoutingMatrix.m_GridRouting);
-            color   = COLOR4D::BLACK;
-
-            top_state       = RoutingMatrix.GetCell( ii, jj, TOP );
-            bottom_state    = RoutingMatrix.GetCell( ii, jj, BOTTOM );
-
-            if( top_state & CELL_is_ZONE )
-                color = COLOR4D( BLUE );
-
-            // obstacles
-            if( ( top_state & CELL_is_EDGE ) || ( bottom_state & CELL_is_EDGE ) )
-                color = COLOR4D::WHITE;
-            else if( top_state & ( HOLE | CELL_is_MODULE ) )
-                color = COLOR4D( LIGHTRED );
-            else if( bottom_state & (HOLE | CELL_is_MODULE) )
-                color = COLOR4D( LIGHTGREEN );
-            else    // Display the filling and keep out regions.
-            {
-                if( RoutingMatrix.GetDist( ii, jj, TOP )
-                    || RoutingMatrix.GetDist( ii, jj, BOTTOM ) )
-                    color = DARKGRAY;
-            }
-
-            GRPutPixel( NULL, DC, ox, oy, color );
-        }
-    }
-}
-
-
-int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel )
-{
-    wxString msg;
-
-    RoutingMatrix.UnInitRoutingMatrix();
-
-    EDA_RECT bbox = aBrd->GetBoardEdgesBoundingBox();
-
-    if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
-    {
-        DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) );
-        return 0;
-    }
-
-    RoutingMatrix.ComputeMatrixSize( aBrd, true );
-    int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows;
-
-    messagePanel->EraseMsgBox();
-    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols );
-    messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN );
-    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows );
-    messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN );
-    msg.Printf( wxT( "%d" ), nbCells );
-    messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW );
-
-    // Choose the number of board sides.
-    RoutingMatrix.m_RoutingLayersCount = 2;
-
-    RoutingMatrix.InitRoutingMatrix();
-
-    // Display memory usage.
-    msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 );
-    messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN );
-
-    g_Route_Layer_BOTTOM = F_Cu;
-
-    if( RoutingMatrix.m_RoutingLayersCount > 1 )
-        g_Route_Layer_BOTTOM = B_Cu;
-
-    g_Route_Layer_TOP = F_Cu;
-
-    // Place the edge layer segments
-    TRACK TmpSegm( NULL );
-
-    TmpSegm.SetLayer( UNDEFINED_LAYER );
-    TmpSegm.SetNetCode( -1 );
-    TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 );
-
-    for( auto PtStruct : aBrd->Drawings() )
-    {
-        DRAWSEGMENT* DrawSegm;
-
-        switch( PtStruct->Type() )
-        {
-        case PCB_LINE_T:
-            DrawSegm = (DRAWSEGMENT*) PtStruct;
-
-            if( DrawSegm->GetLayer() != Edge_Cuts )
-                break;
-
-            TraceSegmentPcb( DrawSegm, HOLE | CELL_is_EDGE,
-                             RoutingMatrix.m_GridRouting, WRITE_CELL );
-            break;
-
-        case PCB_TEXT_T:
-        default:
-            break;
-        }
-    }
-
-    // Mark cells of the routing matrix to CELL_is_ZONE
-    // (i.e. availlable cell to place a module )
-    // Init a starting point of attachment to the area.
-    RoutingMatrix.OrCell( RoutingMatrix.m_Nrows / 2, RoutingMatrix.m_Ncols / 2,
-                          BOTTOM, CELL_is_ZONE );
-
-    // find and mark all other availlable cells:
-    for( int ii = 1; ii != 0; )
-        ii = propagate();
-
-    // Initialize top layer. to the same value as the bottom layer
-    if( RoutingMatrix.m_BoardSide[TOP] )
-        memcpy( RoutingMatrix.m_BoardSide[TOP], RoutingMatrix.m_BoardSide[BOTTOM],
-                nbCells * sizeof(MATRIX_CELL) );
-
-    return 1;
-}
-
-
-/* Place module on Routing matrix.
- */
-void genModuleOnRoutingMatrix( MODULE* Module )
-{
-    int         ox, oy, fx, fy;
-    LSET        layerMask;
-    D_PAD*      Pad;
-
-    EDA_RECT    fpBBox = Module->GetBoundingBox();
-
-    fpBBox.Inflate( RoutingMatrix.m_GridRouting / 2 );
-    ox  = fpBBox.GetX();
-    fx  = fpBBox.GetRight();
-    oy  = fpBBox.GetY();
-    fy  = fpBBox.GetBottom();
-
-    if( ox < RoutingMatrix.m_BrdBox.GetX() )
-        ox = RoutingMatrix.m_BrdBox.GetX();
-
-    if( ox > RoutingMatrix.m_BrdBox.GetRight() )
-        ox = RoutingMatrix.m_BrdBox.GetRight();
-
-    if( fx < RoutingMatrix.m_BrdBox.GetX() )
-        fx = RoutingMatrix.m_BrdBox.GetX();
-
-    if( fx > RoutingMatrix.m_BrdBox.GetRight() )
-        fx = RoutingMatrix.m_BrdBox.GetRight();
-
-    if( oy < RoutingMatrix.m_BrdBox.GetY() )
-        oy = RoutingMatrix.m_BrdBox.GetY();
-
-    if( oy > RoutingMatrix.m_BrdBox.GetBottom() )
-        oy = RoutingMatrix.m_BrdBox.GetBottom();
-
-    if( fy < RoutingMatrix.m_BrdBox.GetY() )
-        fy = RoutingMatrix.m_BrdBox.GetY();
-
-    if( fy > RoutingMatrix.m_BrdBox.GetBottom() )
-        fy = RoutingMatrix.m_BrdBox.GetBottom();
-
-    if( Module->GetLayer() == F_Cu )
-        layerMask.set( F_Cu );
-
-    if( Module->GetLayer() == B_Cu )
-        layerMask.set( B_Cu );
-
-    TraceFilledRectangle( ox, oy, fx, fy, layerMask,
-                          CELL_is_MODULE, WRITE_OR_CELL );
-
-    // Trace pads + clearance areas.
-    for( Pad = Module->Pads(); Pad != NULL; Pad = Pad->Next() )
-    {
-        int margin = (RoutingMatrix.m_GridRouting / 2) + Pad->GetClearance();
-        ::PlacePad( Pad, CELL_is_MODULE, margin, WRITE_OR_CELL );
-    }
-
-    // Trace clearance.
-    int margin = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN;
-    CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask );
-}
-
-
-// A minor helper function to draw a bounding box:
-inline void draw_FootprintRect( EDA_RECT* aClipBox, wxDC* aDC, EDA_RECT& fpBBox, COLOR4D aColor )
-{
-#ifndef USE_WX_OVERLAY
-    GRRect( aClipBox, aDC, fpBBox, 0, aColor );
-#endif
-}
-
-
-int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC )
-{
-    int     error = 1;
-    wxPoint LastPosOK;
-    double  min_cost, curr_cost, Score;
-    bool    TstOtherSide;
-    auto displ_opts = (PCB_DISPLAY_OPTIONS*)aFrame->GetDisplayOptions();
-    BOARD*  brd = aFrame->GetBoard();
-
-    aModule->CalculateBoundingBox();
-
-    bool showRats = displ_opts->m_Show_Module_Ratsnest;
-    displ_opts->m_Show_Module_Ratsnest = false;
-
-    brd->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
-    aFrame->SetMsgPanel( aModule );
-
-    LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin();
-
-    wxPoint     mod_pos = aModule->GetPosition();
-    EDA_RECT    fpBBox  = aModule->GetFootprintRect();
-
-    // Move fpBBox to have the footprint position at (0,0)
-    fpBBox.Move( -mod_pos );
-    wxPoint fpBBoxOrg = fpBBox.GetOrigin();
-
-    // Calculate the limit of the footprint position, relative
-    // to the routing matrix area
-    wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
-
-    wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
-
-    // Stay on grid.
-    initialPos.x    -= initialPos.x % RoutingMatrix.m_GridRouting;
-    initialPos.y    -= initialPos.y % RoutingMatrix.m_GridRouting;
-
-    CurrPosition = initialPos;
-
-    // Undraw the current footprint
-    aModule->DrawOutlinesWhenMoving( aFrame->GetCanvas(), aDC, wxPoint( 0, 0 ) );
-
-    g_Offset_Module = mod_pos - CurrPosition;
-
-    /* Examine pads, and set TstOtherSide to true if a footprint
-     * has at least 1 pad through.
-     */
-    TstOtherSide = false;
-
-    if( RoutingMatrix.m_RoutingLayersCount > 1 )
-    {
-        LSET    other( aModule->GetLayer() == B_Cu  ? F_Cu : B_Cu );
-
-        for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
-        {
-            if( !( pad->GetLayerSet() & other ).any() )
-                continue;
-
-            TstOtherSide = true;
-            break;
-        }
-    }
-
-    // Draw the initial bounding box position
-    COLOR4D color = COLOR4D( BROWN );
-    fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
-    draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color);
-
-    min_cost = -1.0;
-    aFrame->SetStatusText( wxT( "Score ??, pos ??" ) );
-
-    for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting )
-    {
-        wxYield();
-
-        if( aFrame->GetCanvas()->GetAbortRequest() )
-        {
-            if( IsOK( aFrame, _( "OK to abort?" ) ) )
-            {
-                displ_opts->m_Show_Module_Ratsnest = showRats;
-                return ESC;
-            }
-            else
-                aFrame->GetCanvas()->SetAbortRequest( false );
-        }
-
-        CurrPosition.y = initialPos.y;
-
-        for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting )
-        {
-            // Erase traces.
-            draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
-
-            fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
-            g_Offset_Module = mod_pos - CurrPosition;
-            int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide );
-
-            // Draw at new place
-            color = keepOutCost >= 0 ? BROWN : RED;
-            draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
-
-            if( keepOutCost >= 0 )    // i.e. if the module can be put here
-            {
-                error = 0;
-                aFrame->build_ratsnest_module( aModule );
-                curr_cost   = compute_Ratsnest_PlaceModule( brd );
-                Score       = curr_cost + keepOutCost;
-
-                if( (min_cost >= Score ) || (min_cost < 0 ) )
-                {
-                    LastPosOK   = CurrPosition;
-                    min_cost    = Score;
-                    wxString msg;
-                    msg.Printf( wxT( "Score %g, pos %s, %s" ),
-                                min_cost,
-                                GetChars( ::CoordinateToString( LastPosOK.x ) ),
-                                GetChars( ::CoordinateToString( LastPosOK.y ) ) );
-                    aFrame->SetStatusText( msg );
-                }
-            }
-        }
-    }
-
-    // erasing the last traces
-    GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
-
-    displ_opts->m_Show_Module_Ratsnest = showRats;
-
-    // Regeneration of the modified variable.
-    CurrPosition = LastPosOK;
-
-    brd->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK );
-
-    MinCout = min_cost;
-    return error;
-}
-
-
-/* Test if the rectangular area (ux, ux .. y0, y1):
- * - is a free zone (except OCCUPED_By_MODULE returns)
- * - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
- *
- * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
- */
-int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
-{
-    EDA_RECT rect = aRect;
-
-    rect.Inflate( RoutingMatrix.m_GridRouting / 2 );
-
-    wxPoint start   = rect.GetOrigin();
-    wxPoint end     = rect.GetEnd();
-
-    start   -= RoutingMatrix.m_BrdBox.GetOrigin();
-    end     -= RoutingMatrix.m_BrdBox.GetOrigin();
-
-    int row_min = start.y / RoutingMatrix.m_GridRouting;
-    int row_max = end.y / RoutingMatrix.m_GridRouting;
-    int col_min = start.x / RoutingMatrix.m_GridRouting;
-    int col_max = end.x / RoutingMatrix.m_GridRouting;
-
-    if( start.y > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    if( start.x > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    for( int row = row_min; row <= row_max; row++ )
-    {
-        for( int col = col_min; col <= col_max; col++ )
-        {
-            unsigned int data = RoutingMatrix.GetCell( row, col, side );
-
-            if( ( data & CELL_is_ZONE ) == 0 )
-                return OUT_OF_BOARD;
-
-            if( (data & CELL_is_MODULE) )
-                return OCCUPED_By_MODULE;
-        }
-    }
-
-    return FREE_CELL;
-}
-
-
-/* Calculates and returns the clearance area of the rectangular surface
- * aRect):
- * (Sum of cells in terms of distance)
- */
-unsigned int CalculateKeepOutArea( const EDA_RECT& aRect, int side )
-{
-    wxPoint start   = aRect.GetOrigin();
-    wxPoint end     = aRect.GetEnd();
-
-    start   -= RoutingMatrix.m_BrdBox.GetOrigin();
-    end     -= RoutingMatrix.m_BrdBox.GetOrigin();
-
-    int row_min = start.y / RoutingMatrix.m_GridRouting;
-    int row_max = end.y / RoutingMatrix.m_GridRouting;
-    int col_min = start.x / RoutingMatrix.m_GridRouting;
-    int col_max = end.x / RoutingMatrix.m_GridRouting;
-
-    if( start.y > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    if( start.x > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    unsigned int keepOutCost = 0;
-
-    for( int row = row_min; row <= row_max; row++ )
-    {
-        for( int col = col_min; col <= col_max; col++ )
-        {
-            // RoutingMatrix.GetDist returns the "cost" of the cell
-            // at position (row, col)
-            // in autoplace this is the cost of the cell, if it is
-            // inside aRect
-            keepOutCost += RoutingMatrix.GetDist( row, col, side );
-        }
-    }
-
-    return keepOutCost;
-}
-
-
-/* Test if the module can be placed on the board.
- * Returns the value TstRectangle().
- * Module is known by its bounding box
- */
-int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide )
-{
-    int side = TOP;
-    int otherside = BOTTOM;
-
-    if( aModule->GetLayer() == B_Cu )
-    {
-        side = BOTTOM; otherside = TOP;
-    }
-
-    EDA_RECT    fpBBox = aModule->GetFootprintRect();
-    fpBBox.Move( -g_Offset_Module );
-
-    int         diag = TstRectangle( Pcb, fpBBox, side );
-
-    if( diag != FREE_CELL )
-        return diag;
-
-    if( TstOtherSide )
-    {
-        diag = TstRectangle( Pcb, fpBBox, otherside );
-
-        if( diag != FREE_CELL )
-            return diag;
-    }
-
-    int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN;
-
-    fpBBox.Inflate( marge );
-    return CalculateKeepOutArea( fpBBox, side );
-}
-
-
-double compute_Ratsnest_PlaceModule( BOARD* aBrd )
-{
-    double  curr_cost;
-    wxPoint start;      // start point of a ratsnest
-    wxPoint end;        // end point of a ratsnest
-    int     dx, dy;
-
-    if( ( aBrd->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 )
-        return -1;
-
-    curr_cost = 0;
-
-    for( unsigned ii = 0; ii < aBrd->m_LocalRatsnest.size(); ii++ )
-    {
-        RATSNEST_ITEM* pt_local_rats_nest = &aBrd->m_LocalRatsnest[ii];
-
-        if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) )
-            continue; // Skip ratsnest between 2 pads of the current module
-
-        // Skip modules not inside the board area
-        MODULE* module = pt_local_rats_nest->m_PadEnd->GetParent();
-
-        if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) )
-            continue;
-
-        start   = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module;
-        end     = pt_local_rats_nest->m_PadEnd->GetPosition();
-
-        // Cost of the ratsnest.
-        dx  = end.x - start.x;
-        dy  = end.y - start.y;
-
-        dx  = abs( dx );
-        dy  = abs( dy );
-
-        // ttry to have always dx >= dy to calculate the cost of the rastsnet
-        if( dx < dy )
-            std::swap( dx, dy );
-
-        // Cost of the connection = length + penalty due to the slope
-        // dx is the biggest length relative to the X or Y axis
-        // the penalty is max for 45 degrees ratsnests,
-        // and 0 for horizontal or vertical ratsnests.
-        // For Horizontal and Vertical ratsnests, dy = 0;
-        double conn_cost = hypot( dx, dy * 2.0 );
-        curr_cost += conn_cost;    // Total cost = sum of costs of each connection
-    }
-
-    return curr_cost;
-}
-
-
-/**
- * Function CreateKeepOutRectangle
- * builds the cost map:
- * Cells ( in Dist map ) inside the rect x0,y0 a x1,y1 are
- *  incremented by value aKeepOut
- *  Cell outside this rectangle, but inside the rectangle
- *  x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value
- *  (aKeepOut ... 0). The decreasing value depends on the distance to the first rectangle
- *  Therefore the cost is high in rect x0,y0 to x1,y1, and decrease outside this rectangle
- */
-void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
-                             int marge, int aKeepOut, LSET aLayerMask )
-{
-    int         row, col;
-    int         row_min, row_max, col_min, col_max, pmarge;
-    int         trace = 0;
-    DIST_CELL   data, LocalKeepOut;
-    int         lgain, cgain;
-
-    if( aLayerMask[g_Route_Layer_BOTTOM] )
-        trace = 1; // Trace on bottom layer.
-
-    if( aLayerMask[g_Route_Layer_TOP] && RoutingMatrix.m_RoutingLayersCount )
-        trace |= 2; // Trace on top layer.
-
-    if( trace == 0 )
-        return;
-
-    ux0 -= RoutingMatrix.m_BrdBox.GetX();
-    uy0 -= RoutingMatrix.m_BrdBox.GetY();
-    ux1 -= RoutingMatrix.m_BrdBox.GetX();
-    uy1 -= RoutingMatrix.m_BrdBox.GetY();
-
-    ux0 -= marge; ux1 += marge;
-    uy0 -= marge; uy1 += marge;
-
-    pmarge = marge / RoutingMatrix.m_GridRouting;
-
-    if( pmarge < 1 )
-        pmarge = 1;
-
-    // Calculate the coordinate limits of the rectangle.
-    row_max = uy1 / RoutingMatrix.m_GridRouting;
-    col_max = ux1 / RoutingMatrix.m_GridRouting;
-    row_min = uy0 / RoutingMatrix.m_GridRouting;
-
-    if( uy0 > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    col_min = ux0 / RoutingMatrix.m_GridRouting;
-
-    if( ux0 > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= (RoutingMatrix.m_Nrows - 1) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= (RoutingMatrix.m_Ncols - 1) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    for( row = row_min; row <= row_max; row++ )
-    {
-        lgain = 256;
-
-        if( row < pmarge )
-            lgain = ( 256 * row ) / pmarge;
-        else if( row > row_max - pmarge )
-            lgain = ( 256 * ( row_max - row ) ) / pmarge;
-
-        for( col = col_min; col <= col_max; col++ )
-        {
-            // RoutingMatrix Dist map containt the "cost" of the cell
-            // at position (row, col)
-            // in autoplace this is the cost of the cell, when
-            // a footprint overlaps it, near a "master" footprint
-            // this cost is hight near the "master" footprint
-            // and decrease with the distance
-            cgain = 256;
-            LocalKeepOut = aKeepOut;
-
-            if( col < pmarge )
-                cgain = ( 256 * col ) / pmarge;
-            else if( col > col_max - pmarge )
-                cgain = ( 256 * ( col_max - col ) ) / pmarge;
-
-            cgain = ( cgain * lgain ) / 256;
-
-            if( cgain != 256 )
-                LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
-
-            if( trace & 1 )
-            {
-                data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut;
-                RoutingMatrix.SetDist( row, col, BOTTOM, data );
-            }
-
-            if( trace & 2 )
-            {
-                data    = RoutingMatrix.GetDist( row, col, TOP );
-                data    = std::max( data, LocalKeepOut );
-                RoutingMatrix.SetDist( row, col, TOP, data );
-            }
-        }
-    }
-}
-
-
-// Sort routines
-static bool Tri_PlaceModules( MODULE* ref, MODULE* compare )
-{
-    double ff1, ff2;
-
-    ff1 = ref->GetArea() * ref->GetPadCount();
-    ff2 = compare->GetArea() * compare->GetPadCount();
-
-    return ff2 < ff1;
-}
-
-
-static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare )
-{
-    double ff1, ff2;
-
-    ff1 = ref->GetArea() * ref->GetFlag();
-    ff2 = compare->GetArea() * compare->GetFlag();
-    return ff2 < ff1;
-}
-
-
-/**
- * Function PickModule
- * find the "best" module place
- * The criteria are:
- * - Maximum ratsnest with modules already placed
- * - Max size, and number of pads max
- */
-static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
-{
-    MODULE* Module;
-    std::vector <MODULE*> moduleList;
-
-    // Build sorted footprints list (sort by decreasing size )
-    Module = pcbframe->GetBoard()->m_Modules;
-
-    for( ; Module != NULL; Module = Module->Next() )
-    {
-        Module->CalculateBoundingBox();
-        moduleList.push_back( Module );
-    }
-
-    sort( moduleList.begin(), moduleList.end(), Tri_PlaceModules );
-
-    for( unsigned kk = 0; kk < moduleList.size(); kk++ )
-    {
-        Module = moduleList[kk];
-        Module->SetFlag( 0 );
-
-        if( !Module->NeedsPlaced() )
-            continue;
-
-        pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
-        pcbframe->SetMsgPanel( Module );
-        pcbframe->build_ratsnest_module( Module );
-
-        // Calculate external ratsnest.
-        for( unsigned ii = 0; ii < pcbframe->GetBoard()->m_LocalRatsnest.size(); ii++ )
-        {
-            if( ( pcbframe->GetBoard()->m_LocalRatsnest[ii].m_Status &
-                  LOCAL_RATSNEST_ITEM ) == 0 )
-                Module->IncrementFlag();
-        }
-    }
-
-    pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
-
-    sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize );
-
-    // Search for "best" module.
-    MODULE* bestModule  = NULL;
-    MODULE* altModule   = NULL;
-
-    for( unsigned ii = 0; ii < moduleList.size(); ii++ )
-    {
-        Module = moduleList[ii];
-
-        if( !Module->NeedsPlaced() )
-            continue;
-
-        altModule = Module;
-
-        if( Module->GetFlag() == 0 )
-            continue;
-
-        bestModule = Module;
-        break;
-    }
-
-    if( bestModule )
-        return bestModule;
-    else
-        return altModule;
-}
-
-
-/**
- * Function propagate
- * Used only in autoplace calculations
- * Uses the routing matrix to fill the cells within the zone
- * Search and mark cells within the zone, and agree with DRC options.
- * Requirements:
- * Start from an initial point, to fill zone
- * The zone must have no "copper island"
- *  Algorithm:
- *  If the current cell has a neighbor flagged as "cell in the zone", it
- *  become a cell in the zone
- *  The first point in the zone is the starting point
- *  4 searches within the matrix are made:
- *          1 - Left to right and top to bottom
- *          2 - Right to left and top to bottom
- *          3 - bottom to top and Right to left
- *          4 - bottom to top and Left to right
- *  Given the current cell, for each search, we consider the 2 neighbor cells
- *  the previous cell on the same line and the previous cell on the same column.
- *
- *  This function can request some iterations
- *  Iterations are made until no cell is added to the zone.
- *  @return added cells count (i.e. which the attribute CELL_is_ZONE is set)
- */
-int propagate()
-{
-    int     row, col;
-    long    current_cell, old_cell_H;
-    std::vector<long> pt_cell_V;
-    int     nbpoints = 0;
-
-#define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
-
-    pt_cell_V.reserve( std::max( RoutingMatrix.m_Nrows, RoutingMatrix.m_Ncols ) );
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
-
-    // Search from left to right and top to bottom.
-    for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
-    {
-        old_cell_H = 0;
-
-        for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
-        {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
-
-            if( current_cell == 0 )    // a free cell is found
-            {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
-            }
-
-            pt_cell_V[col] = old_cell_H = current_cell;
-        }
-    }
-
-    // Search from right to left and top to bottom/
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
-
-    for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
-    {
-        old_cell_H = 0;
-
-        for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
-        {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
-
-            if( current_cell == 0 )    // a free cell is found
-            {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
-            }
-
-            pt_cell_V[col] = old_cell_H = current_cell;
-        }
-    }
-
-    // Search from bottom to top and right to left.
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
-
-    for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
-    {
-        old_cell_H = 0;
-
-        for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
-        {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
-
-            if( current_cell == 0 )    // a free cell is found
-            {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
-            }
-
-            pt_cell_V[row] = old_cell_H = current_cell;
-        }
-    }
-
-    // Search from bottom to top and left to right.
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
-
-    for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
-    {
-        old_cell_H = 0;
-
-        for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
-        {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
-
-            if( current_cell == 0 )    // a free cell is found
-            {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
-            }
-
-            pt_cell_V[row] = old_cell_H = current_cell;
-        }
-    }
-
-    return nbpoints;
-}
diff --git a/pcbnew/autorouter/cell.h b/pcbnew/autorouter/cell.h
deleted file mode 100644
index 63b76ae..0000000
--- a/pcbnew/autorouter/cell.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * @file cell.h
- */
-
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
- * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
- * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
- *
- * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
- *
- * First copyright (C) Randy Nevin, 1989 (see PCBCA package)
- *
- * 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-
-#ifndef _CELL_H_
-#define _CELL_H_
-
-
-/* Bits characterizing cell */
-#define HOLE           0x01  /* a conducting hole or obstacle */
-#define CELL_is_MODULE 0x02  /* auto placement occupied by a module */
-#define CELL_is_EDGE   0x20  /* Area and auto-placement: limiting cell contour (Board, Zone) */
-#define CELL_is_FRIEND 0x40  /* Area and auto-placement: cell part of the net */
-#define CELL_is_ZONE   0x80  /* Area and auto-placement: cell available */
-
-/* Bit masks for presence of obstacles to autorouting */
-#define OCCUPE            1  /* Autorouting: obstacle tracks and vias. */
-#define VIA_IMPOSSIBLE    2  /* Autorouting: obstacle for vias. */
-#define CURRENT_PAD       4
-
-
-/* traces radiating outward from a hole to a side or corner */
-#define HOLE_NORTH        0x00000002L /* upward       */
-#define HOLE_NORTHEAST    0x00000004L /* upward and right */
-#define HOLE_EAST         0x00000008L /* to the right     */
-#define HOLE_SOUTHEAST    0x00000010L /* downward and right   */
-#define HOLE_SOUTH        0x00000020L /* downward     */
-#define HOLE_SOUTHWEST    0x00000040L /* downward and left    */
-#define HOLE_WEST         0x00000080L /* to the left      */
-#define HOLE_NORTHWEST    0x00000100L /* upward and left  */
-
-/* straight lines through the center */
-#define LINE_HORIZONTAL   0x00000002L /* left-to-right line   */
-#define LINE_VERTICAL     0x00000004L /* top-to-bottom line   */
-
-/* lines cutting across a corner, connecting adjacent sides */
-#define CORNER_NORTHEAST  0x00000008L /* upper right corner   */
-#define CORNER_SOUTHEAST  0x00000010L /* lower right corner   */
-#define CORNER_SOUTHWEST  0x00000020L /* lower left corner    */
-#define CORNER_NORTHWEST  0x00000040L /* upper left corner    */
-
-/* diagonal lines through the center */
-#define DIAG_NEtoSW       0x00000080L /* northeast to southwest */
-#define DIAG_SEtoNW       0x00000100L /* southeast to northwest */
-
-/* 135 degree angle side-to-far-corner lines */
-#define BENT_NtoSE        0x00000200L /* north to southeast   */
-#define BENT_NtoSW        0x00000400L /* north to southwest   */
-#define BENT_EtoSW        0x00000800L /* east to southwest    */
-#define BENT_EtoNW        0x00001000L /* east to northwest    */
-#define BENT_StoNW        0x00002000L /* south to northwest   */
-#define BENT_StoNE        0x00004000L /* south to northeast   */
-#define BENT_WtoNE        0x00008000L /* west to northeast    */
-#define BENT_WtoSE        0x00010000L /* west to southeast    */
-
-/* 90 degree corner-to-adjacent-corner lines */
-#define ANGLE_NEtoSE      0x00020000L /* northeast to southeast */
-#define ANGLE_SEtoSW      0x00040000L /* southeast to southwest */
-#define ANGLE_SWtoNW      0x00080000L /* southwest to northwest */
-#define ANGLE_NWtoNE      0x00100000L /* northwest to northeast */
-
-/* 45 degree angle side-to-near-corner lines */
-#define SHARP_NtoNE       0x00200000L /* north to northeast   */
-#define SHARP_EtoNE       0x00400000L /* east to northeast    */
-#define SHARP_EtoSE       0x00800000L /* east to southeast    */
-#define SHARP_StoSE       0x01000000L /* south to southeast   */
-#define SHARP_StoSW       0x02000000L /* south to southwest   */
-#define SHARP_WtoSW       0x04000000L /* west to southwest    */
-#define SHARP_WtoNW       0x08000000L /* west to northwest    */
-#define SHARP_NtoNW       0x10000000L /* north to northwest   */
-
-/* directions the cell can be reached from (point to previous cell) */
-#define FROM_NOWHERE      0
-#define FROM_NORTH        1
-#define FROM_NORTHEAST    2
-#define FROM_EAST         3
-#define FROM_SOUTHEAST    4
-#define FROM_SOUTH        5
-#define FROM_SOUTHWEST    6
-#define FROM_WEST         7
-#define FROM_NORTHWEST    8
-#define FROM_OTHERSIDE    9
-
-
-#endif    // _CELL_H_
-
diff --git a/pcbnew/autorouter/routing_matrix.cpp b/pcbnew/autorouter/routing_matrix.cpp
deleted file mode 100644
index 856dead..0000000
--- a/pcbnew/autorouter/routing_matrix.cpp
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
- * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
- * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
- *
- * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors.
- *
- * 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-/**
- * @file routing_matrix.cpp
- * @brief Functions to create autorouting maps
- */
-
-#include <fctsys.h>
-#include <common.h>
-
-#include <pcbnew.h>
-#include <cell.h>
-#include <autorout.h>
-
-#include <class_eda_rect.h>
-#include <class_board.h>
-#include <class_module.h>
-#include <class_track.h>
-#include <class_drawsegment.h>
-#include <class_edge_mod.h>
-#include <class_pcb_text.h>
-
-
-MATRIX_ROUTING_HEAD::MATRIX_ROUTING_HEAD()
-{
-    m_BoardSide[0] = m_BoardSide[1] = NULL;
-    m_DistSide[0] = m_DistSide[1] = NULL;
-    m_DirSide[0] = m_DirSide[1] = NULL;
-    m_opWriteCell        = NULL;
-    m_InitMatrixDone     = false;
-    m_Nrows              = 0;
-    m_Ncols              = 0;
-    m_MemSize            = 0;
-    m_RoutingLayersCount = 1;
-    m_GridRouting        = 0;
-    m_RouteCount         = 0;
-}
-
-
-MATRIX_ROUTING_HEAD::~MATRIX_ROUTING_HEAD()
-{
-}
-
-
-bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly )
-{
-    // The boundary box must have its start point on routing grid:
-    m_BrdBox = aUseBoardEdgesOnly ? aPcb->GetBoardEdgesBoundingBox() : aPcb->GetBoundingBox();
-
-    m_BrdBox.SetX( m_BrdBox.GetX() - ( m_BrdBox.GetX() % m_GridRouting ) );
-    m_BrdBox.SetY( m_BrdBox.GetY() - ( m_BrdBox.GetY() % m_GridRouting ) );
-
-    // The boundary box must have its end point on routing grid:
-    wxPoint end = m_BrdBox.GetEnd();
-
-    end.x -= end.x % m_GridRouting;
-    end.x += m_GridRouting;
-
-    end.y -= end.y % m_GridRouting;
-    end.y += m_GridRouting;
-
-    m_BrdBox.SetEnd( end );
-
-    m_Nrows = m_BrdBox.GetHeight() / m_GridRouting;
-    m_Ncols = m_BrdBox.GetWidth() / m_GridRouting;
-
-    // gives a small margin
-    m_Ncols += 1;
-    m_Nrows += 1;
-
-    return true;
-}
-
-
-int MATRIX_ROUTING_HEAD::InitRoutingMatrix()
-{
-    if( m_Nrows <= 0 || m_Ncols <= 0 )
-        return 0;
-
-    m_InitMatrixDone = true;     // we have been called
-
-    // give a small margin for memory allocation:
-    int ii = (RoutingMatrix.m_Nrows + 1) * (RoutingMatrix.m_Ncols + 1);
-
-    int side = BOTTOM;
-    for( int jj = 0; jj < m_RoutingLayersCount; jj++ )  // m_RoutingLayersCount = 1 or 2
-    {
-        m_BoardSide[side] = NULL;
-        m_DistSide[side]  = NULL;
-        m_DirSide[side]   = NULL;
-
-        // allocate matrix & initialize everything to empty
-        m_BoardSide[side] = (MATRIX_CELL*) operator new( ii * sizeof(MATRIX_CELL) );
-        memset( m_BoardSide[side], 0, ii * sizeof(MATRIX_CELL) );
-
-        if( m_BoardSide[side] == NULL )
-            return -1;
-
-        // allocate Distances
-        m_DistSide[side] = (DIST_CELL*) operator new( ii * sizeof(DIST_CELL) );
-        memset( m_DistSide[side], 0, ii * sizeof(DIST_CELL) );
-
-        if( m_DistSide[side] == NULL )
-            return -1;
-
-        // allocate Dir (chars)
-        m_DirSide[side] = (char*) operator new( ii );
-        memset( m_DirSide[side], 0, ii );
-
-        if( m_DirSide[side] == NULL )
-            return -1;
-
-        side = TOP;
-    }
-
-    m_MemSize = m_RouteCount * ii * ( sizeof(MATRIX_CELL)
-                + sizeof(DIST_CELL) + sizeof(char) );
-
-    return m_MemSize;
-}
-
-
-void MATRIX_ROUTING_HEAD::UnInitRoutingMatrix()
-{
-    int ii;
-
-    m_InitMatrixDone = false;
-
-    for( ii = 0; ii < MAX_ROUTING_LAYERS_COUNT; ii++ )
-    {
-        // de-allocate Dir matrix
-        if( m_DirSide[ii] )
-        {
-            delete m_DirSide[ii];
-            m_DirSide[ii] = NULL;
-        }
-
-        // de-allocate Distances matrix
-        if( m_DistSide[ii] )
-        {
-            delete m_DistSide[ii];
-            m_DistSide[ii] = NULL;
-        }
-
-        // de-allocate cells matrix
-        if( m_BoardSide[ii] )
-        {
-            delete m_BoardSide[ii];
-            m_BoardSide[ii] = NULL;
-        }
-    }
-
-    m_Nrows = m_Ncols = 0;
-}
-
-
-/**
- * Function PlaceCells
- * Initialize the matrix routing by setting obstacles for each occupied cell
- * a cell set to HOLE is an obstacle for tracks and vias
- * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only.
- * a cell set to CELL_is_EDGE is a frontier.
- * Tracks and vias having the same net code as net_code are skipped
- * (htey do not are obstacles)
- *
- * For single-sided Routing 1:
- * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP
- *
- * If flag == FORCE_PADS: all pads will be put in matrix as obstacles.
- */
-void PlaceCells( BOARD* aPcb, int net_code, int flag )
-{
-    int     ux0 = 0, uy0 = 0, ux1, uy1, dx, dy;
-    int     marge, via_marge;
-    LSET    layerMask;
-
-    // use the default NETCLASS?
-    NETCLASSPTR nc = aPcb->GetDesignSettings().GetDefault();
-
-    int     trackWidth = nc->GetTrackWidth();
-    int     clearance  = nc->GetClearance();
-    int     viaSize    = nc->GetViaDiameter();
-
-    marge     = clearance + (trackWidth / 2);
-    via_marge = clearance + (viaSize / 2);
-
-    // Place PADS on matrix routing:
-    for( unsigned i = 0; i < aPcb->GetPadCount(); ++i )
-    {
-        D_PAD* pad = aPcb->GetPad( i );
-
-        if( net_code != pad->GetNetCode() || (flag & FORCE_PADS) )
-        {
-            ::PlacePad( pad, HOLE, marge, WRITE_CELL );
-        }
-
-        ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
-    }
-
-    // Place outlines of modules on matrix routing, if they are on a copper layer
-    // or on the edge layer
-
-    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
-    {
-        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
-        {
-            switch( item->Type() )
-            {
-            case PCB_MODULE_EDGE_T:
-            {
-                EDGE_MODULE* edge = (EDGE_MODULE*) item;
-                EDGE_MODULE tmpEdge( *edge );
-
-                if( tmpEdge.GetLayer() == Edge_Cuts )
-                    tmpEdge.SetLayer( UNDEFINED_LAYER );
-
-                TraceSegmentPcb( &tmpEdge, HOLE, marge, WRITE_CELL );
-                TraceSegmentPcb( &tmpEdge, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
-            }
-            break;
-
-            default:
-                break;
-            }
-        }
-    }
-
-    // Place board outlines and texts on copper layers:
-    for( auto item : aPcb->Drawings() )
-    {
-        switch( item->Type() )
-        {
-        case PCB_LINE_T:
-            {
-                DRAWSEGMENT* DrawSegm;
-
-                int          type_cell = HOLE;
-                DrawSegm = (DRAWSEGMENT*) item;
-                DRAWSEGMENT tmpSegm( DrawSegm );
-
-                if( DrawSegm->GetLayer() == Edge_Cuts )
-                {
-                    tmpSegm.SetLayer( UNDEFINED_LAYER );
-                    type_cell |= CELL_is_EDGE;
-                }
-
-                TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL );
-            }
-            break;
-
-        case PCB_TEXT_T:
-            {
-                TEXTE_PCB* PtText = (TEXTE_PCB*) item;
-
-                if( PtText->GetText().Length() == 0 )
-                    break;
-
-                EDA_RECT textbox = PtText->GetTextBox( -1 );
-                ux0 = textbox.GetX();
-                uy0 = textbox.GetY();
-                dx  = textbox.GetWidth();
-                dy  = textbox.GetHeight();
-
-                // Put bounding box (rectangle) on matrix
-                dx /= 2;
-                dy /= 2;
-
-                ux1 = ux0 + dx;
-                uy1 = uy0 + dy;
-
-                ux0 -= dx;
-                uy0 -= dy;
-
-                layerMask = LSET( PtText->GetLayer() );
-
-                TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge,
-                                      uy1 + marge, PtText->GetTextAngle(),
-                                      layerMask, HOLE, WRITE_CELL );
-
-                TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge,
-                                      ux1 + via_marge, uy1 + via_marge,
-                                      PtText->GetTextAngle(),
-                                      layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL );
-            }
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    // Put tracks and vias on matrix
-    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
-    {
-        if( net_code == track->GetNetCode() )
-            continue;
-
-        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
-        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
-    }
-}
-
-
-int Build_Work( BOARD* Pcb )
-{
-    RATSNEST_ITEM*  pt_rats;
-    D_PAD*          pt_pad;
-    int             r1, r2, c1, c2, current_net_code;
-    RATSNEST_ITEM*  pt_ch;
-    int             demi_pas = RoutingMatrix.m_GridRouting / 2;
-    wxString        msg;
-
-    InitWork(); // clear work list
-    int cellCount = 0;
-
-    for( unsigned ii = 0; ii < Pcb->GetRatsnestsCount(); ii++ )
-    {
-        pt_rats = &Pcb->m_FullRatsnest[ii];
-
-        /* We consider here only ratsnest that are active ( obviously not yet routed)
-         * and routables (that are not yet attempt to be routed and fail
-         */
-        if( (pt_rats->m_Status & CH_ACTIF) == 0 )
-            continue;
-
-        if( pt_rats->m_Status & CH_UNROUTABLE )
-            continue;
-
-        if( (pt_rats->m_Status & CH_ROUTE_REQ) == 0 )
-            continue;
-
-        pt_pad = pt_rats->m_PadStart;
-
-        current_net_code = pt_pad->GetNetCode();
-        pt_ch = pt_rats;
-
-        r1 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY() + demi_pas )
-            / RoutingMatrix.m_GridRouting;
-
-        if( r1 < 0 || r1 >= RoutingMatrix.m_Nrows )
-        {
-            msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r1,
-                        pt_pad->GetPosition().y, RoutingMatrix.m_BrdBox.GetY() );
-            wxMessageBox( msg );
-            return 0;
-        }
-
-        c1 = ( pt_pad->GetPosition().x - RoutingMatrix.m_BrdBox.GetX() + demi_pas ) / RoutingMatrix.m_GridRouting;
-
-        if( c1 < 0 || c1 >= RoutingMatrix.m_Ncols )
-        {
-            msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c1,
-                        pt_pad->GetPosition().x, RoutingMatrix.m_BrdBox.GetX() );
-            wxMessageBox( msg );
-            return 0;
-        }
-
-        pt_pad = pt_rats->m_PadEnd;
-
-        r2 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY()
-               + demi_pas ) / RoutingMatrix.m_GridRouting;
-
-        if( r2 < 0 || r2 >= RoutingMatrix.m_Nrows )
-        {
-            msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r2,
-                        pt_pad->GetPosition().y, RoutingMatrix.m_BrdBox.GetY() );
-            wxMessageBox( msg );
-            return 0;
-        }
-
-        c2 = ( pt_pad->GetPosition().x - RoutingMatrix.m_BrdBox.GetX() + demi_pas )
-             / RoutingMatrix.m_GridRouting;
-
-        if( c2 < 0 || c2 >= RoutingMatrix.m_Ncols )
-        {
-            msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c2,
-                        pt_pad->GetPosition().x, RoutingMatrix.m_BrdBox.GetX() );
-            wxMessageBox( msg );
-            return 0;
-        }
-
-        SetWork( r1, c1, current_net_code, r2, c2, pt_ch, 0 );
-        cellCount++;
-    }
-
-    SortWork();
-    return cellCount;
-}
-
-// Initialize m_opWriteCell member to make the aLogicOp
-void MATRIX_ROUTING_HEAD::SetCellOperation( int aLogicOp )
-{
-    switch( aLogicOp )
-    {
-    default:
-    case WRITE_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::SetCell;
-        break;
-
-    case WRITE_OR_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::OrCell;
-        break;
-
-    case WRITE_XOR_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::XorCell;
-        break;
-
-    case WRITE_AND_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::AndCell;
-        break;
-
-    case WRITE_ADD_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::AddCell;
-        break;
-    }
-}
-
-
-/* return the value stored in a cell
- */
-MATRIX_CELL MATRIX_ROUTING_HEAD::GetCell( int aRow, int aCol, int aSide )
-{
-    MATRIX_CELL* p;
-
-    p = RoutingMatrix.m_BoardSide[aSide];
-    return p[aRow * m_Ncols + aCol];
-}
-
-
-/* basic cell operation : WRITE operation
- */
-void MATRIX_ROUTING_HEAD::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
-
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] = x;
-}
-
-
-/* basic cell operation : OR operation
- */
-void MATRIX_ROUTING_HEAD::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
-
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] |= x;
-}
-
-
-/* basic cell operation : XOR operation
- */
-void MATRIX_ROUTING_HEAD::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
-
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] ^= x;
-}
-
-
-/* basic cell operation : AND operation
- */
-void MATRIX_ROUTING_HEAD::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
-
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] &= x;
-}
-
-
-/* basic cell operation : ADD operation
- */
-void MATRIX_ROUTING_HEAD::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
-
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] += x;
-}
-
-
-// fetch distance cell
-DIST_CELL MATRIX_ROUTING_HEAD::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
-{
-    DIST_CELL* p;
-
-    p = RoutingMatrix.m_DistSide[aSide];
-    return p[aRow * m_Ncols + aCol];
-}
-
-
-// store distance cell
-void MATRIX_ROUTING_HEAD::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
-{
-    DIST_CELL* p;
-
-    p = RoutingMatrix.m_DistSide[aSide];
-    p[aRow * m_Ncols + aCol] = x;
-}
-
-
-// fetch direction cell
-int MATRIX_ROUTING_HEAD::GetDir( int aRow, int aCol, int aSide )
-{
-    DIR_CELL* p;
-
-    p = RoutingMatrix.m_DirSide[aSide];
-    return (int) (p[aRow * m_Ncols + aCol]);
-}
-
-
-// store direction cell
-void MATRIX_ROUTING_HEAD::SetDir( int aRow, int aCol, int aSide, int x )
-{
-    DIR_CELL* p;
-
-    p = RoutingMatrix.m_DirSide[aSide];
-    p[aRow * m_Ncols + aCol] = (char) x;
-}
-- 
2.7.4

>From 307bf79d8fee4b693ab8ec199571c7d920fca6b1 Mon Sep 17 00:00:00 2001
From: Tomasz Wlostowski <tomasz.wlostowski@xxxxxxx>
Date: Thu, 9 Aug 2018 16:02:05 +0200
Subject: [PATCH 2/3] VIEW: added support for VIEW_OVERLAYS (temporary overlays
 for drawing debug graphics)

---
 common/CMakeLists.txt        |   1 +
 common/view/view.cpp         |  10 ++
 common/view/view_overlay.cpp | 249 +++++++++++++++++++++++++++++++++++++++++++
 include/view/view.h          |   4 +
 include/view/view_overlay.h  |  62 +++++++++++
 5 files changed, 326 insertions(+)
 create mode 100644 common/view/view_overlay.cpp
 create mode 100644 include/view/view_overlay.h

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index ca31d61..3d5d509 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -43,6 +43,7 @@ set( GAL_SRCS
     gal/stroke_font.cpp
     geometry/hetriang.cpp
     view/view_controls.cpp
+    view/view_overlay.cpp
     view/wx_view_controls.cpp
 
     # OpenGL GAL
diff --git a/common/view/view.cpp b/common/view/view.cpp
index df44d5c..4ea11dd 100644
--- a/common/view/view.cpp
+++ b/common/view/view.cpp
@@ -31,6 +31,8 @@
 #include <view/view_group.h>
 #include <view/view_item.h>
 #include <view/view_rtree.h>
+#include <view/view_overlay.h>
+
 #include <gal/definitions.h>
 #include <gal/graphics_abstraction_layer.h>
 #include <painter.h>
@@ -1546,6 +1548,14 @@ void VIEW::Update( VIEW_ITEM* aItem, int aUpdateFlags )
 
 }
 
+std::shared_ptr<VIEW_OVERLAY> VIEW::MakeOverlay()
+{
+    std::shared_ptr<VIEW_OVERLAY> overlay( new VIEW_OVERLAY );
+
+    Add ( overlay.get() );
+    return overlay;
+}
+
 const int VIEW::TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS;
 
 }
diff --git a/common/view/view_overlay.cpp b/common/view/view_overlay.cpp
new file mode 100644
index 0000000..0eb8f17
--- /dev/null
+++ b/common/view/view_overlay.cpp
@@ -0,0 +1,249 @@
+#include <view/view.h>
+#include <view/view_item.h>
+#include <view/view_overlay.h>
+#include <gal/graphics_abstraction_layer.h>
+#include <painter.h>
+
+#include <layers_id_colors_and_visibility.h>
+#include <geometry/seg.h>
+
+namespace KIGFX {
+struct VIEW_OVERLAY::COMMAND
+{
+    virtual ~COMMAND() {};
+    virtual void Execute( VIEW* aView ) const = 0;
+};
+
+struct VIEW_OVERLAY::COMMAND_LINE : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_LINE( const VECTOR2D& aP0, const VECTOR2D& aP1 ) :
+        m_p0( aP0 ),
+        m_p1( aP1 ) {};
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        aView->GetGAL()->DrawLine( m_p0, m_p1 );
+    }
+
+    VECTOR2D m_p0, m_p1;
+};
+
+struct VIEW_OVERLAY::COMMAND_CIRCLE : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_CIRCLE( const VECTOR2D& aCenter, double aRadius ) :
+        m_center(aCenter),
+        m_radius(aRadius)
+        {}
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        aView->GetGAL()->DrawCircle( m_center, m_radius
+         );
+    }
+
+    VECTOR2D m_center;
+    double m_radius;
+};
+
+struct VIEW_OVERLAY::COMMAND_ARC : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_ARC( const VECTOR2D& aCenter, double aRadius, double aStartAngle, double aEndAngle ) :
+        m_center(aCenter),
+        m_radius(aRadius),
+        m_startAngle( aStartAngle ),
+        m_endAngle( aEndAngle )
+        {}
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        aView->GetGAL()->DrawArc( m_center, m_radius, m_startAngle, m_endAngle );
+    }
+
+    VECTOR2D m_center;
+    double m_startAngle, m_endAngle;
+    double m_radius;
+};
+
+struct VIEW_OVERLAY::COMMAND_SET_STROKE : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_SET_STROKE( bool aIsStroke ) :
+        m_isStroke(  aIsStroke ) {}
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        aView->GetGAL()->SetIsStroke( m_isStroke );
+    }
+
+    bool m_isStroke;
+};
+
+struct VIEW_OVERLAY::COMMAND_SET_FILL : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_SET_FILL( bool aIsFill ) :
+        m_isFill(  aIsFill ) {}
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        aView->GetGAL()->SetIsFill( m_isFill );
+    }
+
+    bool m_isFill;
+};
+
+struct VIEW_OVERLAY::COMMAND_SET_COLOR : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_SET_COLOR( bool aIsStroke, const COLOR4D& aColor ) :
+        m_isStroke( aIsStroke ),
+        m_color( aColor )
+    {}
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        if( m_isStroke )
+            aView->GetGAL()->SetStrokeColor( m_color );
+        else
+            aView->GetGAL()->SetFillColor( m_color );
+    }
+
+    bool m_isStroke;
+    COLOR4D m_color;
+};
+
+struct VIEW_OVERLAY::COMMAND_SET_WIDTH : public VIEW_OVERLAY::COMMAND
+{
+    COMMAND_SET_WIDTH( double aWidth ) :
+        m_width( aWidth )
+    {}
+
+    virtual void Execute( VIEW* aView ) const override
+    {
+        aView->GetGAL()->SetLineWidth( m_width );
+    }
+
+    double m_width;
+};
+
+VIEW_OVERLAY::VIEW_OVERLAY()
+{
+}
+
+
+VIEW_OVERLAY::~VIEW_OVERLAY()
+{
+    releaseCommands();
+}
+
+
+void VIEW_OVERLAY::releaseCommands()
+{
+    for( auto cmd : m_commands )
+        delete cmd;
+
+    m_commands.clear();
+}
+
+
+void VIEW_OVERLAY::Clear()
+{
+    releaseCommands();
+}
+
+
+const BOX2I VIEW_OVERLAY::ViewBBox() const
+{
+    BOX2I maxBox;
+
+    maxBox.SetMaximum();
+    return maxBox;
+}
+
+
+void VIEW_OVERLAY::ViewDraw( int aLayer, VIEW* aView ) const
+{
+    for( const auto& cmd : m_commands )
+        cmd->Execute( aView );
+}
+
+
+void VIEW_OVERLAY::ViewGetLayers( int aLayers[], int& aCount ) const
+{
+    aLayers[0] = LAYER_GP_OVERLAY;
+    aCount = 1;
+}
+
+
+void VIEW_OVERLAY::Line( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
+{
+    m_commands.push_back( new COMMAND_LINE( aStartPoint, aEndPoint ) );
+}
+
+void VIEW_OVERLAY::Line( const SEG& aSeg )
+{
+    Line( aSeg.A, aSeg.B );
+}
+
+
+void VIEW_OVERLAY::Segment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth )
+{
+}
+
+
+void VIEW_OVERLAY::Polyline( std::deque<VECTOR2D>& aPointList )
+{
+}
+
+
+void VIEW_OVERLAY::Circle( const VECTOR2D& aCenterPoint, double aRadius )
+{
+    m_commands.push_back( new COMMAND_CIRCLE( aCenterPoint, aRadius ) );
+}
+
+
+void VIEW_OVERLAY::Arc( const VECTOR2D& aCenterPoint,
+        double aRadius,
+        double aStartAngle,
+        double aEndAngle )
+{
+    m_commands.push_back( new COMMAND_ARC( aCenterPoint, aRadius, aStartAngle, aEndAngle ) );
+}
+
+
+void VIEW_OVERLAY::Rectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
+{
+}
+
+
+void VIEW_OVERLAY::Polygon( const std::deque<VECTOR2D>& aPointList )
+{
+}
+
+
+void VIEW_OVERLAY::SetIsFill( bool aIsFillEnabled )
+{
+    m_commands.push_back( new COMMAND_SET_FILL( aIsFillEnabled ) );
+}
+
+
+void VIEW_OVERLAY::SetIsStroke( bool aIsStrokeEnabled )
+{
+    m_commands.push_back( new COMMAND_SET_STROKE( aIsStrokeEnabled ) );
+}
+
+
+void VIEW_OVERLAY::SetFillColor( const COLOR4D& aColor )
+{
+    m_commands.push_back( new COMMAND_SET_COLOR( false, aColor ) );
+}
+
+
+void VIEW_OVERLAY::SetStrokeColor( const COLOR4D& aColor )
+{
+    m_commands.push_back( new COMMAND_SET_COLOR( true, aColor ) );
+}
+
+void VIEW_OVERLAY::SetLineWidth( double aLineWidth )
+{
+    m_commands.push_back( new COMMAND_SET_WIDTH( aLineWidth ) );
+}
+
+}
diff --git a/include/view/view.h b/include/view/view.h
index ad8635f..7bc78a5 100644
--- a/include/view/view.h
+++ b/include/view/view.h
@@ -28,10 +28,13 @@
 #include <vector>
 #include <set>
 #include <unordered_map>
+#include <memory>
 
 #include <math/box2.h>
 #include <gal/definitions.h>
 
+#include <view/view_overlay.h> // fixme
+
 namespace KIGFX
 {
 class PAINTER;
@@ -683,6 +686,7 @@ public:
 
     static const int VIEW_MAX_LAYERS = 512;      ///< maximum number of layers that may be shown
 
+    std::shared_ptr<VIEW_OVERLAY> MakeOverlay();
 
 private:
     struct VIEW_LAYER
diff --git a/include/view/view_overlay.h b/include/view/view_overlay.h
new file mode 100644
index 0000000..9fd83c8
--- /dev/null
+++ b/include/view/view_overlay.h
@@ -0,0 +1,62 @@
+#ifndef __VIEW_OVERLAY_H
+#define __VIEW_OVERLAY_H
+
+//#include <view/view.h>
+#include <view/view_item.h>
+#include <gal/graphics_abstraction_layer.h>
+
+#include <vector>
+#include <deque>
+
+class SEG;
+
+namespace KIGFX
+{
+
+    class VIEW;
+
+class VIEW_OVERLAY : public VIEW_ITEM
+{
+public:
+    VIEW_OVERLAY();
+    virtual ~VIEW_OVERLAY();
+
+    struct COMMAND;
+    struct COMMAND_ARC;
+    struct COMMAND_LINE;
+    struct COMMAND_CIRCLE;
+    struct COMMAND_SET_STROKE;
+    struct COMMAND_SET_FILL;
+    struct COMMAND_SET_COLOR;
+    struct COMMAND_SET_WIDTH;
+
+    void Clear();
+
+    virtual const BOX2I ViewBBox() const override;
+    virtual void ViewDraw( int aLayer, VIEW *aView ) const override;
+    virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
+
+    void Line( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
+    void Line( const SEG& aSeg );
+    void Segment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth );
+    void Polyline( std::deque<VECTOR2D>& aPointList );
+    void Circle( const VECTOR2D& aCenterPoint, double aRadius );
+    void Arc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle );
+    void Rectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
+    void Polygon( const std::deque<VECTOR2D>& aPointList );
+    void SetIsFill( bool aIsFillEnabled );
+    void SetIsStroke( bool aIsStrokeEnabled );
+    void SetFillColor( const COLOR4D& aColor );
+    void SetStrokeColor( const COLOR4D& aColor );
+
+    void SetLineWidth( double aLineWidth );
+
+private:
+    void releaseCommands();
+
+    std::vector<COMMAND*> m_commands;
+};
+} // namespace KIGFX
+
+
+#endif
-- 
2.7.4

>From 39ee9f5f14a8b59cfeebfa10be6ad71b514920cd Mon Sep 17 00:00:00 2001
From: Tomasz Wlostowski <tomasz.wlostowski@xxxxxxx>
Date: Thu, 9 Aug 2018 16:04:51 +0200
Subject: [PATCH 3/3] pcbnew: bring back the autoplacer tool to GAL

---
 pcbnew/CMakeLists.txt                              |    3 +
 pcbnew/autorouter/ar_autoplacer.cpp                | 1540 +++++++++-----------
 pcbnew/autorouter/ar_autoplacer.h                  |  121 ++
 pcbnew/autorouter/ar_cell.h                        |   20 +-
 pcbnew/autorouter/ar_matrix.cpp                    | 1351 +++++++++++++----
 pcbnew/autorouter/ar_matrix.h                      |  178 +++
 pcbnew/autorouter/autoplacer_tool.cpp              |  126 ++
 pcbnew/autorouter/autoplacer_tool.h                |   52 +
 pcbnew/autorouter/graphpcb.cpp                     |  689 +--------
 .../autorouter/move_and_route_event_functions.cpp  |    2 +
 pcbnew/autorouter/solve.cpp                        |  305 ++--
 pcbnew/autorouter/work.cpp                         |   43 +-
 pcbnew/connectivity_data.cpp                       |   39 +
 pcbnew/connectivity_data.h                         |    4 +
 pcbnew/edit.cpp                                    |   43 +-
 pcbnew/menubar_pcb_editor.cpp                      |   17 +
 pcbnew/onrightclick.cpp                            |   20 +-
 pcbnew/pcb_edit_frame.cpp                          |    6 -
 pcbnew/pcbnew_id.h                                 |   27 +-
 pcbnew/tools/pcb_actions.cpp                       |    7 +
 pcbnew/tools/pcb_actions.h                         |    2 +
 pcbnew/tools/tools_common.cpp                      |    2 +
 22 files changed, 2473 insertions(+), 2124 deletions(-)
 create mode 100644 pcbnew/autorouter/ar_autoplacer.h
 create mode 100644 pcbnew/autorouter/ar_matrix.h
 create mode 100644 pcbnew/autorouter/autoplacer_tool.cpp
 create mode 100644 pcbnew/autorouter/autoplacer_tool.h

diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index d9f55dd..a77f8eb 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -205,6 +205,9 @@ set( PCBNEW_CLASS_SRCS
 
     autorouter/rect_placement/rect_placement.cpp
     autorouter/spread_footprints.cpp
+    autorouter/ar_autoplacer.cpp
+    autorouter/ar_matrix.cpp
+    autorouter/autoplacer_tool.cpp
 
     action_plugin.cpp
     append_board_to_current.cpp
diff --git a/pcbnew/autorouter/ar_autoplacer.cpp b/pcbnew/autorouter/ar_autoplacer.cpp
index 289c9db..39ed071 100644
--- a/pcbnew/autorouter/ar_autoplacer.cpp
+++ b/pcbnew/autorouter/ar_autoplacer.cpp
@@ -1,8 +1,3 @@
-/**
- * @file auto_place_footprints.cpp
- * @brief Functions to automatically place Footprints on a board.
- */
-
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
@@ -39,26 +34,31 @@
 #include <macros.h>
 #include <msgpanel.h>
 
-#include <autorout.h>
-#include <cell.h>
-
 #include <class_board.h>
 #include <class_module.h>
 #include <class_track.h>
 #include <class_drawsegment.h>
-#include <convert_to_biu.h>
-#include <base_units.h>
-#include <protos.h>
+#include <class_pad.h>
 
+#include <board_commit.h>
 
-#define GAIN            16
-#define KEEP_OUT_MARGIN 500
+#include <connectivity_data.h>
+#include <ratsnest_data.h>
 
+#include <widgets/progress_reporter.h>
+
+#include "ar_matrix.h"
+#include "ar_cell.h"
+#include "ar_autoplacer.h"
+
+#define AR_GAIN            16
+#define AR_KEEPOUT_MARGIN  500
+#define AR_ABORT_PLACEMENT -1
 
 /* Penalty (cost) for CntRot90 and CntRot180:
  * CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed)
  */
-static const double OrientPenality[11] =
+static const double OrientationPenalty[11] =
 {
     2.0,        // CntRot = 0 rotation prohibited
     1.9,        // CntRot = 1
@@ -73,563 +73,471 @@ static const double OrientPenality[11] =
     1.0         // CntRot = 10 rotation authorized, no penalty
 };
 
-// Cell states.
-#define OUT_OF_BOARD        -2
-#define OCCUPED_By_MODULE   -1
-#define FREE_CELL   0
-
-
-static wxPoint  CurrPosition; // Current position of the current module placement
-double          MinCout;
-
-
-/* generates the Routing matrix, used to fing the best placement
- * of a footprint.
- * Allocate a "bitmap" which is an image of the real board
- * the bitmap handles:
- * - The free areas
- * - penalties (cell not occupied, but near occupied areas)
- * - cells occupied by footprints, board cutout ...
- */
-int             genPlacementRoutingMatrix(  BOARD* aBrd, EDA_MSG_PANEL* messagePanel );
-
-/* searches for the optimal position of aModule.
- * return 1 if placement impossible or 0 if OK.
- */
-static int      getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame,
-                                           MODULE* aModule, wxDC* aDC );
-
-/*
- * Function compute_Ratsnest_PlaceModule
- * displays the module's ratsnest during displacement, and assess the "cost"
- * of the position.
- *
- * The cost is the longest ratsnest distance with penalty for connections
- * approaching 45 degrees.
- */
-static double   compute_Ratsnest_PlaceModule( BOARD* aBrd );
-
-/* Place a footprint on the Routing matrix.
- */
-void            genModuleOnRoutingMatrix( MODULE* Module );
-/*
- * Displays the Placement/Routing matrix on the screen
- */
-static void     drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC );
-
-static int      TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide );
-
-static void     CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
-                                        int marge, int aKeepOut, LSET aLayerMask );
-
-static MODULE*  PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC );
-static int      propagate();
+AR_AUTOPLACER::AR_AUTOPLACER( BOARD* aBoard )
+{
+    m_board = aBoard;
+    m_connectivity.reset( new CONNECTIVITY_DATA );
+
+    for( auto mod : m_board->Modules() )
+        m_connectivity->Add( mod );
+        
+    m_gridSize = Millimeter2iu( 0.5 );
+    m_progressReporter = nullptr;
+    m_refreshCallback = nullptr;
+}
 
-void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
+void AR_AUTOPLACER::placeModule( MODULE* aModule, bool aDoNotRecreateRatsnest, const wxPoint& aPos )
 {
-    MODULE*             currModule = NULL;
-    wxPoint             PosOK;
-    wxPoint             memopos;
-    int                 error;
-    PCB_LAYER_ID            lay_tmp_TOP, lay_tmp_BOTTOM;
+    if( !aModule )
+        return;
 
-    // Undo: init list
-    PICKED_ITEMS_LIST   newList;
+    aModule->SetPosition( aPos );
+    m_connectivity->Update( aModule );
+}
 
-    newList.m_Status = UR_CHANGED;
-    ITEM_PICKER         picker( NULL, UR_CHANGED );
 
-    if( GetBoard()->m_Modules == NULL )
-        return;
+int AR_AUTOPLACER::genPlacementRoutingMatrix()
+{
+    m_matrix.UnInitRoutingMatrix();
 
-    m_canvas->SetAbortRequest( false );
+    EDA_RECT bbox = m_board->GetBoardEdgesBoundingBox();
 
-    switch( place_mode )
+    if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
     {
-    case PLACE_1_MODULE:
-        currModule = Module;
+        //DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) );
+        // fixme: no wx here
+        return 0;
+    }
 
-        if( currModule == NULL )
-            return;
+    m_matrix.ComputeMatrixSize( bbox );
+    int nbCells = m_matrix.m_Ncols * m_matrix.m_Nrows;
 
-        currModule->SetIsPlaced( false );
-        currModule->SetNeedsPlaced( false );
-        break;
+    // Choose the number of board sides.
+    m_matrix.m_RoutingLayersCount = 2;
+    m_matrix.InitRoutingMatrix();
 
-    case PLACE_OUT_OF_BOARD:
-        break;
+    m_matrix.m_routeLayerBottom = F_Cu;
 
-    case PLACE_ALL:
+    if( m_matrix.m_RoutingLayersCount > 1 )
+        m_matrix.m_routeLayerBottom = B_Cu;
 
-        if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) )
-            return;
+    m_matrix.m_routeLayerTop = F_Cu;
 
-        break;
+    // Place the edge layer segments
+    TRACK tmp( NULL );
 
-    case PLACE_INCREMENTAL:
+    tmp.SetLayer( UNDEFINED_LAYER );
+    tmp.SetNetCode( -1 );
+    tmp.SetWidth( m_matrix.m_GridRouting / 2 );
 
-        if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) )
-            return;
+    for( auto drawing : m_board->Drawings() )
+    {
+        DRAWSEGMENT* DrawSegm;
 
-        break;
-    }
+        switch( drawing->Type() )
+        {
+        case PCB_LINE_T:
+            DrawSegm = (DRAWSEGMENT*) drawing;
 
-    memopos = CurrPosition;
-    lay_tmp_BOTTOM  = g_Route_Layer_BOTTOM;
-    lay_tmp_TOP     = g_Route_Layer_TOP;
+            if( DrawSegm->GetLayer() != Edge_Cuts )
+                break;
 
-    RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x;
 
-    // Ensure Board.m_GridRouting has a reasonable value:
-    if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) )
-        RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 );
+            //printf("addSeg %p grid %d\n", DrawSegm,  m_matrix.m_GridRouting );
+            m_matrix.TraceSegmentPcb( DrawSegm, CELL_IS_HOLE | CELL_IS_EDGE,
+                             m_matrix.m_GridRouting, AR_MATRIX::WRITE_CELL );
+            break;
 
-    // Compute module parameters used in auto place
-    if( genPlacementRoutingMatrix( GetBoard(), m_messagePanel ) == 0 )
-        return;
+        case PCB_TEXT_T:
+        default:
+            break;
+        }
+    }
 
-    int moduleCount = 0;
-    Module = GetBoard()->m_Modules;
+    // Mark cells of the routing matrix to CELL_IS_ZONE
+    // (i.e. availlable cell to place a module )
+    // Init a starting point of attachment to the area.
+    m_matrix.OrCell( m_matrix.m_Nrows / 2, m_matrix.m_Ncols / 2,
+                          AR_SIDE_BOTTOM, CELL_IS_ZONE );
 
-    for( ; Module != NULL; Module = Module->Next() )
-    {
-        Module->SetNeedsPlaced( false );
+    // find and mark all other availlable cells:
+    for( int ii = 1; ii != 0; )
+        ii = propagate();
 
-        switch( place_mode )
-        {
-        case PLACE_1_MODULE:
+    // Initialize top layer. to the same value as the bottom layer
+    if( m_matrix.m_BoardSide[AR_SIDE_TOP] )
+        memcpy( m_matrix.m_BoardSide[AR_SIDE_TOP], m_matrix.m_BoardSide[AR_SIDE_BOTTOM],
+                nbCells * sizeof(AR_MATRIX::MATRIX_CELL) );
 
-            if( currModule == Module )
-            {
-                // Module will be placed, add to undo.
-                picker.SetItem( currModule );
-                newList.PushItem( picker );
-                Module->SetNeedsPlaced( true );
-            }
+    return 1;
+}
 
-            break;
+void AR_AUTOPLACER::rotateModule( MODULE* module, double angle, bool incremental )
+{
+    if( module == NULL )
+        return;
 
-        case PLACE_OUT_OF_BOARD:
-            Module->SetIsPlaced( false );
+    if( incremental )
+        module->SetOrientation( module->GetOrientation() + angle );
+    else
+        module->SetOrientation( angle );
 
-            if( Module->IsLocked() )
-                break;
 
-            if( !RoutingMatrix.m_BrdBox.Contains( Module->GetPosition() ) )
-            {
-                // Module will be placed, add to undo.
-                picker.SetItem( Module );
-                newList.PushItem( picker );
-                Module->SetNeedsPlaced( true );
-            }
+    m_board->GetConnectivity()->Update( module );
+}
 
-            break;
+/**
+ * Function propagate
+ * Used only in autoplace calculations
+ * Uses the routing matrix to fill the cells within the zone
+ * Search and mark cells within the zone, and agree with DRC options.
+ * Requirements:
+ * Start from an initial point, to fill zone
+ * The zone must have no "copper island"
+ *  Algorithm:
+ *  If the current cell has a neighbor flagged as "cell in the zone", it
+ *  become a cell in the zone
+ *  The first point in the zone is the starting point
+ *  4 searches within the matrix are made:
+ *          1 - Left to right and top to bottom
+ *          2 - Right to left and top to bottom
+ *          3 - bottom to top and Right to left
+ *          4 - bottom to top and Left to right
+ *  Given the current cell, for each search, we consider the 2 neighbor cells
+ *  the previous cell on the same line and the previous cell on the same column.
+ *
+ *  This function can request some iterations
+ *  Iterations are made until no cell is added to the zone.
+ *  @return added cells count (i.e. which the attribute CELL_IS_ZONE is set)
+ */
 
-        case PLACE_ALL:
-            Module->SetIsPlaced( false );
+int AR_AUTOPLACER::propagate()
+{
+    int     row, col;
+    long    current_cell, old_cell_H;
+    std::vector<int> pt_cell_V;
+    int     nbpoints = 0;
 
-            if( Module->IsLocked() )
-                break;
+    const uint32_t NO_CELL_ZONE = CELL_IS_HOLE | CELL_IS_EDGE | CELL_IS_ZONE;
 
-            // Module will be placed, add to undo.
-            picker.SetItem( Module );
-            newList.PushItem( picker );
-            Module->SetNeedsPlaced( true );
-            break;
+    pt_cell_V.reserve( std::max( m_matrix.m_Nrows, m_matrix.m_Ncols ) );
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
 
-        case PLACE_INCREMENTAL:
+    // Search from left to right and top to bottom.
+    for( row = 0; row < m_matrix.m_Nrows; row++ )
+    {
+        old_cell_H = 0;
 
-            if( Module->IsLocked() )
-            {
-                Module->SetIsPlaced( false );
-                break;
-            }
+        for( col = 0; col < m_matrix.m_Ncols; col++ )
+        {
+            current_cell = m_matrix.GetCell( row, col, AR_SIDE_BOTTOM ) & NO_CELL_ZONE;
 
-            if( !Module->NeedsPlaced() )
+            if( current_cell == 0 )    // a free cell is found
             {
-                // Module will be placed, add to undo.
-                picker.SetItem( Module );
-                newList.PushItem( picker );
-                Module->SetNeedsPlaced( true );
+                if( (old_cell_H & CELL_IS_ZONE) || (pt_cell_V[col] & CELL_IS_ZONE) )
+                {
+                    m_matrix.OrCell( row, col, AR_SIDE_BOTTOM, CELL_IS_ZONE );
+                    current_cell = CELL_IS_ZONE;
+                    nbpoints++;
+                }
             }
 
-            break;
-        }
-
-        if( Module->NeedsPlaced() )    // Erase from screen
-        {
-            moduleCount++;
-            Module->Draw( m_canvas, DC, GR_XOR );
-        }
-        else
-        {
-            genModuleOnRoutingMatrix( Module );
+            pt_cell_V[col] = old_cell_H = current_cell;
         }
     }
 
-    // Undo command: prepare list
-    if( newList.GetCount() )
-        SaveCopyInUndoList( newList, UR_CHANGED );
-
-    int         cnt = 0;
-    wxString    msg;
+    // Search from right to left and top to bottom/
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
 
-    while( ( Module = PickModule( this, DC ) ) != NULL )
+    for( row = 0; row < m_matrix.m_Nrows; row++ )
     {
-        // Display some info about activity, module placement can take a while:
-        msg.Printf( _( "Place footprint %d of %d" ), cnt, moduleCount );
-        SetStatusText( msg );
-
-        double initialOrient = Module->GetOrientation();
-        // Display fill area of interest, barriers, penalties.
-        drawPlacementRoutingMatrix( GetBoard(), DC );
-
-        error = getOptimalModulePlacement( this, Module, DC );
-        double bestScore = MinCout;
-        double bestRotation = 0.0;
-        int rotAllowed;
-        PosOK = CurrPosition;
-
-        if( error == ESC )
-            goto end_of_tst;
-
-        // Try orientations 90, 180, 270 degrees from initial orientation
-        rotAllowed = Module->GetPlacementCost180();
+        old_cell_H = 0;
 
-        if( rotAllowed != 0 )
+        for( col = m_matrix.m_Ncols - 1; col >= 0; col-- )
         {
-            Rotate_Module( DC, Module, 1800.0, true );
-            error   = getOptimalModulePlacement( this, Module, DC );
-            MinCout *= OrientPenality[rotAllowed];
+            current_cell = m_matrix.GetCell( row, col, AR_SIDE_BOTTOM ) & NO_CELL_ZONE;
 
-            if( bestScore > MinCout )    // This orientation is better.
-            {
-                PosOK       = CurrPosition;
-                bestScore   = MinCout;
-                bestRotation = 1800.0;
-            }
-            else
+            if( current_cell == 0 )    // a free cell is found
             {
-                Rotate_Module( DC, Module, initialOrient, false );
+                if( (old_cell_H & CELL_IS_ZONE) || (pt_cell_V[col] & CELL_IS_ZONE) )
+                {
+                    m_matrix.OrCell( row, col, AR_SIDE_BOTTOM, CELL_IS_ZONE );
+                    current_cell = CELL_IS_ZONE;
+                    nbpoints++;
+                }
             }
 
-            if( error == ESC )
-                goto end_of_tst;
+            pt_cell_V[col] = old_cell_H = current_cell;
         }
+    }
 
-        // Determine if the best orientation of a module is 90.
-        rotAllowed = Module->GetPlacementCost90();
+    // Search from bottom to top and right to left.
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
 
-        if( rotAllowed != 0 )
+    for( col = m_matrix.m_Ncols - 1; col >= 0; col-- )
+    {
+        old_cell_H = 0;
+
+        for( row = m_matrix.m_Nrows - 1; row >= 0; row-- )
         {
-            Rotate_Module( DC, Module, 900.0, true );
-            error   = getOptimalModulePlacement( this, Module, DC );
-            MinCout *= OrientPenality[rotAllowed];
+            current_cell = m_matrix.GetCell( row, col, AR_SIDE_BOTTOM ) & NO_CELL_ZONE;
 
-            if( bestScore > MinCout )    // This orientation is better.
-            {
-                PosOK       = CurrPosition;
-                bestScore   = MinCout;
-                bestRotation = 900.0;
-            }
-            else
+            if( current_cell == 0 )    // a free cell is found
             {
-                Rotate_Module( DC, Module, initialOrient, false );
+                if( (old_cell_H & CELL_IS_ZONE) || (pt_cell_V[row] & CELL_IS_ZONE) )
+                {
+                    m_matrix.OrCell( row, col, AR_SIDE_BOTTOM, CELL_IS_ZONE );
+                    current_cell = CELL_IS_ZONE;
+                    nbpoints++;
+                }
             }
 
-            if( error == ESC )
-                goto end_of_tst;
+            pt_cell_V[row] = old_cell_H = current_cell;
         }
+    }
 
-        // Determine if the best orientation of a module is -90.
-        if( rotAllowed != 0 )
+    // Search from bottom to top and left to right.
+    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+
+    for( col = 0; col < m_matrix.m_Ncols; col++ )
+    {
+        old_cell_H = 0;
+
+        for( row = m_matrix.m_Nrows - 1; row >= 0; row-- )
         {
-            Rotate_Module( DC, Module, 2700.0, true );
-            error   = getOptimalModulePlacement( this, Module, DC );
-            MinCout *= OrientPenality[rotAllowed];
+            current_cell = m_matrix.GetCell( row, col, AR_SIDE_BOTTOM ) & NO_CELL_ZONE;
 
-            if( bestScore > MinCout )    // This orientation is better.
-            {
-                PosOK       = CurrPosition;
-                bestScore   = MinCout;
-                bestRotation = 2700.0;
-            }
-            else
+            if( current_cell == 0 )    // a free cell is found
             {
-                Rotate_Module( DC, Module, initialOrient, false );
+                if( (old_cell_H & CELL_IS_ZONE) || (pt_cell_V[row] & CELL_IS_ZONE) )
+                {
+                    m_matrix.OrCell( row, col, AR_SIDE_BOTTOM, CELL_IS_ZONE );
+                    current_cell = CELL_IS_ZONE;
+                    nbpoints++;
+                }
             }
 
-            if( error == ESC )
-                goto end_of_tst;
+            pt_cell_V[row] = old_cell_H = current_cell;
         }
+    }
 
-end_of_tst:
+    return nbpoints;
+}
 
-        if( error == ESC )
-            break;
+void AR_AUTOPLACER::genModuleOnRoutingMatrix( MODULE* Module )
+{
+    int         ox, oy, fx, fy;
+    LSET        layerMask;
+    
+    EDA_RECT    fpBBox = Module->GetBoundingBox();
 
-        // Place module.
-        CurrPosition = GetCrossHairPosition();
-        SetCrossHairPosition( PosOK );
+    fpBBox.Inflate( m_matrix.m_GridRouting / 2 );
+    ox  = fpBBox.GetX();
+    fx  = fpBBox.GetRight();
+    oy  = fpBBox.GetY();
+    fy  = fpBBox.GetBottom();
 
-        PlaceModule( Module, DC );
+    if( ox < m_matrix.m_BrdBox.GetX() )
+        ox = m_matrix.m_BrdBox.GetX();
 
-        bestRotation += initialOrient;
+    if( ox > m_matrix.m_BrdBox.GetRight() )
+        ox = m_matrix.m_BrdBox.GetRight();
 
-        if( bestRotation != Module->GetOrientation() )
-            Rotate_Module( DC, Module, bestRotation, false );
+    if( fx < m_matrix.m_BrdBox.GetX() )
+        fx = m_matrix.m_BrdBox.GetX();
 
-        SetCrossHairPosition( CurrPosition );
+    if( fx > m_matrix.m_BrdBox.GetRight() )
+        fx = m_matrix.m_BrdBox.GetRight();
 
-        Module->CalculateBoundingBox();
+    if( oy < m_matrix.m_BrdBox.GetY() )
+        oy = m_matrix.m_BrdBox.GetY();
 
-        genModuleOnRoutingMatrix( Module );
-        Module->SetIsPlaced( true );
-        Module->SetNeedsPlaced( false );
-    }
+    if( oy > m_matrix.m_BrdBox.GetBottom() )
+        oy = m_matrix.m_BrdBox.GetBottom();
 
-    CurrPosition = memopos;
+    if( fy < m_matrix.m_BrdBox.GetY() )
+        fy = m_matrix.m_BrdBox.GetY();
 
-    RoutingMatrix.UnInitRoutingMatrix();
+    if( fy > m_matrix.m_BrdBox.GetBottom() )
+        fy = m_matrix.m_BrdBox.GetBottom();
+
+    if( Module->GetLayer() == F_Cu )
+        layerMask.set( F_Cu );
 
-    g_Route_Layer_TOP       = lay_tmp_TOP;
-    g_Route_Layer_BOTTOM    = lay_tmp_BOTTOM;
+    if( Module->GetLayer() == B_Cu )
+        layerMask.set( B_Cu );
 
-    Module = GetBoard()->m_Modules;
+    m_matrix.TraceFilledRectangle( ox, oy, fx, fy, layerMask,
+                          CELL_IS_MODULE, AR_MATRIX::WRITE_OR_CELL );
 
-    for( ; Module != NULL; Module = Module->Next() )
+    // Trace pads + clearance areas.
+    for( auto pad : Module->Pads() )
     {
-        Module->CalculateBoundingBox();
+        int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
+        m_matrix.PlacePad( pad, CELL_IS_MODULE, margin, AR_MATRIX::WRITE_OR_CELL );
     }
 
-    GetBoard()->m_Status_Pcb = 0;
-    Compile_Ratsnest( DC, true );
-    m_canvas->ReDraw( DC, true );
+    // Trace clearance.
+    int margin = ( m_matrix.m_GridRouting * Module->GetPadCount() ) / AR_GAIN;
+    m_matrix.CreateKeepOutRectangle( ox, oy, fx, fy, margin, AR_KEEPOUT_MARGIN , layerMask );
 }
 
-
-void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC )
+/* Test if the rectangular area (ux, ux .. y0, y1):
+ * - is a free zone (except OCCUPED_By_MODULE returns)
+ * - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
+ *
+ * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
+ */
+int AR_AUTOPLACER::testRectangle( const EDA_RECT& aRect, int side )
 {
-    int         ii, jj;
-    COLOR4D     color;
-    int         ox, oy;
-    MATRIX_CELL top_state, bottom_state;
-
-    GRSetDrawMode( DC, GR_COPY );
+    EDA_RECT rect = aRect;
 
-    for( ii = 0; ii < RoutingMatrix.m_Nrows; ii++ )
-    {
-        oy = RoutingMatrix.m_BrdBox.GetY() + ( ii * RoutingMatrix.m_GridRouting );
+    rect.Inflate( m_matrix.m_GridRouting / 2 );
 
-        for( jj = 0; jj < RoutingMatrix.m_Ncols; jj++ )
-        {
-            ox      = RoutingMatrix.m_BrdBox.GetX() + (jj * RoutingMatrix.m_GridRouting);
-            color   = COLOR4D::BLACK;
+    wxPoint start   = rect.GetOrigin();
+    wxPoint end     = rect.GetEnd();
 
-            top_state       = RoutingMatrix.GetCell( ii, jj, TOP );
-            bottom_state    = RoutingMatrix.GetCell( ii, jj, BOTTOM );
+    start   -= m_matrix.m_BrdBox.GetOrigin();
+    end     -= m_matrix.m_BrdBox.GetOrigin();
 
-            if( top_state & CELL_is_ZONE )
-                color = COLOR4D( BLUE );
+    int row_min = start.y / m_matrix.m_GridRouting;
+    int row_max = end.y / m_matrix.m_GridRouting;
+    int col_min = start.x / m_matrix.m_GridRouting;
+    int col_max = end.x / m_matrix.m_GridRouting;
 
-            // obstacles
-            if( ( top_state & CELL_is_EDGE ) || ( bottom_state & CELL_is_EDGE ) )
-                color = COLOR4D::WHITE;
-            else if( top_state & ( HOLE | CELL_is_MODULE ) )
-                color = COLOR4D( LIGHTRED );
-            else if( bottom_state & (HOLE | CELL_is_MODULE) )
-                color = COLOR4D( LIGHTGREEN );
-            else    // Display the filling and keep out regions.
-            {
-                if( RoutingMatrix.GetDist( ii, jj, TOP )
-                    || RoutingMatrix.GetDist( ii, jj, BOTTOM ) )
-                    color = DARKGRAY;
-            }
+    if( start.y > row_min * m_matrix.m_GridRouting )
+        row_min++;
 
-            GRPutPixel( NULL, DC, ox, oy, color );
-        }
-    }
-}
+    if( start.x > col_min * m_matrix.m_GridRouting )
+        col_min++;
 
+    if( row_min < 0 )
+        row_min = 0;
 
-int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel )
-{
-    wxString msg;
+    if( row_max >= ( m_matrix.m_Nrows - 1 ) )
+        row_max = m_matrix.m_Nrows - 1;
 
-    RoutingMatrix.UnInitRoutingMatrix();
+    if( col_min < 0 )
+        col_min = 0;
 
-    EDA_RECT bbox = aBrd->GetBoardEdgesBoundingBox();
+    if( col_max >= ( m_matrix.m_Ncols - 1 ) )
+        col_max = m_matrix.m_Ncols - 1;
 
-    if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
+    for( int row = row_min; row <= row_max; row++ )
     {
-        DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) );
-        return 0;
-    }
-
-    RoutingMatrix.ComputeMatrixSize( aBrd, true );
-    int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows;
+        for( int col = col_min; col <= col_max; col++ )
+        {
+            unsigned int data = m_matrix.GetCell( row, col, side );
 
-    messagePanel->EraseMsgBox();
-    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols );
-    messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN );
-    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows );
-    messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN );
-    msg.Printf( wxT( "%d" ), nbCells );
-    messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW );
+            if( ( data & CELL_IS_ZONE ) == 0 )
+                return AR_OUT_OF_BOARD;
 
-    // Choose the number of board sides.
-    RoutingMatrix.m_RoutingLayersCount = 2;
+            if( (data & CELL_IS_MODULE) )
+                return AR_OCCUIPED_BY_MODULE;
+        }
+    }
 
-    RoutingMatrix.InitRoutingMatrix();
+    return AR_FREE_CELL;
+}
 
-    // Display memory usage.
-    msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 );
-    messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN );
+/* Calculates and returns the clearance area of the rectangular surface
+ * aRect):
+ * (Sum of cells in terms of distance)
+ */
+unsigned int AR_AUTOPLACER::calculateKeepOutArea( const EDA_RECT& aRect, int side )
+{
+    wxPoint start   = aRect.GetOrigin();
+    wxPoint end     = aRect.GetEnd();
 
-    g_Route_Layer_BOTTOM = F_Cu;
+    start   -= m_matrix.m_BrdBox.GetOrigin();
+    end     -= m_matrix.m_BrdBox.GetOrigin();
 
-    if( RoutingMatrix.m_RoutingLayersCount > 1 )
-        g_Route_Layer_BOTTOM = B_Cu;
+    int row_min = start.y / m_matrix.m_GridRouting;
+    int row_max = end.y / m_matrix.m_GridRouting;
+    int col_min = start.x / m_matrix.m_GridRouting;
+    int col_max = end.x / m_matrix.m_GridRouting;
 
-    g_Route_Layer_TOP = F_Cu;
+    if( start.y > row_min * m_matrix.m_GridRouting )
+        row_min++;
 
-    // Place the edge layer segments
-    TRACK TmpSegm( NULL );
+    if( start.x > col_min * m_matrix.m_GridRouting )
+        col_min++;
 
-    TmpSegm.SetLayer( UNDEFINED_LAYER );
-    TmpSegm.SetNetCode( -1 );
-    TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 );
+    if( row_min < 0 )
+        row_min = 0;
 
-    for( auto PtStruct : aBrd->Drawings() )
-    {
-        DRAWSEGMENT* DrawSegm;
+    if( row_max >= ( m_matrix.m_Nrows - 1 ) )
+        row_max = m_matrix.m_Nrows - 1;
 
-        switch( PtStruct->Type() )
-        {
-        case PCB_LINE_T:
-            DrawSegm = (DRAWSEGMENT*) PtStruct;
+    if( col_min < 0 )
+        col_min = 0;
 
-            if( DrawSegm->GetLayer() != Edge_Cuts )
-                break;
+    if( col_max >= ( m_matrix.m_Ncols - 1 ) )
+        col_max = m_matrix.m_Ncols - 1;
 
-            TraceSegmentPcb( DrawSegm, HOLE | CELL_is_EDGE,
-                             RoutingMatrix.m_GridRouting, WRITE_CELL );
-            break;
+    unsigned int keepOutCost = 0;
 
-        case PCB_TEXT_T:
-        default:
-            break;
+    for( int row = row_min; row <= row_max; row++ )
+    {
+        for( int col = col_min; col <= col_max; col++ )
+        {
+            // m_matrix.GetDist returns the "cost" of the cell
+            // at position (row, col)
+            // in autoplace this is the cost of the cell, if it is
+            // inside aRect
+            keepOutCost += m_matrix.GetDist( row, col, side );
         }
     }
 
-    // Mark cells of the routing matrix to CELL_is_ZONE
-    // (i.e. availlable cell to place a module )
-    // Init a starting point of attachment to the area.
-    RoutingMatrix.OrCell( RoutingMatrix.m_Nrows / 2, RoutingMatrix.m_Ncols / 2,
-                          BOTTOM, CELL_is_ZONE );
-
-    // find and mark all other availlable cells:
-    for( int ii = 1; ii != 0; )
-        ii = propagate();
-
-    // Initialize top layer. to the same value as the bottom layer
-    if( RoutingMatrix.m_BoardSide[TOP] )
-        memcpy( RoutingMatrix.m_BoardSide[TOP], RoutingMatrix.m_BoardSide[BOTTOM],
-                nbCells * sizeof(MATRIX_CELL) );
-
-    return 1;
+    return keepOutCost;
 }
 
-
-/* Place module on Routing matrix.
+/* Test if the module can be placed on the board.
+ * Returns the value TstRectangle().
+ * Module is known by its bounding box
  */
-void genModuleOnRoutingMatrix( MODULE* Module )
+int AR_AUTOPLACER::testModuleOnBoard( MODULE* aModule, bool TstOtherSide, const wxPoint& aOffset )
 {
-    int         ox, oy, fx, fy;
-    LSET        layerMask;
-    D_PAD*      Pad;
-
-    EDA_RECT    fpBBox = Module->GetBoundingBox();
-
-    fpBBox.Inflate( RoutingMatrix.m_GridRouting / 2 );
-    ox  = fpBBox.GetX();
-    fx  = fpBBox.GetRight();
-    oy  = fpBBox.GetY();
-    fy  = fpBBox.GetBottom();
-
-    if( ox < RoutingMatrix.m_BrdBox.GetX() )
-        ox = RoutingMatrix.m_BrdBox.GetX();
-
-    if( ox > RoutingMatrix.m_BrdBox.GetRight() )
-        ox = RoutingMatrix.m_BrdBox.GetRight();
-
-    if( fx < RoutingMatrix.m_BrdBox.GetX() )
-        fx = RoutingMatrix.m_BrdBox.GetX();
-
-    if( fx > RoutingMatrix.m_BrdBox.GetRight() )
-        fx = RoutingMatrix.m_BrdBox.GetRight();
-
-    if( oy < RoutingMatrix.m_BrdBox.GetY() )
-        oy = RoutingMatrix.m_BrdBox.GetY();
+    int side = AR_SIDE_TOP;
+    int otherside = AR_SIDE_BOTTOM;
 
-    if( oy > RoutingMatrix.m_BrdBox.GetBottom() )
-        oy = RoutingMatrix.m_BrdBox.GetBottom();
-
-    if( fy < RoutingMatrix.m_BrdBox.GetY() )
-        fy = RoutingMatrix.m_BrdBox.GetY();
-
-    if( fy > RoutingMatrix.m_BrdBox.GetBottom() )
-        fy = RoutingMatrix.m_BrdBox.GetBottom();
+    if( aModule->GetLayer() == B_Cu )
+    {
+        side = AR_SIDE_BOTTOM; otherside = AR_SIDE_TOP;
+    }
 
-    if( Module->GetLayer() == F_Cu )
-        layerMask.set( F_Cu );
+    EDA_RECT    fpBBox = aModule->GetFootprintRect();
+    fpBBox.Move( -aOffset );
 
-    if( Module->GetLayer() == B_Cu )
-        layerMask.set( B_Cu );
+    int         diag = testRectangle( fpBBox, side );
 
-    TraceFilledRectangle( ox, oy, fx, fy, layerMask,
-                          CELL_is_MODULE, WRITE_OR_CELL );
+    if( diag != AR_FREE_CELL )
+        return diag;
 
-    // Trace pads + clearance areas.
-    for( Pad = Module->Pads(); Pad != NULL; Pad = Pad->Next() )
+    if( TstOtherSide )
     {
-        int margin = (RoutingMatrix.m_GridRouting / 2) + Pad->GetClearance();
-        ::PlacePad( Pad, CELL_is_MODULE, margin, WRITE_OR_CELL );
-    }
+        diag = testRectangle( fpBBox, otherside );
 
-    // Trace clearance.
-    int margin = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN;
-    CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask );
-}
+        if( diag != AR_FREE_CELL )
+            return diag;
+    }
 
+    int marge = ( m_matrix.m_GridRouting * aModule->GetPadCount() ) / AR_GAIN;
 
-// A minor helper function to draw a bounding box:
-inline void draw_FootprintRect( EDA_RECT* aClipBox, wxDC* aDC, EDA_RECT& fpBBox, COLOR4D aColor )
-{
-#ifndef USE_WX_OVERLAY
-    GRRect( aClipBox, aDC, fpBBox, 0, aColor );
-#endif
+    fpBBox.Inflate( marge );
+    return calculateKeepOutArea( fpBBox, side );
 }
 
-
-int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC )
+int AR_AUTOPLACER::getOptimalModulePlacement(MODULE* aModule)
 {
     int     error = 1;
     wxPoint LastPosOK;
     double  min_cost, curr_cost, Score;
     bool    TstOtherSide;
-    auto displ_opts = (PCB_DISPLAY_OPTIONS*)aFrame->GetDisplayOptions();
-    BOARD*  brd = aFrame->GetBoard();
-
+    
     aModule->CalculateBoundingBox();
 
-    bool showRats = displ_opts->m_Show_Module_Ratsnest;
-    displ_opts->m_Show_Module_Ratsnest = false;
-
-    brd->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
-    aFrame->SetMsgPanel( aModule );
-
-    LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin();
+    LastPosOK = m_matrix.m_BrdBox.GetOrigin();
 
     wxPoint     mod_pos = aModule->GetPosition();
     EDA_RECT    fpBBox  = aModule->GetFootprintRect();
@@ -640,31 +548,27 @@ int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aD
 
     // Calculate the limit of the footprint position, relative
     // to the routing matrix area
-    wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
+    wxPoint xylimit = m_matrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
 
-    wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
+    wxPoint initialPos = m_matrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
 
     // Stay on grid.
-    initialPos.x    -= initialPos.x % RoutingMatrix.m_GridRouting;
-    initialPos.y    -= initialPos.y % RoutingMatrix.m_GridRouting;
-
-    CurrPosition = initialPos;
+    initialPos.x    -= initialPos.x % m_matrix.m_GridRouting;
+    initialPos.y    -= initialPos.y % m_matrix.m_GridRouting;
 
-    // Undraw the current footprint
-    aModule->DrawOutlinesWhenMoving( aFrame->GetCanvas(), aDC, wxPoint( 0, 0 ) );
-
-    g_Offset_Module = mod_pos - CurrPosition;
+    m_curPosition = initialPos;
+    auto moduleOffset = mod_pos - m_curPosition;
 
     /* Examine pads, and set TstOtherSide to true if a footprint
      * has at least 1 pad through.
      */
     TstOtherSide = false;
 
-    if( RoutingMatrix.m_RoutingLayersCount > 1 )
+    if( m_matrix.m_RoutingLayersCount > 1 )
     {
         LSET    other( aModule->GetLayer() == B_Cu  ? F_Cu : B_Cu );
 
-        for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
+        for( auto pad : aModule->Pads() )
         {
             if( !( pad->GetLayerSet() & other ).any() )
                 continue;
@@ -674,257 +578,121 @@ int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aD
         }
     }
 
-    // Draw the initial bounding box position
-    COLOR4D color = COLOR4D( BROWN );
-    fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
-    draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color);
+    fpBBox.SetOrigin( fpBBoxOrg + m_curPosition );
 
     min_cost = -1.0;
-    aFrame->SetStatusText( wxT( "Score ??, pos ??" ) );
+//    m_frame->SetStatusText( wxT( "Score ??, pos ??" ) );
 
-    for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting )
-    {
-        wxYield();
 
-        if( aFrame->GetCanvas()->GetAbortRequest() )
+    for( ; m_curPosition.x < xylimit.x; m_curPosition.x += m_matrix.m_GridRouting )
+    {
+        if ( m_refreshCallback )
         {
-            if( IsOK( aFrame, _( "OK to abort?" ) ) )
-            {
-                displ_opts->m_Show_Module_Ratsnest = showRats;
-                return ESC;
-            }
-            else
-                aFrame->GetCanvas()->SetAbortRequest( false );
+            if ( m_refreshCallback() == AR_ABORT_PLACEMENT )
+                return AR_ABORT_PLACEMENT;
         }
 
-        CurrPosition.y = initialPos.y;
+        m_curPosition.y = initialPos.y;
 
-        for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting )
+        for( ; m_curPosition.y < xylimit.y; m_curPosition.y += m_matrix.m_GridRouting )
         {
-            // Erase traces.
-            draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
-
-            fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
-            g_Offset_Module = mod_pos - CurrPosition;
-            int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide );
 
-            // Draw at new place
-            color = keepOutCost >= 0 ? BROWN : RED;
-            draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
+            fpBBox.SetOrigin( fpBBoxOrg + m_curPosition );
+            moduleOffset = mod_pos - m_curPosition;
+            int keepOutCost = testModuleOnBoard( aModule, TstOtherSide, moduleOffset );
 
             if( keepOutCost >= 0 )    // i.e. if the module can be put here
             {
                 error = 0;
-                aFrame->build_ratsnest_module( aModule );
-                curr_cost   = compute_Ratsnest_PlaceModule( brd );
+                // m_frame->build_ratsnest_module( aModule ); // fixme
+                curr_cost   = computePlacementRatsnestCost( aModule, moduleOffset );
                 Score       = curr_cost + keepOutCost;
 
                 if( (min_cost >= Score ) || (min_cost < 0 ) )
                 {
-                    LastPosOK   = CurrPosition;
+                    LastPosOK   = m_curPosition;
                     min_cost    = Score;
                     wxString msg;
-                    msg.Printf( wxT( "Score %g, pos %s, %s" ),
+/*                    msg.Printf( wxT( "Score %g, pos %s, %s" ),
                                 min_cost,
                                 GetChars( ::CoordinateToString( LastPosOK.x ) ),
                                 GetChars( ::CoordinateToString( LastPosOK.y ) ) );
-                    aFrame->SetStatusText( msg );
+                    m_frame->SetStatusText( msg );*/
                 }
             }
         }
     }
 
-    // erasing the last traces
-    GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
-
-    displ_opts->m_Show_Module_Ratsnest = showRats;
-
     // Regeneration of the modified variable.
-    CurrPosition = LastPosOK;
-
-    brd->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK );
+    m_curPosition = LastPosOK;
 
-    MinCout = min_cost;
+    m_minCost = min_cost;
     return error;
 }
 
 
-/* Test if the rectangular area (ux, ux .. y0, y1):
- * - is a free zone (except OCCUPED_By_MODULE returns)
- * - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
- *
- * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
- */
-int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
+const D_PAD* AR_AUTOPLACER::nearestPad( MODULE *aRefModule, D_PAD* aRefPad, const wxPoint& aOffset)
 {
-    EDA_RECT rect = aRect;
-
-    rect.Inflate( RoutingMatrix.m_GridRouting / 2 );
-
-    wxPoint start   = rect.GetOrigin();
-    wxPoint end     = rect.GetEnd();
-
-    start   -= RoutingMatrix.m_BrdBox.GetOrigin();
-    end     -= RoutingMatrix.m_BrdBox.GetOrigin();
-
-    int row_min = start.y / RoutingMatrix.m_GridRouting;
-    int row_max = end.y / RoutingMatrix.m_GridRouting;
-    int col_min = start.x / RoutingMatrix.m_GridRouting;
-    int col_max = end.x / RoutingMatrix.m_GridRouting;
-
-    if( start.y > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    if( start.x > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
+    const D_PAD* nearest = nullptr;
+    int64_t nearestDist = INT64_MAX;
 
-    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    for( int row = row_min; row <= row_max; row++ )
+    for ( auto mod : m_board->Modules() )
     {
-        for( int col = col_min; col <= col_max; col++ )
-        {
-            unsigned int data = RoutingMatrix.GetCell( row, col, side );
-
-            if( ( data & CELL_is_ZONE ) == 0 )
-                return OUT_OF_BOARD;
-
-            if( (data & CELL_is_MODULE) )
-                return OCCUPED_By_MODULE;
-        }
-    }
-
-    return FREE_CELL;
-}
-
-
-/* Calculates and returns the clearance area of the rectangular surface
- * aRect):
- * (Sum of cells in terms of distance)
- */
-unsigned int CalculateKeepOutArea( const EDA_RECT& aRect, int side )
-{
-    wxPoint start   = aRect.GetOrigin();
-    wxPoint end     = aRect.GetEnd();
-
-    start   -= RoutingMatrix.m_BrdBox.GetOrigin();
-    end     -= RoutingMatrix.m_BrdBox.GetOrigin();
-
-    int row_min = start.y / RoutingMatrix.m_GridRouting;
-    int row_max = end.y / RoutingMatrix.m_GridRouting;
-    int col_min = start.x / RoutingMatrix.m_GridRouting;
-    int col_max = end.x / RoutingMatrix.m_GridRouting;
-
-    if( start.y > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    if( start.x > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
+        if ( mod == aRefModule )
+            continue;
 
-    unsigned int keepOutCost = 0;
+        if( !m_matrix.m_BrdBox.Contains( mod->GetPosition() ) )
+            continue;
 
-    for( int row = row_min; row <= row_max; row++ )
-    {
-        for( int col = col_min; col <= col_max; col++ )
+        for ( auto pad: mod->Pads() )
         {
-            // RoutingMatrix.GetDist returns the "cost" of the cell
-            // at position (row, col)
-            // in autoplace this is the cost of the cell, if it is
-            // inside aRect
-            keepOutCost += RoutingMatrix.GetDist( row, col, side );
-        }
-    }
-
-    return keepOutCost;
-}
-
-
-/* Test if the module can be placed on the board.
- * Returns the value TstRectangle().
- * Module is known by its bounding box
- */
-int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide )
-{
-    int side = TOP;
-    int otherside = BOTTOM;
-
-    if( aModule->GetLayer() == B_Cu )
-    {
-        side = BOTTOM; otherside = TOP;
-    }
-
-    EDA_RECT    fpBBox = aModule->GetFootprintRect();
-    fpBBox.Move( -g_Offset_Module );
-
-    int         diag = TstRectangle( Pcb, fpBBox, side );
+        
+            if ( pad->GetNetCode() != aRefPad->GetNetCode() || pad->GetNetCode() <= 0 )
+                continue;
 
-    if( diag != FREE_CELL )
-        return diag;
+            auto dist = (VECTOR2I( aRefPad->GetPosition() - aOffset ) - VECTOR2I( pad->GetPosition() ) ).EuclideanNorm();
 
-    if( TstOtherSide )
-    {
-        diag = TstRectangle( Pcb, fpBBox, otherside );
+            //printf("Dist %lld pad %p\n", dist, pad );
 
-        if( diag != FREE_CELL )
-            return diag;
+            if ( dist < nearestDist )
+            {
+                nearestDist = dist;
+                nearest = pad;
+            }
+        }
     }
 
-    int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN;
-
-    fpBBox.Inflate( marge );
-    return CalculateKeepOutArea( fpBBox, side );
+    return nearest;
 }
 
-
-double compute_Ratsnest_PlaceModule( BOARD* aBrd )
+double AR_AUTOPLACER::computePlacementRatsnestCost( MODULE *aModule, const wxPoint& aOffset )
 {
     double  curr_cost;
-    wxPoint start;      // start point of a ratsnest
-    wxPoint end;        // end point of a ratsnest
+    VECTOR2I start;      // start point of a ratsnest
+    VECTOR2I end;        // end point of a ratsnest
     int     dx, dy;
 
-    if( ( aBrd->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 )
-        return -1;
-
     curr_cost = 0;
 
-    for( unsigned ii = 0; ii < aBrd->m_LocalRatsnest.size(); ii++ )
-    {
-        RATSNEST_ITEM* pt_local_rats_nest = &aBrd->m_LocalRatsnest[ii];
+  
+  //  m_overlay->Clear();
 
-        if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) )
-            continue; // Skip ratsnest between 2 pads of the current module
 
-        // Skip modules not inside the board area
-        MODULE* module = pt_local_rats_nest->m_PadEnd->GetParent();
+    for ( auto pad : aModule->Pads() )
+    {
+        auto nearest = nearestPad( aModule, pad, aOffset );
 
-        if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) )
+        if( !nearest )
             continue;
 
-        start   = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module;
-        end     = pt_local_rats_nest->m_PadEnd->GetPosition();
+        //printf("pad %s nearest %s\n", (const char *)aModule->GetReference().c_str(), (const char *)nearest->GetParent()->GetReference().c_str());
+
+        start   = VECTOR2I( pad->GetPosition() ) - VECTOR2I(aOffset);
+        end     = VECTOR2I( nearest->GetPosition() );
+
+        //m_overlay->SetIsStroke( true );
+        //m_overlay->SetStrokeColor( COLOR4D(0.0, 1.0, 0.0, 1.0) );
+        //m_overlay->Line( start, end );
 
         // Cost of the ratsnest.
         dx  = end.x - start.x;
@@ -949,122 +717,8 @@ double compute_Ratsnest_PlaceModule( BOARD* aBrd )
     return curr_cost;
 }
 
-
-/**
- * Function CreateKeepOutRectangle
- * builds the cost map:
- * Cells ( in Dist map ) inside the rect x0,y0 a x1,y1 are
- *  incremented by value aKeepOut
- *  Cell outside this rectangle, but inside the rectangle
- *  x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value
- *  (aKeepOut ... 0). The decreasing value depends on the distance to the first rectangle
- *  Therefore the cost is high in rect x0,y0 to x1,y1, and decrease outside this rectangle
- */
-void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
-                             int marge, int aKeepOut, LSET aLayerMask )
-{
-    int         row, col;
-    int         row_min, row_max, col_min, col_max, pmarge;
-    int         trace = 0;
-    DIST_CELL   data, LocalKeepOut;
-    int         lgain, cgain;
-
-    if( aLayerMask[g_Route_Layer_BOTTOM] )
-        trace = 1; // Trace on bottom layer.
-
-    if( aLayerMask[g_Route_Layer_TOP] && RoutingMatrix.m_RoutingLayersCount )
-        trace |= 2; // Trace on top layer.
-
-    if( trace == 0 )
-        return;
-
-    ux0 -= RoutingMatrix.m_BrdBox.GetX();
-    uy0 -= RoutingMatrix.m_BrdBox.GetY();
-    ux1 -= RoutingMatrix.m_BrdBox.GetX();
-    uy1 -= RoutingMatrix.m_BrdBox.GetY();
-
-    ux0 -= marge; ux1 += marge;
-    uy0 -= marge; uy1 += marge;
-
-    pmarge = marge / RoutingMatrix.m_GridRouting;
-
-    if( pmarge < 1 )
-        pmarge = 1;
-
-    // Calculate the coordinate limits of the rectangle.
-    row_max = uy1 / RoutingMatrix.m_GridRouting;
-    col_max = ux1 / RoutingMatrix.m_GridRouting;
-    row_min = uy0 / RoutingMatrix.m_GridRouting;
-
-    if( uy0 > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    col_min = ux0 / RoutingMatrix.m_GridRouting;
-
-    if( ux0 > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= (RoutingMatrix.m_Nrows - 1) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= (RoutingMatrix.m_Ncols - 1) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    for( row = row_min; row <= row_max; row++ )
-    {
-        lgain = 256;
-
-        if( row < pmarge )
-            lgain = ( 256 * row ) / pmarge;
-        else if( row > row_max - pmarge )
-            lgain = ( 256 * ( row_max - row ) ) / pmarge;
-
-        for( col = col_min; col <= col_max; col++ )
-        {
-            // RoutingMatrix Dist map containt the "cost" of the cell
-            // at position (row, col)
-            // in autoplace this is the cost of the cell, when
-            // a footprint overlaps it, near a "master" footprint
-            // this cost is hight near the "master" footprint
-            // and decrease with the distance
-            cgain = 256;
-            LocalKeepOut = aKeepOut;
-
-            if( col < pmarge )
-                cgain = ( 256 * col ) / pmarge;
-            else if( col > col_max - pmarge )
-                cgain = ( 256 * ( col_max - col ) ) / pmarge;
-
-            cgain = ( cgain * lgain ) / 256;
-
-            if( cgain != 256 )
-                LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
-
-            if( trace & 1 )
-            {
-                data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut;
-                RoutingMatrix.SetDist( row, col, BOTTOM, data );
-            }
-
-            if( trace & 2 )
-            {
-                data    = RoutingMatrix.GetDist( row, col, TOP );
-                data    = std::max( data, LocalKeepOut );
-                RoutingMatrix.SetDist( row, col, TOP, data );
-            }
-        }
-    }
-}
-
-
 // Sort routines
-static bool Tri_PlaceModules( MODULE* ref, MODULE* compare )
+static bool sortFootprintsByComplexity( MODULE* ref, MODULE* compare )
 {
     double ff1, ff2;
 
@@ -1074,7 +728,6 @@ static bool Tri_PlaceModules( MODULE* ref, MODULE* compare )
     return ff2 < ff1;
 }
 
-
 static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare )
 {
     double ff1, ff2;
@@ -1086,70 +739,67 @@ static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare )
 
 
 /**
- * Function PickModule
+ * Function Module
  * find the "best" module place
  * The criteria are:
  * - Maximum ratsnest with modules already placed
  * - Max size, and number of pads max
  */
-static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
+MODULE* AR_AUTOPLACER::pickModule( )
 {
-    MODULE* Module;
+    MODULE* module;
     std::vector <MODULE*> moduleList;
 
-    // Build sorted footprints list (sort by decreasing size )
-    Module = pcbframe->GetBoard()->m_Modules;
-
-    for( ; Module != NULL; Module = Module->Next() )
+    
+    for( auto m : m_board->Modules() )
     {
-        Module->CalculateBoundingBox();
-        moduleList.push_back( Module );
+        m->CalculateBoundingBox();
+        moduleList.push_back( m );
     }
 
-    sort( moduleList.begin(), moduleList.end(), Tri_PlaceModules );
+    sort( moduleList.begin(), moduleList.end(), sortFootprintsByComplexity );
 
     for( unsigned kk = 0; kk < moduleList.size(); kk++ )
     {
-        Module = moduleList[kk];
-        Module->SetFlag( 0 );
+        module = moduleList[kk];
+        module->SetFlag( 0 );
 
-        if( !Module->NeedsPlaced() )
+        if( !module->NeedsPlaced() )
             continue;
 
-        pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
-        pcbframe->SetMsgPanel( Module );
-        pcbframe->build_ratsnest_module( Module );
-
-        // Calculate external ratsnest.
-        for( unsigned ii = 0; ii < pcbframe->GetBoard()->m_LocalRatsnest.size(); ii++ )
-        {
-            if( ( pcbframe->GetBoard()->m_LocalRatsnest[ii].m_Status &
-                  LOCAL_RATSNEST_ITEM ) == 0 )
-                Module->IncrementFlag();
-        }
+        m_connectivity->Update( module );
     }
 
-    pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
+    m_connectivity->RecalculateRatsnest();
+    
+    for( unsigned kk = 0; kk < moduleList.size(); kk++ )
+    {
+        module = moduleList[kk];
+
+        auto edges = m_connectivity->GetRatsnestForComponent( module, true );
+
+        module->SetFlag( edges.size() ) ;
+    }
 
     sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize );
 
     // Search for "best" module.
-    MODULE* bestModule  = NULL;
-    MODULE* altModule   = NULL;
+    MODULE* bestModule  = nullptr;
+    MODULE* altModule   = nullptr;
 
     for( unsigned ii = 0; ii < moduleList.size(); ii++ )
     {
-        Module = moduleList[ii];
+        module = moduleList[ii];
 
-        if( !Module->NeedsPlaced() )
+        if( !module->NeedsPlaced() )
             continue;
 
-        altModule = Module;
+        altModule = module;
 
-        if( Module->GetFlag() == 0 )
+        if( module->GetFlag() == 0 )
             continue;
 
-        bestModule = Module;
+        bestModule = module;
         break;
     }
 
@@ -1160,139 +810,269 @@ static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
 }
 
 
-/**
- * Function propagate
- * Used only in autoplace calculations
- * Uses the routing matrix to fill the cells within the zone
- * Search and mark cells within the zone, and agree with DRC options.
- * Requirements:
- * Start from an initial point, to fill zone
- * The zone must have no "copper island"
- *  Algorithm:
- *  If the current cell has a neighbor flagged as "cell in the zone", it
- *  become a cell in the zone
- *  The first point in the zone is the starting point
- *  4 searches within the matrix are made:
- *          1 - Left to right and top to bottom
- *          2 - Right to left and top to bottom
- *          3 - bottom to top and Right to left
- *          4 - bottom to top and Left to right
- *  Given the current cell, for each search, we consider the 2 neighbor cells
- *  the previous cell on the same line and the previous cell on the same column.
- *
- *  This function can request some iterations
- *  Iterations are made until no cell is added to the zone.
- *  @return added cells count (i.e. which the attribute CELL_is_ZONE is set)
- */
-int propagate()
+void AR_AUTOPLACER::drawPlacementRoutingMatrix( )
 {
-    int     row, col;
-    long    current_cell, old_cell_H;
-    std::vector<long> pt_cell_V;
-    int     nbpoints = 0;
-
-#define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
-
-    pt_cell_V.reserve( std::max( RoutingMatrix.m_Nrows, RoutingMatrix.m_Ncols ) );
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+    int         ii, jj;
+    COLOR4D     color;
+    int         ox, oy;
+    AR_MATRIX::MATRIX_CELL top_state, bottom_state;
 
-    // Search from left to right and top to bottom.
-    for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
+    
+    for( ii = 0; ii < m_matrix.m_Nrows; ii++ )
     {
-        old_cell_H = 0;
+        oy = m_matrix.m_BrdBox.GetY() + ( ii * m_matrix.m_GridRouting );
 
-        for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
+        for( jj = 0; jj < m_matrix.m_Ncols; jj++ )
         {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+            ox      = m_matrix.m_BrdBox.GetX() + (jj * m_matrix.m_GridRouting);
+            color   = COLOR4D::BLACK;
 
-            if( current_cell == 0 )    // a free cell is found
+            top_state       = m_matrix.GetCell( ii, jj, AR_SIDE_TOP );
+            bottom_state    = m_matrix.GetCell( ii, jj, AR_SIDE_BOTTOM );
+
+            if(top_state || bottom_state)
             {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
+             //   printf("[%d, %d] [%d, %d] TS %x BS %x\n",ii,jj, ox, oy, top_state, bottom_state );
             }
 
-            pt_cell_V[col] = old_cell_H = current_cell;
+            if( top_state & CELL_IS_ZONE )
+                color = COLOR4D( BLUE );
+
+            // obstacles
+            if( ( top_state & CELL_IS_EDGE ) || ( bottom_state & CELL_IS_EDGE ) )
+                color = COLOR4D::WHITE;
+            else if( top_state & ( CELL_IS_HOLE | CELL_IS_MODULE ) )
+                color = COLOR4D( LIGHTRED );
+            else if( bottom_state & ( CELL_IS_HOLE | CELL_IS_MODULE) )
+                color = COLOR4D( LIGHTGREEN );
+            else    // Display the filling and keep out regions.
+            {
+                if( m_matrix.GetDist( ii, jj, AR_SIDE_TOP )
+                    || m_matrix.GetDist( ii, jj, AR_SIDE_BOTTOM ) )
+                    color = DARKGRAY;
+            }
+
+            m_overlay->SetIsFill(true);
+            m_overlay->SetFillColor( color );
+            
+            VECTOR2D p(ox, oy);
+            m_overlay->Circle(p, m_matrix.m_GridRouting/4 );
         }
     }
+}
 
-    // Search from right to left and top to bottom/
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+AR_RESULT AR_AUTOPLACER::AutoplaceModules( std::vector<MODULE*> aModules, BOARD_COMMIT* aCommit, bool aPlaceOffboardModules )
+{
+    wxPoint             PosOK;
+    wxPoint             memopos;
+    int                 error;
+    MODULE* module = nullptr;
+    bool cancelled = false;
+
+    memopos = m_curPosition;
+    
+    //printf("set grid: %d\n", m_gridSize);
+
+    m_matrix.m_GridRouting = m_gridSize; //(int) m_frame->GetScreen()->GetGridSize().x;
 
-    for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
+    // Ensure Board.m_GridRouting has a reasonable value:
+    if( m_matrix.m_GridRouting < Millimeter2iu( 0.25 ) )
+        m_matrix.m_GridRouting = Millimeter2iu( 0.25 );
+
+    // Compute module parameters used in auto place
+    if( genPlacementRoutingMatrix( ) == 0 )
+        return AR_FAILURE;
+
+    int moduleCount = 0;
+    
+    
+    for ( auto m : m_board->Modules() )
     {
-        old_cell_H = 0;
+        m->SetNeedsPlaced( false );
+    }
 
-        for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
-        {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+    
+    std::vector<MODULE *> offboardMods;
 
-            if( current_cell == 0 )    // a free cell is found
+    if( aPlaceOffboardModules )
+    {
+        for ( auto m : m_board->Modules() )
+        {
+            if( !m_matrix.m_BrdBox.Contains( m->GetPosition() ) )
             {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
+                offboardMods.push_back( m );
             }
+        }
+    }
 
-            pt_cell_V[col] = old_cell_H = current_cell;
+    for ( auto m : aModules )
+    {
+        m->SetNeedsPlaced( true );
+        aCommit->Modify(m);
+    }
+
+    for ( auto m : offboardMods )
+    {
+        m->SetNeedsPlaced( true );
+        aCommit->Modify(m);
+    }
+
+    for ( auto m : m_board->Modules() )
+    {
+        if( m->NeedsPlaced() )    // Erase from screen
+        {
+            moduleCount++;
+        }
+        else
+        {
+            genModuleOnRoutingMatrix( m );
         }
     }
 
-    // Search from bottom to top and right to left.
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+    drawPlacementRoutingMatrix();
+
+    int         cnt = 0;
+    wxString    msg;
 
-    for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
+    if( m_progressReporter )
     {
-        old_cell_H = 0;
+        m_progressReporter->Report( _( "Autoplacing components..." ) );
+        m_progressReporter->SetMaxProgress( moduleCount );
+    }
+
+    while( ( module = pickModule( ) ) != nullptr )
+    {
+        // Display some info about activity, module placement can take a while:
+        //printf( _( "Place footprint %d of %d [%s]\n" ), cnt, moduleCount, (const char *)module->GetReference().c_str() );
+        //m_frame->SetStatusText( msg );
+
+        double initialOrient = module->GetOrientation();
+        // Display fill area of interest, barriers, penalties.
+        //drawPlacementRoutingMatrix( );
+
+        error = getOptimalModulePlacement( module );
+        double bestScore = m_minCost;
+        double bestRotation = 0.0;
+        int rotAllowed;
+        PosOK = m_curPosition;
+
+        if( error == AR_ABORT_PLACEMENT )
+            goto end_of_tst;
+
+        // Try orientations 90, 180, 270 degrees from initial orientation
+        rotAllowed = module->GetPlacementCost180();
 
-        for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
+        //printf("rotAllowed %d\n", rotAllowed);
+
+        if( rotAllowed != 0 )
         {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+            rotateModule( module, 1800.0, true );
+            error   = getOptimalModulePlacement( module );
+            m_minCost *= OrientationPenalty[rotAllowed];
 
-            if( current_cell == 0 )    // a free cell is found
+            if( bestScore > m_minCost )    // This orientation is better.
             {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
+                PosOK       = m_curPosition;
+                bestScore   = m_minCost;
+                bestRotation = 1800.0;
+            }
+            else
+            {
+                rotateModule( module, initialOrient, false );
             }
 
-            pt_cell_V[row] = old_cell_H = current_cell;
+            if( error == AR_ABORT_PLACEMENT )
+                goto end_of_tst;
         }
-    }
 
-    // Search from bottom to top and left to right.
-    fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
+        // Determine if the best orientation of a module is 90.
+        rotAllowed = module->GetPlacementCost90();
+        if( rotAllowed != 0 )
+        {
+            rotateModule( module, 900.0, true );
+            error   = getOptimalModulePlacement( module );
+            m_minCost *= OrientationPenalty[rotAllowed];
 
-    for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
-    {
-        old_cell_H = 0;
+            if( bestScore > m_minCost )    // This orientation is better.
+            {
+                PosOK       = m_curPosition;
+                bestScore   = m_minCost;
+                bestRotation = 900.0;
+            }
+            else
+            {
+                rotateModule( module, initialOrient, false );
+            }
 
-        for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
+            if( error == AR_ABORT_PLACEMENT )
+                goto end_of_tst;
+        }
+
+        // Determine if the best orientation of a module is -90.
+        if( rotAllowed != 0 )
         {
-            current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
+            rotateModule( module, 2700.0, true );
+            error   = getOptimalModulePlacement( module );
+            m_minCost *= OrientationPenalty[rotAllowed];
 
-            if( current_cell == 0 )    // a free cell is found
+            if( bestScore > m_minCost )    // This orientation is better.
             {
-                if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
-                {
-                    RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
-                    current_cell = CELL_is_ZONE;
-                    nbpoints++;
-                }
+                PosOK       = m_curPosition;
+                bestScore   = m_minCost;
+                bestRotation = 2700.0;
+            }
+            else
+            {
+                rotateModule( module, initialOrient, false );
             }
 
-            pt_cell_V[row] = old_cell_H = current_cell;
+            if( error == AR_ABORT_PLACEMENT )
+                goto end_of_tst;
+        }
+
+end_of_tst:
+
+        if( error == AR_ABORT_PLACEMENT )
+            break;
+
+
+        bestRotation += initialOrient;
+
+        if( bestRotation != module->GetOrientation() )
+        {
+            //printf("best rotation %d\n",  bestRotation );
+            rotateModule( module, bestRotation, false );
         }
+
+        // Place module.
+        placeModule( module, true, m_curPosition );
+
+        module->CalculateBoundingBox();
+        genModuleOnRoutingMatrix( module );
+        module->SetIsPlaced( true );
+        module->SetNeedsPlaced( false );
+
+
+        if( m_progressReporter )
+        {
+            m_progressReporter->AdvanceProgress();
+            if ( !m_progressReporter->KeepRefreshing( false ) )
+            {
+                cancelled = true;
+                break;
+            }
+        }
+        cnt++;
     }
 
-    return nbpoints;
+    m_curPosition = memopos;
+
+    m_matrix.UnInitRoutingMatrix();
+
+    for ( auto m : m_board->Modules() )
+    {
+        m->CalculateBoundingBox();
+    }
+
+    return cancelled ? AR_CANCELLED : AR_COMPLETED;
 }
diff --git a/pcbnew/autorouter/ar_autoplacer.h b/pcbnew/autorouter/ar_autoplacer.h
new file mode 100644
index 0000000..552962b
--- /dev/null
+++ b/pcbnew/autorouter/ar_autoplacer.h
@@ -0,0 +1,121 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
+ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ *
+ * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+
+#ifndef __AR_AUTOPLACER_H
+#define __AR_AUTOPLACER_H
+
+#include "ar_matrix.h"
+#include "ar_cell.h"
+
+#include <class_board.h>
+#include <class_module.h>
+
+#include <connectivity_data.h>
+
+#include <view/view_overlay.h>
+
+enum AR_CELL_STATE
+{
+    AR_OUT_OF_BOARD = -2,
+    AR_OCCUIPED_BY_MODULE = -1,
+    AR_FREE_CELL = 0
+};
+
+enum AR_RESULT
+{
+    AR_COMPLETED = 1,
+    AR_CANCELLED,
+    AR_FAILURE
+};
+
+class PROGRESS_REPORTER;
+
+class AR_AUTOPLACER 
+{
+
+public:
+
+    AR_AUTOPLACER( BOARD* aBoard );
+
+    AR_RESULT AutoplaceModules( std::vector<MODULE*> aModules, BOARD_COMMIT* aCommit, bool aPlaceOffboardModules = false );
+    
+
+    const std::vector<MODULE*> QueryOffboardModules();
+
+    void SetPlacementGrid( int aGrid )
+    {
+        m_gridSize = aGrid;
+    }
+
+    void SetOverlay( std::shared_ptr<KIGFX::VIEW_OVERLAY> aOverlay )
+    {
+        m_overlay = aOverlay;
+    }
+
+    void SetRefreshCallback( std::function<int()> aCallback )
+    {
+        m_refreshCallback = aCallback;
+    }
+
+    void SetProgressReporter( PROGRESS_REPORTER* aReporter )
+    {
+        m_progressReporter = aReporter;
+    }
+
+        
+private:
+    void drawPlacementRoutingMatrix( );
+    void rotateModule( MODULE* module, double angle, bool incremental );
+    int genPlacementRoutingMatrix();
+    void genModuleOnRoutingMatrix( MODULE* Module );
+    int propagate();
+    int testRectangle( const EDA_RECT& aRect, int side );
+    unsigned int calculateKeepOutArea( const EDA_RECT& aRect, int side );
+    int testModuleOnBoard( MODULE* aModule, bool TstOtherSide, const wxPoint& aOffset );
+    int getOptimalModulePlacement(MODULE* aModule);
+    double computePlacementRatsnestCost( MODULE *aModule, const wxPoint& aOffset );
+    MODULE* pickModule( );
+    void placeModule( MODULE* aModule, bool aDoNotRecreateRatsnest, const wxPoint& aPos );
+    const D_PAD* nearestPad( MODULE *aRefModule, D_PAD* aRefPad, const wxPoint& aOffset);
+
+    AR_MATRIX m_matrix;
+
+    BOARD* m_board;
+
+    wxPoint m_curPosition;
+    wxPoint m_moduleOffset;
+    double m_minCost;
+    int m_gridSize;
+
+    std::shared_ptr<KIGFX::VIEW_OVERLAY> m_overlay;
+    std::unique_ptr<CONNECTIVITY_DATA> m_connectivity;
+    std::function<int()> m_refreshCallback;
+    PROGRESS_REPORTER* m_progressReporter;
+};
+
+#endif
diff --git a/pcbnew/autorouter/ar_cell.h b/pcbnew/autorouter/ar_cell.h
index 63b76ae..2dbaafe 100644
--- a/pcbnew/autorouter/ar_cell.h
+++ b/pcbnew/autorouter/ar_cell.h
@@ -1,7 +1,3 @@
-/**
- * @file cell.h
- */
-
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
@@ -32,16 +28,16 @@
  */
 
 
-#ifndef _CELL_H_
-#define _CELL_H_
-
+#ifndef _AR_CELL_H_
+#define _AR_CELL_H_
 
 /* Bits characterizing cell */
-#define HOLE           0x01  /* a conducting hole or obstacle */
-#define CELL_is_MODULE 0x02  /* auto placement occupied by a module */
-#define CELL_is_EDGE   0x20  /* Area and auto-placement: limiting cell contour (Board, Zone) */
-#define CELL_is_FRIEND 0x40  /* Area and auto-placement: cell part of the net */
-#define CELL_is_ZONE   0x80  /* Area and auto-placement: cell available */
+#define CELL_IS_EMPTY  0x00
+#define CELL_IS_HOLE   0x01  /* a conducting hole or obstacle */
+#define CELL_IS_MODULE 0x02  /* auto placement occupied by a module */
+#define CELL_IS_EDGE   0x20  /* Area and auto-placement: limiting cell contour (Board, Zone) */
+#define CELL_IS_FRIEND 0x40  /* Area and auto-placement: cell part of the net */
+#define CELL_IS_ZONE   0x80  /* Area and auto-placement: cell available */
 
 /* Bit masks for presence of obstacles to autorouting */
 #define OCCUPE            1  /* Autorouting: obstacle tracks and vias. */
diff --git a/pcbnew/autorouter/ar_matrix.cpp b/pcbnew/autorouter/ar_matrix.cpp
index 856dead..dfc7b68 100644
--- a/pcbnew/autorouter/ar_matrix.cpp
+++ b/pcbnew/autorouter/ar_matrix.cpp
@@ -25,33 +25,23 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-/**
- * @file routing_matrix.cpp
- * @brief Functions to create autorouting maps
- */
+#include "ar_matrix.h"
+#include "ar_cell.h"
 
-#include <fctsys.h>
+#include <trigo.h>
+#include <math_for_graphics.h>
 #include <common.h>
 
-#include <pcbnew.h>
-#include <cell.h>
-#include <autorout.h>
-
-#include <class_eda_rect.h>
-#include <class_board.h>
-#include <class_module.h>
-#include <class_track.h>
 #include <class_drawsegment.h>
-#include <class_edge_mod.h>
-#include <class_pcb_text.h>
-
+#include <class_track.h>
+#include <class_pad.h>
 
-MATRIX_ROUTING_HEAD::MATRIX_ROUTING_HEAD()
+AR_MATRIX::AR_MATRIX()
 {
-    m_BoardSide[0] = m_BoardSide[1] = NULL;
-    m_DistSide[0] = m_DistSide[1] = NULL;
-    m_DirSide[0] = m_DirSide[1] = NULL;
-    m_opWriteCell        = NULL;
+    m_BoardSide[0] = m_BoardSide[1] = nullptr;
+    m_DistSide[0] = m_DistSide[1] = nullptr;
+    m_DirSide[0] = m_DirSide[1] = nullptr;
+    m_opWriteCell        = nullptr;
     m_InitMatrixDone     = false;
     m_Nrows              = 0;
     m_Ncols              = 0;
@@ -62,15 +52,17 @@ MATRIX_ROUTING_HEAD::MATRIX_ROUTING_HEAD()
 }
 
 
-MATRIX_ROUTING_HEAD::~MATRIX_ROUTING_HEAD()
+AR_MATRIX::~AR_MATRIX()
 {
 }
 
+// was: bool AR_MATRIX::ComputeMatrixSize(  BOARD* aPcb, bool aUseBoardEdgesOnly )
+// aUseBoardEdgesOnly ? aPcb->GetBoardEdgesBoundingBox() : aPcb->GetBoundingBox();
 
-bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly )
+bool AR_MATRIX::ComputeMatrixSize( const EDA_RECT& aBoundingBox )
 {
     // The boundary box must have its start point on routing grid:
-    m_BrdBox = aUseBoardEdgesOnly ? aPcb->GetBoardEdgesBoundingBox() : aPcb->GetBoundingBox();
+    m_BrdBox = aBoundingBox;
 
     m_BrdBox.SetX( m_BrdBox.GetX() - ( m_BrdBox.GetX() % m_GridRouting ) );
     m_BrdBox.SetY( m_BrdBox.GetY() - ( m_BrdBox.GetY() % m_GridRouting ) );
@@ -97,7 +89,7 @@ bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnl
 }
 
 
-int MATRIX_ROUTING_HEAD::InitRoutingMatrix()
+int AR_MATRIX::InitRoutingMatrix()
 {
     if( m_Nrows <= 0 || m_Ncols <= 0 )
         return 0;
@@ -105,37 +97,37 @@ int MATRIX_ROUTING_HEAD::InitRoutingMatrix()
     m_InitMatrixDone = true;     // we have been called
 
     // give a small margin for memory allocation:
-    int ii = (RoutingMatrix.m_Nrows + 1) * (RoutingMatrix.m_Ncols + 1);
+    int ii = (m_Nrows + 1) * (m_Ncols + 1);
 
-    int side = BOTTOM;
+    int side = AR_SIDE_BOTTOM;
     for( int jj = 0; jj < m_RoutingLayersCount; jj++ )  // m_RoutingLayersCount = 1 or 2
     {
-        m_BoardSide[side] = NULL;
-        m_DistSide[side]  = NULL;
-        m_DirSide[side]   = NULL;
+        m_BoardSide[side] = nullptr;
+        m_DistSide[side]  = nullptr;
+        m_DirSide[side]   = nullptr;
 
         // allocate matrix & initialize everything to empty
         m_BoardSide[side] = (MATRIX_CELL*) operator new( ii * sizeof(MATRIX_CELL) );
         memset( m_BoardSide[side], 0, ii * sizeof(MATRIX_CELL) );
 
-        if( m_BoardSide[side] == NULL )
+        if( m_BoardSide[side] == nullptr )
             return -1;
 
         // allocate Distances
         m_DistSide[side] = (DIST_CELL*) operator new( ii * sizeof(DIST_CELL) );
         memset( m_DistSide[side], 0, ii * sizeof(DIST_CELL) );
 
-        if( m_DistSide[side] == NULL )
+        if( m_DistSide[side] == nullptr )
             return -1;
 
         // allocate Dir (chars)
         m_DirSide[side] = (char*) operator new( ii );
         memset( m_DirSide[side], 0, ii );
 
-        if( m_DirSide[side] == NULL )
+        if( m_DirSide[side] == nullptr )
             return -1;
 
-        side = TOP;
+        side = AR_SIDE_TOP;
     }
 
     m_MemSize = m_RouteCount * ii * ( sizeof(MATRIX_CELL)
@@ -145,403 +137,1196 @@ int MATRIX_ROUTING_HEAD::InitRoutingMatrix()
 }
 
 
-void MATRIX_ROUTING_HEAD::UnInitRoutingMatrix()
+void AR_MATRIX::UnInitRoutingMatrix()
 {
     int ii;
 
     m_InitMatrixDone = false;
 
-    for( ii = 0; ii < MAX_ROUTING_LAYERS_COUNT; ii++ )
+    for( ii = 0; ii < AR_MAX_ROUTING_LAYERS_COUNT; ii++ )
     {
         // de-allocate Dir matrix
         if( m_DirSide[ii] )
         {
             delete m_DirSide[ii];
-            m_DirSide[ii] = NULL;
+            m_DirSide[ii] = nullptr;
         }
 
         // de-allocate Distances matrix
         if( m_DistSide[ii] )
         {
             delete m_DistSide[ii];
-            m_DistSide[ii] = NULL;
+            m_DistSide[ii] = nullptr;
         }
 
         // de-allocate cells matrix
         if( m_BoardSide[ii] )
         {
             delete m_BoardSide[ii];
-            m_BoardSide[ii] = NULL;
+            m_BoardSide[ii] = nullptr;
         }
     }
 
     m_Nrows = m_Ncols = 0;
 }
 
+// Initialize m_opWriteCell member to make the aLogicOp
+void AR_MATRIX::SetCellOperation( AR_MATRIX::CELL_OP aLogicOp )
+{
+    switch( aLogicOp )
+    {
+    default:
+    case WRITE_CELL:
+        m_opWriteCell = &AR_MATRIX::SetCell;
+        break;
 
-/**
- * Function PlaceCells
- * Initialize the matrix routing by setting obstacles for each occupied cell
- * a cell set to HOLE is an obstacle for tracks and vias
- * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only.
- * a cell set to CELL_is_EDGE is a frontier.
- * Tracks and vias having the same net code as net_code are skipped
- * (htey do not are obstacles)
- *
- * For single-sided Routing 1:
- * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP
- *
- * If flag == FORCE_PADS: all pads will be put in matrix as obstacles.
+    case WRITE_OR_CELL:
+        m_opWriteCell = &AR_MATRIX::OrCell;
+        break;
+
+    case WRITE_XOR_CELL:
+        m_opWriteCell = &AR_MATRIX::XorCell;
+        break;
+
+    case WRITE_AND_CELL:
+        m_opWriteCell = &AR_MATRIX::AndCell;
+        break;
+
+    case WRITE_ADD_CELL:
+        m_opWriteCell = &AR_MATRIX::AddCell;
+        break;
+    }
+}
+
+
+/* return the value stored in a cell
  */
-void PlaceCells( BOARD* aPcb, int net_code, int flag )
+AR_MATRIX::MATRIX_CELL AR_MATRIX::GetCell( int aRow, int aCol, int aSide )
 {
-    int     ux0 = 0, uy0 = 0, ux1, uy1, dx, dy;
-    int     marge, via_marge;
-    LSET    layerMask;
+    MATRIX_CELL* p;
+
+    p = m_BoardSide[aSide];
+    return p[aRow * m_Ncols + aCol];
+}
 
-    // use the default NETCLASS?
-    NETCLASSPTR nc = aPcb->GetDesignSettings().GetDefault();
 
-    int     trackWidth = nc->GetTrackWidth();
-    int     clearance  = nc->GetClearance();
-    int     viaSize    = nc->GetViaDiameter();
+/* basic cell operation : WRITE operation
+ */
+void AR_MATRIX::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
 
-    marge     = clearance + (trackWidth / 2);
-    via_marge = clearance + (viaSize / 2);
+    p = m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] = x;
+}
+
+
+/* basic cell operation : OR operation
+ */
+void AR_MATRIX::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] |= x;
+}
+
+
+/* basic cell operation : XOR operation
+ */
+void AR_MATRIX::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] ^= x;
+}
+
+
+/* basic cell operation : AND operation
+ */
+void AR_MATRIX::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] &= x;
+}
+
+
+/* basic cell operation : ADD operation
+ */
+void AR_MATRIX::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+{
+    MATRIX_CELL* p;
+
+    p = m_BoardSide[aSide];
+    p[aRow * m_Ncols + aCol] += x;
+}
+
+
+// fetch distance cell
+AR_MATRIX::DIST_CELL AR_MATRIX::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
+{
+    DIST_CELL* p;
+
+    p = m_DistSide[aSide];
+    return p[aRow * m_Ncols + aCol];
+}
+
+
+// store distance cell
+void AR_MATRIX::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
+{
+    DIST_CELL* p;
+
+    p = m_DistSide[aSide];
+    p[aRow * m_Ncols + aCol] = x;
+}
+
+
+// fetch direction cell
+int AR_MATRIX::GetDir( int aRow, int aCol, int aSide )
+{
+    DIR_CELL* p;
+
+    p = m_DirSide[aSide];
+    return (int) (p[aRow * m_Ncols + aCol]);
+}
+
+
+// store direction cell
+void AR_MATRIX::SetDir( int aRow, int aCol, int aSide, int x )
+{
+    DIR_CELL* p;
 
-    // Place PADS on matrix routing:
-    for( unsigned i = 0; i < aPcb->GetPadCount(); ++i )
+    p = m_DirSide[aSide];
+    p[aRow * m_Ncols + aCol] = (char) x;
+}
+
+/* The tables of distances and keep out areas are established on the basis of a
+ * 50 units grid size (the pitch between the cells is 50 units).
+ * The actual distance could be computed by a scaling factor, but this is
+ * not needed, we can use only reduced values
+ */
+
+ /* calculate approximate distance (manhattan distance)
+ */
+int AR_MATRIX::GetApxDist( int r1, int c1, int r2, int c2 )
+{
+    int d1, d2; /* row and column deltas */
+
+    if( ( d1 = r1 - r2 ) < 0 ) /* get absolute row delta */
+        d1 = -d1;
+
+    if( ( d2 = c1 - c2 ) < 0 ) /* get absolute column delta */
+        d2 = -d2;
+
+    return ( d1+d2 ) * 50;
+}
+
+
+/* distance to go thru a cell (en mils) */
+static const int dist[10][10] =
+{ /* OT=Otherside, OR=Origin (source) cell */
+/*..........N, NE,  E, SE,  S, SW,  W, NW,   OT, OR */
+/* N  */ { 50, 60, 35, 60, 99, 60, 35, 60,   12, 12 },
+/* NE */ { 60, 71, 60, 71, 60, 99, 60, 71,   23, 23 },
+/* E  */ { 35, 60, 50, 60, 35, 60, 99, 60,   12, 12 },
+/* SE */ { 60, 71, 60, 71, 60, 71, 60, 99,   23, 23 },
+/* S  */ { 99, 60, 35, 60, 50, 60, 35, 60,   12, 12 },
+/* SW */ { 60, 99, 60, 71, 60, 71, 60, 71,   23, 23 },
+/* W  */ { 35, 60, 99, 60, 35, 60, 50, 60,   12, 12 },
+/* NW */ { 60, 71, 60, 99, 60, 71, 60, 71,   23, 23 },
+
+/* OT */ { 12, 23, 12, 23, 12, 23, 12, 23,   99, 99 },
+/* OR */ { 99, 99, 99, 99, 99, 99, 99, 99,   99, 99 }
+};
+
+/* penalty for extraneous holes and corners, scaled by sharpness of turn */
+static const int penalty[10][10] =
+{ /* OT=Otherside, OR=Origin (source) cell */
+/*......... N, NE,  E, SE,  S, SW,  W, NW,   OT, OR */
+/* N  */ {  0,  5, 10, 15, 20, 15, 10,  5,   50, 0 },
+/* NE */ {  5,  0,  5, 10, 15, 20, 15, 10,   50, 0 },
+/* E  */ { 10,  5,  0,  5, 10, 15, 20, 15,   50, 0 },
+/* SE */ { 15, 10,  5,  0,  5, 10, 15, 20,   50, 0 },
+/* S  */ { 20, 15, 10,  5,  0,  5, 10, 15,   50, 0 },
+/* SW */ { 15, 20, 15, 10,  5,  0,  5, 10,   50, 0 },
+/* W  */ { 10, 15, 20, 15, 10,  5,  0,  5,   50, 0 },
+/* NW */ {  5, 10, 15, 20, 15, 10,  5,  0,   50, 0 },
+
+/* OT */ { 50, 50, 50, 50, 50, 50, 50, 50,  100, 0 },
+/* OR */ {  0,  0,  0,  0,  0,  0,  0,  0,    0, 0 }
+};
+
+/* penalty pour directions preferencielles */
+#define PN 20
+static const int dir_penalty_TOP[10][10] =
+{
+/* OT=Otherside, OR=Origin (source) cell */
+/*......... N, NE,  E, SE,  S, SW,  W, NW,   OT, OR */
+/* N  */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* NE */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* E  */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* SE */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* S  */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* SW */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* W  */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* NW */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+
+/* OT */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 },
+/* OR */ { PN,  0,  0,  0, PN,  0,  0,  0,    0, 0 }
+};
+
+static int dir_penalty_BOTTOM[10][10] =
+{
+/* OT=Otherside, OR=Origin (source) cell */
+/*......... N, NE,  E, SE,  S, SW,  W, NW,   OT, OR */
+/* N  */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* NE */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* E  */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* SE */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* S  */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* SW */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* W  */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* NW */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+
+/* OT */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 },
+/* OR */ {  0,  0, PN,  0,  0,  0, PN,  0,    0, 0 }
+};
+
+/*
+** x is the direction to enter the cell of interest.
+** y is the direction to exit the cell of interest.
+** z is the direction to really exit the cell, if y=FROM_OTHERSIDE.
+**
+** return the distance of the trace through the cell of interest.
+** the calculation is driven by the tables above.
+*/
+
+
+/* calculate distance (with penalty) of a trace through a cell
+*/
+int AR_MATRIX::CalcDist(int x,int y,int z ,int side  )
+{
+    int adjust, ldist;
+
+    adjust = 0; /* set if hole is encountered */
+
+    if( x == CELL_IS_EMPTY )
+        x = 10;
+
+    if( y == CELL_IS_EMPTY )
     {
-        D_PAD* pad = aPcb->GetPad( i );
+        y = 10;
+    }
+    else if( y == FROM_OTHERSIDE )
+    {
+        if( z == CELL_IS_EMPTY )
+            z = 10;
 
-        if( net_code != pad->GetNetCode() || (flag & FORCE_PADS) )
-        {
-            ::PlacePad( pad, HOLE, marge, WRITE_CELL );
-        }
+        adjust = penalty[x-1][z-1];
+    }
+
+    ldist = dist[x-1][y-1] + penalty[x-1][y-1] + adjust;
+
+    if( m_RouteCount > 1 )
+    {
+        if( side == AR_SIDE_BOTTOM )
+            ldist += dir_penalty_TOP[x-1][y-1];
+
+        if( side == AR_SIDE_TOP )
+            ldist += dir_penalty_BOTTOM[x-1][y-1];
+    }
+
+    return ldist * 10;
+}
+
+#define OP_CELL( layer, dy, dx )                                        \
+    {                                                                   \
+        if( layer == UNDEFINED_LAYER )                                  \
+        {                                                               \
+            WriteCell( dy, dx, AR_SIDE_BOTTOM, color );           \
+            if( m_RoutingLayersCount > 1 )                \
+                WriteCell( dy, dx, AR_SIDE_TOP, color );          \
+        }                                                               \
+        else                                                            \
+        {                                                               \
+            if( layer == m_routeLayerBottom )                         \
+                WriteCell( dy, dx, AR_SIDE_BOTTOM, color );       \
+            if( m_RoutingLayersCount > 1 )                \
+                if( layer == m_routeLayerTop )                        \
+                    WriteCell( dy, dx, AR_SIDE_TOP, color );      \
+        }                                                               \
+    }
+
+/* Fills all cells inside a segment
+ * half-width = lg, org = ux0,uy0 end = ux1,uy1
+ * coordinates are in PCB units
+ */
+void AR_MATRIX::drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
+                     int color, AR_MATRIX::CELL_OP op_logic )
+{
+    int64_t  row, col;
+    int64_t  inc;
+    int64_t  row_max, col_max, row_min, col_min;
+    int64_t  demi_pas;
+
+    int  cx, cy, dx, dy;
+
+
+    //printf("segmQcq %d %d %d %d\n", ux0, uy0, ux1, uy1);
+
+    SetCellOperation( op_logic );
+
+    // Make coordinate ux1 tj > ux0 to simplify calculations
+    if( ux1 < ux0 )
+    {
+        std::swap( ux1, ux0 );
+        std::swap( uy1, uy0 );
+    }
+
+    // Calculating the incrementing the Y axis
+    inc = 1;
+
+    if( uy1 < uy0 )
+        inc = -1;
+
+    demi_pas = m_GridRouting / 2;
+
+    col_min = ( ux0 - lg ) / m_GridRouting;
+
+    if( col_min < 0 )
+        col_min = 0;
+
+    col_max = ( ux1 + lg + demi_pas ) / m_GridRouting;
+
+    if( col_max > ( m_Ncols - 1 ) )
+        col_max = m_Ncols - 1;
+
+    if( inc > 0 )
+    {
+        row_min = ( uy0 - lg ) / m_GridRouting;
+        row_max = ( uy1 + lg + demi_pas ) / m_GridRouting;
+    }
+    else
+    {
+        row_min = ( uy1 - lg ) / m_GridRouting;
+        row_max = ( uy0 + lg + demi_pas ) / m_GridRouting;
+    }
+
+    if( row_min < 0 )
+        row_min = 0;
+
+    if( row_min > ( m_Nrows - 1 ) )
+        row_min = m_Nrows - 1;
+
+    if( row_max < 0 )
+        row_max = 0;
 
-        ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
+    if( row_max > ( m_Nrows - 1 ) )
+        row_max = m_Nrows - 1;
+
+    dx = ux1 - ux0;
+    dy = uy1 - uy0;
+
+    double angle;
+    if( dx )
+    {
+        angle = ArcTangente( dy, dx );
     }
+    else
+    {
+        angle = 900;
+
+        if( dy < 0 )
+            angle = -900;
+    }
+
+    RotatePoint( &dx, &dy, angle );   // dx = length, dy = 0
 
-    // Place outlines of modules on matrix routing, if they are on a copper layer
-    // or on the edge layer
 
-    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
+    //printf("col_min %d max %d row_min %d max %d\n", col_min, col_max, row_min, row_max);
+
+    for( col = col_min; col <= col_max; col++ )
     {
-        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
+        int64_t cxr;
+        cxr = ( col * m_GridRouting ) - ux0;
+
+        for( row = row_min; row <= row_max; row++ )
         {
-            switch( item->Type() )
-            {
-            case PCB_MODULE_EDGE_T:
+            cy = (row * m_GridRouting) - uy0;
+            cx = cxr;
+            RotatePoint( &cx, &cy, angle );
+
+            if( abs( cy ) > lg )
+                continue;             // The point is too far on the Y axis.
+
+            /* This point a test is close to the segment: the position
+             * along the X axis must be tested.
+             */
+            if( ( cx >= 0 ) && ( cx <= dx ) )
             {
-                EDGE_MODULE* edge = (EDGE_MODULE*) item;
-                EDGE_MODULE tmpEdge( *edge );
+                OP_CELL( layer, row, col );
+                continue;
+            }
 
-                if( tmpEdge.GetLayer() == Edge_Cuts )
-                    tmpEdge.SetLayer( UNDEFINED_LAYER );
+            // Examination of extremities are rounded.
+            if( ( cx < 0 ) && ( cx >= -lg ) )
+            {
+                if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
+                    OP_CELL( layer, row, col );
 
-                TraceSegmentPcb( &tmpEdge, HOLE, marge, WRITE_CELL );
-                TraceSegmentPcb( &tmpEdge, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
+                continue;
             }
-            break;
 
-            default:
-                break;
+            if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
+            {
+                if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) ) <= ( lg * lg ) )
+                    OP_CELL( layer, row, col );
+
+                continue;
             }
         }
     }
+}
 
-    // Place board outlines and texts on copper layers:
-    for( auto item : aPcb->Drawings() )
+/* Fills all cells of the routing matrix contained in the circle
+ * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle.
+ * coord are in PCB units.
+ */
+void AR_MATRIX::traceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
+                  int color, AR_MATRIX::CELL_OP op_logic )
+{
+    int radius, nb_segm;
+    int x0, y0,             // Starting point of the current segment trace.
+        x1, y1;             // End point.
+    int ii;
+    int angle;
+
+    radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
+
+    x0 = x1 = radius;
+    y0 = y1 = 0;
+
+    if( lg < 1 )
+        lg = 1;
+
+    nb_segm = ( 2 * radius ) / lg;
+
+    if( nb_segm < 5 )
+        nb_segm = 5;
+
+    if( nb_segm > 100 )
+        nb_segm = 100;
+
+    for( ii = 1; ii < nb_segm; ii++ )
     {
-        switch( item->Type() )
-        {
-        case PCB_LINE_T:
-            {
-                DRAWSEGMENT* DrawSegm;
+        angle = (3600 * ii) / nb_segm;
+        x1    = KiROUND( cosdecideg( radius, angle ) );
+        y1    = KiROUND( sindecideg( radius, angle ) );
+        drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
+        x0 = x1;
+        y0 = y1;
+    }
 
-                int          type_cell = HOLE;
-                DrawSegm = (DRAWSEGMENT*) item;
-                DRAWSEGMENT tmpSegm( DrawSegm );
+    drawSegmentQcq( x1 + ux0, y1 + uy0, ux0 + radius, uy0, lg, layer, color, op_logic );
+}
 
-                if( DrawSegm->GetLayer() == Edge_Cuts )
-                {
-                    tmpSegm.SetLayer( UNDEFINED_LAYER );
-                    type_cell |= CELL_is_EDGE;
-                }
+void AR_MATRIX::traceFilledCircle( int cx, int cy, int radius,
+        LSET aLayerMask,  int color,  AR_MATRIX::CELL_OP op_logic )
+{
+    int   row, col;
+    int   ux0, uy0, ux1, uy1;
+    int   row_max, col_max, row_min, col_min;
+    int   trace = 0;
+    double fdistmin, fdistx, fdisty;
+    int   tstwrite = 0;
+    int   distmin;
 
-                TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL );
-            }
-            break;
+    if( aLayerMask[m_routeLayerBottom] )
+        trace = 1;       // Trace on BOTTOM
 
-        case PCB_TEXT_T:
-            {
-                TEXTE_PCB* PtText = (TEXTE_PCB*) item;
+    if( aLayerMask[m_routeLayerTop] )
+        if( m_RoutingLayersCount > 1 )
+            trace |= 2;  // Trace on TOP
 
-                if( PtText->GetText().Length() == 0 )
-                    break;
+    if( trace == 0 )
+        return;
 
-                EDA_RECT textbox = PtText->GetTextBox( -1 );
-                ux0 = textbox.GetX();
-                uy0 = textbox.GetY();
-                dx  = textbox.GetWidth();
-                dy  = textbox.GetHeight();
+    SetCellOperation( op_logic );
 
-                // Put bounding box (rectangle) on matrix
-                dx /= 2;
-                dy /= 2;
+    cx -= GetBrdCoordOrigin().x;
+    cy -= GetBrdCoordOrigin().y;
 
-                ux1 = ux0 + dx;
-                uy1 = uy0 + dy;
+    distmin = radius;
 
-                ux0 -= dx;
-                uy0 -= dy;
+    // Calculate the bounding rectangle of the circle.
+    ux0 = cx - radius;
+    uy0 = cy - radius;
+    ux1 = cx + radius;
+    uy1 = cy + radius;
 
-                layerMask = LSET( PtText->GetLayer() );
+    // Calculate limit coordinates of cells belonging to the rectangle.
+    row_max = uy1 / m_GridRouting;
+    col_max = ux1 / m_GridRouting;
+    row_min = uy0 / m_GridRouting;  // if (uy0 > row_min*Board.m_GridRouting) row_min++;
+    col_min = ux0 / m_GridRouting;  // if (ux0 > col_min*Board.m_GridRouting) col_min++;
 
-                TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge,
-                                      uy1 + marge, PtText->GetTextAngle(),
-                                      layerMask, HOLE, WRITE_CELL );
+    if( row_min < 0 )
+        row_min = 0;
 
-                TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge,
-                                      ux1 + via_marge, uy1 + via_marge,
-                                      PtText->GetTextAngle(),
-                                      layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL );
-            }
-            break;
+    if( row_max >= (m_Nrows - 1) )
+        row_max = m_Nrows - 1;
+
+    if( col_min < 0 )
+        col_min = 0;
+
+    if( col_max >= (m_Ncols - 1) )
+        col_max = m_Ncols - 1;
+
+    // Calculate coordinate limits of cell belonging to the rectangle.
+    if( row_min > row_max )
+        row_max = row_min;
+
+    if( col_min > col_max )
+        col_max = col_min;
+
+    fdistmin = (double) distmin * distmin;
+
+    for( row = row_min; row <= row_max; row++ )
+    {
+        fdisty  = (double) ( cy - ( row * m_GridRouting ) );
+        fdisty *= fdisty;
+
+        for( col = col_min; col <= col_max; col++ )
+        {
+            fdistx  = (double) ( cx - ( col * m_GridRouting ) );
+            fdistx *= fdistx;
+
+            if( fdistmin <= ( fdistx + fdisty ) )
+                continue;
+
+            if( trace & 1 )
+                WriteCell( row, col, AR_SIDE_BOTTOM, color );
 
-        default:
-            break;
+            if( trace & 2 )
+                WriteCell( row, col, AR_SIDE_TOP, color );
+
+            tstwrite = 1;
         }
     }
 
-    // Put tracks and vias on matrix
-    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
+    if( tstwrite )
+        return;
+
+    /* If no cell has been written, it affects the 4 neighboring diagonal
+     * (Adverse event: pad off grid in the center of the 4 neighboring
+     * diagonal) */
+    distmin  = m_GridRouting / 2 + 1;
+    fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally
+
+    for( row = row_min; row <= row_max; row++ )
     {
-        if( net_code == track->GetNetCode() )
-            continue;
+        fdisty  = (double) ( cy - ( row * m_GridRouting ) );
+        fdisty *= fdisty;
+
+        for( col = col_min; col <= col_max; col++ )
+        {
+            fdistx  = (double) ( cx - ( col * m_GridRouting ) );
+            fdistx *= fdistx;
+
+            if( fdistmin <= ( fdistx + fdisty ) )
+                continue;
+
+            if( trace & 1 )
+                WriteCell( row, col, AR_SIDE_BOTTOM, color );
 
-        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
-        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
+            if( trace & 2 )
+                WriteCell( row, col, AR_SIDE_TOP, color );
+        }
     }
 }
 
 
-int Build_Work( BOARD* Pcb )
+/* Fills all routing matrix cells contained in the arc
+ * angle = ArcAngle, half-width lg
+ * center = ux0,uy0, starting at ux1, uy1.  Coordinates are in
+ * PCB units.
+ */
+void AR_MATRIX::traceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg,
+               LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic )
 {
-    RATSNEST_ITEM*  pt_rats;
-    D_PAD*          pt_pad;
-    int             r1, r2, c1, c2, current_net_code;
-    RATSNEST_ITEM*  pt_ch;
-    int             demi_pas = RoutingMatrix.m_GridRouting / 2;
-    wxString        msg;
+    int radius, nb_segm;
+    int x0, y0,             // Starting point of the current segment trace
+        x1, y1;             // End point
+    int ii;
+    double angle, StAngle;
+
+
+    radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
+
+    x0 = ux1 - ux0;
+    y0 = uy1 - uy0;
+    StAngle = ArcTangente( uy1 - uy0, ux1 - ux0 );
+
+    if( lg < 1 )
+        lg = 1;
 
-    InitWork(); // clear work list
-    int cellCount = 0;
+    nb_segm = ( 2 * radius ) / lg;
+    nb_segm = ( nb_segm * std::abs( ArcAngle ) ) / 3600;
 
-    for( unsigned ii = 0; ii < Pcb->GetRatsnestsCount(); ii++ )
+    if( nb_segm < 5 )
+        nb_segm = 5;
+
+    if( nb_segm > 100 )
+        nb_segm = 100;
+
+    for( ii = 1; ii <= nb_segm; ii++ )
     {
-        pt_rats = &Pcb->m_FullRatsnest[ii];
+        angle  = ( ArcAngle * ii ) / nb_segm;
+        angle += StAngle;
+
+        NORMALIZE_ANGLE_POS( angle );
+
+        x1 = KiROUND( cosdecideg( radius, angle ) );
+        y1 = KiROUND( cosdecideg( radius, angle ) );
+        drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
+        x0 = x1;
+        y0 = y1;
+    }
+}
+
+
+void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
+                           double angle, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
+{
+    int  row, col;
+    int  cx, cy;    // Center of rectangle
+    int  radius;     // Radius of the circle
+    int  row_min, row_max, col_min, col_max;
+    int  rotrow, rotcol;
+    int  trace = 0;
+
+    if( aLayerMask[m_routeLayerBottom] )
+        trace = 1;     // Trace on BOTTOM
+
+    if( aLayerMask[m_routeLayerTop] )
+    {
+        if( m_RoutingLayersCount > 1 )
+            trace |= 2;  // Trace on TOP
+    }
+
+    if( trace == 0 )
+        return;
+
+    SetCellOperation( op_logic );
+
+    ux0 -= GetBrdCoordOrigin().x;
+    uy0 -= GetBrdCoordOrigin().y;
+    ux1 -= GetBrdCoordOrigin().x;
+    uy1 -= GetBrdCoordOrigin().y;
+
+    cx    = (ux0 + ux1) / 2;
+    cy    = (uy0 + uy1) / 2;
+    radius = KiROUND( Distance( ux0, uy0, cx, cy ) );
+
+    // Calculating coordinate limits belonging to the rectangle.
+    row_max = ( cy + radius ) / m_GridRouting;
+    col_max = ( cx + radius ) / m_GridRouting;
+    row_min = ( cy - radius ) / m_GridRouting;
+
+    if( uy0 > row_min * m_GridRouting )
+        row_min++;
+
+    col_min = ( cx - radius ) / m_GridRouting;
+
+    if( ux0 > col_min * m_GridRouting )
+        col_min++;
+
+    if( row_min < 0 )
+        row_min = 0;
+
+    if( row_max >= ( m_Nrows - 1 ) )
+        row_max = m_Nrows - 1;
+
+    if( col_min < 0 )
+        col_min = 0;
+
+    if( col_max >= ( m_Ncols - 1 ) )
+        col_max = m_Ncols - 1;
+
+    for( row = row_min; row <= row_max; row++ )
+    {
+        for( col = col_min; col <= col_max; col++ )
+        {
+            rotrow = row * m_GridRouting;
+            rotcol = col * m_GridRouting;
+            RotatePoint( &rotcol, &rotrow, cx, cy, -angle );
+
+            if( rotrow <= uy0 )
+                continue;
+
+            if( rotrow >= uy1 )
+                continue;
+
+            if( rotcol <= ux0 )
+                continue;
+
+            if( rotcol >= ux1 )
+                continue;
+
+            if( trace & 1 )
+                WriteCell( row, col, AR_SIDE_BOTTOM, color );
+
+            if( trace & 2 )
+                WriteCell( row, col, AR_SIDE_TOP, color );
+        }
+    }
+}
+
+
+void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
+                           LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
+{
+    int  row, col;
+    int  row_min, row_max, col_min, col_max;
+    int  trace = 0;
+
+    if( aLayerMask[m_routeLayerBottom] )
+        trace = 1;     // Trace on BOTTOM
+
+    if( aLayerMask[m_routeLayerTop] && m_RoutingLayersCount > 1 )
+        trace |= 2;    // Trace on TOP
+
+    if( trace == 0 )
+        return;
+
+    SetCellOperation( op_logic );
+
+    ux0 -= GetBrdCoordOrigin().x;
+    uy0 -= GetBrdCoordOrigin().y;
+    ux1 -= GetBrdCoordOrigin().x;
+    uy1 -= GetBrdCoordOrigin().y;
+
+    // Calculating limits coord cells belonging to the rectangle.
+    row_max = uy1 / m_GridRouting;
+    col_max = ux1 / m_GridRouting;
+    row_min = uy0 / m_GridRouting;
 
-        /* We consider here only ratsnest that are active ( obviously not yet routed)
-         * and routables (that are not yet attempt to be routed and fail
-         */
-        if( (pt_rats->m_Status & CH_ACTIF) == 0 )
-            continue;
+    if( uy0 > row_min * m_GridRouting )
+        row_min++;
 
-        if( pt_rats->m_Status & CH_UNROUTABLE )
-            continue;
+    col_min = ux0 / m_GridRouting;
 
-        if( (pt_rats->m_Status & CH_ROUTE_REQ) == 0 )
-            continue;
+    if( ux0 > col_min * m_GridRouting )
+        col_min++;
 
-        pt_pad = pt_rats->m_PadStart;
+    if( row_min < 0 )
+        row_min = 0;
 
-        current_net_code = pt_pad->GetNetCode();
-        pt_ch = pt_rats;
+    if( row_max >= ( m_Nrows - 1 ) )
+        row_max = m_Nrows - 1;
 
-        r1 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY() + demi_pas )
-            / RoutingMatrix.m_GridRouting;
+    if( col_min < 0 )
+        col_min = 0;
 
-        if( r1 < 0 || r1 >= RoutingMatrix.m_Nrows )
+    if( col_max >= ( m_Ncols - 1 ) )
+        col_max = m_Ncols - 1;
+
+    for( row = row_min; row <= row_max; row++ )
+    {
+        for( col = col_min; col <= col_max; col++ )
         {
-            msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r1,
-                        pt_pad->GetPosition().y, RoutingMatrix.m_BrdBox.GetY() );
-            wxMessageBox( msg );
-            return 0;
+            if( trace & 1 )
+                WriteCell( row, col, AR_SIDE_BOTTOM, color );
+
+            if( trace & 2 )
+                WriteCell( row, col, AR_SIDE_TOP, color );
         }
+    }
+}
 
-        c1 = ( pt_pad->GetPosition().x - RoutingMatrix.m_BrdBox.GetX() + demi_pas ) / RoutingMatrix.m_GridRouting;
 
-        if( c1 < 0 || c1 >= RoutingMatrix.m_Ncols )
+/* Draws a line, if layer = -1 on all layers
+ */
+void AR_MATRIX::tracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic  )
+{
+    int  dx, dy, lim;
+    int  cumul, inc, il, delta;
+
+    SetCellOperation( op_logic );
+
+    if( x0 == x1 )  // Vertical.
+    {
+        if( y1 < y0 )
+            std::swap( y0, y1 );
+
+        dy  = y0 / m_GridRouting;
+        lim = y1 / m_GridRouting;
+        dx  = x0 / m_GridRouting;
+
+        // Clipping limits of board.
+        if( ( dx < 0 ) || ( dx >= m_Ncols ) )
+            return;
+
+        if( dy < 0 )
+            dy = 0;
+
+        if( lim >= m_Nrows )
+            lim = m_Nrows - 1;
+
+        for( ; dy <= lim; dy++ )
         {
-            msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c1,
-                        pt_pad->GetPosition().x, RoutingMatrix.m_BrdBox.GetX() );
-            wxMessageBox( msg );
-            return 0;
+            OP_CELL( layer, dy, dx );
         }
 
-        pt_pad = pt_rats->m_PadEnd;
+        return;
+    }
+
+    if( y0 == y1 )  // Horizontal
+    {
+        if( x1 < x0 )
+            std::swap( x0, x1 );
+
+        dx  = x0 / m_GridRouting;
+        lim = x1 / m_GridRouting;
+        dy  = y0 / m_GridRouting;
+
+        // Clipping limits of board.
+        if( ( dy < 0 ) || ( dy >= m_Nrows ) )
+            return;
 
-        r2 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY()
-               + demi_pas ) / RoutingMatrix.m_GridRouting;
+        if( dx < 0 )
+            dx = 0;
 
-        if( r2 < 0 || r2 >= RoutingMatrix.m_Nrows )
+        if( lim >= m_Ncols )
+            lim = m_Ncols - 1;
+
+        for( ; dx <= lim; dx++ )
         {
-            msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r2,
-                        pt_pad->GetPosition().y, RoutingMatrix.m_BrdBox.GetY() );
-            wxMessageBox( msg );
-            return 0;
+            OP_CELL( layer, dy, dx );
         }
 
-        c2 = ( pt_pad->GetPosition().x - RoutingMatrix.m_BrdBox.GetX() + demi_pas )
-             / RoutingMatrix.m_GridRouting;
+        return;
+    }
 
-        if( c2 < 0 || c2 >= RoutingMatrix.m_Ncols )
+    // Here is some perspective: using the algorithm LUCAS.
+    if( abs( x1 - x0 ) >= abs( y1 - y0 ) ) // segment slightly inclined/
+    {
+        if( x1 < x0 )
         {
-            msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c2,
-                        pt_pad->GetPosition().x, RoutingMatrix.m_BrdBox.GetX() );
-            wxMessageBox( msg );
-            return 0;
+            std::swap( x1, x0 );
+            std::swap( y1, y0 );
         }
 
-        SetWork( r1, c1, current_net_code, r2, c2, pt_ch, 0 );
-        cellCount++;
+        dx  = x0 / m_GridRouting;
+        lim = x1 / m_GridRouting;
+        dy  = y0 / m_GridRouting;
+        inc = 1;
+
+        if( y1 < y0 )
+            inc = -1;
+
+        il    = lim - dx; cumul = il / 2;
+        delta = abs( y1 - y0 ) / m_GridRouting;
+
+        for( ; dx <= lim; )
+        {
+            if( ( dx >= 0 ) && ( dy >= 0 ) &&
+                ( dx < m_Ncols ) &&
+                ( dy < m_Nrows ) )
+            {
+                OP_CELL( layer, dy, dx );
+            }
+
+            dx++;
+            cumul += delta;
+
+            if( cumul > il )
+            {
+                cumul -= il;
+                dy    += inc;
+            }
+        }
     }
+    else
+    {
+        if( y1 < y0 )
+        {
+            std::swap( x1, x0 );
+            std::swap( y1, y0 );
+        }
+
+        dy  = y0 / m_GridRouting;
+        lim = y1 / m_GridRouting;
+        dx  = x0 / m_GridRouting;
+        inc = 1;
+
+        if( x1 < x0 )
+            inc = -1;
+
+        il    = lim - dy;
+        cumul = il / 2;
+        delta = abs( x1 - x0 ) / m_GridRouting;
 
-    SortWork();
-    return cellCount;
+        for( ; dy <= lim; )
+        {
+            if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < m_Ncols ) && ( dy < m_Nrows ) )
+            {
+                OP_CELL( layer, dy, dx );
+            }
+
+            dy++;
+            cumul += delta;
+
+            if( cumul > il )
+            {
+                cumul -= il;
+                dx    += inc;
+            }
+        }
+    }
 }
 
-// Initialize m_opWriteCell member to make the aLogicOp
-void MATRIX_ROUTING_HEAD::SetCellOperation( int aLogicOp )
+void AR_MATRIX::TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic )
 {
-    switch( aLogicOp )
-    {
-    default:
-    case WRITE_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::SetCell;
-        break;
+    int half_width = ( pt_segm->GetWidth() / 2 ) + marge;
 
-    case WRITE_OR_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::OrCell;
-        break;
+    // Calculate the bounding rectangle of the segment (if H, V or Via)
+    int ux0 = pt_segm->GetStart().x - GetBrdCoordOrigin().x;
+    int uy0 = pt_segm->GetStart().y - GetBrdCoordOrigin().y;
+    int ux1 = pt_segm->GetEnd().x - GetBrdCoordOrigin().x;
+    int uy1 = pt_segm->GetEnd().y - GetBrdCoordOrigin().y;
 
-    case WRITE_XOR_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::XorCell;
+    //printf("traceSegm %d %d %d %d\n", ux0, uy0, ux1, uy1);
+
+    LAYER_NUM layer = pt_segm->GetLayer();
+
+    //if( color == VIA_IMPOSSIBLE )
+        layer = UNDEFINED_LAYER;
+
+
+    switch( pt_segm->GetShape() )
+    {
+    // The segment is here a straight line or a circle or an arc.:
+    case S_CIRCLE:
+        traceCircle( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
         break;
 
-    case WRITE_AND_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::AndCell;
+    case S_ARC:
+        traceArc( ux0, uy0, ux1, uy1, pt_segm->GetAngle(), half_width, layer, color, op_logic );
         break;
 
-    case WRITE_ADD_CELL:
-        m_opWriteCell = &MATRIX_ROUTING_HEAD::AddCell;
+    // The segment is here a line segment.
+    default:
+        drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
         break;
     }
 }
 
-
-/* return the value stored in a cell
- */
-MATRIX_CELL MATRIX_ROUTING_HEAD::GetCell( int aRow, int aCol, int aSide )
+void AR_MATRIX::TraceSegmentPcb( TRACK* aTrack, int color, int marge, AR_MATRIX::CELL_OP op_logic )
 {
-    MATRIX_CELL* p;
+    int half_width = ( aTrack->GetWidth() / 2 ) + marge;
 
-    p = RoutingMatrix.m_BoardSide[aSide];
-    return p[aRow * m_Ncols + aCol];
-}
+    // Test if VIA (filled circle need to be drawn)
+    if( aTrack->Type() == PCB_VIA_T )
+    {
+        LSET layer_mask;
 
+        if( aTrack->IsOnLayer( m_routeLayerBottom ) )
+            layer_mask.set( m_routeLayerBottom );
 
-/* basic cell operation : WRITE operation
- */
-void MATRIX_ROUTING_HEAD::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
+        if( aTrack->IsOnLayer( m_routeLayerTop ) )
+        {
+            if( !layer_mask.any() )
+                layer_mask = LSET( m_routeLayerTop );
+            else
+                layer_mask.set();
+        }
 
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] = x;
-}
+        if( color == VIA_IMPOSSIBLE )
+            layer_mask.set();
 
+        if( layer_mask.any() )
+            traceFilledCircle( aTrack->GetStart().x, aTrack->GetStart().y,
+                               half_width, layer_mask, color, op_logic );
+    }
+    else
+    {
+        // Calculate the bounding rectangle of the segment
+        int ux0 = aTrack->GetStart().x - GetBrdCoordOrigin().x;
+        int uy0 = aTrack->GetStart().y - GetBrdCoordOrigin().y;
+        int ux1 = aTrack->GetEnd().x - GetBrdCoordOrigin().x;
+        int uy1 = aTrack->GetEnd().y - GetBrdCoordOrigin().y;
 
-/* basic cell operation : OR operation
- */
-void MATRIX_ROUTING_HEAD::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
+        // Ordinary track
+        PCB_LAYER_ID layer = aTrack->GetLayer();
 
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] |= x;
+        if( color == VIA_IMPOSSIBLE )
+            layer = UNDEFINED_LAYER;
+
+        drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
+    }
 }
 
 
-/* basic cell operation : XOR operation
+
+/**
+ * Function CreateKeepOutRectangle
+ * builds the cost map:
+ * Cells ( in Dist map ) inside the rect x0,y0 a x1,y1 are
+ *  incremented by value aKeepOut
+ *  Cell outside this rectangle, but inside the rectangle
+ *  x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value
+ *  (aKeepOut ... 0). The decreasing value depends on the distance to the first rectangle
+ *  Therefore the cost is high in rect x0,y0 to x1,y1, and decrease outside this rectangle
  */
-void MATRIX_ROUTING_HEAD::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
+void AR_MATRIX::CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
+                             int marge, int aKeepOut, LSET aLayerMask )
 {
-    MATRIX_CELL* p;
+    int         row, col;
+    int         row_min, row_max, col_min, col_max, pmarge;
+    int         trace = 0;
+    DIST_CELL   data, LocalKeepOut;
+    int         lgain, cgain;
 
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] ^= x;
-}
+    if( aLayerMask[m_routeLayerBottom] )
+        trace = 1; // Trace on bottom layer.
 
+    if( aLayerMask[m_routeLayerTop] && m_RoutingLayersCount )
+        trace |= 2; // Trace on top layer.
 
-/* basic cell operation : AND operation
- */
-void MATRIX_ROUTING_HEAD::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
+    if( trace == 0 )
+        return;
 
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] &= x;
-}
+    ux0 -= m_BrdBox.GetX();
+    uy0 -= m_BrdBox.GetY();
+    ux1 -= m_BrdBox.GetX();
+    uy1 -= m_BrdBox.GetY();
 
+    ux0 -= marge; ux1 += marge;
+    uy0 -= marge; uy1 += marge;
 
-/* basic cell operation : ADD operation
- */
-void MATRIX_ROUTING_HEAD::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
-{
-    MATRIX_CELL* p;
+    pmarge = marge / m_GridRouting;
 
-    p = RoutingMatrix.m_BoardSide[aSide];
-    p[aRow * m_Ncols + aCol] += x;
-}
+    if( pmarge < 1 )
+        pmarge = 1;
 
+    // Calculate the coordinate limits of the rectangle.
+    row_max = uy1 / m_GridRouting;
+    col_max = ux1 / m_GridRouting;
+    row_min = uy0 / m_GridRouting;
 
-// fetch distance cell
-DIST_CELL MATRIX_ROUTING_HEAD::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
-{
-    DIST_CELL* p;
+    if( uy0 > row_min * m_GridRouting )
+        row_min++;
 
-    p = RoutingMatrix.m_DistSide[aSide];
-    return p[aRow * m_Ncols + aCol];
-}
+    col_min = ux0 / m_GridRouting;
 
+    if( ux0 > col_min * m_GridRouting )
+        col_min++;
 
-// store distance cell
-void MATRIX_ROUTING_HEAD::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
-{
-    DIST_CELL* p;
+    if( row_min < 0 )
+        row_min = 0;
 
-    p = RoutingMatrix.m_DistSide[aSide];
-    p[aRow * m_Ncols + aCol] = x;
-}
+    if( row_max >= (m_Nrows - 1) )
+        row_max = m_Nrows - 1;
 
+    if( col_min < 0 )
+        col_min = 0;
 
-// fetch direction cell
-int MATRIX_ROUTING_HEAD::GetDir( int aRow, int aCol, int aSide )
-{
-    DIR_CELL* p;
+    if( col_max >= (m_Ncols - 1) )
+        col_max = m_Ncols - 1;
 
-    p = RoutingMatrix.m_DirSide[aSide];
-    return (int) (p[aRow * m_Ncols + aCol]);
-}
+    for( row = row_min; row <= row_max; row++ )
+    {
+        lgain = 256;
 
+        if( row < pmarge )
+            lgain = ( 256 * row ) / pmarge;
+        else if( row > row_max - pmarge )
+            lgain = ( 256 * ( row_max - row ) ) / pmarge;
 
-// store direction cell
-void MATRIX_ROUTING_HEAD::SetDir( int aRow, int aCol, int aSide, int x )
+        for( col = col_min; col <= col_max; col++ )
+        {
+            // RoutingMatrix Dist map containt the "cost" of the cell
+            // at position (row, col)
+            // in autoplace this is the cost of the cell, when
+            // a footprint overlaps it, near a "master" footprint
+            // this cost is hight near the "master" footprint
+            // and decrease with the distance
+            cgain = 256;
+            LocalKeepOut = aKeepOut;
+
+            if( col < pmarge )
+                cgain = ( 256 * col ) / pmarge;
+            else if( col > col_max - pmarge )
+                cgain = ( 256 * ( col_max - col ) ) / pmarge;
+
+            cgain = ( cgain * lgain ) / 256;
+
+            if( cgain != 256 )
+                LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
+
+            if( trace & 1 )
+            {
+                data = GetDist( row, col, AR_SIDE_BOTTOM ) + LocalKeepOut;
+                SetDist( row, col, AR_SIDE_BOTTOM, data );
+            }
+
+            if( trace & 2 )
+            {
+                data    = GetDist( row, col, AR_SIDE_TOP );
+                data    = std::max( data, LocalKeepOut );
+                SetDist( row, col, AR_SIDE_TOP, data );
+            }
+        }
+    }
+}
+
+void AR_MATRIX::PlacePad( D_PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic )
 {
-    DIR_CELL* p;
+    int     dx, dy;
+    wxPoint shape_pos = aPad->ShapePos();
 
-    p = RoutingMatrix.m_DirSide[aSide];
-    p[aRow * m_Ncols + aCol] = (char) x;
+    dx = aPad->GetSize().x / 2;
+    dx += marge;
+
+    if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
+    {
+        traceFilledCircle( shape_pos.x, shape_pos.y, dx,
+                           aPad->GetLayerSet(), color, op_logic );
+        return;
+    }
+
+    dy = aPad->GetSize().y / 2;
+    dy += marge;
+
+    if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
+    {
+        dx += abs( aPad->GetDelta().y ) / 2;
+        dy += abs( aPad->GetDelta().x ) / 2;
+    }
+
+    // The pad is a rectangle ( horizontal or vertical )
+    if( int( aPad->GetOrientation() ) % 900 == 0 )
+    {
+        // Orientation turned 90 deg.
+        if( aPad->GetOrientation() == 900  ||  aPad->GetOrientation() == 2700 )
+        {
+            std::swap( dx, dy );
+        }
+
+        TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy,
+                              shape_pos.x + dx, shape_pos.y + dy,
+                              aPad->GetLayerSet(), color, op_logic );
+    }
+    else
+    {
+        TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy,
+                              shape_pos.x + dx, shape_pos.y + dy,
+                              aPad->GetOrientation(),
+                              aPad->GetLayerSet(), color, op_logic );
+    }
 }
diff --git a/pcbnew/autorouter/ar_matrix.h b/pcbnew/autorouter/ar_matrix.h
new file mode 100644
index 0000000..c453fa3
--- /dev/null
+++ b/pcbnew/autorouter/ar_matrix.h
@@ -0,0 +1,178 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxx
+ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ *
+ * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+
+#ifndef __AR_MATRIX_H
+#define __AR_MATRIX_H
+
+#include <eda_rect.h>
+#include <layers_id_colors_and_visibility.h>
+
+class DRAWSEGMENT;
+class TRACK;
+class D_PAD;
+class MODULE;
+
+#define AR_MAX_ROUTING_LAYERS_COUNT 2
+
+#define AR_SIDE_TOP     0
+#define AR_SIDE_BOTTOM  1
+
+/**
+ * class AR_MATRIX
+ * handle the matrix routing that describes the actual board
+ */
+class AR_MATRIX
+{
+public:
+    typedef unsigned char MATRIX_CELL;
+    typedef int  DIST_CELL;
+    typedef char DIR_CELL;
+ 
+    MATRIX_CELL* m_BoardSide[AR_MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides
+    DIST_CELL*   m_DistSide[AR_MAX_ROUTING_LAYERS_COUNT];  // the image map of 2 board sides:
+                                                        // distance to cells
+    DIR_CELL*    m_DirSide[AR_MAX_ROUTING_LAYERS_COUNT];   // the image map of 2 board sides:
+                                                        // pointers back to source
+    bool         m_InitMatrixDone;
+    int          m_RoutingLayersCount;          // Number of layers for autorouting (0 or 1)
+    int          m_GridRouting;                 // Size of grid for autoplace/autoroute
+    EDA_RECT     m_BrdBox;                      // Actual board bounding box
+    int          m_Nrows, m_Ncols;              // Matrix size
+    int          m_MemSize;                     // Memory requirement, just for statistics
+    int          m_RouteCount;                  // Number of routes
+
+    PCB_LAYER_ID m_routeLayerTop;
+    PCB_LAYER_ID m_routeLayerBottom;
+    
+
+private:
+    // a pointer to the current selected cell operation
+    void        (AR_MATRIX::* m_opWriteCell)( int aRow, int aCol,
+                                                        int aSide, MATRIX_CELL aCell);
+
+public:
+
+    enum CELL_OP
+    {
+     WRITE_CELL     = 0,
+     WRITE_OR_CELL  = 1,
+     WRITE_XOR_CELL = 2,
+     WRITE_AND_CELL = 3,
+     WRITE_ADD_CELL = 4
+    };
+
+    AR_MATRIX();
+    ~AR_MATRIX();
+
+    void WriteCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell)
+    {
+        (*this.*m_opWriteCell)( aRow, aCol, aSide, aCell );
+    }
+
+    /**
+     * function GetBrdCoordOrigin
+     * @return the board coordinate corresponding to the
+     * routing matrix origin ( board coordinate offset )
+     */
+    wxPoint GetBrdCoordOrigin()
+    {
+        return m_BrdBox.GetOrigin();
+    }
+
+    /**
+     * Function ComputeMatrixSize
+     * calculates the number of rows and columns of dimensions of \a aPcb for routing and
+     * automatic calculation of area.
+     * @param aPcb = the physical board
+     * @param aUseBoardEdgesOnly = true to use board edges only,
+     *                           = false to use the full board bounding box (default)
+     */
+    bool ComputeMatrixSize( const EDA_RECT& aBoundingBox );
+
+    /**
+     * Function InitBoard
+     * initializes the data structures.
+     *
+     * @return the amount of memory used or -1 if default.
+     */
+    int InitRoutingMatrix();
+
+    void UnInitRoutingMatrix();
+
+    // Initialize WriteCell to make the aLogicOp
+    void SetCellOperation( CELL_OP aLogicOp );
+
+    // functions to read/write one cell ( point on grid routing matrix:
+    MATRIX_CELL GetCell( int aRow, int aCol, int aSide);
+    void SetCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell);
+    void OrCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell);
+    void XorCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell);
+    void AndCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell);
+    void AddCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell);
+    DIST_CELL GetDist( int aRow, int aCol, int aSide );
+    void SetDist( int aRow, int aCol, int aSide, DIST_CELL );
+    int GetDir( int aRow, int aCol, int aSide );
+    void SetDir( int aRow, int aCol, int aSide, int aDir);
+
+    // calculate distance (with penalty) of a trace through a cell
+    int CalcDist(int x,int y,int z ,int side );
+
+    // calculate approximate distance (manhattan distance)
+    int GetApxDist( int r1, int c1, int r2, int c2 );
+
+
+    void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic );
+    void TraceSegmentPcb( TRACK* aTrack, int color, int marge, AR_MATRIX::CELL_OP op_logic );
+    void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
+                             int marge, int aKeepOut, LSET aLayerMask );
+    void PlacePad( D_PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic );
+    void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
+                           double angle, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic );
+    void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
+                           LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic );
+
+private:
+
+    void drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
+                     int color, CELL_OP op_logic );
+
+    void traceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
+                  int color, AR_MATRIX::CELL_OP op_logic );
+    void traceFilledCircle( int cx, int cy, int radius,
+                LSET aLayerMask,  int color,  AR_MATRIX::CELL_OP op_logic );
+    void traceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg,
+               LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic );
+    
+    
+    void tracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic  );
+                           
+
+
+};
+
+#endif
diff --git a/pcbnew/autorouter/autoplacer_tool.cpp b/pcbnew/autorouter/autoplacer_tool.cpp
new file mode 100644
index 0000000..480d45b
--- /dev/null
+++ b/pcbnew/autorouter/autoplacer_tool.cpp
@@ -0,0 +1,126 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+
+#include <gal/graphics_abstraction_layer.h>
+#include <class_draw_panel_gal.h>
+#include <view/view_controls.h>
+#include <view/view.h>
+#include <tool/tool_manager.h>
+#include <board_commit.h>
+#include <confirm.h>
+#include <preview_items/two_point_geom_manager.h>
+#include <preview_items/centreline_rect_item.h>
+
+// For frame ToolID values
+#include <pcbnew_id.h>
+
+// For action icons
+#include <bitmaps.h>
+
+#include <class_board_item.h>
+#include <class_module.h>
+#include <tools/pcb_actions.h>
+#include <tools/selection_tool.h>
+#include <tools/tool_event_utils.h>
+
+#include <widgets/progress_reporter.h>
+
+#include "autoplacer_tool.h"
+#include "ar_autoplacer.h"
+
+
+TOOL_ACTION PCB_ACTIONS::autoplaceSelectedComponents(
+        "pcbnew.Autoplacer.autoplaceSelected",
+        AS_GLOBAL, 0,
+        _( "Auto-place selected components" ), _( "Performs automatic placement of selected components" )
+        );
+
+TOOL_ACTION PCB_ACTIONS::autoplaceOffboardComponents(
+        "pcbnew.Autoplacer.autoplaceOffboard",
+        AS_GLOBAL, 0,
+        _( "Auto-place off-board components" ), _( "Performs automatic placement of components outside board area" )
+         );
+
+AUTOPLACE_TOOL::AUTOPLACE_TOOL() :
+        PCB_TOOL( "pcbnew.Autoplacer" )
+{
+}
+
+
+AUTOPLACE_TOOL::~AUTOPLACE_TOOL()
+{}
+
+int AUTOPLACE_TOOL::autoplace( std::vector<MODULE*>& aModules, bool aPlaceOffboard )
+{
+    auto overlay = view()->MakeOverlay();
+
+    Activate();
+
+    AR_AUTOPLACER autoplacer( board() );
+
+    BOARD_COMMIT commit( frame() );
+
+    autoplacer.SetOverlay( overlay );
+    
+    std::unique_ptr<WX_PROGRESS_REPORTER> progressReporter(
+            new WX_PROGRESS_REPORTER( frame(), _( "Autoplace Components" ), 1 )
+            );
+
+    autoplacer.SetProgressReporter( progressReporter.get() );
+    auto result = autoplacer.AutoplaceModules( aModules, &commit, aPlaceOffboard );
+
+    if( result == AR_COMPLETED )
+        commit.Push( _("Autoplace components") );
+    else
+        commit.Revert();
+    
+    return 0;    
+}
+
+int AUTOPLACE_TOOL::autoplaceSelected( const TOOL_EVENT& aEvent )
+{
+    std::vector<MODULE*> mods;
+
+    for ( auto item : selection() )
+    {
+        if ( item->Type() == PCB_MODULE_T )
+            mods.push_back( static_cast<MODULE*>( item ) );
+    }
+    
+    return autoplace( mods, false );
+}
+
+int AUTOPLACE_TOOL::autoplaceOffboard( const TOOL_EVENT& aEvent )
+{
+    std::vector<MODULE*> mods;
+
+    return autoplace( mods, true );
+}
+
+
+void AUTOPLACE_TOOL::setTransitions()
+{
+    Go( &AUTOPLACE_TOOL::autoplaceSelected, PCB_ACTIONS::autoplaceSelectedComponents.MakeEvent() );
+    Go( &AUTOPLACE_TOOL::autoplaceOffboard, PCB_ACTIONS::autoplaceOffboardComponents.MakeEvent() );
+}
diff --git a/pcbnew/autorouter/autoplacer_tool.h b/pcbnew/autorouter/autoplacer_tool.h
new file mode 100644
index 0000000..57eee27
--- /dev/null
+++ b/pcbnew/autorouter/autoplacer_tool.h
@@ -0,0 +1,52 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef TOOLS_AUTOPLACE_TOOL_H
+#define TOOLS_AUTOPLACE_TOOL_H
+
+#include <tools/pcb_tool.h>
+
+#
+/**
+ * Class AUTOPLACE_TOOL
+ *
+ * Tool responsible for automagic placement of components.
+ */
+class AUTOPLACE_TOOL : public PCB_TOOL
+{
+public:
+    AUTOPLACE_TOOL();
+    ~AUTOPLACE_TOOL();
+
+    ///> Bind handlers to corresponding TOOL_ACTIONs
+    void setTransitions() override;
+
+private:
+    int autoplace( std::vector<MODULE*>& aModules, bool aPlaceOffboard );
+
+    int autoplaceSelected( const TOOL_EVENT& aEvent );
+    int autoplaceOffboard( const TOOL_EVENT& aEvent );
+};
+
+
+#endif // TOOLS_AUTOPLACE_TOOL_H
diff --git a/pcbnew/autorouter/graphpcb.cpp b/pcbnew/autorouter/graphpcb.cpp
index 119eed1..819f787 100644
--- a/pcbnew/autorouter/graphpcb.cpp
+++ b/pcbnew/autorouter/graphpcb.cpp
@@ -40,51 +40,32 @@
 #include <class_drawsegment.h>
 
 #include <pcbnew.h>
+#include <class_undoredo_container.h>
 #include <autorout.h>
 #include <cell.h>
 
-void TracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color );
-
-void TraceArc( int ux0, int uy0,
-               int ux1, int uy1,
-               double ArcAngle,
-               int lg, LAYER_NUM layer, int color,
-               int op_logic );
-
-
-static void DrawSegmentQcq( int ux0, int uy0,
-                            int ux1, int uy1,
-                            int lg, LAYER_NUM layer, int color,
-                            int op_logic );
-
-static void TraceFilledCircle( int    cx, int cy, int radius,
-                               LSET aLayerMask,
-                               int    color,
-                               int    op_logic );
-
-static void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
-                         int color, int op_logic );
+#include <class_undoredo_container.h>
 
 // Macro call to update cell.
 #define OP_CELL( layer, dy, dx )                                        \
     {                                                                   \
         if( layer == UNDEFINED_LAYER )                                  \
         {                                                               \
-            RoutingMatrix.WriteCell( dy, dx, BOTTOM, color );           \
-            if( RoutingMatrix.m_RoutingLayersCount > 1 )                \
-                RoutingMatrix.WriteCell( dy, dx, TOP, color );          \
+            m_routingMatrix.WriteCell( dy, dx, BOTTOM, color );           \
+            if( m_routingMatrix.m_RoutingLayersCount > 1 )                \
+                m_routingMatrix.WriteCell( dy, dx, TOP, color );          \
         }                                                               \
         else                                                            \
         {                                                               \
             if( layer == g_Route_Layer_BOTTOM )                         \
-                RoutingMatrix.WriteCell( dy, dx, BOTTOM, color );       \
-            if( RoutingMatrix.m_RoutingLayersCount > 1 )                \
+                m_routingMatrix.WriteCell( dy, dx, BOTTOM, color );       \
+            if( m_routingMatrix.m_RoutingLayersCount > 1 )                \
                 if( layer == g_Route_Layer_TOP )                        \
-                    RoutingMatrix.WriteCell( dy, dx, TOP, color );      \
+                    m_routingMatrix.WriteCell( dy, dx, TOP, color );      \
         }                                                               \
     }
 
-void PlacePad( D_PAD* aPad, int color, int marge, int op_logic )
+void AUTOROUTER::PlacePad( D_PAD* aPad, int color, int marge, int op_logic )
 {
     int     dx, dy;
     wxPoint shape_pos = aPad->ShapePos();
@@ -131,138 +112,16 @@ void PlacePad( D_PAD* aPad, int color, int marge, int op_logic )
 }
 
 
-/* Set to color the cells included in the circle
- * Parameters:
- * center: cx, cy.
- * radius: a value add to the radius or half the score pad
- * aLayerMask: layer occupied
- * color: mask write in cells
- * op_logic: type of writing in the cell (WRITE, OR)
- */
-void TraceFilledCircle( int cx, int cy, int radius,
-        LSET aLayerMask,  int color,  int op_logic )
-{
-    int   row, col;
-    int   ux0, uy0, ux1, uy1;
-    int   row_max, col_max, row_min, col_min;
-    int   trace = 0;
-    double fdistmin, fdistx, fdisty;
-    int   tstwrite = 0;
-    int   distmin;
-
-    if( aLayerMask[g_Route_Layer_BOTTOM] )
-        trace = 1;       // Trace on BOTTOM
-
-    if( aLayerMask[g_Route_Layer_TOP] )
-        if( RoutingMatrix.m_RoutingLayersCount > 1 )
-            trace |= 2;  // Trace on TOP
-
-    if( trace == 0 )
-        return;
-
-    RoutingMatrix.SetCellOperation( op_logic );
-
-    cx -= RoutingMatrix.GetBrdCoordOrigin().x;
-    cy -= RoutingMatrix.GetBrdCoordOrigin().y;
-
-    distmin = radius;
-
-    // Calculate the bounding rectangle of the circle.
-    ux0 = cx - radius;
-    uy0 = cy - radius;
-    ux1 = cx + radius;
-    uy1 = cy + radius;
-
-    // Calculate limit coordinates of cells belonging to the rectangle.
-    row_max = uy1 / RoutingMatrix.m_GridRouting;
-    col_max = ux1 / RoutingMatrix.m_GridRouting;
-    row_min = uy0 / RoutingMatrix.m_GridRouting;  // if (uy0 > row_min*Board.m_GridRouting) row_min++;
-    col_min = ux0 / RoutingMatrix.m_GridRouting;  // if (ux0 > col_min*Board.m_GridRouting) col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= (RoutingMatrix.m_Nrows - 1) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= (RoutingMatrix.m_Ncols - 1) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    // Calculate coordinate limits of cell belonging to the rectangle.
-    if( row_min > row_max )
-        row_max = row_min;
-
-    if( col_min > col_max )
-        col_max = col_min;
-
-    fdistmin = (double) distmin * distmin;
-
-    for( row = row_min; row <= row_max; row++ )
-    {
-        fdisty  = (double) ( cy - ( row * RoutingMatrix.m_GridRouting ) );
-        fdisty *= fdisty;
-
-        for( col = col_min; col <= col_max; col++ )
-        {
-            fdistx  = (double) ( cx - ( col * RoutingMatrix.m_GridRouting ) );
-            fdistx *= fdistx;
-
-            if( fdistmin <= ( fdistx + fdisty ) )
-                continue;
-
-            if( trace & 1 )
-                RoutingMatrix.WriteCell( row, col, BOTTOM, color );
-
-            if( trace & 2 )
-                RoutingMatrix.WriteCell( row, col, TOP, color );
-
-            tstwrite = 1;
-        }
-    }
-
-    if( tstwrite )
-        return;
-
-    /* If no cell has been written, it affects the 4 neighboring diagonal
-     * (Adverse event: pad off grid in the center of the 4 neighboring
-     * diagonal) */
-    distmin  = RoutingMatrix.m_GridRouting / 2 + 1;
-    fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally
-
-    for( row = row_min; row <= row_max; row++ )
-    {
-        fdisty  = (double) ( cy - ( row * RoutingMatrix.m_GridRouting ) );
-        fdisty *= fdisty;
-
-        for( col = col_min; col <= col_max; col++ )
-        {
-            fdistx  = (double) ( cx - ( col * RoutingMatrix.m_GridRouting ) );
-            fdistx *= fdistx;
-
-            if( fdistmin <= ( fdistx + fdisty ) )
-                continue;
-
-            if( trace & 1 )
-                RoutingMatrix.WriteCell( row, col, BOTTOM, color );
-
-            if( trace & 2 )
-                RoutingMatrix.WriteCell( row, col, TOP, color );
-        }
-    }
-}
 
-void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, int op_logic )
+void AUTOROUTER::TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, int op_logic )
 {
     int half_width = ( pt_segm->GetWidth() / 2 ) + marge;
 
     // Calculate the bounding rectangle of the segment (if H, V or Via)
-    int ux0 = pt_segm->GetStart().x - RoutingMatrix.GetBrdCoordOrigin().x;
-    int uy0 = pt_segm->GetStart().y - RoutingMatrix.GetBrdCoordOrigin().y;
-    int ux1 = pt_segm->GetEnd().x - RoutingMatrix.GetBrdCoordOrigin().x;
-    int uy1 = pt_segm->GetEnd().y - RoutingMatrix.GetBrdCoordOrigin().y;
+    int ux0 = pt_segm->GetStart().x - m_routingMatrix.GetBrdCoordOrigin().x;
+    int uy0 = pt_segm->GetStart().y - m_routingMatrix.GetBrdCoordOrigin().y;
+    int ux1 = pt_segm->GetEnd().x - m_routingMatrix.GetBrdCoordOrigin().x;
+    int uy1 = pt_segm->GetEnd().y - m_routingMatrix.GetBrdCoordOrigin().y;
 
     LAYER_NUM layer = pt_segm->GetLayer();
 
@@ -287,7 +146,7 @@ void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, int op_logic )
     }
 }
 
-void TraceSegmentPcb( TRACK* aTrack, int color, int marge, int op_logic )
+void AUTOROUTER::TraceSegmentPcb( TRACK* aTrack, int color, int marge, int op_logic )
 {
     int half_width = ( aTrack->GetWidth() / 2 ) + marge;
 
@@ -317,13 +176,13 @@ void TraceSegmentPcb( TRACK* aTrack, int color, int marge, int op_logic )
     else
     {
         // Calculate the bounding rectangle of the segment
-        int ux0 = aTrack->GetStart().x - RoutingMatrix.GetBrdCoordOrigin().x;
-        int uy0 = aTrack->GetStart().y - RoutingMatrix.GetBrdCoordOrigin().y;
-        int ux1 = aTrack->GetEnd().x - RoutingMatrix.GetBrdCoordOrigin().x;
-        int uy1 = aTrack->GetEnd().y - RoutingMatrix.GetBrdCoordOrigin().y;
+        int ux0 = aTrack->GetStart().x - m_routingMatrix.GetBrdCoordOrigin().x;
+        int uy0 = aTrack->GetStart().y - m_routingMatrix.GetBrdCoordOrigin().y;
+        int ux1 = aTrack->GetEnd().x - m_routingMatrix.GetBrdCoordOrigin().x;
+        int uy1 = aTrack->GetEnd().y - m_routingMatrix.GetBrdCoordOrigin().y;
 
         // Ordinary track
-        PCB_LAYER_ID layer = aTrack->GetLayer();
+        LAYER_ID layer = aTrack->GetLayer();
 
         if( color == VIA_IMPOSSIBLE )
             layer = UNDEFINED_LAYER;
@@ -333,511 +192,3 @@ void TraceSegmentPcb( TRACK* aTrack, int color, int marge, int op_logic )
 }
 
 
-/* Draws a line, if layer = -1 on all layers
- */
-void TracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, int op_logic  )
-{
-    int  dx, dy, lim;
-    int  cumul, inc, il, delta;
-
-    RoutingMatrix.SetCellOperation( op_logic );
-
-    if( x0 == x1 )  // Vertical.
-    {
-        if( y1 < y0 )
-            std::swap( y0, y1 );
-
-        dy  = y0 / RoutingMatrix.m_GridRouting;
-        lim = y1 / RoutingMatrix.m_GridRouting;
-        dx  = x0 / RoutingMatrix.m_GridRouting;
-
-        // Clipping limits of board.
-        if( ( dx < 0 ) || ( dx >= RoutingMatrix.m_Ncols ) )
-            return;
-
-        if( dy < 0 )
-            dy = 0;
-
-        if( lim >= RoutingMatrix.m_Nrows )
-            lim = RoutingMatrix.m_Nrows - 1;
-
-        for( ; dy <= lim; dy++ )
-        {
-            OP_CELL( layer, dy, dx );
-        }
-
-        return;
-    }
-
-    if( y0 == y1 )  // Horizontal
-    {
-        if( x1 < x0 )
-            std::swap( x0, x1 );
-
-        dx  = x0 / RoutingMatrix.m_GridRouting;
-        lim = x1 / RoutingMatrix.m_GridRouting;
-        dy  = y0 / RoutingMatrix.m_GridRouting;
-
-        // Clipping limits of board.
-        if( ( dy < 0 ) || ( dy >= RoutingMatrix.m_Nrows ) )
-            return;
-
-        if( dx < 0 )
-            dx = 0;
-
-        if( lim >= RoutingMatrix.m_Ncols )
-            lim = RoutingMatrix.m_Ncols - 1;
-
-        for( ; dx <= lim; dx++ )
-        {
-            OP_CELL( layer, dy, dx );
-        }
-
-        return;
-    }
-
-    // Here is some perspective: using the algorithm LUCAS.
-    if( abs( x1 - x0 ) >= abs( y1 - y0 ) ) // segment slightly inclined/
-    {
-        if( x1 < x0 )
-        {
-            std::swap( x1, x0 );
-            std::swap( y1, y0 );
-        }
-
-        dx  = x0 / RoutingMatrix.m_GridRouting;
-        lim = x1 / RoutingMatrix.m_GridRouting;
-        dy  = y0 / RoutingMatrix.m_GridRouting;
-        inc = 1;
-
-        if( y1 < y0 )
-            inc = -1;
-
-        il    = lim - dx; cumul = il / 2;
-        delta = abs( y1 - y0 ) / RoutingMatrix.m_GridRouting;
-
-        for( ; dx <= lim; )
-        {
-            if( ( dx >= 0 ) && ( dy >= 0 ) &&
-                ( dx < RoutingMatrix.m_Ncols ) &&
-                ( dy < RoutingMatrix.m_Nrows ) )
-            {
-                OP_CELL( layer, dy, dx );
-            }
-
-            dx++;
-            cumul += delta;
-
-            if( cumul > il )
-            {
-                cumul -= il;
-                dy    += inc;
-            }
-        }
-    }
-    else
-    {
-        if( y1 < y0 )
-        {
-            std::swap( x1, x0 );
-            std::swap( y1, y0 );
-        }
-
-        dy  = y0 / RoutingMatrix.m_GridRouting;
-        lim = y1 / RoutingMatrix.m_GridRouting;
-        dx  = x0 / RoutingMatrix.m_GridRouting;
-        inc = 1;
-
-        if( x1 < x0 )
-            inc = -1;
-
-        il    = lim - dy;
-        cumul = il / 2;
-        delta = abs( x1 - x0 ) / RoutingMatrix.m_GridRouting;
-
-        for( ; dy <= lim; )
-        {
-            if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < RoutingMatrix.m_Ncols ) && ( dy < RoutingMatrix.m_Nrows ) )
-            {
-                OP_CELL( layer, dy, dx );
-            }
-
-            dy++;
-            cumul += delta;
-
-            if( cumul > il )
-            {
-                cumul -= il;
-                dx    += inc;
-            }
-        }
-    }
-}
-
-
-void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
-                           LSET aLayerMask, int color, int op_logic )
-{
-    int  row, col;
-    int  row_min, row_max, col_min, col_max;
-    int  trace = 0;
-
-    if( aLayerMask[g_Route_Layer_BOTTOM] )
-        trace = 1;     // Trace on BOTTOM
-
-    if( aLayerMask[g_Route_Layer_TOP] && RoutingMatrix.m_RoutingLayersCount > 1 )
-        trace |= 2;    // Trace on TOP
-
-    if( trace == 0 )
-        return;
-
-    RoutingMatrix.SetCellOperation( op_logic );
-
-    ux0 -= RoutingMatrix.GetBrdCoordOrigin().x;
-    uy0 -= RoutingMatrix.GetBrdCoordOrigin().y;
-    ux1 -= RoutingMatrix.GetBrdCoordOrigin().x;
-    uy1 -= RoutingMatrix.GetBrdCoordOrigin().y;
-
-    // Calculating limits coord cells belonging to the rectangle.
-    row_max = uy1 / RoutingMatrix.m_GridRouting;
-    col_max = ux1 / RoutingMatrix.m_GridRouting;
-    row_min = uy0 / RoutingMatrix.m_GridRouting;
-
-    if( uy0 > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    col_min = ux0 / RoutingMatrix.m_GridRouting;
-
-    if( ux0 > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    for( row = row_min; row <= row_max; row++ )
-    {
-        for( col = col_min; col <= col_max; col++ )
-        {
-            if( trace & 1 )
-                RoutingMatrix.WriteCell( row, col, BOTTOM, color );
-
-            if( trace & 2 )
-                RoutingMatrix.WriteCell( row, col, TOP, color );
-        }
-    }
-}
-
-
-void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
-                           double angle, LSET aLayerMask, int color, int op_logic )
-{
-    int  row, col;
-    int  cx, cy;    // Center of rectangle
-    int  radius;     // Radius of the circle
-    int  row_min, row_max, col_min, col_max;
-    int  rotrow, rotcol;
-    int  trace = 0;
-
-    if( aLayerMask[g_Route_Layer_BOTTOM] )
-        trace = 1;     // Trace on BOTTOM
-
-    if( aLayerMask[g_Route_Layer_TOP] )
-    {
-        if( RoutingMatrix.m_RoutingLayersCount > 1 )
-            trace |= 2;  // Trace on TOP
-    }
-
-    if( trace == 0 )
-        return;
-
-    RoutingMatrix.SetCellOperation( op_logic );
-
-    ux0 -= RoutingMatrix.GetBrdCoordOrigin().x;
-    uy0 -= RoutingMatrix.GetBrdCoordOrigin().y;
-    ux1 -= RoutingMatrix.GetBrdCoordOrigin().x;
-    uy1 -= RoutingMatrix.GetBrdCoordOrigin().y;
-
-    cx    = (ux0 + ux1) / 2;
-    cy    = (uy0 + uy1) / 2;
-    radius = KiROUND( Distance( ux0, uy0, cx, cy ) );
-
-    // Calculating coordinate limits belonging to the rectangle.
-    row_max = ( cy + radius ) / RoutingMatrix.m_GridRouting;
-    col_max = ( cx + radius ) / RoutingMatrix.m_GridRouting;
-    row_min = ( cy - radius ) / RoutingMatrix.m_GridRouting;
-
-    if( uy0 > row_min * RoutingMatrix.m_GridRouting )
-        row_min++;
-
-    col_min = ( cx - radius ) / RoutingMatrix.m_GridRouting;
-
-    if( ux0 > col_min * RoutingMatrix.m_GridRouting )
-        col_min++;
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    for( row = row_min; row <= row_max; row++ )
-    {
-        for( col = col_min; col <= col_max; col++ )
-        {
-            rotrow = row * RoutingMatrix.m_GridRouting;
-            rotcol = col * RoutingMatrix.m_GridRouting;
-            RotatePoint( &rotcol, &rotrow, cx, cy, -angle );
-
-            if( rotrow <= uy0 )
-                continue;
-
-            if( rotrow >= uy1 )
-                continue;
-
-            if( rotcol <= ux0 )
-                continue;
-
-            if( rotcol >= ux1 )
-                continue;
-
-            if( trace & 1 )
-                RoutingMatrix.WriteCell( row, col, BOTTOM, color );
-
-            if( trace & 2 )
-                RoutingMatrix.WriteCell( row, col, TOP, color );
-        }
-    }
-}
-
-
-/* Fills all cells inside a segment
- * half-width = lg, org = ux0,uy0 end = ux1,uy1
- * coordinates are in PCB units
- */
-void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
-                     int color, int op_logic )
-{
-    int  row, col;
-    int  inc;
-    int  row_max, col_max, row_min, col_min;
-    int  demi_pas;
-
-    int  cx, cy, dx, dy;
-
-    RoutingMatrix.SetCellOperation( op_logic );
-
-    // Make coordinate ux1 tj > ux0 to simplify calculations
-    if( ux1 < ux0 )
-    {
-        std::swap( ux1, ux0 );
-        std::swap( uy1, uy0 );
-    }
-
-    // Calculating the incrementing the Y axis
-    inc = 1;
-
-    if( uy1 < uy0 )
-        inc = -1;
-
-    demi_pas = RoutingMatrix.m_GridRouting / 2;
-
-    col_min = ( ux0 - lg ) / RoutingMatrix.m_GridRouting;
-
-    if( col_min < 0 )
-        col_min = 0;
-
-    col_max = ( ux1 + lg + demi_pas ) / RoutingMatrix.m_GridRouting;
-
-    if( col_max > ( RoutingMatrix.m_Ncols - 1 ) )
-        col_max = RoutingMatrix.m_Ncols - 1;
-
-    if( inc > 0 )
-    {
-        row_min = ( uy0 - lg ) / RoutingMatrix.m_GridRouting;
-        row_max = ( uy1 + lg + demi_pas ) / RoutingMatrix.m_GridRouting;
-    }
-    else
-    {
-        row_min = ( uy1 - lg ) / RoutingMatrix.m_GridRouting;
-        row_max = ( uy0 + lg + demi_pas ) / RoutingMatrix.m_GridRouting;
-    }
-
-    if( row_min < 0 )
-        row_min = 0;
-
-    if( row_min > ( RoutingMatrix.m_Nrows - 1 ) )
-        row_min = RoutingMatrix.m_Nrows - 1;
-
-    if( row_max < 0 )
-        row_max = 0;
-
-    if( row_max > ( RoutingMatrix.m_Nrows - 1 ) )
-        row_max = RoutingMatrix.m_Nrows - 1;
-
-    dx = ux1 - ux0;
-    dy = uy1 - uy0;
-
-    double angle;
-    if( dx )
-    {
-        angle = ArcTangente( dy, dx );
-    }
-    else
-    {
-        angle = 900;
-
-        if( dy < 0 )
-            angle = -900;
-    }
-
-    RotatePoint( &dx, &dy, angle );   // dx = length, dy = 0
-
-    for( col = col_min; col <= col_max; col++ )
-    {
-        int cxr;
-        cxr = ( col * RoutingMatrix.m_GridRouting ) - ux0;
-
-        for( row = row_min; row <= row_max; row++ )
-        {
-            cy = (row * RoutingMatrix.m_GridRouting) - uy0;
-            cx = cxr;
-            RotatePoint( &cx, &cy, angle );
-
-            if( abs( cy ) > lg )
-                continue;             // The point is too far on the Y axis.
-
-            /* This point a test is close to the segment: the position
-             * along the X axis must be tested.
-             */
-            if( ( cx >= 0 ) && ( cx <= dx ) )
-            {
-                OP_CELL( layer, row, col );
-                continue;
-            }
-
-            // Examination of extremities are rounded.
-            if( ( cx < 0 ) && ( cx >= -lg ) )
-            {
-                if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
-                    OP_CELL( layer, row, col );
-
-                continue;
-            }
-
-            if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
-            {
-                if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) ) <= ( lg * lg ) )
-                    OP_CELL( layer, row, col );
-
-                continue;
-            }
-        }
-    }
-}
-
-
-/* Fills all cells of the routing matrix contained in the circle
- * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle.
- * coord are in PCB units.
- */
-void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
-                  int color, int op_logic )
-{
-    int radius, nb_segm;
-    int x0, y0,             // Starting point of the current segment trace.
-        x1, y1;             // End point.
-    int ii;
-    int angle;
-
-    radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
-
-    x0 = x1 = radius;
-    y0 = y1 = 0;
-
-    if( lg < 1 )
-        lg = 1;
-
-    nb_segm = ( 2 * radius ) / lg;
-
-    if( nb_segm < 5 )
-        nb_segm = 5;
-
-    if( nb_segm > 100 )
-        nb_segm = 100;
-
-    for( ii = 1; ii < nb_segm; ii++ )
-    {
-        angle = (3600 * ii) / nb_segm;
-        x1    = KiROUND( cosdecideg( radius, angle ) );
-        y1    = KiROUND( sindecideg( radius, angle ) );
-        DrawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
-        x0 = x1;
-        y0 = y1;
-    }
-
-    DrawSegmentQcq( x1 + ux0, y1 + uy0, ux0 + radius, uy0, lg, layer, color, op_logic );
-}
-
-
-/* Fills all routing matrix cells contained in the arc
- * angle = ArcAngle, half-width lg
- * center = ux0,uy0, starting at ux1, uy1.  Coordinates are in
- * PCB units.
- */
-void TraceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg,
-               LAYER_NUM layer, int color, int op_logic )
-{
-    int radius, nb_segm;
-    int x0, y0,             // Starting point of the current segment trace
-        x1, y1;             // End point
-    int ii;
-    double angle, StAngle;
-
-
-    radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
-
-    x0 = ux1 - ux0;
-    y0 = uy1 - uy0;
-    StAngle = ArcTangente( uy1 - uy0, ux1 - ux0 );
-
-    if( lg < 1 )
-        lg = 1;
-
-    nb_segm = ( 2 * radius ) / lg;
-    nb_segm = ( nb_segm * std::abs( ArcAngle ) ) / 3600;
-
-    if( nb_segm < 5 )
-        nb_segm = 5;
-
-    if( nb_segm > 100 )
-        nb_segm = 100;
-
-    for( ii = 1; ii <= nb_segm; ii++ )
-    {
-        angle  = ( ArcAngle * ii ) / nb_segm;
-        angle += StAngle;
-
-        NORMALIZE_ANGLE_POS( angle );
-
-        x1 = KiROUND( cosdecideg( radius, angle ) );
-        y1 = KiROUND( cosdecideg( radius, angle ) );
-        DrawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
-        x0 = x1;
-        y0 = y1;
-    }
-}
diff --git a/pcbnew/autorouter/move_and_route_event_functions.cpp b/pcbnew/autorouter/move_and_route_event_functions.cpp
index 6adf7cc..124b780 100644
--- a/pcbnew/autorouter/move_and_route_event_functions.cpp
+++ b/pcbnew/autorouter/move_and_route_event_functions.cpp
@@ -63,6 +63,7 @@ wxString ModulesMaskSelection = wxT( "*" );
  */
 void PCB_EDIT_FRAME::OnPlaceOrRouteFootprints( wxCommandEvent& event )
 {
+    #if 0
     int        id = event.GetId();
 
     if( m_mainToolBar == NULL )
@@ -178,6 +179,7 @@ void PCB_EDIT_FRAME::OnPlaceOrRouteFootprints( wxCommandEvent& event )
 
     GetBoard()->m_Status_Pcb &= ~DO_NOT_SHOW_GENERAL_RASTNEST;
     Compile_Ratsnest( &dc, true );
+    #endif
 }
 
 
diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp
index 4c83d42..fc0e685 100644
--- a/pcbnew/autorouter/solve.cpp
+++ b/pcbnew/autorouter/solve.cpp
@@ -48,44 +48,6 @@
 #include <autorout.h>
 #include <cell.h>
 
-static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
-                                int             two_sides,
-                                int             row_source,
-                                int             col_source,
-                                int             row_target,
-                                int             col_target,
-                                RATSNEST_ITEM*  pt_rat );
-
-static int Retrace( AUTOROUTER_CONTEXT& ctx,
-                    int,
-                    int,
-                    int,
-                    int,
-                    int,
-                    int              net_code );
-
-static void OrCell_Trace( AUTOROUTER_CONTEXT& ctx,
-                          int    col,
-                          int    row,
-                          int    side,
-                          int    orient,
-                          int    current_net_code );
-
-static void AddNewTrace( AUTOROUTER_CONTEXT& ctx );
-
-
-static int            segm_oX, segm_oY;
-static int            segm_fX, segm_fY; /* Origin and position of the current
-                                         * trace segment. */
-static RATSNEST_ITEM* pt_cur_ch;
-static int            s_Clearance;  // Clearance value used in autorouter
-
-static PICKED_ITEMS_LIST s_ItemsListPicker;
-
-int OpenNodes;       // total number of nodes opened
-int ClosNodes;       // total number of nodes closed
-int MoveNodes;       // total number of nodes moved
-int MaxNodes;        // maximum number of nodes opened at one time
 
 #define NOSUCCESS       0
 #define STOP_FROM_ESC   -1
@@ -263,7 +225,7 @@ static long newmask[8] =
  * -1 if escape (stop being routed) request
  * -2 if default memory allocation
  */
-int PCB_EDIT_FRAME::Solve( AUTOROUTER_CONTEXT& aCtx, int aLayersCount )
+int AUTOROUTER::solve( int aLayersCount )
 {
     int           current_net_code;
     int           row_source, col_source, row_target, col_target;
@@ -274,9 +236,8 @@ int PCB_EDIT_FRAME::Solve( AUTOROUTER_CONTEXT& aCtx, int aLayersCount )
     int           routedCount = 0;      // routed ratsnest count
     bool          two_sides = aLayersCount == 2;
 
-    m_canvas->SetAbortRequest( false );
 
-    s_Clearance = aCtx.board->GetDesignSettings().GetDefault()->GetClearance();
+    s_Clearance = m_board->GetDesignSettings().GetDefault()->GetClearance();
 
     // Prepare the undo command info
     s_ItemsListPicker.ClearListAndDeleteItems();  // Should not be necessary, but...
@@ -291,6 +252,7 @@ int PCB_EDIT_FRAME::Solve( AUTOROUTER_CONTEXT& aCtx, int aLayersCount )
                                            &pt_cur_ch ) )
     {
         // Test to stop routing ( escape key pressed )
+    #ifdef AR_YIELD
         wxYield();
 
         if( m_canvas->GetAbortRequest() )
@@ -306,39 +268,42 @@ int PCB_EDIT_FRAME::Solve( AUTOROUTER_CONTEXT& aCtx, int aLayersCount )
                 m_canvas->SetAbortRequest( false );
             }
         }
+    #endif
 
-        EraseMsgBox();
+        m_frame->EraseMsgBox();
 
         routedCount++;
-        net = aCtx.board->FindNet( current_net_code );
+        net = m_board->FindNet( current_net_code );
 
         if( net )
         {
             msg.Printf( wxT( "[%8.8s]" ), GetChars( net->GetNetname() ) );
-            AppendMsgPanel( wxT( "Net route" ), msg, BROWN );
-            msg.Printf( wxT( "%d / %d" ), routedCount, RoutingMatrix.m_RouteCount );
-            AppendMsgPanel( wxT( "Activity" ), msg, BROWN );
+            m_frame->AppendMsgPanel( wxT( "Net route" ), msg, BROWN );
+            msg.Printf( wxT( "%d / %d" ), routedCount, m_routingMatrix.m_RouteCount );
+            m_frame->AppendMsgPanel( wxT( "Activity" ), msg, BROWN );
         }
 
-        segm_oX = aCtx.bbox.GetX() + ( RoutingMatrix.m_GridRouting * col_source );
-        segm_oY = aCtx.bbox.GetY() + ( RoutingMatrix.m_GridRouting * row_source );
-        segm_fX = aCtx.bbox.GetX() + ( RoutingMatrix.m_GridRouting * col_target );
-        segm_fY = aCtx.bbox.GetY() + ( RoutingMatrix.m_GridRouting * row_target );
+        segm_oX = m_bbox.GetX() + ( m_routingMatrix.m_GridRouting * col_source );
+        segm_oY = m_bbox.GetY() + ( m_routingMatrix.m_GridRouting * row_source );
+        segm_fX = m_bbox.GetX() + ( m_routingMatrix.m_GridRouting * col_target );
+        segm_fY = m_bbox.GetY() + ( m_routingMatrix.m_GridRouting * row_target );
 
         // Draw segment.
+#ifdef AR_DRAW
         GRLine( m_canvas->GetClipBox(), aCtx.dc,
                 segm_oX, segm_oY, segm_fX, segm_fY,
                 0, WHITE );
-        pt_cur_ch->m_PadStart->Draw( m_canvas, aCtx.dc, GR_OR | GR_HIGHLIGHT );
-        pt_cur_ch->m_PadEnd->Draw( m_canvas, aCtx.dc, GR_OR | GR_HIGHLIGHT );
+        pt_cur_ch->m_padStart->Draw( m_canvas, aCtx.dc, GR_OR | GR_HIGHLIGHT );
+        pt_cur_ch->m_padEnd->Draw( m_canvas, aCtx.dc, GR_OR | GR_HIGHLIGHT );
+#endif
 
-        success = Autoroute_One_Track( aCtx, two_sides, row_source, col_source,
+        success = Autoroute_One_Track( two_sides, row_source, col_source,
                                        row_target, col_target, pt_cur_ch );
 
         switch( success )
         {
         case NOSUCCESS:
-            pt_cur_ch->m_Status |= CH_UNROUTABLE;
+            pt_cur_ch->m_status |= CH_UNROUTABLE;
             nbunsucces++;
             break;
 
@@ -356,21 +321,23 @@ int PCB_EDIT_FRAME::Solve( AUTOROUTER_CONTEXT& aCtx, int aLayersCount )
         }
 
         msg.Printf( wxT( "%d" ), nbsucces );
-        AppendMsgPanel( wxT( "OK" ), msg, GREEN );
+        m_frame->AppendMsgPanel( wxT( "OK" ), msg, GREEN );
         msg.Printf( wxT( "%d" ), nbunsucces );
-        AppendMsgPanel( wxT( "Fail" ), msg, RED );
-        msg.Printf( wxT( "  %d" ), aCtx.board->GetUnconnectedNetCount() );
-        AppendMsgPanel( wxT( "Not Connected" ), msg, CYAN );
+        m_frame->AppendMsgPanel( wxT( "Fail" ), msg, RED );
+        msg.Printf( wxT( "  %d" ), m_board->GetUnconnectedNetCount() );
+        m_frame->AppendMsgPanel( wxT( "Not Connected" ), msg, CYAN );
 
         // Delete routing from display.
-        pt_cur_ch->m_PadStart->Draw( m_canvas, aCtx.dc, GR_AND );
-        pt_cur_ch->m_PadEnd->Draw( m_canvas, aCtx.dc, GR_AND );
+#ifdef AR_DRAW
+        pt_cur_ch->m_padStart->Draw( m_canvas, aCtx.dc, GR_AND );
+        pt_cur_ch->m_padEnd->Draw( m_canvas, aCtx.dc, GR_AND );
+#endif
 
         if( stop )
             break;
     }
 
-    SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED );
+    m_frame->SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED );
     s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
 
     return SUCCESS;
@@ -392,13 +359,13 @@ int PCB_EDIT_FRAME::Solve( AUTOROUTER_CONTEXT& aCtx, int aLayersCount )
  * Escape STOP_FROM_ESC if demand
  * ERR_MEMORY if memory allocation failed.
  */
-static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
+int AUTOROUTER::Autoroute_One_Track(
                                 int             two_sides,
                                 int             row_source,
                                 int             col_source,
                                 int             row_target,
                                 int             col_target,
-                                RATSNEST_ITEM*  pt_rat )
+                                AR_CONNECTION*  pt_rat )
 {
     int          r, c, side, d, apx_dist, nr, nc;
     int          result, skip;
@@ -422,21 +389,21 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
     wxString     msg;
 
     // @todo this could be a bottle neck
-    LSET all_cu = LSET::AllCuMask( ctx.board->GetCopperLayerCount() );
+    LSET all_cu = LSET::AllCuMask( m_board->GetCopperLayerCount() );
 
     wxBusyCursor dummy_cursor;      // Set an hourglass cursor while routing a
                                     // track
 
     result = NOSUCCESS;
 
-    marge = s_Clearance + ( ctx.pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );
+    marge = s_Clearance + ( m_frame->GetDesignSettings().GetCurrentTrackWidth() / 2 );
 
     // clear direction flags
-    i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL);
+    i = m_routingMatrix.m_Nrows * m_routingMatrix.m_Ncols * sizeof(DIR_CELL);
 
     if( two_sides )
-        memset( RoutingMatrix.m_DirSide[TOP], FROM_NOWHERE, i );
-    memset( RoutingMatrix.m_DirSide[BOTTOM], FROM_NOWHERE, i );
+        memset( m_routingMatrix.m_DirSide[TOP], FROM_NOWHERE, i );
+    memset( m_routingMatrix.m_DirSide[BOTTOM], FROM_NOWHERE, i );
 
     lastopen = lastclos = lastmove = 0;
 
@@ -451,9 +418,9 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
     pt_cur_ch = pt_rat;
 
     current_net_code  = pt_rat->GetNet();
-    padLayerMaskStart = pt_cur_ch->m_PadStart->GetLayerSet();
+    padLayerMaskStart = pt_cur_ch->m_padStart->GetLayerSet();
 
-    padLayerMaskEnd = pt_cur_ch->m_PadEnd->GetLayerSet();
+    padLayerMaskEnd = pt_cur_ch->m_padEnd->GetLayerSet();
 
 
     /* First Test if routing possible ie if the pads are accessible
@@ -469,27 +436,27 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
      * On the routing grid (1 grid point must be in the pad)
      */
     {
-        int cX = ( RoutingMatrix.m_GridRouting * col_source ) + ctx.bbox.GetX();
-        int cY = ( RoutingMatrix.m_GridRouting * row_source ) + ctx.bbox.GetY();
-        int dx = pt_cur_ch->m_PadStart->GetSize().x / 2;
-        int dy = pt_cur_ch->m_PadStart->GetSize().y / 2;
-        int px = pt_cur_ch->m_PadStart->GetPosition().x;
-        int py = pt_cur_ch->m_PadStart->GetPosition().y;
-
-        if( ( ( int( pt_cur_ch->m_PadStart->GetOrientation() ) / 900 ) & 1 ) != 0 )
+        int cX = ( m_routingMatrix.m_GridRouting * col_source ) + m_bbox.GetX();
+        int cY = ( m_routingMatrix.m_GridRouting * row_source ) + m_bbox.GetY();
+        int dx = pt_cur_ch->m_padStart->GetSize().x / 2;
+        int dy = pt_cur_ch->m_padStart->GetSize().y / 2;
+        int px = pt_cur_ch->m_padStart->GetPosition().x;
+        int py = pt_cur_ch->m_padStart->GetPosition().y;
+
+        if( ( ( int( pt_cur_ch->m_padStart->GetOrientation() ) / 900 ) & 1 ) != 0 )
             std::swap( dx, dy );
 
         if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
             goto end_of_route;
 
-        cX = ( RoutingMatrix.m_GridRouting * col_target ) + ctx.bbox.GetX();
-        cY = ( RoutingMatrix.m_GridRouting * row_target ) + ctx.bbox.GetY();
-        dx = pt_cur_ch->m_PadEnd->GetSize().x / 2;
-        dy = pt_cur_ch->m_PadEnd->GetSize().y / 2;
-        px = pt_cur_ch->m_PadEnd->GetPosition().x;
-        py = pt_cur_ch->m_PadEnd->GetPosition().y;
+        cX = ( m_routingMatrix.m_GridRouting * col_target ) + m_bbox.GetX();
+        cY = ( m_routingMatrix.m_GridRouting * row_target ) + m_bbox.GetY();
+        dx = pt_cur_ch->m_padEnd->GetSize().x / 2;
+        dy = pt_cur_ch->m_padEnd->GetSize().y / 2;
+        px = pt_cur_ch->m_padEnd->GetPosition().x;
+        py = pt_cur_ch->m_padEnd->GetPosition().y;
 
-        if( ( ( int( pt_cur_ch->m_PadEnd->GetOrientation() ) / 900) & 1 ) != 0 )
+        if( ( ( int( pt_cur_ch->m_padEnd->GetOrientation() ) / 900) & 1 ) != 0 )
             std::swap( dx, dy );
 
         if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
@@ -505,27 +472,27 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
     }
 
     // Placing the bit to remove obstacles on 2 pads to a link.
-    ctx.pcbframe->SetStatusText( wxT( "Gen Cells" ) );
+    m_frame->SetStatusText( wxT( "Gen Cells" ) );
 
-    PlacePad( pt_cur_ch->m_PadStart, CURRENT_PAD, marge, WRITE_OR_CELL );
-    PlacePad( pt_cur_ch->m_PadEnd, CURRENT_PAD, marge, WRITE_OR_CELL );
+    PlacePad( pt_cur_ch->m_padStart, CURRENT_PAD, marge, WRITE_OR_CELL );
+    PlacePad( pt_cur_ch->m_padEnd, CURRENT_PAD, marge, WRITE_OR_CELL );
 
     // Regenerates the remaining barriers (which may encroach on the
     // placement bits precedent)
-    i = ctx.board->GetPadCount();
+    i = m_board->GetPadCount();
 
-    for( unsigned ii = 0; ii < ctx.board->GetPadCount(); ii++ )
+    for( unsigned ii = 0; ii < m_board->GetPadCount(); ii++ )
     {
-        D_PAD* ptr = ctx.board->GetPad( ii );
+        D_PAD* ptr = m_board->GetPad( ii );
 
-        if( ( pt_cur_ch->m_PadStart != ptr ) && ( pt_cur_ch->m_PadEnd != ptr ) )
+        if( ( pt_cur_ch->m_padStart != ptr ) && ( pt_cur_ch->m_padEnd != ptr ) )
         {
             PlacePad( ptr, ~CURRENT_PAD, marge, WRITE_AND_CELL );
         }
     }
 
     InitQueue(); // initialize the search queue
-    apx_dist = RoutingMatrix.GetApxDist( row_source, col_source, row_target, col_target );
+    apx_dist = m_routingMatrix.GetApxDist( row_source, col_source, row_target, col_target );
 
     // Initialize first search.
     if( two_sides )   // Preferred orientation.
@@ -594,7 +561,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
 
     for( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
     {
-        curcell = RoutingMatrix.GetCell( r, c, side );
+        curcell = m_routingMatrix.GetCell( r, c, side );
 
         if( curcell & CURRENT_PAD )
             curcell &= ~HOLE;
@@ -603,16 +570,18 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
            && (tab_mask[side] & padLayerMaskEnd).any() )
         {
             // Remove link.
+#ifdef AR_DRAW
             GRSetDrawMode( ctx.dc, GR_XOR );
-            GRLine( ctx.pcbframe->GetCanvas()->GetClipBox(),
+            GRLine( m_frame->GetCanvas()->GetClipBox(),
                     ctx.dc,
                     segm_oX, segm_oY,
                     segm_fX, segm_fY,
                     0,
                     WHITE );
+#endif
 
             // Generate trace.
-            if( Retrace( ctx, row_source, col_source,
+            if( Retrace( row_source, col_source,
                          row_target, col_target, side, current_net_code ) )
             {
                 result = SUCCESS;   // Success : Route OK
@@ -621,7 +590,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
             break;                  // Routing complete.
         }
 
-        if( ctx.pcbframe->GetCanvas()->GetAbortRequest() )
+        if( m_frame->GetCanvas()->GetAbortRequest() )
         {
             result = STOP_FROM_ESC;
             break;
@@ -639,7 +608,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
             lastmove = MoveNodes;
             msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d" ),
                         OpenNodes, ClosNodes, MoveNodes );
-            ctx.pcbframe->SetStatusText( msg );
+            m_frame->SetStatusText( msg );
         }
 
         _self = 0;
@@ -664,14 +633,14 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
             nc = c + delta[i][1];
 
             // off the edge?
-            if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
-                nc < 0 || nc >= RoutingMatrix.m_Ncols )
+            if( nr < 0 || nr >= m_routingMatrix.m_Nrows ||
+                nc < 0 || nc >= m_routingMatrix.m_Ncols )
                 continue;  // off the edge
 
             if( _self == 5 && selfok2[i].present )
                 continue;
 
-            newcell = RoutingMatrix.GetCell( nr, nc, side );
+            newcell = m_routingMatrix.GetCell( nr, nc, side );
 
             if( newcell & CURRENT_PAD )
                 newcell &= ~HOLE;
@@ -692,7 +661,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
             if( delta[i][0] && delta[i][1] )
             {
                 // check first buddy
-                buddy = RoutingMatrix.GetCell( r + blocking[i].r1, c + blocking[i].c1, side );
+                buddy = m_routingMatrix.GetCell( r + blocking[i].r1, c + blocking[i].c1, side );
 
                 if( buddy & CURRENT_PAD )
                     buddy &= ~HOLE;
@@ -702,7 +671,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
 
 //              if (buddy & (blocking[i].b1)) continue;
                 // check second buddy
-                buddy = RoutingMatrix.GetCell( r + blocking[i].r2, c + blocking[i].c2, side );
+                buddy = m_routingMatrix.GetCell( r + blocking[i].r2, c + blocking[i].c2, side );
 
                 if( buddy & CURRENT_PAD )
                     buddy &= ~HOLE;
@@ -713,31 +682,31 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
 //              if (buddy & (blocking[i].b2)) continue;
             }
 
-            olddir  = RoutingMatrix.GetDir( r, c, side );
-            newdist = d + RoutingMatrix.CalcDist( ndir[i], olddir,
+            olddir  = m_routingMatrix.GetDir( r, c, side );
+            newdist = d + m_routingMatrix.CalcDist( ndir[i], olddir,
                                     ( olddir == FROM_OTHERSIDE ) ?
-                                    RoutingMatrix.GetDir( r, c, 1 - side ) : 0, side );
+                                    m_routingMatrix.GetDir( r, c, 1 - side ) : 0, side );
 
             // if (a) not visited yet, or (b) we have
             // found a better path, add it to queue
-            if( !RoutingMatrix.GetDir( nr, nc, side ) )
+            if( !m_routingMatrix.GetDir( nr, nc, side ) )
             {
-                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
-                RoutingMatrix.SetDist( nr, nc, side, newdist );
+                m_routingMatrix.SetDir( nr, nc, side, ndir[i] );
+                m_routingMatrix.SetDist( nr, nc, side, newdist );
 
                 if( SetQueue( nr, nc, side, newdist,
-                              RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
+                              m_routingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                               row_target, col_target ) == 0 )
                 {
                     return ERR_MEMORY;
                 }
             }
-            else if( newdist < RoutingMatrix.GetDist( nr, nc, side ) )
+            else if( newdist < m_routingMatrix.GetDist( nr, nc, side ) )
             {
-                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
-                RoutingMatrix.SetDist( nr, nc, side, newdist );
+                m_routingMatrix.SetDir( nr, nc, side, ndir[i] );
+                m_routingMatrix.SetDist( nr, nc, side, newdist );
                 ReSetQueue( nr, nc, side, newdist,
-                            RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
+                            m_routingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                             row_target, col_target );
             }
         }
@@ -745,7 +714,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
         //* Test the other layer. *
         if( two_sides )
         {
-            olddir = RoutingMatrix.GetDir( r, c, side );
+            olddir = m_routingMatrix.GetDir( r, c, side );
 
             if( olddir == FROM_OTHERSIDE )
                 continue;   // useless move, so don't bother
@@ -754,7 +723,7 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
                 continue;
 
             // check for holes or traces on other side
-            if( ( newcell = RoutingMatrix.GetCell( r, c, 1 - side ) ) != 0 )
+            if( ( newcell = m_routingMatrix.GetCell( r, c, 1 - side ) ) != 0 )
                 continue;
 
             // check for nearby holes or traces on both sides
@@ -762,17 +731,17 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
             {
                 nr = r + delta[i][0]; nc = c + delta[i][1];
 
-                if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
-                    nc < 0 || nc >= RoutingMatrix.m_Ncols )
+                if( nr < 0 || nr >= m_routingMatrix.m_Nrows ||
+                    nc < 0 || nc >= m_routingMatrix.m_Ncols )
                     continue;  // off the edge !!
 
-                if( RoutingMatrix.GetCell( nr, nc, side ) /* & blocking2[i] */ )
+                if( m_routingMatrix.GetCell( nr, nc, side ) /* & blocking2[i] */ )
                 {
                     skip = 1; // can't drill via here
                     break;
                 }
 
-                if( RoutingMatrix.GetCell( nr, nc, 1 - side ) /* & blocking2[i] */ )
+                if( m_routingMatrix.GetCell( nr, nc, 1 - side ) /* & blocking2[i] */ )
                 {
                     skip = 1; // can't drill via here
                     break;
@@ -782,25 +751,25 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
             if( skip )      // neighboring hole or trace?
                 continue;   // yes, can't drill via here
 
-            newdist = d + RoutingMatrix.CalcDist( FROM_OTHERSIDE, olddir, 0, side );
+            newdist = d + m_routingMatrix.CalcDist( FROM_OTHERSIDE, olddir, 0, side );
 
             /*  if (a) not visited yet,
              *  or (b) we have found a better path,
              *  add it to queue */
-            if( !RoutingMatrix.GetDir( r, c, 1 - side ) )
+            if( !m_routingMatrix.GetDir( r, c, 1 - side ) )
             {
-                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
-                RoutingMatrix.SetDist( r, c, 1 - side, newdist );
+                m_routingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
+                m_routingMatrix.SetDist( r, c, 1 - side, newdist );
 
                 if( SetQueue( r, c, 1 - side, newdist, apx_dist, row_target, col_target ) == 0 )
                 {
                     return ERR_MEMORY;
                 }
             }
-            else if( newdist < RoutingMatrix.GetDist( r, c, 1 - side ) )
+            else if( newdist < m_routingMatrix.GetDist( r, c, 1 - side ) )
             {
-                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
-                RoutingMatrix.SetDist( r, c, 1 - side, newdist );
+                m_routingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
+                m_routingMatrix.SetDist( r, c, 1 - side, newdist );
                 ReSetQueue( r, c,
                             1 - side,
                             newdist,
@@ -812,12 +781,12 @@ static int Autoroute_One_Track( AUTOROUTER_CONTEXT& ctx,
     }
 
 end_of_route:
-    PlacePad( pt_cur_ch->m_PadStart, ~CURRENT_PAD, marge, WRITE_AND_CELL );
-    PlacePad( pt_cur_ch->m_PadEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL );
+    PlacePad( pt_cur_ch->m_padStart, ~CURRENT_PAD, marge, WRITE_AND_CELL );
+    PlacePad( pt_cur_ch->m_padEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL );
 
     msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d"),
                 OpenNodes, ClosNodes, MoveNodes );
-    ctx.pcbframe->SetStatusText( msg );
+    m_frame->SetStatusText( msg );
 
     return result;
 }
@@ -940,7 +909,7 @@ static long bit[8][9] =
  * 0 if error
  * > 0 if Ok
  */
-static int Retrace( AUTOROUTER_CONTEXT& ctx,
+int AUTOROUTER::Retrace(
                     int row_source, int col_source,
                     int row_target, int col_target, int target_side,
                     int current_net_code )
@@ -962,7 +931,7 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
     {
         // find where we came from to get here
         r2 = r1; c2 = c1; s2 = s1;
-        x  = RoutingMatrix.GetDir( r1, c1, s1 );
+        x  = m_routingMatrix.GetDir( r1, c1, s1 );
 
         switch( x )
         {
@@ -1012,7 +981,7 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
         }
 
         if( r0 != ILLEGAL )
-            y = RoutingMatrix.GetDir( r0, c0, s0 );
+            y = m_routingMatrix.GetDir( r0, c0, s0 );
 
         // see if target or hole
         if( ( ( r1 == row_target ) && ( c1 == col_target ) ) || ( s1 != s0 ) )
@@ -1055,11 +1024,11 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
 
             case FROM_OTHERSIDE:
             default:
-                DisplayError( ctx.pcbframe, wxT( "Retrace: error 1" ) );
+                DisplayError( m_frame, wxT( "Retrace: error 1" ) );
                 return 0;
             }
 
-            OrCell_Trace( ctx, r1, c1, s1, p_dir, current_net_code );
+            OrCell_Trace( r1, c1, s1, p_dir, current_net_code );
         }
         else
         {
@@ -1074,10 +1043,10 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
                     || x == FROM_OTHERSIDE )
                && ( ( b = bit[y - 1][x - 1] ) != 0 ) )
             {
-                OrCell_Trace( ctx, r1, c1, s1, b, current_net_code );
+                OrCell_Trace( r1, c1, s1, b, current_net_code );
 
                 if( b & HOLE )
-                    OrCell_Trace( ctx, r2, c2, s2, HOLE, current_net_code );
+                    OrCell_Trace( r2, c2, s2, HOLE, current_net_code );
             }
             else
             {
@@ -1130,7 +1099,7 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
                 return 0;
             }
 
-            OrCell_Trace( ctx, r2, c2, s2, p_dir, current_net_code );
+            OrCell_Trace( r2, c2, s2, p_dir, current_net_code );
         }
 
         // move to next cell
@@ -1142,7 +1111,7 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
         s1 = s2;
     } while( !( ( r2 == row_source ) && ( c2 == col_source ) ) );
 
-    AddNewTrace( ctx );
+    AddNewTrace( );
     return 1;
 }
 
@@ -1150,30 +1119,30 @@ static int Retrace( AUTOROUTER_CONTEXT& ctx,
 /* This function is used by Retrace and read the autorouting matrix data cells to create
  * the real track on the physical board
  */
-static void OrCell_Trace( AUTOROUTER_CONTEXT& ctx, int col, int row,
+void AUTOROUTER::OrCell_Trace( int col, int row,
                           int side, int orient, int current_net_code )
 {
     if( orient == HOLE )  // placement of a via
     {
-        VIA* newVia = new VIA( ctx.board );
+        VIA* newVia = new VIA( m_board );
 
         g_CurrentTrackList.PushBack( newVia );
 
         g_CurrentTrackSegment->SetState( TRACK_AR, true );
         g_CurrentTrackSegment->SetLayer( F_Cu );
 
-        g_CurrentTrackSegment->SetStart( wxPoint( ctx.bbox.GetX() + RoutingMatrix.m_GridRouting * row,
-                            ctx.bbox.GetY() + RoutingMatrix.m_GridRouting * col ) );
+        g_CurrentTrackSegment->SetStart( wxPoint( m_bbox.GetX() + m_routingMatrix.m_GridRouting * row,
+                            m_bbox.GetY() + m_routingMatrix.m_GridRouting * col ) );
         g_CurrentTrackSegment->SetEnd( g_CurrentTrackSegment->GetStart() );
 
-        g_CurrentTrackSegment->SetWidth( ctx.board->GetDesignSettings().GetCurrentViaSize() );
-        newVia->SetViaType( ctx.board->GetDesignSettings().m_CurrentViaType );
+        g_CurrentTrackSegment->SetWidth( m_board->GetDesignSettings().GetCurrentViaSize() );
+        newVia->SetViaType( m_board->GetDesignSettings().m_CurrentViaType );
 
         g_CurrentTrackSegment->SetNetCode( current_net_code );
     }
     else    // placement of a standard segment
     {
-        TRACK* newTrack = new TRACK( ctx.board );
+        TRACK* newTrack = new TRACK( m_board );
         int    dx0, dy0, dx1, dy1;
 
         g_CurrentTrackList.PushBack( newTrack );
@@ -1184,8 +1153,8 @@ static void OrCell_Trace( AUTOROUTER_CONTEXT& ctx, int col, int row,
             g_CurrentTrackSegment->SetLayer( g_Route_Layer_TOP );
 
         g_CurrentTrackSegment->SetState( TRACK_AR, true );
-        g_CurrentTrackSegment->SetEnd( wxPoint( ctx.bbox.GetX() + RoutingMatrix.m_GridRouting * row,
-                            ctx.bbox.GetY() + RoutingMatrix.m_GridRouting * col ) );
+        g_CurrentTrackSegment->SetEnd( wxPoint( m_bbox.GetX() + m_routingMatrix.m_GridRouting * row,
+                            m_bbox.GetY() + m_routingMatrix.m_GridRouting * col ) );
         g_CurrentTrackSegment->SetNetCode( current_net_code );
 
         if( g_CurrentTrackSegment->Back() == NULL ) // Start trace.
@@ -1196,17 +1165,17 @@ static void OrCell_Trace( AUTOROUTER_CONTEXT& ctx, int col, int row,
             dx1 = g_CurrentTrackSegment->GetEnd().x - g_CurrentTrackSegment->GetStart().x;
             dy1 = g_CurrentTrackSegment->GetEnd().y - g_CurrentTrackSegment->GetStart().y;
 
-            dx0 = pt_cur_ch->m_PadEnd->GetPosition().x - g_CurrentTrackSegment->GetStart().x;
-            dy0 = pt_cur_ch->m_PadEnd->GetPosition().y - g_CurrentTrackSegment->GetStart().y;
+            dx0 = pt_cur_ch->m_padEnd->GetPosition().x - g_CurrentTrackSegment->GetStart().x;
+            dy0 = pt_cur_ch->m_padEnd->GetPosition().y - g_CurrentTrackSegment->GetStart().y;
 
             // If aligned, change the origin point.
             if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) )
             {
-                g_CurrentTrackSegment->SetStart( pt_cur_ch->m_PadEnd->GetPosition() );
+                g_CurrentTrackSegment->SetStart( pt_cur_ch->m_padEnd->GetPosition() );
             }
             else    // Creation of a supplemental segment
             {
-                g_CurrentTrackSegment->SetStart( pt_cur_ch->m_PadEnd->GetPosition() );
+                g_CurrentTrackSegment->SetStart( pt_cur_ch->m_padEnd->GetPosition() );
 
                 newTrack = (TRACK*)g_CurrentTrackSegment->Clone();
                 newTrack->SetStart( g_CurrentTrackSegment->GetEnd());
@@ -1222,7 +1191,7 @@ static void OrCell_Trace( AUTOROUTER_CONTEXT& ctx, int col, int row,
             }
         }
 
-        g_CurrentTrackSegment->SetWidth( ctx.board->GetDesignSettings().GetCurrentTrackWidth() );
+        g_CurrentTrackSegment->SetWidth( m_board->GetDesignSettings().GetCurrentTrackWidth() );
 
         if( g_CurrentTrackSegment->GetStart() != g_CurrentTrackSegment->GetEnd() )
         {
@@ -1254,48 +1223,48 @@ static void OrCell_Trace( AUTOROUTER_CONTEXT& ctx, int col, int row,
  * connected
  * Center on pads even if they are off grid.
  */
-static void AddNewTrace( AUTOROUTER_CONTEXT& ctx )
+void AUTOROUTER::AddNewTrace( )
 {
     if( g_FirstTrackSegment == NULL )
         return;
 
     int dx0, dy0, dx1, dy1;
     int marge, via_marge;
-    EDA_DRAW_PANEL* panel = ctx.pcbframe->GetCanvas();
-    PCB_SCREEN* screen = ctx.pcbframe->GetScreen();
+    EDA_DRAW_PANEL* panel = m_frame->GetCanvas();
+    PCB_SCREEN* screen = m_frame->GetScreen();
 
-    marge = s_Clearance + ( ctx.pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );
-    via_marge = s_Clearance + ( ctx.pcbframe->GetDesignSettings().GetCurrentViaSize() / 2 );
+    marge = s_Clearance + ( m_frame->GetDesignSettings().GetCurrentTrackWidth() / 2 );
+    via_marge = s_Clearance + ( m_frame->GetDesignSettings().GetCurrentViaSize() / 2 );
 
     dx1 = g_CurrentTrackSegment->GetEnd().x - g_CurrentTrackSegment->GetStart().x;
     dy1 = g_CurrentTrackSegment->GetEnd().y - g_CurrentTrackSegment->GetStart().y;
 
     // Place on center of pad if off grid.
-    dx0 = pt_cur_ch->m_PadStart->GetPosition().x - g_CurrentTrackSegment->GetStart().x;
-    dy0 = pt_cur_ch->m_PadStart->GetPosition().y - g_CurrentTrackSegment->GetStart().y;
+    dx0 = pt_cur_ch->m_padStart->GetPosition().x - g_CurrentTrackSegment->GetStart().x;
+    dy0 = pt_cur_ch->m_padStart->GetPosition().y - g_CurrentTrackSegment->GetStart().y;
 
     // If aligned, change the origin point.
     if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) )
     {
-        g_CurrentTrackSegment->SetEnd( pt_cur_ch->m_PadStart->GetPosition() );
+        g_CurrentTrackSegment->SetEnd( pt_cur_ch->m_padStart->GetPosition() );
     }
     else
     {
         TRACK* newTrack = (TRACK*)g_CurrentTrackSegment->Clone();
 
-        newTrack->SetEnd( pt_cur_ch->m_PadStart->GetPosition() );
+        newTrack->SetEnd( pt_cur_ch->m_padStart->GetPosition() );
         newTrack->SetStart( g_CurrentTrackSegment->GetEnd() );
 
         g_CurrentTrackList.PushBack( newTrack );
     }
 
-    g_FirstTrackSegment->start = ctx.board->GetPad( g_FirstTrackSegment,
+    g_FirstTrackSegment->start = m_board->GetPad( g_FirstTrackSegment,
             ENDPOINT_START );
 
     if( g_FirstTrackSegment->start )
         g_FirstTrackSegment->SetState( BEGIN_ONPAD, true );
 
-    g_CurrentTrackSegment->end = ctx.board->GetPad( g_CurrentTrackSegment,
+    g_CurrentTrackSegment->end = m_board->GetPad( g_CurrentTrackSegment,
             ENDPOINT_END );
 
     if( g_CurrentTrackSegment->end )
@@ -1315,18 +1284,20 @@ static void AddNewTrace( AUTOROUTER_CONTEXT& ctx )
 
     // Put entire new current segment list in BOARD
     TRACK* track;
-    TRACK* insertBeforeMe = g_CurrentTrackSegment->GetBestInsertPoint( ctx.board );
+    TRACK* insertBeforeMe = g_CurrentTrackSegment->GetBestInsertPoint( m_board );
 
     while( ( track = g_CurrentTrackList.PopFront() ) != NULL )
     {
         ITEM_PICKER picker( track, UR_NEW );
         s_ItemsListPicker.PushItem( picker );
-        ctx.board->m_Track.Insert( track, insertBeforeMe );
+        m_board->m_Track.Insert( track, insertBeforeMe );
     }
 
+#ifdef AR_DRAW
     DrawTraces( panel, ctx.dc, firstTrack, newCount, GR_OR );
 
-    ctx.pcbframe->TestNetConnection( ctx.dc, netcode );
+    m_frame->TestNetConnection( ctx.dc, netcode );
+#endif
 
     screen->SetModify();
 }
diff --git a/pcbnew/autorouter/work.cpp b/pcbnew/autorouter/work.cpp
index 68aa48c..d579569 100644
--- a/pcbnew/autorouter/work.cpp
+++ b/pcbnew/autorouter/work.cpp
@@ -32,6 +32,17 @@
  * @file work.cpp
  * @brief Automatic routing routines
  */
+ #include <fctsys.h>
+ #include <common.h>
+ #include <macros.h>
+ #include <trigo.h>
+ #include <math_for_graphics.h>
+ #include <class_board.h>
+ #include <class_track.h>
+ #include <class_drawsegment.h>
+
+ #include <pcbnew.h>
+ #include <class_undoredo_container.h>
 
 #include <fctsys.h>
 #include <common.h>
@@ -41,31 +52,15 @@
 #include <cell.h>
 
 
-struct CWORK    // a unit of work is a source-target to connect
-                // this is a ratsnest item in the routing matrix world
-{
-    int             m_FromRow;      // source row
-    int             m_FromCol;      // source column
-    int             m_ToRow;        // target row
-    int             m_ToCol;        // target column
-    RATSNEST_ITEM*  m_Ratsnest;     // Corresponding ratsnest
-    int             m_NetCode;      // m_NetCode
-    int             m_ApxDist;      // approximate distance
-    int             m_Cost;         // cost for sort by length
-    int             m_Priority;     // route priority
 
-    // the function that calculates the cost of this ratsnest:
-    void CalculateCost();
-};
 
 
 // the list of ratsnests
-static std::vector <CWORK> WorkList;
-static unsigned Current = 0;
+
 
 
 // initialize the work list
-void InitWork()
+void AUTOROUTER::InitWork()
 {
     WorkList.clear();
     Current = 0;
@@ -78,10 +73,10 @@ void InitWork()
  *  0 if memory allocation failed
  */
 
-int SetWork( int r1, int c1,
+int AUTOROUTER::SetWork( int r1, int c1,
              int n_c,
              int r2, int c2,
-             RATSNEST_ITEM* pt_ch, int pri )
+             AR_CONNECTION* pt_ch, int pri )
 {
     CWORK item;
     item.m_FromRow    = r1;
@@ -90,7 +85,7 @@ int SetWork( int r1, int c1,
     item.m_ToRow      = r2;
     item.m_ToCol      = c2;
     item.m_Ratsnest   = pt_ch;
-    item.m_ApxDist    = RoutingMatrix.GetApxDist( r1, c1, r2, c2 );
+    item.m_ApxDist    = m_routingMatrix.GetApxDist( r1, c1, r2, c2 );
     item.CalculateCost();
     item.m_Priority   = pri;
     WorkList.push_back( item );
@@ -99,10 +94,10 @@ int SetWork( int r1, int c1,
 
 
 /* fetch a unit of work from the work list */
-void GetWork( int* r1, int* c1,
+void AUTOROUTER::GetWork( int* r1, int* c1,
               int* n_c,
               int* r2, int* c2,
-              RATSNEST_ITEM** pt_ch )
+              AR_CONNECTION** pt_ch )
 {
     if( Current < WorkList.size() )
     {
@@ -132,7 +127,7 @@ bool sort_by_cost( const CWORK& ref, const CWORK& item )
     return ref.m_Priority >= item.m_Priority;
 }
 
-void SortWork()
+void AUTOROUTER::SortWork()
 {
     sort( WorkList.begin(), WorkList.end(), sort_by_cost );
 }
diff --git a/pcbnew/connectivity_data.cpp b/pcbnew/connectivity_data.cpp
index 6498ae7..3a4199b 100644
--- a/pcbnew/connectivity_data.cpp
+++ b/pcbnew/connectivity_data.cpp
@@ -659,3 +659,42 @@ void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter )
     m_progressReporter = aReporter;
     m_connAlgo->SetProgressReporter( m_progressReporter );
 }
+
+const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForComponent( MODULE* aComponent, bool aSkipInternalConnections )
+{
+    std::set<int> nets;
+    std::set<D_PAD*> pads;
+    std::vector<CN_EDGE> edges;
+
+    for( auto pad : aComponent->Pads() )
+    {
+        nets.insert( pad->GetNetCode() );
+        pads.insert( pad );
+    }
+
+    for ( auto netcode : nets )
+    {
+        auto net = GetRatsnestForNet( netcode );
+        
+        for ( auto edge : net->GetEdges() )
+        {
+            auto srcNode = edge.GetSourceNode();
+            auto dstNode = edge.GetTargetNode();
+    
+            auto srcParent = static_cast<D_PAD*>( srcNode->Parent() );
+            auto dstParent = static_cast<D_PAD*>( dstNode->Parent() );
+
+            bool srcFound = ( pads.find(srcParent) != pads.end() );
+            bool dstFound = ( pads.find(dstParent) != pads.end() );
+
+            if ( srcFound && dstFound && !aSkipInternalConnections )
+            {
+                edges.push_back( edge );
+            } else if ( srcFound || dstFound )
+            {
+                edges.push_back( edge );
+            }
+        }
+    }
+    return edges;
+}
\ No newline at end of file
diff --git a/pcbnew/connectivity_data.h b/pcbnew/connectivity_data.h
index bf9c57e..7e7f6ce 100644
--- a/pcbnew/connectivity_data.h
+++ b/pcbnew/connectivity_data.h
@@ -48,6 +48,7 @@ class RN_DATA;
 class RN_NET;
 class TRACK;
 class D_PAD;
+class MODULE;
 class PROGRESS_REPORTER;
 
 struct CN_DISJOINT_NET_ENTRY
@@ -235,6 +236,9 @@ public:
 
     void SetProgressReporter( PROGRESS_REPORTER* aReporter );
 
+    const std::vector<CN_EDGE> GetRatsnestForComponent( MODULE* aComponent, bool aSkipInternalConnections = false );
+    
+
 private:
     
     int countRelevantItems( const std::vector<BOARD_ITEM*>& aItems );
diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp
index 0652c18..f51475e 100644
--- a/pcbnew/edit.cpp
+++ b/pcbnew/edit.cpp
@@ -156,10 +156,6 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
     case ID_POPUP_PCB_MOVE_MODULE_REQUEST:
     case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST:
     case ID_POPUP_PCB_MOVE_PCB_TARGET_REQUEST:
-    case ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES:
-    case ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE:
-    case ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES:
-    case ID_POPUP_PCB_AUTOPLACE_FREE_MODULE:
         break;
 
     case ID_POPUP_CANCEL_CURRENT_COMMAND:
@@ -1257,44 +1253,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
         m_canvas->Refresh();
         break;
 
-    case ID_POPUP_PCB_SPREAD_ALL_MODULES:
-        if( !IsOK( this,
-                   _("Not locked footprints inside the board will be moved. OK?") ) )
-            break;
-        // Fall through
-    case ID_POPUP_PCB_SPREAD_NEW_MODULES:
-        if( GetBoard()->m_Modules == NULL )
-        {
-            DisplayError( this, _( "No footprint found!" ) );
-            return;
-        }
-        else
-        {
-            MODULE* footprint = GetBoard()->m_Modules;
-            std::vector<MODULE*> footprintList;
-            for( ; footprint != NULL; footprint = footprint->Next() )
-                footprintList.push_back( footprint );
-
-            SpreadFootprints( &footprintList, id == ID_POPUP_PCB_SPREAD_NEW_MODULES,
-                              true, GetCrossHairPosition() );
-        }
-        break;
-    case ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE:
-        LockModule( (MODULE*) GetScreen()->GetCurItem(), true );
-        break;
-
-    case ID_POPUP_PCB_AUTOPLACE_FREE_MODULE:
-        LockModule( (MODULE*) GetScreen()->GetCurItem(), false );
-        break;
-
-    case ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES:
-        LockModule( NULL, false );
-        break;
-
-    case ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES:
-        LockModule( NULL, true );
-        break;
-
+   
     default:
         wxString msg;
         msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ), id );
diff --git a/pcbnew/menubar_pcb_editor.cpp b/pcbnew/menubar_pcb_editor.cpp
index 91407e2..d458c51 100644
--- a/pcbnew/menubar_pcb_editor.cpp
+++ b/pcbnew/menubar_pcb_editor.cpp
@@ -337,6 +337,23 @@ void preparePlaceMenu( wxMenu* aParentMenu )
                  _( "&Grid Origin" ),
                  _( "Set grid origin point" ),
                  KiBitmap( grid_select_axis_xpm ) );
+
+    aParentMenu->AppendSeparator();
+
+    wxMenu* autoplaceSubmenu = new wxMenu;
+    AddMenuItem( autoplaceSubmenu, ID_POPUP_PCB_AUTOPLACE_OFF_BOARD_MODULES,
+               _( "&Autoplace off-board components" ), _( "" ), KiBitmap( grid_select_axis_xpm ) // fixme: icons
+              );
+
+    AddMenuItem( autoplaceSubmenu, ID_POPUP_PCB_AUTOPLACE_SELECTED_MODULES,
+               _( "&Autoplace selected components" ), _( "" ), KiBitmap( grid_select_axis_xpm ) // fixme: icons
+              );
+
+    
+    AddMenuItem( aParentMenu, autoplaceSubmenu,
+            -1, _( "&Auto-place" ),
+            _( "Automatic component placement" ), KiBitmap( grid_select_axis_xpm ) // fixme: icons
+             );
 }
 
 
diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp
index fa1b2ce..a01d926 100644
--- a/pcbnew/onrightclick.cpp
+++ b/pcbnew/onrightclick.cpp
@@ -394,17 +394,7 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
     case ID_NO_TOOL_SELECTED:
     {
         wxMenu* commands = new wxMenu;
-        AddMenuItem( aPopMenu, commands, ID_POPUP_PCB_AUTOPLACE_COMMANDS,
-                     _( "Global Spread and Place" ), KiBitmap( move_xpm ) );
-        AddMenuItem( commands, ID_POPUP_PCB_SPREAD_ALL_MODULES,
-                     _( "Spread out All Footprints" ), KiBitmap( move_xpm ) );
-        commands->Append( ID_POPUP_PCB_SPREAD_NEW_MODULES,
-                          _( "Spread out Footprints not Already on Board" ) );
-        AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES,
-                _( "Unlock All Footprints" ), KiBitmap( unlocked_xpm ) );
-        AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES,
-                _( "Lock All Footprints" ), KiBitmap( locked_xpm ) );
-
+      
         if( !trackFound )
         {
             msg = AddHotkeyName( _( "Begin Track" ), g_Board_Editor_Hotkeys_Descr, HK_ADD_NEW_TRACK );
@@ -808,17 +798,9 @@ void PCB_EDIT_FRAME::createPopUpMenuForFootprints( MODULE* aModule, wxMenu* menu
 
     if( !aModule->IsLocked() )
     {
-        msg = AddHotkeyName( _("Lock Footprint" ), g_Board_Editor_Hotkeys_Descr,
-                             HK_LOCK_UNLOCK_FOOTPRINT );
-        AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, msg,
-                     KiBitmap( locked_xpm ) );
     }
     else
     {
-        msg = AddHotkeyName( _( "Unlock Footprint" ), g_Board_Editor_Hotkeys_Descr,
-                             HK_LOCK_UNLOCK_FOOTPRINT );
-        AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, msg,
-                     KiBitmap( unlocked_xpm ) );
     }
 
 }
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index b45924a..bc41141 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -255,12 +255,6 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
     EVT_MENU( ID_POPUP_PCB_DELETE_TRACKSEG, PCB_EDIT_FRAME::Process_Special_Functions )
     EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE,
                     PCB_EDIT_FRAME::Process_Special_Functions )
-    EVT_MENU( ID_POPUP_PCB_SPREAD_ALL_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
-    EVT_MENU( ID_POPUP_PCB_SPREAD_NEW_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
-    EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, PCB_EDIT_FRAME::Process_Special_Functions )
-    EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
-    EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
-    EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, PCB_EDIT_FRAME::Process_Special_Functions )
 
     // User interface update event handlers.
     EVT_UPDATE_UI( ID_SAVE_BOARD, PCB_EDIT_FRAME::OnUpdateSave )
diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h
index b076383..abd5008 100644
--- a/pcbnew/pcbnew_id.h
+++ b/pcbnew/pcbnew_id.h
@@ -250,28 +250,11 @@ enum pcbnew_ids
     // reserve a block of MAX_ITEMS_IN_PICKER ids for the item selection popup
     ID_POPUP_PCB_ITEM_SELECTION_START,
     ID_POPUP_PCB_ITEM_SELECTION_END = MAX_ITEMS_IN_PICKER + ID_POPUP_PCB_ITEM_SELECTION_START,
-    ID_POPUP_PCB_AUTOPLACE_START_RANGE,
-    ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE,
-    ID_POPUP_PCB_AUTOPLACE_FREE_MODULE,
-    ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES,
-    ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES,
-    ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE,
-    ID_POPUP_PCB_SPREAD_ALL_MODULES,
-    ID_POPUP_PCB_SPREAD_NEW_MODULES,
-    ID_POPUP_PCB_AUTOPLACE_COMMANDS,
-    ID_POPUP_PCB_AUTOPLACE_ALL_MODULES,
-    ID_POPUP_PCB_AUTOPLACE_NEW_MODULES,
-    ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE,
-
-    ID_POPUP_PCB_AUTOROUTE_COMMANDS,
-    ID_POPUP_PCB_AUTOROUTE_ALL_MODULES,
-    ID_POPUP_PCB_AUTOROUTE_MODULE,
-    ID_POPUP_PCB_AUTOROUTE_PAD,
-    ID_POPUP_PCB_AUTOROUTE_NET,
-
-    ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED,
-    ID_POPUP_PCB_AUTOROUTE_SELECT_LAYERS,
-    ID_POPUP_PCB_AUTOPLACE_END_RANGE,
+    
+    ID_POPUP_PCB_SPREAD_SELECTED_MODULES,
+    ID_POPUP_PCB_SPREAD_OFF_BOARD_MODULES,
+    ID_POPUP_PCB_AUTOPLACE_SELECTED_MODULES,
+    ID_POPUP_PCB_AUTOPLACE_OFF_BOARD_MODULES,
 
     ID_MENU_READ_BOARD_BACKUP_FILE,
     ID_MENU_RECOVER_BOARD_AUTOSAVE,
diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp
index cded71f..22ee622 100644
--- a/pcbnew/tools/pcb_actions.cpp
+++ b/pcbnew/tools/pcb_actions.cpp
@@ -212,6 +212,13 @@ OPT<TOOL_EVENT> PCB_ACTIONS::TranslateLegacyId( int aId )
 
     case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES:
         return PCB_ACTIONS::zoneUnfillAll.MakeEvent();
+
+    case ID_POPUP_PCB_AUTOPLACE_OFF_BOARD_MODULES:
+        return PCB_ACTIONS::autoplaceOffboardComponents.MakeEvent();
+
+    case ID_POPUP_PCB_AUTOPLACE_SELECTED_MODULES:
+        return PCB_ACTIONS::autoplaceSelectedComponents.MakeEvent();
+
     }
 
     return OPT<TOOL_EVENT>();
diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h
index b7ebf85..78d88fe 100644
--- a/pcbnew/tools/pcb_actions.h
+++ b/pcbnew/tools/pcb_actions.h
@@ -406,6 +406,8 @@ public:
     static TOOL_ACTION copySettingsToPads;
     static TOOL_ACTION globalEditPads;
 
+    static TOOL_ACTION autoplaceOffboardComponents;
+    static TOOL_ACTION autoplaceSelectedComponents;
 
     ///> @copydoc COMMON_ACTIONS::TranslateLegacyId()
     virtual OPT<TOOL_EVENT> TranslateLegacyId( int aId ) override;
diff --git a/pcbnew/tools/tools_common.cpp b/pcbnew/tools/tools_common.cpp
index 76d2d57..4bc4cfa 100644
--- a/pcbnew/tools/tools_common.cpp
+++ b/pcbnew/tools/tools_common.cpp
@@ -45,6 +45,7 @@
 
 #include <router/router_tool.h>
 #include <router/length_tuner_tool.h>
+#include <autorouter/autoplacer_tool.h>
 
 void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
 {
@@ -64,4 +65,5 @@ void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
     aToolManager->RegisterTool( new MICROWAVE_TOOL );
     aToolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
     aToolManager->RegisterTool( new ZONE_FILLER_TOOL );
+    aToolManager->RegisterTool( new AUTOPLACE_TOOL );
 }
-- 
2.7.4


Follow ups