diff --git a/internat/fr/kicad.mo b/internat/fr/kicad.mo index 816ef82da5..7549a30944 100644 Binary files a/internat/fr/kicad.mo and b/internat/fr/kicad.mo differ diff --git a/internat/fr/kicad.po b/internat/fr/kicad.po index d586ce466e..d71f512c1c 100644 --- a/internat/fr/kicad.po +++ b/internat/fr/kicad.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: kicad\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-11-13 17:41+0100\n" -"PO-Revision-Date: 2009-11-13 17:47+0100\n" +"PO-Revision-Date: 2009-11-13 20:06+0100\n" "Last-Translator: \n" "Language-Team: kicad team \n" "MIME-Version: 1.0\n" @@ -286,7 +286,7 @@ msgstr "Inclure Modules" #: pcbnew/block.cpp:128 msgid "Include tracks" -msgstr "Inclure Pistes" +msgstr "Inclure pistes" #: pcbnew/block.cpp:133 msgid "Include zones" @@ -3183,6 +3183,8 @@ msgid "" "Set these values to 0\n" "to use Parent footprint or global values" msgstr "" +"Mettre ces valeurs à 0\n" +"pour utiliser les valeurs du module parent ou les valeurs globales" #: pcbnew/dialog_pad_properties_base.cpp:237 msgid "Net pad clearance" @@ -3936,7 +3938,7 @@ msgstr "NETCLASS: '%s' a une isolation:%s qui est moins que la valeur globale:%s #: pcbnew/drc.cpp:340 #, c-format msgid "NETCLASS: '%s' has TrackWidth:%s which is less than global:%s" -msgstr "" +msgstr "NETCLASS: '%s' a une largeur de piste: %s plust petite que la valeur globale:%s" #: pcbnew/drc.cpp:354 #, c-format @@ -4791,9 +4793,8 @@ msgid "Pads Mask Clearance" msgstr "Marge Masque des Pads" #: pcbnew/menubarpcb.cpp:232 -#, fuzzy msgid "Adjust the global clearance between pads and the solder resist mask" -msgstr "Ceci est l'espace entre pads et le masque" +msgstr "Ajuster la marge globale entre pads et le masque de vernis épargne" #: pcbnew/menubarpcb.cpp:242 msgid "Texts and Drawings" @@ -4990,7 +4991,7 @@ msgstr "<<<" #: pcbnew/dialog_design_rules_base.cpp:114 msgid "Move the selected nets in the right list to the left list" -msgstr "" +msgstr "Déplacer les nets sélectionnés de la liste droite vers la liste gauche" #: pcbnew/dialog_design_rules_base.cpp:118 msgid ">>>" @@ -5356,7 +5357,7 @@ msgstr "Valeurs locales pour marges sur masques:" #: pcbnew/dialog_edit_module_for_Modedit_base.cpp:116 #: pcbnew/dialog_edit_module_for_BoardEditor_base.cpp:145 msgid "Set these values to 0 to use global values" -msgstr "" +msgstr "Mettre ces valeurs à 0 pour utiliser les valeurs globales" #: pcbnew/dialog_edit_module_for_Modedit_base.cpp:127 #: pcbnew/dialog_edit_module_for_BoardEditor_base.cpp:156 @@ -8183,9 +8184,8 @@ msgid "Library browser" msgstr "Visualisateur des librairies" #: eeschema/tool_sch.cpp:58 -#, fuzzy msgid "Navigate schematic hierarchy" -msgstr "Sauver le Projet schématique" +msgstr "Navigateur de hiérarchie" #: eeschema/tool_sch.cpp:84 msgid "Print schematic" @@ -8212,9 +8212,8 @@ msgid "Schematic Electric Rules Check" msgstr "Contrôle des règles électriques" #: eeschema/tool_sch.cpp:129 -#, fuzzy msgid "Bill of material and/or Cross references" -msgstr "Liste des composants et références croisées" +msgstr "Liste des composants ou/et références croisées" #: eeschema/tool_sch.cpp:133 msgid "Backannotate footprint" @@ -8261,9 +8260,8 @@ msgid "Place hierarchical sheet" msgstr "Placer feuille hiérarchique" #: eeschema/tool_sch.cpp:215 -#, fuzzy msgid "Place a pin sheet, imported from the corresponding hierarchical label in sheet" -msgstr "Placer une pin hiérarchique, importée d'un un label hiérarchique dans la feuille." +msgstr "Placer une pin hiérarchique, importée du label hiérarchique correspondant dans la feuille." #: eeschema/tool_sch.cpp:220 msgid "Place hierarchical pin to sheet" @@ -10417,9 +10415,8 @@ msgid "&Configuration" msgstr "&Configuration" #: cvpcb/menucfg.cpp:49 -#, fuzzy msgid "Set libraries and library search paths" -msgstr "Librairie modules PCB %s non trouvée dans les chemins de recherche" +msgstr "Sélectionner les librairie et les chemins de recherche des librairies" #: cvpcb/menucfg.cpp:56 msgid "Keep Open On Save" diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 20d412a79a..e7e0239052 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -11,10 +11,11 @@ set(PCBNEW_SRCS automove.cpp autoplac.cpp autorout.cpp + board.cpp + board_items_to_polygon_shape_transform.cpp + board_undo_redo.cpp block.cpp block_module_editor.cpp - board.cpp - board_undo_redo.cpp build_BOM_from_board.cpp clean.cpp # cleaningoptions_dialog.cpp diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp new file mode 100644 index 0000000000..b3b20e7b82 --- /dev/null +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -0,0 +1,318 @@ +/**********************************************/ +/* board_items_to_polygon_shape_transform.cpp */ +/**********************************************/ + +/* Function to convert pads and tranck shapes to polygons + * Used to fill zones areas + */ +#include + +#include "fctsys.h" +#include "common.h" +#include "pcbnew.h" +#include "wxPcbStruct.h" +#include "trigo.h" + +/* Exported functions */ + +/** Function TransformRoundedEndsSegmentToPolygon + * convert a segment with rounded ends to a polygon + * Convert arcs to multiple straight lines + * @param aCornerBuffer = a buffer to store the polygon + * @param aStart = the segment start point coordinate + * @param aEnd = the segment end point coordinate + * @param aWidth = the segment width + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + */ +void TransformRoundedEndsSegmentToPolygon( std::vector & aCornerBuffer, + wxPoint aStart, wxPoint aEnd, + int aCircleToSegmentsCount, + int aWidth ); + + +/** Function TransformTrackWithClearanceToPolygon + * Convert the track shape to a closed polygon + * Used in filling zones calculations + * Circles (vias) and arcs (ends of tracks) are approximated by segments + * @param aCornerBuffer = a buffer to store the polygon + * @param aClearanceValue = the clearance around the pad + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aCorrectionFactor = the correction to apply to circles radius to keep + * clearance when the circle is approxiamted by segment bigger or equal + * to the real clearance value (usually near from 1.0) + */ +void TRACK::TransformTrackWithClearanceToPolygon( std::vector & aCornerBuffer, + int aClearanceValue, + int aCircleToSegmentsCount, + double aCorrectionFactor ) +{ + wxPoint corner_position; + int ii, angle; + int dx = (m_Width / 2) + aClearanceValue; + + int delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree + + switch( Type() ) + { + case TYPE_VIA: + dx = (int) ( dx * aCorrectionFactor ); + for( ii = 0; ii < aCircleToSegmentsCount; ii++ ) + { + corner_position = wxPoint( dx, 0 ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + angle = ii * delta; + RotatePoint( &corner_position, angle ); + corner_position += m_Start; + aCornerBuffer.push_back( corner_position ); + } + + break; + + default: + TransformRoundedEndsSegmentToPolygon( aCornerBuffer, + m_Start, m_End, aCircleToSegmentsCount, + m_Width + (2 * aClearanceValue) ); + break; + } +} + + +/* Function TransformRoundedEndsSegmentToPolygon + */ +void TransformRoundedEndsSegmentToPolygon( std::vector & aCornerBuffer, + wxPoint aStart, wxPoint aEnd, + int aCircleToSegmentsCount, + int aWidth ) +{ + int rayon = aWidth / 2; + wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) + wxPoint startp = aStart; + wxPoint corner; + int seg_len; + + // normalize the position in order to have endp.x >= 0; + if( endp.x < 0 ) + { + endp = aStart - aEnd; + startp = aEnd; + } + int delta_angle = ArcTangente( endp.y, endp.x ); // delta_angle is in 0.1 degrees + seg_len = (int) sqrt( ( (double) endp.y * endp.y ) + ( (double) endp.x * endp.x ) ); + + int delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree + + // Compute the outlines of the segment, and creates a polygon + corner = wxPoint( 0, rayon ); + RotatePoint( &corner, -delta_angle ); + corner += startp; + aCornerBuffer.push_back( corner ); + + corner = wxPoint( seg_len, rayon ); + RotatePoint( &corner, -delta_angle ); + corner += startp; + aCornerBuffer.push_back( corner ); + + // add right rounded end: + for( int ii = delta; ii < 1800; ii += delta ) + { + corner = wxPoint( 0, rayon ); + RotatePoint( &corner, ii ); + corner.x += seg_len; + RotatePoint( &corner, -delta_angle ); + corner += startp; + aCornerBuffer.push_back( corner ); + } + + corner = wxPoint( seg_len, -rayon ); + RotatePoint( &corner, -delta_angle ); + corner += startp; + aCornerBuffer.push_back( corner ); + + corner = wxPoint( 0, -rayon ); + RotatePoint( &corner, -delta_angle ); + corner += startp; + aCornerBuffer.push_back( corner ); + + // add left rounded end: + for( int ii = delta; ii < 1800; ii += delta ) + { + corner = wxPoint( 0, -rayon ); + RotatePoint( &corner, ii ); + RotatePoint( &corner, -delta_angle ); + corner += startp; + aCornerBuffer.push_back( corner ); + } +} + + +/** function TransformPadWithClearanceToPolygon + * Convert the pad shape to a closed polygon + * Used in filling zones calculations + * Circles and arcs are approximated by segments + * @param aCornerBuffer = a buffer to store the polygon + * @param aClearanceValue = the clearance around the pad + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aCorrectionFactor = the correction to apply to circles radius to keep + * clearance when the circle is approxiamted by segment bigger or equal + * to the real clearance value (usually near from 1.0) + */ +void D_PAD::TransformPadWithClearanceToPolygon( std::vector & aCornerBuffer, + int aClearanceValue, + int aCircleToSegmentsCount, + double aCorrectionFactor ) +{ + wxPoint corner_position; + int ii, angle; + int dx = (m_Size.x / 2) + aClearanceValue; + int dy = (m_Size.y / 2) + aClearanceValue; + + int delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree + wxPoint PadShapePos = ReturnShapePos(); /* Note: for pad having a shape offset, + * the pad position is NOT the shape position */ + wxSize psize = m_Size; /* pad size unsed in RECT and TRAPEZOIDAL pads + * trapezoidal pads are considered as rect pad shape having they boudary box size + */ + + switch( m_PadShape ) + { + case PAD_CIRCLE: + dx = (int) ( dx * aCorrectionFactor ); + for( ii = 0; ii < aCircleToSegmentsCount; ii++ ) + { + corner_position = wxPoint( dx, 0 ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); // Half increment offset to get more space between + angle = ii * delta; + RotatePoint( &corner_position, angle ); + corner_position += PadShapePos; + aCornerBuffer.push_back( corner_position ); + } + + break; + + case PAD_OVAL: + angle = m_Orient; + if( dy > dx ) // Oval pad X/Y ratio for choosing translation axles + { + dy = (int) ( dy * aCorrectionFactor ); + int angle_pg; // Polygon angle + wxPoint shape_offset = wxPoint( 0, (dy - dx) ); + RotatePoint( &shape_offset, angle ); // Rotating shape offset vector with component + + for( ii = 0; ii < aCircleToSegmentsCount / 2 + 1; ii++ ) // Half circle end cap... + { + corner_position = wxPoint( dx, 0 ); // Coordinate translation +dx + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + RotatePoint( &corner_position, angle ); + angle_pg = ii * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position += PadShapePos - shape_offset; + aCornerBuffer.push_back( corner_position ); + } + + for( ii = 0; ii < aCircleToSegmentsCount / 2 + 1; ii++ ) // Second half circle end cap... + { + corner_position = wxPoint( -dx, 0 ); // Coordinate translation -dx + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + RotatePoint( &corner_position, angle ); + angle_pg = ii * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position += PadShapePos + shape_offset; + aCornerBuffer.push_back( corner_position ); + } + + break; + } + else //if( dy <= dx ) + { + dx = (int) ( dx * aCorrectionFactor ); + int angle_pg; // Polygon angle + wxPoint shape_offset = wxPoint( (dy - dx), 0 ); + RotatePoint( &shape_offset, angle ); + + for( ii = 0; ii < aCircleToSegmentsCount / 2 + 1; ii++ ) + { + corner_position = wxPoint( 0, dy ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + RotatePoint( &corner_position, angle ); + angle_pg = ii * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position += PadShapePos - shape_offset; + aCornerBuffer.push_back( corner_position ); + } + + for( ii = 0; ii < aCircleToSegmentsCount / 2 + 1; ii++ ) + { + corner_position = wxPoint( 0, -dy ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + RotatePoint( &corner_position, angle ); + angle_pg = ii * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position += PadShapePos + shape_offset; + aCornerBuffer.push_back( corner_position ); + } + + break; + } + + default: + case PAD_TRAPEZOID: + psize.x += ABS( m_DeltaSize.y ); + psize.y += ABS( m_DeltaSize.x ); + + // fall through + case PAD_RECT: // Easy implementation for rectangular cutouts with rounded corners // Easy implementation for rectangular cutouts with rounded corners + angle = m_Orient; + int rounding_radius = (int) ( aClearanceValue * aCorrectionFactor ); // Corner rounding radius + int angle_pg; // Polygon increment angle + + for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ ) + { + corner_position = wxPoint( 0, -rounding_radius ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); // Start at half increment offset + angle_pg = i * delta; + RotatePoint( &corner_position, angle_pg ); // Rounding vector rotation + corner_position -= psize / 2; // Rounding vector + Pad corner offset + RotatePoint( &corner_position, angle ); // Rotate according to module orientation + corner_position += PadShapePos; // Shift origin to position + aCornerBuffer.push_back( corner_position ); + } + + for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ ) + { + corner_position = wxPoint( -rounding_radius, 0 ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + angle_pg = i * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position -= wxPoint( psize.x / 2, -psize.y / 2 ); + RotatePoint( &corner_position, angle ); + corner_position += PadShapePos; + aCornerBuffer.push_back( corner_position ); + } + + for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ ) + { + corner_position = wxPoint( 0, rounding_radius ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + angle_pg = i * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position += psize / 2; + RotatePoint( &corner_position, angle ); + corner_position += PadShapePos; + aCornerBuffer.push_back( corner_position ); + } + + for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ ) + { + corner_position = wxPoint( rounding_radius, 0 ); + RotatePoint( &corner_position, (1800 / aCircleToSegmentsCount) ); + angle_pg = i * delta; + RotatePoint( &corner_position, angle_pg ); + corner_position -= wxPoint( -psize.x / 2, psize.y / 2 ); + RotatePoint( &corner_position, angle ); + corner_position += PadShapePos; + aCornerBuffer.push_back( corner_position ); + } + + break; + } +} diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index c56e85e01b..7fd44774a1 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -141,6 +141,19 @@ public: m_Pos = aPos; } + /** function TransformPadWithClearanceToPolygon + * Convert the pad shape to a closed polygon + * Used in filling zones calculations + * Circles and arcs are approximated by segments + * @param aCornerBuffer = a buffer to store the polygon + * @param aClearanceValue = the clearance around the pad + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aCorrectionFactor = the correction to apply to circles radius to keep + * clearance when the circle is approxiamted by segment bigger or equal + * to the real clearance value (usually near from 1.0) + */ + void TransformPadWithClearanceToPolygon( std::vector & aCornerBuffer, + int aClearanceValue, int aCircleToSegmentsCount, double aCorrectionFactor ); /** * Function GetClearance diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index 04e2a0e15a..14100603c1 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -148,6 +148,21 @@ public: /* divers */ int Shape() const { return m_Shape & 0xFF; } + /** Function TransformTrackWithClearanceToPolygon + * Convert the track shape to a closed polygon + * Used in filling zones calculations + * Circles (vias) and arcs (ends of tracks) are approximated by segments + * @param aCornerBuffer = a buffer to store the polygon + * @param aClearanceValue = the clearance around the pad + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aCorrectionFactor = the correction to apply to circles radius to keep + * clearance when the circle is approxiamted by segment bigger or equal + * to the real clearance value (usually near from 1.0) + */ + void TransformTrackWithClearanceToPolygon( std::vector & aCornerBuffer, + int aClearanceValue, + int aCircleToSegmentsCount, + double aCorrectionFactor ); /** * Function SetDrillValue * Set the drill value for vias diff --git a/pcbnew/debug_kbool_key_file_fct.cpp b/pcbnew/debug_kbool_key_file_fct.cpp index d40440f9da..1dcd4d95c0 100644 --- a/pcbnew/debug_kbool_key_file_fct.cpp +++ b/pcbnew/debug_kbool_key_file_fct.cpp @@ -4,6 +4,7 @@ #include "fctsys.h" #include "common.h" +#include "kicad_string.h" #include "pcbnew.h" #include "wxPcbStruct.h" #include "zones.h" @@ -11,14 +12,22 @@ #include "debug_kbool_key_file_fct.h" -#ifdef CREATE_KBOOL_KEY_FILES +#if defined (CREATE_KBOOL_KEY_FILES) || (CREATE_KBOOL_KEY_FILES_FIRST_PASS) static FILE* kdebugFile; -static const char * sDate_Time = "2009-09-07 15:59:24"; +static char sDate_Time[256]; void CreateKeyFile() { + wxString datetimestr; + wxDateTime datetime = wxDateTime::Now(); + datetime.SetCountry( wxDateTime::Country_Default ); + datetimestr = datetime.FormatISODate( ) + + wxT(" ") + + datetime.FormatISOTime( ); + strcpy(sDate_Time, CONV_TO_UTF8(datetimestr) ); + kdebugFile = fopen( KEYFILE_FILENAME, "wt" ); if( kdebugFile ) { @@ -55,7 +64,7 @@ void CloseKeyFile() const char* sCurrEntityName = NULL; static int s_count; -void OpenEntity( const char* aName ) +void OpenKeyFileEntity( const char* aName ) { if( kdebugFile ) { @@ -69,21 +78,21 @@ void OpenEntity( const char* aName ) } -void CloseEntity() +void CloseKeyFileEntity() { if( kdebugFile ) fprintf( kdebugFile, "\nENDSTR %s;\n", sCurrEntityName ); } -void StartPolygon(int aCornersCount, int aLayer) +void StartKeyFilePolygon(int aCornersCount, int aLayer) { fprintf( kdebugFile, "\nBOUNDARY; LAYER %d; DATATYPE 0;\n", aLayer ); fprintf( kdebugFile, " XY %d;\n", aCornersCount ); s_count = 0; } -void EndElement() +void EndKeyFileElement() { if ( s_count == 1 ) fprintf( kdebugFile, "\n"); @@ -114,14 +123,14 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer } // write corners: - StartPolygon( count+1, aLayer ); + StartKeyFilePolygon( count+1, aLayer ); corner = &aZone->m_FilledPolysList[ic]; int startpointX = corner->x; int startpointY = corner->y; for( ; ic < corners_count; ic++ ) { corner = &aZone->m_FilledPolysList[ic]; - AddPointXY( corner->x, corner->y ); + AddKeyFilePointXY( corner->x, corner->y ); if( corner->end_contour ) { ic++; @@ -129,21 +138,19 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer } } // Close polygon: - AddPointXY( startpointX, startpointY ); - EndElement(); + AddKeyFilePointXY( startpointX, startpointY ); + EndKeyFileElement(); } } -void AddPointXY( int aXcoord, int aYcoord) +void AddKeyFilePointXY( int aXcoord, int aYcoord) { if ( s_count >= 2 ) { s_count = 0; fprintf( kdebugFile, "\n"); } - SetLocaleTo_C_standard(); fprintf( kdebugFile, " X %d; Y %d;", aXcoord, aYcoord ); - SetLocaleTo_Default( ); s_count ++; } diff --git a/pcbnew/debug_kbool_key_file_fct.h b/pcbnew/debug_kbool_key_file_fct.h index f4519a03d0..0fee97983a 100644 --- a/pcbnew/debug_kbool_key_file_fct.h +++ b/pcbnew/debug_kbool_key_file_fct.h @@ -4,17 +4,18 @@ #ifndef _DEBUG_KBOOL_KEY_FILE_FCT_H_ #define _DEBUG_KBOOL_KEY_FILE_FCT_H_ -/* This line must be uncommented only if you wan to produce a file -* to debug kbool +/* These line must be uncommented only if you want to produce a file +* to debug kbool in zone filling algorithms */ -//#define CREATE_KBOOL_KEY_FILES +//#define CREATE_KBOOL_KEY_FILES_FIRST_PASS 1 +//#define CREATE_KBOOL_KEY_FILES 1 -#ifdef CREATE_KBOOL_KEY_FILES +#if defined (CREATE_KBOOL_KEY_FILES) || (CREATE_KBOOL_KEY_FILES_FIRST_PASS) -// Allows or not) 0 degree orientation thermal shapes, for kbool tests +// Allows (or not) 0 degree orientation thermal shapes, for kbool tests //#define CREATE_KBOOL_KEY_FILES_WITH_0_DEG -#define KEYFILE_FILENAME "dbgfile.key" +#define KEYFILE_FILENAME "pcbnew_dbgfile.key" /** function CreateKeyFile * open KEYFILE_FILENAME file @@ -29,17 +30,17 @@ void CloseKeyFile(); /* create header to start an entity description */ -void OpenEntity(const char * aName); +void OpenKeyFileEntity(const char * aName); /* close the entity description */ -void CloseEntity(); +void CloseKeyFileEntity(); /* polygon creations: */ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer); -void StartPolygon(int aCornersCount, int aLayer); -void AddPointXY( int aXcoord, int aYcoord); -void EndElement(); +void StartKeyFilePolygon(int aCornersCount, int aLayer); +void AddKeyFilePointXY( int aXcoord, int aYcoord); +void EndKeyFileElement(); #endif // CREATE_KBOOL_KEY_FILES diff --git a/pcbnew/zones_convert_brd_items_to_polygons.cpp b/pcbnew/zones_convert_brd_items_to_polygons.cpp index 18cf46c3ef..e283d4d508 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons.cpp @@ -31,14 +31,15 @@ #include "zones.h" #include "PolyLine.h" + // Kbool 1.9 and before had sometimes problemes when calculating thermal shapes as polygons (this is the best solution) // So as a workaround we can use stubs (small tracks segments) to create thermal shape // Define USE_STUBS_FOR_THERMAL to work on this workaround -// Currently under development: DO NOT USE +// Currently only for tests: DO NOT USE // because the code is not really tested, pcbnew can do not work properly when used // Kbool 2.0 has solved some problems, but not all // Kbool 2.1 has solved some others problems, but not all -//#define USE_STUBS_FOR_THERMAL +//define USE_STUBS_FOR_THERMAL // Used to create data files to debug Kbool #include "debug_kbool_key_file_fct.h" @@ -48,18 +49,25 @@ // See debug_kbool_key_file_fct.h -extern void Test_For_Copper_Island_And_Remove( BOARD* aPcb, ZONE_CONTAINER* aZone_container ); +extern void Test_For_Copper_Island_And_Remove( BOARD* aPcb, + ZONE_CONTAINER* aZone_container ); +extern void TransformRoundedEndsSegmentToPolygon( std::vector & aCornerBuffer, + wxPoint aStart, wxPoint aEnd, + int aCircleToSegmentsCount, + int aWidth ); #ifdef CREATE_KBOOL_KEY_FILES -bool s_GenDataForKbool = false; +bool s_GenDataForKbool = false; #endif // Local Functions: #ifdef USE_STUBS_FOR_THERMAL -#warning USE_STUBS_FOR_THERMAL is defined: for test version only do not use for working pcbnew version -void CreateStubsForThermalShapes(BOARD* aPcb, ZONE_CONTAINER* aZone_container, - int aThermalGap, - int aCopperThickness, int aMinThicknessValue); +#warning \ + USE_STUBS_FOR_THERMAL is defined: for test version only do not use for working pcbnew version +void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_container, + int aThermalGap, + int aCopperThickness, int aMinThicknessValue ); + #endif void AddTrackWithClearancePolygon( Bool_Engine* aBooleng, TRACK& aTrack, int aClearanceValue ); @@ -71,9 +79,6 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng, void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng, wxPoint aStart, wxPoint aEnd, int aWidth ); -void AddSquareEndsSegmentPolygon( Bool_Engine* aBooleng, - wxPoint aStart, wxPoint aEnd, - int aWidth ); void AddTextBoxWithClearancePolygon( Bool_Engine* aBooleng, TEXTE_PCB* aText, int aClearanceValue ); @@ -204,19 +209,25 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) int zone_clearance = max( m_ZoneClearance, GetClearance() ); zone_clearance += m_ZoneMinThickness / 2; - /* Add holes (i.e. tracks and pads areas as polygons outlines) * in GroupB in Bool_Engine */ + /* items ouside the zone bounding box are skipped - * the bounding box is the zone bounding box + the biigest clearance found in Netclass list - */ + * the bounding box is the zone bounding box + the biggest clearance found in Netclass list + */ EDA_Rect item_boundingbox; - EDA_Rect zone_boundingbox = GetBoundingBox(); - int biggest_clearance = aPcb->GetBiggestClearanceValue(); + EDA_Rect zone_boundingbox = GetBoundingBox(); + int biggest_clearance = aPcb->GetBiggestClearanceValue(); biggest_clearance = MAX( biggest_clearance, zone_clearance ); zone_boundingbox.Inflate( biggest_clearance, biggest_clearance ); +#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS + CreateKeyFile(); + OpenKeyFileEntity( "Layer_fp" ); + CopyPolygonsFromFilledPolysListToKeyFile( this, 0 ); +#endif + /* * First : Add pads. Note: pads having the same net as zone are left in zone. * Thermal shapes will be created later if necessary @@ -232,11 +243,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) if( pad->GetNet() != GetNet() ) { - item_clearance = pad->GetClearance() + (m_ZoneMinThickness / 2); + item_clearance = pad->GetClearance() + (m_ZoneMinThickness / 2); item_boundingbox = pad->GetBoundingBox(); if( item_boundingbox.Intersects( zone_boundingbox ) ) { - AddPadWithClearancePolygon( booleng, *pad, MAX(zone_clearance,item_clearance) ); + AddPadWithClearancePolygon( booleng, *pad, MAX( zone_clearance, item_clearance ) ); have_poly_to_substract = true; } continue; @@ -248,8 +259,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) #else if( (m_PadOption == PAD_NOT_IN_ZONE) || (GetNet() == 0) || pad->m_PadShape == PAD_TRAPEZOID ) + // PAD_TRAPEZOID shapes are not in zones because they are used in microwave apps - // and i think it is good shapes are not changed by thermal pads or others + // and i think it is good that shapes are not changed by thermal pads or others #endif { item_boundingbox = pad->GetBoundingBox(); @@ -273,17 +285,16 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) if( track->GetNet() == GetNet() && (GetNet() != 0) ) continue; - item_clearance = track->GetClearance() + (m_ZoneMinThickness / 2); + item_clearance = track->GetClearance() + (m_ZoneMinThickness / 2); item_boundingbox = track->GetBoundingBox(); if( item_boundingbox.Intersects( zone_boundingbox ) ) { - AddTrackWithClearancePolygon( booleng, *track, MAX(zone_clearance,item_clearance) ); + AddTrackWithClearancePolygon( booleng, *track, MAX( zone_clearance, item_clearance ) ); have_poly_to_substract = true; } } - // Draw graphic items (copper texts) and board edges - // zone clearance is used here regardless of the g_DesignSettings.m_TrackClearance value + // Add graphic items (copper texts) and board edges for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) { if( item->GetLayer() != GetLayer() && item->GetLayer() != EDGE_N ) @@ -319,6 +330,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) have_poly_to_substract = true; break; } + break; case TYPE_TEXTE: @@ -331,7 +343,12 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) } } +#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS + CloseKeyFileEntity(); + CloseKeyFile(); +#endif /* calculates copper areas */ + if( have_poly_to_substract ) { booleng->Do_Operation( BOOL_A_SUB_B ); @@ -341,8 +358,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) CopyPolygonsFromBoolengineToFilledPolysList( booleng ); } delete booleng; - #ifdef USE_STUBS_FOR_THERMAL + // remove thermal gaps if required: if( m_PadOption != THERMAL_PAD || aPcb->m_Modules == NULL ) { @@ -351,18 +368,19 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) } #ifdef CREATE_KBOOL_KEY_FILES - CreateKeyFile(); - OpenEntity("Layer"); - CopyPolygonsFromFilledPolysListToKeyFile(this, 0); + CreateKeyFileKeyFile(); + OpenKeyFileEntity( "Layer" ); + CopyPolygonsFromFilledPolysListToKeyFile( this, 0 ); #endif - CreateStubsForThermalShapes(aPcb, this, m_ThermalReliefGapValue, - m_ThermalReliefCopperBridgeValue, m_ZoneMinThickness); + CreateStubsForThermalShapes( aPcb, this, m_ThermalReliefGapValue, + m_ThermalReliefCopperBridgeValue, m_ZoneMinThickness ); Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); #ifdef CREATE_KBOOL_KEY_FILES - CloseEntity(); + CloseKeyFileEntity(); CloseKeyFile(); #endif #else + // Remove insulated islands: if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); @@ -381,9 +399,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) have_poly_to_substract = false; #ifdef CREATE_KBOOL_KEY_FILES - CreateKeyFile(); - OpenEntity("Layer"); - CopyPolygonsFromFilledPolysListToKeyFile(this, 0); + CreateKeyFile(); + OpenKeyFileEntity( "Layer" ); + CopyPolygonsFromFilledPolysListToKeyFile( this, 0 ); #endif for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) @@ -407,8 +425,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) } } } + #ifdef CREATE_KBOOL_KEY_FILES - CloseEntity(); + CloseKeyFileEntity(); #endif if( have_poly_to_substract ) @@ -429,7 +448,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); #ifdef CREATE_KBOOL_KEY_FILES - CloseKeyFile(); + CloseKeyFile(); #endif } @@ -478,8 +497,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) int fAngle = pad->m_Orient; if( pad->m_PadShape == PAD_CIRCLE ) { - dx = (int) ( dx * s_Correction ); - dy = dx; + dx = (int) ( dx * s_Correction ); + dy = dx; #ifdef CREATE_KBOOL_KEY_FILES_WITH_0_DEG fAngle = 0; #else @@ -594,180 +613,47 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) void AddPadWithClearancePolygon( Bool_Engine* aBooleng, D_PAD& aPad, int aClearanceValue ) { + static std::vector cornerBuffer; if( aBooleng->StartPolygonAdd( GROUP_B ) == 0 ) return; - wxPoint corner_position; - int ii, angle; - int dx = (aPad.m_Size.x / 2) + aClearanceValue; - int dy = (aPad.m_Size.y / 2) + aClearanceValue; + cornerBuffer.clear(); + aPad.TransformPadWithClearanceToPolygon( cornerBuffer, + aClearanceValue, + s_CircleToSegmentsCount, + s_Correction ); - int delta = 3600 / s_CircleToSegmentsCount; // rot angle in 0.1 degree - wxPoint PadShapePos = aPad.ReturnShapePos(); /* Note: for pad having a shape offset, - * the pad position is NOT the shape position */ - wxSize psize = aPad.m_Size; /* pad size unsed in RECT and TRAPEZOIDAL pads - * trapezoidal pads are considered as rect pad shape having they boudary box size - */ - - switch( aPad.m_PadShape ) - { - case PAD_CIRCLE: - dx = (int) ( dx * s_Correction ); - for( ii = 0; ii < s_CircleToSegmentsCount; ii++ ) - { - corner_position = wxPoint( dx, 0 ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); // Half increment offset to get more space between - angle = ii * delta; - RotatePoint( &corner_position, angle ); - corner_position += PadShapePos; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - break; - - case PAD_OVAL: - angle = aPad.m_Orient; - if( dy > dx ) // Oval pad X/Y ratio for choosing translation axles - { - dy = (int) ( dy * s_Correction ); - int angle_pg; // Polygon angle - wxPoint shape_offset = wxPoint( 0, (dy - dx) ); - RotatePoint( &shape_offset, angle ); // Rotating shape offset vector with component - - for( ii = 0; ii < s_CircleToSegmentsCount / 2 + 1; ii++ ) // Half circle end cap... - { - corner_position = wxPoint( dx, 0 ); // Coordinate translation +dx - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - RotatePoint( &corner_position, angle ); - angle_pg = ii * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position += PadShapePos - shape_offset; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - for( ii = 0; ii < s_CircleToSegmentsCount / 2 + 1; ii++ ) // Second half circle end cap... - { - corner_position = wxPoint( -dx, 0 ); // Coordinate translation -dx - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - RotatePoint( &corner_position, angle ); - angle_pg = ii * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position += PadShapePos + shape_offset; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - break; - } - else //if( dy <= dx ) - { - dx = (int) ( dx * s_Correction ); - int angle_pg; // Polygon angle - wxPoint shape_offset = wxPoint( (dy - dx), 0 ); - RotatePoint( &shape_offset, angle ); - - for( ii = 0; ii < s_CircleToSegmentsCount / 2 + 1; ii++ ) - { - corner_position = wxPoint( 0, dy ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - RotatePoint( &corner_position, angle ); - angle_pg = ii * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position += PadShapePos - shape_offset; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - for( ii = 0; ii < s_CircleToSegmentsCount / 2 + 1; ii++ ) - { - corner_position = wxPoint( 0, -dy ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - RotatePoint( &corner_position, angle ); - angle_pg = ii * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position += PadShapePos + shape_offset; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - break; - } - - default: - case PAD_TRAPEZOID: - psize.x += ABS(aPad.m_DeltaSize.y); - psize.y += ABS(aPad.m_DeltaSize.x); - // fall through - case PAD_RECT: // Easy implementation for rectangular cutouts with rounded corners // Easy implementation for rectangular cutouts with rounded corners - angle = aPad.m_Orient; - int rounding_radius = (int) ( aClearanceValue * s_Correction ); // Corner rounding radius - int angle_pg; // Polygon increment angle - - for( int i = 0; i < s_CircleToSegmentsCount / 4 + 1; i++ ) - { - corner_position = wxPoint( 0, -rounding_radius ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); // Start at half increment offset - angle_pg = i * delta; - RotatePoint( &corner_position, angle_pg ); // Rounding vector rotation - corner_position -= psize / 2; // Rounding vector + Pad corner offset - RotatePoint( &corner_position, angle ); // Rotate according to module orientation - corner_position += PadShapePos; // Shift origin to position - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - for( int i = 0; i < s_CircleToSegmentsCount / 4 + 1; i++ ) - { - corner_position = wxPoint( -rounding_radius, 0 ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - angle_pg = i * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position -= wxPoint( psize.x / 2, -psize.y / 2 ); - RotatePoint( &corner_position, angle ); - corner_position += PadShapePos; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - for( int i = 0; i < s_CircleToSegmentsCount / 4 + 1; i++ ) - { - corner_position = wxPoint( 0, rounding_radius ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - angle_pg = i * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position += psize / 2; - RotatePoint( &corner_position, angle ); - corner_position += PadShapePos; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - for( int i = 0; i < s_CircleToSegmentsCount / 4 + 1; i++ ) - { - corner_position = wxPoint( rounding_radius, 0 ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - angle_pg = i * delta; - RotatePoint( &corner_position, angle_pg ); - corner_position -= wxPoint( -psize.x / 2, psize.y / 2 ); - RotatePoint( &corner_position, angle ); - corner_position += PadShapePos; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } - - break; - } + for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) + aBooleng->AddPoint( cornerBuffer[ii].x, cornerBuffer[ii].y ); aBooleng->EndPolygonAdd(); + +#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS + StartKeyFilePolygon( cornerBuffer.size() + 1, 1 ); + for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) + AddKeyFilePointXY( cornerBuffer[ii].x, cornerBuffer[ii].y ); + + // Close polygon + AddKeyFilePointXY( cornerBuffer[0].x, cornerBuffer[0].y ); + EndKeyFileElement(); +#endif } /** function CreateStubsForThermalShapes() * Only for testing the thermal shapes by stubs purposes * Do not use for working pcbnew versions -*/ -void CreateStubsForThermalShapes(BOARD* aPcb, ZONE_CONTAINER* aZone_container, - int aThermalGap, - int aCopperThickness, int aMinThicknessValue) + */ +void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_container, + int aThermalGap, + int aCopperThickness, int aMinThicknessValue ) { - EDA_Rect zone_boundingbox = aZone_container->GetBoundingBox(); - bool have_poly_to_add = false; - Bool_Engine * booleng = new Bool_Engine(); + EDA_Rect zone_boundingbox = aZone_container->GetBoundingBox(); + bool have_poly_to_add = false; + Bool_Engine* booleng = new Bool_Engine(); + ArmBoolEng( booleng, true ); - TRACK dummy_track(aPcb); + TRACK dummy_track( aPcb ); if( aCopperThickness <= aMinThicknessValue ) return; @@ -824,11 +710,10 @@ void CreateStubsForThermalShapes(BOARD* aPcb, ZONE_CONTAINER* aZone_conta if( inside ) { - dummy_track.m_Start = pad->ReturnShapePos(); - dummy_track.m_End = ptTest[i]; - dummy_track.SetNet(aZone_container->GetNet()); - dummy_track.SetLayer(aZone_container->GetLayer() ); + dummy_track.m_End = ptTest[i]; + dummy_track.SetNet( aZone_container->GetNet() ); + dummy_track.SetLayer( aZone_container->GetLayer() ); dummy_track.m_Width = aCopperThickness; dummy_track.SetState( BEGIN_ONPAD, ON ); dummy_track.start = pad; @@ -838,15 +723,20 @@ void CreateStubsForThermalShapes(BOARD* aPcb, ZONE_CONTAINER* aZone_conta if( pcbFrame->GetDrcController()->Drc( &dummy_track, aPcb->m_Track ) == OK_DRC ) { have_poly_to_add = true; + // because stubs outlines are drawn with a pen size = aMinThicknessValue, // the width of the stub is aCopperThickness - aMinThicknessValue int thickness = dummy_track.m_Width - aMinThicknessValue; - AddRoundedEndsSegmentPolygon( booleng, dummy_track.m_Start, dummy_track.m_End, thickness ); + AddRoundedEndsSegmentPolygon( booleng, + dummy_track.m_Start, + dummy_track.m_End, + thickness ); } } } } } + #ifdef CREATE_KBOOL_KEY_FILES s_GenDataForKbool = false; #endif @@ -1016,7 +906,7 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng, if( aBooleng->StartPolygonAdd( GROUP_B ) ) { #ifdef CREATE_KBOOL_KEY_FILES - StartPolygon(corners_buffer.size() +1, 1); + StartKeyFilePolygon( corners_buffer.size() + 1, 1 ); #endif for( unsigned ii = 0; ii < corners_buffer.size(); ii++ ) { @@ -1025,20 +915,22 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng, corner += PadShapePos; aBooleng->AddPoint( corner.x, corner.y ); #ifdef CREATE_KBOOL_KEY_FILES - AddPointXY(corner.x, corner.y); + AddKeyFilePointXY( corner.x, corner.y ); #endif } + #ifdef CREATE_KBOOL_KEY_FILES + // Close polygon corner = corners_buffer[0]; RotatePoint( &corner, angle + angle_pad ); // Rotate by segment angle and pad orientation corner += PadShapePos; - AddPointXY( corner.x, corner.y ); + AddKeyFilePointXY( corner.x, corner.y ); #endif aBooleng->EndPolygonAdd(); #ifdef CREATE_KBOOL_KEY_FILES - EndElement(); + EndKeyFileElement(); #endif angle += 900; // Note: angle in in 0.1 deg. } @@ -1290,38 +1182,30 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng, void AddTrackWithClearancePolygon( Bool_Engine* aBooleng, TRACK& aTrack, int aClearanceValue ) { - wxPoint corner_position; - int ii, angle; - int dx = (aTrack.m_Width / 2) + aClearanceValue; + static std::vector cornerBuffer; + cornerBuffer.clear(); + aTrack.TransformTrackWithClearanceToPolygon( cornerBuffer, + aClearanceValue, + s_CircleToSegmentsCount, + s_Correction ); - int delta = 3600 / s_CircleToSegmentsCount; // rot angle in 0.1 degree + if( !aBooleng->StartPolygonAdd( GROUP_B ) ) + return; - switch( aTrack.Type() ) - { - case TYPE_VIA: - if( aBooleng->StartPolygonAdd( GROUP_B ) ) - { - dx = (int) ( dx * s_Correction ); - for( ii = 0; ii < s_CircleToSegmentsCount; ii++ ) - { - corner_position = wxPoint( dx, 0 ); - RotatePoint( &corner_position, (1800 / s_CircleToSegmentsCount) ); - angle = ii * delta; - RotatePoint( &corner_position, angle ); - corner_position += aTrack.m_Start; - aBooleng->AddPoint( corner_position.x, corner_position.y ); - } + for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) + aBooleng->AddPoint( cornerBuffer[ii].x, cornerBuffer[ii].y ); - aBooleng->EndPolygonAdd(); - } - break; + aBooleng->EndPolygonAdd(); - default: - AddRoundedEndsSegmentPolygon( aBooleng, - aTrack.m_Start, aTrack.m_End, - aTrack.m_Width + (2 * aClearanceValue) ); - break; - } +#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS + StartKeyFilePolygon( cornerBuffer.size() + 1, 1 ); + for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) + AddKeyFilePointXY( cornerBuffer[ii].x, cornerBuffer[ii].y ); + + // Close polygon + AddKeyFilePointXY( cornerBuffer[0].x, cornerBuffer[0].y ); + EndKeyFileElement(); +#endif } @@ -1333,208 +1217,29 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng, wxPoint aStart, wxPoint aEnd, int aWidth ) { - int rayon = aWidth / 2; - wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) - wxPoint startp = aStart; - wxPoint corner; - int seg_len; - - // normalize the position in order to have endp.x >= 0; - if( endp.x < 0 ) - { - endp = aStart - aEnd; - startp = aEnd; - } - int delta_angle = ArcTangente( endp.y, endp.x ); // delta_angle is in 0.1 degrees - seg_len = (int) sqrt( ( (double) endp.y * endp.y ) + ( (double) endp.x * endp.x ) ); + static std::vector cornerBuffer; + cornerBuffer.clear(); + TransformRoundedEndsSegmentToPolygon( cornerBuffer, + aStart, aEnd, + s_CircleToSegmentsCount, + aWidth ); if( !aBooleng->StartPolygonAdd( GROUP_B ) ) - return; // error! + return; - int delta = 3600 / s_CircleToSegmentsCount; // rot angle in 0.1 degree - - -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - StartPolygon(s_CircleToSegmentsCount+4, 1); -#endif - - - // Compute the outlines of the segment, and creates a polygon - corner = wxPoint( 0, rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - corner = wxPoint( seg_len, rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - // add right rounded end: - for( int ii = delta; ii < 1800; ii += delta ) - { - corner = wxPoint( 0, rayon ); - RotatePoint( &corner, ii ); - corner.x += seg_len; - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - } - - corner = wxPoint( seg_len, -rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - corner = wxPoint( 0, -rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - // add left rounded end: - for( int ii = delta; ii < 1800; ii += delta ) - { - corner = wxPoint( 0, -rayon ); - RotatePoint( &corner, ii ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - } + for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) + aBooleng->AddPoint( cornerBuffer[ii].x, cornerBuffer[ii].y ); aBooleng->EndPolygonAdd(); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - EndElement(); -#endif -} - -/** Function AddSquareEndsSegmentPolygon - * Add a polygon cutout for a segment (with square ends) in a zone area - */ -void AddSquareEndsSegmentPolygon( Bool_Engine* aBooleng, - wxPoint aStart, wxPoint aEnd, - int aWidth ) -{ - int rayon = aWidth / 2; - wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) - wxPoint startp = aStart; - wxPoint corner; - int seg_len; - - // normalize the position in order to have endp.x >= 0; - if( endp.x < 0 ) - { - endp = aStart - aEnd; - startp = aEnd; - } - int delta_angle = ArcTangente( endp.y, endp.x ); // delta_angle is in 0.1 degrees - seg_len = (int) sqrt( ( (double) endp.y * endp.y ) + ( (double) endp.x * endp.x ) ); - - if( !aBooleng->StartPolygonAdd( GROUP_B ) ) - return; // error! - - int delta = 900; // rot angle in 0.1 degree #ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - StartPolygon(5, 1); -#endif + StartKeyFilePolygon( cornerBuffer.size() + 1, 1 ); + for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) + AddKeyFilePointXY( cornerBuffer[ii].x, cornerBuffer[ii].y ); - // Compute the outlines of the segment, and creates a polygon - corner = wxPoint( 0, rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - corner = wxPoint( seg_len, rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - // add right rounded end: - for( int ii = delta; ii < 1800; ii += delta ) - { - corner = wxPoint( 0, rayon ); - RotatePoint( &corner, ii ); - corner.x += seg_len; - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - } - - corner = wxPoint( seg_len, -rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - corner = wxPoint( 0, -rayon ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - - // add left rounded end: - for( int ii = delta; ii < 1800; ii += delta ) - { - corner = wxPoint( 0, -rayon ); - RotatePoint( &corner, ii ); - RotatePoint( &corner, -delta_angle ); - corner += startp; - aBooleng->AddPoint( corner.x, corner.y ); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - AddPointXY(corner.x, corner.y); -#endif - } - - aBooleng->EndPolygonAdd(); -#ifdef CREATE_KBOOL_KEY_FILES - if( s_GenDataForKbool ) - EndElement(); + // Close polygon + AddKeyFilePointXY( cornerBuffer[0].x, cornerBuffer[0].y ); + EndKeyFileElement(); #endif } @@ -1588,14 +1293,14 @@ void AddRingPolygon( Bool_Engine* aBooleng, wxPoint aCentre, void AddTextBoxWithClearancePolygon( Bool_Engine* aBooleng, TEXTE_PCB* aText, int aClearanceValue ) { - if ( aText->GetLength() == 0 ) + if( aText->GetLength() == 0 ) return; - wxPoint corners[4]; // Buffer of polygon corners + wxPoint corners[4]; // Buffer of polygon corners EDA_Rect rect = aText->GetTextBox( -1 ); rect.Inflate( aClearanceValue, aClearanceValue ); - corners[0] = rect.GetOrigin(); + corners[0] = rect.GetOrigin(); corners[1].y = corners[0].y; corners[1].x = rect.GetRight(); corners[2].x = corners[1].x; @@ -1606,10 +1311,14 @@ void AddTextBoxWithClearancePolygon( Bool_Engine* aBooleng, if( aBooleng->StartPolygonAdd( GROUP_B ) ) { - for( int ii = 0; ii < 4; ii ++ ) + for( int ii = 0; ii < 4; ii++ ) { // Rotate polygon - RotatePoint( &corners[ii].x, &corners[ii].y, aText->m_Pos.x, aText->m_Pos.y, aText->m_Orient ); + RotatePoint( &corners[ii].x, + &corners[ii].y, + aText->m_Pos.x, + aText->m_Pos.y, + aText->m_Orient ); aBooleng->AddPoint( corners[ii].x, corners[ii].y ); } diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 7a7b69344a..f9de95c248 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -569,7 +569,7 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) Another scaling with Grid is applied on top of it to create space in the integer number for even smaller numbers. */ - int GRID = 10000; // initial value = 10000 in kbool example + int GRID = 1000; // initial value = 10000 in kbool example aBooleng->SetMarge( MARGE ); aBooleng->SetGrid( GRID );