From aeed8e6e2c41e2f34dfdfa3fe56b99749fdf5793 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 15 Jun 2020 20:50:20 +0100 Subject: [PATCH] Finish implementation of DRAWSEGMENT::C_RECT. It's currently only supported in the Footprint Editor. It could be easily added to the board editor (all the code is there), but the board editor is a little short on room in the drawing tools toolbar. --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 36 +- common/base_struct.cpp | 1 + common/pcb.keywords | 2 + pcbnew/autorouter/ar_autoplacer.cpp | 28 +- pcbnew/autorouter/ar_autoplacer.h | 10 - pcbnew/autorouter/ar_cell.h | 111 ------ pcbnew/autorouter/ar_matrix.cpp | 369 +----------------- pcbnew/autorouter/ar_matrix.h | 14 - ...board_items_to_polygon_shape_transform.cpp | 12 + pcbnew/class_drawsegment.cpp | 175 ++++++--- pcbnew/class_drawsegment.h | 6 + pcbnew/class_edge_mod.cpp | 7 - .../convert_drawsegment_list_to_polygon.cpp | 19 + .../dialog_graphic_item_properties.cpp | 4 + pcbnew/drc/drc.cpp | 12 + pcbnew/exporters/export_gencad.cpp | 25 ++ pcbnew/exporters/export_idf.cpp | 24 ++ pcbnew/exporters/export_vrml.cpp | 12 +- pcbnew/kicad_plugin.cpp | 14 +- pcbnew/kicad_plugin.h | 3 +- pcbnew/pcb_painter.cpp | 11 +- pcbnew/pcb_parser.cpp | 63 ++- pcbnew/plot_brditems_plotter.cpp | 12 + pcbnew/router/pns_kicad_iface.cpp | 12 + pcbnew/toolbars_footprint_editor.cpp | 29 +- pcbnew/tools/drawing_tool.cpp | 47 ++- pcbnew/tools/drawing_tool.h | 9 + pcbnew/tools/pcb_actions.cpp | 5 + pcbnew/tools/pcb_actions.h | 1 + pcbnew/tools/point_editor.cpp | 53 ++- utils/idftools/idf_common.h | 6 + 31 files changed, 518 insertions(+), 614 deletions(-) delete mode 100644 pcbnew/autorouter/ar_cell.h diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index f12d003b08..3946d2422a 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -781,6 +781,31 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSe } break; + case S_RECT: + { + std::vector pts; + aDrawSegment->GetRectCorners( &pts ); + + const SFVEC2F topLeft3DU( pts[0].x * m_biuTo3Dunits, -pts[0].y * m_biuTo3Dunits ); + const SFVEC2F topRight3DU( pts[1].x * m_biuTo3Dunits, -pts[1].y * m_biuTo3Dunits ); + const SFVEC2F botRight3DU( pts[2].x * m_biuTo3Dunits, -pts[2].y * m_biuTo3Dunits ); + const SFVEC2F botLeft3DU( pts[3].x * m_biuTo3Dunits, -pts[3].y * m_biuTo3Dunits ); + + aDstContainer->Add( new CROUNDSEGMENT2D( topLeft3DU, topRight3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( topRight3DU, botRight3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( botRight3DU, botLeft3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( botLeft3DU, topLeft3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + } + break; + case S_ARC: { const unsigned int nr_segments = @@ -798,10 +823,10 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSe case S_SEGMENT: { - const SFVEC2F start3DU( aDrawSegment->GetStart().x * m_biuTo3Dunits, + const SFVEC2F start3DU( aDrawSegment->GetStart().x * m_biuTo3Dunits, -aDrawSegment->GetStart().y * m_biuTo3Dunits ); - const SFVEC2F end3DU ( aDrawSegment->GetEnd().x * m_biuTo3Dunits, + const SFVEC2F end3DU ( aDrawSegment->GetEnd().x * m_biuTo3Dunits, -aDrawSegment->GetEnd().y * m_biuTo3Dunits ); if( Is_segment_a_circle( start3DU, end3DU ) ) @@ -812,8 +837,7 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSe } else { - aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, - end3DU, + aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU, linewidth * m_biuTo3Dunits, *aDrawSegment ) ); } @@ -832,8 +856,8 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSe if( polyList.IsEmpty() ) // Just for caution break; - Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, - m_biuTo3Dunits, *aDrawSegment ); + Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, + *aDrawSegment ); } break; diff --git a/common/base_struct.cpp b/common/base_struct.cpp index 30cca89120..21ef3aa084 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -656,6 +656,7 @@ void EDA_RECT::Merge( const wxPoint& aPoint ) { m_Pos = aPoint; m_Size = wxSize( 0, 0 ); + m_init = true; return; } diff --git a/common/pcb.keywords b/common/pcb.keywords index 1524957a76..a889be2e2e 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -106,6 +106,7 @@ fp_circle fp_curve fp_line fp_poly +fp_rect fp_text full general @@ -115,6 +116,7 @@ gr_circle gr_curve gr_line gr_poly +gr_rect gr_text hatch hatch_thickness diff --git a/pcbnew/autorouter/ar_autoplacer.cpp b/pcbnew/autorouter/ar_autoplacer.cpp index 9680a313af..610f71d854 100644 --- a/pcbnew/autorouter/ar_autoplacer.cpp +++ b/pcbnew/autorouter/ar_autoplacer.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,6 @@ #include #include "ar_autoplacer.h" -#include "ar_cell.h" #include "ar_matrix.h" #include @@ -53,6 +51,15 @@ #define STEP_AR_MM 1.0 +/* Bits characterizing cell */ +#define CELL_IS_EMPTY 0x00 +#define CELL_IS_HOLE 0x01 /* a conducting hole or obstacle */ +#define CELL_IS_MODULE 0x02 /* auto placement occupied by a module */ +#define CELL_IS_EDGE 0x20 /* Area and auto-placement: limiting cell contour (Board, Zone) */ +#define CELL_IS_FRIEND 0x40 /* Area and auto-placement: cell part of the net */ +#define CELL_IS_ZONE 0x80 /* Area and auto-placement: cell available */ + + /* Penalty (cost) for CntRot90 and CntRot180: * CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed) */ @@ -265,7 +272,6 @@ bool AR_AUTOPLACER::fillMatrix() } - void AR_AUTOPLACER::rotateModule( MODULE* module, double angle, bool incremental ) { if( module == NULL ) @@ -485,22 +491,6 @@ int AR_AUTOPLACER::testRectangle( const EDA_RECT& aRect, int side ) return AR_FREE_CELL; } -int AR_AUTOPLACER::testModuleByPolygon( MODULE* aModule, int aSide, const wxPoint& aOffset ) -{ - // Test for footprint out of board: - // If a footprint is not fully inside the board, substract board polygon - // to the footprint polygon gives a non null area. - SHAPE_POLY_SET fp_area = m_fpAreaTop; - fp_area.Move( -aOffset ); - SHAPE_POLY_SET out_of_board_area; - out_of_board_area.BooleanSubtract( fp_area, m_topFreeArea, SHAPE_POLY_SET::PM_FAST ); - - if( out_of_board_area.OutlineCount() ) - return AR_OCCUIPED_BY_MODULE; - - return AR_FREE_CELL; -} - /* Calculates and returns the clearance area of the rectangular surface * aRect): diff --git a/pcbnew/autorouter/ar_autoplacer.h b/pcbnew/autorouter/ar_autoplacer.h index c46be6eba0..6a17a66425 100644 --- a/pcbnew/autorouter/ar_autoplacer.h +++ b/pcbnew/autorouter/ar_autoplacer.h @@ -29,7 +29,6 @@ #ifndef __AR_AUTOPLACER_H #define __AR_AUTOPLACER_H -#include "ar_cell.h" #include "ar_matrix.h" #include @@ -63,13 +62,6 @@ public: AR_RESULT AutoplaceModules( std::vector aModules, BOARD_COMMIT* aCommit, bool aPlaceOffboardModules = false ); - const std::vector QueryOffboardModules(); - - void SetPlacementGrid( int aGrid ) - { - m_gridSize = aGrid; - } - /** * Set a VIEW overlay to draw items during a autoplace session. */ @@ -104,7 +96,6 @@ private: void genModuleOnRoutingMatrix( MODULE* Module ); int testRectangle( const EDA_RECT& aRect, int side ); - int testModuleByPolygon( MODULE* aModule,int aSide, const wxPoint& aOffset ); unsigned int calculateKeepOutArea( const EDA_RECT& aRect, int side ); int testModuleOnBoard( MODULE* aModule, bool TstOtherSide, const wxPoint& aOffset ); int getOptimalModulePlacement( MODULE* aModule ); @@ -140,7 +131,6 @@ private: BOARD* m_board; wxPoint m_curPosition; - wxPoint m_moduleOffset; double m_minCost; int m_gridSize; diff --git a/pcbnew/autorouter/ar_cell.h b/pcbnew/autorouter/ar_cell.h deleted file mode 100644 index 1136a3dfc0..0000000000 --- a/pcbnew/autorouter/ar_cell.h +++ /dev/null @@ -1,111 +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 - * Copyright (C) 2011 Wayne Stambaugh - * - * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. - * - * First copyright (C) Randy Nevin, 1989 (see PCBCA package) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef _AR_CELL_H_ -#define _AR_CELL_H_ - -/* Bits characterizing cell */ -#define CELL_IS_EMPTY 0x00 -#define CELL_IS_HOLE 0x01 /* a conducting hole or obstacle */ -#define CELL_IS_MODULE 0x02 /* auto placement occupied by a module */ -#define CELL_IS_EDGE 0x20 /* Area and auto-placement: limiting cell contour (Board, Zone) */ -#define CELL_IS_FRIEND 0x40 /* Area and auto-placement: cell part of the net */ -#define CELL_IS_ZONE 0x80 /* Area and auto-placement: cell available */ - -/* Bit masks for presence of obstacles to autorouting */ -#define OCCUPE 1 /* Autorouting: obstacle tracks and vias. */ -#define VIA_IMPOSSIBLE 2 /* Autorouting: obstacle for vias. */ -#define CURRENT_PAD 4 - - -/* traces radiating outward from a hole to a side or corner */ -#define HOLE_NORTH 0x00000002L /* upward */ -#define HOLE_NORTHEAST 0x00000004L /* upward and right */ -#define HOLE_EAST 0x00000008L /* to the right */ -#define HOLE_SOUTHEAST 0x00000010L /* downward and right */ -#define HOLE_SOUTH 0x00000020L /* downward */ -#define HOLE_SOUTHWEST 0x00000040L /* downward and left */ -#define HOLE_WEST 0x00000080L /* to the left */ -#define HOLE_NORTHWEST 0x00000100L /* upward and left */ - -/* straight lines through the center */ -#define LINE_HORIZONTAL 0x00000002L /* left-to-right line */ -#define LINE_VERTICAL 0x00000004L /* top-to-bottom line */ - -/* lines cutting across a corner, connecting adjacent sides */ -#define CORNER_NORTHEAST 0x00000008L /* upper right corner */ -#define CORNER_SOUTHEAST 0x00000010L /* lower right corner */ -#define CORNER_SOUTHWEST 0x00000020L /* lower left corner */ -#define CORNER_NORTHWEST 0x00000040L /* upper left corner */ - -/* diagonal lines through the center */ -#define DIAG_NEtoSW 0x00000080L /* northeast to southwest */ -#define DIAG_SEtoNW 0x00000100L /* southeast to northwest */ - -/* 135 degree angle side-to-far-corner lines */ -#define BENT_NtoSE 0x00000200L /* north to southeast */ -#define BENT_NtoSW 0x00000400L /* north to southwest */ -#define BENT_EtoSW 0x00000800L /* east to southwest */ -#define BENT_EtoNW 0x00001000L /* east to northwest */ -#define BENT_StoNW 0x00002000L /* south to northwest */ -#define BENT_StoNE 0x00004000L /* south to northeast */ -#define BENT_WtoNE 0x00008000L /* west to northeast */ -#define BENT_WtoSE 0x00010000L /* west to southeast */ - -/* 90 degree corner-to-adjacent-corner lines */ -#define ANGLE_NEtoSE 0x00020000L /* northeast to southeast */ -#define ANGLE_SEtoSW 0x00040000L /* southeast to southwest */ -#define ANGLE_SWtoNW 0x00080000L /* southwest to northwest */ -#define ANGLE_NWtoNE 0x00100000L /* northwest to northeast */ - -/* 45 degree angle side-to-near-corner lines */ -#define SHARP_NtoNE 0x00200000L /* north to northeast */ -#define SHARP_EtoNE 0x00400000L /* east to northeast */ -#define SHARP_EtoSE 0x00800000L /* east to southeast */ -#define SHARP_StoSE 0x01000000L /* south to southeast */ -#define SHARP_StoSW 0x02000000L /* south to southwest */ -#define SHARP_WtoSW 0x04000000L /* west to southwest */ -#define SHARP_WtoNW 0x08000000L /* west to northwest */ -#define SHARP_NtoNW 0x10000000L /* north to northwest */ - -/* directions the cell can be reached from (point to previous cell) */ -#define FROM_NOWHERE 0 -#define FROM_NORTH 1 -#define FROM_NORTHEAST 2 -#define FROM_EAST 3 -#define FROM_SOUTHEAST 4 -#define FROM_SOUTH 5 -#define FROM_SOUTHWEST 6 -#define FROM_WEST 7 -#define FROM_NORTHWEST 8 -#define FROM_OTHERSIDE 9 - - -#endif // __AR_CELL_H diff --git a/pcbnew/autorouter/ar_matrix.cpp b/pcbnew/autorouter/ar_matrix.cpp index d0de1f5ddc..4e3b4f1e85 100644 --- a/pcbnew/autorouter/ar_matrix.cpp +++ b/pcbnew/autorouter/ar_matrix.cpp @@ -26,16 +26,12 @@ */ #include "ar_matrix.h" -#include "ar_cell.h" - -#include #include // for KiROUND #include #include #include #include -#include AR_MATRIX::AR_MATRIX() { @@ -46,7 +42,6 @@ AR_MATRIX::AR_MATRIX() m_DirSide[0] = nullptr; m_DirSide[1] = nullptr; m_opWriteCell = nullptr; - m_InitMatrixDone = false; m_Nrows = 0; m_Ncols = 0; m_MemSize = 0; @@ -100,8 +95,6 @@ int AR_MATRIX::InitRoutingMatrix() if( m_Nrows <= 0 || m_Ncols <= 0 ) return 0; - m_InitMatrixDone = true; // we have been called - // give a small margin for memory allocation: int ii = ( m_Nrows + 1 ) * ( m_Ncols + 1 ); @@ -147,8 +140,6 @@ void AR_MATRIX::UnInitRoutingMatrix() { int ii; - m_InitMatrixDone = false; - for( ii = 0; ii < AR_MAX_ROUTING_LAYERS_COUNT; ii++ ) { // de-allocate Dir matrix @@ -182,14 +173,10 @@ void AR_MATRIX::SetCellOperation( AR_MATRIX::CELL_OP aLogicOp ) switch( aLogicOp ) { default: - case WRITE_CELL: m_opWriteCell = &AR_MATRIX::SetCell; break; - - case WRITE_OR_CELL: m_opWriteCell = &AR_MATRIX::OrCell; break; - + case WRITE_CELL: m_opWriteCell = &AR_MATRIX::SetCell; break; + case WRITE_OR_CELL: m_opWriteCell = &AR_MATRIX::OrCell; break; case WRITE_XOR_CELL: m_opWriteCell = &AR_MATRIX::XorCell; break; - case WRITE_AND_CELL: m_opWriteCell = &AR_MATRIX::AndCell; break; - case WRITE_ADD_CELL: m_opWriteCell = &AR_MATRIX::AddCell; break; } } @@ -281,116 +268,6 @@ void AR_MATRIX::SetDist( int aRow, int aCol, int aSide, DIST_CELL x ) } -// fetch direction cell -int AR_MATRIX::GetDir( int aRow, int aCol, int aSide ) -{ - DIR_CELL* p; - - p = m_DirSide[aSide]; - return (int) ( p[aRow * m_Ncols + aCol] ); -} - - -// store direction cell -void AR_MATRIX::SetDir( int aRow, int aCol, int aSide, int x ) -{ - DIR_CELL* p; - - p = m_DirSide[aSide]; - p[aRow * m_Ncols + aCol] = (char) x; -} - -/* The tables of distances and keep out areas are established on the basis of a - * 50 units grid size (the pitch between the cells is 50 units). - * The actual distance could be computed by a scaling factor, but this is - * not needed, we can use only reduced values - */ - -/* calculate approximate distance (manhattan distance) - */ -int AR_MATRIX::GetApxDist( int r1, int c1, int r2, int c2 ) -{ - int d1, d2; /* row and column deltas */ - - if( ( d1 = r1 - r2 ) < 0 ) /* get absolute row delta */ - d1 = -d1; - - if( ( d2 = c1 - c2 ) < 0 ) /* get absolute column delta */ - d2 = -d2; - - return ( d1 + d2 ) * 50; -} - - -/* distance to go thru a cell (en mils) */ -static const int dist[10][10] = { /* OT=Otherside, OR=Origin (source) cell */ - /*..........N, NE, E, SE, S, SW, W, NW, OT, OR */ - /* N */ { 50, 60, 35, 60, 99, 60, 35, 60, 12, 12 }, - /* NE */ { 60, 71, 60, 71, 60, 99, 60, 71, 23, 23 }, - /* E */ { 35, 60, 50, 60, 35, 60, 99, 60, 12, 12 }, - /* SE */ { 60, 71, 60, 71, 60, 71, 60, 99, 23, 23 }, - /* S */ { 99, 60, 35, 60, 50, 60, 35, 60, 12, 12 }, - /* SW */ { 60, 99, 60, 71, 60, 71, 60, 71, 23, 23 }, - /* W */ { 35, 60, 99, 60, 35, 60, 50, 60, 12, 12 }, - /* NW */ { 60, 71, 60, 99, 60, 71, 60, 71, 23, 23 }, - - /* OT */ { 12, 23, 12, 23, 12, 23, 12, 23, 99, 99 }, - /* OR */ { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 } -}; - - -/* penalty for extraneous holes and corners, scaled by sharpness of turn */ -static const int penalty[10][10] = { /* OT=Otherside, OR=Origin (source) cell */ - /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */ - /* N */ { 0, 5, 10, 15, 20, 15, 10, 5, 50, 0 }, - /* NE */ { 5, 0, 5, 10, 15, 20, 15, 10, 50, 0 }, - /* E */ { 10, 5, 0, 5, 10, 15, 20, 15, 50, 0 }, - /* SE */ { 15, 10, 5, 0, 5, 10, 15, 20, 50, 0 }, - /* S */ { 20, 15, 10, 5, 0, 5, 10, 15, 50, 0 }, - /* SW */ { 15, 20, 15, 10, 5, 0, 5, 10, 50, 0 }, - /* W */ { 10, 15, 20, 15, 10, 5, 0, 5, 50, 0 }, - /* NW */ { 5, 10, 15, 20, 15, 10, 5, 0, 50, 0 }, - - /* OT */ { 50, 50, 50, 50, 50, 50, 50, 50, 100, 0 }, - /* OR */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -}; - - -/* penalty pour directions preferencielles */ -#define PN 20 -static const int dir_penalty_TOP[10][10] = { - /* OT=Otherside, OR=Origin (source) cell */ - /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */ - /* N */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* NE */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* E */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* SE */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* S */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* SW */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* W */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* NW */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - - /* OT */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, - /* OR */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 } -}; - - -static int dir_penalty_BOTTOM[10][10] = { - /* OT=Otherside, OR=Origin (source) cell */ - /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */ - /* N */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* NE */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* E */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* SE */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* S */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* SW */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* W */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* NW */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - - /* OT */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, - /* OR */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 } -}; - /* ** x is the direction to enter the cell of interest. ** y is the direction to exit the cell of interest. @@ -401,44 +278,6 @@ static int dir_penalty_BOTTOM[10][10] = { */ -/* calculate distance (with penalty) of a trace through a cell -*/ -int AR_MATRIX::CalcDist( int x, int y, int z, int side ) -{ - int adjust, ldist; - - adjust = 0; /* set if hole is encountered */ - - if( x == CELL_IS_EMPTY ) - x = 10; - - if( y == CELL_IS_EMPTY ) - { - y = 10; - } - else if( y == FROM_OTHERSIDE ) - { - if( z == CELL_IS_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 == AR_SIDE_BOTTOM ) - ldist += dir_penalty_TOP[x - 1][y - 1]; - - if( side == AR_SIDE_TOP ) - ldist += dir_penalty_BOTTOM[x - 1][y - 1]; - } - - return ldist * 10; -} - - #define OP_CELL( layer, dy, dx ) \ { \ if( layer == UNDEFINED_LAYER ) \ @@ -947,147 +786,6 @@ void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, LSET a } -/* Draws a line, if layer = -1 on all layers - */ -void AR_MATRIX::tracePcbLine( - int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic ) -{ - int dx, dy, lim; - int cumul, inc, il, delta; - - SetCellOperation( op_logic ); - - if( x0 == x1 ) // Vertical. - { - if( y1 < y0 ) - std::swap( y0, y1 ); - - dy = y0 / m_GridRouting; - lim = y1 / m_GridRouting; - dx = x0 / m_GridRouting; - - // Clipping limits of board. - if( ( dx < 0 ) || ( dx >= m_Ncols ) ) - return; - - if( dy < 0 ) - dy = 0; - - if( lim >= m_Nrows ) - lim = m_Nrows - 1; - - for( ; dy <= lim; dy++ ) - { - OP_CELL( layer, dy, dx ); - } - - return; - } - - if( y0 == y1 ) // Horizontal - { - if( x1 < x0 ) - std::swap( x0, x1 ); - - dx = x0 / m_GridRouting; - lim = x1 / m_GridRouting; - dy = y0 / m_GridRouting; - - // Clipping limits of board. - if( ( dy < 0 ) || ( dy >= m_Nrows ) ) - return; - - if( dx < 0 ) - dx = 0; - - if( lim >= m_Ncols ) - lim = 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 / m_GridRouting; - lim = x1 / m_GridRouting; - dy = y0 / m_GridRouting; - inc = 1; - - if( y1 < y0 ) - inc = -1; - - il = lim - dx; - cumul = il / 2; - delta = abs( y1 - y0 ) / m_GridRouting; - - for( ; dx <= lim; ) - { - if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < m_Ncols ) && ( dy < m_Nrows ) ) - { - OP_CELL( layer, dy, dx ); - } - - dx++; - cumul += delta; - - if( cumul > il ) - { - cumul -= il; - dy += inc; - } - } - } - else - { - if( y1 < y0 ) - { - std::swap( x1, x0 ); - std::swap( y1, y0 ); - } - - dy = y0 / m_GridRouting; - lim = y1 / m_GridRouting; - dx = x0 / m_GridRouting; - inc = 1; - - if( x1 < x0 ) - inc = -1; - - il = lim - dy; - cumul = il / 2; - delta = abs( x1 - x0 ) / m_GridRouting; - - for( ; dy <= lim; ) - { - if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < m_Ncols ) && ( dy < m_Nrows ) ) - { - OP_CELL( layer, dy, dx ); - } - - dy++; - cumul += delta; - - if( cumul > il ) - { - cumul -= il; - dx += inc; - } - } - } -} - void AR_MATRIX::TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic ) { @@ -1101,69 +799,24 @@ void AR_MATRIX::TraceSegmentPcb( //printf("traceSegm %d %d %d %d\n", ux0, uy0, ux1, uy1); - LAYER_NUM layer = pt_segm->GetLayer(); - - //if( color == VIA_IMPOSSIBLE ) - layer = UNDEFINED_LAYER; - + LAYER_NUM layer = UNDEFINED_LAYER; // Draw on all layers 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_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 AR_MATRIX::TraceSegmentPcb( TRACK* aTrack, int color, int marge, AR_MATRIX::CELL_OP 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( m_routeLayerBottom ) ) - layer_mask.set( m_routeLayerBottom ); - - if( aTrack->IsOnLayer( m_routeLayerTop ) ) - { - if( !layer_mask.any() ) - layer_mask = LSET( m_routeLayerTop ); - 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 - GetBrdCoordOrigin().x; - int uy0 = aTrack->GetStart().y - GetBrdCoordOrigin().y; - int ux1 = aTrack->GetEnd().x - GetBrdCoordOrigin().x; - int uy1 = aTrack->GetEnd().y - GetBrdCoordOrigin().y; - - // Ordinary track - PCB_LAYER_ID layer = aTrack->GetLayer(); - - if( color == VIA_IMPOSSIBLE ) - layer = UNDEFINED_LAYER; - + case S_SEGMENT: drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic ); + break; + + default: + break; } } diff --git a/pcbnew/autorouter/ar_matrix.h b/pcbnew/autorouter/ar_matrix.h index db01f37ae5..01833171b7 100644 --- a/pcbnew/autorouter/ar_matrix.h +++ b/pcbnew/autorouter/ar_matrix.h @@ -58,7 +58,6 @@ public: // distance to cells DIR_CELL* m_DirSide[AR_MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides: // pointers back to source - bool m_InitMatrixDone; int m_RoutingLayersCount; // Number of layers for autorouting (0 or 1) int m_GridRouting; // Size of grid for autoplace/autoroute EDA_RECT m_BrdBox; // Actual board bounding box @@ -133,18 +132,8 @@ public: void AddCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell ); DIST_CELL GetDist( int aRow, int aCol, int aSide ); void SetDist( int aRow, int aCol, int aSide, DIST_CELL ); - int GetDir( int aRow, int aCol, int aSide ); - void SetDir( int aRow, int aCol, int aSide, int aDir ); - - // calculate distance (with penalty) of a trace through a cell - int CalcDist( int x, int y, int z, int side ); - - // calculate approximate distance (manhattan distance) - int GetApxDist( int r1, int c1, int r2, int c2 ); - void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic ); - void TraceSegmentPcb( TRACK* aTrack, int color, int marge, AR_MATRIX::CELL_OP op_logic ); void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, LSET aLayerMask ); void PlacePad( D_PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic ); @@ -154,7 +143,6 @@ public: AR_MATRIX::CELL_OP op_logic ); private: - void drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color, CELL_OP op_logic ); @@ -164,8 +152,6 @@ private: int cx, int cy, int radius, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic ); void traceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic ); - void tracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, - AR_MATRIX::CELL_OP op_logic ); }; #endif diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index dccdaebc42..ac878f0b4f 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -368,6 +368,18 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, width ); break; + case S_RECT: + { + std::vector pts; + GetRectCorners( &pts ); + + aCornerBuffer.NewOutline(); + + for( const wxPoint& pt : pts ) + aCornerBuffer.Append( pt ); + } + break; + case S_ARC: TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, width ); break; diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 857fc09bae..d7e8d3a4cc 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -25,7 +25,6 @@ */ #include -#include #include #include #include @@ -87,9 +86,14 @@ double DRAWSEGMENT::GetLength() const break; - default: + case S_SEGMENT: length = GetLineLength( GetStart(), GetEnd() ); break; + + default: + wxASSERT_MSG( false, "DRAWSEGMENT::GetLength not implemented for shape" + + ShowShape( GetShape() ) ); + break; } return length; @@ -116,10 +120,8 @@ void DRAWSEGMENT::Move( const wxPoint& aMoveVector ) m_BezierC1 += aMoveVector; m_BezierC2 += aMoveVector; - for( unsigned int ii = 0; ii < m_BezierPoints.size(); ii++ ) - { - m_BezierPoints[ii] += aMoveVector; - } + for( wxPoint& pt : m_BezierPoints) + pt += aMoveVector; break; @@ -136,6 +138,7 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle ) case S_ARC: case S_SEGMENT: case S_CIRCLE: + case S_RECT: // these can all be done by just rotating the start and end points RotatePoint( &m_Start, aRotCentre, aAngle); RotatePoint( &m_End, aRotCentre, aAngle); @@ -151,13 +154,11 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle ) RotatePoint( &m_BezierC1, aRotCentre, aAngle); RotatePoint( &m_BezierC2, aRotCentre, aAngle); - for( unsigned int ii = 0; ii < m_BezierPoints.size(); ii++ ) - { - RotatePoint( &m_BezierPoints[ii], aRotCentre, aAngle); - } + for( wxPoint& pt : m_BezierPoints ) + RotatePoint( &pt, aRotCentre, aAngle); + break; - case S_RECT: default: // un-handled edge transform wxASSERT_MSG( false, wxT( "DRAWSEGMENT::Rotate not implemented for " @@ -385,7 +386,17 @@ void DRAWSEGMENT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector pts; + GetRectCorners( &pts ); + + bbox = EDA_RECT(); // re-init for merging + + for( wxPoint& pt : pts ) + bbox.Merge( pt ); + } + break; + case S_SEGMENT: bbox.SetEnd( m_End ); break; @@ -452,9 +480,8 @@ const EDA_RECT DRAWSEGMENT::GetBoundingBox() const if( m_Poly.IsEmpty() ) break; { - wxPoint p_end; MODULE* module = GetParentModule(); - bool first = true; + bbox = EDA_RECT(); // re-init for merging for( auto iter = m_Poly.CIterate(); iter; iter++ ) { @@ -466,31 +493,12 @@ const EDA_RECT DRAWSEGMENT::GetBoundingBox() const pt += module->GetPosition(); } - - if( first ) - { - p_end = pt; - bbox.SetX( pt.x ); - bbox.SetY( pt.y ); - first = false; - } - else - { - - bbox.SetX( std::min( bbox.GetX(), pt.x ) ); - bbox.SetY( std::min( bbox.GetY(), pt.y ) ); - - p_end.x = std::max( p_end.x, pt.x ); - p_end.y = std::max( p_end.y, pt.y ); - } + bbox.Merge( pt ); } - - bbox.SetEnd( p_end ); + } break; - } case S_CURVE: - bbox.Merge( m_BezierC1 ); bbox.Merge( m_BezierC2 ); bbox.Merge( m_End ); @@ -572,6 +580,21 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const return true; break; + case S_RECT: + { + std::vector pts; + GetRectCorners( &pts ); + + if( TestSegmentHit( aPosition, pts[0], pts[1], maxdist ) + || TestSegmentHit( aPosition, pts[1], pts[2], maxdist ) + || TestSegmentHit( aPosition, pts[2], pts[3], maxdist ) + || TestSegmentHit( aPosition, pts[3], pts[0], maxdist ) ) + { + return true; + } + } + break; + case S_POLYGON: { if( !IsPolygonFilled() ) @@ -644,6 +667,26 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy } break; + case S_RECT: + if( aContained ) + { + return arect.Contains( bb ); + } + else + { + std::vector pts; + GetRectCorners( &pts ); + + // Account for the width of the lines + arect.Inflate( GetWidth() / 2 ); + return ( arect.Intersects( pts[0], pts[1] ) + || arect.Intersects( pts[1], pts[2] ) + || arect.Intersects( pts[2], pts[3] ) + || arect.Intersects( pts[3], pts[0] ) ); + } + + break; + case S_SEGMENT: if( aContained ) { @@ -734,9 +777,8 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy wxString DRAWSEGMENT::GetSelectMenuText( EDA_UNITS aUnits ) const { - return wxString::Format( _( "Pcb Graphic %s, length %s on %s" ), + return wxString::Format( _( "Pcb Graphic %s on %s" ), ShowShape( m_Shape ), - MessageTextFromValue( aUnits, GetLength() ), GetLayerName() ); } @@ -769,6 +811,40 @@ const BOX2I DRAWSEGMENT::ViewBBox() const } +void DRAWSEGMENT::GetRectCorners( std::vector* pts ) const +{ + MODULE* module = GetParentModule(); + wxPoint topLeft = GetStart(); + wxPoint botRight = GetEnd(); + + // Un-rotate rect topLeft and botRight + if( module && KiROUND( module->GetOrientation() ) % 900 != 0 ) + { + topLeft -= module->GetPosition(); + RotatePoint( &topLeft, -module->GetOrientation() ); + + botRight -= module->GetPosition(); + RotatePoint( &botRight, -module->GetOrientation() ); + } + + // Set up the un-rotated 4 corners + pts->emplace_back( topLeft ); + pts->emplace_back( botRight.x, topLeft.y ); + pts->emplace_back( botRight ); + pts->emplace_back( topLeft.x, botRight.y ); + + // Now re-rotate the 4 corners to get a diamond + if( module && KiROUND( module->GetOrientation() ) % 900 != 0 ) + { + for( wxPoint& pt : *pts ) + { + RotatePoint( &pt,module->GetOrientation() ); + pt += module->GetPosition(); + } + } +} + + void DRAWSEGMENT::computeArcBBox( EDA_RECT& aBBox ) const { // Do not include the center, which is not necessarily @@ -816,21 +892,10 @@ void DRAWSEGMENT::computeArcBBox( EDA_RECT& aBBox ) const { switch( quarter ) { - case 0: - aBBox.Merge( wxPoint( m_Start.x, m_Start.y + radius ) ); // down - break; - - case 1: - aBBox.Merge( wxPoint( m_Start.x - radius, m_Start.y ) ); // left - break; - - case 2: - aBBox.Merge( wxPoint( m_Start.x, m_Start.y - radius ) ); // up - break; - - case 3: - aBBox.Merge( wxPoint( m_Start.x + radius, m_Start.y ) ); // right - break; + case 0: aBBox.Merge( wxPoint( m_Start.x, m_Start.y + radius ) ); break; // down + case 1: aBBox.Merge( wxPoint( m_Start.x - radius, m_Start.y ) ); break; // left + case 2: aBBox.Merge( wxPoint( m_Start.x, m_Start.y - radius ) ); break; // up + case 3: aBBox.Merge( wxPoint( m_Start.x + radius, m_Start.y ) ); break; // right } if( directionCW ) @@ -849,10 +914,8 @@ void DRAWSEGMENT::SetPolyPoints( const std::vector& aPoints ) m_Poly.RemoveAllContours(); m_Poly.NewOutline(); - for ( auto p : aPoints ) - { + for ( const wxPoint& p : aPoints ) m_Poly.Append( p.x, p.y ); - } } @@ -865,9 +928,7 @@ const std::vector DRAWSEGMENT::BuildPolyPointsList() const if( m_Poly.COutline( 0 ).PointCount() ) { for ( auto iter = m_Poly.CIterate(); iter; iter++ ) - { rv.emplace_back( iter->x, iter->y ); - } } } diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index 791996ab64..314c0b1e66 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -150,6 +150,7 @@ public: const wxPoint& GetArcStart() const { return m_End; } const wxPoint GetArcEnd() const; const wxPoint GetArcMid() const; + void GetRectCorners( std::vector* pts ) const; /** * function GetArcAngleStart() @@ -181,6 +182,11 @@ public: */ void SetCenter( const wxPoint& aCenterPoint ) { m_Start = aCenterPoint; } + const wxPoint GetFocusPosition() const override + { + return GetCenter(); + } + /** * Function GetParentModule * returns a pointer to the parent module, or NULL if DRAWSEGMENT does not diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index 1d7025b535..300bba6943 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -30,14 +30,10 @@ */ #include -#include #include #include -#include #include -#include #include -#include #include #include #include @@ -46,15 +42,12 @@ #include #include #include - #include #include #include #include - #include -#include EDGE_MODULE::EDGE_MODULE( MODULE* parent, STROKE_T aShape ) : DRAWSEGMENT( parent, PCB_MODULE_EDGE_T ) diff --git a/pcbnew/convert_drawsegment_list_to_polygon.cpp b/pcbnew/convert_drawsegment_list_to_polygon.cpp index 5805b73221..55baad4bf1 100644 --- a/pcbnew/convert_drawsegment_list_to_polygon.cpp +++ b/pcbnew/convert_drawsegment_list_to_polygon.cpp @@ -207,6 +207,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE switch( graphic->GetShape() ) { + case S_RECT: case S_SEGMENT: { if( graphic->GetStart().x < xmin.x ) @@ -326,6 +327,16 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE { TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), aTolerance ); } + else if( graphic->GetShape() == S_RECT ) + { + std::vector pts; + graphic->GetRectCorners( &pts ); + + aPolygons.NewOutline(); + + for( const wxPoint& pt : pts ) + aPolygons.Append( pt ); + } else if( graphic->GetShape() == S_POLYGON ) { MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints @@ -542,6 +553,14 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE aPolygons.Append( nextPt, -1, hole ); } } + else if( graphic->GetShape() == S_RECT ) + { + std::vector pts; + graphic->GetRectCorners( &pts ); + + for( const wxPoint& pt : pts ) + aPolygons.Append( pt, -1, hole ); + } else { // Polygon start point. Arbitrarily chosen end of the diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index 536cc591e4..1a3d5e1b09 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -180,6 +180,10 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataToWindow() m_sizerLeft->Show( false ); break; + case S_RECT: + SetTitle( _( "Rectangle Properties" ) ); + break; + case S_SEGMENT: if( m_item->GetStart().x == m_item->GetEnd().x ) m_flipStartEnd = m_item->GetStart().y > m_item->GetEnd().y; diff --git a/pcbnew/drc/drc.cpp b/pcbnew/drc/drc.cpp index 055aaac81d..874ef0c80a 100644 --- a/pcbnew/drc/drc.cpp +++ b/pcbnew/drc/drc.cpp @@ -941,6 +941,18 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem ) itemShape.emplace_back( SEG( drawItem->GetStart(), drawItem->GetEnd() ) ); break; + case S_RECT: + { + std::vector pts; + drawItem->GetRectCorners( &pts ); + + itemShape.emplace_back( SEG( pts[0], pts[1] ) ); + itemShape.emplace_back( SEG( pts[1], pts[2] ) ); + itemShape.emplace_back( SEG( pts[2], pts[3] ) ); + itemShape.emplace_back( SEG( pts[3], pts[0] ) ); + } + break; + case S_CIRCLE: { // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index d40733c45f..65683cda47 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -1259,6 +1259,31 @@ static void FootprintWriteShape( FILE* aFile, MODULE* module, const wxString& aS -PtEdge->m_End0.y / SCALE_FACTOR ); break; + case S_RECT: + { + fprintf( aFile, "LINE %g %g %g %g\n", + PtEdge->m_Start0.x / SCALE_FACTOR, + -PtEdge->m_Start0.y / SCALE_FACTOR, + PtEdge->m_End0.x / SCALE_FACTOR, + -PtEdge->m_Start0.y / SCALE_FACTOR ); + fprintf( aFile, "LINE %g %g %g %g\n", + PtEdge->m_End0.x / SCALE_FACTOR, + -PtEdge->m_Start0.y / SCALE_FACTOR, + PtEdge->m_End0.x / SCALE_FACTOR, + -PtEdge->m_End0.y / SCALE_FACTOR ); + fprintf( aFile, "LINE %g %g %g %g\n", + PtEdge->m_End0.x / SCALE_FACTOR, + -PtEdge->m_End0.y / SCALE_FACTOR, + PtEdge->m_Start0.x / SCALE_FACTOR, + -PtEdge->m_End0.y / SCALE_FACTOR ); + fprintf( aFile, "LINE %g %g %g %g\n", + PtEdge->m_Start0.x / SCALE_FACTOR, + -PtEdge->m_End0.y / SCALE_FACTOR, + PtEdge->m_Start0.x / SCALE_FACTOR, + -PtEdge->m_Start0.y / SCALE_FACTOR ); + } + break; + case S_CIRCLE: { int radius = KiROUND( GetLineLength( PtEdge->m_End0, diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp index eb746fd761..601e36460c 100644 --- a/pcbnew/exporters/export_idf.cpp +++ b/pcbnew/exporters/export_idf.cpp @@ -102,6 +102,30 @@ static void idf_export_outline( BOARD* aPcb, IDF3_BOARD& aIDFBoard ) } break; + case S_RECT: + { + if( ( graphic->GetStart().x == graphic->GetEnd().x ) + && ( graphic->GetStart().y == graphic->GetEnd().y ) ) + break; + + double top = graphic->GetStart().y * scale + offY; + double left = graphic->GetStart().x * scale + offX; + double bottom = graphic->GetEnd().y * scale + offY; + double right = graphic->GetEnd().x * scale + offX; + + IDF_POINT corners[4]; + corners[0] = IDF_POINT( left, top ); + corners[1] = IDF_POINT( right, top ); + corners[2] = IDF_POINT( right, bottom ); + corners[3] = IDF_POINT( left, bottom ); + + lines.push_back( new IDF_SEGMENT( corners[0], corners[1] ) ); + lines.push_back( new IDF_SEGMENT( corners[1], corners[2] ) ); + lines.push_back( new IDF_SEGMENT( corners[2], corners[3] ) ); + lines.push_back( new IDF_SEGMENT( corners[3], corners[0] ) ); + } + break; + case S_ARC: { if( ( graphic->GetCenter().x == graphic->GetArcStart().x ) diff --git a/pcbnew/exporters/export_vrml.cpp b/pcbnew/exporters/export_vrml.cpp index be38b8356c..cd038461fb 100644 --- a/pcbnew/exporters/export_vrml.cpp +++ b/pcbnew/exporters/export_vrml.cpp @@ -750,9 +750,19 @@ static void export_vrml_drawsegment( MODEL_VRML& aModel, DRAWSEGMENT* drawseg ) export_vrml_polygon( aModel, layer, drawseg, 0.0, wxPoint( 0, 0 ) ); break; - default: + case S_SEGMENT: export_vrml_line( aModel, layer, x, y, xf, yf, w ); break; + + case S_RECT: + export_vrml_line( aModel, layer, x, y, xf, y, w ); + export_vrml_line( aModel, layer, xf, y, xf, yf, w ); + export_vrml_line( aModel, layer, xf, yf, x, yf, w ); + export_vrml_line( aModel, layer, x, yf, x, y, w ); + break; + + default: + break; } } diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 078a5fee43..7506d706de 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -23,7 +23,6 @@ */ #include -#include #include #include // LEGACY_BOARD_FILE_VERSION #include @@ -39,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -888,6 +886,12 @@ void PCB_IO::format( DRAWSEGMENT* aSegment, int aNestLevel ) const break; + case S_RECT: // Rectangle + m_out->Print( aNestLevel, "(gr_rect (start %s) (end %s)", + FormatInternalUnits( aSegment->GetStart() ).c_str(), + FormatInternalUnits( aSegment->GetEnd() ).c_str() ); + break; + case S_CIRCLE: // Circle m_out->Print( aNestLevel, "(gr_circle (center %s) (end %s)", FormatInternalUnits( aSegment->GetStart() ).c_str(), @@ -961,6 +965,12 @@ void PCB_IO::format( EDGE_MODULE* aModuleDrawing, int aNestLevel ) const FormatInternalUnits( aModuleDrawing->GetEnd0() ).c_str() ); break; + case S_RECT: // Rectangle + m_out->Print( aNestLevel, "(fp_rect (start %s) (end %s)", + FormatInternalUnits( aModuleDrawing->GetStart0() ).c_str(), + FormatInternalUnits( aModuleDrawing->GetEnd0() ).c_str() ); + break; + case S_CIRCLE: // Circle m_out->Print( aNestLevel, "(fp_circle (center %s) (end %s)", FormatInternalUnits( aModuleDrawing->GetStart0() ).c_str(), diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index 5c65a3d560..386150fd71 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -68,7 +68,8 @@ class TEXTE_PCB; //#define SEXPR_BOARD_FILE_VERSION 20200104 // pad property for fabrication //#define SEXPR_BOARD_FILE_VERSION 20200119 // arcs in tracks //#define SEXPR_BOARD_FILE_VERSION 20200512 // page -> paper -#define SEXPR_BOARD_FILE_VERSION 20200518 // save hole_to_hole_min +//#define SEXPR_BOARD_FILE_VERSION 20200518 // save hole_to_hole_min +#define SEXPR_BOARD_FILE_VERSION 20200614 // Add support for fp_rects and gr_rects #define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names #define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library) diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 1133c486d6..13cf943bf6 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -915,8 +915,15 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer ) break; case S_RECT: - wxASSERT_MSG( false, "Not tested yet" ); - m_gal->DrawRectangle( start, end ); + { + std::vector pts; + aSegment->GetRectCorners( &pts ); + + m_gal->DrawSegment( pts[0], pts[1], thickness ); + m_gal->DrawSegment( pts[1], pts[2], thickness ); + m_gal->DrawSegment( pts[2], pts[3], thickness ); + m_gal->DrawSegment( pts[3], pts[0], thickness ); + } break; case S_ARC: diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index eed8cc718d..6b12c149f3 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -582,6 +582,7 @@ BOARD* PCB_PARSER::parseBOARD_unchecked() case T_gr_arc: case T_gr_circle: case T_gr_curve: + case T_gr_rect: case T_gr_line: case T_gr_poly: m_board->Add( parseDRAWSEGMENT(), ADD_MODE::APPEND ); @@ -1942,7 +1943,7 @@ void PCB_PARSER::parseNETCLASS() DRAWSEGMENT* PCB_PARSER::parseDRAWSEGMENT( bool aAllowCirclesZeroWidth ) { wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve || - CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL, + CurTok() == T_gr_rect || CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL, wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) ); T token; @@ -2017,6 +2018,30 @@ DRAWSEGMENT* PCB_PARSER::parseDRAWSEGMENT( bool aAllowCirclesZeroWidth ) NeedRIGHT(); break; + case T_gr_rect: + segment->SetShape( S_RECT ); + NeedLEFT(); + token = NextTok(); + + if( token != T_start ) + Expecting( T_start ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart( pt ); + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd( pt ); + NeedRIGHT(); + break; + case T_gr_line: // Default DRAWSEGMENT type is S_SEGMENT. NeedLEFT(); @@ -2061,7 +2086,7 @@ DRAWSEGMENT* PCB_PARSER::parseDRAWSEGMENT( bool aAllowCirclesZeroWidth ) break; default: - Expecting( "gr_arc, gr_circle, gr_curve, gr_line, or gr_poly" ); + Expecting( "gr_arc, gr_circle, gr_curve, gr_line, gr_poly, or gp_rect" ); } for( token = NextTok(); token != T_RIGHT; token = NextTok() ) @@ -2107,7 +2132,9 @@ DRAWSEGMENT* PCB_PARSER::parseDRAWSEGMENT( bool aAllowCirclesZeroWidth ) // However in custom pad shapes, zero-line width is allowed for filled circles if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 && !( segment->GetShape() == S_CIRCLE && aAllowCirclesZeroWidth ) ) + { segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) ); + } return segment.release(); } @@ -2588,6 +2615,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments ) case T_fp_circle: case T_fp_curve: + case T_fp_rect: case T_fp_line: case T_fp_poly: { @@ -2628,7 +2656,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments ) "autoplace_cost90, autoplace_cost180, solder_mask_margin, " "solder_paste_margin, solder_paste_ratio, clearance, " "zone_connect, thermal_width, thermal_gap, attr, fp_text, " - "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, " + "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, " "zone, or model" ); } } @@ -2738,7 +2766,7 @@ TEXTE_MODULE* PCB_PARSER::parseTEXTE_MODULE() EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE() { wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || - CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL, + CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL, wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) ); wxPoint pt; @@ -2821,6 +2849,31 @@ EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE() NeedRIGHT(); break; + case T_fp_rect: + segment->SetShape( S_RECT ); + NeedLEFT(); + token = NextTok(); + + if( token != T_start ) + Expecting( T_start ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart0( pt ); + + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd0( pt ); + NeedRIGHT(); + break; + case T_fp_line: // Default DRAWSEGMENT type is S_SEGMENT. NeedLEFT(); @@ -2865,7 +2918,7 @@ EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE() break; default: - Expecting( "fp_arc, fp_circle, fp_curve, fp_line, or fp_poly" ); + Expecting( "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, or fp_rect" ); } for( token = NextTok(); token != T_RIGHT; token = NextTok() ) diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 95ef0b11bc..20451ca4a7 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -529,6 +529,18 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( EDGE_MODULE* aEdge ) m_plotter->ThickSegment( pos, end, thickness, GetPlotMode(), &gbr_metadata ); break; + case S_RECT: + { + std::vector pts; + aEdge->GetRectCorners( &pts ); + + m_plotter->ThickSegment( pts[0], pts[1], thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( pts[1], pts[2], thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( pts[2], pts[3], thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( pts[3], pts[0], thickness, GetPlotMode(), &gbr_metadata ); + } + break; + case S_CIRCLE: radius = KiROUND( GetLineLength( end, pos ) ); m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 412f3b28cb..76c10df02f 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -985,6 +985,18 @@ bool PNS_KICAD_IFACE_BASE::syncGraphicalItem( PNS::NODE* aWorld, DRAWSEGMENT* aI break; + case S_RECT: + { + std::vector pts; + aItem->GetRectCorners( &pts ); + + segs.push_back( new SHAPE_SEGMENT( pts[0], pts[1], aItem->GetWidth() ) ); + segs.push_back( new SHAPE_SEGMENT( pts[1], pts[2], aItem->GetWidth() ) ); + segs.push_back( new SHAPE_SEGMENT( pts[2], pts[3], aItem->GetWidth() ) ); + segs.push_back( new SHAPE_SEGMENT( pts[3], pts[0], aItem->GetWidth() ) ); + } + break; + case S_CIRCLE: { // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC diff --git a/pcbnew/toolbars_footprint_editor.cpp b/pcbnew/toolbars_footprint_editor.cpp index c274cca0df..9ff7d11ca7 100644 --- a/pcbnew/toolbars_footprint_editor.cpp +++ b/pcbnew/toolbars_footprint_editor.cpp @@ -145,22 +145,23 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar() m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); - m_drawToolBar->Add( ACTIONS::selectionTool, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( ACTIONS::selectionTool, ACTION_TOOLBAR::TOGGLE ); KiScaledSeparator( m_drawToolBar, this ); - m_drawToolBar->Add( PCB_ACTIONS::placePad, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawLine, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawPolygon, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::placePad, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawLine, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawRectangle, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawPolygon, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( PCB_ACTIONS::drawZoneKeepout, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); KiScaledSeparator( m_drawToolBar, this ); - m_drawToolBar->Add( PCB_ACTIONS::setAnchor, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::gridSetOrigin, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::setAnchor, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::gridSetOrigin, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Realize(); } @@ -237,8 +238,8 @@ void FOOTPRINT_EDIT_FRAME::SyncToolbars() m_mainToolBar->Refresh(); m_optionsToolBar->Toggle( ACTIONS::toggleGrid, IsGridVisible() ); - m_optionsToolBar->Toggle( ACTIONS::metricUnits, GetUserUnits() != EDA_UNITS::INCHES ); - m_optionsToolBar->Toggle( ACTIONS::imperialUnits, GetUserUnits() == EDA_UNITS::INCHES ); + m_optionsToolBar->Toggle( ACTIONS::metricUnits, GetUserUnits() != EDA_UNITS::INCHES ); + m_optionsToolBar->Toggle( ACTIONS::imperialUnits, GetUserUnits() == EDA_UNITS::INCHES ); m_optionsToolBar->Toggle( ACTIONS::togglePolarCoords, GetShowPolarCoords() ); m_optionsToolBar->Toggle( PCB_ACTIONS::padDisplayMode, !opts.m_DisplayPadFill ); m_optionsToolBar->Toggle( PCB_ACTIONS::textOutlines, !opts.m_DisplayTextFill ); @@ -252,6 +253,7 @@ void FOOTPRINT_EDIT_FRAME::SyncToolbars() // If there is no footprint loaded, disable the editing tools m_drawToolBar->Toggle( PCB_ACTIONS::placePad, false, false ); m_drawToolBar->Toggle( PCB_ACTIONS::drawLine, false, false ); + m_drawToolBar->Toggle( PCB_ACTIONS::drawRectangle, false, false ); m_drawToolBar->Toggle( PCB_ACTIONS::drawCircle, false, false ); m_drawToolBar->Toggle( PCB_ACTIONS::drawArc, false, false ); m_drawToolBar->Toggle( PCB_ACTIONS::drawPolygon, false, false ); @@ -266,6 +268,7 @@ void FOOTPRINT_EDIT_FRAME::SyncToolbars() { TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::placePad ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawLine ); + TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawRectangle ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawCircle ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawArc ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawPolygon ); diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 485b346bb7..23c851234a 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -183,6 +183,48 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent ) } +int DRAWING_TOOL::DrawRectangle( const TOOL_EVENT& aEvent ) +{ + if( m_editModules && !m_frame->GetModel() ) + return 0; + + MODULE* module = dynamic_cast( m_frame->GetModel() ); + DRAWSEGMENT* rect = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT; + BOARD_COMMIT commit( m_frame ); + SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::RECT ); + OPT startingPoint = boost::make_optional( false, VECTOR2D( 0, 0 ) ); + + rect->SetFlags(IS_NEW ); + + if( aEvent.HasPosition() ) + startingPoint = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) ); + + std::string tool = aEvent.GetCommandStr().get(); + m_frame->PushTool( tool ); + Activate(); + + while( drawSegment( tool, S_RECT, rect, startingPoint ) ) + { + if( rect ) + { + if( m_editModules ) + static_cast( rect )->SetLocalCoord(); + + commit.Add( rect ); + commit.Push( _( "Draw a rectangle" ) ); + + m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, rect ); + } + + rect = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT; + rect->SetFlags(IS_NEW ); + startingPoint = NULLOPT; + } + + return 0; +} + + int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent ) { if( m_editModules && !m_frame->GetModel() ) @@ -918,8 +960,8 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent ) bool DRAWING_TOOL::drawSegment( const std::string& aTool, int aShape, DRAWSEGMENT*& aGraphic, OPT aStartingPoint ) { - // Only two shapes are currently supported - assert( aShape == S_SEGMENT || aShape == S_CIRCLE ); + // Only three shapes are currently supported + assert( aShape == S_SEGMENT || aShape == S_CIRCLE || aShape == S_RECT ); GRID_HELPER grid( m_toolMgr, m_frame->GetMagneticItemsSettings() ); POINT_EDITOR* pointEditor = m_toolMgr->GetTool(); @@ -1938,6 +1980,7 @@ void DRAWING_TOOL::setTransitions() { Go( &DRAWING_TOOL::DrawLine, PCB_ACTIONS::drawLine.MakeEvent() ); Go( &DRAWING_TOOL::DrawZone, PCB_ACTIONS::drawPolygon.MakeEvent() ); + Go( &DRAWING_TOOL::DrawRectangle, PCB_ACTIONS::drawRectangle.MakeEvent() ); Go( &DRAWING_TOOL::DrawCircle, PCB_ACTIONS::drawCircle.MakeEvent() ); Go( &DRAWING_TOOL::DrawArc, PCB_ACTIONS::drawArc.MakeEvent() ); Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawDimension.MakeEvent() ); diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index c22267b3fa..6d422dbbc7 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -63,6 +63,7 @@ public: { NONE, LINE, + RECT, CIRCLE, ARC, TEXT, @@ -91,6 +92,14 @@ public: */ int DrawLine( const TOOL_EVENT& aEvent ); + /** + * Function DrawRectangle() + * Starts interactively drawing a rectangle. After invoking the function it expects the user + * to first click on a point that is going to be used as the top-left of the rectangle. The + * second click determines the bottom-right. + */ + int DrawRectangle( const TOOL_EVENT& aEvent ); + /** * Function DrawCircle() * Starts interactively drawing a circle. After invoking the function it expects the user diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index af32549068..013759798c 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -66,6 +66,11 @@ TOOL_ACTION PCB_ACTIONS::drawPolygon( "pcbnew.InteractiveDrawing.graphicPolygon" _( "Draw Graphic Polygon" ), _( "Draw a graphic polygon" ), add_graphical_polygon_xpm, AF_ACTIVATE, (void*) ZONE_MODE::GRAPHIC_POLYGON ); +TOOL_ACTION PCB_ACTIONS::drawRectangle( "pcbnew.InteractiveDrawing.rectangle", + AS_GLOBAL, 0, "", + _( "Draw Rectangle" ), _( "Draw a rectangle" ), + add_rectangle_xpm, AF_ACTIVATE ); + TOOL_ACTION PCB_ACTIONS::drawCircle( "pcbnew.InteractiveDrawing.circle", AS_GLOBAL, MD_SHIFT + MD_CTRL + 'C', LEGACY_HK_NAME( "Draw Circle" ), diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index 226ee7ca8c..adccf68cac 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -136,6 +136,7 @@ public: // Drawing Tool Activations static TOOL_ACTION drawLine; static TOOL_ACTION drawPolygon; + static TOOL_ACTION drawRectangle; static TOOL_ACTION drawCircle; static TOOL_ACTION drawArc; static TOOL_ACTION placeText; diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index 37e3f757d7..41635e64e5 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -50,6 +50,11 @@ enum SEG_POINTS SEG_START, SEG_END }; +enum RECT_POINTS +{ + RECT_TOP_LEFT, RECT_TOP_RIGHT, RECT_BOT_RIGHT, RECT_BOT_LEFT +}; + enum ARC_POINTS { ARC_CENTER, ARC_START, ARC_MID, ARC_END @@ -144,6 +149,13 @@ public: points->AddPoint( segment->GetEnd() ); break; + case S_RECT: + points->AddPoint( segment->GetStart() ); + points->AddPoint( wxPoint( segment->GetEnd().x, segment->GetStart().y ) ); + points->AddPoint( segment->GetEnd() ); + points->AddPoint( wxPoint( segment->GetStart().x, segment->GetEnd().y ) ); + break; + case S_ARC: points->AddPoint( segment->GetCenter() ); points->AddPoint( segment->GetArcStart() ); @@ -163,7 +175,6 @@ public: case S_CIRCLE: points->AddPoint( segment->GetCenter() ); points->AddPoint( segment->GetEnd() ); - break; case S_POLYGON: @@ -441,6 +452,29 @@ void POINT_EDITOR::updateItem() const break; + case S_RECT: + { + if( isModified( m_editPoints->Point( RECT_TOP_LEFT ) ) ) + { + segment->SetStart( (wxPoint) m_editPoints->Point( RECT_TOP_LEFT ).GetPosition() ); + } + else if( isModified( m_editPoints->Point( RECT_TOP_RIGHT ) ) ) + { + segment->SetStartY( m_editPoints->Point( RECT_TOP_RIGHT ).GetPosition().y ); + segment->SetEndX( m_editPoints->Point( RECT_TOP_RIGHT ).GetPosition().x ); + } + else if( isModified( m_editPoints->Point( RECT_BOT_RIGHT ) ) ) + { + segment->SetEnd( (wxPoint) m_editPoints->Point( RECT_BOT_RIGHT ).GetPosition() ); + } + else if( isModified( m_editPoints->Point( RECT_BOT_LEFT ) ) ) + { + segment->SetStartX( m_editPoints->Point( RECT_BOT_LEFT ).GetPosition().x ); + segment->SetEndY( m_editPoints->Point( RECT_BOT_LEFT ).GetPosition().y ); + } + } + break; + case S_ARC: { VECTOR2I center = m_editPoints->Point( ARC_CENTER ).GetPosition(); @@ -482,9 +516,8 @@ void POINT_EDITOR::updateItem() const segment->SetAngle( newAngle ); } - - break; } + break; case S_CIRCLE: { @@ -500,9 +533,8 @@ void POINT_EDITOR::updateItem() const { segment->SetEnd( wxPoint( end.x, end.y ) ); } - - break; } + break; case S_POLYGON: { @@ -512,8 +544,8 @@ void POINT_EDITOR::updateItem() const outline.SetVertex( i, m_editPoints->Point( i ).GetPosition() ); validatePolygon( outline ); - break; } + break; case S_CURVE: if( isModified( m_editPoints->Point( BEZIER_CURVE_START ) ) ) @@ -685,6 +717,15 @@ void POINT_EDITOR::updatePoints() m_editPoints->Point( SEG_END ).SetPosition( segment->GetEnd() ); break; + case S_RECT: + m_editPoints->Point( RECT_TOP_LEFT ).SetPosition( segment->GetStart() ); + m_editPoints->Point( RECT_TOP_RIGHT ).SetPosition( segment->GetEnd().x, + segment->GetStart().y ); + m_editPoints->Point( RECT_BOT_RIGHT ).SetPosition( segment->GetEnd() ); + m_editPoints->Point( RECT_BOT_LEFT ).SetPosition( segment->GetStart().x, + segment->GetEnd().y ); + break; + case S_ARC: m_editPoints->Point( ARC_CENTER ).SetPosition( segment->GetCenter() ); m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() ); diff --git a/utils/idftools/idf_common.h b/utils/idftools/idf_common.h index 632ce2af3a..ae48ec2cdf 100644 --- a/utils/idftools/idf_common.h +++ b/utils/idftools/idf_common.h @@ -480,6 +480,12 @@ public: y = 0.0; } + IDF_POINT( double aX, double aY ) + { + x = aX; + y = aY; + } + /** * Function Matches() * returns true if the given coordinate point is within the given radius