diff --git a/common/common_plotDXF_functions.cpp b/common/common_plotDXF_functions.cpp index b6827078de..4da335b052 100644 --- a/common/common_plotDXF_functions.cpp +++ b/common/common_plotDXF_functions.cpp @@ -5,7 +5,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2016 KiCad Developers, see CHANGELOG.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 @@ -617,6 +617,43 @@ void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, FinishTo( wxPoint( ox, oy ) ); } +void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ) +{ + SHAPE_POLY_SET outline; + const int segmentToCircleCount = 64; + TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, + aCornerRadius, segmentToCircleCount ); + + // TransformRoundRectToPolygon creates only one convex polygon + SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); + + MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) ); + + for( int ii = 1; ii < poly.PointCount(); ++ii ) + LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + FinishTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) ); +} + +void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ) +{ + for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt ) + { + SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt ); + + MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) ); + + for( int ii = 1; ii < poly.PointCount(); ++ii ) + LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + FinishTo(wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) ); + } +} + /** * DXF trapezoidal pad: only sketch mode is supported diff --git a/common/common_plotGERBER_functions.cpp b/common/common_plotGERBER_functions.cpp index 2e041e600a..b7fa38f367 100644 --- a/common/common_plotGERBER_functions.cpp +++ b/common/common_plotGERBER_functions.cpp @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2016 KiCad Developers, see CHANGELOG.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 @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -479,8 +480,9 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub if( trace_mode == FILLED ) { - /* XXX to do: use an aperture macro to declare the rotated pad */ - /* The pad is reduced to an oval with dy > dx */ + // TODO: use an aperture macro to declare the rotated pad + // + // The pad is reduced to an segment with dy > dx delta = size.y - size.x; x0 = 0; y0 = -delta / 2; @@ -559,12 +561,71 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, } } +void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ) + +{ + // Currently, a Pad RoundRect is plotted as polygon. + // TODO: use Aperture macro and flash it + SHAPE_POLY_SET outline; + const int segmentToCircleCount = 64; + TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, + aCornerRadius, segmentToCircleCount ); + + std::vector< wxPoint > cornerList; + cornerList.reserve( segmentToCircleCount + 5 ); + // TransformRoundRectToPolygon creates only one convex polygon + SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + // Close polygon + cornerList.push_back( cornerList[0] ); + + PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL ); +} + +void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ) + +{ + // A Pad custom is plotted as polygon. +#if 1 + // A flashed circle @aPadPos is added (anchor pad) + // However, because the anchor pad can be circle or rect, we use only + // a circle not bigger tahn the rect. + // the main purpose is to show a flashed DCode as pad anchor + FlashPadCircle( aPadPos, std::min( aSize.x, aSize.x ), aTraceMode ); +#endif + + std::vector< wxPoint > cornerList; + + for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt ) + { + SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt ); + cornerList.clear(); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + // Close polygon + cornerList.push_back( cornerList[0] ); + + PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL ); + } +} + void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ) { - // XXX to do: use an aperture macro to declare the pad + // Currently, a Pad Trapezoid is plotted as polygon. + // TODO: use Aperture macro and flash it + // polygon corners list std::vector< wxPoint > cornerList; diff --git a/common/common_plotHPGL_functions.cpp b/common/common_plotHPGL_functions.cpp index 697b1a8541..4af40f311e 100644 --- a/common/common_plotHPGL_functions.cpp +++ b/common/common_plotHPGL_functions.cpp @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2016 KiCad Developers, see CHANGELOG.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 @@ -25,7 +25,6 @@ /** * @file common_plotHPGL_functions.cpp * @brief KiCad: Common plot HPGL Routines - * Filled primitive are not supported, but some could be using HPGL/2 * Since this plot engine is mostly intended for import in external programs, * sadly HPGL/2 isn't supported a lot... some of the primitives use overlapped * strokes to fill the shape @@ -113,6 +112,12 @@ * but the outputs and feedrates are affected. * PD {x, y}; * + * PM Polygon mode + * associated commands: + * PM2 End polygon mode + * FP Fill polygon + * EP Draw polygon outline + * * PR (Plot Relative): Moves to the relative position specified and sets relative mode * for future PU and PD commands. * If no arguments follow the command, only relative mode is set. @@ -179,7 +184,7 @@ * VS (Velocity Select): * VS {v {, n}}; * v [1 .. 40] - * n [1 .. 8, je nach Ausstattung] + * n [1 .. 8] * * XT (X Tick): * XT; @@ -197,6 +202,7 @@ #include #include #include +#include // HPGL scale factor (1 PLU = 1/40mm = 25 micrometers) static const double PLUsPERDECIMIL = 0.102041; @@ -223,8 +229,6 @@ void HPGL_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, paperSize.y *= 10.0 * aIusPerDecimil; SetDefaultLineWidth( 0 ); // HPGL has pen sizes instead m_plotMirror = aMirror; - penOverlap = 0; - penDiameter = 0; } @@ -284,8 +288,9 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, /** - * HPGL polygon: fill not supported (but closed, at least) + * HPGL polygon: */ + void HPGL_PLOTTER::PlotPoly( const std::vector& aCornerList, FILL_T aFill, int aWidth ) { @@ -293,19 +298,38 @@ void HPGL_PLOTTER::PlotPoly( const std::vector& aCornerList, return; SetCurrentLineWidth( aWidth ); - MoveTo( aCornerList[0] ); - for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) - LineTo( aCornerList[ii] ); - - // Close polygon if filled. - if( aFill ) + if( aFill == FILLED_SHAPE ) { + // Draw the filled area + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); + fprintf( outputFile, "PM 0;\n" ); // Start polygon + + for( unsigned ii = 1; ii < aCornerList.size(); ++ii ) + LineTo( aCornerList[ii] ); + int ii = aCornerList.size() - 1; if( aCornerList[ii] != aCornerList[0] ) LineTo( aCornerList[0] ); + + fprintf( outputFile, "PM 2; FP; EP;\n" ); // Close, fill polygon and draw outlines + } + else + { + // Plot only the polygon outline. + for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) + LineTo( aCornerList[ii] ); + + // Always close polygon if filled. + if( aFill ) + { + int ii = aCornerList.size() - 1; + + if( aCornerList[ii] != aCornerList[0] ) + LineTo( aCornerList[0] ); + } } PenFinish(); @@ -455,7 +479,7 @@ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double int deltaxy, cx, cy; wxSize size( aSize ); - /* The pad is reduced to an oval with size.y > size.x + /* The pad will be drawn as an oblong shape with size.y > size.x * (Oval vertical orientation 0) */ if( size.x > size.y ) @@ -477,7 +501,7 @@ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double RotatePoint( &cx, &cy, orient ); FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode ); } - else // Plot in SKETCH mode. + else // Plot in outline mode. { sketchOval( pos, size, orient, KiROUND( penDiameter ) ); } @@ -492,28 +516,34 @@ void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, wxASSERT( outputFile ); DPOINT pos_dev = userToDeviceCoordinates( pos ); - int delta = KiROUND( penDiameter - penOverlap ); - int radius = ( diametre - KiROUND( penDiameter ) ) / 2; + int radius = diametre / 2; + + if( trace_mode == FILLED ) + { + // if filled mode, the pen diameter is removed from diameter + // to keep the pad size + radius -= KiROUND( penDiameter ) / 2; + } if( radius < 0 ) radius = 0; double rsize = userToDeviceSize( radius ); - fprintf( outputFile, "PA %.0f,%.0f;CI %.0f;\n", - pos_dev.x, pos_dev.y, rsize ); - if( trace_mode == FILLED ) // Plot in filled mode. { - if( delta > 0 ) - { - while( (radius -= delta ) >= 0 ) - { - rsize = userToDeviceSize( radius ); - fprintf( outputFile, "PA %.0f,%.0f;CI %.0f;\n", + // A filled polygon uses always the current point to start the polygon. + // Gives a correct current starting point for the circle + MoveTo( wxPoint( pos.x+radius, pos.y ) ); + // Plot filled area and its outline + fprintf( outputFile, "PM 0; PA %.0f,%.0f;CI %.0f; PM 2; FP; EP;\n", pos_dev.x, pos_dev.y, rsize ); - } - } + } + else + { + // Draw outline only: + fprintf( outputFile, "PA %.0f,%.0f;CI %.0f;\n", + pos_dev.x, pos_dev.y, rsize ); } PenFinish(); @@ -523,113 +553,92 @@ void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, double orient, EDA_DRAW_MODE_T trace_mode ) { - wxASSERT( outputFile ); - wxSize size; - int delta; - int ox, oy, fx, fy; + // Build rect polygon: + std::vector corners; - size.x = padsize.x / 2; - size.y = padsize.y / 2; - - size.x = (padsize.x - (int) penDiameter) / 2; - size.y = (padsize.y - (int) penDiameter) / 2; - - if( size.x < 0 ) - size.x = 0; - - if( size.y < 0 ) - size.y = 0; - - // If a dimension is zero, the trace is reduced to 1 line. - if( size.x == 0 ) - { - ox = pos.x; - oy = pos.y - size.y; - RotatePoint( &ox, &oy, pos.x, pos.y, orient ); - fx = pos.x; - fy = pos.y + size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - MoveTo( wxPoint( ox, oy ) ); - FinishTo( wxPoint( fx, fy ) ); - return; - } - - if( size.y == 0 ) - { - ox = pos.x - size.x; - oy = pos.y; - RotatePoint( &ox, &oy, pos.x, pos.y, orient ); - fx = pos.x + size.x; - fy = pos.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - MoveTo( wxPoint( ox, oy ) ); - FinishTo( wxPoint( fx, fy ) ); - return; - } - - ox = pos.x - size.x; - oy = pos.y - size.y; - RotatePoint( &ox, &oy, pos.x, pos.y, orient ); - MoveTo( wxPoint( ox, oy ) ); - - fx = pos.x - size.x; - fy = pos.y + size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - LineTo( wxPoint( fx, fy ) ); - - fx = pos.x + size.x; - fy = pos.y + size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - LineTo( wxPoint( fx, fy ) ); - - fx = pos.x + size.x; - fy = pos.y - size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - LineTo( wxPoint( fx, fy ) ); - - FinishTo( wxPoint( ox, oy ) ); + int dx = padsize.x / 2; + int dy = padsize.y / 2; if( trace_mode == FILLED ) { - // Plot in filled mode. - delta = (int) (penDiameter - penOverlap); - - if( delta > 0 ) - while( (size.x > 0) && (size.y > 0) ) - { - size.x -= delta; - size.y -= delta; - - if( size.x < 0 ) - size.x = 0; - - if( size.y < 0 ) - size.y = 0; - - ox = pos.x - size.x; - oy = pos.y - size.y; - RotatePoint( &ox, &oy, pos.x, pos.y, orient ); - MoveTo( wxPoint( ox, oy ) ); - - fx = pos.x - size.x; - fy = pos.y + size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - LineTo( wxPoint( fx, fy ) ); - - fx = pos.x + size.x; - fy = pos.y + size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - LineTo( wxPoint( fx, fy ) ); - - fx = pos.x + size.x; - fy = pos.y - size.y; - RotatePoint( &fx, &fy, pos.x, pos.y, orient ); - LineTo( wxPoint( fx, fy ) ); - - FinishTo( wxPoint( ox, oy ) ); - } + // in filled mode, the pen diameter is removed from size + // to compensate the extra size due to this pen size + dx -= KiROUND( penDiameter ) / 2; + dx = std::max( dx, 0); + dy -= KiROUND( penDiameter ) / 2; + dy = std::max( dy, 0); + } + corners.push_back( wxPoint( - dx, - dy ) ); + corners.push_back( wxPoint( - dx, + dy ) ); + corners.push_back( wxPoint( + dx, + dy ) ); + corners.push_back( wxPoint( + dx, - dy ) ); + + + for( unsigned ii = 0; ii < corners.size(); ii++ ) + { + RotatePoint( &corners[ii], orient ); + corners[ii] += pos; + } + + PlotPoly( corners, trace_mode == FILLED ? FILLED_SHAPE : NO_FILL ); +} + + +void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ) +{ + SHAPE_POLY_SET outline; + const int segmentToCircleCount = 32; + + wxSize size = aSize; + + if( aTraceMode == FILLED ) + { + // in filled mode, the pen diameter is removed from size + // to keep the pad size + size.x -= KiROUND( penDiameter ) / 2; + size.x = std::max( size.x, 0); + size.y -= KiROUND( penDiameter ) / 2; + size.y = std::max( size.y, 0); + + // keep aCornerRadius to a value < min size x,y < 2: + aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 ); + } + + TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, + aCornerRadius, segmentToCircleCount ); + + // TransformRoundRectToPolygon creates only one convex polygon + std::vector< wxPoint > cornerList; + cornerList.reserve( segmentToCircleCount + 4 ); + SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL ); +} + +void HPGL_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ) +{ + std::vector< wxPoint > cornerList; + + for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt ) + { + SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt ); + + cornerList.clear(); + cornerList.reserve( poly.PointCount() ); + + for( int ii = 1; ii < poly.PointCount(); ++ii ) + cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL ); } } @@ -637,105 +646,16 @@ void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, void HPGL_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ) { - wxASSERT( outputFile ); - wxPoint polygone[4]; // coordinates of corners relatives to the pad - wxPoint coord[4]; // absolute coordinates of corners (coordinates in plotter space) - int move; - - move = KiROUND( penDiameter ); + std::vector< wxPoint > cornerList; + cornerList.reserve( 4 ); - for( int ii = 0; ii < 4; ii++ ) - polygone[ii] = aCorners[ii]; - - // polygone[0] is assumed the lower left - // polygone[1] is assumed the upper left - // polygone[2] is assumed the upper right - // polygone[3] is assumed the lower right - - // Plot the outline: for( int ii = 0; ii < 4; ii++ ) { - coord[ii] = polygone[ii]; - RotatePoint( &coord[ii], aPadOrient ); - coord[ii] += aPadPos; + wxPoint coord( aCorners[ii] ); + RotatePoint( &coord, aPadOrient ); + coord += aPadPos; + cornerList.push_back( coord ); } - MoveTo( coord[0] ); - LineTo( coord[1] ); - LineTo( coord[2] ); - LineTo( coord[3] ); - FinishTo( coord[0] ); - - // Fill shape: - if( aTrace_Mode == FILLED ) - { - // TODO: replace this par the HPGL plot polygon. - int jj; - // Fill the shape - move = KiROUND( penDiameter - penOverlap ); - // Calculate fill height. - - if( polygone[0].y == polygone[3].y ) // Horizontal - { - jj = polygone[3].y - (int) ( penDiameter + ( 2 * penOverlap ) ); - } - else // vertical - { - jj = polygone[3].x - (int) ( penDiameter + ( 2 * penOverlap ) ); - } - - // Calculation of dd = number of segments was traced to fill. - jj = jj / (int) ( penDiameter - penOverlap ); - - // Trace the outline. - for( ; jj > 0; jj-- ) - { - polygone[0].x += move; - polygone[0].y -= move; - polygone[1].x += move; - polygone[1].y += move; - polygone[2].x -= move; - polygone[2].y += move; - polygone[3].x -= move; - polygone[3].y -= move; - - // Test for crossed vertexes. - if( polygone[0].x > polygone[3].x ) /* X axis intersection on - * vertexes 0 and 3 */ - { - polygone[0].x = polygone[3].x = 0; - } - - if( polygone[1].x > polygone[2].x ) /* X axis intersection on - * vertexes 1 and 2 */ - { - polygone[1].x = polygone[2].x = 0; - } - - if( polygone[1].y > polygone[0].y ) /* Y axis intersection on - * vertexes 0 and 1 */ - { - polygone[0].y = polygone[1].y = 0; - } - - if( polygone[2].y > polygone[3].y ) /* Y axis intersection on - * vertexes 2 and 3 */ - { - polygone[2].y = polygone[3].y = 0; - } - - for( int ii = 0; ii < 4; ii++ ) - { - coord[ii] = polygone[ii]; - RotatePoint( &coord[ii], aPadOrient ); - coord[ii] += aPadPos; - } - - MoveTo( coord[0] ); - LineTo( coord[1] ); - LineTo( coord[2] ); - LineTo( coord[3] ); - FinishTo( coord[0] ); - } - } + PlotPoly( cornerList, aTrace_Mode == FILLED ? FILLED_SHAPE : NO_FILL ); } diff --git a/common/common_plotPS_functions.cpp b/common/common_plotPS_functions.cpp index 22b1de5858..2aa83be026 100644 --- a/common/common_plotPS_functions.cpp +++ b/common/common_plotPS_functions.cpp @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2016 KiCad Developers, see CHANGELOG.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 @@ -35,6 +35,7 @@ #include #include #include +#include /* Forward declaration of the font width metrics (yes extern! this is the way to forward declare variables */ @@ -188,6 +189,76 @@ void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, GetCurrentLineWidth() ); } +void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ) +{ + wxSize size( aSize ); + + if( aTraceMode == FILLED ) + SetCurrentLineWidth( 0 ); + else + { + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); + size.x -= GetCurrentLineWidth(); + size.y -= GetCurrentLineWidth(); + aCornerRadius -= GetCurrentLineWidth()/2; + } + + + SHAPE_POLY_SET outline; + const int segmentToCircleCount = 64; + TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, + aCornerRadius, segmentToCircleCount ); + + std::vector< wxPoint > cornerList; + cornerList.reserve( segmentToCircleCount + 5 ); + // TransformRoundRectToPolygon creates only one convex polygon + SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + // Close polygon + cornerList.push_back( cornerList[0] ); + + PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, + GetCurrentLineWidth() ); +} + +void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ) +{ + wxSize size( aSize ); + + if( aTraceMode == FILLED ) + SetCurrentLineWidth( 0 ); + else + { + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); + size.x -= GetCurrentLineWidth(); + size.y -= GetCurrentLineWidth(); + } + + + std::vector< wxPoint > cornerList; + + for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt ) + { + SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt ); + cornerList.clear(); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + + // Close polygon + cornerList.push_back( cornerList[0] ); + + PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, + GetCurrentLineWidth() ); + } +} void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) diff --git a/common/convert_basic_shapes_to_polygon.cpp b/common/convert_basic_shapes_to_polygon.cpp index fbbd3c17a0..e8fd615db3 100644 --- a/common/convert_basic_shapes_to_polygon.cpp +++ b/common/convert_basic_shapes_to_polygon.cpp @@ -64,6 +64,71 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, } } +/* Returns the centers of the rounded corners of a rect. + */ +void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, + const wxPoint& aPosition, const wxSize& aSize, double aRotation ) +{ + wxSize size( aSize/2 ); + + size.x -= aRadius; + size.y -= aRadius; + + aCenters[0].x = -size.x; + aCenters[0].y = size.y; + + aCenters[1].x = size.x; + aCenters[1].y = size.y; + + aCenters[2].x = size.x; + aCenters[2].y = -size.y; + + aCenters[3].x = -size.x; + aCenters[3].y = -size.y; + + // Rotate the polygon + if( aRotation ) + { + for( int ii = 0; ii < 4; ii++ ) + RotatePoint( &aCenters[ii], aRotation ); + } + + // move the polygon to the position + for( int ii = 0; ii < 4; ii++ ) + aCenters[ii] += aPosition; +} + +/** + * Function TransformRoundRectToPolygon + * convert a rectangle with rounded corners to a polygon + * Convert arcs to multiple straight lines + * @param aCornerBuffer = a buffer to store the polygon + * @param aPosition = the coordinate of the center of the rectangle + * @param aSize = the size of the rectangle + * @param aRadius = radius of rounded corners + * @param aRotation = rotation in 0.1 degrees of the rectangle + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + */ +void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, + const wxPoint& aPosition, const wxSize& aSize, + double aRotation, int aCornerRadius, + int aCircleToSegmentsCount ) +{ + wxPoint corners[4]; + GetRoundRectCornerCenters( corners, aCornerRadius, aPosition, aSize, aRotation ); + + SHAPE_POLY_SET outline; + outline.NewOutline(); + + for( int ii = 0; ii < 4; ++ii ) + outline.Append( corners[ii].x, corners[ii].y ); + + outline.Inflate( aCornerRadius, aCircleToSegmentsCount ); + + // Add the outline: + aCornerBuffer.Append( outline ); +} + /** * Function TransformRoundedEndsSegmentToPolygon diff --git a/include/convert_basic_shapes_to_polygon.h b/include/convert_basic_shapes_to_polygon.h index 17e6663995..f558be3a14 100644 --- a/include/convert_basic_shapes_to_polygon.h +++ b/include/convert_basic_shapes_to_polygon.h @@ -50,6 +50,34 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, int aCircleToSegmentsCount ); +/** + * Helper function GetRoundRectCornerCenters + * Has meaning only for rounded rect + * Returns the centers of the rounded corners. + * @param aPosition = position of the round rect + * @param aSize = size of the of the round rect. + * @param aRotation = rotation of the of the round rect + * @param aCenters a buffer to store the 4 coordinates. + */ +void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, + const wxPoint& aPosition, const wxSize& aSize, double aRotation ); + +/** + * Function TransformRoundRectToPolygon + * convert a rectangle with rounded corners to a polygon + * Convert arcs to multiple straight lines + * @param aCornerBuffer = a buffer to store the polygon + * @param aPosition = the coordinate of the center of the rectangle + * @param aSize = the size of the rectangle + * @param aCornerRadius = radius of rounded corners + * @param aRotation = rotation in 0.1 degrees of the rectangle + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + */ +void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, + const wxPoint& aPosition, const wxSize& aSize, + double aRotation, int aCornerRadius, + int aCircleToSegmentsCount ); + /** * Function TransformRoundedEndsSegmentToPolygon * convert a segment with rounded ends to a polygon diff --git a/include/plot_common.h b/include/plot_common.h index 334b95518a..8bd541a6c9 100644 --- a/include/plot_common.h +++ b/include/plot_common.h @@ -38,6 +38,8 @@ #include #include // FILL_T +class SHAPE_POLY_SET; + /** * Enum PlotFormat * is the set of supported output plot formats. They should be kept in order @@ -280,6 +282,29 @@ public: virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) = 0; + /** + * virtual function FlashPadRoundRect + * @param aPadPos Position of the shape (center of the rectangle + * @param aSize = size of rounded rect + * @param cornerRadius Radius of the rounded corners + * @param aOrient The rotation of the shape + * @param aTraceMode FILLED or SKETCH + */ + virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ) = 0; + + /** + * virtual function FlashPadCustom + * @param aPadPos Position of the shape (center of the rectangle + * @param aSize = size of round reference pad + * @param aPolygons the shape as polygon set + * @param aTraceMode FILLED or SKETCH + */ + virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ) = 0; + /** virtual function FlashPadTrapez * flash a trapezoidal pad * @param aPadPos = the position of the shape @@ -534,6 +559,12 @@ public: EDA_DRAW_MODE_T trace_mode ); virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, double orient, EDA_DRAW_MODE_T trace_mode ); + virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ); + virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ); virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); @@ -586,6 +617,12 @@ public: EDA_DRAW_MODE_T trace_mode ); virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, double orient, EDA_DRAW_MODE_T trace_mode ); + virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ); + virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ); virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); @@ -942,14 +979,28 @@ public: EDA_DRAW_MODE_T trace_mode ); /** - * Filled rect flashes are handled as aperture in the 90 degree positions only + * Filled rect flashes are handled as aperture in the 0 90 180 or 270 degree orientation only + * and as polygon for other orientations + * TODO: always use flashed shapes (aperture macros) */ virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, double orient, EDA_DRAW_MODE_T trace_mode ); + /** + * Roundrect pad at the moment are not handled as aperture, since + * they require aperture macros + * TODO: always use flashed shapes (aperture macros) + */ + virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ); + virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ); /** * Trapezoidal pad at the moment are *never* handled as aperture, since * they require aperture macros + * TODO: always use flashed shapes (aperture macros) */ virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); @@ -1069,6 +1120,12 @@ public: EDA_DRAW_MODE_T trace_mode ); virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, double orient, EDA_DRAW_MODE_T trace_mode ); + virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, + int aCornerRadius, double aOrient, + EDA_DRAW_MODE_T aTraceMode ); + virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, + SHAPE_POLY_SET* aPolygons, + EDA_DRAW_MODE_T aTraceMode ); virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h index b2eebc58b7..f7ffcaaeb1 100644 --- a/pcbnew/class_edge_mod.h +++ b/pcbnew/class_edge_mod.h @@ -136,8 +136,6 @@ public: void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override #endif -//protected: @todo: is it just me? - wxPoint m_Start0; // Start point or center, relative to module origin, orient 0. wxPoint m_End0; // End point, relative to module origin, orient 0. }; diff --git a/pcbnew/dialogs/dialog_layer_selection_base.cpp b/pcbnew/dialogs/dialog_layer_selection_base.cpp index bdd2b7d03b..c03ea708ec 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.cpp +++ b/pcbnew/dialogs/dialog_layer_selection_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Jan 1 2016) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -198,7 +198,7 @@ DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE m_sdbSizer->AddButton( m_sdbSizerCancel ); m_sdbSizer->Realize(); - bSizerMain->Add( m_sdbSizer, 0, wxEXPAND, 5 ); + bSizerMain->Add( m_sdbSizer, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); this->SetSizer( bSizerMain ); diff --git a/pcbnew/dialogs/dialog_layer_selection_base.fbp b/pcbnew/dialogs/dialog_layer_selection_base.fbp index 9bea630a96..b4821b6e32 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.fbp +++ b/pcbnew/dialogs/dialog_layer_selection_base.fbp @@ -1,6 +1,6 @@ - + C++ @@ -20,8 +20,10 @@ . 1 + 1 1 1 + UI 0 0 @@ -1025,7 +1027,7 @@ 5 - wxEXPAND + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT 0 0 diff --git a/pcbnew/dialogs/dialog_layer_selection_base.h b/pcbnew/dialogs/dialog_layer_selection_base.h index d61d4bf6cd..1b90b54fe3 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.h +++ b/pcbnew/dialogs/dialog_layer_selection_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) +// C++ code generated with wxFormBuilder (version Jan 1 2016) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE!