From cffe0cfcaa0270c13d5f9e2678863c2f32804238 Mon Sep 17 00:00:00 2001 From: charras Date: Thu, 25 Jun 2009 20:45:27 +0000 Subject: [PATCH] support for bezier curves --- common/CMakeLists.txt | 1 + common/about_kicad.cpp | 23 +- common/bezier_curves.cpp | 398 ++++++++++++++++++++++++++ common/drawpanel.cpp | 4 +- common/gr_basic.cpp | 41 ++- eeschema/build_BOM.cpp | 4 +- eeschema/classes_body_items.cpp | 232 +++++++++++++++ eeschema/classes_body_items.h | 66 +++++ eeschema/eelibs_read_libraryfiles.cpp | 5 + eeschema/locate.cpp | 7 + eeschema/plot.cpp | 23 ++ eeschema/savelib.cpp | 4 + include/base_struct.h | 1 + include/bezier_curves.h | 13 + include/board_item_struct.h | 3 +- include/gr_basic.h | 5 +- include/wxstruct.h | 1 - pcbnew/class_board_item.cpp | 1 + pcbnew/class_drawsegment.cpp | 166 ++++++++--- pcbnew/class_drawsegment.h | 3 + pcbnew/class_pad_draw_functions.cpp | 4 +- pcbnew/cotation.cpp | 2 + pcbnew/modules.cpp | 5 +- pcbnew/plot_rtn.cpp | 77 +++-- polygon/PolyLine.cpp | 22 +- polygon/PolyLine.h | 5 + 26 files changed, 1026 insertions(+), 90 deletions(-) create mode 100644 common/bezier_curves.cpp create mode 100644 include/bezier_curves.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 298d655c51..4bd23620ee 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -10,6 +10,7 @@ set(COMMON_SRCS base_screen.cpp base_struct.cpp basicframe.cpp + bezier_curves.cpp block_commande.cpp class_drawpickedstruct.cpp common.cpp diff --git a/common/about_kicad.cpp b/common/about_kicad.cpp index 07b531ac5e..31265c988b 100644 --- a/common/about_kicad.cpp +++ b/common/about_kicad.cpp @@ -9,29 +9,25 @@ #define BUILD_VERSION "(20090621-unstable)" -#ifndef KICAD_ABOUT_VERSION -#define KICAD_ABOUT_VERSION BUILD_VERSION -#endif -wxString g_BuildVersion - #ifdef HAVE_SVN_VERSION #include "version.h" -( wxT( KICAD_SVN_VERSION ) ) +wxString g_BuildVersion( wxT( KICAD_SVN_VERSION ) ); #else -( wxT( BUILD_VERSION ) ) +wxString g_BuildVersion( wxT( BUILD_VERSION ) ); #endif -; -wxString g_BuildAboutVersion + #if defined(HAVE_SVN_VERSION) || defined(HAVE_SVN_REVISION) # include "version.h" -( wxT( KICAD_ABOUT_VERSION ) ) -#else -( wxT( BUILD_VERSION ) ) +#ifndef KICAD_ABOUT_VERSION +#define KICAD_ABOUT_VERSION BUILD_VERSION +#endif +wxString g_BuildAboutVersion( wxT( KICAD_ABOUT_VERSION ) ); +#else +wxString g_BuildAboutVersion( wxT( BUILD_VERSION ) ); #endif -; /**********************************/ @@ -137,6 +133,7 @@ void InitKiCadAbout( wxAboutDialogInfo& info ) info.AddDeveloper( SetMsg( wxT( "Jerry Jacobs " ) ) ); info.AddDeveloper( SetMsg( wxT( "Jonas Diemer " ) ) ); info.AddDeveloper( SetMsg( wxT( "KBool Library " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Marco Serantoni " ) ) ); info.AddDeveloper( SetMsg( wxT( "Rok Markovic " ) ) ); info.AddDeveloper( SetMsg( wxT( "Tim Hanson " ) ) ); info.AddDeveloper( SetMsg( wxT( "Vesa Solonen " ) ) ); diff --git a/common/bezier_curves.cpp b/common/bezier_curves.cpp new file mode 100644 index 0000000000..c1631ff20b --- /dev/null +++ b/common/bezier_curves.cpp @@ -0,0 +1,398 @@ +/************************************/ +/* routines to handle bezier curves */ +/************************************/ + +#include "fctsys.h" +#include "bezier_curves.h" + + +#define add_segment(segment) if(bezier_points[bezier_points.size()-1] != segment) bezier_points.push_back(segment); + + +// Local variables: +static std::vector bezier_points; + +static int bezier_recursion_limit = 12; +static double bezier_approximation_scale = 0.5; // 1 + +static double bezier_curve_collinearity_epsilon = 1e-30; +static double bezier_curve_angle_tolerance_epsilon = 0.0001; +static double bezier_distance_tolerance_square; // derived by approximation_scale +static double bezier_angle_tolerance = 0.0; +static double bezier_cusp_limit = 0.0; + +// Local functions: +static void recursive_bezier( int x1, int y1, int x2, int y2, int x3, int y3, int level ); +static void recursive_bezier( int x1, + int y1, + int x2, + int y2, + int x3, + int y3, + int x4, + int y4, + int level ); + +/***********************************************************************************/ + + +std::vector Bezier2Poly( wxPoint c1, wxPoint c2, wxPoint c3, wxPoint c4 ) +{ + return Bezier2Poly( c1.x, c1.y, c2.x, c2.y, c3.x, c3.y, c4.x, c4.y ); +} + + +std::vector Bezier2Poly( wxPoint c1, wxPoint c2, wxPoint c3 ) +{ + return Bezier2Poly( c1.x, c1.y, c2.x, c2.y, c3.x, c3.y ); +} + + +inline int calc_sq_distance( int x1, int y1, int x2, int y2 ) +{ + int dx = x2 - x1; + int dy = y2 - y1; + + return dx * dx + dy * dy; +} + + +std::vector Bezier2Poly( int x1, int y1, int x2, int y2, int x3, int y3 ) +{ + bezier_points.clear(); + + bezier_distance_tolerance_square = 0.5 / bezier_approximation_scale; + bezier_distance_tolerance_square *= bezier_distance_tolerance_square; + bezier_points.push_back( wxPoint( x1, y1 ) ); + recursive_bezier( x1, y1, x2, y2, x3, y3, 0 ); + bezier_points.push_back( wxPoint( x3, y3 ) ); + + wxLogDebug( wxT( "Bezier Conversion - End (%d vertex)" ), bezier_points.size() ); + return bezier_points; +} + + +std::vector Bezier2Poly( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) +{ + bezier_points.clear(); + bezier_distance_tolerance_square = 0.5 / bezier_approximation_scale; + bezier_distance_tolerance_square *= bezier_distance_tolerance_square; + + bezier_points.push_back( wxPoint( x1, y1 ) ); + recursive_bezier( x1, y1, x2, y2, x3, y3, x4, y4, 0 ); + bezier_points.push_back( wxPoint( x4, y4 ) ); + wxLogDebug( wxT( "Bezier Conversion - End (%d vertex)" ), bezier_points.size() ); + return bezier_points; +} + + +void recursive_bezier( int x1, int y1, int x2, int y2, int x3, int y3, int level ) +{ + if( abs( level ) > bezier_recursion_limit ) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + int x12 = (x1 + x2) / 2; + int y12 = (y1 + y2) / 2; + int x23 = (x2 + x3) / 2; + int y23 = (y2 + y3) / 2; + int x123 = (x12 + x23) / 2; + int y123 = (y12 + y23) / 2; + + int dx = x3 - x1; + int dy = y3 - y1; + double d = fabs( ( (x2 - x3) * dy - (y2 - y3) * dx ) ); + double da; + + if( d > bezier_curve_collinearity_epsilon ) + { + // Regular case + //----------------- + if( d * d <= bezier_distance_tolerance_square * (dx * dx + dy * dy) ) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if( bezier_angle_tolerance < bezier_curve_angle_tolerance_epsilon ) + { + add_segment( wxPoint( x123, y123 ) ); + return; + } + + // Angle & Cusp Condition + //---------------------- + da = fabs( atan2( y3 - y2, x3 - x2 ) - atan2( y2 - y1, x2 - x1 ) ); + if( da >=M_PI ) + da = 2 * M_PI - da; + + if( da < bezier_angle_tolerance ) + { + // Finally we can stop the recursion + //---------------------- + add_segment( wxPoint( x123, y123 ) ); + return; + } + } + } + else + { + // Collinear case + //------------------ + da = dx * dx + dy * dy; + if( da == 0 ) + { + d = calc_sq_distance( x1, y1, x2, y2 ); + } + else + { + d = ( (x2 - x1) * dx + (y2 - y1) * dy ) / da; + if( d > 0 && d < 1 ) + { + // Simple collinear case, 1---2---3 + // We can leave just two endpoints + return; + } + if( d <= 0 ) + d = calc_sq_distance( x2, y2, x1, y1 ); + else if( d >= 1 ) + d = calc_sq_distance( x2, y2, x3, y3 ); + else + d = calc_sq_distance( x2, y2, x1 + d * dx, y1 + d * dy ); + } + if( d < bezier_distance_tolerance_square ) + { + add_segment( wxPoint( x2, y2 ) ); + return; + } + } + + // Continue subdivision + //---------------------- + recursive_bezier( x1, y1, x12, y12, x123, y123, level + 1 ); + recursive_bezier( x123, y123, x23, y23, x3, y3, -(level + 1) ); +} + + +void recursive_bezier( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int level ) +{ + if( abs( level ) > bezier_recursion_limit ) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + int x12 = (x1 + x2) / 2; + int y12 = (y1 + y2) / 2; + int x23 = (x2 + x3) / 2; + int y23 = (y2 + y3) / 2; + int x34 = (x3 + x4) / 2; + int y34 = (y3 + y4) / 2; + int x123 = (x12 + x23) / 2; + int y123 = (y12 + y23) / 2; + int x234 = (x23 + x34) / 2; + int y234 = (y23 + y34) / 2; + int x1234 = (x123 + x234) / 2; + int y1234 = (y123 + y234) / 2; + + + // Try to approximate the full cubic curve by a single straight line + //------------------ + int dx = x4 - x1; + int dy = y4 - y1; + + double d2 = fabs( ( (x2 - x4) * dy - (y2 - y4) * dx ) ); + double d3 = fabs( ( (x3 - x4) * dy - (y3 - y4) * dx ) ); + double da1, da2, k; + + switch( (int(d2 > bezier_curve_collinearity_epsilon) << 1) + + int(d3 > bezier_curve_collinearity_epsilon) ) + { + case 0: + + // All collinear OR p1==p4 + //---------------------- + k = dx * dx + dy * dy; + if( k == 0 ) + { + d2 = calc_sq_distance( x1, y1, x2, y2 ); + d3 = calc_sq_distance( x4, y4, x3, y3 ); + } + else + { + k = 1 / k; + da1 = x2 - x1; + da2 = y2 - y1; + d2 = k * (da1 * dx + da2 * dy); + da1 = x3 - x1; + da2 = y3 - y1; + d3 = k * (da1 * dx + da2 * dy); + if( d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1 ) + { + // Simple collinear case, 1---2---3---4 + // We can leave just two endpoints + return; + } + if( d2 <= 0 ) + d2 = calc_sq_distance( x2, y2, x1, y1 ); + else if( d2 >= 1 ) + d2 = calc_sq_distance( x2, y2, x4, y4 ); + else + d2 = calc_sq_distance( x2, y2, x1 + d2 * dx, y1 + d2 * dy ); + + if( d3 <= 0 ) + d3 = calc_sq_distance( x3, y3, x1, y1 ); + else if( d3 >= 1 ) + d3 = calc_sq_distance( x3, y3, x4, y4 ); + else + d3 = calc_sq_distance( x3, y3, x1 + d3 * dx, y1 + d3 * dy ); + } + if( d2 > d3 ) + { + if( d2 < bezier_distance_tolerance_square ) + { + add_segment( wxPoint( x2, y2 ) ); + return; + } + } + else + { + if( d3 < bezier_distance_tolerance_square ) + { + add_segment( wxPoint( x3, y3 ) ); + return; + } + } + break; + + case 1: + + // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if( d3 * d3 <= bezier_distance_tolerance_square * (dx * dx + dy * dy) ) + { + if( bezier_angle_tolerance < bezier_curve_angle_tolerance_epsilon ) + { + add_segment( wxPoint( x23, y23 ) ); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs( atan2( y4 - y3, x4 - x3 ) - atan2( y3 - y2, x3 - x2 ) ); + if( da1 >= M_PI ) + da1 = 2 * M_PI - da1; + + if( da1 < bezier_angle_tolerance ) + { + add_segment( wxPoint( x2, y2 ) ); + add_segment( wxPoint( x3, y3 ) ); + return; + } + + if( bezier_cusp_limit != 0.0 ) + { + if( da1 > bezier_cusp_limit ) + { + add_segment( wxPoint( x3, y3 ) ); + return; + } + } + } + break; + + case 2: + + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if( d2 * d2 <= bezier_distance_tolerance_square * (dx * dx + dy * dy) ) + { + if( bezier_angle_tolerance < bezier_curve_angle_tolerance_epsilon ) + { + add_segment( wxPoint( x23, y23 ) ); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs( atan2( y3 - y2, x3 - x2 ) - atan2( y2 - y1, x2 - x1 ) ); + if( da1 >= M_PI ) + da1 = 2 * M_PI - da1; + + if( da1 < bezier_angle_tolerance ) + { + add_segment( wxPoint( x2, y2 ) ); + add_segment( wxPoint( x3, y3 ) ); + return; + } + + if( bezier_cusp_limit != 0.0 ) + { + if( da1 > bezier_cusp_limit ) + { + add_segment( wxPoint( x2, y2 ) ); + return; + } + } + } + break; + + case 3: + + // Regular case + //----------------- + if( (d2 + d3) * (d2 + d3) <= bezier_distance_tolerance_square * (dx * dx + dy * dy) ) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if( bezier_angle_tolerance < bezier_curve_angle_tolerance_epsilon ) + { + add_segment( wxPoint( x23, y23 ) ); + return; + } + + // Angle & Cusp Condition + //---------------------- + k = atan2( y3 - y2, x3 - x2 ); + da1 = fabs( k - atan2( y2 - y1, x2 - x1 ) ); + da2 = fabs( atan2( y4 - y3, x4 - x3 ) - k ); + if( da1 >= M_PI ) + da1 = 2 * M_PI - da1; + if( da2 >= M_PI ) + da2 = 2 * M_PI - da2; + + if( da1 + da2 < bezier_angle_tolerance ) + { + // Finally we can stop the recursion + //---------------------- + add_segment( wxPoint( x23, y23 ) ); + return; + } + + if( bezier_cusp_limit != 0.0 ) + { + if( da1 > bezier_cusp_limit ) + { + add_segment( wxPoint( x2, y2 ) ); + return; + } + + if( da2 > bezier_cusp_limit ) + { + add_segment( wxPoint( x3, y3 ) ); + return; + } + } + } + break; + } + + // Continue subdivision + //---------------------- + recursive_bezier( x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1 ); + recursive_bezier( x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1 ); +} diff --git a/common/drawpanel.cpp b/common/drawpanel.cpp index 4c17aa233e..dad6806108 100644 --- a/common/drawpanel.cpp +++ b/common/drawpanel.cpp @@ -289,8 +289,8 @@ void WinEDA_DrawPanel::PostDirtyRect( EDA_Rect aRect ) // The pcb units have finer granularity than the pixels, so it can happen // that the rectangle is not large enough for the erase portion. - aRect.m_Size.x += 2; // += 1 is not enough! - aRect.m_Size.y += 2; + aRect.m_Size.x += 4; // += 1 is not enough! + aRect.m_Size.y += 4; // D( printf( "2) PostDirtyRect( x=%d, y=%d, width=%d, height=%d)\n", aRect.m_Pos.x, aRect.m_Pos.y, aRect.m_Size.x, aRect.m_Size.y ); ) diff --git a/common/gr_basic.cpp b/common/gr_basic.cpp index b2986fff95..4b29699801 100644 --- a/common/gr_basic.cpp +++ b/common/gr_basic.cpp @@ -10,6 +10,8 @@ #include "macros.h" #include "base_struct.h" #include "class_base_screen.h" +#include "bezier_curves.h" + #ifndef FILLED #define FILLED 1 @@ -33,7 +35,7 @@ /* variables generales */ -// pour les tracés en mode XOR = GR_XOR ou GR_NXOR selon couleur de fond +// pour les tracÈs en mode XOR = GR_XOR ou GR_NXOR selon couleur de fond int g_XorMode = GR_NXOR; // couleur de fond de la frame de dessin int g_DrawBgColor = WHITE; @@ -364,7 +366,7 @@ bool GetGRForceBlackPenState( void ) void GRSetDrawMode( wxDC* DC, int draw_mode ) { if( draw_mode & GR_OR ) -#if defined(__WXMAC__) && wxMAC_USE_CORE_GRAPHICS +#if defined(__WXMAC__) && (wxMAC_USE_CORE_GRAPHICS || wxCHECK_VERSION(2,9,0) ) DC->SetLogicalFunction( wxCOPY ); #else DC->SetLogicalFunction( wxOR ); @@ -372,7 +374,7 @@ void GRSetDrawMode( wxDC* DC, int draw_mode ) else if( draw_mode & GR_XOR ) DC->SetLogicalFunction( wxXOR ); else if( draw_mode & GR_NXOR ) -#if defined (__WXMAC__) && wxMAC_USE_CORE_GRAPHICS +#if defined (__WXMAC__) && (wxMAC_USE_CORE_GRAPHICS || wxCHECK_VERSION(2,9,0) ) DC->SetLogicalFunction( wxXOR ); #else DC->SetLogicalFunction( wxEQUIV ); @@ -1497,3 +1499,36 @@ void ClipAndDrawFilledPoly( EDA_Rect* aClipBox, wxDC* aDC, wxPoint aPoints[], in aDC->DrawPolygon( clippedPolygon.size(), &clippedPolygon[0] ); } #endif + +void GRBezier( EDA_Rect* ClipBox, + wxDC* DC, + int x1, + int y1, + int x2, + int y2, + int x3, + int y3, + int width, + int Color ) +{ + std::vector Points = Bezier2Poly( x1, y1, x2, y2, x3, y3 ); + GRPoly( ClipBox, DC, Points.size(), &Points[0], false, width, Color, 0 ); +} + + +void GRBezier( EDA_Rect* ClipBox, + wxDC* DC, + int x1, + int y1, + int x2, + int y2, + int x3, + int y3, + int x4, + int y4, + int width, + int Color ) +{ + std::vector Points = Bezier2Poly( x1, y1, x2, y2, x3, y3, x4, y4 ); + GRPoly( ClipBox, DC, Points.size(), &Points[0], false, width, Color, 0 ); +} diff --git a/eeschema/build_BOM.cpp b/eeschema/build_BOM.cpp index d79613a622..b737bae0a7 100644 --- a/eeschema/build_BOM.cpp +++ b/eeschema/build_BOM.cpp @@ -515,7 +515,7 @@ void DIALOG_BUILD_BOM::PrintFieldData( FILE* f, SCH_COMPONENT* DrawLibItem, /*******************************************************************************************/ { // @todo make this variable length - static const wxCheckBox* FieldListCtrl[] = { + const wxCheckBox* FieldListCtrl[] = { m_AddField1, m_AddField2, m_AddField3, @@ -586,7 +586,7 @@ int DIALOG_BUILD_BOM::PrintComponentsListByRef( if( CompactForm ) { // @todo make this variable length - static const wxCheckBox* FieldListCtrl[FIELD8 - FIELD1 + 1] = { + const wxCheckBox* FieldListCtrl[FIELD8 - FIELD1 + 1] = { m_AddField1, m_AddField2, m_AddField3, diff --git a/eeschema/classes_body_items.cpp b/eeschema/classes_body_items.cpp index f73819de74..a2446118d8 100644 --- a/eeschema/classes_body_items.cpp +++ b/eeschema/classes_body_items.cpp @@ -8,6 +8,7 @@ #include "class_drawpanel.h" #include "drawtxt.h" #include "trigo.h" +#include "bezier_curves.h" #include "program.h" #include "libcmp.h" @@ -1104,3 +1105,234 @@ void LibDrawPolyline::DisplayInfo( WinEDA_DrawFrame* frame ) frame->MsgPanel->Affiche_1_Parametre( 40, _( "Bounding box" ), msg, BROWN ); } + +/***************************/ +/** class LibDrawBezier **/ +/***************************/ +LibDrawBezier::LibDrawBezier( EDA_LibComponentStruct* aParent ) : + LibEDA_BaseStruct( COMPONENT_BEZIER_DRAW_TYPE, aParent ) +{ + m_Fill = NO_FILL; + m_Width = 0; + m_typeName = _( "Bezier" ); +} + + +bool LibDrawBezier::Save( FILE* ExportFile ) const +{ + int ccount = GetCornerCount(); + + fprintf( ExportFile, "B %d %d %d %d", ccount, m_Unit, m_Convert, m_Width ); + + for( unsigned i = 0; i < GetCornerCount(); i++ ) + { + fprintf( ExportFile, " %d %d", m_BezierPoints[i].x, m_BezierPoints[i].y ); + } + + fprintf( ExportFile, " %c\n", fill_tab[m_Fill] ); + + return true; +} + + +bool LibDrawBezier::Load( char* line, wxString& errorMsg ) +{ + char* p; + int i, ccount = 0; + wxPoint pt; + + i = sscanf( &line[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert, + &m_Width ); + + if( i !=4 ) + { + errorMsg.Printf( _( "Bezier only had %d parameters of the required 4" ), i ); + return false; + } + if( ccount <= 0 ) + { + errorMsg.Printf( _( "Bezier count parameter %d is invalid" ), + ccount ); + return false; + } + + p = strtok( &line[2], " \t\n" ); + p = strtok( NULL, " \t\n" ); + p = strtok( NULL, " \t\n" ); + p = strtok( NULL, " \t\n" ); + + for( i = 0; i < ccount; i++ ) + { + wxPoint point; + p = strtok( NULL, " \t\n" ); + if( sscanf( p, "%d", &pt.x ) != 1 ) + { + errorMsg.Printf( _( "Bezier point %d X position not defined" ), + i ); + return false; + } + p = strtok( NULL, " \t\n" ); + if( sscanf( p, "%d", &pt.y ) != 1 ) + { + errorMsg.Printf( _( "Bezier point %d Y position not defined" ), + i ); + return false; + } + m_BezierPoints.push_back( pt ); + } + + m_Fill = NO_FILL; + + if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) + { + if( p[0] == 'F' ) + m_Fill = FILLED_SHAPE; + if( p[0] == 'f' ) + m_Fill = FILLED_WITH_BG_BODYCOLOR; + } + + return true; +} + + +LibDrawBezier* LibDrawBezier::GenCopy() +{ + LibDrawBezier* newitem = new LibDrawBezier(GetParent()); + + newitem->m_BezierPoints = m_BezierPoints; // Vector copy + newitem->m_Width = m_Width; + newitem->m_Unit = m_Unit; + newitem->m_Convert = m_Convert; + newitem->m_Flags = m_Flags; + newitem->m_Fill = m_Fill; + return newitem; +} + +void LibDrawBezier::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, + const wxPoint& aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) +{ + wxPoint pos1; + std::vector PolyPointsTraslated; + + int color = ReturnLayerColor( LAYER_DEVICE ); + int linewidth = (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; + + m_PolyPoints = Bezier2Poly( m_BezierPoints[0] , + m_BezierPoints[1] , + m_BezierPoints[2] , + m_BezierPoints[3]); + + PolyPointsTraslated.clear(); + for( unsigned int i = 0; i < m_PolyPoints.size() ; i++) + PolyPointsTraslated.push_back( TransformCoordinate( aTransformMatrix, m_PolyPoints[i] ) + aOffset); + + if( aColor < 0 ) // Used normal color or selected color + { + if( m_Selected & IS_SELECTED ) + color = g_ItemSelectetColor; + } + else + color = aColor; + + FILL_T fill = aData ? NO_FILL : m_Fill; + if( aColor >= 0 ) + fill = NO_FILL; + + if( fill == FILLED_WITH_BG_BODYCOLOR ) + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + &PolyPointsTraslated[0], 1, linewidth, color, + ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + else if( fill == FILLED_SHAPE ) + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + &PolyPointsTraslated[0], 1, linewidth, color, color ); + else + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + &PolyPointsTraslated[0], 0, linewidth, color, color ); + +} + + +/** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPos A wxPoint to test + * @return bool - true if a hit, else false + */ +bool LibDrawBezier::HitTest( const wxPoint& aRefPos ) +{ + int mindist = m_Width ? m_Width /2 : g_DrawDefaultLineThickness / 2; + // Have a minimal tolerance for hit test + if ( mindist < 3 ) + mindist = 3; // = 3 mils + return HitTest( aRefPos, mindist, DefaultTransformMatrix ); +} + +/** Function HitTest + * @return true if the point aPosRef is near a segment + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + */ +bool LibDrawBezier::HitTest( wxPoint aPosRef, int aThreshold, + const int aTransMat[2][2] ) +{ + wxPoint ref, start, end; + + for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) + { + start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] ); + end = TransformCoordinate( aTransMat, m_PolyPoints[ii] ); + if ( TestSegmentHit( aPosRef, start, end, aThreshold ) ) + return true; + } + + return false; +} + + +/** Function GetBoundingBox + * @return the boundary box for this, in library coordinates + */ +EDA_Rect LibDrawBezier::GetBoundingBox() +{ + EDA_Rect rect; + int xmin, xmax, ymin, ymax; + if(!GetCornerCount()) + return rect; + xmin = xmax = m_PolyPoints[0].x; + ymin = ymax = m_PolyPoints[0].y; + + for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) + { + xmin = MIN( xmin, m_PolyPoints[ii].x ); + xmax = MAX( xmax, m_PolyPoints[ii].x ); + ymin = MIN( ymin, m_PolyPoints[ii].y ); + ymax = MAX( ymax, m_PolyPoints[ii].y ); + } + + rect.SetOrigin( xmin, ymin * -1 ); + rect.SetEnd( xmax, ymax * -1 ); + rect.Inflate( m_Width / 2, m_Width / 2 ); + + return rect; +} + + +void LibDrawBezier::DisplayInfo( WinEDA_DrawFrame* frame ) +{ + wxString msg; + EDA_Rect bBox = GetBoundingBox(); + + LibEDA_BaseStruct::DisplayInfo( frame ); + + msg = ReturnStringFromValue( g_UnitMetric, m_Width, + EESCHEMA_INTERNAL_UNIT, true ); + + frame->MsgPanel->Affiche_1_Parametre( 20, _( "Line width" ), msg, BLUE ); + + msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, + bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); + + frame->MsgPanel->Affiche_1_Parametre( 40, _( "Bounding box" ), msg, BROWN ); +} diff --git a/eeschema/classes_body_items.h b/eeschema/classes_body_items.h index c985839485..d34f07a7e7 100644 --- a/eeschema/classes_body_items.h +++ b/eeschema/classes_body_items.h @@ -658,4 +658,70 @@ public: virtual void DisplayInfo( WinEDA_DrawFrame* frame ); }; +/**********************************************************/ +/* Graphic Body Item: Bezier Curve (set of lines) */ +/**********************************************************/ +class LibDrawBezier : public LibEDA_BaseStruct + { + public: + int m_Width; /* Line width */ + std::vector m_BezierPoints; // list of parameter (3|4) + std::vector m_PolyPoints; // list of points (>= 2) + + public: + LibDrawBezier(EDA_LibComponentStruct * aParent); + ~LibDrawBezier() { } + + virtual wxString GetClass() const + { + return wxT( "LibDrawBezier" ); + } + + + /** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" + * format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ + virtual bool Save( FILE* aFile ) const; + virtual bool Load( char* line, wxString& errorMsg ); + + LibDrawBezier* GenCopy(); + void AddPoint( const wxPoint& point ); + + /** Function GetCornerCount + * @return the number of corners + */ + unsigned GetCornerCount() const { return m_PolyPoints.size(); } + + /** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPos A wxPoint to test + * @return bool - true if a hit, else false + */ + virtual bool HitTest( const wxPoint& aRefPos ); + + /** Function HitTest + * @return true if the point aPosRef is near a segment + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ); + + /** Function GetBoundingBox + * @return the boundary box for this, in library coordinates + */ + virtual EDA_Rect GetBoundingBox(); + + void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual void DisplayInfo( WinEDA_DrawFrame* frame ); + }; + #endif // CLASSES_BODY_ITEMS_H diff --git a/eeschema/eelibs_read_libraryfiles.cpp b/eeschema/eelibs_read_libraryfiles.cpp index 5a3d539ff2..82d3ada128 100644 --- a/eeschema/eelibs_read_libraryfiles.cpp +++ b/eeschema/eelibs_read_libraryfiles.cpp @@ -594,6 +594,11 @@ static LibEDA_BaseStruct* ReadDrawEntryItemDescription (EDA_LibComponentStruct* entryLoaded = New->Load( Line, errorMsg ); break; + case 'B': /* Bezier */ + New = ( LibEDA_BaseStruct* ) new LibDrawBezier(aParent); + entryLoaded = New->Load( Line, errorMsg ); + break; + default: MsgLine.Printf( wxT( "Undefined DRAW command in line %d\n%s, aborted." ), *LineNum, Line ); diff --git a/eeschema/locate.cpp b/eeschema/locate.cpp index 0a10c8950c..bd887e4374 100644 --- a/eeschema/locate.cpp +++ b/eeschema/locate.cpp @@ -717,6 +717,13 @@ LibEDA_BaseStruct* LocateDrawItem( SCH_SCREEN* Screen, return DrawItem; break; + case COMPONENT_BEZIER_DRAW_TYPE: + if( (masque & LOCATE_COMPONENT_POLYLINE_DRAW_TYPE) == 0 ) + break; + if( DrawItem->HitTest( aRefPoint ) ) + return DrawItem; + break; + case COMPONENT_LINE_DRAW_TYPE: if( (masque & LOCATE_COMPONENT_LINE_DRAW_TYPE) == 0 ) break; diff --git a/eeschema/plot.cpp b/eeschema/plot.cpp index d2c1eaad8c..97295bcff4 100644 --- a/eeschema/plot.cpp +++ b/eeschema/plot.cpp @@ -347,6 +347,29 @@ void PlotLibPart( SCH_COMPONENT* DrawLibItem ) } break; + case COMPONENT_BEZIER_DRAW_TYPE: + { + LibDrawBezier* polyline = (LibDrawBezier*) DEntry; + Poly = (int*) MyMalloc( sizeof(int) * 2 * polyline->GetCornerCount() ); + for( ii = 0; ii < (int) polyline->GetCornerCount(); ii++ ) + { + pos = polyline->m_PolyPoints[ii]; + pos = TransformCoordinate( TransMat, pos ) + DrawLibItem->m_Pos; + Poly[ii * 2] = pos.x; + Poly[ii * 2 + 1] = pos.y; + } + + if( draw_bgfill && polyline->m_Fill == FILLED_WITH_BG_BODYCOLOR ) + { + SetColorMapPS( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + PlotPoly( ii, Poly, true, 0 ); + } + if( (g_PlotFormat == PLOT_FORMAT_POST) && g_PlotPSColorOpt ) + SetColorMapPS( ReturnLayerColor( LAYER_DEVICE ) ); + PlotPoly( ii, Poly, polyline->m_Fill == FILLED_SHAPE ? true : false, polyline->m_Width ); + MyFree( Poly ); + } + default: D( printf( "Drawing Type=%d\n", DEntry->Type() ) ); } diff --git a/eeschema/savelib.cpp b/eeschema/savelib.cpp index 9c6640e0e8..050da853f4 100644 --- a/eeschema/savelib.cpp +++ b/eeschema/savelib.cpp @@ -60,6 +60,10 @@ LibEDA_BaseStruct* CopyDrawEntryStruct( wxWindow* frame, NewDrawItem = ( (LibDrawPolyline*) DrawItem )->GenCopy(); break; + case COMPONENT_BEZIER_DRAW_TYPE: + NewDrawItem = ( (LibDrawBezier*) DrawItem )->GenCopy(); + break; + default: msg.Printf( wxT( "CopyDrawLibEntryStruct: unknown Draw Type %d" ), DrawItem->Type() ); diff --git a/include/base_struct.h b/include/base_struct.h index be077a4a76..d4ae10692c 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -77,6 +77,7 @@ enum KICAD_T { COMPONENT_LINE_DRAW_TYPE, COMPONENT_PIN_DRAW_TYPE, COMPONENT_FIELD_DRAW_TYPE, + COMPONENT_BEZIER_DRAW_TYPE, // End value MAX_STRUCT_TYPE_ID diff --git a/include/bezier_curves.h b/include/bezier_curves.h new file mode 100644 index 0000000000..688cd27375 --- /dev/null +++ b/include/bezier_curves.h @@ -0,0 +1,13 @@ +#ifndef BEZIER_CURVES_H +#define BEZIER_CURVES_H + +#include + +std::vector Bezier2Poly(wxPoint c1, wxPoint c2, wxPoint c3); +std::vector Bezier2Poly(wxPoint c1, wxPoint c2, wxPoint c3,wxPoint c4); + +std::vector Bezier2Poly(int x1, int y1, int x2, int y2, int x3, int y3); +std::vector Bezier2Poly(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4); + + +#endif // BEZIER_CURVES_H diff --git a/include/board_item_struct.h b/include/board_item_struct.h index ad8e0cf7ab..25723ec955 100644 --- a/include/board_item_struct.h +++ b/include/board_item_struct.h @@ -19,7 +19,8 @@ enum Track_Shapes { S_SPOT_OVALE, /* Oblong spot (for GERBER)*/ S_SPOT_CIRCLE, /* rounded spot (for GERBER)*/ S_SPOT_RECT, /* Rectangular spott (for GERBER)*/ - S_POLYGON /* polygonal shape */ + S_POLYGON, /* polygonal shape */ + S_CURVE /* Bezier Curve*/ }; diff --git a/include/gr_basic.h b/include/gr_basic.h index 7a00df6f31..76cd560a05 100644 --- a/include/gr_basic.h +++ b/include/gr_basic.h @@ -6,8 +6,7 @@ #define GR_BASIC #include "colors.h" - - +#include class EDA_Rect; @@ -86,6 +85,8 @@ void GRSLineRel(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int width, int Colo void GRPoly(EDA_Rect * ClipBox, wxDC * DC, int n, wxPoint Points[], bool Fill, int width, int Color, int BgColor); +void GRBezier(EDA_Rect* ClipBox, wxDC* DC,int x1, int y1, int x2, int y2, int x3, int y3,int width, int Color); +void GRBezier(EDA_Rect* ClipBox, wxDC* DC,int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,int width, int Color); /** * Function GRClosedPoly diff --git a/include/wxstruct.h b/include/wxstruct.h index 80ad0369af..e8ba012956 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -9,7 +9,6 @@ #include - #include #include "wx/log.h" #include "wx/config.h" diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp index e1d75e8e99..9f911971a9 100644 --- a/pcbnew/class_board_item.cpp +++ b/pcbnew/class_board_item.cpp @@ -24,6 +24,7 @@ wxString BOARD_ITEM::ShowShape( Track_Shapes aShape ) case S_RECT: return _( "Rect" ); case S_ARC: return _( "Arc" ); case S_CIRCLE: return _( "Circle" ); + case S_CURVE: return _( "Bezier Curve" ); // used in Gerbview: case S_ARC_RECT: return wxT( "arc_rect" ); diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 332473f8e7..93f7d9c464 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -5,6 +5,7 @@ #include "fctsys.h" #include "wxstruct.h" #include "gr_basic.h" +#include "bezier_curves.h" #include "common.h" #include "class_drawpanel.h" #include "kicad_string.h" @@ -39,6 +40,8 @@ void DRAWSEGMENT::Copy( DRAWSEGMENT* source ) m_Shape = source->m_Shape; m_Angle = source->m_Angle; m_TimeStamp = source->m_TimeStamp; + m_BezierC1 = source->m_BezierC1; + m_BezierC2 = source->m_BezierC1; } @@ -56,10 +59,17 @@ bool DRAWSEGMENT::Save( FILE* aFile ) const m_Shape, m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width ); - - fprintf( aFile, "De %d %d %d %lX %X\n", - m_Layer, m_Type, m_Angle, - m_TimeStamp, ReturnStatus() ); + if( m_Type != S_CURVE) { + fprintf( aFile, "De %d %d %d %lX %X\n", + m_Layer, m_Type, m_Angle, + m_TimeStamp, ReturnStatus() ); + } else { + fprintf( aFile, "De %d %d %d %lX %X %d %d %d %d\n", + m_Layer, m_Type, m_Angle, + m_TimeStamp, ReturnStatus(), + m_BezierC1.x,m_BezierC1.y, + m_BezierC2.x,m_BezierC2.y); + } if( fprintf( aFile, "$EndDRAWSEGMENT\n" ) != sizeof("$EndDRAWSEGMENT\n") - 1 ) goto out; @@ -96,9 +106,44 @@ bool DRAWSEGMENT::ReadDrawSegmentDescr( FILE* File, int* LineNum ) if( Line[0] == 'D' ) { int status; - sscanf( Line + 2, " %d %d %d %lX %X", - &m_Layer, &m_Type, &m_Angle, - &m_TimeStamp, &status ); + char* token=0; + + token = strtok(Line," "); + + for(int i=0; (token = strtok(NULL," ")) != NULL; i++){ + switch(i){ + case 0: + sscanf(token,"%d",&m_Layer); + break; + case 1: + sscanf(token,"%d",&m_Type); + break; + case 2: + sscanf(token,"%d",&m_Angle); + break; + case 3: + sscanf(token,"%lX",&m_TimeStamp); + break; + case 4: + sscanf(token,"%X",&status); + break; + /* Bezier Control Points*/ + case 5: + sscanf(token,"%d",&m_BezierC1.x); + break; + case 6: + sscanf(token,"%d",&m_BezierC1.y); + break; + case 7: + sscanf(token,"%d",&m_BezierC2.x); + break; + case 8: + sscanf(token,"%d",&m_BezierC2.y); + break; + default: + break; + } + } if( m_Layer < FIRST_NO_COPPER_LAYER ) m_Layer = FIRST_NO_COPPER_LAYER; @@ -235,7 +280,30 @@ void DRAWSEGMENT::Draw( WinEDA_DrawPanel* panel, wxDC* DC, rayon, m_Width, color ); } break; + case S_CURVE: + m_BezierPoints = Bezier2Poly(m_Start,m_BezierC1, m_BezierC2, m_End); + for (unsigned int i=1; i < m_BezierPoints.size(); i++) { + if( mode == FILAIRE ) + GRLine( &panel->m_ClipBox, DC, + m_BezierPoints[i].x, m_BezierPoints[i].y, + m_BezierPoints[i-1].x, m_BezierPoints[i-1].y, 0, color ); + else if( mode == SKETCH ) + { + GRCSegm( &panel->m_ClipBox, DC, + m_BezierPoints[i].x, m_BezierPoints[i].y, + m_BezierPoints[i-1].x, m_BezierPoints[i-1].y, + m_Width, color ); + } + else + { + GRFillCSegm( &panel->m_ClipBox, DC, + m_BezierPoints[i].x, m_BezierPoints[i].y, + m_BezierPoints[i-1].x, m_BezierPoints[i-1].y, + m_Width, color ); + } + } + break; default: if( mode == FILAIRE ) GRLine( &panel->m_ClipBox, DC, ux0, uy0, dx, dy, 0, color ); @@ -274,19 +342,24 @@ void DRAWSEGMENT::DisplayInfo( WinEDA_DrawFrame* frame ) wxString shape = _( "Shape" ); - if( m_Shape == S_CIRCLE ) - Affiche_1_Parametre( frame, 10, shape, _( "Circle" ), RED ); + switch( m_Shape ) { + case S_CIRCLE: + Affiche_1_Parametre( frame, 10, shape, _( "Circle" ), RED ); + break; - else if( m_Shape == S_ARC ) - { - Affiche_1_Parametre( frame, 10, shape, _( "Arc" ), RED ); + case S_ARC: + Affiche_1_Parametre( frame, 10, shape, _( "Arc" ), RED ); - msg.Printf( wxT( "%d.%d" ), m_Angle/10, m_Angle % 10 ); - Affiche_1_Parametre( frame, 18, _("Angle"), msg, RED ); + msg.Printf( wxT( "%d.%d" ), m_Angle/10, m_Angle % 10 ); + Affiche_1_Parametre( frame, 18, _("Angle"), msg, RED ); + break; + case S_CURVE: + Affiche_1_Parametre( frame, 10, shape, _( "Curve" ), RED ); + break; + + default: + Affiche_1_Parametre( frame, 10, shape, _( "Segment" ), RED ); } - else - Affiche_1_Parametre( frame, 10, shape, _( "Segment" ), RED ); - wxString start; start << GetStart(); @@ -322,37 +395,46 @@ bool DRAWSEGMENT::HitTest( const wxPoint& ref_pos ) int spot_cX = ref_pos.x - ux0; int spot_cY = ref_pos.y - uy0; - if( m_Shape==S_CIRCLE || m_Shape==S_ARC ) - { - int rayon, dist, stAngle, endAngle, mouseAngle; + switch(m_Shape){ + case S_CIRCLE: + case S_ARC: - rayon = (int) hypot( (double) (dx), (double) (dy) ); - dist = (int) hypot( (double) (spot_cX), (double) (spot_cY) ); + int rayon, dist, stAngle, endAngle, mouseAngle; - if( abs( rayon - dist ) <= ( m_Width / 2 ) ) - { - if( m_Shape == S_CIRCLE ) - return true; + rayon = (int) hypot( (double) (dx), (double) (dy) ); + dist = (int) hypot( (double) (spot_cX), (double) (spot_cY) ); - /* pour un arc, controle complementaire */ - mouseAngle = (int) ArcTangente( spot_cY, spot_cX ); - stAngle = (int) ArcTangente( dy, dx ); - endAngle = stAngle + m_Angle; - - if( endAngle > 3600 ) + if( abs( rayon - dist ) <= ( m_Width / 2 ) ) { - stAngle -= 3600; - endAngle -= 3600; - } + if( m_Shape == S_CIRCLE ) + return true; - if( mouseAngle >= stAngle && mouseAngle <= endAngle ) + /* pour un arc, controle complementaire */ + mouseAngle = (int) ArcTangente( spot_cY, spot_cX ); + stAngle = (int) ArcTangente( dy, dx ); + endAngle = stAngle + m_Angle; + + if( endAngle > 3600 ) + { + stAngle -= 3600; + endAngle -= 3600; + } + + if( mouseAngle >= stAngle && mouseAngle <= endAngle ) + return true; + } + break; + + case S_CURVE: + for( unsigned int i= 1; i < m_BezierPoints.size(); i++) + { + if( TestSegmentHit( ref_pos,m_BezierPoints[i-1],m_BezierPoints[i-1], m_Width / 2 ) ) + return true; + } + break; + default: + if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) ) return true; - } - } - else - { - if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) ) - return true; } return false; } diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index ee96c51d6e..82e269a3bd 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -15,7 +15,10 @@ public: int m_Shape; // Shape: line, Circle, Arc int m_Type; // Used in complex associations ( Dimensions.. ) int m_Angle; // Used only for Arcs: Arc angle in 1/10 deg + wxPoint m_BezierC1; // Bezier Control Point 1 + wxPoint m_BezierC2; // Bezier Control Point 1 + std::vector m_BezierPoints; public: DRAWSEGMENT( BOARD_ITEM* aParent, KICAD_T idtype = TYPE_DRAWSEGMENT ); ~DRAWSEGMENT(); diff --git a/pcbnew/class_pad_draw_functions.cpp b/pcbnew/class_pad_draw_functions.cpp index ffcfd190ef..2a3e2d2fc1 100644 --- a/pcbnew/class_pad_draw_functions.cpp +++ b/pcbnew/class_pad_draw_functions.cpp @@ -46,8 +46,8 @@ void D_PAD::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin if( frame->m_DisplayPadFill == FILLED ) fillpad = 1; -#ifdef PCBNEW - if( m_Flags & IS_MOVED ) +#if defined(PCBNEW) || defined(__WXMAC__) + if( m_Flags & IS_MOVED || !DisplayOpt.DisplayPadFill ) fillpad = 0; #endif diff --git a/pcbnew/cotation.cpp b/pcbnew/cotation.cpp index 5a80113bc7..6047cba07d 100644 --- a/pcbnew/cotation.cpp +++ b/pcbnew/cotation.cpp @@ -348,6 +348,8 @@ void WinEDA_PcbFrame::Install_Edit_Cotation( COTATION* Cotation, WinEDA_CotationPropertiesFrame* frame = new WinEDA_CotationPropertiesFrame( this, Cotation, DC, pos ); + + Ajuste_Details_Cotation( Cotation ); frame->ShowModal(); frame->Destroy(); } diff --git a/pcbnew/modules.cpp b/pcbnew/modules.cpp index 4946557fa6..6eb10745fe 100644 --- a/pcbnew/modules.cpp +++ b/pcbnew/modules.cpp @@ -787,8 +787,11 @@ void DrawModuleOutlines( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* module ) if( g_Show_Pads_Module_in_Move ) { pad_fill_tmp = DisplayOpt.DisplayPadFill; +#ifndef __WXMAC__ DisplayOpt.DisplayPadFill = true; /* Trace en SKETCH en deplacement */ - +#else + DisplayOpt.DisplayPadFill = false; +#endif pt_pad = module->m_Pads; for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) { diff --git a/pcbnew/plot_rtn.cpp b/pcbnew/plot_rtn.cpp index 9476ad7e5f..61b38ae5bf 100644 --- a/pcbnew/plot_rtn.cpp +++ b/pcbnew/plot_rtn.cpp @@ -753,32 +753,69 @@ void PlotDrawSegment( DRAWSEGMENT* pt_segm, int Format, int masque_layer ) { case PLOT_FORMAT_GERBER: SelectD_CODE_For_LineDraw( thickness ); - if( pt_segm->m_Shape == S_CIRCLE ) - PlotCircle( PLOT_FORMAT_GERBER, thickness, start, radius ); - else if( pt_segm->m_Shape == S_ARC ) - PlotArc( PLOT_FORMAT_GERBER, start, + + switch(pt_segm->m_Shape) + { + case S_CIRCLE: + PlotCircle( PLOT_FORMAT_GERBER, thickness, start, radius ); + break; + + case S_ARC: + PlotArc( PLOT_FORMAT_GERBER, start, StAngle, EndAngle, radius, thickness ); - else - PlotGERBERLine( start, end, thickness ); - break; + break; + case S_CURVE: + for (unsigned int i=1; i < pt_segm->m_BezierPoints.size(); i++) { + PlotGERBERLine( pt_segm->m_BezierPoints[i-1], pt_segm->m_BezierPoints[i], thickness); + } + break; + default: + PlotGERBERLine( start, end, thickness ); + } + break; case PLOT_FORMAT_HPGL: - if( pt_segm->m_Shape == S_CIRCLE ) - PlotCircle( PLOT_FORMAT_HPGL, thickness, start, radius ); - else if( pt_segm->m_Shape == S_ARC ) - PlotArc( PLOT_FORMAT_HPGL, start, StAngle, EndAngle, radius, thickness ); - else - Plot_Filled_Segment_HPGL( start, end, thickness, (GRFillMode) g_Plot_Mode ); - break; + switch(pt_segm->m_Shape) + { + case S_CIRCLE: + PlotCircle( PLOT_FORMAT_HPGL, thickness, start, radius ); + break; + + case S_ARC: + PlotArc( PLOT_FORMAT_HPGL, start, StAngle, EndAngle, radius, thickness ); + break; + + case S_CURVE: + for (unsigned int i=1; i < pt_segm->m_BezierPoints.size(); i++) { + Plot_Filled_Segment_HPGL( pt_segm->m_BezierPoints[i-1], pt_segm->m_BezierPoints[i], thickness,(GRFillMode) g_Plot_Mode); + } + break; + default: + Plot_Filled_Segment_HPGL( start, end, thickness, (GRFillMode) g_Plot_Mode ); + } + break; case PLOT_FORMAT_POST: - if( pt_segm->m_Shape == S_CIRCLE ) - PlotCircle( PLOT_FORMAT_POST, thickness, start, radius ); - else if( pt_segm->m_Shape == S_ARC ) - PlotArc( PLOT_FORMAT_POST, start, + switch(pt_segm->m_Shape) + { + case S_CIRCLE: + PlotCircle( PLOT_FORMAT_POST, thickness, start, radius ); + break; + + case S_ARC: + PlotArc( PLOT_FORMAT_POST, start, StAngle, EndAngle, radius, thickness ); - else - PlotFilledSegmentPS( start, end, thickness ); + break; + + case S_CURVE: + for (unsigned int i=1; i < pt_segm->m_BezierPoints.size(); i++) { + PlotFilledSegmentPS( pt_segm->m_BezierPoints[i-1], pt_segm->m_BezierPoints[i], thickness); + } + break; + + default: + PlotFilledSegmentPS( start, end, thickness ); + } break; } } diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 2f5981e6af..669ca47b1b 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -9,11 +9,13 @@ #include "fctsys.h" #include "PolyLine.h" +#include "gr_basic.h" +#include "bezier_curves.h" using namespace std; -#define pi 3.14159265359 +#define pi M_PI CPolyLine::CPolyLine() { @@ -1571,3 +1573,21 @@ void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int n Close( STRAIGHT ); } + +// Bezier Support +void CPolyLine::AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3) { + std::vector bezier_points; + + bezier_points = Bezier2Poly(x1,y1,x2,y2,x3,y3); + for( unsigned int i = 0; i < bezier_points.size() ; i++) + AppendCorner( bezier_points[i].x, bezier_points[i].y); +} + +void CPolyLine::AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){ + std::vector bezier_points; + + bezier_points = Bezier2Poly(x1,y1,x2,y2,x3,y3,x4,y4); + for( unsigned int i = 0; i < bezier_points.size() ; i++) + AppendCorner( bezier_points[i].x, bezier_points[i].y); +} + diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index db0db68822..8f401695b2 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -243,6 +243,11 @@ public: private: Bool_Engine* m_Kbool_Poly_Engine; // polygons set in kbool engine data bool bDrawn; + + // Bezier Support +public: + void AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3); + void AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4); }; #endif // #ifndef POLYLINE_H