diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index 380fec090c..ce03dc6420 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -49,7 +49,6 @@ #include <3d_draw_basic_functions.h> // Imported function: -extern void SetGLColor( EDA_COLOR_T color ); extern void Set_Object_Data( std::vector& aVertices, double aBiuTo3DUnits ); extern void CheckGLError(); @@ -161,14 +160,28 @@ void EDA_3D_CANVAS::BuildBoard3DView() // for holes and items which do not need // a fine representation double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2) ); - CPOLYGONS_LIST bufferPolys; - bufferPolys.reserve( 200000 ); // Reserve for large board (tracks mainly) - CPOLYGONS_LIST bufferZonesPolys; - bufferPolys.reserve( 500000 ); // Reserve for large board ( copper zones mainly ) - CPOLYGONS_LIST currLayerHoles; // Contains holes for the current layer - CPOLYGONS_LIST allLayerHoles; // Contains through holes, calculated only once + CPOLYGONS_LIST bufferPolys; + bufferPolys.reserve( 200000 ); // Reserve for large board (tracks mainly) + + CPOLYGONS_LIST bufferPcbOutlines; // stores the board main outlines + CPOLYGONS_LIST allLayerHoles; // Contains through holes, calculated only once allLayerHoles.reserve( 20000 ); + + // Build a polygon from edge cut items + wxString msg; + if( ! pcb->GetBoardPolygonOutlines( bufferPcbOutlines, + allLayerHoles, &msg ) ) + { + msg << wxT("\n\n") << + _("Unable to calculate the board outlines, will use the outlines boundary box"); + wxMessageBox( msg ); + } + + CPOLYGONS_LIST bufferZonesPolys; + bufferZonesPolys.reserve( 500000 ); // Reserve for large board ( copper zones mainly ) + + CPOLYGONS_LIST currLayerHoles; // Contains holes for the current layer bool throughHolesListBuilt = false; // flag to build the through hole polygon list only once bool hightQualityMode = false; @@ -282,7 +295,8 @@ void EDA_3D_CANVAS::BuildBoard3DView() } } - // bufferPolys contains polygons to merge. Many overlaps . Calculate merged polygons + // bufferPolys contains polygons to merge. Many overlaps . + // Calculate merged polygons if( bufferPolys.GetCornersCount() == 0 ) continue; @@ -346,6 +360,9 @@ void EDA_3D_CANVAS::BuildBoard3DView() if( !g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) ) continue; + if( layer == EDGE_N ) + continue; + bufferPolys.RemoveAllContours(); for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() ) @@ -407,26 +424,29 @@ void EDA_3D_CANVAS::BuildBoard3DView() // Calculate merged polygons and remove pads and vias holes if( bufferPolys.GetCornersCount() == 0 ) continue; - KI_POLYGON_SET currLayerPolyset; KI_POLYGON_SET polyset; - bufferPolys.ExportTo( polyset ); - // merge polys: - currLayerPolyset += polyset; + + // Solder mask layers are "negative" layers. + // Shapes should be removed from the full board area. + if( layer == SOLDERMASK_N_BACK || layer == SOLDERMASK_N_FRONT ) + { + bufferPcbOutlines.ExportTo( currLayerPolyset ); + bufferPolys.Append( allLayerHoles ); + bufferPolys.ExportTo( polyset ); + currLayerPolyset -= polyset; + } + else // usuall layers, merge polys built from each item shape: + { + bufferPolys.ExportTo( polyset ); + currLayerPolyset += polyset; + } EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( layer ); int thickness = g_Parm_3D_Visu.GetLayerObjectThicknessBIU( layer ); int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer ); - if( layer == EDGE_N ) - { - thickness = g_Parm_3D_Visu.GetLayerZcoordBIU( LAYER_N_FRONT ) - - g_Parm_3D_Visu.GetLayerZcoordBIU( LAYER_N_BACK ); - zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( LAYER_N_BACK ) - + (thickness / 2); - } - - SetGLColor( color ); + SetGLColor( color, 0.7 ); glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); bufferPolys.RemoveAllContours(); @@ -435,6 +455,37 @@ void EDA_3D_CANVAS::BuildBoard3DView() thickness, g_Parm_3D_Visu.m_BiuTo3Dunits ); } + // Draw board substrate: + if( bufferPcbOutlines.GetCornersCount() ) + { + int copper_thickness = g_Parm_3D_Visu.GetLayerObjectThicknessBIU( LAYER_N_BACK ); + int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( LAYER_N_BACK ); + int thickness = g_Parm_3D_Visu.GetLayerZcoordBIU( LAYER_N_FRONT ) + - g_Parm_3D_Visu.GetLayerZcoordBIU( LAYER_N_BACK ); + zpos += (thickness/2) + (copper_thickness/2); + thickness -= copper_thickness; + EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( EDGE_N ); + SetGLColor( color, 0.8 ); + glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( LAYER_N_FRONT ) ); + KI_POLYGON_SET currLayerPolyset; + KI_POLYGON_SET polysetHoles; + + // Add polygons, without holes + bufferPcbOutlines.ExportTo( currLayerPolyset ); + + // Build holes list + allLayerHoles.ExportTo( polysetHoles ); + + // remove holes + currLayerPolyset -= polysetHoles; + + bufferPcbOutlines.RemoveAllContours(); + bufferPcbOutlines.ImportFrom( currLayerPolyset ); + + Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos, + thickness, g_Parm_3D_Visu.m_BiuTo3Dunits ); + } + // draw modules 3D shapes for( MODULE* module = pcb->m_Modules; module != NULL; module = module->Next() ) module->ReadAndInsert3DComponentShape( this ); @@ -517,6 +568,7 @@ void EDA_3D_CANVAS::DrawGrid( double aGriSizeMM ) EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines EDA_COLOR_T gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines double scale = g_Parm_3D_Visu.m_BiuTo3Dunits; + double transparency = 0.4; glNormal3f( 0.0, 0.0, 1.0 ); @@ -539,9 +591,9 @@ void EDA_3D_CANVAS::DrawGrid( double aGriSizeMM ) for( int ii = 0; ; ii++ ) { if( (ii % 5) ) - SetGLColor( gridcolor ); + SetGLColor( gridcolor, transparency ); else - SetGLColor( gridcolor_marker ); + SetGLColor( gridcolor_marker, transparency ); int delta = KiROUND( ii * aGriSizeMM * IU_PER_MM ); @@ -588,9 +640,9 @@ void EDA_3D_CANVAS::DrawGrid( double aGriSizeMM ) for( int ii = 0; ; ii++ ) { if( (ii % 5) ) - SetGLColor( gridcolor ); + SetGLColor( gridcolor, transparency ); else - SetGLColor( gridcolor_marker ); + SetGLColor( gridcolor_marker, transparency ); double delta = ii * aGriSizeMM * IU_PER_MM; @@ -615,9 +667,9 @@ void EDA_3D_CANVAS::DrawGrid( double aGriSizeMM ) for( int ii = 0; ; ii++ ) { if( (ii % 5) ) - SetGLColor( gridcolor ); + SetGLColor( gridcolor, transparency); else - SetGLColor( gridcolor_marker ); + SetGLColor( gridcolor_marker, transparency ); double delta = ii * aGriSizeMM * IU_PER_MM * scale; diff --git a/3d-viewer/3d_draw_basic_functions.cpp b/3d-viewer/3d_draw_basic_functions.cpp index bb08b572b3..d4233c5bfa 100644 --- a/3d-viewer/3d_draw_basic_functions.cpp +++ b/3d-viewer/3d_draw_basic_functions.cpp @@ -34,7 +34,6 @@ #include #include <3d_draw_basic_functions.h> - // Imported function: extern void Set_Object_Data( std::vector& aVertices, double aBiuTo3DUnits ); extern void CheckGLError(); @@ -122,7 +121,7 @@ static void Draw3D_VerticalPolygonalCylinder( const CPOLYGONS_LIST& aPolysList, } -void SetGLColor( EDA_COLOR_T color ) +void SetGLColor( EDA_COLOR_T color, double alpha ) { double red, green, blue; const StructColors &colordata = g_ColorRefs[ColorGetBase( color )]; @@ -130,7 +129,7 @@ void SetGLColor( EDA_COLOR_T color ) red = colordata.m_Red / 255.0; blue = colordata.m_Blue / 255.0; green = colordata.m_Green / 255.0; - glColor3f( red, green, blue ); + glColor4f( red, green, blue, alpha ); } diff --git a/3d-viewer/3d_draw_basic_functions.h b/3d-viewer/3d_draw_basic_functions.h index 9f40bc0821..714d4b2c07 100644 --- a/3d-viewer/3d_draw_basic_functions.h +++ b/3d-viewer/3d_draw_basic_functions.h @@ -118,5 +118,12 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius, void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos, int aRadius, int aHeight, int aThickness, int aZpos, double aBiuTo3DUnits ); +/** + * Set the current 3D color from a Kicad color, with optional transparency + * @param aColor = a EDA_COLOR_T kicad color index + * @param aTransparency = the color transparency (default = 1.0 = no transparency) + */ +void SetGLColor( EDA_COLOR_T aColor, double aTransparency = 1.0 ); + #endif // _3D_DRAW_BASIC_FUNCTIONS_H_ diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index e2fa10f651..73258dbba1 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -139,6 +139,9 @@ set(PCB_COMMON_SRCS ../pcbnew/kicad_plugin.cpp ../pcbnew/gpcb_plugin.cpp ../pcbnew/pcb_netlist.cpp + ../pcbnew/specctra.cpp + ../pcbnew/specctra_export.cpp + ../pcbnew/specctra_keywords.cpp pcb_plot_params_keywords.cpp pcb_keywords.cpp ../pcbnew/pcb_parser.cpp @@ -155,6 +158,17 @@ set_source_files_properties( ${PCB_COMMON_SRCS} PROPERTIES add_library(pcbcommon STATIC ${PCB_COMMON_SRCS}) +# auto-generate specctra_lexer.h and specctra_keywords.cpp +make_lexer( + ${PROJECT_SOURCE_DIR}/pcbnew/specctra.keywords + ${PROJECT_SOURCE_DIR}/pcbnew/specctra_lexer.h + ${PROJECT_SOURCE_DIR}/pcbnew/specctra_keywords.cpp + DSN + + # Pass header file with dependency on *_lexer.h as extra_arg + specctra.h + ) + # auto-generate netlist_lexer.h and netlist_keywords.cpp make_lexer( ${CMAKE_CURRENT_SOURCE_DIR}/netlist.keywords diff --git a/common/common_plotGERBER_functions.cpp b/common/common_plotGERBER_functions.cpp index 468e9085b2..5ed5ec0f55 100644 --- a/common/common_plotGERBER_functions.cpp +++ b/common/common_plotGERBER_functions.cpp @@ -67,6 +67,10 @@ bool GERBER_PLOTTER::StartPlot() if( outputFile == NULL ) return false; + /* Set coordinate format to 3.4 absolute, leading zero omitted */ + fputs( "%FSLAX34Y34*%\n", outputFile ); + fputs( "G04 Gerber Fmt 3.4, Leading zero omitted, Abs format*\n", outputFile ); + wxString Title = creator + wxT( " " ) + GetBuildVersion(); fprintf( outputFile, "G04 (created by %s) date %s*\n", TO_UTF8( Title ), TO_UTF8( DateAndTime() ) ); @@ -74,10 +78,6 @@ bool GERBER_PLOTTER::StartPlot() /* Mass parameter: unit = INCHES */ fputs( "%MOIN*%\n", outputFile ); - /* Set coordinate format to 3.4 absolute, leading zero omitted */ - fputs( "G04 Gerber Fmt 3.4, Leading zero omitted, Abs format*\n%FSLAX34Y34*%\n", - outputFile ); - /* Specify linear interpol (G01), unit = INCH (G70), abs format (G90) */ fputs( "G01*\nG70*\nG90*\n", outputFile ); fputs( "G04 APERTURE LIST*\n", outputFile ); diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp index 55aa35f151..a16843f1f0 100644 --- a/gerbview/excellon_read_drill_file.cpp +++ b/gerbview/excellon_read_drill_file.cpp @@ -58,8 +58,8 @@ */ /* * Note there are some variant of tool definition: - * T1F00S00C... Feed Rate and Spindle Speed of Tool 1 - * Feed Rate and Spindle Speed are just skipped because they are not used in a viwer + * T1F00S00C0.2 or T1C0.02F00S00 ... Feed Rate and Spindle Speed of Tool 1 + * Feed Rate and Spindle Speed are just skipped because they are not used in a viewer */ #include @@ -348,7 +348,7 @@ bool EXCELLON_IMAGE::Execute_HEADER_Command( char*& text ) m_State = READ_PROGRAM_STATE; break; - case DRILL_REWIND_STOP: // TODO: what this command really is ? + case DRILL_REWIND_STOP: // End of header. No action in a viewer m_State = READ_PROGRAM_STATE; break; @@ -440,11 +440,11 @@ bool EXCELLON_IMAGE::Execute_HEADER_Command( char*& text ) case DRILL_TOOL_INFORMATION: // Read a tool definition like T1C0.02: - // or T1F00S00C0.02000 + // or T1F00S00C0.02 or T1C0.02F00S00 // Read tool number: iprm = ReadInt( text, false ); - // Skip Feed rate and Spindle speed + // Skip Feed rate and Spindle speed, if any here while( *text && ( *text == 'F' || *text == 'S' ) ) { text++; diff --git a/gerbview/export_to_pcbnew.cpp b/gerbview/export_to_pcbnew.cpp index 5e3af4cadd..1594f5d7af 100644 --- a/gerbview/export_to_pcbnew.cpp +++ b/gerbview/export_to_pcbnew.cpp @@ -141,7 +141,7 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) wxFileDialog filedlg( this, _( "Board file name:" ), path, fileName, LegacyPcbFileWildcard, - wxFD_OPEN ); + wxFD_SAVE ); if( filedlg.ShowModal() == wxID_CANCEL ) return; @@ -233,7 +233,7 @@ void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, LA #define SEG_SHAPE 0 #define ARC_SHAPE 2 int shape = SEG_SHAPE; - + // please note: the old PCB format only has integer support for angles int angle = 0; wxPoint seg_start, seg_end; diff --git a/include/class_bitmap_base.h b/include/class_bitmap_base.h index a735c2772b..4ba3a93d03 100644 --- a/include/class_bitmap_base.h +++ b/include/class_bitmap_base.h @@ -6,8 +6,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2011 jean-pierre.charras - * Copyright (C) 2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 jean-pierre.charras jp.charras at wanadoo.fr + * Copyright (C) 2013 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,13 +31,13 @@ #define _BITMAP_BASE_H_ -#include +class PLOTTER; /** * This class handle bitmap images in KiCad. * It is not intended to be used alone, but inside an other class, * so all methods are protected ( or private ) - * It is used in SCH_BITMAP class (and other in futute) + * It is used in SCH_BITMAP class and WS_DRAW_ITEM_BITMAP (and other in future) * * Remember not all plotters are able to plot a bitmap * Mainly GERBER plotters cannot. @@ -106,13 +106,13 @@ public: BITMAP_BASE( const wxPoint& pos = wxPoint( 0, 0 ) ); /** * Function GetSize - * @returns the actual size (in user units, not in pixels) of the image + * @return the actual size (in user units, not in pixels) of the image */ wxSize GetSize() const; /** * Function GetSizePixels - * @returns the size in pixels of the image + * @return the size in pixels of the image */ wxSize GetSizePixels() const { @@ -136,8 +136,8 @@ public: BITMAP_BASE( const wxPoint& pos = wxPoint( 0, 0 ) ); /** * Function ReadImageFile - * Reads and stores an image file. Init the bitmap used to draw this item - * format. + * Reads and stores in memory an image file. + * Init the bitmap format used to draw this item. * supported images formats are format supported by wxImage * if all handlers are loaded * by default, .png, .jpeg are alway loaded @@ -191,7 +191,7 @@ public: BITMAP_BASE( const wxPoint& pos = wxPoint( 0, 0 ) ); * @param aDefaultColor = the color used to plot the rectangle when bitmap is not supported * @param aDefaultPensize = the pen size used to plot the rectangle when bitmap is not supported */ - void PlotImage( PLOTTER* aPlotter, const wxPoint& aPos, + void PlotImage( PLOTTER* aPlotter, const wxPoint& aPos, EDA_COLOR_T aDefaultColor, int aDefaultPensize ); }; diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 7e6909b7bd..414b8541d4 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -199,10 +199,10 @@ set( PCBNEW_CLASS_SRCS print_board_functions.cpp printout_controler.cpp ratsnest.cpp - specctra.cpp - specctra_export.cpp +# specctra.cpp #moved in pcbcommon lib +# specctra_export.cpp +# specctra_keywords.cpp specctra_import.cpp - specctra_keywords.cpp swap_layers.cpp target_edit.cpp tool_modedit.cpp diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 43d2f3c4d8..c1814743a7 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -2715,3 +2715,19 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, } } +/* Extracts the board outlines and build a closed polygon + * from lines, arcs and circle items on edge cut layer + * Any closed outline inside the main outline is a hole + * All contours should be closed, i.e. are valid vertices for a closed polygon + * return true if success, false if a contour is not valid + */ +#include +bool BOARD::GetBoardPolygonOutlines( CPOLYGONS_LIST& aOutlines, + CPOLYGONS_LIST& aHoles, + wxString* aErrorText ) +{ + // the SPECCTRA_DB function to extract board outlines: + SPECCTRA_DB dummy; + return dummy.GetBoardPolygonOutlines( this, aOutlines, + aHoles, aErrorText ); +} diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index b234a1cd3d..8763dd9af8 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -628,6 +628,23 @@ public: m_colorsSettings = aColorsSettings; } + /** + * Function GetBoardPolygonOutlines + * Extracts the board outlines and build a closed polygon + * from lines, arcs and circle items on edge cut layer + * Any closed outline inside the main outline is a hole + * All contours should be closed, i.e. have valid vertices to build a closed polygon + * @param aOutlines The CPOLYGONS_LIST to fill in with main outlines. + * @param aHoles The empty CPOLYGONS_LIST to fill in with holes, if any. + * @param aErrorText = a wxString reference to display an error message + * with the coordinate of the point which creates the error + * (default = NULL , no message returned on error) + * @return true if success, false if a contour is not valid + */ + bool GetBoardPolygonOutlines( CPOLYGONS_LIST& aOutlines, + CPOLYGONS_LIST& aHoles, + wxString* aErrorText = NULL ); + /** * Function GetLayerName * returns the name of a layer given by aLayer. Copper layers may diff --git a/pcbnew/specctra.h b/pcbnew/specctra.h index d160019cd2..2a53c33211 100644 --- a/pcbnew/specctra.h +++ b/pcbnew/specctra.h @@ -465,6 +465,9 @@ public: point1.FixNegativeZero(); } + POINT GetOrigin() { return point0; } + POINT GetEnd() { return point1; } + void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR ) { const char* newline = nestLevel ? "\n" : ""; @@ -593,6 +596,8 @@ public: points.push_back( aPoint ); } + POINTS& GetPoints() {return points; } + void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; @@ -662,6 +667,40 @@ public: delete rectangle; } + /** + * GetCorners fills aBuffer with a list of coordinates (x,y) of corners + */ + void GetCorners( std::vector& aBuffer ) + { + if( rectangle ) + { + aBuffer.push_back( rectangle->GetOrigin().x ); + aBuffer.push_back( rectangle->GetOrigin().y ); + + aBuffer.push_back( rectangle->GetOrigin().x ); + aBuffer.push_back( rectangle->GetEnd().y ); + + aBuffer.push_back( rectangle->GetEnd().x ); + aBuffer.push_back( rectangle->GetEnd().y ); + + aBuffer.push_back( rectangle->GetEnd().x ); + aBuffer.push_back( rectangle->GetOrigin().y ); + } + else + { + for( PATHS::iterator i=paths.begin(); i!=paths.end(); ++i ) + { + POINTS& plist = i->GetPoints(); + for( unsigned jj = 0; jj < plist.size(); jj++ ) + { + aBuffer.push_back( plist[jj].x ); + aBuffer.push_back( plist[jj].y ); + } + } + } + } + + void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR ) { out->Print( nestLevel, "(%s\n", Name() ); @@ -3926,6 +3965,26 @@ public: * flips the modules which were on the back side of the board back to the back. */ void RevertMODULEs( BOARD* aBoard ); + + /** + * Function GetBoardPolygonOutlines + * Is not used in SPECCTRA export, but uses a lot of functions from it + * and is used to extract a board outlines (3D view, automatic zones build ...) + * makes the board perimeter by filling the BOUNDARY element + * any closed outline inside the main outline is a hole + * All contours should be closed, i.e. have valid vertices to build a closed polygon + * @param aBoard The BOARD to get information from in order to make the outlines. + * @param aOutlines The CPOLYGONS_LIST to fill in with main outlines. + * @param aHoles The empty CPOLYGONS_LIST to fill in with holes, if any. + * @param aErrorText = a wxString reference to display an error message + * with the coordinate of the point which creates the error + * (default = NULL , no message returned on error) + * @return true if success, false if a contour is not valid + */ + bool GetBoardPolygonOutlines( BOARD* aBoard, + CPOLYGONS_LIST& aOutlines, + CPOLYGONS_LIST& aHoles, + wxString* aErrorText = NULL ); }; diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index 016776698f..67cd3c1944 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -1251,6 +1251,98 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER } } +/* This function is not used in SPECCTRA export, + * but uses a lot of functions from it + * and is used to extract a board outlines (3D view, automatic zones build ...) + * makes the board perimeter for the DSN file by filling the BOUNDARY element. + * Any closed outline inside the main outline is a hole + * All contours should be closed, i.e. valid closed polygon vertices + */ +bool SPECCTRA_DB::GetBoardPolygonOutlines( BOARD* aBoard, + CPOLYGONS_LIST& aOutlines, + CPOLYGONS_LIST& aHoles, + wxString* aErrorText ) +{ + bool success = true; + double specctra2UIfactor = IU_PER_MM / 1000.0; // Specctra unite = micron + + if( ! pcb ) + { + pcb = new PCB(); + pcb->structure = new STRUCTURE( pcb ); + } + + CPolyPt corner; + BOUNDARY* boundary = new BOUNDARY( 0 ); + pcb->structure->SetBOUNDARY( boundary ); + + try + { + fillBOUNDARY( aBoard, boundary ); + std::vector buffer; + boundary->GetCorners( buffer ); + + for( unsigned ii = 0; ii < buffer.size(); ii+=2 ) + { + corner.x = buffer[ii] * specctra2UIfactor; + corner.y = - buffer[ii+1] * specctra2UIfactor; + aOutlines.Append( corner ); + } + + aOutlines.CloseLastContour(); + + // Export holes, stored as keepouts polygonal shapes. + // by fillBOUNDARY() + KEEPOUTS& holes = pcb->structure->keepouts; + + for( KEEPOUTS::iterator i=holes.begin(); i!=holes.end(); ++i ) + { + KEEPOUT& keepout = *i; + PATH* poly_hole = (PATH*)keepout.shape; + POINTS& plist = poly_hole->GetPoints(); + for( unsigned ii = 0; ii < plist.size(); ii+=2 ) + { + corner.x = plist[ii].x * specctra2UIfactor; + corner.y = - plist[ii].y * specctra2UIfactor; + aHoles.Append( corner ); + } + aHoles.CloseLastContour(); + } + } + catch( IO_ERROR ioe ) + { + // Creates a valid polygon outline is not possible. + // So uses the board edge cuts bounding box to create a + // rectangular outline + // (when no edge cuts items, fillBOUNDARY biuld n outline + // from global bounding box + success = false; + if( aErrorText ) + *aErrorText = ioe.errorText; + + EDA_RECT bbbox = aBoard->ComputeBoundingBox( true ); + corner.x = bbbox.GetOrigin().x; + corner.y = bbbox.GetOrigin().y; + aOutlines.Append( corner ); + + corner.x = bbbox.GetOrigin().x; + corner.y = bbbox.GetEnd().y; + aOutlines.Append( corner ); + + corner.x = bbbox.GetEnd().x; + corner.y = bbbox.GetEnd().y; + aOutlines.Append( corner ); + + corner.x = bbbox.GetEnd().x; + corner.y = bbbox.GetOrigin().y; + aOutlines.Append( corner ); + + aOutlines.CloseLastContour(); + } + + return success; +} + typedef std::set STRINGSET; typedef std::pair STRINGSET_PAIR;