Commit 4cbcf56c authored by jean-pierre charras's avatar jean-pierre charras

remove useless USE_BOOST_POLYGON_LIBRARY cmake option, and remove unused files.

BOOST POLYGON is always used in zone filling functions.
Kbool is still in use in other calculations.
parent 14c14860
...@@ -35,10 +35,6 @@ option(USE_WX_GRAPHICS_CONTEXT ...@@ -35,10 +35,6 @@ option(USE_WX_GRAPHICS_CONTEXT
option(USE_WX_OVERLAY option(USE_WX_OVERLAY
"Use wxOverlay: Always ON for MAC (default OFF). Warning, this is experimental") "Use wxOverlay: Always ON for MAC (default OFF). Warning, this is experimental")
option(USE_BOOST_POLYGON_LIBRARY
"Use boost polygon library instead of Kbool to calculate filled areas in zones (default ON)."
ON )
#One of these 2 option *must* be set to ON: #One of these 2 option *must* be set to ON:
option(KICAD_STABLE_VERSION option(KICAD_STABLE_VERSION
"set this option to ON to build the stable version of KICAD. mainly used to set version ID (default OFF)" "set this option to ON to build the stable version of KICAD. mainly used to set version ID (default OFF)"
...@@ -112,11 +108,6 @@ if(USE_WX_GRAPHICS_CONTEXT) ...@@ -112,11 +108,6 @@ if(USE_WX_GRAPHICS_CONTEXT)
add_definitions(-DUSE_WX_GRAPHICS_CONTEXT) add_definitions(-DUSE_WX_GRAPHICS_CONTEXT)
endif(USE_WX_GRAPHICS_CONTEXT) endif(USE_WX_GRAPHICS_CONTEXT)
if(USE_BOOST_POLYGON_LIBRARY)
set( USE_BOOST_POLYGON_LIBRARY ON )
add_definitions(-DUSE_BOOST_POLYGON_LIBRARY)
endif(USE_BOOST_POLYGON_LIBRARY)
# Allow user to override the default settings for adding images to menu items. By default # Allow user to override the default settings for adding images to menu items. By default
# images in menu items are enabled on all plaforms except OSX. This can be over ridden by # images in menu items are enabled on all plaforms except OSX. This can be over ridden by
# defining -DUSE_IMAGES_IN_MENUS=ON/OFF to force the preferred behavior. # defining -DUSE_IMAGES_IN_MENUS=ON/OFF to force the preferred behavior.
......
...@@ -333,7 +333,7 @@ void BM2CMP_FRAME::OnExportPcbnew( wxCommandEvent& event ) ...@@ -333,7 +333,7 @@ void BM2CMP_FRAME::OnExportPcbnew( wxCommandEvent& event )
if( path.IsEmpty() || !wxDirExists(path) ) if( path.IsEmpty() || !wxDirExists(path) )
path = ::wxGetCwd(); path = ::wxGetCwd();
wxString msg = _( "Footprint file (*.mod)|*.mod" ); wxString msg = _( "Footprint file (*.mod;*.emp)|*.mod;*.emp" );
wxFileDialog FileDlg( this, _( "Create a footprint file for PcbNew" ), wxFileDialog FileDlg( this, _( "Create a footprint file for PcbNew" ),
path, wxEmptyString, path, wxEmptyString,
msg, msg,
......
...@@ -532,12 +532,7 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event ) ...@@ -532,12 +532,7 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event )
tmp << wxT( "OFF\n" ); tmp << wxT( "OFF\n" );
#endif #endif
tmp << wxT( " USE_BOOST_POLYGON_LIBRARY=" ); tmp << wxT( " USE_BOOST_POLYGON_LIBRARY" );
#ifdef USE_BOOST_POLYGON_LIBRARY
tmp << wxT( "ON\n" );
#else
tmp << wxT( "OFF\n" );
#endif
wxTheClipboard->SetData( new wxTextDataObject( tmp ) ); wxTheClipboard->SetData( new wxTextDataObject( tmp ) );
wxTheClipboard->Close(); wxTheClipboard->Close();
......
...@@ -13,14 +13,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ...@@ -13,14 +13,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
### ###
# Sources # Sources
# #
# NOTE: Many of the commented out ones are nested in *.cpp files for dialogs
###
if( USE_BOOST_POLYGON_LIBRARY )
set(PCBNEW_SRC_FILL_ZONE zones_convert_brd_items_to_polygons_with_Boost.cpp)
else( USE_BOOST_POLYGON_LIBRARY )
set(PCBNEW_SRC_FILL_ZONE zones_convert_brd_items_to_polygons_with_Kbool.cpp)
endif( USE_BOOST_POLYGON_LIBRARY )
set(PCBNEW_DIALOGS set(PCBNEW_DIALOGS
dialogs/dialog_block_options_base.cpp dialogs/dialog_block_options_base.cpp
dialogs/dialog_cleaning_options_base.cpp dialogs/dialog_cleaning_options_base.cpp
...@@ -100,7 +92,6 @@ set(PCBNEW_SRCS ...@@ -100,7 +92,6 @@ set(PCBNEW_SRCS
controle.cpp controle.cpp
dimension.cpp dimension.cpp
cross-probing.cpp cross-probing.cpp
debug_kbool_key_file_fct.cpp
deltrack.cpp deltrack.cpp
${PCBNEW_DIALOGS} ${PCBNEW_DIALOGS}
dist.cpp dist.cpp
...@@ -185,7 +176,7 @@ set(PCBNEW_SRCS ...@@ -185,7 +176,7 @@ set(PCBNEW_SRCS
trpiste.cpp trpiste.cpp
work.cpp work.cpp
xchgmod.cpp xchgmod.cpp
${PCBNEW_SRC_FILL_ZONE} zones_convert_brd_items_to_polygons_with_Boost.cpp
zones_convert_to_polygons_aux_functions.cpp zones_convert_to_polygons_aux_functions.cpp
zones_by_polygon.cpp zones_by_polygon.cpp
zones_by_polygon_fill_functions.cpp zones_by_polygon_fill_functions.cpp
......
...@@ -659,13 +659,7 @@ void CreateThermalReliefPadPolygon( std::vector<CPolyPt>& aCornerBuffer, ...@@ -659,13 +659,7 @@ void CreateThermalReliefPadPolygon( std::vector<CPolyPt>& aCornerBuffer,
corners_buffer.push_back( corner ); corners_buffer.push_back( corner );
// Now, add the 4 holes ( each is the pattern, rotated by 0, 90, 180 and 270 deg // Now, add the 4 holes ( each is the pattern, rotated by 0, 90, 180 and 270 deg
// WARNING: problems with kbool if angle = 0 (in fact when angle < 200): // aThermalRot = 450 (45.0 degrees orientation) work fine.
// bad filled polygon on some cases, when pads are on a same vertical line
// this seems a bug in kbool polygon (exists in 2.0 kbool version)
// aThermalRot = 450 (45.0 degrees orientation) seems work fine.
// aThermalRot = 0 with thermal shapes without angle < 90 deg has problems in rare
// circumstances.
// Note: with the 2 step build ( thermal shapes added after areas are built), 0 seems work
int angle_pad = aPad.m_Orient; // Pad orientation int angle_pad = aPad.m_Orient; // Pad orientation
int th_angle = aThermalRot; int th_angle = aThermalRot;
......
/* file debug_kbool_key_file_fct.cpp
*/
#include <vector>
#include "fctsys.h"
#include "kicad_string.h"
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "zones.h"
#include "PolyLine.h"
#include "debug_kbool_key_file_fct.h"
#if defined (CREATE_KBOOL_KEY_FILES) || (CREATE_KBOOL_KEY_FILES_FIRST_PASS)
// Helper class to handle a coordinate
struct kfcoord
{
int x, y;
};
static FILE* kdebugFile;
static char sDate_Time[256];
static vector <kfcoord> s_EntityCoordinates;
void CreateKeyFile()
{
wxString datetimestr;
wxDateTime datetime = wxDateTime::Now();
datetime.SetCountry( wxDateTime::Country_Default );
datetimestr = datetime.FormatISODate( )
+ wxT(" ")
+ datetime.FormatISOTime( );
strcpy(sDate_Time, TO_UTF8(datetimestr) );
kdebugFile = fopen( KEYFILE_FILENAME, "wt" );
if( kdebugFile )
{
fprintf( kdebugFile, "# KEY file for GDS-II postprocessing tool\n" );
fprintf( kdebugFile, "# File = %s\n", KEYFILE_FILENAME );
fprintf( kdebugFile, "# ====================================================================\n");
fprintf( kdebugFile, "\nHEADER 5; # version\n");
fprintf( kdebugFile, "BGNLIB;\n");
fprintf( kdebugFile, "LASTMOD {%s}; # last modification time\n",sDate_Time );
fprintf( kdebugFile, "LASTACC {%s}; # last access time\n",sDate_Time );
fprintf( kdebugFile, "LIBNAME trial;\n" );
fprintf( kdebugFile, "UNITS;\n# Internal Pcbnew units are in 0.0001 inch\n" );
fprintf( kdebugFile, "USERUNITS 1; PHYSUNITS 1;\n\n" );
}
else
{
wxMessageBox( wxT( "CreateKeyFile() cannot create output file" ) );
}
s_EntityCoordinates.clear();
}
void CloseKeyFile()
{
if( kdebugFile )
{
fprintf( kdebugFile, "\nENDLIB;\n" );
fclose( kdebugFile );
}
s_EntityCoordinates.clear();
}
const char* sCurrEntityName = NULL;
void OpenKeyFileEntity( const char* aName )
{
if( kdebugFile )
{
fprintf( kdebugFile, "\nBGNSTR; # Begin of structure\n" );
fprintf( kdebugFile, "CREATION {%s}; # creation time\n",sDate_Time);
fprintf( kdebugFile, "LASTMOD {%s}; # last modification time\n",sDate_Time);
fprintf( kdebugFile, "STRNAME %s;\n", aName );
}
sCurrEntityName = aName;
s_EntityCoordinates.clear();
}
void CloseKeyFileEntity()
{
if( kdebugFile )
fprintf( kdebugFile, "\nENDSTR %s;\n", sCurrEntityName );
}
/* start a polygon entity in key file
*/
void StartKeyFilePolygon( int aLayer)
{
s_EntityCoordinates.clear();
fprintf( kdebugFile, "\nBOUNDARY; LAYER %d; DATATYPE 0;\n", aLayer );
}
/* add a polygon corner to the current polygon entity in key file
*/
void AddKeyFilePointXY( int aXcoord, int aYcoord)
{
kfcoord coord;
coord.x = aXcoord;
coord.y = aYcoord;
s_EntityCoordinates.push_back( coord );
}
/* Close a polygon entity in key file
* write the entire polygon data to the file
*/
void EndKeyFilePolygon()
{
// Polygon must be closed: test for that and close it if needed
if( s_EntityCoordinates.size() )
{
if( s_EntityCoordinates.back().x != s_EntityCoordinates[0].x
|| s_EntityCoordinates.back().y != s_EntityCoordinates[0].y )
s_EntityCoordinates.push_back( s_EntityCoordinates[0] );
}
fprintf( kdebugFile, " XY %d;\n", s_EntityCoordinates.size() );
for( unsigned ii = 0; ii < s_EntityCoordinates.size(); ii ++ )
fprintf( kdebugFile, " X %d; Y %d;\n",
s_EntityCoordinates[ii].x, s_EntityCoordinates[ii].y );
fprintf( kdebugFile, "ENDEL;\n" );
s_EntityCoordinates.clear();
}
void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer )
{
if( !kdebugFile )
return;
unsigned corners_count = aZone->m_FilledPolysList.size();
unsigned ic = 0;
while( ic < corners_count )
{
// write polygon:
StartKeyFilePolygon( aLayer );
for( ; ic < corners_count; ic++ )
{
CPolyPt* corner = &aZone->m_FilledPolysList[ic];
AddKeyFilePointXY( corner->x, corner->y );
if( corner->end_contour )
{
ic++;
break;
}
}
EndKeyFilePolygon();
}
}
#endif
/* debug_kbool_key_file_fct.h
*/
#ifndef _DEBUG_KBOOL_KEY_FILE_FCT_H_
#define _DEBUG_KBOOL_KEY_FILE_FCT_H_
/* 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_FIRST_PASS 1
//#define CREATE_KBOOL_KEY_FILES 1
#if defined (CREATE_KBOOL_KEY_FILES) || (CREATE_KBOOL_KEY_FILES_FIRST_PASS)
// Allows (or not) 0 degree orientation thermal shapes, for kbool tests
//#define CREATE_KBOOL_KEY_FILES_WITH_0_DEG
#define KEYFILE_FILENAME "pcbnew_dbgfile.key"
/**
* Function CreateKeyFile
* open KEYFILE_FILENAME file
* and create header
*/
void CreateKeyFile();
/**
* Function CloseKeyFile
* close KEYFILE_FILENAME file
*/
void CloseKeyFile();
/* create header to start an entity description
*/
void OpenKeyFileEntity(const char * aName);
/* close the entity description
*/
void CloseKeyFileEntity();
/* polygon creations:
*/
void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer);
void StartKeyFilePolygon( int aLayer);
void AddKeyFilePointXY( int aXcoord, int aYcoord);
void EndKeyFilePolygon();
#endif // CREATE_KBOOL_KEY_FILES
#endif // _DEBUG_KBOOL_KEY_FILE_FCT_H_
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#ifndef _POLYGONS_DEFS_H_ #ifndef _POLYGONS_DEFS_H_
#define _POLYGONS_DEFS_H_ #define _POLYGONS_DEFS_H_
#ifdef USE_BOOST_POLYGON_LIBRARY
#include "boost/polygon/polygon.hpp" #include "boost/polygon/polygon.hpp"
// Define some types used here from boost::polygon // Define some types used here from boost::polygon
...@@ -20,6 +18,4 @@ typedef bpl::polygon_data<int> KPolygon; ...@@ -20,6 +18,4 @@ typedef bpl::polygon_data<int> KPolygon;
typedef std::vector<KPolygon> KPolygonSet; typedef std::vector<KPolygon> KPolygonSet;
typedef bpl::point_data<int> KPolyPoint; typedef bpl::point_data<int> KPolyPoint;
#endif // USE_BOOST_POLYGON_LIBRARY
#endif // #ifndef _POLYGONS_DEFS_H_ #endif // #ifndef _POLYGONS_DEFS_H_
...@@ -125,14 +125,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -125,14 +125,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
*/ */
s_Correction = 1.0 / cos( 3.14159265 / s_CircleToSegmentsCount ); s_Correction = 1.0 / cos( 3.14159265 / s_CircleToSegmentsCount );
/* Uses a kbool engine to add holes in the m_FilledPolysList polygon. // This KPolygonSet is the area(s) to fill, with m_ZoneMinThickness/2
* Because this function is called just after creating the m_FilledPolysList,
* only one polygon is in list.
* (initial holes in zones are linked into outer contours by double overlapping segments).
* because after adding holes, many polygons could be exist in this list.
*/
// This polygon set is the area(s) to fill, with m_ZoneMinThickness/2
KPolygonSet polyset_zone_solid_areas; KPolygonSet polyset_zone_solid_areas;
int margin = m_ZoneMinThickness / 2; int margin = m_ZoneMinThickness / 2;
......
/*******************************************/
/* zones_convert_brd_items_to_polygons.cpp */
/*******************************************/
/* Functions to convert some board items to polygons
* (pads, tracks ..)
* This is used to calculate filled areas in copper zones.
* Filled areas are areas remainder of the full zone area after removed all polygons
* calculated from these items shapes and the clearance area
*
* Important note:
* Because filled areas must have a minimum thickness to match with Design rule, they are
* draw in 2 step:
* 1 - filled polygons are drawn
* 2 - polygon outlines are drawn with a "minimum thickness width" ( or with a minimum
* thickness pen )
* So outlines of filled polygons are calculated with the constraint they match with clearance,
* taking in account outlines have thickness
* This ensures:
* - areas meet the minimum thickness requirement.
* - shapes are smoothed.
*/
#include <math.h>
#include <vector>
#include "fctsys.h"
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "trigo.h"
#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)
// Kbool 2.0 has solved some problems, but not all
// Kbool 2.1 has solved some others problems, but not all
// Used to create data files to debug Kbool
#include "debug_kbool_key_file_fct.h"
// Also we can create test files for Kbool bebug purposes
// when CREATE_KBOOL_KEY_FILES is defined
// See debug_kbool_key_file_fct.h
extern void BuildUnconnectedThermalStubsPolygonList( std::vector<CPolyPt>& aCornerBuffer,
BOARD* aPcb, ZONE_CONTAINER* aZone,
double aArcCorrection,
int aRoundPadThermalRotation);
extern void Test_For_Copper_Island_And_Remove( BOARD* aPcb,
ZONE_CONTAINER* aZone_container );
extern void CreateThermalReliefPadPolygon( std::vector<CPolyPt>& aCornerBuffer,
D_PAD& aPad,
int aThermalGap,
int aCopperThickness,
int aMinThicknessValue,
int aCircleToSegmentsCount,
double aCorrectionFactor,
int aThermalRot );
// Local Functions:
static void AddPolygonCornersToBoolengine( std::vector <CPolyPt>& aCornersBuffer,
Bool_Engine* aBoolengine, GroupType aGroup );
// Local Variables:
#ifdef CREATE_KBOOL_KEY_FILES_WITH_0_DEG
static int s_thermalRot = 0;
#else
static int s_thermalRot = 450; // angle of stubs in thermal reliefs for round pads
#endif
/* how many segments are used to create a polygon from a circle: */
static int s_CircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; /* default value. the real value will be changed to
* ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF
* if m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF
*/
double s_Correction; /* mult coeff used to enlarge rounded and oval pads (and vias)
* because the segment approximation for arcs and circles
* create a smaller gap than a true circle
*/
/**
* Function AddClearanceAreasPolygonsToPolysList
* Supports a min thickness area constraint.
* Add non copper areas polygons (pads and tracks with clearence)
* to the filled copper area found
* in BuildFilledPolysListData after calculating filled areas in a zone
* Non filled copper areas are pads and track and their clearance areas
* The filled copper area must be computed just before.
* BuildFilledPolysListData() call this function just after creating the
* filled copper area polygon (without clearence areas
* to do that this function:
* 1 - creates a Bool_Engine,with option: holes are linked to outer contours by double
* overlapping segments this means the created polygons have no holes (hole are linked
* to outer outline by double overlapped segments and are therefore compatible with
* draw functions (DC draw polygons and Gerber or PS outputs)
* 2 - Add the main outline (zone outline) in group A
* 3 - Creates a correction using BOOL_CORRECTION operation to shrink the resulting area
* with m_ZoneMinThickness/2 value.
* The result is areas with a margin of m_ZoneMinThickness/2
* When drawing outline with segments having a thickness of m_ZoneMinThickness, the
* outlines will
* match exactly the initial outlines
* 4 - recreates the same Bool_Engine, with no correction
* 5 - Add the main modified outline (zone outline) in group A
* 6 - Add all non filled areas (pads, tracks) in group B with a clearance of m_Clearance +
* m_ZoneMinThickness/2
* 7 - calculates the polygon A - B
* 8 - put resulting list of polygons (filled areas) in m_FilledPolysList
* This zone contains pads with the same net.
* 9 - Remove insulated copper islands
* 10 - If Thermal shapes are wanted, remove copper around pads in zone, in order to create
* thes thermal shapes
* a - Creates a bool engine and add the last copper areas in group A
* b - Add thermal shapes (non copper ares in group B
* c - Calculates the polygon A - B
* 11 - Remove new insulated copper islands
*/
/* Important note:
* One can add thermal areas in the step 6, with others items to substract.
* It is faster.
* But :
* kbool fails sometimes in this case
* The separate step to make thermal shapes allows a more sophisticated algorith (todo)
* like remove thermal copper bridges in thermal shapes that are not connected to an area
*/
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{
// Set the number of segments in arc approximations
if( m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF )
s_CircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
else
s_CircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
/* calculates the coeff to compensate radius reduction of holes clearance
* due to the segment approx.
* For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2)
* s_Correction is 1 /cos( PI/s_CircleToSegmentsCount )
*/
s_Correction = 1.0 / cos( 3.14159265 / s_CircleToSegmentsCount );
/* Uses a kbool engine to add holes in the m_FilledPolysList polygon.
* Because this function is called just after creating the m_FilledPolysList,
* only one polygon is in list.
* (initial holes in zones are linked into outer contours by double overlapping segments).
* because after adding holes, many polygons could be exist in this list.
*/
Bool_Engine* booleng = new Bool_Engine();
ArmBoolEng( booleng, true );
/* First, Add the main polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine to do a BOOL_CORRECTION operation
* to reserve a m_ZoneMinThickness/2 margind around the outlines and holes
* the margin will be filled when redraw outilnes with segments having a width set to
* m_ZoneMinThickness
* so m_ZoneMinThickness is the min thickness of the filled zones areas
*/
CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A );
booleng->SetCorrectionFactor( (double) -m_ZoneMinThickness / 2 );
booleng->Do_Operation( BOOL_CORRECTION );
/* Now copy the new outline in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng;
if( m_FilledPolysList.size() == 0 )
return;
/* Second, Add the main (corrected) polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation
* All areas to remove will be put in GroupB in Bool_Engine
*/
booleng = new Bool_Engine();
ArmBoolEng( booleng, true );
/* Calculates the clearance value that meet DRC requirements
* from m_ZoneClearance and clearance from the corresponding netclass
* We have a "local" clearance in zones because most of time
* clearance between a zone and others items is bigger than the netclass clearance
* this is more true for small clearance values
* Note also the "local" clearance is used for clearance between non copper items
* or items like texts on copper layers
*/
int margin = m_ZoneMinThickness / 2;
int zone_clearance = max( m_ZoneClearance, GetClearance() );
zone_clearance += margin;
/* 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 biggest clearance found in Netclass list
*/
EDA_RECT item_boundingbox;
EDA_RECT zone_boundingbox = GetBoundingBox();
int biggest_clearance = aPcb->GetBiggestClearanceValue();
biggest_clearance = MAX( biggest_clearance, zone_clearance );
zone_boundingbox.Inflate( 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
*/
int item_clearance;
// static to avoid unnecessary memory allocation when filling many zones.
static std::vector <CPolyPt> cornerBufferPolysToSubstract;
cornerBufferPolysToSubstract.clear();
/* Use a dummy pad to calculate hole clerance when a pad is not on all copper layers
* and this pad has a hole
* This dummy pad has the size and shape of the hole
* Therefore, this dummy pad is a circle or an oval.
* A pad must have a parent because some functions expect a non null parent
* to find the parent board, and some other data
*/
MODULE dummymodule( aPcb ); // Creates a dummy parent
D_PAD dummypad( &dummymodule );
D_PAD* nextpad;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = nextpad )
{
nextpad = pad->Next(); // pad pointer can be modified by next code, so calculate the next pad here
if( !pad->IsOnLayer( GetLayer() ) )
{
/* Test fo pads that are on top or bottom only and have a hole.
* There are curious pads but they can be used for some components that are inside the
* board (in fact inside the hole. Some photo diodes and Leds are like this)
*/
if( (pad->m_Drill.x == 0) && (pad->m_Drill.y == 0) )
continue;
// Use a dummy pad to calculate a hole shape that have the same dimension as the pad hole
dummypad.m_Size = pad->m_Drill;
dummypad.m_Orient = pad->m_Orient;
dummypad.m_PadShape = pad->m_DrillShape;
dummypad.m_Pos = pad->m_Pos;
pad = &dummypad;
}
if( pad->GetNet() != GetNet() )
{
item_clearance = pad->GetClearance() + margin;
item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
int clearance = MAX( zone_clearance, item_clearance );
pad->TransformShapeWithClearanceToPolygon( cornerBufferPolysToSubstract,
clearance,
s_CircleToSegmentsCount,
s_Correction );
}
continue;
}
int gap = zone_clearance;
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 that shapes are not changed by thermal pads or others
{
item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
pad->TransformShapeWithClearanceToPolygon( cornerBufferPolysToSubstract,
gap,
s_CircleToSegmentsCount,
s_Correction );
}
}
}
}
/* Add holes (i.e. tracks and vias areas as polygons outlines)
* in cornerBufferPolysToSubstract
*/
for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
{
if( !track->IsOnLayer( GetLayer() ) )
continue;
if( track->GetNet() == GetNet() && (GetNet() != 0) )
continue;
item_clearance = track->GetClearance() + margin;
item_boundingbox = track->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
int clearance = MAX( zone_clearance, item_clearance );
track->TransformShapeWithClearanceToPolygon( cornerBufferPolysToSubstract,
clearance,
s_CircleToSegmentsCount,
s_Correction );
}
}
/* Add module edge items that are on copper layers
* Pcbnew allows these items to be on copper layers in microwvae applictions
* This is a bad thing, but must be handle here, until a better way is found
*/
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
for( BOARD_ITEM* item = module->m_Drawings; item; item = item->Next() )
{
if( !item->IsOnLayer( GetLayer() ) )
continue;
if( item->Type() != PCB_MODULE_EDGE_T )
continue;
item_boundingbox = item->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
( (EDGE_MODULE*) item )->TransformShapeWithClearanceToPolygon(
cornerBufferPolysToSubstract, zone_clearance,
s_CircleToSegmentsCount, s_Correction );
}
}
}
// 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 )
continue;
switch( item->Type() )
{
case PCB_LINE_T:
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
cornerBufferPolysToSubstract,
zone_clearance,
s_CircleToSegmentsCount,
s_Correction );
break;
case PCB_TEXT_T:
( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygon(
cornerBufferPolysToSubstract,
zone_clearance,
s_CircleToSegmentsCount,
s_Correction );
break;
default:
break;
}
}
// cornerBufferPolysToSubstract contains polygons to substract,
// prepare booleng to do that:
AddPolygonCornersToBoolengine( cornerBufferPolysToSubstract, booleng, GROUP_B );
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
for( unsigned icnt = 0; icnt < cornerBuffer.size(); )
{
StartKeyFilePolygon( 1 );
for( ii = icnt; ii < cornerBuffer.size(); ii++ )
{
AddKeyFilePointXY( cornerBufferPolysToSubstract[ii].x,
cornerBufferPolysToSubstract[ii].y );
if( cornerBufferPolysToSubstract[ii].end_contour )
break;
}
EndKeyFilePolygon();
icnt = ii + 1;
}
CloseKeyFileEntity();
CloseKeyFile();
#endif
/* calculates copper areas */
if( cornerBufferPolysToSubstract.size() > 0 )
{
/* Add the main corrected polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine
*/
CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A );
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
}
delete booleng;
// Remove insulated islands:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
// remove thermal gaps if required:
if( m_PadOption != THERMAL_PAD || aPcb->m_Modules == NULL )
return;
// Remove thermal symbols
cornerBufferPolysToSubstract.clear();
if( m_PadOption == THERMAL_PAD )
{
booleng = new Bool_Engine();
ArmBoolEng( booleng, true );
#ifdef CREATE_KBOOL_KEY_FILES
CreateKeyFile();
OpenKeyFileEntity( "Layer" );
CopyPolygonsFromFilledPolysListToKeyFile( this, 0 );
#endif
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
{
if( !pad->IsOnLayer( GetLayer() ) )
continue;
if( pad->GetNet() != GetNet() )
continue;
item_boundingbox = pad->GetBoundingBox();
item_boundingbox.Inflate( m_ThermalReliefGapValue );
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
CreateThermalReliefPadPolygon( cornerBufferPolysToSubstract,
*pad, m_ThermalReliefGapValue,
m_ThermalReliefCopperBridgeValue,
m_ZoneMinThickness,
s_CircleToSegmentsCount,
s_Correction, s_thermalRot );
}
}
}
if( cornerBufferPolysToSubstract.size() )
{
/* Add the main corrected polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine
*/
CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A );
// cornerBufferPolysToSubstract contains polygons to substract,
// prepare booleng to do that:
AddPolygonCornersToBoolengine( cornerBufferPolysToSubstract, booleng, GROUP_B );
/* remove thermal areas (non copper areas) */
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
}
delete booleng;
// Remove insulated islands:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
#ifdef CREATE_KBOOL_KEY_FILES
for( unsigned icnt = 0; icnt < cornerBufferPolysToSubstract.size(); )
{
StartKeyFilePolygon( 1 );
for( ii = icnt; ii < cornerBufferPolysToSubstract.size(); ii++ )
{
AddKeyFilePointXY( cornerBufferPolysToSubstract[ii].x,
cornerBufferPolysToSubstract[ii].y );
if( cornerBufferPolysToSubstract[ii].end_contour )
break;
}
EndKeyFilePolygon();
icnt = ii + 1;
}
}
CloseKeyFileEntity();
CloseKeyFile();
#endif
}
// Now we remove all unused thermal stubs.
#define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations
#ifdef REMOVE_UNUSED_THERMAL_STUBS
// Test thermal stubs connections and add polygons to remove unconnected stubs.
booleng = new Bool_Engine();
ArmBoolEng( booleng, true );
cornerBufferPolysToSubstract.clear();
BuildUnconnectedThermalStubsPolygonList( cornerBufferPolysToSubstract, aPcb, this,
s_Correction, s_thermalRot );
/* remove copper areas */
if( cornerBufferPolysToSubstract.size() )
{
/* Add the main corrected polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine
*/
CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A );
AddPolygonCornersToBoolengine( cornerBufferPolysToSubstract, booleng, GROUP_B );
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
// Remove insulated islands, if any:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
}
delete booleng;
#endif // REMOVE_UNUSED_THERMAL_STUBS
}
/** AddPolygonCornersToBoolengine
* copy a set of polygons in a kbool engine
* @param aCornersBuffer = list of polygons defined by corners.
* @param aBoolengine = the kbool engine to populate
* @param aGroup = GROUP_A or GROUP_B
*/
void AddPolygonCornersToBoolengine( std::vector <CPolyPt>& aCornersBuffer,
Bool_Engine* aBoolengine, GroupType aGroup )
{
unsigned ii;
for( unsigned icnt = 0; icnt < aCornersBuffer.size(); )
{
aBoolengine->StartPolygonAdd( aGroup );
for( ii = icnt; ii < aCornersBuffer.size(); ii++ )
{
aBoolengine->AddPoint( aCornersBuffer[ii].x, aCornersBuffer[ii].y );
if( aCornersBuffer[ii].end_contour )
break;
}
aBoolengine->EndPolygonAdd();
icnt = ii + 1;
}
}
/**
* Function CopyPolygonsFromFilledPolysListToBoolengine
* Copy (Add) polygons found in m_FilledPolysList to kbool BoolEngine
* m_FilledPolysList may have more than one polygon
* @param aBoolengine = kbool engine
* @param aGroup = group in kbool engine (GROUP_A or GROUP_B only)
* @return the corner count
*/
int ZONE_CONTAINER::CopyPolygonsFromFilledPolysListToBoolengine( Bool_Engine* aBoolengine,
GroupType aGroup )
{
unsigned corners_count = m_FilledPolysList.size();
int count = 0;
unsigned ic = 0;
while( ic < corners_count )
{
if( aBoolengine->StartPolygonAdd( aGroup ) )
{
for( ; ic < corners_count; ic++ )
{
CPolyPt* corner = &m_FilledPolysList[ic];
aBoolengine->AddPoint( corner->x, corner->y );
count++;
if( corner->end_contour )
{
ic++;
break;
}
}
aBoolengine->EndPolygonAdd();
}
}
return count;
}
/**
* Function CopyPolygonsFromBoolengineToFilledPolysList
* Copy (Add) polygons created by kbool (after Do_Operation) to m_FilledPolysList
* @param aBoolengine = kbool engine
* @return the corner count
*/
int ZONE_CONTAINER::CopyPolygonsFromBoolengineToFilledPolysList( Bool_Engine* aBoolengine )
{
int count = 0;
while( aBoolengine->StartPolygonGet() )
{
CPolyPt corner( 0, 0, false );
while( aBoolengine->PolygonHasMorePoints() )
{
corner.x = (int) aBoolengine->GetPolygonXPoint();
corner.y = (int) aBoolengine->GetPolygonYPoint();
corner.end_contour = false;
// Flag this corner if starting a hole connection segment:
// This is used by draw functions to draw only useful segments (and not extra segments)
corner.utility = (aBoolengine->GetPolygonPointEdgeType() == KB_FALSE_EDGE) ? 1 : 0;
m_FilledPolysList.push_back( corner );
count++;
}
corner.end_contour = true;
m_FilledPolysList.pop_back();
m_FilledPolysList.push_back( corner );
aBoolengine->EndPolygonGet();
}
return count;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment