82 changed files with 549 additions and 8136 deletions
-
2common/base_screen.cpp
-
5common/legacy_gal/eda_draw_frame.cpp
-
5common/legacy_wx/eda_draw_frame.cpp
-
1common/legacy_wx/eda_draw_panel.cpp
-
1eeschema/libedit/lib_edit_frame.cpp
-
3eeschema/sch_screen.cpp
-
2gerbview/clear_gbr_drawlayers.cpp
-
10gerbview/events_called_functions.cpp
-
20gerbview/gerbview_frame.cpp
-
12gerbview/gerbview_frame.h
-
26gerbview/tools/gerbview_control.cpp
-
1gerbview/tools/gerbview_control.h
-
21gerbview/tools/gerbview_selection_tool.cpp
-
9include/base_screen.h
-
64include/pcb_base_frame.h
-
18include/pcb_screen.h
-
18pagelayout_editor/pl_editor_screen.h
-
11pcbnew/CMakeLists.txt
-
278pcbnew/autorouter/autorout.cpp
-
248pcbnew/autorouter/autorout.h
-
171pcbnew/autorouter/dist.cpp
-
843pcbnew/autorouter/graphpcb.cpp
-
173pcbnew/autorouter/move_and_route_event_functions.cpp
-
220pcbnew/autorouter/queue.cpp
-
1332pcbnew/autorouter/solve.cpp
-
164pcbnew/autorouter/work.cpp
-
30pcbnew/class_board.cpp
-
27pcbnew/class_board.h
-
12pcbnew/class_module.h
-
41pcbnew/class_pcb_target.cpp
-
2pcbnew/cross-probing.cpp
-
258pcbnew/deltrack.cpp
-
1pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
-
7pcbnew/dialogs/dialog_drc.cpp
-
5pcbnew/dialogs/dialog_exchange_footprints.cpp
-
9pcbnew/dialogs/dialog_find.cpp
-
2pcbnew/dialogs/dialog_global_deletion.cpp
-
7pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp
-
2pcbnew/dialogs/dialog_netlist.cpp
-
122pcbnew/dialogs/dialog_target_properties.cpp
-
36pcbnew/dialogs/dialog_text_properties.cpp
-
3pcbnew/dialogs/dialog_text_properties.h
-
228pcbnew/dimension.cpp
-
175pcbnew/drag.h
-
301pcbnew/dragsegm.cpp
-
176pcbnew/edit.cpp
-
181pcbnew/edit_track_width.cpp
-
511pcbnew/editrack-part2.cpp
-
843pcbnew/editrack.cpp
-
172pcbnew/event_handlers_tracks_vias_sizes.cpp
-
22pcbnew/footprint_edit_frame.cpp
-
11pcbnew/footprint_edit_frame.h
-
11pcbnew/footprint_editor_utils.cpp
-
5pcbnew/footprint_libraries_utils.cpp
-
21pcbnew/footprint_viewer_frame.cpp
-
7pcbnew/footprint_viewer_frame.h
-
2pcbnew/footprint_wizard_frame_functions.cpp
-
4pcbnew/initpcb.cpp
-
120pcbnew/load_select_footprint.cpp
-
304pcbnew/magnetic_tracks_functions.cpp
-
145pcbnew/minimun_spanning_tree.cpp
-
101pcbnew/minimun_spanning_tree.h
-
11pcbnew/netlist.cpp
-
12pcbnew/pcb_base_edit_frame.h
-
91pcbnew/pcb_base_frame.cpp
-
4pcbnew/pcb_edit_frame.cpp
-
125pcbnew/pcb_edit_frame.h
-
233pcbnew/pcb_footprint_edit_utils.cpp
-
53pcbnew/pcb_legacy_draw_utils.cpp
-
82pcbnew/protos.h
-
145pcbnew/ratsnest.cpp
-
3pcbnew/specctra_import_export/specctra_import.cpp
-
271pcbnew/target_edit.cpp
-
4pcbnew/tools/drawing_tool.cpp
-
15pcbnew/tools/edit_tool.cpp
-
7pcbnew/tools/microwave_tool.cpp
-
26pcbnew/tools/pcbnew_control.cpp
-
1pcbnew/tools/pcbnew_control.h
-
28pcbnew/tools/selection_tool.cpp
-
1pcbnew/tracks_cleaner.cpp
-
3pcbnew/undo_redo.cpp
-
8pcbnew/zones_by_polygon.cpp
@ -1,278 +0,0 @@ |
|||
/**
|
|||
* @file autorout.cpp |
|||
* @brief Autorouting command and control. |
|||
*/ |
|||
|
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* |
|||
* 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 <wxPcbStruct.h>
|
|||
#include <gr_basic.h>
|
|||
#include <msgpanel.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <cell.h>
|
|||
#include <zones.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_module.h>
|
|||
#include <class_track.h>
|
|||
#include <convert_to_biu.h>
|
|||
|
|||
#include <autorout.h>
|
|||
|
|||
|
|||
MATRIX_ROUTING_HEAD RoutingMatrix; // routing matrix (grid) to route 2-sided boards
|
|||
|
|||
/* init board, route traces*/ |
|||
void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) |
|||
{ |
|||
int start, stop; |
|||
MODULE* Module = NULL; |
|||
D_PAD* Pad = NULL; |
|||
int autoroute_net_code = -1; |
|||
wxString msg; |
|||
|
|||
if( GetBoard()->GetCopperLayerCount() > 1 ) |
|||
{ |
|||
g_Route_Layer_TOP = GetScreen()->m_Route_Layer_TOP; |
|||
g_Route_Layer_BOTTOM = GetScreen()->m_Route_Layer_BOTTOM; |
|||
} |
|||
else |
|||
{ |
|||
g_Route_Layer_TOP = g_Route_Layer_BOTTOM = B_Cu; |
|||
} |
|||
|
|||
switch( mode ) |
|||
{ |
|||
case ROUTE_NET: |
|||
if( GetScreen()->GetCurItem() ) |
|||
{ |
|||
switch( GetScreen()->GetCurItem()->Type() ) |
|||
{ |
|||
case PCB_PAD_T: |
|||
Pad = (D_PAD*) GetScreen()->GetCurItem(); |
|||
autoroute_net_code = Pad->GetNetCode(); |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
if( autoroute_net_code <= 0 ) |
|||
{ |
|||
wxMessageBox( _( "Net not selected" ) ); return; |
|||
} |
|||
break; |
|||
|
|||
case ROUTE_MODULE: |
|||
Module = (MODULE*) GetScreen()->GetCurItem(); |
|||
if( (Module == NULL) || (Module->Type() != PCB_MODULE_T) ) |
|||
{ |
|||
wxMessageBox( _( "Footprint not selected" ) ); |
|||
return; |
|||
} |
|||
break; |
|||
|
|||
case ROUTE_PAD: |
|||
Pad = (D_PAD*) GetScreen()->GetCurItem(); |
|||
|
|||
if( (Pad == NULL) || (Pad->Type() != PCB_PAD_T) ) |
|||
{ |
|||
wxMessageBox( _( "Pad not selected" ) ); |
|||
return; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
|
|||
if( (GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 ) |
|||
Compile_Ratsnest( DC, true ); |
|||
|
|||
/* Set the flag on the ratsnest to CH_ROUTE_REQ. */ |
|||
for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ ) |
|||
{ |
|||
RATSNEST_ITEM* ptmp = &GetBoard()->m_FullRatsnest[ii]; |
|||
ptmp->m_Status &= ~CH_ROUTE_REQ; |
|||
|
|||
switch( mode ) |
|||
{ |
|||
case ROUTE_ALL: |
|||
ptmp->m_Status |= CH_ROUTE_REQ; |
|||
break; |
|||
|
|||
case ROUTE_NET: |
|||
if( autoroute_net_code == ptmp->GetNet() ) |
|||
ptmp->m_Status |= CH_ROUTE_REQ; |
|||
break; |
|||
|
|||
case ROUTE_MODULE: |
|||
{ |
|||
D_PAD* pt_pad = (D_PAD*) Module->Pads(); |
|||
for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) |
|||
{ |
|||
if( ptmp->m_PadStart == pt_pad ) |
|||
ptmp->m_Status |= CH_ROUTE_REQ; |
|||
|
|||
if( ptmp->m_PadEnd == pt_pad ) |
|||
ptmp->m_Status |= CH_ROUTE_REQ; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
|
|||
case ROUTE_PAD: |
|||
if( ( ptmp->m_PadStart == Pad ) || ( ptmp->m_PadEnd == Pad ) ) |
|||
ptmp->m_Status |= CH_ROUTE_REQ; |
|||
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
start = time( NULL ); |
|||
|
|||
/* Calculation of no fixed routing to 5 mils and more. */ |
|||
RoutingMatrix.m_GridRouting = (int)GetScreen()->GetGridSize().x; |
|||
|
|||
if( RoutingMatrix.m_GridRouting < (5*IU_PER_MILS) ) |
|||
RoutingMatrix.m_GridRouting = 5*IU_PER_MILS; |
|||
|
|||
|
|||
/* Calculated ncol and nrow, matrix size for routing. */ |
|||
RoutingMatrix.ComputeMatrixSize( GetBoard() ); |
|||
AUTOROUTER_CONTEXT ctx = { this, GetBoard(), RoutingMatrix.m_BrdBox, DC }; |
|||
|
|||
m_messagePanel->EraseMsgBox(); |
|||
|
|||
/* Map the board */ |
|||
RoutingMatrix.m_RoutingLayersCount = 1; |
|||
|
|||
if( g_Route_Layer_TOP != g_Route_Layer_BOTTOM ) |
|||
RoutingMatrix.m_RoutingLayersCount = 2; |
|||
|
|||
if( RoutingMatrix.InitRoutingMatrix() < 0 ) |
|||
{ |
|||
wxMessageBox( _( "No memory for autorouting" ) ); |
|||
RoutingMatrix.UnInitRoutingMatrix(); /* Free memory. */ |
|||
return; |
|||
} |
|||
|
|||
SetStatusText( _( "Place Cells" ) ); |
|||
PlaceCells( GetBoard(), -1, FORCE_PADS ); |
|||
|
|||
/* Construction of the track list for router. */ |
|||
RoutingMatrix.m_RouteCount = Build_Work( GetBoard() ); |
|||
|
|||
// DisplayRoutingMatrix( m_canvas, DC );
|
|||
|
|||
Solve( ctx, RoutingMatrix.m_RoutingLayersCount ); |
|||
|
|||
/* Free memory. */ |
|||
FreeQueue(); |
|||
InitWork(); /* Free memory for the list of router connections. */ |
|||
RoutingMatrix.UnInitRoutingMatrix(); |
|||
stop = time( NULL ) - start; |
|||
msg.Printf( wxT( "time = %d second%s" ), stop, ( stop == 1 ) ? wxT( "" ) : wxT( "s" ) ); |
|||
SetStatusText( msg ); |
|||
} |
|||
|
|||
|
|||
/* Clear the flag CH_NOROUTABLE which is set to 1 by Solve(),
|
|||
* when a track was not routed. |
|||
* (If this flag is 1 the corresponding track it is not rerouted) |
|||
*/ |
|||
void PCB_EDIT_FRAME::Reset_Noroutable( wxDC* DC ) |
|||
{ |
|||
if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK )== 0 ) |
|||
Compile_Ratsnest( DC, true ); |
|||
|
|||
for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ ) |
|||
{ |
|||
GetBoard()->m_FullRatsnest[ii].m_Status &= ~CH_UNROUTABLE; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* DEBUG Function: displays the routing matrix */ |
|||
void DisplayRoutingMatrix( EDA_DRAW_PANEL* panel, wxDC* DC ) |
|||
{ |
|||
int dcell0; |
|||
COLOR4D color; |
|||
|
|||
int maxi = 600 / RoutingMatrix.m_Ncols; |
|||
maxi = ( maxi * 3 ) / 4; |
|||
|
|||
if( !maxi ) |
|||
maxi = 1; |
|||
|
|||
GRSetDrawMode( DC, GR_COPY ); |
|||
|
|||
for( int col = 0; col < RoutingMatrix.m_Ncols; col++ ) |
|||
{ |
|||
for( int row = 0; row < RoutingMatrix.m_Nrows; row++ ) |
|||
{ |
|||
color = COLOR4D::BLACK; |
|||
dcell0 = RoutingMatrix.GetCell( row, col, BOTTOM ); |
|||
|
|||
if( dcell0 & HOLE ) |
|||
color = COLOR4D( GREEN ); |
|||
|
|||
#if 0
|
|||
int dcell1 = 0; |
|||
|
|||
if( RoutingMatrix.m_RoutingLayersCount ) |
|||
dcell1 = GetCell( row, col, TOP ); |
|||
|
|||
if( dcell1 & HOLE ) |
|||
color = COLOR4D( RED ); |
|||
|
|||
dcell0 |= dcell1; |
|||
#endif
|
|||
if( ( color == COLOR4D::BLACK ) && ( dcell0 & VIA_IMPOSSIBLE ) ) |
|||
color = COLOR4D( BLUE ); |
|||
|
|||
if( dcell0 & CELL_is_EDGE ) |
|||
color = COLOR4D( YELLOW ); |
|||
else if( dcell0 & CELL_is_ZONE ) |
|||
color = COLOR4D( YELLOW ); |
|||
|
|||
#define DRAW_OFFSET_X -20
|
|||
#define DRAW_OFFSET_Y 20
|
|||
// if( color )
|
|||
{ |
|||
for( int i = 0; i < maxi; i++ ) |
|||
for( int j = 0; j < maxi; j++ ) |
|||
GRPutPixel( panel->GetClipBox(), DC, |
|||
( col * maxi ) + i + DRAW_OFFSET_X, |
|||
( row * maxi ) + j + DRAW_OFFSET_Y, color ); |
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,248 +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@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* |
|||
* 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 |
|||
*/ |
|||
|
|||
/** |
|||
* @file autorout.h |
|||
*/ |
|||
|
|||
#ifndef AUTOROUT_H |
|||
#define AUTOROUT_H |
|||
|
|||
|
|||
#include <base_struct.h> |
|||
#include <class_eda_rect.h> |
|||
#include <layers_id_colors_and_visibility.h> |
|||
|
|||
|
|||
class BOARD; |
|||
class DRAWSEGMENT; |
|||
class TRACK; |
|||
class D_PAD; |
|||
class RATSNEST_ITEM; |
|||
class PCB_EDIT_FRAME; |
|||
|
|||
|
|||
#define TOP 0 |
|||
#define BOTTOM 1 |
|||
#define EMPTY 0 |
|||
#define ILLEGAL -1 |
|||
|
|||
|
|||
/* Autorouter commands. */ |
|||
enum AUTOPLACEROUTE_OPTIONS |
|||
{ |
|||
PLACE_ALL, |
|||
PLACE_OUT_OF_BOARD, |
|||
PLACE_INCREMENTAL, |
|||
PLACE_1_MODULE, |
|||
|
|||
ROUTE_ALL, |
|||
ROUTE_NET, |
|||
ROUTE_MODULE, |
|||
ROUTE_PAD |
|||
}; |
|||
|
|||
#define MAX_ROUTING_LAYERS_COUNT 2 |
|||
|
|||
#define FORCE_PADS 1 /* Force placement of pads for any Netcode */ |
|||
|
|||
/* search statistics */ |
|||
extern int OpenNodes; /* total number of nodes opened */ |
|||
extern int ClosNodes; /* total number of nodes closed */ |
|||
extern int MoveNodes; /* total number of nodes moved */ |
|||
extern int MaxNodes; /* maximum number of nodes opened at one time */ |
|||
|
|||
|
|||
/* Structures useful to the generation of board as bitmap. */ |
|||
typedef unsigned char MATRIX_CELL; |
|||
typedef int DIST_CELL; |
|||
typedef char DIR_CELL; |
|||
|
|||
struct AUTOROUTER_CONTEXT |
|||
{ |
|||
///> Parent frame |
|||
PCB_EDIT_FRAME* pcbframe; |
|||
|
|||
///> Board to be routed |
|||
BOARD* board; |
|||
|
|||
///> Cached board bounding box |
|||
const EDA_RECT bbox; |
|||
|
|||
///> Drawing context |
|||
wxDC* dc; |
|||
}; |
|||
|
|||
/** |
|||
* class MATRIX_ROUTING_HEAD |
|||
* handle the matrix routing that describes the actual board |
|||
*/ |
|||
class MATRIX_ROUTING_HEAD |
|||
{ |
|||
public: |
|||
MATRIX_CELL* m_BoardSide[MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides |
|||
DIST_CELL* m_DistSide[MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides: |
|||
// distance to cells |
|||
DIR_CELL* m_DirSide[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 |
|||
|
|||
private: |
|||
// a pointer to the current selected cell operation |
|||
void (MATRIX_ROUTING_HEAD::* m_opWriteCell)( int aRow, int aCol, |
|||
int aSide, MATRIX_CELL aCell); |
|||
|
|||
public: |
|||
MATRIX_ROUTING_HEAD(); |
|||
~MATRIX_ROUTING_HEAD(); |
|||
|
|||
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( BOARD* aPcb, bool aUseBoardEdgesOnly = false ); |
|||
|
|||
/** |
|||
* 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( int 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 ); |
|||
}; |
|||
|
|||
extern MATRIX_ROUTING_HEAD RoutingMatrix; /* 2-sided board */ |
|||
|
|||
|
|||
/* Constants used to trace the cells on the BOARD */ |
|||
#define WRITE_CELL 0 |
|||
#define WRITE_OR_CELL 1 |
|||
#define WRITE_XOR_CELL 2 |
|||
#define WRITE_AND_CELL 3 |
|||
#define WRITE_ADD_CELL 4 |
|||
|
|||
// Functions: |
|||
|
|||
/* Initialize a color value, the cells included in the board edge of the |
|||
* pad surface by pt_pad, with the margin reserved for isolation and the |
|||
* half width of the runway |
|||
* Parameters: |
|||
* Pt_pad: pointer to the description of the pad |
|||
* color: mask write in cells |
|||
* margin: add a value to the radius or half the score pad |
|||
* op_logic: type of writing in the cell (WRITE, OR) |
|||
*/ |
|||
void PlacePad( D_PAD* pt_pad, int type, int marge, int op_logic ); |
|||
|
|||
/* Draws a segment of track on the board. */ |
|||
void TraceSegmentPcb( TRACK* pt_segm, int type, int marge, int op_logic ); |
|||
void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int type, int marge, int op_logic ); |
|||
|
|||
/* Uses the color value of all cells included in the board |
|||
* coord of the rectangle ux0, uy0 (top right corner) |
|||
* a ux1, uy1 (lower left corner) (coord PCB) |
|||
* the rectangle is horizontal (or vertical) |
|||
* masque_layer = mask layers; |
|||
* op_logic = WRITE_CELL, WRITE_OR_CELL, WRITE_XOR_CELL, WRITE_AND_CELL |
|||
*/ |
|||
void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, |
|||
LSET side, int color, int op_logic); |
|||
|
|||
|
|||
/* Same as above, but the rectangle is inclined angle angle. */ |
|||
void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, |
|||
double angle, LSET masque_layer, |
|||
int color, int op_logic ); |
|||
|
|||
/* QUEUE.CPP */ |
|||
void FreeQueue(); |
|||
void InitQueue(); |
|||
void GetQueue( int *, int *, int *, int *, int * ); |
|||
bool SetQueue( int, int, int, int, int, int, int ); |
|||
void ReSetQueue( int, int, int, int, int, int, int ); |
|||
|
|||
/* WORK.CPP */ |
|||
void InitWork(); |
|||
void ReInitWork(); |
|||
int SetWork( int, int, int , int, int, RATSNEST_ITEM *, int ); |
|||
void GetWork( int *, int *, int *, int *, int *, RATSNEST_ITEM ** ); |
|||
void SortWork(); /* order the work items; shortest first */ |
|||
|
|||
/* routing_matrix.cpp */ |
|||
int Build_Work( BOARD * Pcb ); |
|||
void PlaceCells( BOARD * Pcb, int net_code, int flag = 0 ); |
|||
|
|||
|
|||
#endif // AUTOROUT_H |
@ -1,171 +0,0 @@ |
|||
/**
|
|||
* @file dist.cpp |
|||
* @brief Routines to calculate PCB editor auto routing distances. |
|||
*/ |
|||
|
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 |
|||
*/ |
|||
#include <autorout.h>
|
|||
#include <cell.h>
|
|||
|
|||
|
|||
/* 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 MATRIX_ROUTING_HEAD::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 MATRIX_ROUTING_HEAD::CalcDist(int x,int y,int z ,int side ) |
|||
{ |
|||
int adjust, ldist; |
|||
|
|||
adjust = 0; /* set if hole is encountered */ |
|||
|
|||
if( x == EMPTY ) |
|||
x = 10; |
|||
|
|||
if( y == EMPTY ) |
|||
{ |
|||
y = 10; |
|||
} |
|||
else if( y == FROM_OTHERSIDE ) |
|||
{ |
|||
if( z == EMPTY ) |
|||
z = 10; |
|||
|
|||
adjust = penalty[x-1][z-1]; |
|||
} |
|||
|
|||
ldist = dist[x-1][y-1] + penalty[x-1][y-1] + adjust; |
|||
|
|||
if( m_RouteCount > 1 ) |
|||
{ |
|||
if( side == BOTTOM ) |
|||
ldist += dir_penalty_TOP[x-1][y-1]; |
|||
|
|||
if( side == TOP ) |
|||
ldist += dir_penalty_BOTTOM[x-1][y-1]; |
|||
} |
|||
|
|||
return ldist * 10; |
|||
} |
@ -1,843 +0,0 @@ |
|||
/**
|
|||
* @file graphpcb.cpp |
|||
* @brief PCB editor autorouting and "graphics" routines. |
|||
*/ |
|||
|
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* |
|||
* 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 <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 <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 ); |
|||
|
|||
// 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 ); \ |
|||
} \ |
|||
else \ |
|||
{ \ |
|||
if( layer == g_Route_Layer_BOTTOM ) \ |
|||
RoutingMatrix.WriteCell( dy, dx, BOTTOM, color ); \ |
|||
if( RoutingMatrix.m_RoutingLayersCount > 1 ) \ |
|||
if( layer == g_Route_Layer_TOP ) \ |
|||
RoutingMatrix.WriteCell( dy, dx, TOP, color ); \ |
|||
} \ |
|||
} |
|||
|
|||
void PlacePad( D_PAD* aPad, int color, int marge, int op_logic ) |
|||
{ |
|||
int dx, dy; |
|||
wxPoint shape_pos = aPad->ShapePos(); |
|||
|
|||
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 ); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* 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 ) |
|||
{ |
|||
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; |
|||
|
|||
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 S_ARC: |
|||
TraceArc( ux0, uy0, ux1, uy1, pt_segm->GetAngle(), half_width, layer, color, op_logic ); |
|||
break; |
|||
|
|||
// The segment is here a line segment.
|
|||
default: |
|||
DrawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic ); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void TraceSegmentPcb( TRACK* aTrack, int color, int marge, int op_logic ) |
|||
{ |
|||
int half_width = ( aTrack->GetWidth() / 2 ) + marge; |
|||
|
|||
// Test if VIA (filled circle need to be drawn)
|
|||
if( aTrack->Type() == PCB_VIA_T ) |
|||
{ |
|||
LSET layer_mask; |
|||
|
|||
if( aTrack->IsOnLayer( g_Route_Layer_BOTTOM ) ) |
|||
layer_mask.set( g_Route_Layer_BOTTOM ); |
|||
|
|||
if( aTrack->IsOnLayer( g_Route_Layer_TOP ) ) |
|||
{ |
|||
if( !layer_mask.any() ) |
|||
layer_mask = LSET( g_Route_Layer_TOP ); |
|||
else |
|||
layer_mask.set(); |
|||
} |
|||
|
|||
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 - 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; |
|||
|
|||
// Ordinary track
|
|||
PCB_LAYER_ID layer = aTrack->GetLayer(); |
|||
|
|||
if( color == VIA_IMPOSSIBLE ) |
|||
layer = UNDEFINED_LAYER; |
|||
|
|||
DrawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, 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; |
|||
} |
|||
} |
@ -1,173 +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@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* |
|||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.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 move_and_route_event_functions.cpp |
|||
* @brief Routines for automatic displacement and rotation of modules. |
|||
*/ |
|||
|
|||
#include <algorithm>
|
|||
|
|||
#include <fctsys.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <confirm.h>
|
|||
#include <kicad_string.h>
|
|||
#include <pcbnew.h>
|
|||
#include <wxPcbStruct.h>
|
|||
#include <kicad_device_context.h>
|
|||
|
|||
#include <autorout.h>
|
|||
#include <cell.h>
|
|||
#include <pcbnew_id.h>
|
|||
#include <class_board.h>
|
|||
#include <class_module.h>
|
|||
|
|||
|
|||
typedef enum { |
|||
FIXE_MODULE, |
|||
FREE_MODULE, |
|||
FIXE_ALL_MODULES, |
|||
FREE_ALL_MODULES |
|||
} SelectFixeFct; |
|||
|
|||
|
|||
|
|||
wxString ModulesMaskSelection = wxT( "*" ); |
|||
|
|||
|
|||
/* Called on events (popup menus) relative to automove and autoplace footprints
|
|||
*/ |
|||
void PCB_EDIT_FRAME::OnPlaceOrRouteFootprints( wxCommandEvent& event ) |
|||
{ |
|||
int id = event.GetId(); |
|||
|
|||
if( m_mainToolBar == NULL ) |
|||
return; |
|||
|
|||
INSTALL_UNBUFFERED_DC( dc, m_canvas ); |
|||
|
|||
switch( id ) |
|||
{ |
|||
case ID_POPUP_PCB_AUTOROUTE_SELECT_LAYERS: |
|||
return; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE: |
|||
LockModule( (MODULE*) GetScreen()->GetCurItem(), true ); |
|||
return; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_FREE_MODULE: |
|||
LockModule( (MODULE*) GetScreen()->GetCurItem(), false ); |
|||
return; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES: |
|||
LockModule( NULL, false ); |
|||
return; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES: |
|||
LockModule( NULL, true ); |
|||
return; |
|||
|
|||
default: // Abort a current command (if any)
|
|||
m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); |
|||
break; |
|||
} |
|||
|
|||
// Erase ratsnest if needed
|
|||
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) ) |
|||
DrawGeneralRatsnest( &dc ); |
|||
|
|||
GetBoard()->m_Status_Pcb |= DO_NOT_SHOW_GENERAL_RASTNEST; |
|||
|
|||
switch( id ) |
|||
{ |
|||
case ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE: |
|||
AutoPlaceModule( (MODULE*) GetScreen()->GetCurItem(), PLACE_1_MODULE, &dc ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_ALL_MODULES: |
|||
AutoPlaceModule( NULL, PLACE_ALL, &dc ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_NEW_MODULES: |
|||
AutoPlaceModule( NULL, PLACE_OUT_OF_BOARD, &dc ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE: |
|||
AutoPlaceModule( NULL, PLACE_INCREMENTAL, &dc ); |
|||
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_AUTOROUTE_ALL_MODULES: |
|||
Autoroute( &dc, ROUTE_ALL ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOROUTE_MODULE: |
|||
Autoroute( &dc, ROUTE_MODULE ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOROUTE_PAD: |
|||
Autoroute( &dc, ROUTE_PAD ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOROUTE_NET: |
|||
Autoroute( &dc, ROUTE_NET ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED: |
|||
Reset_Noroutable( &dc ); |
|||
break; |
|||
|
|||
default: |
|||
wxMessageBox( wxT( "OnPlaceOrRouteFootprints command error" ) ); |
|||
break; |
|||
} |
|||
|
|||
GetBoard()->m_Status_Pcb &= ~DO_NOT_SHOW_GENERAL_RASTNEST; |
|||
Compile_Ratsnest( &dc, true ); |
|||
} |
@ -1,220 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* |
|||
* Copyright (C) 1992-2015 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 |
|||
*/ |
|||
|
|||
|
|||
/**
|
|||
* @file queue.cpp |
|||
*/ |
|||
|
|||
#include <fctsys.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <autorout.h>
|
|||
#include <cell.h>
|
|||
|
|||
|
|||
struct PcbQueue /* search queue structure */ |
|||
{ |
|||
struct PcbQueue* Next; |
|||
int Row; /* current row */ |
|||
int Col; /* current column */ |
|||
int Side; /* 0=top, 1=bottom */ |
|||
int Dist; /* path distance to this cell so far */ |
|||
int ApxDist; /* approximate distance to target from here */ |
|||
}; |
|||
|
|||
static long qlen = 0; /* current queue length */ |
|||
static struct PcbQueue* Head = NULL; |
|||
static struct PcbQueue* Tail = NULL; |
|||
static struct PcbQueue* Save = NULL; /* hold empty queue structs */ |
|||
|
|||
|
|||
/* Free the memory used for storing all the queue */ |
|||
void FreeQueue() |
|||
{ |
|||
struct PcbQueue* p; |
|||
|
|||
InitQueue(); |
|||
|
|||
while( (p = Save) != NULL ) |
|||
{ |
|||
Save = p->Next; |
|||
delete p; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* initialize the search queue */ |
|||
void InitQueue() |
|||
{ |
|||
struct PcbQueue* p; |
|||
|
|||
while( (p = Head) != NULL ) |
|||
{ |
|||
Head = p->Next; |
|||
p->Next = Save; Save = p; |
|||
} |
|||
|
|||
Tail = NULL; |
|||
OpenNodes = ClosNodes = MoveNodes = MaxNodes = qlen = 0; |
|||
} |
|||
|
|||
|
|||
/* get search queue item from list */ |
|||
void GetQueue( int* r, int* c, int* s, int* d, int* a ) |
|||
{ |
|||
struct PcbQueue* p; |
|||
|
|||
if( (p = Head) != NULL ) /* return first item in list */ |
|||
{ |
|||
*r = p->Row; *c = p->Col; |
|||
*s = p->Side; |
|||
*d = p->Dist; *a = p->ApxDist; |
|||
|
|||
if( (Head = p->Next) == NULL ) |
|||
Tail = NULL; |
|||
|
|||
/* put node on free list */ |
|||
p->Next = Save; Save = p; |
|||
ClosNodes++; qlen--; |
|||
} |
|||
else /* empty list */ |
|||
{ |
|||
*r = *c = *s = *d = *a = ILLEGAL; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* add a search node to the list
|
|||
* : |
|||
* 1 - OK |
|||
* 0 - Failed to allocate memory. |
|||
*/ |
|||
bool SetQueue( int r, int c, int side, int d, int a, int r2, int c2 ) |
|||
{ |
|||
struct PcbQueue* p, * q, * t; |
|||
int i, j; |
|||
|
|||
j = 0; // gcc warning fix
|
|||
|
|||
if( (p = Save) != NULL ) /* try free list first */ |
|||
{ |
|||
Save = p->Next; |
|||
} |
|||
else if( ( p = (PcbQueue*) operator new( sizeof( PcbQueue ), std::nothrow ) ) == NULL ) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
p->Row = r; |
|||
p->Col = c; |
|||
p->Side = side; |
|||
i = (p->Dist = d) + (p->ApxDist = a); |
|||
p->Next = NULL; |
|||
|
|||
if( (q = Head) != NULL ) /* insert in proper position in list */ |
|||
{ |
|||
if( q->Dist + q->ApxDist > i ) /* insert at head */ |
|||
{ |
|||
p->Next = q; Head = p; |
|||
} |
|||
else /* search for proper position */ |
|||
{ |
|||
for( t = q, q = q->Next; q && i > ( j = q->Dist + q->ApxDist ); t = q, q = q->Next ) |
|||
; |
|||
|
|||
if( q && i == j && q->Row == r2 && q->Col == c2 ) |
|||
{ |
|||
/* insert after q, which is a goal node */ |
|||
if( ( p->Next = q->Next ) == NULL ) |
|||
Tail = p; |
|||
|
|||
q->Next = p; |
|||
} |
|||
else /* insert in front of q */ |
|||
{ |
|||
if( ( p->Next = q ) == NULL ) |
|||
Tail = p; |
|||
|
|||
t->Next = p; |
|||
} |
|||
} |
|||
} |
|||
else /* empty search list */ |
|||
{ |
|||
Head = Tail = p; |
|||
} |
|||
|
|||
OpenNodes++; |
|||
|
|||
if( ++qlen > MaxNodes ) |
|||
MaxNodes = qlen; |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
|
|||
/* reposition node in list */ |
|||
void ReSetQueue( int r, int c, int s, int d, int a, int r2, int c2 ) |
|||
{ |
|||
struct PcbQueue* p, * q; |
|||
|
|||
/* first, see if it is already in the list */ |
|||
for( q = NULL, p = Head; p; q = p, p = p->Next ) |
|||
{ |
|||
if( p->Row == r && p->Col == c && p->Side == s ) |
|||
{ |
|||
/* old one to remove */ |
|||
if( q ) |
|||
{ |
|||
if( ( q->Next = p->Next ) == NULL ) |
|||
Tail = q; |
|||
} |
|||
else if( ( Head = p->Next ) == NULL ) |
|||
{ |
|||
Tail = NULL; |
|||
} |
|||
|
|||
p->Next = Save; |
|||
Save = p; |
|||
OpenNodes--; |
|||
MoveNodes++; |
|||
qlen--; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if( !p ) /* not found, it has already been closed once */ |
|||
ClosNodes--; /* we will close it again, but just count once */ |
|||
|
|||
/* if it was there, it's gone now; insert it at the proper position */ |
|||
bool res = SetQueue( r, c, s, d, a, r2, c2 ); |
|||
(void) res; |
|||
} |
1332
pcbnew/autorouter/solve.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,164 +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@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* |
|||
* 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 |
|||
*/ |
|||
|
|||
|
|||
/**
|
|||
* @file work.cpp |
|||
* @brief Automatic routing routines |
|||
*/ |
|||
|
|||
#include <fctsys.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <autorout.h>
|
|||
#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() |
|||
{ |
|||
WorkList.clear(); |
|||
Current = 0; |
|||
} |
|||
|
|||
|
|||
/* add a unit of work to the work list
|
|||
* : |
|||
* 1 if OK |
|||
* 0 if memory allocation failed |
|||
*/ |
|||
|
|||
int SetWork( int r1, int c1, |
|||
int n_c, |
|||
int r2, int c2, |
|||
RATSNEST_ITEM* pt_ch, int pri ) |
|||
{ |
|||
CWORK item; |
|||
item.m_FromRow = r1; |
|||
item.m_FromCol = c1; |
|||
item.m_NetCode = n_c; |
|||
item.m_ToRow = r2; |
|||
item.m_ToCol = c2; |
|||
item.m_Ratsnest = pt_ch; |
|||
item.m_ApxDist = RoutingMatrix.GetApxDist( r1, c1, r2, c2 ); |
|||
item.CalculateCost(); |
|||
item.m_Priority = pri; |
|||
WorkList.push_back( item ); |
|||
return 1; |
|||
} |
|||
|
|||
|
|||
/* fetch a unit of work from the work list */ |
|||
void GetWork( int* r1, int* c1, |
|||
int* n_c, |
|||
int* r2, int* c2, |
|||
RATSNEST_ITEM** pt_ch ) |
|||
{ |
|||
if( Current < WorkList.size() ) |
|||
{ |
|||
*r1 = WorkList[Current].m_FromRow; |
|||
*c1 = WorkList[Current].m_FromCol; |
|||
*n_c = WorkList[Current].m_NetCode; |
|||
*r2 = WorkList[Current].m_ToRow; |
|||
*c2 = WorkList[Current].m_ToCol; |
|||
*pt_ch = WorkList[Current].m_Ratsnest; |
|||
Current++; |
|||
} |
|||
else /* none left */ |
|||
{ |
|||
*r1 = *c1 = *r2 = *c2 = ILLEGAL; |
|||
*n_c = 0; |
|||
*pt_ch = NULL; |
|||
} |
|||
} |
|||
|
|||
|
|||
// order the work items; shortest (low cost) first:
|
|||
bool sort_by_cost( const CWORK& ref, const CWORK& item ) |
|||
{ |
|||
if( ref.m_Priority == item.m_Priority ) |
|||
return ref.m_Cost < item.m_Cost; |
|||
|
|||
return ref.m_Priority >= item.m_Priority; |
|||
} |
|||
|
|||
void SortWork() |
|||
{ |
|||
sort( WorkList.begin(), WorkList.end(), sort_by_cost ); |
|||
} |
|||
|
|||
|
|||
/* Calculate the cost of a ratsnest:
|
|||
* cost = (| dx | + | dy |) * disability |
|||
* disability = 1 if dx or dy = 0, max if | dx | # | dy | |
|||
*/ |
|||
void CWORK::CalculateCost() |
|||
{ |
|||
int dx, dy, mx, my; |
|||
double incl = 1.0; |
|||
|
|||
dx = abs( m_ToCol - m_FromCol ); |
|||
dy = abs( m_ToRow - m_FromRow ); |
|||
mx = dx; |
|||
my = dy; |
|||
|
|||
if( mx < my ) |
|||
{ |
|||
mx = dy; my = dx; |
|||
} |
|||
|
|||
if( mx ) |
|||
incl += (2 * (double) my / mx); |
|||
|
|||
m_Cost = (int) ( ( dx + dy ) * incl ); |
|||
} |
@ -1,258 +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@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 deltrack.cpp |
|||
*/ |
|||
|
|||
#include <fctsys.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <confirm.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <macros.h>
|
|||
#include <connectivity/connectivity_data.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <protos.h>
|
|||
|
|||
|
|||
TRACK* PCB_EDIT_FRAME::Delete_Segment( wxDC* DC, TRACK* aTrack ) |
|||
{ |
|||
if( aTrack == NULL ) |
|||
return NULL; |
|||
|
|||
if( aTrack->IsNew() ) // Trace in progress, erase the last segment
|
|||
{ |
|||
if( g_CurrentTrackList.GetCount() > 0 ) |
|||
{ |
|||
PCB_LAYER_ID previous_layer = GetActiveLayer(); |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ) |
|||
|
|||
// Delete the current trace
|
|||
ShowNewTrackWhenMovingCursor( m_canvas, DC, wxDefaultPosition, false ); |
|||
|
|||
// delete the most recently entered
|
|||
delete g_CurrentTrackList.PopBack(); |
|||
|
|||
if( Settings().m_legacyUseTwoSegmentTracks ) |
|||
{ |
|||
// if in 2 track mode, and the next most recent is a segment
|
|||
// not a via, and the one previous to that is a via, then
|
|||
// delete up to the via.
|
|||
if( g_CurrentTrackList.GetCount() >= 2 |
|||
&& g_CurrentTrackSegment->Type() != PCB_VIA_T |
|||
&& g_CurrentTrackSegment->Back()->Type() == PCB_VIA_T ) |
|||
{ |
|||
delete g_CurrentTrackList.PopBack(); |
|||
} |
|||
} |
|||
|
|||
while( g_CurrentTrackSegment && g_CurrentTrackSegment->Type() == PCB_VIA_T ) |
|||
{ |
|||
delete g_CurrentTrackList.PopBack(); |
|||
|
|||
if( g_CurrentTrackSegment && g_CurrentTrackSegment->Type() != PCB_VIA_T ) |
|||
previous_layer = g_CurrentTrackSegment->GetLayer(); |
|||
} |
|||
|
|||
// Correct active layer which could change if a via
|
|||
// has been erased
|
|||
SetActiveLayer( previous_layer ); |
|||
|
|||
UpdateStatusBar(); |
|||
|
|||
if( Settings().m_legacyUseTwoSegmentTracks ) // We must have 2 segments or more, or 0
|
|||
{ |
|||
if( g_CurrentTrackList.GetCount() == 1 |
|||
&& g_CurrentTrackSegment->Type() != PCB_VIA_T ) |
|||
{ |
|||
delete g_CurrentTrackList.PopBack(); |
|||
} |
|||
} |
|||
|
|||
if( g_CurrentTrackList.GetCount() == 0 ) |
|||
{ |
|||
m_canvas->SetMouseCapture( NULL, NULL ); |
|||
|
|||
if( GetBoard()->IsHighLightNetON() ) |
|||
HighLight( DC ); |
|||
|
|||
SetCurItem( NULL ); |
|||
return NULL; |
|||
} |
|||
else |
|||
{ |
|||
if( m_canvas->IsMouseCaptured() ) |
|||
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); |
|||
|
|||
return g_CurrentTrackSegment; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
int netcode = aTrack->GetNetCode(); |
|||
|
|||
// Remove the segment from list, but do not delete it (it will be stored in undo list)
|
|||
GetBoard()->Remove( aTrack ); |
|||
GetBoard()->GetConnectivity()->Remove( aTrack ); |
|||
|
|||
SaveCopyInUndoList( aTrack, UR_DELETED ); |
|||
OnModify(); |
|||
|
|||
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) && DC ) |
|||
{ |
|||
GRSetDrawMode( DC, GR_XOR ); |
|||
DrawGeneralRatsnest( DC, 0 ); |
|||
} |
|||
// compute and display the new ratsnest
|
|||
TestNetConnection( DC, netcode ); |
|||
SetMsgPanel( GetBoard() ); |
|||
|
|||
// redraw the area where the track was
|
|||
m_canvas->RefreshDrawingRect( aTrack->GetBoundingBox() ); |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::Delete_Track( wxDC* DC, TRACK* aTrack ) |
|||
{ |
|||
if( aTrack != NULL ) |
|||
{ |
|||
Remove_One_Track( DC, aTrack ); |
|||
OnModify(); |
|||
} |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::Delete_net( wxDC* DC, TRACK* aTrack ) |
|||
{ |
|||
if( aTrack == NULL ) |
|||
return; |
|||
|
|||
if( !IsOK( this, _( "Delete NET?" ) ) ) |
|||
return; |
|||
|
|||
PICKED_ITEMS_LIST itemsList; |
|||
ITEM_PICKER picker( NULL, UR_DELETED ); |
|||
int netcode = aTrack->GetNetCode(); |
|||
|
|||
/* Search the first item for the given net code */ |
|||
TRACK* trackList = GetBoard()->m_Track->GetStartNetCode( netcode ); |
|||
|
|||
/* Remove all segments having the given net code */ |
|||
int ii = 0; |
|||
TRACK* next_track; |
|||
for( TRACK* segm = trackList; segm; segm = next_track, ++ii ) |
|||
{ |
|||
next_track = segm->Next(); |
|||
if( segm->GetNetCode() != netcode ) |
|||
break; |
|||
|
|||
GetBoard()->GetConnectivity()->Remove( segm ); |
|||
GetBoard()->m_Track.Remove( segm ); |
|||
|
|||
// redraw the area where the track was
|
|||
m_canvas->RefreshDrawingRect( segm->GetBoundingBox() ); |
|||
picker.SetItem( segm ); |
|||
itemsList.PushItem( picker ); |
|||
} |
|||
|
|||
SaveCopyInUndoList( itemsList, UR_DELETED ); |
|||
OnModify(); |
|||
|
|||
// Erase old ratsnest
|
|||
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) ) |
|||
{ |
|||
GRSetDrawMode( DC, GR_XOR ); |
|||
DrawGeneralRatsnest( DC, 0 ); |
|||
} |
|||
|
|||
TestNetConnection( DC, netcode ); |
|||
SetMsgPanel( GetBoard() ); |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm ) |
|||
{ |
|||
int segments_to_delete_count; |
|||
|
|||
if( pt_segm == NULL ) |
|||
return; |
|||
|
|||
TRACK* trackList = GetBoard()->MarkTrace( GetBoard()->m_Track, pt_segm, |
|||
&segments_to_delete_count, |
|||
NULL, NULL, true ); |
|||
|
|||
if( segments_to_delete_count == 0 ) |
|||
return; |
|||
|
|||
int net_code = pt_segm->GetNetCode(); |
|||
PICKED_ITEMS_LIST itemsList; |
|||
ITEM_PICKER picker( NULL, UR_DELETED ); |
|||
|
|||
int ii = 0; |
|||
TRACK* tracksegment = trackList; |
|||
TRACK* next_track; |
|||
|
|||
for( ; ii < segments_to_delete_count; ii++, tracksegment = next_track ) |
|||
{ |
|||
next_track = tracksegment->Next(); |
|||
tracksegment->SetState( BUSY, false ); |
|||
|
|||
DBG( std::cout << __func__ << ": track " << tracksegment << " status=" \ |
|||
<< TO_UTF8( TRACK::ShowState( tracksegment->GetStatus() ) ) \ |
|||
<< std::endl; ) |
|||
|
|||
GetBoard()->GetConnectivity()->Remove( tracksegment ); |
|||
GetBoard()->m_Track.Remove( tracksegment ); |
|||
|
|||
// redraw the area where the track was
|
|||
m_canvas->RefreshDrawingRect( tracksegment->GetBoundingBox() ); |
|||
picker.SetItem( tracksegment ); |
|||
itemsList.PushItem( picker ); |
|||
} |
|||
|
|||
SaveCopyInUndoList( itemsList, UR_DELETED ); |
|||
|
|||
if( net_code > 0 ) |
|||
{ |
|||
// Erase old ratsnest
|
|||
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) ) |
|||
{ |
|||
GRSetDrawMode( DC, GR_XOR ); |
|||
DrawGeneralRatsnest( DC, 0 ); |
|||
} |
|||
|
|||
// Build and draw the new ratsnest
|
|||
TestNetConnection( DC, net_code ); |
|||
} |
|||
} |
@ -0,0 +1,122 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.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 <pcb_edit_frame.h>
|
|||
#include <dialog_helpers.h>
|
|||
#include <base_units.h>
|
|||
#include <gr_basic.h>
|
|||
#include <board_commit.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_pcb_target.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <dialog_target_properties_base.h>
|
|||
#include <widgets/unit_binder.h>
|
|||
|
|||
|
|||
class DIALOG_TARGET_PROPERTIES : public DIALOG_TARGET_PROPERTIES_BASE |
|||
{ |
|||
private: |
|||
PCB_EDIT_FRAME* m_Parent; |
|||
PCB_TARGET* m_Target; |
|||
|
|||
UNIT_BINDER m_Size; |
|||
UNIT_BINDER m_Thickness; |
|||
|
|||
public: |
|||
DIALOG_TARGET_PROPERTIES( PCB_EDIT_FRAME* aParent, PCB_TARGET* aTarget ); |
|||
~DIALOG_TARGET_PROPERTIES() { } |
|||
|
|||
private: |
|||
bool TransferDataToWindow() override; |
|||
bool TransferDataFromWindow() override; |
|||
}; |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::ShowTargetOptionsDialog( PCB_TARGET* aTarget ) |
|||
{ |
|||
DIALOG_TARGET_PROPERTIES dialog( this, aTarget ); |
|||
|
|||
dialog.ShowModal(); |
|||
} |
|||
|
|||
|
|||
DIALOG_TARGET_PROPERTIES::DIALOG_TARGET_PROPERTIES( PCB_EDIT_FRAME* aParent, PCB_TARGET* aTarget ) : |
|||
DIALOG_TARGET_PROPERTIES_BASE( aParent ), |
|||
m_Parent( aParent ), |
|||
m_Target( aTarget ), |
|||
m_Size( aParent, m_sizeLabel, m_sizeCtrl, m_sizeUnits, true ), |
|||
m_Thickness( aParent, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true ) |
|||
{ |
|||
m_sdbSizerButtsOK->SetDefault(); |
|||
|
|||
SetInitialFocus( m_sizeCtrl ); |
|||
|
|||
// Now all widgets have the size fixed, call FinishDialogSettings
|
|||
FinishDialogSettings(); |
|||
} |
|||
|
|||
|
|||
bool DIALOG_TARGET_PROPERTIES::TransferDataToWindow() |
|||
{ |
|||
m_Size.SetValue( m_Target->GetSize() ); |
|||
m_Thickness.SetValue( m_Target->GetWidth() ); |
|||
|
|||
m_TargetShape->SetSelection( m_Target->GetShape() ? 1 : 0 ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool DIALOG_TARGET_PROPERTIES::TransferDataFromWindow() |
|||
{ |
|||
// Zero-size targets are hard to see/select.
|
|||
if( !m_Size.Validate( Mils2iu( 1 ), INT_MAX ) ) |
|||
return false; |
|||
|
|||
BOARD_COMMIT commit( m_Parent ); |
|||
commit.Modify( m_Target ); |
|||
|
|||
// Save old item in undo list, if is is not currently edited (will be later if so)
|
|||
bool pushCommit = ( m_Target->GetEditFlags() == 0 ); |
|||
|
|||
if( m_Target->GetEditFlags() != 0 ) // other edit in progress (MOVE, NEW ..)
|
|||
m_Target->SetFlags( IN_EDIT ); // set flag in edit to force
|
|||
// undo/redo/abort proper operation
|
|||
|
|||
m_Target->SetWidth( m_Thickness.GetValue() ); |
|||
m_Target->SetSize( m_Size.GetValue() ); |
|||
m_Target->SetShape( m_TargetShape->GetSelection() ? 1 : 0 ); |
|||
|
|||
if( pushCommit ) |
|||
commit.Push( _( "Modified alignment target" ) ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
@ -1,228 +0,0 @@ |
|||
/**
|
|||
* @file dimension.cpp |
|||
* @brief Dialog and code for editing a dimension object. |
|||
*/ |
|||
|
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.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 <confirm.h>
|
|||
#include <gr_basic.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <draw_graphic_text.h>
|
|||
#include <dialog_helpers.h>
|
|||
#include <macros.h>
|
|||
#include <base_units.h>
|
|||
#include <board_commit.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_pcb_text.h>
|
|||
#include <class_dimension.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <pcb_layer_box_selector.h>
|
|||
#include <dialogs/dialog_text_properties.h>
|
|||
|
|||
/* Local functions */ |
|||
static void BuildDimension( EDA_DRAW_PANEL* aPanel, wxDC* aDC, |
|||
const wxPoint& aPosition, bool aErase ); |
|||
|
|||
/* Local variables : */ |
|||
static int status_dimension; /* Used in dimension creation:
|
|||
* = 0 : initial value: no dimension in progress |
|||
* = 1 : First point created |
|||
* = 2 : Second point created, the text must be placed */ |
|||
|
|||
/*
|
|||
* A dimension has this shape: |
|||
* It has 2 reference points, and a text |
|||
* | | |
|||
* | dist | |
|||
* |<---------->| |
|||
* | | |
|||
* |
|||
*/ |
|||
|
|||
static void AbortBuildDimension( EDA_DRAW_PANEL* Panel, wxDC* aDC ) |
|||
{ |
|||
DIMENSION* dimension = (DIMENSION*) Panel->GetScreen()->GetCurItem(); |
|||
|
|||
if( dimension ) |
|||
{ |
|||
if( dimension->IsNew() ) |
|||
{ |
|||
dimension->Draw( Panel, aDC, GR_XOR ); |
|||
dimension->DeleteStructure(); |
|||
} |
|||
else |
|||
{ |
|||
dimension->Draw( Panel, aDC, GR_OR ); |
|||
} |
|||
} |
|||
|
|||
status_dimension = 0; |
|||
((PCB_EDIT_FRAME*)Panel->GetParent())->SetCurItem( NULL ); |
|||
} |
|||
|
|||
|
|||
DIMENSION* PCB_EDIT_FRAME::EditDimension( DIMENSION* aDimension, wxDC* aDC ) |
|||
{ |
|||
wxPoint pos; |
|||
|
|||
if( aDimension == NULL ) |
|||
{ |
|||
const BOARD_DESIGN_SETTINGS& boardSettings = GetBoard()->GetDesignSettings(); |
|||
|
|||
status_dimension = 1; |
|||
pos = GetCrossHairPosition(); |
|||
|
|||
aDimension = new DIMENSION( GetBoard() ); |
|||
aDimension->SetFlags( IS_NEW ); |
|||
aDimension->SetLayer( GetActiveLayer() ); |
|||
aDimension->SetOrigin( pos ); |
|||
aDimension->SetEnd( pos ); |
|||
|
|||
aDimension->Text().SetTextSize( boardSettings.GetTextSize( GetActiveLayer() ) ); |
|||
aDimension->Text().SetThickness( boardSettings.GetTextThickness( GetActiveLayer() ) ); |
|||
aDimension->Text().SetItalic( boardSettings.GetTextItalic( GetActiveLayer() ) ); |
|||
aDimension->SetWidth( boardSettings.GetLineThickness( GetActiveLayer() ) ); |
|||
aDimension->AdjustDimensionDetails(); |
|||
aDimension->Draw( m_canvas, aDC, GR_XOR ); |
|||
|
|||
m_canvas->SetMouseCapture( BuildDimension, AbortBuildDimension ); |
|||
return aDimension; |
|||
} |
|||
|
|||
// Dimension != NULL
|
|||
if( status_dimension == 1 ) |
|||
{ |
|||
status_dimension = 2; |
|||
return aDimension; |
|||
} |
|||
|
|||
aDimension->Draw( m_canvas, aDC, GR_OR ); |
|||
aDimension->ClearFlags(); |
|||
|
|||
/* ADD this new item in list */ |
|||
GetBoard()->Add( aDimension ); |
|||
|
|||
// Add store it in undo/redo list
|
|||
SaveCopyInUndoList( aDimension, UR_NEW ); |
|||
|
|||
OnModify(); |
|||
m_canvas->SetMouseCapture( NULL, NULL ); |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
static void BuildDimension( EDA_DRAW_PANEL* aPanel, wxDC* aDC, |
|||
const wxPoint& aPosition, bool aErase ) |
|||
{ |
|||
PCB_SCREEN* screen = (PCB_SCREEN*) aPanel->GetScreen(); |
|||
DIMENSION* Dimension = (DIMENSION*) screen->GetCurItem(); |
|||
wxPoint pos = aPanel->GetParent()->GetCrossHairPosition(); |
|||
|
|||
if( Dimension == NULL ) |
|||
return; |
|||
|
|||
// Erase previous dimension.
|
|||
if( aErase ) |
|||
{ |
|||
Dimension->Draw( aPanel, aDC, GR_XOR ); |
|||
} |
|||
|
|||
Dimension->SetLayer( screen->m_Active_Layer ); |
|||
|
|||
if( status_dimension == 1 ) |
|||
{ |
|||
Dimension->m_featureLineDO = pos; |
|||
Dimension->m_crossBarF = Dimension->m_featureLineDO; |
|||
Dimension->AdjustDimensionDetails(); |
|||
} |
|||
else |
|||
{ |
|||
/* Calculating the direction of travel perpendicular to the selected axis. */ |
|||
double angle = Dimension->GetAngle() + (M_PI / 2); |
|||
|
|||
wxPoint delta = pos - Dimension->m_featureLineDO; |
|||
double depl = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) ); |
|||
Dimension->SetHeight( depl ); |
|||
} |
|||
|
|||
Dimension->Draw( aPanel, aDC, GR_XOR ); |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::ShowDimensionPropertyDialog( DIMENSION* aDimension, wxDC* aDC ) |
|||
{ |
|||
if( aDimension == NULL ) |
|||
return; |
|||
|
|||
DIALOG_TEXT_PROPERTIES dlg( this, aDimension, aDC ); |
|||
dlg.ShowModal(); |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::DeleteDimension( DIMENSION* aDimension, wxDC* aDC ) |
|||
{ |
|||
if( aDimension == NULL ) |
|||
return; |
|||
|
|||
if( aDC ) |
|||
aDimension->Draw( m_canvas, aDC, GR_XOR ); |
|||
|
|||
SaveCopyInUndoList( aDimension, UR_DELETED ); |
|||
aDimension->UnLink(); |
|||
OnModify(); |
|||
} |
|||
|
|||
|
|||
/* Initialize parameters to move a pcb text
|
|||
*/ |
|||
static wxPoint initialTextPosition; |
|||
|
|||
/*
|
|||
* Place the current dimension text being moving |
|||
*/ |
|||
void PCB_EDIT_FRAME::PlaceDimensionText( DIMENSION* aItem, wxDC* DC ) |
|||
{ |
|||
m_canvas->SetMouseCapture( NULL, NULL ); |
|||
SetCurItem( NULL ); |
|||
|
|||
if( aItem == NULL ) |
|||
return; |
|||
|
|||
aItem->Draw( m_canvas, DC, GR_OR ); |
|||
OnModify(); |
|||
|
|||
wxPoint tmp = aItem->Text().GetTextPos(); |
|||
aItem->Text().SetTextPos( initialTextPosition ); |
|||
SaveCopyInUndoList( aItem, UR_CHANGED ); |
|||
aItem->Text().SetTextPos( tmp ); |
|||
aItem->ClearFlags(); |
|||
} |
@ -1,175 +0,0 @@ |
|||
/** |
|||
* @file drag.h |
|||
* @brief Useful classes and functions used to collect tracks to drag |
|||
*/ |
|||
|
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2012 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* 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 _DRAG_H_ |
|||
#define _DRAG_H_ |
|||
|
|||
|
|||
#include <class_track.h> |
|||
#include <vector> |
|||
|
|||
|
|||
class wxDC; |
|||
class wxPoint; |
|||
class EDA_DRAW_PANEL; |
|||
class MODULE; |
|||
class D_PAD; |
|||
class CONNECTIONS; |
|||
|
|||
|
|||
/** Helper classes to handle a list of track segments to drag |
|||
* and has info to undo/abort the move command |
|||
*/ |
|||
|
|||
/* |
|||
* a DRAG_LIST manages the list of track segments to modify |
|||
* when the pad or the module is moving in drag mode |
|||
*/ |
|||
|
|||
/** |
|||
* a DRAG_SEGM_PICKER manage one track segment or a via |
|||
*/ |
|||
class DRAG_SEGM_PICKER |
|||
{ |
|||
public: |
|||
TRACK* m_Track; // pointer to the parent track segment |
|||
D_PAD* m_Pad_Start; // pointer to the moving pad |
|||
// if the start point should follow this pad |
|||
// or NULL |
|||
D_PAD* m_Pad_End; // pointer to the moving pad |
|||
// if the end point should follow this pad |
|||
// or NULL |
|||
int m_TempFlags; // flag used in drag vias and drag track segment functions |
|||
|
|||
private: |
|||
double m_RotationOffset; // initial orientation of the parent module |
|||
// Used to recalculate m_PadStartOffset and m_PadEndOffset |
|||
// after a module rotation when dragging |
|||
bool m_Flipped; // initial side of the parent module |
|||
// Used to recalculate m_PadStartOffset and m_PadEndOffset |
|||
// if the module is flipped when dragging |
|||
wxPoint m_PadStartOffset; // offset between the pad and the starting point of the track |
|||
// usually 0,0, but not always |
|||
wxPoint m_PadEndOffset; // offset between the pad and the ending point of the track |
|||
// usually 0,0, but not always |
|||
wxPoint m_startInitialValue; |
|||
wxPoint m_endInitialValue; // For abort command: |
|||
// initial m_Start and m_End values for m_Track |
|||
|
|||
public: |
|||
|
|||
DRAG_SEGM_PICKER( TRACK* aTrack ); |
|||
~DRAG_SEGM_PICKER() {}; |
|||
|
|||
/** |
|||
* Set auxiliary parameters relative to calculations needed |
|||
* to find track ends positions while dragging pads |
|||
* and when modules are rotated, flipped |
|||
*/ |
|||
void SetAuxParameters(); |
|||
|
|||
/** |
|||
* Calculate track ends position while dragging pads |
|||
* and when modules are rotated, flipped |
|||
* @param aOffset = offset of module or pad position (when moving) |
|||
*/ |
|||
void SetTrackEndsCoordinates( wxPoint aOffset ); |
|||
|
|||
void RestoreInitialValues() |
|||
{ |
|||
m_Track->SetStart( m_startInitialValue ); |
|||
m_Track->SetEnd( m_endInitialValue ); |
|||
} |
|||
}; |
|||
|
|||
|
|||
class DRAG_LIST |
|||
{ |
|||
public: |
|||
BOARD* m_Brd; // the main board |
|||
MODULE* m_Module; // The link to the module to move, or NULL |
|||
D_PAD* m_Pad; // The link to the pad to move, or NULL |
|||
|
|||
std::vector<DRAG_SEGM_PICKER> m_DragList; // The list of DRAG_SEGM_PICKER items |
|||
|
|||
public: |
|||
DRAG_LIST( BOARD* aPcb ) |
|||
{ |
|||
m_Brd = aPcb; |
|||
m_Module = NULL; |
|||
m_Pad = NULL; |
|||
} |
|||
|
|||
/** |
|||
* Function ClearList |
|||
* clear the .m_Flags of all track segments in m_DragList |
|||
* and clear the list. |
|||
*/ |
|||
void ClearList(); |
|||
|
|||
/** Build the list of track segments connected to pads of aModule |
|||
* in m_DragList |
|||
* For each selected track segment the EDIT flag is set |
|||
*/ |
|||
void BuildDragListe( MODULE* aModule ); |
|||
|
|||
/** Build the list of track segments connected to aPad |
|||
* in m_DragList |
|||
* For each selected track segment the EDIT flag is set |
|||
*/ |
|||
void BuildDragListe( D_PAD* aPad ); |
|||
|
|||
private: |
|||
|
|||
/** Fills m_DragList with of track segments connected to pads in aConnections |
|||
* For each selected track segment the EDIT flag is set |
|||
*/ |
|||
void fillList( std::vector<D_PAD*>& aList ); |
|||
}; |
|||
|
|||
|
|||
// Global variables: |
|||
|
|||
// a list of DRAG_SEGM_PICKER items used to move or drag tracks. |
|||
// Each DRAG_SEGM_PICKER item points a segment to move. |
|||
extern std::vector<DRAG_SEGM_PICKER> g_DragSegmentList; |
|||
|
|||
// Functions: |
|||
void DrawSegmentWhileMovingFootprint( EDA_DRAW_PANEL* panel, wxDC* DC ); |
|||
|
|||
/** |
|||
* Function EraseDragList |
|||
* clear the .m_Flags of all track segments stored in g_DragSegmentList |
|||
* and clear the list. |
|||
* In order to avoid useless memory reallocation, the memory is not freed |
|||
* and will be reused when creating a new list |
|||
*/ |
|||
void EraseDragList(); |
|||
|
|||
#endif // _DRAG_H_ |
@ -1,301 +0,0 @@ |
|||
/**
|
|||
* @file dragsegm.cpp |
|||
* @brief Classes to find track segments connected to a pad or a module |
|||
* for drag commands |
|||
*/ |
|||
|
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2012 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* 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 <common.h>
|
|||
#include <trigo.h>
|
|||
#include <gr_basic.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <pcb_base_frame.h>
|
|||
#include <macros.h>
|
|||
|
|||
#include <drag.h>
|
|||
#include <pcbnew.h>
|
|||
|
|||
#include <class_module.h>
|
|||
#include <class_board.h>
|
|||
#include <connectivity/connectivity_data.h>
|
|||
|
|||
/* a list of DRAG_SEGM_PICKER items used to move or drag tracks */ |
|||
std::vector<DRAG_SEGM_PICKER> g_DragSegmentList; |
|||
|
|||
/* helper class to handle a list of track segments to drag or move
|
|||
*/ |
|||
DRAG_SEGM_PICKER::DRAG_SEGM_PICKER( TRACK* aTrack ) |
|||
{ |
|||
m_Track = aTrack; |
|||
m_startInitialValue = m_Track->GetStart(); |
|||
m_endInitialValue = m_Track->GetEnd(); |
|||
m_Pad_Start = m_Track->GetState( START_ON_PAD ) ? (D_PAD*)m_Track->start : NULL; |
|||
m_Pad_End = m_Track->GetState( END_ON_PAD ) ? (D_PAD*)m_Track->end : NULL; |
|||
m_TempFlags = 0; |
|||
m_RotationOffset = 0.0; |
|||
m_Flipped = false; |
|||
} |
|||
|
|||
|
|||
void DRAG_SEGM_PICKER::SetAuxParameters() |
|||
{ |
|||
MODULE* module = NULL; |
|||
|
|||
if( m_Pad_Start ) |
|||
{ |
|||
module = m_Pad_Start->GetParent(); |
|||
m_PadStartOffset = m_Track->GetStart() - m_Pad_Start->GetPosition(); |
|||
} |
|||
|
|||
if( m_Pad_End ) |
|||
{ |
|||
if( module == NULL ) |
|||
module = m_Pad_End->GetParent(); |
|||
|
|||
m_PadEndOffset = m_Track->GetEnd() - m_Pad_End->GetPosition(); |
|||
} |
|||
|
|||
if( module ) |
|||
{ |
|||
m_Flipped = module->IsFlipped(); |
|||
m_RotationOffset = module->GetOrientation(); |
|||
} |
|||
} |
|||
|
|||
|
|||
void DRAG_SEGM_PICKER::SetTrackEndsCoordinates( wxPoint aOffset ) |
|||
{ |
|||
// the track start position is the pad position + m_PadStartOffset
|
|||
// however m_PadStartOffset is known for the initial rotation/flip
|
|||
// this is also true for track end position and m_PadEndOffset
|
|||
// Therefore, because rotation/flipping is allowed during a drag
|
|||
// and move module, we should recalculate the pad offset,
|
|||
// depending on the current orientation/flip state of the module
|
|||
// relative to its initial orientation.
|
|||
// (although most of time, offset is 0,0)
|
|||
|
|||
double curr_rot_offset = m_RotationOffset; |
|||
MODULE* module = NULL; |
|||
bool flip = false; |
|||
|
|||
if( m_Pad_Start ) |
|||
module = m_Pad_Start->GetParent(); |
|||
|
|||
if( module == NULL && m_Pad_End ) |
|||
module = m_Pad_End->GetParent(); |
|||
|
|||
if( module ) |
|||
{ |
|||
flip = m_Flipped != module->IsFlipped(); |
|||
curr_rot_offset = module->GetOrientation() - m_RotationOffset; |
|||
|
|||
if( flip ) // when flipping, module orientation is negated
|
|||
curr_rot_offset = - module->GetOrientation() - m_RotationOffset; |
|||
} |
|||
|
|||
if( m_Pad_Start ) |
|||
{ |
|||
wxPoint padoffset = m_PadStartOffset; |
|||
|
|||
if( curr_rot_offset != 0.0 ) |
|||
RotatePoint(&padoffset, curr_rot_offset); |
|||
|
|||
if( flip ) |
|||
padoffset.y = -padoffset.y; |
|||
|
|||
m_Track->SetStart( m_Pad_Start->GetPosition() - aOffset + padoffset ); |
|||
} |
|||
|
|||
if( m_Pad_End ) |
|||
{ |
|||
wxPoint padoffset = m_PadEndOffset; |
|||
|
|||
if( curr_rot_offset != 0.0 ) |
|||
RotatePoint( &padoffset, curr_rot_offset ); |
|||
|
|||
if( flip ) |
|||
padoffset.y = -padoffset.y; |
|||
|
|||
m_Track->SetEnd( m_Pad_End->GetPosition() - aOffset + padoffset ); |
|||
} |
|||
} |
|||
|
|||
|
|||
// A sort function needed to build ordered pads lists
|
|||
extern bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp ); |
|||
|
|||
|
|||
void DRAG_LIST::BuildDragListe( MODULE* aModule ) |
|||
{ |
|||
m_Pad = NULL; |
|||
m_Module = aModule; |
|||
|
|||
std::vector<D_PAD*> padList; |
|||
|
|||
for( auto pad : aModule->Pads() ) |
|||
padList.push_back( pad ); |
|||
|
|||
sort( padList.begin(), padList.end(), sortPadsByXthenYCoord ); |
|||
|
|||
fillList( padList ); |
|||
} |
|||
|
|||
|
|||
void DRAG_LIST::BuildDragListe( D_PAD* aPad ) |
|||
{ |
|||
m_Pad = aPad; |
|||
m_Module = NULL; |
|||
|
|||
// Build connections info
|
|||
std::vector<D_PAD*> padList; |
|||
padList.push_back( aPad ); |
|||
|
|||
fillList( padList ); |
|||
} |
|||
|
|||
|
|||
// A helper function to sort track list per tracks
|
|||
bool sort_tracklist( const DRAG_SEGM_PICKER& ref, const DRAG_SEGM_PICKER& tst ) |
|||
{ |
|||
return ref.m_Track < tst.m_Track; |
|||
} |
|||
|
|||
void DRAG_LIST::fillList( std::vector<D_PAD*>& aList ) |
|||
{ |
|||
// clear flags and variables of selected tracks
|
|||
for( auto pad : aList ) |
|||
{ |
|||
auto connectedTracks = m_Brd->GetConnectivity()->GetConnectedTracks( pad ); |
|||
|
|||
// store track connected to the pad
|
|||
for( auto track : connectedTracks ) |
|||
{ |
|||
track->start = NULL; |
|||
track->end = NULL; |
|||
track->SetState( START_ON_PAD|END_ON_PAD|BUSY, false ); |
|||
} |
|||
} |
|||
|
|||
// store tracks connected to pads
|
|||
for( auto pad : aList ) |
|||
{ |
|||
auto connectedTracks = m_Brd->GetConnectivity()->GetConnectedTracks( pad ); |
|||
|
|||
// store track connected to the pad
|
|||
for( auto track : connectedTracks ) |
|||
{ |
|||
if( pad->HitTest( track->GetStart() ) ) |
|||
{ |
|||
track->start = pad; |
|||
track->SetState( START_ON_PAD, true ); |
|||
} |
|||
|
|||
if( pad->HitTest( track->GetEnd() ) ) |
|||
{ |
|||
track->end = pad; |
|||
track->SetState( END_ON_PAD, true ); |
|||
} |
|||
|
|||
DRAG_SEGM_PICKER wrapper( track ); |
|||
m_DragList.push_back( wrapper ); |
|||
} |
|||
} |
|||
|
|||
// remove duplicate in m_DragList:
|
|||
// a track can be stored more than once if connected to 2 overlapping pads, or
|
|||
// each track end connected to 2 moving pads
|
|||
// to avoid artifact in draw function, items should be not duplicated
|
|||
// However, there is not a lot of items to be removed, so there ir no optimization.
|
|||
|
|||
// sort the drag list by track pointers
|
|||
sort( m_DragList.begin(), m_DragList.end(), sort_tracklist ); |
|||
|
|||
// Explore the list, merge duplicates
|
|||
for( int ii = 0; ii < (int)m_DragList.size()-1; ii++ ) |
|||
{ |
|||
int jj = ii+1; |
|||
|
|||
if( m_DragList[ii].m_Track != m_DragList[jj].m_Track ) |
|||
continue; |
|||
|
|||
// duplicate found: merge info and remove duplicate
|
|||
if( m_DragList[ii].m_Pad_Start == NULL ) |
|||
m_DragList[ii].m_Pad_Start = m_DragList[jj].m_Pad_Start; |
|||
|
|||
if( m_DragList[ii].m_Pad_End == NULL ) |
|||
m_DragList[ii].m_Pad_End = m_DragList[jj].m_Pad_End; |
|||
|
|||
m_DragList.erase( m_DragList.begin() + jj ); |
|||
ii--; |
|||
} |
|||
|
|||
// Initialize pad offsets and other params
|
|||
for( unsigned ii = 0; ii < m_DragList.size(); ii++ ) |
|||
m_DragList[ii].SetAuxParameters(); |
|||
|
|||
// Copy the list in global list
|
|||
g_DragSegmentList = m_DragList; |
|||
} |
|||
|
|||
|
|||
void DRAG_LIST::ClearList() |
|||
{ |
|||
for( unsigned ii = 0; ii < m_DragList.size(); ii++ ) |
|||
m_DragList[ii].m_Track->ClearFlags(); |
|||
|
|||
m_DragList.clear(); |
|||
|
|||
m_Module = NULL; |
|||
m_Pad = NULL; |
|||
} |
|||
|
|||
|
|||
// Redraw the list of segments stored in g_DragSegmentList, while moving a footprint
|
|||
void DrawSegmentWhileMovingFootprint( EDA_DRAW_PANEL* panel, wxDC* DC ) |
|||
{ |
|||
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) |
|||
{ |
|||
TRACK* track = g_DragSegmentList[ii].m_Track; |
|||
|
|||
#ifndef USE_WX_OVERLAY
|
|||
track->Draw( panel, DC, GR_XOR ); // erase from screen at old position
|
|||
#endif
|
|||
g_DragSegmentList[ii].SetTrackEndsCoordinates( g_Offset_Module ); |
|||
track->Draw( panel, DC, GR_XOR ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void EraseDragList() |
|||
{ |
|||
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) |
|||
g_DragSegmentList[ii].m_Track->ClearFlags(); |
|||
|
|||
g_DragSegmentList.clear(); |
|||
} |
|||
|
|||
|
@ -1,511 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.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 editrack-part2.cpp |
|||
*/ |
|||
|
|||
|
|||
#include <fctsys.h>
|
|||
#include <gr_basic.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <confirm.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_module.h>
|
|||
#include <class_track.h>
|
|||
#include <class_marker_pcb.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <drc.h>
|
|||
|
|||
#include <connectivity/connectivity_data.h>
|
|||
|
|||
|
|||
bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) |
|||
{ |
|||
unsigned itmp; |
|||
|
|||
if( aTrack == NULL ) |
|||
{ |
|||
if( GetActiveLayer() != GetScreen()->m_Route_Layer_TOP ) |
|||
SetActiveLayer( GetScreen()->m_Route_Layer_TOP ); |
|||
else |
|||
SetActiveLayer( GetScreen()->m_Route_Layer_BOTTOM ); |
|||
|
|||
UpdateStatusBar(); |
|||
return true; |
|||
} |
|||
|
|||
// Avoid more than one via on the current location:
|
|||
if( GetBoard()->GetViaByPosition( g_CurrentTrackSegment->GetEnd(), |
|||
g_CurrentTrackSegment->GetLayer() ) ) |
|||
return false; |
|||
|
|||
for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() ) |
|||
{ |
|||
if( segm->Type() == PCB_VIA_T && g_CurrentTrackSegment->GetEnd() == segm->GetStart() ) |
|||
return false; |
|||
} |
|||
|
|||
// Is the current segment Ok (no DRC error) ?
|
|||
if( Settings().m_legacyDrcOn ) |
|||
{ |
|||
if( BAD_DRC==m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment, GetBoard()->m_Track ) ) |
|||
// DRC error, the change layer is not made
|
|||
return false; |
|||
|
|||
// Handle 2 segments.
|
|||
if( Settings().m_legacyUseTwoSegmentTracks && g_CurrentTrackSegment->Back() ) |
|||
{ |
|||
if( BAD_DRC == m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment->Back(), |
|||
GetBoard()->m_Track ) ) |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/* Save current state before placing a via.
|
|||
* If the via cannot be placed this current state will be reused |
|||
*/ |
|||
itmp = g_CurrentTrackList.GetCount(); |
|||
Begin_Route( g_CurrentTrackSegment, DC ); |
|||
|
|||
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); |
|||
|
|||
// create the via
|
|||
VIA* via = new VIA( GetBoard() ); |
|||
via->SetFlags( IS_NEW ); |
|||
via->SetViaType( GetDesignSettings().m_CurrentViaType ); |
|||
via->SetNetCode( GetBoard()->GetHighLightNetCode() ); |
|||
via->SetPosition( g_CurrentTrackSegment->GetEnd() ); |
|||
|
|||
// for microvias, the size and hole will be changed later.
|
|||
via->SetWidth( GetDesignSettings().GetCurrentViaSize()); |
|||
via->SetDrill( GetDesignSettings().GetCurrentViaDrill() ); |
|||
|
|||
// Usual via is from copper to component.
|
|||
// layer pair is B_Cu and F_Cu.
|
|||
via->SetLayerPair( B_Cu, F_Cu ); |
|||
|
|||
PCB_LAYER_ID first_layer = GetActiveLayer(); |
|||
PCB_LAYER_ID last_layer; |
|||
|
|||
// prepare switch to new active layer:
|
|||
if( first_layer != GetScreen()->m_Route_Layer_TOP ) |
|||
last_layer = GetScreen()->m_Route_Layer_TOP; |
|||
else |
|||
last_layer = GetScreen()->m_Route_Layer_BOTTOM; |
|||
|
|||
// Adjust the actual via layer pair
|
|||
switch( via->GetViaType() ) |
|||
{ |
|||
case VIA_BLIND_BURIED: |
|||
via->SetLayerPair( first_layer, last_layer ); |
|||
break; |
|||
|
|||
case VIA_MICROVIA: // from external to the near neighbor inner layer
|
|||
{ |
|||
PCB_LAYER_ID last_inner_layer = ToLAYER_ID( ( GetBoard()->GetCopperLayerCount() - 2 ) ); |
|||
|
|||
if( first_layer == B_Cu ) |
|||
last_layer = last_inner_layer; |
|||
else if( first_layer == F_Cu ) |
|||
last_layer = In1_Cu; |
|||
else if( first_layer == last_inner_layer ) |
|||
last_layer = B_Cu; |
|||
else if( first_layer == In1_Cu ) |
|||
last_layer = F_Cu; |
|||
// else error: will be removed later
|
|||
via->SetLayerPair( first_layer, last_layer ); |
|||
|
|||
// Update diameter and hole size, which where set previously
|
|||
// for normal vias
|
|||
NETINFO_ITEM* net = via->GetNet(); |
|||
via->SetWidth( net->GetMicroViaSize() ); |
|||
via->SetDrill( net->GetMicroViaDrillSize() ); |
|||
} |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
|
|||
if( Settings().m_legacyDrcOn && |
|||
BAD_DRC == m_drc->DrcOnCreatingTrack( via, GetBoard()->m_Track ) ) |
|||
{ |
|||
// DRC fault: the Via cannot be placed here ...
|
|||
delete via; |
|||
|
|||
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); |
|||
|
|||
// delete the track(s) added in Begin_Route()
|
|||
while( g_CurrentTrackList.GetCount() > itmp ) |
|||
{ |
|||
Delete_Segment( DC, g_CurrentTrackSegment ); |
|||
} |
|||
|
|||
SetCurItem( g_CurrentTrackSegment, false ); |
|||
|
|||
// Refresh DRC diag, erased by previous calls
|
|||
if( m_drc->GetCurrentMarker() ) |
|||
SetMsgPanel( m_drc->GetCurrentMarker() ); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
SetActiveLayer( last_layer ); |
|||
|
|||
TRACK* lastNonVia = g_CurrentTrackSegment; |
|||
|
|||
/* A new via was created. It was Ok.
|
|||
*/ |
|||
g_CurrentTrackList.PushBack( via ); |
|||
|
|||
/* The via is now in linked list and we need a new track segment
|
|||
* after the via, starting at via location. |
|||
* it will become the new current segment (from via to the mouse cursor) |
|||
*/ |
|||
|
|||
TRACK* track = (TRACK*)lastNonVia->Clone(); |
|||
|
|||
/* the above creates a new segment from the last entered segment, with the
|
|||
* current width, flags, netcode, etc... values. |
|||
* layer, start and end point are not correct, |
|||
* and will be modified next |
|||
*/ |
|||
|
|||
// set the layer to the new value
|
|||
track->SetLayer( GetActiveLayer() ); |
|||
|
|||
/* the start point is the via position and the end point is the cursor
|
|||
* which also is on the via (will change when moving mouse) |
|||
*/ |
|||
track->SetEnd( via->GetStart() ); |
|||
track->SetStart( via->GetStart() ); |
|||
|
|||
g_CurrentTrackList.PushBack( track ); |
|||
|
|||
if( Settings().m_legacyUseTwoSegmentTracks ) |
|||
{ |
|||
// Create a second segment (we must have 2 track segments to adjust)
|
|||
g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() ); |
|||
} |
|||
|
|||
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); |
|||
SetMsgPanel( via ); |
|||
UpdateStatusBar(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State, |
|||
bool onoff ); |
|||
|
|||
|
|||
void DrawTraces( EDA_DRAW_PANEL* panel, wxDC* DC, TRACK* aTrackList, int nbsegment, |
|||
GR_DRAWMODE draw_mode ) |
|||
{ |
|||
// preserve the start of the list for debugging.
|
|||
for( TRACK* track = aTrackList; nbsegment > 0 && track; nbsegment--, track = track->Next() ) |
|||
{ |
|||
track->Draw( panel, DC, draw_mode ); |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* This function try to remove an old track, when a new track is created, |
|||
* and the old track is no more needed |
|||
*/ |
|||
int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC, |
|||
TRACK* aNewTrack, |
|||
int aNewTrackSegmentsCount, |
|||
PICKED_ITEMS_LIST* aItemsListPicker ) |
|||
{ |
|||
TRACK* StartTrack, * EndTrack; |
|||
TRACK* pt_segm; |
|||
TRACK* pt_del; |
|||
int nb_segm, nbconnect; |
|||
wxPoint start; |
|||
wxPoint end; |
|||
LSET startmasklayer, endmasklayer; |
|||
int netcode = aNewTrack->GetNetCode(); |
|||
|
|||
// Reconstruct the complete track (the new track has to start on a segment of track).
|
|||
// Note: aNewTrackSegmentsCount conatins the number of new track segments
|
|||
ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, false ); |
|||
|
|||
/* If the new track begins with a via, complete the track segment using
|
|||
* the following segment as a reference because a via is often a hub of |
|||
* segments, and does not characterize track. |
|||
*/ |
|||
if( aNewTrack->Type() == PCB_VIA_T && ( aNewTrackSegmentsCount > 1 ) ) |
|||
aNewTrack = aNewTrack->Next(); |
|||
|
|||
// When MarkTrace try to find the entire track, if the starting segment
|
|||
// is fully inside a pad, MarkTrace does not find correctly the full trace,
|
|||
// because the entire track is the set of segments between 2 nodes
|
|||
// (pads or point connecting more than 2 items)
|
|||
// so use another (better) starting segment in this case
|
|||
TRACK* track_segment = aNewTrack; |
|||
|
|||
for( int ii = 0; ii < aNewTrackSegmentsCount; ii++ ) |
|||
{ |
|||
D_PAD* pad_st = m_Pcb->GetPad( aNewTrack->GetStart() ); |
|||
D_PAD* pad_end = m_Pcb->GetPad( aNewTrack->GetEnd() ); |
|||
|
|||
if( pad_st && pad_st == pad_end ) |
|||
track_segment = aNewTrack->Next(); |
|||
else |
|||
break; |
|||
} |
|||
|
|||
// Mark the full trace containing track_segment, and recalculate the
|
|||
// beginning of the trace, and the number of segments, as the new trace
|
|||
// can contain also already existing track segments
|
|||
aNewTrack = GetBoard()->MarkTrace( GetBoard()->m_Track, track_segment, |
|||
&aNewTrackSegmentsCount, |
|||
nullptr, nullptr, true ); |
|||
wxASSERT( aNewTrack ); |
|||
|
|||
TRACK* bufStart = m_Pcb->m_Track->GetStartNetCode( netcode ); // Beginning of tracks of the net
|
|||
TRACK* bufEnd = bufStart->GetEndNetCode( netcode ); // End of tracks of the net
|
|||
|
|||
// Flags for cleaning the net.
|
|||
for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() ) |
|||
{ |
|||
// printf( "track %p turning off BUSY | IN_EDIT | IS_LINKED\n", pt_del );
|
|||
pt_del->SetState( BUSY | IN_EDIT | IS_LINKED, false ); |
|||
|
|||
if( pt_del == bufEnd ) // Last segment reached
|
|||
break; |
|||
} |
|||
|
|||
if( aNewTrack->GetEndSegments( aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 ) |
|||
return 0; |
|||
|
|||
if( ( StartTrack == NULL ) || ( EndTrack == NULL ) ) |
|||
return 0; |
|||
|
|||
start = StartTrack->GetStart(); |
|||
end = EndTrack->GetEnd(); |
|||
|
|||
// The start and end points cannot be the same.
|
|||
if( start == end ) |
|||
return 0; |
|||
|
|||
// Determine layers interconnected these points.
|
|||
startmasklayer = StartTrack->GetLayerSet(); |
|||
endmasklayer = EndTrack->GetLayerSet(); |
|||
|
|||
// There may be a via or a pad on the end points.
|
|||
pt_segm = m_Pcb->m_Track->GetVia( NULL, start, startmasklayer ); |
|||
|
|||
if( pt_segm ) |
|||
startmasklayer |= pt_segm->GetLayerSet(); |
|||
|
|||
if( StartTrack->start && ( StartTrack->start->Type() == PCB_PAD_T ) ) |
|||
{ |
|||
// Start on pad.
|
|||
D_PAD* pad = (D_PAD*) StartTrack->start; |
|||
startmasklayer |= pad->GetLayerSet(); |
|||
} |
|||
|
|||
pt_segm = m_Pcb->m_Track->GetVia( NULL, end, endmasklayer ); |
|||
|
|||
if( pt_segm ) |
|||
endmasklayer |= pt_segm->GetLayerSet(); |
|||
|
|||
if( EndTrack->end && ( EndTrack->end->Type() == PCB_PAD_T ) ) |
|||
{ |
|||
D_PAD* pad = (D_PAD*) EndTrack->end; |
|||
endmasklayer |= pad->GetLayerSet(); |
|||
} |
|||
|
|||
// Mark as deleted a new track (which is not involved in the search for other connections)
|
|||
ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, true ); |
|||
|
|||
/* A segment must be connected to the starting point, otherwise
|
|||
* it is unnecessary to analyze the other point |
|||
*/ |
|||
pt_segm = GetTrack( bufStart, bufEnd, start, startmasklayer ); |
|||
|
|||
if( pt_segm == NULL ) // Not connected to the track starting point.
|
|||
{ |
|||
// Clear the delete flag.
|
|||
ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false ); |
|||
return 0; |
|||
} |
|||
|
|||
/* Marking a list of candidate segmented connect to endpoint
|
|||
* Note: the vias are not taken into account because they do |
|||
* not define a track, since they are on an intersection. |
|||
*/ |
|||
for( pt_del = bufStart, nbconnect = 0; ; ) |
|||
{ |
|||
pt_segm = GetTrack( pt_del, bufEnd, end, endmasklayer ); |
|||
|
|||
if( pt_segm == NULL ) |
|||
break; |
|||
|
|||
if( pt_segm->Type() != PCB_VIA_T ) |
|||
{ |
|||
if( pt_segm->GetState( IS_LINKED ) == 0 ) |
|||
{ |
|||
pt_segm->SetState( IS_LINKED, true ); |
|||
nbconnect++; |
|||
} |
|||
} |
|||
|
|||
if( pt_del == bufEnd ) |
|||
break; |
|||
|
|||
pt_del = pt_segm->Next(); |
|||
} |
|||
|
|||
if( nbconnect == 0 ) |
|||
{ |
|||
// Clear used flags
|
|||
for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() ) |
|||
{ |
|||
pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false ); |
|||
|
|||
if( pt_del == bufEnd ) // Last segment reached
|
|||
break; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
// Mark trace as edited (which does not involve searching for other tracks)
|
|||
ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false ); |
|||
ListSetState( aNewTrack, aNewTrackSegmentsCount, IN_EDIT, true ); |
|||
|
|||
// Test all marked segments.
|
|||
while( nbconnect ) |
|||
{ |
|||
for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() ) |
|||
{ |
|||
if( pt_del->GetState( IS_LINKED ) ) |
|||
break; |
|||
|
|||
if( pt_del == bufEnd ) // Last segment reached
|
|||
break; |
|||
} |
|||
|
|||
nbconnect--; |
|||
|
|||
if( pt_del ) |
|||
pt_del->SetState( IS_LINKED, false ); |
|||
|
|||
pt_del = GetBoard()->MarkTrace( GetBoard()->m_Track, pt_del, &nb_segm, |
|||
NULL, NULL, true ); |
|||
|
|||
/* Test if the marked track is redundant, i.e. if one of marked segments
|
|||
* is connected to the starting point of the new track. |
|||
*/ |
|||
|
|||
pt_segm = pt_del; |
|||
|
|||
for( int ii = 0; pt_segm && (ii < nb_segm); pt_segm = pt_segm->Next(), ii++ ) |
|||
{ |
|||
if( pt_segm->GetState( BUSY ) == 0 ) |
|||
break; |
|||
|
|||
if( pt_segm->GetStart() == start || pt_segm->GetEnd() == start ) |
|||
{ |
|||
// Marked track can be erased.
|
|||
TRACK* NextS; |
|||
|
|||
DrawTraces( m_canvas, aDC, pt_del, nb_segm, GR_XOR | GR_HIGHLIGHT ); |
|||
|
|||
for( int jj = 0; jj < nb_segm; jj++, pt_del = NextS ) |
|||
{ |
|||
NextS = pt_del->Next(); |
|||
|
|||
if( aItemsListPicker ) |
|||
{ |
|||
pt_del->UnLink(); |
|||
pt_del->SetStatus( 0 ); |
|||
pt_del->ClearFlags(); |
|||
GetBoard()->GetConnectivity()->Remove( pt_del ); |
|||
ITEM_PICKER picker( pt_del, UR_DELETED ); |
|||
aItemsListPicker->PushItem( picker ); |
|||
} |
|||
else |
|||
{ |
|||
GetBoard()->GetConnectivity()->Remove( pt_del ); |
|||
pt_del->DeleteStructure(); |
|||
} |
|||
} |
|||
|
|||
// Clean up flags.
|
|||
for( pt_del = m_Pcb->m_Track; pt_del != NULL; pt_del = pt_del->Next() ) |
|||
{ |
|||
if( pt_del->GetState( IN_EDIT ) ) |
|||
{ |
|||
pt_del->SetState( IN_EDIT, false ); |
|||
|
|||
if( aDC ) |
|||
pt_del->Draw( m_canvas, aDC, GR_OR ); |
|||
} |
|||
|
|||
pt_del->SetState( IN_EDIT | IS_LINKED, false ); |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
} |
|||
|
|||
// Clear BUSY flag here because the track did not get marked.
|
|||
ListSetState( pt_del, nb_segm, BUSY, false ); |
|||
} |
|||
|
|||
// Clear used flags
|
|||
for( pt_del = m_Pcb->m_Track; pt_del; pt_del = pt_del->Next() ) |
|||
{ |
|||
pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false ); |
|||
|
|||
if( pt_del == bufEnd ) // Last segment reached
|
|||
break; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
/* Set the bits of .m_State member to on/off value, using bit mask State
|
|||
* of a list of EDA_ITEM |
|||
*/ |
|||
static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State, |
|||
bool onoff ) |
|||
{ |
|||
for( ; (Start != NULL ) && ( NbItem > 0 ); NbItem--, Start = Start->Next() ) |
|||
{ |
|||
Start->SetState( State, onoff ); |
|||
} |
|||
} |
@ -1,843 +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@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 editrack.cpp |
|||
*/ |
|||
|
|||
#include <fctsys.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <trigo.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <drc.h>
|
|||
#include <protos.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
#include <class_zone.h>
|
|||
#include <connectivity/connectivity_data.h>
|
|||
|
|||
|
|||
static void Abort_Create_Track( EDA_DRAW_PANEL* panel, wxDC* DC ); |
|||
void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, |
|||
const wxPoint& aPosition, bool aErase ); |
|||
static void ComputeBreakPoint( TRACK* track, int SegmentCount, wxPoint end ); |
|||
|
|||
// A PICKED_ITEMS_LIST to store tracks which are modified/added/deleted
|
|||
// during a track editing:
|
|||
static PICKED_ITEMS_LIST s_ItemsListPicker; |
|||
|
|||
|
|||
/* Function called to abort a track creation
|
|||
*/ |
|||
static void Abort_Create_Track( EDA_DRAW_PANEL* Panel, wxDC* DC ) |
|||
{ |
|||
PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Panel->GetParent(); |
|||
BOARD* pcb = frame->GetBoard(); |
|||
TRACK* track = dyn_cast<TRACK*>( frame->GetCurItem() ); |
|||
|
|||
if( track ) |
|||
{ |
|||
// Erase the current drawing
|
|||
ShowNewTrackWhenMovingCursor( Panel, DC, wxDefaultPosition, false ); |
|||
|
|||
if( pcb->IsHighLightNetON() ) |
|||
frame->HighLight( DC ); |
|||
|
|||
pcb->PopHighLight(); |
|||
|
|||
if( pcb->IsHighLightNetON() ) |
|||
pcb->DrawHighLight( Panel, DC, pcb->GetHighLightNetCode() ); |
|||
|
|||
frame->ClearMsgPanel(); |
|||
|
|||
// Undo pending changes (mainly a lock point creation) and clear the
|
|||
// undo picker list:
|
|||
frame->PutDataInPreviousState( &s_ItemsListPicker, false, false ); |
|||
s_ItemsListPicker.ClearListAndDeleteItems(); |
|||
|
|||
// Delete current (new) track
|
|||
g_CurrentTrackList.DeleteAll(); |
|||
} |
|||
|
|||
frame->SetCurItem( NULL ); |
|||
} |
|||
|
|||
/*
|
|||
* This function starts a new track segment. |
|||
* If a new track segment is in progress, ends this current new segment, |
|||
* and created a new one. |
|||
*/ |
|||
TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) |
|||
{ |
|||
TRACK* trackOnStartPoint = NULL; |
|||
LSET layerMask( GetScreen()->m_Active_Layer ); |
|||
wxPoint pos = GetCrossHairPosition(); |
|||
|
|||
BOARD_CONNECTED_ITEM* lockPoint; |
|||
|
|||
if( aTrack == NULL ) // Starting a new track segment
|
|||
{ |
|||
m_canvas->SetMouseCapture( ShowNewTrackWhenMovingCursor, Abort_Create_Track ); |
|||
|
|||
// Prepare the undo command info
|
|||
s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but...
|
|||
|
|||
GetBoard()->PushHighLight(); |
|||
|
|||
// erase old highlight
|
|||
if( GetBoard()->IsHighLightNetON() ) |
|||
HighLight( aDC ); |
|||
|
|||
g_CurrentTrackList.PushBack( new TRACK( GetBoard() ) ); |
|||
g_CurrentTrackSegment->SetFlags( IS_NEW ); |
|||
|
|||
GetBoard()->SetHighLightNet( 0 ); |
|||
|
|||
// Search for a starting point of the new track, a track or pad
|
|||
lockPoint = GetBoard()->GetLockPoint( pos, layerMask ); |
|||
|
|||
D_PAD* pad = NULL; |
|||
if( lockPoint ) // An item (pad or track) is found
|
|||
{ |
|||
if( lockPoint->Type() == PCB_PAD_T ) |
|||
{ |
|||
pad = (D_PAD*) lockPoint; |
|||
|
|||
// A pad is found: put the starting point on pad center
|
|||
pos = pad->GetPosition(); |
|||
GetBoard()->SetHighLightNet( pad->GetNetCode() ); |
|||
} |
|||
else // A track segment is found
|
|||
{ |
|||
trackOnStartPoint = (TRACK*) lockPoint; |
|||
GetBoard()->SetHighLightNet( trackOnStartPoint->GetNetCode() ); |
|||
GetBoard()->CreateLockPoint( pos, trackOnStartPoint, &s_ItemsListPicker ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// Not a starting point, but a filled zone area can exist. This is also a
|
|||
// good starting point.
|
|||
ZONE_CONTAINER* zone; |
|||
zone = GetBoard()->HitTestForAnyFilledArea( pos, |
|||
GetScreen()-> m_Active_Layer, |
|||
GetScreen()-> m_Active_Layer, |
|||
-1 ); |
|||
|
|||
if( zone ) |
|||
GetBoard()->SetHighLightNet( zone->GetNetCode() ); |
|||
} |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity() ); |
|||
|
|||
int net = -1; |
|||
|
|||
if( lockPoint ) |
|||
net = lockPoint->GetNetCode(); |
|||
|
|||
BuildAirWiresTargetsList( lockPoint, wxPoint( 0, 0 ), net ); |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity() ); |
|||
|
|||
GetBoard()->HighLightON(); |
|||
GetBoard()->DrawHighLight( m_canvas, aDC, GetBoard()->GetHighLightNetCode() ); |
|||
|
|||
// Display info about track Net class, and init track and vias sizes:
|
|||
g_CurrentTrackSegment->SetNetCode( GetBoard()->GetHighLightNetCode() ); |
|||
SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() ); |
|||
|
|||
g_CurrentTrackSegment->SetLayer( GetScreen()->m_Active_Layer ); |
|||
g_CurrentTrackSegment->SetWidth( GetDesignSettings().GetCurrentTrackWidth() ); |
|||
|
|||
if( GetDesignSettings().m_UseConnectedTrackWidth ) |
|||
{ |
|||
if( trackOnStartPoint && trackOnStartPoint->Type() == PCB_TRACE_T ) |
|||
g_CurrentTrackSegment->SetWidth( trackOnStartPoint->GetWidth()); |
|||
} |
|||
|
|||
g_CurrentTrackSegment->SetStart( pos ); |
|||
g_CurrentTrackSegment->SetEnd( pos ); |
|||
|
|||
if( pad ) |
|||
{ |
|||
// Useful to display track length, if the pad has a die length:
|
|||
g_CurrentTrackSegment->SetState( BEGIN_ONPAD, true ); |
|||
g_CurrentTrackSegment->start = pad; |
|||
} |
|||
|
|||
if( Settings().m_legacyUseTwoSegmentTracks ) |
|||
{ |
|||
// Create 2nd segment
|
|||
g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() ); |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
|
|||
g_CurrentTrackSegment->start = g_FirstTrackSegment; |
|||
g_FirstTrackSegment->end = g_CurrentTrackSegment; |
|||
|
|||
g_FirstTrackSegment->SetState( BEGIN_ONPAD | END_ONPAD, false ); |
|||
} |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
|
|||
SetMsgPanel( g_CurrentTrackSegment ); |
|||
SetCurItem( g_CurrentTrackSegment, false ); |
|||
m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); |
|||
|
|||
if( Settings().m_legacyDrcOn ) |
|||
{ |
|||
if( BAD_DRC == m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment, GetBoard()->m_Track ) ) |
|||
{ |
|||
return g_CurrentTrackSegment; |
|||
} |
|||
} |
|||
} |
|||
else // Track in progress : segment coordinates are updated by ShowNewTrackWhenMovingCursor.
|
|||
{ |
|||
// Test for a D.R.C. error:
|
|||
if( Settings().m_legacyDrcOn ) |
|||
{ |
|||
if( BAD_DRC == m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment, GetBoard()->m_Track ) ) |
|||
return NULL; |
|||
|
|||
// We must handle 2 segments
|
|||
if( Settings().m_legacyUseTwoSegmentTracks && g_CurrentTrackSegment->Back() ) |
|||
{ |
|||
if( BAD_DRC == m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment->Back(), |
|||
GetBoard()->m_Track ) ) |
|||
return NULL; |
|||
} |
|||
} |
|||
|
|||
/* Current track is Ok: current segment is kept, and a new one is
|
|||
* created unless the current segment is null, or 2 last are null |
|||
* if this is a 2 segments track build. |
|||
*/ |
|||
bool CanCreateNewSegment = true; |
|||
|
|||
if( !Settings().m_legacyUseTwoSegmentTracks && g_CurrentTrackSegment->IsNull() ) |
|||
CanCreateNewSegment = false; |
|||
|
|||
if( Settings().m_legacyUseTwoSegmentTracks && g_CurrentTrackSegment->IsNull() |
|||
&& g_CurrentTrackSegment->Back() |
|||
&& g_CurrentTrackSegment->Back()->IsNull() ) |
|||
CanCreateNewSegment = false; |
|||
|
|||
if( CanCreateNewSegment ) |
|||
{ |
|||
// Erase old track on screen
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
|
|||
ShowNewTrackWhenMovingCursor( m_canvas, aDC, wxDefaultPosition, false ); |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
|
|||
if( g_Raccord_45_Auto ) |
|||
Add45DegreeSegment( aDC ); |
|||
|
|||
TRACK* previousTrack = g_CurrentTrackSegment; |
|||
|
|||
TRACK* newTrack = (TRACK*)g_CurrentTrackSegment->Clone(); |
|||
g_CurrentTrackList.PushBack( newTrack ); |
|||
newTrack->SetFlags( IS_NEW ); |
|||
|
|||
newTrack->SetState( BEGIN_ONPAD | END_ONPAD, false ); |
|||
newTrack->start = previousTrack->end; |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
|
|||
newTrack->SetStart( newTrack->GetEnd() ); |
|||
|
|||
newTrack->SetLayer( GetScreen()->m_Active_Layer ); |
|||
|
|||
if( !GetDesignSettings().m_UseConnectedTrackWidth ) |
|||
newTrack->SetWidth( GetDesignSettings().GetCurrentTrackWidth() ); |
|||
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
|
|||
// Show the new position
|
|||
ShowNewTrackWhenMovingCursor( m_canvas, aDC, wxDefaultPosition, false ); |
|||
} |
|||
} |
|||
|
|||
SetCurItem( g_CurrentTrackSegment, false ); |
|||
return g_CurrentTrackSegment; |
|||
} |
|||
|
|||
|
|||
bool PCB_EDIT_FRAME::Add45DegreeSegment( wxDC* aDC ) |
|||
{ |
|||
int dx0, dy0, dx1, dy1; |
|||
|
|||
if( g_CurrentTrackList.GetCount() < 2 ) |
|||
return false; // There must be 2 segments.
|
|||
|
|||
TRACK* curTrack = g_CurrentTrackSegment; |
|||
TRACK* prevTrack = curTrack->Back(); |
|||
|
|||
// Test if we have 2 consecutive track segments ( not via ) to connect.
|
|||
if( curTrack->Type() != PCB_TRACE_T || prevTrack->Type() != PCB_TRACE_T ) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
int segm_step_45 = KiROUND( GetScreen()->GetGridSize().x / 2 ); |
|||
|
|||
if( segm_step_45 < ( curTrack->GetWidth() * 2 ) ) |
|||
segm_step_45 = curTrack->GetWidth() * 2; |
|||
|
|||
// Test if the segments are horizontal or vertical.
|
|||
dx0 = prevTrack->GetEnd().x - prevTrack->GetStart().x; |
|||
dy0 = prevTrack->GetEnd().y - prevTrack->GetStart().y; |
|||
|
|||
dx1 = curTrack->GetEnd().x - curTrack->GetStart().x; |
|||
dy1 = curTrack->GetEnd().y - curTrack->GetStart().y; |
|||
|
|||
// Segments should have a min length.
|
|||
if( std::max( abs( dx0 ), abs( dy0 ) ) < ( segm_step_45 * 2 ) ) |
|||
return false; |
|||
|
|||
if( std::max( abs( dx1 ), abs( dy1 ) ) < ( segm_step_45 * 2 ) ) |
|||
return false; |
|||
|
|||
// Create a new segment and connect it with the previous 2 segments.
|
|||
TRACK* newTrack = (TRACK*)curTrack->Clone(); |
|||
|
|||
newTrack->SetStart( prevTrack->GetEnd() ); |
|||
newTrack->SetEnd( curTrack->GetStart() ); |
|||
|
|||
if( dx0 == 0 ) // Previous segment is Vertical
|
|||
{ |
|||
if( dy1 != 0 ) // 2 segments are not 90 degrees.
|
|||
{ |
|||
delete newTrack; |
|||
return false; |
|||
} |
|||
|
|||
/* Calculate coordinates the connection point.
|
|||
* The new segment connects the 1st vertical segment and the 2nd |
|||
* horizontal segment. |
|||
*/ |
|||
if( dy0 > 0 ) |
|||
newTrack->SetStart( wxPoint(newTrack->GetStart().x, newTrack->GetStart().y -segm_step_45) ); |
|||
else |
|||
newTrack->SetStart( wxPoint(newTrack->GetStart().x, newTrack->GetStart().y + segm_step_45) ); |
|||
|
|||
if( dx1 > 0 ) |
|||
newTrack->SetEnd( wxPoint(newTrack->GetEnd().x + segm_step_45, newTrack->GetEnd().y) ); |
|||
else |
|||
newTrack->SetEnd( wxPoint(newTrack->GetEnd().x - segm_step_45, newTrack->GetEnd().y) ); |
|||
|
|||
if( Settings().m_legacyDrcOn && |
|||
BAD_DRC == m_drc->DrcOnCreatingTrack( curTrack, GetBoard()->m_Track ) ) |
|||
{ |
|||
delete newTrack; |
|||
return false; |
|||
} |
|||
|
|||
prevTrack->SetEnd( newTrack->GetStart()); |
|||
curTrack->SetStart( newTrack->GetEnd()); |
|||
|
|||
g_CurrentTrackList.Insert( newTrack, curTrack ); |
|||
return true; |
|||
} |
|||
|
|||
if( dy0 == 0 ) // Previous segment is horizontal
|
|||
{ |
|||
if( dx1 != 0 ) // 2 segments are not 90 degrees
|
|||
{ |
|||
delete newTrack; |
|||
return false; |
|||
} |
|||
|
|||
/* Calculate the coordinates of the point of connection:
|
|||
* A new segment has been created, connecting segment 1 |
|||
* (horizontal) and segment 2 (vertical) |
|||
*/ |
|||
if( dx0 > 0 ) |
|||
newTrack->SetStart( wxPoint(newTrack->GetStart().x - segm_step_45 , newTrack->GetStart().y)); |
|||
else |
|||
newTrack->SetStart( wxPoint(newTrack->GetStart().x + segm_step_45, newTrack->GetStart().y) ); |
|||
|
|||
if( dy1 > 0 ) |
|||
newTrack->SetEnd( wxPoint(newTrack->GetEnd().x, newTrack->GetEnd().y + segm_step_45) ); |
|||
else |
|||
newTrack->SetEnd( wxPoint(newTrack->GetEnd().x, newTrack->GetEnd().y - segm_step_45) ); |
|||
|
|||
if( Settings().m_legacyDrcOn && |
|||
BAD_DRC == m_drc->DrcOnCreatingTrack( newTrack, GetBoard()->m_Track ) ) |
|||
{ |
|||
delete newTrack; |
|||
return false; |
|||
} |
|||
|
|||
prevTrack->SetEnd( newTrack->GetStart()); |
|||
curTrack->SetStart( newTrack->GetEnd()); |
|||
|
|||
g_CurrentTrackList.Insert( newTrack, curTrack ); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
|
|||
TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, LAYER_NUM aLayer, const wxPoint& aRef ) |
|||
{ |
|||
int net = aTrack->GetNetCode(); |
|||
int width = aTrack->GetWidth(); |
|||
|
|||
TRACK* found = NULL; |
|||
|
|||
for( TRACK* track = listStart; track; track = track->Next() ) |
|||
{ |
|||
if( track->Type() == PCB_TRACE_T ) // skip vias
|
|||
{ |
|||
if( track->GetState( BUSY | IS_DELETED ) ) |
|||
continue; |
|||
|
|||
if( aLayer != track->GetLayer() ) |
|||
continue; |
|||
|
|||
if( track->GetNetCode() == net ) |
|||
continue; |
|||
|
|||
// TRACK::HitTest
|
|||
int dist = (width + track->GetWidth()) / 2 + aTrack->GetClearance( track ); |
|||
|
|||
if( !TestSegmentHit( aRef, track->GetStart(), track->GetEnd(), dist ) ) |
|||
continue; |
|||
|
|||
found = track; |
|||
|
|||
// prefer intrusions from the side, not the end
|
|||
wxPoint pos = aRef - track->GetStart(); |
|||
wxPoint vec = track->GetEnd() - track->GetStart(); |
|||
double tmp = (double) pos.x * vec.x + (double) pos.y * vec.y; |
|||
|
|||
if( tmp >= 0 && tmp <= (double) vec.x * vec.x + (double) vec.y * vec.y ) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return found; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* Function PushTrack |
|||
* detects if the mouse is pointing into a conflicting track. |
|||
* In this case, it tries to push the new track out of the conflicting track's |
|||
* clearance zone. This gives us a cheap mechanism for drawing tracks that |
|||
* tightly follow others, independent of grid settings. |
|||
* |
|||
* KNOWN BUGS: |
|||
* - we do the same sort of search and calculation up to three times: |
|||
* 1) we search for magnetic hits (in controle.cpp) |
|||
* 2) we check if there's a DRC violation in the making (also controle.cpp) |
|||
* 3) we try to fix the DRC violation (here) |
|||
* - if we have a magnetic hit and a DRC violation at the same time, we choose |
|||
* the magnetic hit instead of solving the violation |
|||
* - should locate conflicting tracks also when we're crossing over them |
|||
*/ |
|||
static void PushTrack( EDA_DRAW_PANEL* panel ) |
|||
{ |
|||
PCB_SCREEN* screen = (PCB_SCREEN*) panel->GetParent()->GetScreen(); |
|||
BOARD* pcb = ( (PCB_BASE_FRAME*) (panel->GetParent()) )->GetBoard(); |
|||
wxPoint cursor = panel->GetParent()->GetCrossHairPosition(); |
|||
wxPoint cv, vec, n; |
|||
TRACK* track = g_CurrentTrackSegment; |
|||
TRACK* other; |
|||
double det; |
|||
int dist; |
|||
double f; |
|||
|
|||
other = LocateIntrusion( pcb->m_Track, track, screen->m_Active_Layer, panel->GetParent()->RefPos( true ) ); |
|||
|
|||
// are we currently pointing into a conflicting trace ?
|
|||
if( !other ) |
|||
return; |
|||
|
|||
if( other->GetNetCode() == track->GetNetCode() ) |
|||
return; |
|||
|
|||
cv = cursor - other->GetStart(); |
|||
vec = other->GetEnd() - other->GetStart(); |
|||
|
|||
det = (double) cv.x * vec.y - (double) cv.y * vec.x; |
|||
|
|||
// cursor is right at the center of the old track
|
|||
if( !det ) |
|||
return; |
|||
|
|||
dist = (track->GetWidth() + 1) / 2 + (other->GetWidth() + 1) / 2 + track->GetClearance( other ) + 2; |
|||
|
|||
/*
|
|||
* DRC wants >, so +1. |
|||
* We may have a quantization error of 1/sqrt(2), so +1 again. |
|||
*/ |
|||
|
|||
// Vector "n" is perpendicular to "other", pointing towards the cursor.
|
|||
if( det > 0 ) |
|||
{ |
|||
n.x = vec.y; |
|||
n.y = -vec.x; |
|||
} |
|||
else |
|||
{ |
|||
n.x = -vec.y; |
|||
n.y = vec.x; |
|||
} |
|||
|
|||
f = dist / hypot( double(n.x), double(n.y) ); |
|||
n.x = KiROUND( f * n.x ); |
|||
n.y = KiROUND( f * n.y ); |
|||
|
|||
wxPoint hp = track->GetEnd(); |
|||
FindBestGridPointOnTrack( &hp, cursor, other ); |
|||
track->SetEnd( hp + n ); |
|||
} |
|||
|
|||
|
|||
//Helper function: Draws Via circle and Via Clearance circle.
|
|||
inline void DrawViaCirclesWhenEditingNewTrack( EDA_RECT* aPanelClipBox, |
|||
wxDC* aDC, const wxPoint& aPos, |
|||
int aViaRadius, |
|||
int aViaRadiusWithClearence, |
|||
COLOR4D aColor) |
|||
{ |
|||
//Current viasize clearance circle
|
|||
GRCircle( aPanelClipBox, aDC, aPos.x, aPos.y, aViaRadiusWithClearence, aColor ); |
|||
//Current viasize circle
|
|||
GRCircle( aPanelClipBox, aDC, aPos.x, aPos.y, aViaRadius, aColor ); |
|||
} |
|||
|
|||
/* Redraw the current track being created when the mouse cursor is moved
|
|||
*/ |
|||
void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, |
|||
bool aErase ) |
|||
{ |
|||
// DBG( g_CurrentTrackList.VerifyListIntegrity(); );
|
|||
|
|||
PCB_SCREEN* screen = (PCB_SCREEN*) aPanel->GetScreen(); |
|||
PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); |
|||
auto displ_opts = (PCB_DISPLAY_OPTIONS*) aPanel-> GetDisplayOptions(); |
|||
|
|||
bool tmp = displ_opts->m_DisplayPcbTrackFill; |
|||
displ_opts->m_DisplayPcbTrackFill = true; |
|||
auto showTrackClearanceMode = displ_opts->m_ShowTrackClearanceMode; |
|||
|
|||
if ( g_FirstTrackSegment == NULL ) |
|||
return; |
|||
|
|||
NETCLASSPTR netclass = g_FirstTrackSegment->GetNetClass(); |
|||
|
|||
if( showTrackClearanceMode != PCB_DISPLAY_OPTIONS::DO_NOT_SHOW_CLEARANCE ) |
|||
displ_opts->m_ShowTrackClearanceMode = PCB_DISPLAY_OPTIONS::SHOW_CLEARANCE_ALWAYS; |
|||
|
|||
// Values to Via circle
|
|||
int boardViaRadius = frame->GetDesignSettings().GetCurrentViaSize()/2; |
|||
int viaRadiusWithClearence = boardViaRadius+netclass->GetClearance(); |
|||
EDA_RECT* panelClipBox=aPanel->GetClipBox(); |
|||
|
|||
#ifndef USE_WX_OVERLAY
|
|||
// Erase old track
|
|||
if( aErase ) |
|||
{ |
|||
DrawTraces( aPanel, aDC, g_FirstTrackSegment, g_CurrentTrackList.GetCount(), GR_XOR ); |
|||
|
|||
frame->TraceAirWiresToTargets( aDC ); |
|||
|
|||
if( showTrackClearanceMode >= PCB_DISPLAY_OPTIONS::SHOW_CLEARANCE_NEW_TRACKS_AND_VIA_AREAS ) |
|||
{ |
|||
COLOR4D color = frame->Settings().Colors().GetLayerColor( g_CurrentTrackSegment->GetLayer() ); |
|||
DrawViaCirclesWhenEditingNewTrack( panelClipBox, aDC, g_CurrentTrackSegment->GetEnd(), |
|||
boardViaRadius, viaRadiusWithClearence, color); |
|||
} |
|||
} |
|||
#endif
|
|||
// MacOSX seems to need this.
|
|||
if( g_CurrentTrackList.GetCount() == 0 ) |
|||
return; |
|||
|
|||
// Set track parameters, that can be modified while creating the track
|
|||
g_CurrentTrackSegment->SetLayer( screen->m_Active_Layer ); |
|||
|
|||
if( !frame->GetDesignSettings().m_UseConnectedTrackWidth ) |
|||
g_CurrentTrackSegment->SetWidth( frame->GetDesignSettings().GetCurrentTrackWidth() ); |
|||
|
|||
if( frame->Settings().m_legacyUseTwoSegmentTracks ) |
|||
{ |
|||
TRACK* previous_track = g_CurrentTrackSegment->Back(); |
|||
|
|||
if( previous_track && previous_track->Type()==PCB_TRACE_T ) |
|||
{ |
|||
previous_track->SetLayer( screen->m_Active_Layer ); |
|||
|
|||
if( !frame->GetDesignSettings().m_UseConnectedTrackWidth ) |
|||
previous_track->SetWidth( frame->GetDesignSettings().GetCurrentTrackWidth() ); |
|||
} |
|||
} |
|||
|
|||
if( frame->Settings().m_legacyUse45DegreeTracks ) |
|||
{ |
|||
if( frame->Settings().m_legacyUseTwoSegmentTracks ) |
|||
{ |
|||
g_CurrentTrackSegment->SetEnd( frame->GetCrossHairPosition() ); |
|||
|
|||
if( frame->Settings().m_legacyDrcOn ) |
|||
PushTrack( aPanel ); |
|||
|
|||
ComputeBreakPoint( g_CurrentTrackSegment, |
|||
g_CurrentTrackList.GetCount(), |
|||
g_CurrentTrackSegment->GetEnd() ); |
|||
} |
|||
else |
|||
{ |
|||
/* Calculate of the end of the path for the permitted directions:
|
|||
* horizontal, vertical or 45 degrees. |
|||
*/ |
|||
wxPoint hp = g_CurrentTrackSegment->GetEnd(); |
|||
hp = CalculateSegmentEndPoint( frame->GetCrossHairPosition(), |
|||
g_CurrentTrackSegment->GetStart() ); |
|||
g_CurrentTrackSegment->SetEnd(hp); |
|||
} |
|||
} |
|||
else // Here the angle is arbitrary
|
|||
{ |
|||
g_CurrentTrackSegment->SetEnd( frame->GetCrossHairPosition() ); |
|||
} |
|||
|
|||
// Redraw the new track
|
|||
DBG( g_CurrentTrackList.VerifyListIntegrity(); ); |
|||
DrawTraces( aPanel, aDC, g_FirstTrackSegment, g_CurrentTrackList.GetCount(), GR_XOR ); |
|||
|
|||
if( showTrackClearanceMode >= PCB_DISPLAY_OPTIONS::SHOW_CLEARANCE_NEW_TRACKS_AND_VIA_AREAS ) |
|||
{ |
|||
COLOR4D color = frame->Settings().Colors().GetLayerColor(g_CurrentTrackSegment->GetLayer()); |
|||
|
|||
//Via diameter must have taken what we are using, rather than netclass value.
|
|||
DrawViaCirclesWhenEditingNewTrack( panelClipBox, aDC, g_CurrentTrackSegment->GetEnd(), |
|||
boardViaRadius, viaRadiusWithClearence, color); |
|||
|
|||
} |
|||
|
|||
/* Display info about current segment and the full new track:
|
|||
* Choose the interesting segment: because we are using a 2 segments step, |
|||
* the last segment can be null, and the previous segment can be the |
|||
* interesting segment. |
|||
*/ |
|||
TRACK* isegm = g_CurrentTrackSegment; |
|||
|
|||
if( isegm->GetLength() == 0 && g_CurrentTrackSegment->Back() ) |
|||
isegm = g_CurrentTrackSegment->Back(); |
|||
|
|||
// display track info:
|
|||
frame->SetMsgPanel( isegm ); |
|||
wxString msg; |
|||
|
|||
// Display current segments count (number of segments in this new track):
|
|||
msg.Printf( "%d", g_CurrentTrackList.GetCount() ); |
|||
frame->AppendMsgPanel( _( "Segs Count" ), msg, DARKCYAN ); |
|||
|
|||
displ_opts->m_ShowTrackClearanceMode = showTrackClearanceMode; |
|||
displ_opts->m_DisplayPcbTrackFill = tmp; |
|||
|
|||
frame->BuildAirWiresTargetsList( NULL, g_CurrentTrackSegment->GetEnd(), |
|||
g_CurrentTrackSegment->GetNetCode() ); |
|||
frame->TraceAirWiresToTargets( aDC ); |
|||
} |
|||
|
|||
|
|||
wxPoint CalculateSegmentEndPoint( const wxPoint& aPosition, const wxPoint& aOrigin ) |
|||
{ |
|||
// Determine end point for a segment direction 0, 90, or 45 degrees
|
|||
// depending on it's position from the origin \a aOrigin and \a aPosition.
|
|||
wxPoint endPoint; |
|||
|
|||
int deltax = aPosition.x - aOrigin.x; |
|||
int deltay = aPosition.y - aOrigin.y; |
|||
|
|||
deltax = abs( deltax ); |
|||
deltay = abs( deltay ); |
|||
int angle = 45; |
|||
|
|||
if( deltax >= deltay ) |
|||
{ |
|||
if( deltax == 0 ) |
|||
angle = 0; |
|||
else if( ( (deltay << 6 ) / deltax ) < 26 ) |
|||
angle = 0; |
|||
} |
|||
else |
|||
{ |
|||
angle = 45; |
|||
|
|||
if( deltay == 0 ) |
|||
angle = 90; |
|||
else if( ( (deltax << 6 ) / deltay ) < 26 ) |
|||
angle = 90; |
|||
} |
|||
|
|||
switch( angle ) |
|||
{ |
|||
case 0: |
|||
endPoint.x = aPosition.x; |
|||
endPoint.y = aOrigin.y; |
|||
break; |
|||
|
|||
case 45: |
|||
deltax = std::min( deltax, deltay ); |
|||
deltay = deltax; |
|||
|
|||
// Recalculate the signs for deltax and deltaY.
|
|||
if( ( aPosition.x - aOrigin.x ) < 0 ) |
|||
deltax = -deltax; |
|||
|
|||
if( ( aPosition.y - aOrigin.y ) < 0 ) |
|||
deltay = -deltay; |
|||
|
|||
endPoint.x = aOrigin.x + deltax; |
|||
endPoint.y = aOrigin.y + deltay; |
|||
break; |
|||
|
|||
case 90: |
|||
endPoint.x = aOrigin.x; |
|||
endPoint.y = aPosition.y; |
|||
break; |
|||
} |
|||
|
|||
return endPoint; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* Compute new track angle based on previous track. |
|||
*/ |
|||
void ComputeBreakPoint( TRACK* track, int SegmentCount, wxPoint end ) |
|||
{ |
|||
int iDx = 0; |
|||
int iDy = 0; |
|||
int iAngle = 0; |
|||
|
|||
if( SegmentCount <= 0 ) |
|||
return; |
|||
|
|||
if( track == NULL ) |
|||
return; |
|||
|
|||
TRACK* newTrack = track; |
|||
track = track->Back(); |
|||
SegmentCount--; |
|||
|
|||
if( track ) |
|||
{ |
|||
iDx = end.x - track->GetStart().x; |
|||
iDy = end.y - track->GetStart().y; |
|||
|
|||
iDx = abs( iDx ); |
|||
iDy = abs( iDy ); |
|||
} |
|||
|
|||
TRACK* lastTrack = track ? track->Back() : NULL; |
|||
|
|||
if( lastTrack ) |
|||
{ |
|||
if(( (lastTrack->GetEnd().x == lastTrack->GetStart().x) |
|||
|| (lastTrack->GetEnd().y == lastTrack->GetStart().y) ) |
|||
&& !g_Alternate_Track_Posture) |
|||
{ |
|||
iAngle = 45; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if( g_Alternate_Track_Posture ) |
|||
{ |
|||
iAngle = 45; |
|||
} |
|||
} |
|||
|
|||
if( iAngle == 0 ) |
|||
{ |
|||
if( iDx >= iDy ) |
|||
iAngle = 0; |
|||
else |
|||
iAngle = 90; |
|||
} |
|||
|
|||
if( track == NULL ) |
|||
iAngle = -1; |
|||
|
|||
switch( iAngle ) |
|||
{ |
|||
case -1: |
|||
break; |
|||
|
|||
case 0: |
|||
if( ( end.x - track->GetStart().x ) < 0 ) |
|||
track->SetEnd(wxPoint( end.x + iDy, track->GetStart().y)); |
|||
else |
|||
track->SetEnd(wxPoint( end.x - iDy, track->GetStart().y)); |
|||
break; |
|||
|
|||
case 45: |
|||
iDx = std::min( iDx, iDy ); |
|||
iDy = iDx; |
|||
|
|||
// Recalculate the signs for deltax and deltaY.
|
|||
if( ( end.x - track->GetStart().x ) < 0 ) |
|||
iDx = -iDx; |
|||
|
|||
if( ( end.y - track->GetStart().y ) < 0 ) |
|||
iDy = -iDy; |
|||
|
|||
track->SetEnd(wxPoint(track->GetStart().x + iDx, track->GetStart().y + iDy)); |
|||
break; |
|||
|
|||
case 90: |
|||
if( ( end.y - track->GetStart().y ) < 0 ) |
|||
track->SetEnd(wxPoint(track->GetStart().x , end.y + iDx)); |
|||
else |
|||
track->SetEnd(wxPoint(track->GetStart().x , end.y - iDx)); |
|||
break; |
|||
} |
|||
|
|||
if( track ) |
|||
{ |
|||
if( track->IsNull() ) |
|||
track->SetEnd( end ); |
|||
|
|||
newTrack->SetStart( track->GetEnd() ); |
|||
} |
|||
|
|||
newTrack->SetEnd( end ); |
|||
} |
|||
|
|||
|
@ -1,172 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2009-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 event_handlers_tracks_vias_sizes.cpp |
|||
* @brief Handlers for popup and toolbars events relative to the tracks and vias sizes. |
|||
*/ |
|||
|
|||
|
|||
#include <fctsys.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <confirm.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <dialog_helpers.h>
|
|||
|
|||
#include <pcbnew_id.h>
|
|||
#include <pcbnew.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_module.h>
|
|||
|
|||
|
|||
/* Event handler for tracks and vias size selection (and some options)
|
|||
* relative to toolbars and popup events |
|||
*/ |
|||
void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) |
|||
{ |
|||
int ii; |
|||
int id = event.GetId(); |
|||
|
|||
/* Note: none of these events require aborting the current command (if any)
|
|||
* (like move, edit or block command) |
|||
* so we do not test for a current command in progress and call |
|||
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc ); |
|||
*/ |
|||
switch( id ) |
|||
{ |
|||
case ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH: |
|||
GetDesignSettings().m_UseConnectedTrackWidth = |
|||
not GetDesignSettings().m_UseConnectedTrackWidth; |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES: |
|||
GetDesignSettings().m_UseConnectedTrackWidth = false; |
|||
GetDesignSettings().SetTrackWidthIndex( 0 ); |
|||
GetDesignSettings().SetViaSizeIndex( 0 ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_SELECT_AUTO_WIDTH: |
|||
m_canvas->MoveCursorToCrossHair(); |
|||
GetDesignSettings().m_UseConnectedTrackWidth = true; |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_SELECT_WIDTH1: // this is the default Netclass selection
|
|||
case ID_POPUP_PCB_SELECT_WIDTH2: // this is a custom value selection
|
|||
case ID_POPUP_PCB_SELECT_WIDTH3: |
|||
case ID_POPUP_PCB_SELECT_WIDTH4: |
|||
case ID_POPUP_PCB_SELECT_WIDTH5: |
|||
case ID_POPUP_PCB_SELECT_WIDTH6: |
|||
case ID_POPUP_PCB_SELECT_WIDTH7: |
|||
case ID_POPUP_PCB_SELECT_WIDTH8: |
|||
case ID_POPUP_PCB_SELECT_WIDTH9: |
|||
case ID_POPUP_PCB_SELECT_WIDTH10: |
|||
case ID_POPUP_PCB_SELECT_WIDTH11: |
|||
case ID_POPUP_PCB_SELECT_WIDTH12: |
|||
case ID_POPUP_PCB_SELECT_WIDTH13: |
|||
case ID_POPUP_PCB_SELECT_WIDTH14: |
|||
case ID_POPUP_PCB_SELECT_WIDTH15: |
|||
case ID_POPUP_PCB_SELECT_WIDTH16: |
|||
m_canvas->MoveCursorToCrossHair(); |
|||
GetDesignSettings().m_UseConnectedTrackWidth = false; |
|||
ii = id - ID_POPUP_PCB_SELECT_WIDTH1; |
|||
GetDesignSettings().SetTrackWidthIndex( ii ); |
|||
break; |
|||
|
|||
case ID_POPUP_PCB_SELECT_VIASIZE1: // this is the default Netclass selection
|
|||
case ID_POPUP_PCB_SELECT_VIASIZE2: // this is a custom value selection
|
|||
case ID_POPUP_PCB_SELECT_VIASIZE3: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE4: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE5: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE6: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE7: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE8: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE9: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE10: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE11: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE12: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE13: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE14: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE15: |
|||
case ID_POPUP_PCB_SELECT_VIASIZE16: |
|||
// select the new current value for via size (via diameter)
|
|||
m_canvas->MoveCursorToCrossHair(); |
|||
ii = id - ID_POPUP_PCB_SELECT_VIASIZE1; |
|||
GetDesignSettings().SetViaSizeIndex( ii ); |
|||
break; |
|||
|
|||
case ID_AUX_TOOLBAR_PCB_TRACK_WIDTH: |
|||
ii = m_SelTrackWidthBox->GetSelection(); |
|||
|
|||
if( ii == int( m_SelTrackWidthBox->GetCount() - 2 ) ) |
|||
{ |
|||
// this is the separator
|
|||
m_SelTrackWidthBox->SetSelection( GetDesignSettings().GetTrackWidthIndex() ); |
|||
} |
|||
else if( ii == int( m_SelTrackWidthBox->GetCount() - 1 ) ) |
|||
{ |
|||
m_SelTrackWidthBox->SetSelection( GetDesignSettings().GetTrackWidthIndex() ); |
|||
DoShowBoardSetupDialog( _( "Tracks & Vias" ) ); |
|||
} |
|||
else |
|||
GetDesignSettings().SetTrackWidthIndex( ii ); |
|||
|
|||
break; |
|||
|
|||
case ID_AUX_TOOLBAR_PCB_VIA_SIZE: |
|||
ii = m_SelViaSizeBox->GetSelection(); |
|||
|
|||
if( ii == int( m_SelViaSizeBox->GetCount() - 2 ) ) |
|||
{ |
|||
// this is the separator
|
|||
m_SelViaSizeBox->SetSelection( GetDesignSettings().GetViaSizeIndex() ); |
|||
} |
|||
else if( ii == int( m_SelViaSizeBox->GetCount() - 1 ) ) |
|||
{ |
|||
m_SelViaSizeBox->SetSelection( GetDesignSettings().GetViaSizeIndex() ); |
|||
DoShowBoardSetupDialog( _( "Tracks & Vias" ) ); |
|||
} |
|||
else |
|||
GetDesignSettings().SetViaSizeIndex( ii ); |
|||
|
|||
break; |
|||
|
|||
default: |
|||
wxLogDebug( wxT( "PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event() error") ); |
|||
break; |
|||
} |
|||
|
|||
// Refresh track in progress, if any, by forcing a mouse event,
|
|||
// to call the current function attached to the mouse
|
|||
/*if( m_canvas->IsMouseCaptured() )
|
|||
{ |
|||
wxMouseEvent event(wxEVT_MOTION); |
|||
wxPostEvent( m_canvas, event ); |
|||
}*/ |
|||
//+hp
|
|||
//Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner.
|
|||
|
|||
if( m_canvas->IsMouseCaptured() ) |
|||
m_canvas->Refresh(); |
|||
} |
@ -1,304 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2009-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.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 magnetic_tracks_functions.cpp |
|||
*/ |
|||
|
|||
/* functions used to control the cursor position, when creating a track
|
|||
* and when the "magnetic tracks" option is on |
|||
* (the current created track is kept near existing tracks |
|||
* the distance is the clearance between tracks) |
|||
*/ |
|||
|
|||
#include <fctsys.h>
|
|||
#include <pcbnew.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <macros.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
|
|||
#include <pcbnew_id.h>
|
|||
|
|||
|
|||
/**
|
|||
* Function Join |
|||
* finds the point where line segment (b1,b0) intersects with segment (a1,a0). |
|||
* If that point would be outside of (a0,a1), the respective endpoint is used. |
|||
* Join returns the point in "res" and "true" if a suitable point was found, |
|||
* "false" if both lines are parallel or if the length of either segment is zero. |
|||
*/ |
|||
static bool Join( wxPoint* aIntersectPoint, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 ) |
|||
{ |
|||
/* References:
|
|||
http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
|
|||
http://www.gekkou.co.uk/blogs/monologues/2007/12/13/1197586800000.html
|
|||
*/ |
|||
|
|||
double denom; |
|||
double t; |
|||
|
|||
// if either segment is zero length
|
|||
if( a1.x==a0.x && a1.y==a0.y ) |
|||
return false; |
|||
|
|||
if( b1.x==b0.x && b1.y==b0.y ) |
|||
return false; |
|||
|
|||
a1 -= a0; |
|||
b1 -= b0; |
|||
|
|||
b0 -= a0; |
|||
|
|||
denom = (double) b1.y * a1.x - (double) b1.x * a1.y; |
|||
|
|||
if( !denom ) |
|||
{ |
|||
return false; // parallel
|
|||
} |
|||
|
|||
t = ((double) b1.y * b0.x - (double) b1.x * b0.y ) / denom; |
|||
|
|||
t = std::min( std::max( t, 0.0 ), 1.0 ); |
|||
|
|||
aIntersectPoint->x = KiROUND( a0.x + t * a1.x ); |
|||
aIntersectPoint->y = KiROUND( a0.y + t * a1.y ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* "Project" finds the projection of a grid point on a track. This is the point |
|||
* from where we want to draw new orthogonal tracks when starting on a track. |
|||
*/ |
|||
bool FindBestGridPointOnTrack( wxPoint* aNearPos, wxPoint on_grid, const TRACK* track ) |
|||
{ |
|||
if( track->GetStart ()== track->GetEnd() ) |
|||
return false; |
|||
|
|||
wxPoint vec = track->GetEnd() - track->GetStart(); |
|||
|
|||
double t = double( on_grid.x - track->GetStart().x ) * vec.x + |
|||
double( on_grid.y - track->GetStart().y ) * vec.y; |
|||
|
|||
t /= (double) vec.x * vec.x + (double) vec.y * vec.y; |
|||
t = std::min( std::max( t, 0.0 ), 1.0 ); |
|||
|
|||
aNearPos->x = KiROUND( track->GetStart().x + t * vec.x ); |
|||
aNearPos->y = KiROUND( track->GetStart().y + t * vec.y ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* Function Magnetize |
|||
* tests to see if there are any magnetic items within near reach of the given |
|||
* "curpos". If yes, then curpos is adjusted appropriately according to that |
|||
* near magnetic item and true is returned. |
|||
* @param frame = the current frame |
|||
* @param aCurrentTool = the current tool id (from vertical right toolbar) |
|||
* @param aGridSize = the current grid size |
|||
* @param on_grid = the on grid position near initial position ( often on_grid = curpos) |
|||
* @param curpos The initial position, and what to adjust if a change is needed. |
|||
* @return bool - true if the position was adjusted magnetically, else false. |
|||
*/ |
|||
bool Magnetize( PCB_BASE_EDIT_FRAME* frame, int aCurrentTool, wxSize aGridSize, |
|||
wxPoint on_grid, wxPoint* curpos ) |
|||
{ |
|||
// Note: only used for routing in the Legacy Toolset
|
|||
// Can be greatly simplified when the Legacy Toolset is retired.
|
|||
|
|||
bool doCheckNet = frame->Settings().m_magneticPads != CAPTURE_ALWAYS && frame->Settings().m_legacyDrcOn; |
|||
bool doCheckLayer = aCurrentTool == ID_TRACK_BUTT; |
|||
bool doTrack = false; |
|||
bool doPad = false; |
|||
bool amMovingVia = false; |
|||
|
|||
BOARD* m_Pcb = frame->GetBoard(); |
|||
TRACK* currTrack = g_CurrentTrackSegment; |
|||
BOARD_ITEM* currItem = frame->GetCurItem(); |
|||
PCB_SCREEN* screen = frame->GetScreen(); |
|||
wxPoint pos = frame->RefPos( true ); |
|||
|
|||
// D( printf( "currTrack=%p currItem=%p currTrack->Type()=%d currItem->Type()=%d\n", currTrack, currItem, currTrack ? currTrack->Type() : 0, currItem ? currItem->Type() : 0 ); )
|
|||
|
|||
if( !currTrack && currItem && currItem->Type()==PCB_VIA_T && currItem->GetFlags() ) |
|||
{ |
|||
// moving a VIA
|
|||
currTrack = (TRACK*) currItem; |
|||
amMovingVia = true; |
|||
|
|||
return false; // comment this return out and play with it.
|
|||
} |
|||
else if( currItem != currTrack ) |
|||
{ |
|||
currTrack = NULL; |
|||
} |
|||
|
|||
if( frame->Settings().m_magneticPads == CAPTURE_ALWAYS ) |
|||
doPad = true; |
|||
|
|||
if( frame->Settings().m_magneticTracks == CAPTURE_ALWAYS ) |
|||
doTrack = true; |
|||
|
|||
if( aCurrentTool == ID_TRACK_BUTT || amMovingVia ) |
|||
{ |
|||
int q = CAPTURE_CURSOR_IN_TRACK_TOOL; |
|||
|
|||
if( frame->Settings().m_magneticPads == q ) |
|||
doPad = true; |
|||
|
|||
if( frame->Settings().m_magneticTracks == q ) |
|||
doTrack = true; |
|||
} |
|||
|
|||
// The search precedence order is pads, then tracks/vias
|
|||
if( doPad ) |
|||
{ |
|||
D_PAD* pad; |
|||
if( doCheckLayer ) |
|||
pad = m_Pcb->GetPad( pos, LSET( screen->m_Active_Layer ) ); |
|||
else |
|||
pad = m_Pcb->GetPad( pos ); |
|||
|
|||
if( pad ) |
|||
{ |
|||
if( doCheckNet && currTrack && currTrack->GetNetCode() != pad->GetNetCode() ) |
|||
return false; |
|||
|
|||
*curpos = pad->GetPosition(); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
// after pads, only track & via tests remain, skip them if not desired
|
|||
if( doTrack ) |
|||
{ |
|||
PCB_LAYER_ID layer = screen->m_Active_Layer; |
|||
|
|||
for( TRACK* via = m_Pcb->m_Track; |
|||
via && (via = via->GetVia( *curpos, layer )) != NULL; |
|||
via = via->Next() ) |
|||
{ |
|||
if( via != currTrack ) // a via cannot influence itself
|
|||
{ |
|||
if( !doCheckNet || !currTrack || currTrack->GetNetCode() == via->GetNetCode() ) |
|||
{ |
|||
*curpos = via->GetStart(); |
|||
// D(printf("via hit\n");)
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if( !currTrack ) |
|||
{ |
|||
LSET layers( layer ); |
|||
|
|||
TRACK* track = m_Pcb->GetVisibleTrack( m_Pcb->m_Track, pos, layers ); |
|||
|
|||
if( !track || track->Type() != PCB_TRACE_T ) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return FindBestGridPointOnTrack( curpos, on_grid, track ); |
|||
} |
|||
|
|||
/*
|
|||
* In two segment mode, ignore the final segment if it's inside a grid square. |
|||
*/ |
|||
if( !amMovingVia && currTrack && frame->Settings().m_legacyUseTwoSegmentTracks && currTrack->Back() |
|||
&& currTrack->GetStart().x - aGridSize.x < currTrack->GetEnd().x |
|||
&& currTrack->GetStart().x + aGridSize.x > currTrack->GetEnd().x |
|||
&& currTrack->GetStart().y - aGridSize.y < currTrack->GetEnd().y |
|||
&& currTrack->GetStart().y + aGridSize.y > currTrack->GetEnd().y ) |
|||
{ |
|||
currTrack = currTrack->Back(); |
|||
} |
|||
|
|||
|
|||
for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) |
|||
{ |
|||
if( track->Type() != PCB_TRACE_T ) |
|||
continue; |
|||
|
|||
if( doCheckNet && currTrack && currTrack->GetNetCode() != track->GetNetCode() ) |
|||
continue; |
|||
|
|||
if( m_Pcb->IsLayerVisible( track->GetLayer() ) == false ) |
|||
continue; |
|||
|
|||
// omit the layer check if moving a via
|
|||
if( !amMovingVia && !track->IsOnLayer( layer ) ) |
|||
continue; |
|||
|
|||
if( !track->HitTest( *curpos ) ) |
|||
continue; |
|||
|
|||
if( Join( curpos, track->GetStart(), track->GetEnd(), currTrack->GetStart(), currTrack->GetEnd() ) ) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
if( aCurrentTool == ID_TRACK_BUTT || amMovingVia ) |
|||
{ |
|||
// At this point we have a drawing mouse on a track, we are drawing
|
|||
// a new track and that new track is parallel to the track the
|
|||
// mouse is on. Find the nearest end point of the track under mouse
|
|||
// to the mouse and return that.
|
|||
double distStart = GetLineLength( *curpos, track->GetStart() ); |
|||
double distEnd = GetLineLength( *curpos, track->GetEnd() ); |
|||
|
|||
// if track not via, or if its a via dragging but not with its adjacent track
|
|||
if( currTrack->Type() != PCB_VIA_T || |
|||
( currTrack->GetStart() != track->GetStart() && currTrack->GetStart() != track->GetEnd() )) |
|||
{ |
|||
double max_dist = currTrack->GetWidth() / 2.0f; |
|||
|
|||
if( distStart <= max_dist ) |
|||
{ |
|||
// D(printf("nearest end is start\n");)
|
|||
*curpos = track->GetStart(); |
|||
return true; |
|||
} |
|||
|
|||
if( distEnd <= max_dist ) |
|||
{ |
|||
// D(printf("nearest end is end\n");)
|
|||
*curpos = track->GetEnd(); |
|||
return true; |
|||
} |
|||
|
|||
// @todo otherwise confine curpos such that it stays centered within "track"
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
@ -1,145 +0,0 @@ |
|||
/**
|
|||
* @file minimun_spanning_tree.cpp |
|||
*/ |
|||
|
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2011 Jean-Pierre Charras |
|||
* Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. |
|||
* |
|||
* derived from this article: |
|||
* http://compprog.wordpress.com/2007/11/09/minimal-spanning-trees-prims-algorithm
|
|||
* |
|||
* 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 <limits.h>
|
|||
|
|||
#include <minimun_spanning_tree.h>
|
|||
#include <class_pad.h>
|
|||
|
|||
/*
|
|||
* The class MIN_SPAN_TREE calculates the rectilinear minimum spanning tree |
|||
* of a set of points (pads usually having the same net) |
|||
* using the Prim's algorithm. |
|||
*/ |
|||
|
|||
/*
|
|||
* Prim's Algorithm |
|||
* Step 0 |
|||
* Pick any vertex as a starting vertex. (Call it S). |
|||
* Mark it with any given flag, say 1. |
|||
* |
|||
* Step 1 |
|||
* Find the nearest neighbour of S (call it P1). |
|||
* Mark both P1 and the edge SP1. |
|||
* cheapest unmarked edge in the graph that doesn't close a marked circuit. |
|||
* Mark this edge. |
|||
* |
|||
* Step 2 |
|||
* Find the nearest unmarked neighbour to the marked subgraph |
|||
* (i.e., the closest vertex to any marked vertex). |
|||
* Mark it and the edge connecting the vertex. |
|||
* |
|||
* Step 3 |
|||
* Repeat Step 2 until all vertices are marked. |
|||
* The marked subgraph is a minimum spanning tree. |
|||
*/ |
|||
MIN_SPAN_TREE::MIN_SPAN_TREE() |
|||
{ |
|||
MSP_Init( 0 ); |
|||
} |
|||
|
|||
|
|||
void MIN_SPAN_TREE::MSP_Init( int aNodesCount ) |
|||
{ |
|||
m_Size = std::max( aNodesCount, 1 ); |
|||
inTree.clear(); |
|||
linkedTo.clear(); |
|||
distTo.clear(); |
|||
|
|||
if( m_Size == 0 ) |
|||
return; |
|||
|
|||
// Reserve space in memory
|
|||
inTree.reserve( m_Size ); |
|||
linkedTo.reserve( m_Size ); |
|||
distTo.reserve( m_Size ); |
|||
|
|||
// Initialize values:
|
|||
for( int ii = 0; ii < m_Size; ii++ ) |
|||
{ |
|||
// Initialise dist with infinity:
|
|||
distTo.push_back( INT_MAX ); |
|||
|
|||
// Mark all nodes as NOT beeing in the minimum spanning tree:
|
|||
inTree.push_back( 0 ); |
|||
|
|||
linkedTo.push_back( 0 ); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* updateDistances(int target)
|
|||
* should be called immediately after target is added to the tree; |
|||
* updates dist so that the values are correct (goes through target's |
|||
* neighbours making sure that the distances between them and the tree |
|||
* are indeed minimum) |
|||
*/ |
|||
void MIN_SPAN_TREE::updateDistances( int target ) |
|||
{ |
|||
for( int ii = 0; ii < m_Size; ++ii ) |
|||
{ |
|||
if( !inTree[ii] ) // no need to evaluate weight for already in tree items
|
|||
{ |
|||
int weight = GetWeight( target, ii ); |
|||
if( (weight > 0) && (distTo[ii] > weight ) ) |
|||
{ |
|||
distTo[ii] = weight; |
|||
linkedTo[ii] = target; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void MIN_SPAN_TREE::BuildTree() |
|||
{ |
|||
// Add the first node to the tree
|
|||
inTree[0] = 1; |
|||
updateDistances( 0 ); |
|||
|
|||
for( int treeSize = 1; treeSize < m_Size; ++treeSize ) |
|||
{ |
|||
// Find the node with the smallest distance to the tree
|
|||
int min = -1; |
|||
|
|||
for( int ii = 0; ii < m_Size; ++ii ) |
|||
{ |
|||
if( !inTree[ii] ) |
|||
{ |
|||
if( (min == -1) || (distTo[min] > distTo[ii]) ) |
|||
min = ii; |
|||
} |
|||
} |
|||
|
|||
inTree[min] = 1; |
|||
updateDistances( min ); |
|||
} |
|||
} |
@ -1,101 +0,0 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2011-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 minimun_spanning_tree.h |
|||
*/ |
|||
|
|||
#include <vector> |
|||
|
|||
/** |
|||
* @brief The class MIN_SPAN_TREE calculates the rectilinear minimum spanning tree |
|||
* of a set of points (pads usually having the same net) |
|||
* this class is an abstract class because you must provide the function |
|||
* int GetWeight( int aItem1, int aItem2 ) |
|||
* that calculate the distance between 2 items |
|||
* MIN_SPAN_TREE does not know anything about the actual items to link |
|||
* by the tree |
|||
*/ |
|||
class MIN_SPAN_TREE |
|||
{ |
|||
protected: |
|||
int m_Size; /* The number of nodes in the graph |
|||
*/ |
|||
private: |
|||
std::vector<char> inTree; /* inTree[ii] is a flag set to 1 if the node ii |
|||
* is already in the minimum spanning tree; 0 otherwise |
|||
*/ |
|||
std::vector<int> linkedTo; /* linkedTo[ii] holds the index of the node ii would have to be |
|||
* linked to in order to get a distance of d[ii] |
|||
* NOTE: linkedTo[0] is the starting point of the tree |
|||
* linkedTo[1] is the first linked point to use |
|||
* ii and linkedTo[ii] are the 2 ends of an edge in the graph |
|||
*/ |
|||
std::vector<int> distTo; /* distTo[ii] is the distance between node ii and the minimum spanning |
|||
* tree; |
|||
* this is initially infinity (INT_MAX); |
|||
* if ii is already in the tree, then d[ii] is undefined; |
|||
* this is just a temporary variable. It's not necessary but speeds |
|||
* up execution considerably (by a factor of n) |
|||
*/ |
|||
public: |
|||
MIN_SPAN_TREE(); |
|||
void MSP_Init( int aNodesCount ); |
|||
void BuildTree(); |
|||
|
|||
int GetWhoTo( int aIdx ) |
|||
{ |
|||
return linkedTo[aIdx]; |
|||
} |
|||
|
|||
|
|||
int GetDist( int aIdx ) |
|||
{ |
|||
return distTo[aIdx]; |
|||
} |
|||
|
|||
/** |
|||
* Function GetWeight |
|||
* calculates the weight between 2 items |
|||
* NOTE: The weight between a node and itself should be 0 |
|||
* It is virtual pure, you must provide your GetWeight function |
|||
* @param aItem1 = first item |
|||
* @param aItem2 = other item |
|||
* @return the weight between items ( usually the distance ) |
|||
*/ |
|||
virtual int GetWeight( int aItem1, int aItem2 ) = 0; |
|||
|
|||
private: |
|||
|
|||
/** |
|||
* Function updateDistances |
|||
* should be called immediately after target is added to the tree; |
|||
* updates d so that the values are correct (goes through target's |
|||
* neighbours making sure that the distances between them and the tree |
|||
* are indeed minimum) |
|||
* @param aTarget = index of curr item |
|||
*/ |
|||
void updateDistances( int aTarget ); |
|||
|
|||
}; |
@ -1,233 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr |
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net> |
|||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.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 <gr_basic.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <confirm.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <trigo.h>
|
|||
#include <macros.h>
|
|||
#include <class_board.h>
|
|||
#include <class_module.h>
|
|||
#include <pcbnew.h>
|
|||
#include <drag.h>
|
|||
#include <dialog_get_footprint_by_name.h>
|
|||
|
|||
#include <connectivity/connectivity_data.h>
|
|||
|
|||
static MODULE* s_ModuleInitialCopy = NULL; // Copy of module for abort/undo command
|
|||
|
|||
static PICKED_ITEMS_LIST s_PickedList; // a pick-list to save initial module
|
|||
// and dragged tracks
|
|||
|
|||
|
|||
MODULE* PCB_BASE_FRAME::GetFootprintFromBoardByReference() |
|||
{ |
|||
wxString moduleName; |
|||
MODULE* module = NULL; |
|||
wxArrayString fplist; |
|||
|
|||
// Build list of available fp references, to display them in dialog
|
|||
for( MODULE* fp = GetBoard()->m_Modules; fp; fp = fp->Next() ) |
|||
fplist.Add( fp->GetReference() + wxT(" ( ") + fp->GetValue() + wxT(" )") ); |
|||
|
|||
fplist.Sort(); |
|||
|
|||
DIALOG_GET_FOOTPRINT_BY_NAME dlg( this, fplist ); |
|||
|
|||
if( dlg.ShowModal() != wxID_OK ) //Aborted by user
|
|||
return NULL; |
|||
|
|||
moduleName = dlg.GetValue(); |
|||
moduleName.Trim( true ); |
|||
moduleName.Trim( false ); |
|||
|
|||
if( !moduleName.IsEmpty() ) |
|||
{ |
|||
module = GetBoard()->m_Modules; |
|||
|
|||
while( module ) |
|||
{ |
|||
if( module->GetReference().CmpNoCase( moduleName ) == 0 ) |
|||
break; |
|||
|
|||
module = module->Next(); |
|||
} |
|||
} |
|||
|
|||
return module; |
|||
} |
|||
|
|||
|
|||
void PCB_BASE_FRAME::PlaceModule( MODULE* aModule, wxDC* aDC, bool aRecreateRatsnest ) |
|||
{ |
|||
wxPoint newpos; |
|||
|
|||
if( aModule == 0 ) |
|||
return; |
|||
|
|||
OnModify(); |
|||
|
|||
|
|||
if( aModule->IsNew() ) |
|||
{ |
|||
SaveCopyInUndoList( aModule, UR_NEW ); |
|||
} |
|||
else if( aModule->IsMoving() ) |
|||
{ |
|||
ITEM_PICKER picker( aModule, UR_CHANGED ); |
|||
picker.SetLink( s_ModuleInitialCopy ); |
|||
s_PickedList.PushItem( picker ); |
|||
s_ModuleInitialCopy = NULL; // the picker is now owner of s_ModuleInitialCopy.
|
|||
} |
|||
|
|||
if( s_PickedList.GetCount() ) |
|||
{ |
|||
SaveCopyInUndoList( s_PickedList, UR_UNSPECIFIED ); |
|||
|
|||
// Clear list, but DO NOT delete items, because they are owned by the saved undo
|
|||
// list and they therefore in use
|
|||
s_PickedList.ClearItemsList(); |
|||
} |
|||
|
|||
auto displ_opts = (PCB_DISPLAY_OPTIONS*)GetDisplayOptions(); |
|||
|
|||
if( displ_opts->m_Show_Module_Ratsnest && aDC ) |
|||
TraceModuleRatsNest( aDC ); |
|||
|
|||
newpos = GetCrossHairPosition(); |
|||
aModule->SetPosition( newpos ); |
|||
aModule->ClearFlags(); |
|||
|
|||
delete s_ModuleInitialCopy; |
|||
s_ModuleInitialCopy = NULL; |
|||
|
|||
if( aDC ) |
|||
aModule->Draw( m_canvas, aDC, GR_OR ); |
|||
|
|||
// Redraw dragged track segments, if any
|
|||
bool isDragged = g_DragSegmentList.size() > 0; |
|||
|
|||
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) |
|||
{ |
|||
TRACK * track = g_DragSegmentList[ii].m_Track; |
|||
track->SetState( IN_EDIT, false ); |
|||
track->ClearFlags(); |
|||
|
|||
if( aDC ) |
|||
track->Draw( m_canvas, aDC, GR_OR ); |
|||
} |
|||
|
|||
// Delete drag list
|
|||
EraseDragList(); |
|||
|
|||
m_canvas->SetMouseCapture( NULL, NULL ); |
|||
|
|||
if( aRecreateRatsnest ) |
|||
{ |
|||
if( isDragged ) // Some tracks have positions modified: rebuild the connectivity
|
|||
m_Pcb->GetConnectivity()->Build(m_Pcb); |
|||
else // Only pad positions are modified: rebuild the connectivity only for this footprint (faster)
|
|||
m_Pcb->GetConnectivity()->Update( aModule ); |
|||
} |
|||
|
|||
if( ( GetBoard()->IsElementVisible( LAYER_RATSNEST ) || displ_opts->m_Show_Module_Ratsnest ) |
|||
&& aRecreateRatsnest ) |
|||
Compile_Ratsnest( aDC, true ); |
|||
|
|||
if( aDC ) |
|||
m_canvas->Refresh(); |
|||
|
|||
SetMsgPanel( aModule ); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Rotate the footprint angle degrees in the direction < 0. |
|||
* If incremental == true, the rotation is made from the last orientation, |
|||
* If the module is placed in the absolute orientation angle. |
|||
* If DC == NULL, the component does not redraw. |
|||
* Otherwise, it erases and redraws turns |
|||
*/ |
|||
void PCB_BASE_FRAME::Rotate_Module( wxDC* DC, MODULE* module, double angle, bool incremental ) |
|||
{ |
|||
if( module == NULL ) |
|||
return; |
|||
|
|||
OnModify(); |
|||
|
|||
if( !module->IsMoving() ) // This is a simple rotation, no other edit in progress
|
|||
{ |
|||
if( DC ) // Erase footprint to screen
|
|||
{ |
|||
module->SetFlags( DO_NOT_DRAW ); |
|||
m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); |
|||
module->ClearFlags( DO_NOT_DRAW ); |
|||
|
|||
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) ) |
|||
DrawGeneralRatsnest( DC ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if( DC ) |
|||
{ |
|||
module->DrawOutlinesWhenMoving( m_canvas, DC, g_Offset_Module ); |
|||
DrawSegmentWhileMovingFootprint( m_canvas, DC ); |
|||
} |
|||
} |
|||
|
|||
|
|||
if( incremental ) |
|||
module->SetOrientation( module->GetOrientation() + angle ); |
|||
else |
|||
module->SetOrientation( angle ); |
|||
|
|||
SetMsgPanel( module ); |
|||
m_Pcb->GetConnectivity()->Update( module ); |
|||
|
|||
if( DC ) |
|||
{ |
|||
if( !module->IsMoving() ) |
|||
{ |
|||
// not beiing moved: redraw the module and update ratsnest
|
|||
module->Draw( m_canvas, DC, GR_OR ); |
|||
|
|||
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) ) |
|||
Compile_Ratsnest( DC, true ); |
|||
} |
|||
else |
|||
{ |
|||
// Beiing moved: just redraw it
|
|||
module->DrawOutlinesWhenMoving( m_canvas, DC, g_Offset_Module ); |
|||
DrawSegmentWhileMovingFootprint( m_canvas, DC ); |
|||
} |
|||
|
|||
if( module->GetEditFlags() == 0 ) // module not in edit: redraw full screen
|
|||
m_canvas->Refresh(); |
|||
} |
|||
} |
@ -1,82 +0,0 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2007 Jean-Pierre Charras, jp.charras@wanadoo.fr |
|||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.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 pcbnew/protos.h |
|||
*/ |
|||
|
|||
#ifndef PROTO_H |
|||
#define PROTO_H |
|||
#include <gr_basic.h> |
|||
|
|||
class wxDC; |
|||
class wxPoint; |
|||
class EDA_DRAW_PANEL; |
|||
class BOARD_ITEM; |
|||
class TRACK; |
|||
class MODULE; |
|||
|
|||
|
|||
/***************/ |
|||
/* TRPISTE.CPP */ |
|||
/***************/ |
|||
|
|||
/** |
|||
* Function DrawTraces |
|||
* Draws n consecutive track segments in list. |
|||
* Useful to show a track when it is a chain of segments |
|||
* (for instance when creating a new track) |
|||
* |
|||
* @param panel A EDA_DRAW_ITEM pointer to the canvas. |
|||
* @param DC A wxDC pointer of the device context used for drawing. |
|||
* @param aStartTrace First segment |
|||
* @param nbsegment Number of segments in list |
|||
* @param mode_color Drawing mode (GRXOR, GROR ..) |
|||
*/ |
|||
|
|||
void DrawTraces( EDA_DRAW_PANEL* panel, |
|||
wxDC* DC, |
|||
TRACK* aStartTrace, |
|||
int nbsegment, |
|||
GR_DRAWMODE mode_color ); |
|||
|
|||
void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, |
|||
bool aErase ); |
|||
|
|||
/** |
|||
* Determine end point for a segment direction 0, 90, or 45 degrees |
|||
* depending on it's position from the origin \a aOrigin and \a aPosition. |
|||
*/ |
|||
wxPoint CalculateSegmentEndPoint( const wxPoint& aPosition, const wxPoint& aOrigin ); |
|||
|
|||
/** |
|||
* Finds the projection of a grid point on a track. This is the point |
|||
* from where we want to draw new orthogonal tracks when starting on a track. |
|||
*/ |
|||
bool FindBestGridPointOnTrack( wxPoint* res, wxPoint on_grid, const TRACK* track ); |
|||
TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, LAYER_NUM aLayer, const wxPoint& aRef ); |
|||
|
|||
|
|||
|
|||
#endif /* #define PROTO_H */ |
@ -1,271 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr |
|||
* Copyright (C) 1992-2013 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 target_edit.cpp |
|||
* @brief Functions to edit targets (class #PCB_TARGET). |
|||
*/ |
|||
|
|||
#include <fctsys.h>
|
|||
#include <class_drawpanel.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <dialog_helpers.h>
|
|||
#include <base_units.h>
|
|||
#include <gr_basic.h>
|
|||
#include <board_commit.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_pcb_target.h>
|
|||
|
|||
#include <pcbnew.h>
|
|||
#include <dialog_target_properties_base.h>
|
|||
#include <widgets/unit_binder.h>
|
|||
|
|||
// Routines Locales
|
|||
static void AbortMoveAndEditTarget( EDA_DRAW_PANEL* Panel, wxDC* DC ); |
|||
static void ShowTargetShapeWhileMovingMouse( EDA_DRAW_PANEL* aPanel, |
|||
wxDC* aDC, |
|||
const wxPoint& aPosition, |
|||
bool aErase ); |
|||
|
|||
// Local variables :
|
|||
static int MireDefaultSize = Millimeter2iu( 5 ); |
|||
|
|||
static PCB_TARGET s_TargetCopy( NULL ); // Used to store "old" values of the current item
|
|||
// parameters before editing for undo/redo/cancel
|
|||
|
|||
/**********************************/ |
|||
/* class DIALOG_TARGET_PROPERTIES */ |
|||
/**********************************/ |
|||
|
|||
class DIALOG_TARGET_PROPERTIES : public DIALOG_TARGET_PROPERTIES_BASE |
|||
{ |
|||
private: |
|||
PCB_EDIT_FRAME* m_Parent; |
|||
wxDC* m_DC; |
|||
PCB_TARGET* m_Target; |
|||
|
|||
UNIT_BINDER m_Size; |
|||
UNIT_BINDER m_Thickness; |
|||
|
|||
public: |
|||
DIALOG_TARGET_PROPERTIES( PCB_EDIT_FRAME* aParent, PCB_TARGET* aTarget, wxDC* aDC ); |
|||
~DIALOG_TARGET_PROPERTIES() { } |
|||
|
|||
private: |
|||
bool TransferDataToWindow() override; |
|||
bool TransferDataFromWindow() override; |
|||
}; |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ) |
|||
{ |
|||
DIALOG_TARGET_PROPERTIES dialog( this, aTarget, DC ); |
|||
|
|||
dialog.ShowModal(); |
|||
} |
|||
|
|||
|
|||
DIALOG_TARGET_PROPERTIES::DIALOG_TARGET_PROPERTIES( PCB_EDIT_FRAME* aParent, PCB_TARGET* aTarget, |
|||
wxDC* aDC ) : |
|||
DIALOG_TARGET_PROPERTIES_BASE( aParent ), |
|||
m_Parent( aParent ), |
|||
m_DC( aDC ), |
|||
m_Target( aTarget ), |
|||
m_Size( aParent, m_sizeLabel, m_sizeCtrl, m_sizeUnits, true ), |
|||
m_Thickness( aParent, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true ) |
|||
{ |
|||
m_sdbSizerButtsOK->SetDefault(); |
|||
|
|||
SetInitialFocus( m_sizeCtrl ); |
|||
|
|||
// Now all widgets have the size fixed, call FinishDialogSettings
|
|||
FinishDialogSettings(); |
|||
} |
|||
|
|||
|
|||
bool DIALOG_TARGET_PROPERTIES::TransferDataToWindow() |
|||
{ |
|||
m_Size.SetValue( m_Target->GetSize() ); |
|||
m_Thickness.SetValue( m_Target->GetWidth() ); |
|||
|
|||
m_TargetShape->SetSelection( m_Target->GetShape() ? 1 : 0 ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool DIALOG_TARGET_PROPERTIES::TransferDataFromWindow() |
|||
{ |
|||
// Zero-size targets are hard to see/select.
|
|||
if( !m_Size.Validate( Mils2iu( 1 ), INT_MAX ) ) |
|||
return false; |
|||
|
|||
BOARD_COMMIT commit( m_Parent ); |
|||
commit.Modify( m_Target ); |
|||
|
|||
if( m_DC ) |
|||
m_Target->Draw( m_Parent->GetCanvas(), m_DC, GR_XOR ); |
|||
|
|||
// Save old item in undo list, if is is not currently edited (will be later if so)
|
|||
bool pushCommit = ( m_Target->GetEditFlags() == 0 ); |
|||
|
|||
if( m_Target->GetEditFlags() != 0 ) // other edit in progress (MOVE, NEW ..)
|
|||
m_Target->SetFlags( IN_EDIT ); // set flag in edit to force
|
|||
// undo/redo/abort proper operation
|
|||
|
|||
m_Target->SetWidth( m_Thickness.GetValue() ); |
|||
m_Target->SetSize( m_Size.GetValue() ); |
|||
m_Target->SetShape( m_TargetShape->GetSelection() ? 1 : 0 ); |
|||
|
|||
if( m_DC ) |
|||
m_Target->Draw( m_Parent->GetCanvas(), m_DC, ( m_Target->IsMoving() ) ? GR_XOR : GR_OR ); |
|||
|
|||
if( pushCommit ) |
|||
commit.Push( _( "Modified alignment target" ) ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::DeleteTarget( PCB_TARGET* aTarget, wxDC* DC ) |
|||
{ |
|||
if( aTarget == NULL ) |
|||
return; |
|||
|
|||
aTarget->Draw( m_canvas, DC, GR_XOR ); |
|||
SaveCopyInUndoList( aTarget, UR_DELETED ); |
|||
aTarget->UnLink(); |
|||
} |
|||
|
|||
|
|||
static void AbortMoveAndEditTarget( EDA_DRAW_PANEL* Panel, wxDC* DC ) |
|||
{ |
|||
BASE_SCREEN* screen = Panel->GetScreen(); |
|||
PCB_TARGET* target = (PCB_TARGET*) screen->GetCurItem(); |
|||
|
|||
( (PCB_EDIT_FRAME*) Panel->GetParent() )->SetCurItem( NULL ); |
|||
|
|||
Panel->SetMouseCapture( NULL, NULL ); |
|||
|
|||
if( target == NULL ) |
|||
return; |
|||
|
|||
target->Draw( Panel, DC, GR_XOR ); |
|||
|
|||
if( target->IsNew() ) // If it is new, delete it
|
|||
{ |
|||
target->Draw( Panel, DC, GR_XOR ); |
|||
target->DeleteStructure(); |
|||
target = NULL; |
|||
} |
|||
else // it is an existing item: retrieve initial values of parameters
|
|||
{ |
|||
if( ( target->GetEditFlags() & (IN_EDIT | IS_MOVED) ) ) |
|||
{ |
|||
target->SetPosition( s_TargetCopy.GetPosition() ); |
|||
target->SetWidth( s_TargetCopy.GetWidth() ); |
|||
target->SetSize( s_TargetCopy.GetSize() ); |
|||
target->SetShape( s_TargetCopy.GetShape() ); |
|||
} |
|||
|
|||
target->ClearFlags(); |
|||
target->Draw( Panel, DC, GR_OR ); |
|||
} |
|||
} |
|||
|
|||
|
|||
PCB_TARGET* PCB_EDIT_FRAME::CreateTarget( wxDC* DC ) |
|||
{ |
|||
PCB_TARGET* target = new PCB_TARGET( GetBoard() ); |
|||
|
|||
target->SetFlags( IS_NEW ); |
|||
|
|||
GetBoard()->Add( target ); |
|||
|
|||
target->SetLayer( Edge_Cuts ); |
|||
target->SetWidth( GetDesignSettings().GetLineThickness( Edge_Cuts ) ); |
|||
target->SetSize( MireDefaultSize ); |
|||
target->SetPosition( GetCrossHairPosition() ); |
|||
|
|||
PlaceTarget( target, DC ); |
|||
|
|||
return target; |
|||
} |
|||
|
|||
|
|||
void PCB_EDIT_FRAME::PlaceTarget( PCB_TARGET* aTarget, wxDC* DC ) |
|||
{ |
|||
if( aTarget == NULL ) |
|||
return; |
|||
|
|||
aTarget->Draw( m_canvas, DC, GR_OR ); |
|||
m_canvas->SetMouseCapture( NULL, NULL ); |
|||
SetCurItem( NULL ); |
|||
OnModify(); |
|||
|
|||
if( aTarget->IsNew() ) |
|||
{ |
|||
SaveCopyInUndoList( aTarget, UR_NEW ); |
|||
aTarget->ClearFlags(); |
|||
return; |
|||
} |
|||
|
|||
if( aTarget->GetEditFlags() == IS_MOVED ) |
|||
{ |
|||
SaveCopyInUndoList( aTarget, UR_MOVED, |
|||
aTarget->GetPosition() - s_TargetCopy.GetPosition() ); |
|||
aTarget->ClearFlags(); |
|||
return; |
|||
} |
|||
|
|||
if( (aTarget->GetEditFlags() & IN_EDIT) ) |
|||
{ |
|||
aTarget->SwapData( &s_TargetCopy ); |
|||
SaveCopyInUndoList( aTarget, UR_CHANGED ); |
|||
aTarget->SwapData( &s_TargetCopy ); |
|||
} |
|||
|
|||
aTarget->ClearFlags(); |
|||
} |
|||
|
|||
|
|||
// Redraw the contour of the track while moving the mouse
|
|||
static void ShowTargetShapeWhileMovingMouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC, |
|||
const wxPoint& aPosition, bool aErase ) |
|||
{ |
|||
BASE_SCREEN* screen = aPanel->GetScreen(); |
|||
PCB_TARGET* target = (PCB_TARGET*) screen->GetCurItem(); |
|||
|
|||
if( target == NULL ) |
|||
return; |
|||
|
|||
if( aErase ) |
|||
target->Draw( aPanel, aDC, GR_XOR ); |
|||
|
|||
target->SetPosition( aPanel->GetParent()->GetCrossHairPosition() ); |
|||
|
|||
target->Draw( aPanel, aDC, GR_XOR ); |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue