Merge trunk @ 5308
This commit is contained in:
commit
0cf91f466f
|
@ -226,8 +226,8 @@ if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
|||
|
||||
if( APPLE )
|
||||
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__ASSERTMACROS__ -mmacosx-version-min=10.5" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ASSERTMACROS__ -mmacosx-version-min=10.5" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__ASSERTMACROS__" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ASSERTMACROS__" )
|
||||
|
||||
# Allows .dylib relocation in the future - needed by fixbundle
|
||||
set( CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -headerpad_max_install_names")
|
||||
|
@ -240,6 +240,12 @@ if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
|||
EXEC_PROGRAM( wx-config ARGS --cxx OUTPUT_VARIABLE CMAKE_CXX_COMPILER )
|
||||
endif()
|
||||
|
||||
# There seems to be no consistent behavior when -mmacosx-min-version is
|
||||
# not specified, so force user to set minimum OSX version to build for
|
||||
if( NOT CMAKE_OSX_DEPLOYMENT_TARGET )
|
||||
message( FATAL_ERROR "Please specify target OS X version using -DCMAKE_OSX_DEPLOYMENT_TARGET=10.x" )
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
endif( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
|
|
|
@ -140,11 +140,8 @@ endif()
|
|||
|
||||
|
||||
if( APPLE )
|
||||
# I set this to being compatible with wxWidgets
|
||||
# wxWidgets still using libstdc++ (gcc), meanwhile OSX
|
||||
# has switched to libc++ (llvm) by default
|
||||
set( BOOST_CXXFLAGS "cxxflags=-mmacosx-version-min=10.5 -fno-common" )
|
||||
set( BOOST_LINKFLAGS "linkflags=-mmacosx-version-min=10.5 -fno-common" )
|
||||
set( BOOST_CXXFLAGS "cxxflags=-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -fno-common" )
|
||||
set( BOOST_LINKFLAGS "linkflags=-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -fno-common" )
|
||||
set( BOOST_TOOLSET "toolset=darwin" )
|
||||
|
||||
if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Compiling KiCad on Apple Mac OS X
|
||||
=================================
|
||||
|
||||
Building on OSX is very similar to building on Linux. This document will provide
|
||||
a complete walk-through on what to do but it will focus on OSX specific things.
|
||||
See general documentation on non-OSX specific KiCad build switches, etc.
|
||||
Building on OS X is very similar to building on Linux. This document will provide
|
||||
a complete walk-through on what to do but it will focus on OS X specific things.
|
||||
See general documentation on non OS X specific KiCad build switches, etc.
|
||||
|
||||
|
||||
Prerequisites
|
||||
|
@ -24,6 +24,7 @@ Mandatory library dependencies needed to compile KiCad:
|
|||
OR
|
||||
wxPython - A blending of the wxWidgets C++ class library with the Python
|
||||
programming language
|
||||
* SWIG - Interface compiler (only needed for scripting/wxPython builds)
|
||||
|
||||
Optional library dependencies, depends on used KiCad features
|
||||
* OpenSSL - The Open Source toolkit for SSL/TLS
|
||||
|
@ -31,7 +32,7 @@ Optional library dependencies, depends on used KiCad features
|
|||
|
||||
All tools (except XCode, of course) and all dependencies except wxWidgets/wxPython
|
||||
can be compiled manually, but it is advised to install them using your favorite
|
||||
package manager for OSX like MacPorts or Homebrew.
|
||||
package manager for OS X like MacPorts or Homebrew.
|
||||
Depending on the package manager the development packages of the library
|
||||
dependencies may have to be installed (usually something like <pkg>-dev or
|
||||
<pkg>-devel).
|
||||
|
@ -44,7 +45,7 @@ automatically by KiCad build process.
|
|||
IMPORTANT:
|
||||
At the moment you *must not* use a wxWidgets/wxPython version installed by any
|
||||
package manager.
|
||||
KiCad on OSX needs overlay support and some other fixes, which are not yet
|
||||
KiCad on OS X needs overlay support and some other fixes, which are not yet
|
||||
contained in mainline wxWidgets/wxPython sources and builds.
|
||||
If you don't use a patched wxWidgets you will get graphical artifacts (something
|
||||
like a magnifying glass effect in the upper left corner of KiCad windows) or
|
||||
|
@ -92,13 +93,15 @@ It is recommended to use the latest stable version. As of this writing this is
|
|||
|
||||
There is a little helper script osx_build_wx.sh in kicad/scripts that does all
|
||||
the patching/configuring/compiling of wxWidgets or wxPython for you.
|
||||
Go to your working root "KiCad" and run:
|
||||
# kicad/scripts/osx_build_wx.sh wx-src wx-bin kicad "-j4"
|
||||
Go to your working root "KiCad" and for example run:
|
||||
# kicad/scripts/osx_build_wx.sh wx-src wx-bin kicad 10.7 "-j4"
|
||||
|
||||
First parameter is the source folder of wxWidgets/wxPython, second parameter the
|
||||
target folder for compiled binaries, third parameter is the kicad folder, and
|
||||
the last optional parameter are make options used during the build (in this
|
||||
case for building with 4 jobs in parallel).
|
||||
target folder for compiled binaries, and third parameter is the kicad folder.
|
||||
The fourth parameter is the minimum OS X version you are building for (see the
|
||||
section about compiling KiCad for further notes on minimum OS X version).
|
||||
The last parameter is optional and contains make options used during the build
|
||||
(in this example for building with 4 jobs in parallel).
|
||||
The script will automatically detect if you are compiling wxWidgets or wxPython.
|
||||
NOTE: All paths are assumed to be relative to the current directory, i.e., the
|
||||
working root you are in.
|
||||
|
@ -137,10 +140,8 @@ work:
|
|||
--with-zlib=builtin \
|
||||
--with-expat=builtin \
|
||||
--without-liblzma \
|
||||
--with-macosx-version-min=10.5 \
|
||||
--with-macosx-version-min=<osxtarget> \
|
||||
--enable-universal-binary=i386,x86_64 \
|
||||
CPPFLAGS="-stdlib=libstdc++" \
|
||||
LDFLAGS="-stdlib=libstdc++" \
|
||||
CC=clang \
|
||||
CXX=clang++
|
||||
If you know what you are doing, you can of course use different settings.
|
||||
|
@ -157,6 +158,7 @@ Now, configure KiCad without scripting support:
|
|||
# cmake ../kicad \
|
||||
-DCMAKE_C_COMPILER=clang \
|
||||
-DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \
|
||||
-DwxWidgets_CONFIG_EXECUTABLE=../wx-bin/bin/wx-config \
|
||||
-DKICAD_SCRIPTING=OFF \
|
||||
-DKICAD_SCRIPTING_MODULES=OFF \
|
||||
|
@ -168,6 +170,7 @@ or, configure KiCad with scripting support:
|
|||
# cmake ../kicad \
|
||||
-DCMAKE_C_COMPILER=clang \
|
||||
-DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \
|
||||
-DwxWidgets_CONFIG_EXECUTABLE=../wx-bin/bin/wx-config \
|
||||
-DPYTHON_EXECUTABLE=`which python` \
|
||||
-DPYTHON_SITE_PACKAGE_PATH=`pwd`/../wx-bin/lib/python2.7/site-packages \
|
||||
|
@ -182,7 +185,19 @@ been generated when compiling/installing wxPython. If you want to use a specific
|
|||
python, you can also specify it via "-DPYTHON_EXECUTABLE" instead of using
|
||||
`which python` (this one will just detect/use you default python).
|
||||
|
||||
Now KiCad is configured using default features/build-switches. To add Magic
|
||||
The parameter "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.x" is mandatory, you have to
|
||||
specify the (minimum) OS X version you intend to build for. It is important that
|
||||
at least wxWidgets/wxPython and KiCad (and boost, if you use an external build)
|
||||
are built using the same or compatible settings. If not, you might get linker
|
||||
errors, because this parameter influences which standard C++ library is being
|
||||
used (libstdc++ vs. libc++).
|
||||
If you don't know what to use and you are only building for your machine, just
|
||||
set it to your current OS X version (e.g., MacPorts always builds this way).
|
||||
Binaries built with a target OS X version <10.7 are known to show strange
|
||||
behavior in some situations on recent systems (maybe because libc++ is standard
|
||||
on everything >= 10.7 and problems arise due to mixing libstdc++/libc++).
|
||||
|
||||
Now KiCad is configured using default features/build-switches. To add Magic
|
||||
Trackpad pinch-to-zoom support, add -DUSE_OSX_MAGNIFY_EVENT=ON to the above.
|
||||
See Documentation/compiling/build-config.txt for a list of all CMake options
|
||||
available when compiling KiCad.
|
||||
|
|
|
@ -548,6 +548,9 @@ int EDA_BASE_FRAME::ReadHotkeyConfigFile( const wxString& aFilename,
|
|||
{
|
||||
wxFile cfgfile( aFilename );
|
||||
|
||||
if( !cfgfile.IsOpened() ) // There is a problem to open file
|
||||
return 0;
|
||||
|
||||
// get length
|
||||
cfgfile.SeekEnd();
|
||||
wxFileOffset size = cfgfile.Tell();
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
wxBoxSizer* m_RightBoxSizer;
|
||||
wxBoxSizer* m_RightOptionsBoxSizer;
|
||||
wxBoxSizer* m_LowBoxSizer;
|
||||
wxRadioBox* m_NetOption;
|
||||
|
||||
private:
|
||||
wxString m_pageNetFmtName;
|
||||
|
||||
|
@ -104,14 +104,12 @@ public:
|
|||
/**
|
||||
* function GetPageNetFmtName
|
||||
* @return the name of the netlist format for this page
|
||||
* This is usually the page label.
|
||||
* For the pcbnew netlist, this is "LegacyPcbnew"
|
||||
* when the "old" format is selected
|
||||
* and "PcbnewAdvanced" when the advanced format (S expr fmt)is selected
|
||||
* This is also the page label.
|
||||
*/
|
||||
const wxString GetPageNetFmtName();
|
||||
|
||||
void SetPageNetFmtName( const wxString &aName ) { m_pageNetFmtName = aName; }
|
||||
const wxString GetPageNetFmtName()
|
||||
{
|
||||
return m_pageNetFmtName;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -242,9 +240,6 @@ enum id_netlist {
|
|||
#define NETLIST_USE_DEFAULT_NETNAME wxT( "NetlistUseDefaultNetname" )
|
||||
#define NETLIST_PSPICE_USE_NETNAME wxT( "SpiceUseNetNames" )
|
||||
|
||||
#define NETLIST_PCBNEW_LEGACY wxT("LegacyPcbnew" )
|
||||
#define NETLIST_PCBNEW_NEWFMT wxT("PcbnewAdvanced" )
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( NETLIST_DIALOG, NETLIST_DIALOG_BASE )
|
||||
EVT_BUTTON( ID_CREATE_NETLIST, NETLIST_DIALOG::GenNetlist )
|
||||
|
@ -269,23 +264,15 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent,
|
|||
m_AddSubPrefix = NULL;
|
||||
m_SpiceUseNetcodeAsNetname = NULL;
|
||||
m_ButtonCancel = NULL;
|
||||
m_NetOption = NULL;
|
||||
|
||||
wxString netfmtName = ((NETLIST_DIALOG*)parent->GetParent())->m_NetFmtName;
|
||||
int fmtOption = 1; // Default Pcbnew netlist fmt is advanced fmt
|
||||
|
||||
bool selected = m_pageNetFmtName == netfmtName;
|
||||
|
||||
// PCBNEW Format is a special type:
|
||||
if( id_NetType == NET_TYPE_PCBNEW )
|
||||
{
|
||||
if( netfmtName.IsEmpty() || netfmtName == NETLIST_PCBNEW_NEWFMT )
|
||||
selected = true;
|
||||
if( netfmtName == NETLIST_PCBNEW_LEGACY )
|
||||
{
|
||||
selected = true;
|
||||
fmtOption = 0;
|
||||
}
|
||||
selected = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,34 +299,9 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent,
|
|||
_( "Default format" ) );
|
||||
m_LeftBoxSizer->Add( m_IsCurrentFormat, 0, wxGROW | wxALL, 5 );
|
||||
m_IsCurrentFormat->SetValue( selected );
|
||||
|
||||
if( id_NetType == NET_TYPE_PCBNEW )
|
||||
{
|
||||
wxString netlist_opt[2] = { _( "Legacy Format" ), _( "Advanced Format" ) };
|
||||
m_NetOption = new wxRadioBox( this, -1, _( "Netlist Options:" ),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
2, netlist_opt, 1,
|
||||
wxRA_SPECIFY_COLS );
|
||||
m_NetOption->SetSelection( fmtOption );
|
||||
m_LeftBoxSizer->Add( m_NetOption, 0, wxGROW | wxALL, 5 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const wxString NETLIST_PAGE_DIALOG::GetPageNetFmtName()
|
||||
{
|
||||
// PCBNEW Format is a special type:
|
||||
if( m_IdNetType == NET_TYPE_PCBNEW )
|
||||
{
|
||||
if( m_NetOption->GetSelection() )
|
||||
return NETLIST_PCBNEW_NEWFMT;
|
||||
else
|
||||
return NETLIST_PCBNEW_LEGACY;
|
||||
}
|
||||
|
||||
return m_pageNetFmtName;
|
||||
}
|
||||
|
||||
|
||||
NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
|
||||
NETLIST_DIALOG_BASE( parent )
|
||||
|
@ -599,8 +561,7 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
|
|||
break;
|
||||
|
||||
case NET_TYPE_PCBNEW:
|
||||
if( currPage->m_NetOption->GetSelection() != 0 )
|
||||
netlist_opt = NET_PCBNEW_USE_NEW_FORMAT;
|
||||
netlist_opt = NET_PCBNEW_USE_NEW_FORMAT;
|
||||
break;
|
||||
|
||||
case NET_TYPE_ORCADPCB2:
|
||||
|
|
|
@ -146,7 +146,7 @@ void SCH_EDIT_FRAME::ReCreateHToolbar()
|
|||
HELP_ANNOTATE );
|
||||
|
||||
m_mainToolBar->AddTool( ID_GET_ERC, wxEmptyString, KiBitmap( erc_xpm ),
|
||||
_( "Perform electric rules check" ) );
|
||||
_( "Perform electrical rule check" ) );
|
||||
|
||||
m_mainToolBar->AddTool( ID_GET_NETLIST, wxEmptyString, KiBitmap( netlist_xpm ),
|
||||
_( "Generate netlist" ) );
|
||||
|
|
|
@ -40,6 +40,7 @@ set( GERBVIEW_SRCS
|
|||
class_gerber_draw_item.cpp
|
||||
class_gerbview_layer_widget.cpp
|
||||
class_gbr_layer_box_selector.cpp
|
||||
class_X2_gerber_attributes.cpp
|
||||
controle.cpp
|
||||
dcode.cpp
|
||||
draw_gerber_screen.cpp
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#include <gerbview.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <class_GERBER.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
/**
|
||||
|
@ -88,9 +91,10 @@ void GERBER_LAYER::ResetDefaultValues()
|
|||
GERBER_IMAGE::GERBER_IMAGE( GERBVIEW_FRAME* aParent, int aLayer )
|
||||
{
|
||||
m_Parent = aParent;
|
||||
m_GraphicLayer = aLayer; // Graphic layer Number
|
||||
m_GraphicLayer = aLayer; // Graphic layer Number
|
||||
|
||||
m_Selected_Tool = FIRST_DCODE;
|
||||
m_FileFunction = NULL; // file function parameters
|
||||
|
||||
ResetDefaultValues();
|
||||
|
||||
|
@ -104,9 +108,9 @@ GERBER_IMAGE::~GERBER_IMAGE()
|
|||
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
|
||||
{
|
||||
delete m_Aperture_List[ii];
|
||||
|
||||
// m_Aperture_List[ii] = NULL;
|
||||
}
|
||||
|
||||
delete m_FileFunction;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -158,6 +162,11 @@ void GERBER_IMAGE::ResetDefaultValues()
|
|||
m_FileName.Empty();
|
||||
m_ImageName = wxT( "no name" ); // Image name from the IN command
|
||||
m_ImageNegative = false; // true = Negative image
|
||||
m_IsX2_file = false; // true only if a %TF, %TA or %TD command
|
||||
delete m_FileFunction; // file function parameters
|
||||
m_FileFunction = NULL;
|
||||
m_MD5_value.Empty(); // MD5 value found in a %TF.MD5 command
|
||||
m_PartString.Empty(); // string found in a %TF.Part command
|
||||
m_hasNegativeItems = -1; // set to uninitialized
|
||||
m_ImageJustifyOffset = wxPoint(0,0); // Image justify Offset
|
||||
m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false)
|
||||
|
@ -361,3 +370,171 @@ void GERBER_IMAGE::DisplayImageInfo( void )
|
|||
m_Parent->AppendMsgPanel( _( "Image Justify Offset" ), msg, DARKRED );
|
||||
}
|
||||
|
||||
// GERBER_IMAGE_LIST is a helper class to handle a list of GERBER_IMAGE files
|
||||
GERBER_IMAGE_LIST::GERBER_IMAGE_LIST()
|
||||
{
|
||||
m_GERBER_List.reserve( GERBER_DRAWLAYERS_COUNT );
|
||||
|
||||
for( unsigned layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
|
||||
m_GERBER_List.push_back( NULL );
|
||||
}
|
||||
|
||||
GERBER_IMAGE_LIST::~GERBER_IMAGE_LIST()
|
||||
{
|
||||
ClearList();
|
||||
|
||||
for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
|
||||
{
|
||||
delete m_GERBER_List[layer];
|
||||
m_GERBER_List[layer] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GERBER_IMAGE* GERBER_IMAGE_LIST::GetGbrImage( int aIdx )
|
||||
{
|
||||
if( (unsigned)aIdx < m_GERBER_List.size() )
|
||||
return m_GERBER_List[aIdx];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a new, empty GERBER_IMAGE* at index aIdx
|
||||
* or at the first free location if aIdx < 0
|
||||
* @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
|
||||
* @return true if the index used, or -1 if no room to add image
|
||||
*/
|
||||
int GERBER_IMAGE_LIST::AddGbrImage( GERBER_IMAGE* aGbrImage, int aIdx )
|
||||
{
|
||||
int idx = aIdx;
|
||||
|
||||
if( idx < 0 )
|
||||
{
|
||||
for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ )
|
||||
{
|
||||
if( !IsUsed( idx ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( idx >= (int)m_GERBER_List.size() )
|
||||
return -1; // No room
|
||||
|
||||
m_GERBER_List[idx] = aGbrImage;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
// remove all loaded data in list, but do not delete empty images
|
||||
// (can be reused)
|
||||
void GERBER_IMAGE_LIST::ClearList()
|
||||
{
|
||||
for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
|
||||
ClearImage( layer );
|
||||
}
|
||||
|
||||
// remove the loaded data of image aIdx, but do not delete it
|
||||
void GERBER_IMAGE_LIST::ClearImage( int aIdx )
|
||||
{
|
||||
if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() && m_GERBER_List[aIdx] )
|
||||
{
|
||||
m_GERBER_List[aIdx]->InitToolTable();
|
||||
m_GERBER_List[aIdx]->ResetDefaultValues();
|
||||
m_GERBER_List[aIdx]->m_InUse = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Build a name for image aIdx which can be used in layers manager
|
||||
const wxString GERBER_IMAGE_LIST::GetDisplayName( int aIdx )
|
||||
{
|
||||
wxString name;
|
||||
|
||||
GERBER_IMAGE* gerber = NULL;
|
||||
|
||||
if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() )
|
||||
gerber = m_GERBER_List[aIdx];
|
||||
|
||||
if( IsUsed(aIdx ) )
|
||||
{
|
||||
if( gerber->m_FileFunction )
|
||||
name.Printf( _( "Layer %d (%s, %s)" ), aIdx + 1,
|
||||
GetChars( gerber->m_FileFunction->GetFileType() ),
|
||||
GetChars( gerber->m_FileFunction->GetBrdLayerId() ) );
|
||||
else
|
||||
name.Printf( _( "Layer %d *" ), aIdx + 1 );
|
||||
}
|
||||
else
|
||||
name.Printf( _( "Layer %d" ), aIdx + 1 );
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// return true if image is used (loaded and not cleared)
|
||||
bool GERBER_IMAGE_LIST::IsUsed( int aIdx )
|
||||
{
|
||||
if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() )
|
||||
return m_GERBER_List[aIdx] != NULL && m_GERBER_List[aIdx]->m_InUse;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper function, for std::sort.
|
||||
// Sort loaded images by Z order priority, if they have the X2 FileFormat info
|
||||
// returns true if the first argument (ref) is ordered before the second (test).
|
||||
static bool sortZorder( const GERBER_IMAGE* const& ref, const GERBER_IMAGE* const& test )
|
||||
{
|
||||
if( !ref && !test )
|
||||
return false; // do not change order: no criteria to sort items
|
||||
|
||||
if( !ref || !ref->m_InUse )
|
||||
return false; // Not used: ref ordered after
|
||||
|
||||
if( !test || !test->m_InUse )
|
||||
return true; // Not used: ref ordered before
|
||||
|
||||
if( !ref->m_FileFunction && !test->m_FileFunction )
|
||||
return false; // do not change order: no criteria to sort items
|
||||
|
||||
if( !ref->m_FileFunction )
|
||||
return false;
|
||||
|
||||
if( !test->m_FileFunction )
|
||||
return true;
|
||||
|
||||
if( ref->m_FileFunction->GetZOrder() != test->m_FileFunction->GetZOrder() )
|
||||
return ref->m_FileFunction->GetZOrder() > test->m_FileFunction->GetZOrder();
|
||||
|
||||
return ref->m_FileFunction->GetZSubOrder() > test->m_FileFunction->GetZSubOrder();
|
||||
}
|
||||
|
||||
void GERBER_IMAGE_LIST::SortImagesByZOrder( GERBER_DRAW_ITEM* aDrawList )
|
||||
{
|
||||
std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortZorder );
|
||||
|
||||
// The image order has changed.
|
||||
// Graphic layer numbering must be updated to match the widgets layer order
|
||||
|
||||
// Store the old/new graphic layer info:
|
||||
std::map <int, int> tab_lyr;
|
||||
|
||||
for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
|
||||
{
|
||||
if( m_GERBER_List[layer] )
|
||||
{
|
||||
tab_lyr[m_GERBER_List[layer]->m_GraphicLayer] = layer;
|
||||
m_GERBER_List[layer]->m_GraphicLayer = layer ;
|
||||
}
|
||||
}
|
||||
|
||||
// update the graphic layer in items to draw
|
||||
for( GERBER_DRAW_ITEM* item = aDrawList; item; item = item->Next() )
|
||||
{
|
||||
int layer = item->GetLayer();
|
||||
item->SetLayer( tab_lyr[layer] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The global image list:
|
||||
GERBER_IMAGE_LIST g_GERBER_List;
|
||||
|
|
|
@ -61,6 +61,7 @@ class D_CODE;
|
|||
*/
|
||||
|
||||
class GERBER_IMAGE;
|
||||
class X2_ATTRIBUTE_FILEFUNCTION;
|
||||
|
||||
class GERBER_LAYER
|
||||
{
|
||||
|
@ -104,6 +105,11 @@ public:
|
|||
// (a file is loaded in it)
|
||||
wxString m_FileName; // Full File Name for this layer
|
||||
wxString m_ImageName; // Image name, from IN <name>* command
|
||||
bool m_IsX2_file; // true if a X2 gerber attribute was found in file
|
||||
X2_ATTRIBUTE_FILEFUNCTION* m_FileFunction; // file function parameters, found in a %TF command
|
||||
// or a G04
|
||||
wxString m_MD5_value; // MD5 value found in a %TF.MD5 command
|
||||
wxString m_PartString; // string found in a %TF.Part command
|
||||
int m_GraphicLayer; // Graphic layer Number
|
||||
bool m_ImageNegative; // true = Negative image
|
||||
bool m_ImageJustifyXCenter; // Image Justify Center on X axis (default = false)
|
||||
|
@ -306,5 +312,67 @@ public:
|
|||
void DisplayImageInfo( void );
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GERBER_IMAGE_LIST is a helper class to handle a list of GERBER_IMAGE files
|
||||
* which are loaded and can be displayed
|
||||
* there are 32 images max which can be loaded
|
||||
*/
|
||||
class GERBER_IMAGE_LIST
|
||||
{
|
||||
// the list of loaded images (1 image = 1 gerber file)
|
||||
std::vector<GERBER_IMAGE*> m_GERBER_List;
|
||||
|
||||
public:
|
||||
GERBER_IMAGE_LIST();
|
||||
~GERBER_IMAGE_LIST();
|
||||
|
||||
//Accessor
|
||||
GERBER_IMAGE* GetGbrImage( int aIdx );
|
||||
|
||||
/**
|
||||
* Add a GERBER_IMAGE* at index aIdx
|
||||
* or at the first free location if aIdx < 0
|
||||
* @param aGbrImage = the image to add
|
||||
* @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
|
||||
* @return true if the index used, or -1 if no room to add image
|
||||
*/
|
||||
int AddGbrImage( GERBER_IMAGE* aGbrImage, int aIdx );
|
||||
|
||||
|
||||
/**
|
||||
* remove all loaded data in list
|
||||
*/
|
||||
void ClearList();
|
||||
|
||||
/**
|
||||
* remove the loaded data of image aIdx
|
||||
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
|
||||
*/
|
||||
void ClearImage( int aIdx );
|
||||
|
||||
/**
|
||||
* @return a name for image aIdx which can be used in layers manager
|
||||
* and layer selector
|
||||
* is is "Layer n" (n = aIdx+1), followed by file attribute info (if X2 format)
|
||||
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
|
||||
*/
|
||||
const wxString GetDisplayName( int aIdx );
|
||||
|
||||
/**
|
||||
* @return true if image is used (loaded and with items)
|
||||
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
|
||||
*/
|
||||
bool IsUsed( int aIdx );
|
||||
|
||||
/**
|
||||
* Sort loaded images by Z order priority, if they have the X2 FileFormat info
|
||||
* @param aDrawList: the draw list associated to the gerber images
|
||||
* (SortImagesByZOrder updates the graphic layer of these items)
|
||||
*/
|
||||
void SortImagesByZOrder( GERBER_DRAW_ITEM* aDrawList );
|
||||
};
|
||||
|
||||
|
||||
extern GERBER_IMAGE_LIST g_GERBER_List;
|
||||
|
||||
#endif // ifndef _CLASS_GERBER_H_
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2014 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file class_X2_gerber_attributes.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* Manage the gerber extensions (attributes) in the new X2 version
|
||||
* only few extensions are handled
|
||||
* See http://www.ucamco.com/files/downloads/file/81/the_gerber_file_format_specification.pdf
|
||||
*
|
||||
* gerber attributes in the new X2 version look like:
|
||||
* %TF.FileFunction,Copper,L1,Top*%
|
||||
*
|
||||
* Currently:
|
||||
* .FileFunction .FileFunction Identifies the file’s function in the PCB.
|
||||
* Other Standard Attributes, not yet used in Gerbview:
|
||||
* .Part Identifies the part the file represents, e.g. a single PCB
|
||||
* .MD5 Sets the MD5 file signature or checksum.
|
||||
*/
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
/*
|
||||
* class X2_ATTRIBUTE
|
||||
* The attribute value consists of a number of substrings separated by a “,”
|
||||
*/
|
||||
|
||||
X2_ATTRIBUTE::X2_ATTRIBUTE()
|
||||
{
|
||||
}
|
||||
|
||||
X2_ATTRIBUTE::~X2_ATTRIBUTE()
|
||||
{
|
||||
}
|
||||
|
||||
/* return the attribute name (for instance .FileFunction)
|
||||
* which is given by TF command.
|
||||
*/
|
||||
const wxString& X2_ATTRIBUTE::GetAttribute()
|
||||
{
|
||||
return m_Prms.Item( 0 );
|
||||
}
|
||||
|
||||
/* return a parameter
|
||||
* aIdx = the index of the parameter
|
||||
* aIdx = 0 is the parameter read after the TF function
|
||||
* (the same as GetAttribute())
|
||||
*/
|
||||
const wxString& X2_ATTRIBUTE::GetPrm( int aIdx)
|
||||
{
|
||||
static const wxString dummy;
|
||||
|
||||
if( GetPrmCount() < aIdx && aIdx >= 0 )
|
||||
return m_Prms.Item( aIdx );
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
// Debug function: pring using wxLogMessage le list of parameters
|
||||
void X2_ATTRIBUTE::DbgListPrms()
|
||||
{
|
||||
wxLogMessage( wxT("prms count %d"), GetPrmCount() );
|
||||
|
||||
for( int ii = 0; ii < GetPrmCount(); ii++ )
|
||||
wxLogMessage( m_Prms.Item( ii ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a TF command and fill m_Prms by the parameters found.
|
||||
* aFile = a FILE* ptr to the current Gerber file.
|
||||
* buff = the buffer containing current Gerber data (GERBER_BUFZ size)
|
||||
* text = a pointer to the first char to read in Gerber data
|
||||
*/
|
||||
bool X2_ATTRIBUTE::ParseAttribCmd( FILE* aFile, char *aBuffer, int aBuffSize, char* &aText )
|
||||
{
|
||||
bool ok = true;
|
||||
wxString data;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
while( *aText )
|
||||
{
|
||||
switch( *aText )
|
||||
{
|
||||
case '%': // end of command
|
||||
return ok; // success completion
|
||||
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\n':
|
||||
aText++;
|
||||
break;
|
||||
|
||||
case '*': // End of block
|
||||
m_Prms.Add( data );
|
||||
data.Empty();
|
||||
aText++;
|
||||
break;
|
||||
|
||||
case ',': // End of parameter
|
||||
aText++;
|
||||
m_Prms.Add( data );
|
||||
data.Empty();
|
||||
break;
|
||||
|
||||
default:
|
||||
data.Append( *aText );
|
||||
aText++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// end of current line, read another one.
|
||||
if( aBuffer )
|
||||
{
|
||||
if( fgets( aBuffer, aBuffSize, aFile ) == NULL )
|
||||
{
|
||||
// end of file
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
aText = aBuffer;
|
||||
}
|
||||
else
|
||||
return ok;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* class X2_ATTRIBUTE_FILEFUNCTION ( from %TF.FileFunction in Gerber file)
|
||||
* Example file function:
|
||||
* %TF.FileFunction,Copper,L1,Top*%
|
||||
* - Type. Such as copper, solder mask etc.
|
||||
* - Position. Specifies where the file appears in the PCB layer structure.
|
||||
* Corresponding position substring:
|
||||
* Copper layer: L1, L2, L3...to indicate the layer position followed by Top, Inr or
|
||||
* Bot. L1 is always the top copper layer. E.g. L2,Inr.
|
||||
* Extra layer, e.g. solder mask: Top or Bot – defines the attachment of the layer.
|
||||
* Drill/rout layer: E.g. 1,4 – where 1 is the start and 4 is the end copper layer. The
|
||||
* pair 1,4 defines the span of the drill/rout file
|
||||
* Optional index. This can be used in instances where for example there are two solder
|
||||
* masks on the same side. The index counts from the PCB surface outwards.
|
||||
*/
|
||||
X2_ATTRIBUTE_FILEFUNCTION::X2_ATTRIBUTE_FILEFUNCTION( X2_ATTRIBUTE& aAttributeBase )
|
||||
: X2_ATTRIBUTE()
|
||||
{
|
||||
m_Prms = aAttributeBase.GetPrms();
|
||||
m_z_order = 0;
|
||||
|
||||
//ensure at least 5 parameters
|
||||
while( GetPrmCount() < 5 )
|
||||
m_Prms.Add( wxEmptyString );
|
||||
|
||||
set_Z_Order();
|
||||
}
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetFileType()
|
||||
{
|
||||
// the type of layer (Copper , Soldermask ... )
|
||||
return m_Prms.Item( 1 );
|
||||
}
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetBrdLayerId()
|
||||
{
|
||||
// the brd layer identifier: Top, Bot, Ln
|
||||
return m_Prms.Item( 2 );
|
||||
}
|
||||
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetLabel()
|
||||
{
|
||||
// the filefunction label, if any
|
||||
return m_Prms.Item( 3 );
|
||||
}
|
||||
|
||||
|
||||
// Initialize the z order priority of the current file, from its attributes
|
||||
// this priority is the order of layers from top to bottom to draw/display gerber images
|
||||
// Stack up is( from external copper layer to external)
|
||||
// copper, then solder paste, then solder mask, then silk screen.
|
||||
// and global stackup is Front (top) layers then internal copper layers then Back (bottom) layers
|
||||
void X2_ATTRIBUTE_FILEFUNCTION::set_Z_Order()
|
||||
{
|
||||
m_z_order = -100; // low level
|
||||
m_z_sub_order = 0;
|
||||
|
||||
if( GetFileType().IsSameAs( wxT( "Copper" ), false ) )
|
||||
{
|
||||
// Copper layer: the priority is the layer Id
|
||||
m_z_order = 0;
|
||||
wxString num = GetBrdLayerId().Mid( 1 );
|
||||
long lnum;
|
||||
if( num.ToLong( &lnum ) )
|
||||
m_z_sub_order = -lnum;
|
||||
}
|
||||
|
||||
if( GetFileType().IsSameAs( wxT( "Paste" ), false ) )
|
||||
{
|
||||
// solder paste layer: the priority is top then bottom
|
||||
m_z_order = 1; // for top
|
||||
|
||||
if( GetBrdLayerId().IsSameAs( wxT( "Bot" ), false ) )
|
||||
m_z_order = -m_z_order;
|
||||
}
|
||||
|
||||
if( GetFileType().IsSameAs( wxT( "Soldermask" ), false ) )
|
||||
{
|
||||
// solder mask layer: the priority is top then bottom
|
||||
m_z_order = 2; // for top
|
||||
|
||||
if( GetBrdLayerId().IsSameAs( wxT( "Bot" ), false ) )
|
||||
m_z_order = -m_z_order;
|
||||
}
|
||||
|
||||
if( GetFileType().IsSameAs( wxT( "Legend" ), false ) )
|
||||
{
|
||||
// Silk screen layer: the priority is top then bottom
|
||||
m_z_order = 3; // for top
|
||||
|
||||
if( GetFileType().IsSameAs( wxT( "Legend" ), false ) )
|
||||
|
||||
if( GetBrdLayerId().IsSameAs( wxT( "Bot" ), false ) )
|
||||
m_z_order = -m_z_order;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2014 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file class_X2_gerber_attributes.h
|
||||
*/
|
||||
|
||||
#ifndef _CLASS_X2_GERBER_ATTRIBUTE_H_
|
||||
#define _CLASS_X2_GERBER_ATTRIBUTE_H_
|
||||
|
||||
/*
|
||||
* Manage the gerber extensions (attributes) in the new X2 version
|
||||
* only few extensions are handled
|
||||
* See http://www.ucamco.com/files/downloads/file/81/the_gerber_file_format_specification.pdf
|
||||
*
|
||||
* gerber attributes in the new X2 version look like:
|
||||
* %TF.FileFunction,Copper,L1,Top*%
|
||||
*
|
||||
* Currently:
|
||||
* .FileFunction .FileFunction Identifies the file’s function in the PCB.
|
||||
* Other Standard Attributes, not yet used in Gerbview:
|
||||
* .Part Identifies the part the file represents, e.g. a single PCB
|
||||
* .MD5 Sets the MD5 file signature or checksum.
|
||||
*/
|
||||
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
/**
|
||||
* class X2_ATTRIBUTE
|
||||
* The attribute value consists of a number of substrings separated by a “,”
|
||||
*/
|
||||
|
||||
class X2_ATTRIBUTE
|
||||
{
|
||||
protected:
|
||||
wxArrayString m_Prms; ///< the list of parameters (after TF) in gbr file
|
||||
///< the first one is the attribute name,
|
||||
///< if starting by '.'
|
||||
|
||||
public:
|
||||
X2_ATTRIBUTE();
|
||||
~X2_ATTRIBUTE();
|
||||
|
||||
/**
|
||||
* @return the parameters list read in TF command.
|
||||
*/
|
||||
wxArrayString& GetPrms() { return m_Prms; }
|
||||
|
||||
/**
|
||||
* @return a parameter read in TF command.
|
||||
* @param aIdx = the index of the parameter
|
||||
* aIdx = 0 is the parameter read after the TF function
|
||||
* (the same as GetAttribute())
|
||||
*/
|
||||
const wxString& GetPrm( int aIdx );
|
||||
|
||||
/**
|
||||
* @return the attribute name (for instance .FileFunction)
|
||||
* which is given by TF command (i.e. the first parameter read).
|
||||
*/
|
||||
const wxString& GetAttribute();
|
||||
|
||||
/**
|
||||
* @return the number of parameters read in TF command.
|
||||
*/
|
||||
int GetPrmCount() { return int( m_Prms.GetCount() ); }
|
||||
|
||||
/**
|
||||
* parse a TF command terminated with a % and fill m_Prms
|
||||
* by the parameters found.
|
||||
* @param aFile = a FILE* ptr to the current Gerber file.
|
||||
* @param aBuffer = the buffer containing current Gerber data (can be null)
|
||||
* @param aBuffSize = the size of the buffer
|
||||
* @param aText = a pointer to the first char to read from Gerber data stored in aBuffer
|
||||
* After parsing, text points the last char of the command line ('%') (X2 mode)
|
||||
* or the end of line if the line does not contain '%' or aBuffer == NULL (X1 mode)
|
||||
* @return true if no error.
|
||||
*/
|
||||
bool ParseAttribCmd( FILE* aFile, char *aBuffer, int aBuffSize, char* &aText );
|
||||
|
||||
/**
|
||||
* Debug function: pring using wxLogMessage le list of parameters
|
||||
*/
|
||||
void DbgListPrms();
|
||||
|
||||
/**
|
||||
* return true if the attribute is .FileFunction
|
||||
*/
|
||||
bool IsFileFunction()
|
||||
{
|
||||
return GetAttribute().IsSameAs( wxT(".FileFunction"), false );
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the attribute is .MD5
|
||||
*/
|
||||
bool IsFileMD5()
|
||||
{
|
||||
return GetAttribute().IsSameAs( wxT(".MD5"), false );
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the attribute is .Part
|
||||
*/
|
||||
bool IsFilePart()
|
||||
{
|
||||
return GetAttribute().IsSameAs( wxT(".Part"), false );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* class X2_ATTRIBUTE_FILEFUNCTION ( from %TF.FileFunction in Gerber file)
|
||||
* Example file function:
|
||||
* %TF.FileFunction,Copper,L1,Top*%
|
||||
* - Type. Such as copper, solder mask etc.
|
||||
* - Position. Specifies where the file appears in the PCB layer structure.
|
||||
* Corresponding position substring:
|
||||
* Copper layer: L1, L2, L3...to indicate the layer position followed by Top, Inr or
|
||||
* Bot. L1 is always the top copper layer. E.g. L2,Inr.
|
||||
* Extra layer, e.g. solder mask: Top or Bot – defines the attachment of the layer.
|
||||
* Drill/rout layer: E.g. 1,4 – where 1 is the start and 4 is the end copper layer. The
|
||||
* pair 1,4 defines the span of the drill/rout file
|
||||
* Optional index. This can be used in instances where for example there are two solder
|
||||
* masks on the same side. The index counts from the PCB surface outwards.
|
||||
*/
|
||||
|
||||
class X2_ATTRIBUTE_FILEFUNCTION : public X2_ATTRIBUTE
|
||||
{
|
||||
int m_z_order; // the z order of the layer for a board
|
||||
int m_z_sub_order; // the z sub_order of the copper layer for a board
|
||||
|
||||
public:
|
||||
X2_ATTRIBUTE_FILEFUNCTION( X2_ATTRIBUTE& aAttributeBase );
|
||||
|
||||
const wxString& GetFileType(); ///< the type of layer (Copper , Soldermask ... )
|
||||
const wxString& GetBrdLayerId(); ///< the brd layer identifier: Top, Bot, Ln
|
||||
const wxString& GetLabel(); ///< the filefunction label, if any
|
||||
|
||||
int GetZOrder() { return m_z_order; } ///< the Order of the bdr layer, from front (Top side) to back side
|
||||
int GetZSubOrder() { return m_z_sub_order; } ///< the Order of the bdr copper layer, from front (Top side) to back side
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Initialize the z order priority of the current file, from its attributes
|
||||
*/
|
||||
void set_Z_Order();
|
||||
};
|
||||
|
||||
#endif // _CLASS_X2_GERBER_ATTRIBUTE_H_
|
|
@ -33,11 +33,14 @@
|
|||
#include <colors_selection.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <class_GERBER.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
#include <class_gbr_layer_box_selector.h>
|
||||
|
||||
void GBR_LAYER_BOX_SELECTOR::Resync()
|
||||
{
|
||||
Freeze();
|
||||
Clear();
|
||||
|
||||
for( int layerid = 0; layerid < GERBER_DRAWLAYERS_COUNT; ++layerid )
|
||||
|
@ -55,6 +58,8 @@ void GBR_LAYER_BOX_SELECTOR::Resync()
|
|||
|
||||
Append( layername, layerbmp, (void*)(intptr_t) layerid );
|
||||
}
|
||||
|
||||
Thaw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,7 +75,7 @@ EDA_COLOR_T GBR_LAYER_BOX_SELECTOR::GetLayerColor( int aLayer ) const
|
|||
// Returns the name of the layer id
|
||||
wxString GBR_LAYER_BOX_SELECTOR::GetLayerName( int aLayer ) const
|
||||
{
|
||||
wxString name;
|
||||
name.Printf( _( "Layer %d" ), aLayer + 1 );
|
||||
wxString name = g_GERBER_List.GetDisplayName( aLayer );
|
||||
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ GBR_LAYOUT::GBR_LAYOUT()
|
|||
PAGE_INFO pageInfo( wxT( "GERBER" ) );
|
||||
SetPageSettings( pageInfo );
|
||||
|
||||
// no m_printLayersMask = -1;
|
||||
m_printLayersMask.set();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
/**
|
||||
* @file class_gbr_layout.h
|
||||
* @brief Class CLASS_GBR_LAYOUT to handle a board.
|
||||
* @brief Class CLASS_GBR_LAYOUT to handle info to draw/print loaded Gerber images
|
||||
* and page frame reference
|
||||
*/
|
||||
|
||||
#ifndef CLASS_GBR_LAYOUT_H
|
||||
|
@ -55,7 +56,7 @@ private:
|
|||
std::bitset <GERBER_DRAWLAYERS_COUNT> m_printLayersMask; // When printing: the list of layers to print
|
||||
public:
|
||||
|
||||
DLIST<GERBER_DRAW_ITEM> m_Drawings; // linked list of Gerber Items
|
||||
DLIST<GERBER_DRAW_ITEM> m_Drawings; // linked list of Gerber Items to draw
|
||||
|
||||
GBR_LAYOUT();
|
||||
~GBR_LAYOUT();
|
||||
|
|
|
@ -225,7 +225,9 @@ D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr()
|
|||
{
|
||||
if( (m_DCode < FIRST_DCODE) || (m_DCode > LAST_DCODE) )
|
||||
return NULL;
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[m_Layer];
|
||||
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( m_Layer );
|
||||
|
||||
if( gerber == NULL )
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr
|
||||
* Copyright (C) 2004-2010 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2010 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
|
@ -41,6 +41,7 @@
|
|||
#include <class_GERBER.h>
|
||||
#include <layer_widget.h>
|
||||
#include <class_gerbview_layer_widget.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
|
||||
/*
|
||||
|
@ -70,7 +71,7 @@ GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFo
|
|||
|
||||
// since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
|
||||
// and not m_LayerScrolledWindow->Connect()
|
||||
Connect( ID_SHOW_ALL_LAYERS, ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE,
|
||||
Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END,
|
||||
wxEVT_COMMAND_MENU_SELECTED,
|
||||
wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this );
|
||||
|
||||
|
@ -146,8 +147,7 @@ void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
|
|||
{
|
||||
wxMenu menu;
|
||||
|
||||
// menu text is capitalized:
|
||||
// http://library.gnome.org/devel/hig-book/2.20/design-text-labels.html.en#layout-capitalization
|
||||
// Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
|
||||
menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_LAYERS,
|
||||
_("Show All Layers") ) );
|
||||
|
||||
|
@ -160,6 +160,9 @@ void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
|
|||
menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS,
|
||||
_( "Hide All Layers" ) ) );
|
||||
|
||||
menu.AppendSeparator();
|
||||
menu.Append( new wxMenuItem( &menu, ID_SORT_GBR_LAYERS,
|
||||
_( "Sort Layers if X2 Mode" ) ) );
|
||||
PopupMenu( &menu );
|
||||
|
||||
passOnFocus();
|
||||
|
@ -204,6 +207,13 @@ void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
|
|||
myframe->SetVisibleLayers( visibleLayers );
|
||||
myframe->GetCanvas()->Refresh();
|
||||
break;
|
||||
|
||||
case ID_SORT_GBR_LAYERS:
|
||||
g_GERBER_List.SortImagesByZOrder( myframe->GetItemsList() );
|
||||
myframe->ReFillLayerWidget();
|
||||
myframe->syncLayerBox();
|
||||
myframe->GetCanvas()->Refresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,7 +222,7 @@ bool GERBER_LAYER_WIDGET::OnLayerSelected()
|
|||
if( !m_alwaysShowActiveLayer )
|
||||
return false;
|
||||
|
||||
// postprocess after an active layer selection
|
||||
// postprocess after active layer selection
|
||||
// ensure active layer visible
|
||||
wxCommandEvent event;
|
||||
event.SetId( ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
|
||||
|
@ -223,16 +233,20 @@ bool GERBER_LAYER_WIDGET::OnLayerSelected()
|
|||
|
||||
void GERBER_LAYER_WIDGET::ReFill()
|
||||
{
|
||||
Freeze();
|
||||
|
||||
ClearLayerRows();
|
||||
|
||||
for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( _("Layer %d"), layer+1 );
|
||||
wxString msg = g_GERBER_List.GetDisplayName( layer );
|
||||
|
||||
AppendLayerRow( LAYER_WIDGET::ROW( msg, layer,
|
||||
myframe->GetLayerColor( layer ), wxEmptyString, true ) );
|
||||
}
|
||||
|
||||
Thaw();
|
||||
|
||||
installRightLayerClickHandler();
|
||||
}
|
||||
|
||||
|
@ -298,17 +312,10 @@ void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
|
|||
*/
|
||||
bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow)
|
||||
{
|
||||
bool inUse = false;
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[aRow];
|
||||
|
||||
if( gerber != NULL && gerber->m_InUse )
|
||||
inUse = true;
|
||||
|
||||
return inUse;
|
||||
return g_GERBER_List.IsUsed( aRow );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function UpdateLayerIcons
|
||||
/*
|
||||
* Update the layer manager icons (layers only)
|
||||
* Useful when loading a file or clearing a layer because they change
|
||||
*/
|
||||
|
@ -322,7 +329,8 @@ void GERBER_LAYER_WIDGET::UpdateLayerIcons()
|
|||
continue;
|
||||
|
||||
if( row == m_CurrentRow )
|
||||
bm->SetBitmap( useAlternateBitmap(row) ? *m_RightArrowAlternateBitmap : *m_RightArrowBitmap );
|
||||
bm->SetBitmap( useAlternateBitmap(row) ? *m_RightArrowAlternateBitmap :
|
||||
*m_RightArrowBitmap );
|
||||
else
|
||||
bm->SetBitmap( useAlternateBitmap(row) ? *m_BlankAlternateBitmap : *m_BlankBitmap );
|
||||
}
|
||||
|
|
|
@ -33,6 +33,18 @@
|
|||
|
||||
#include <layer_widget.h>
|
||||
|
||||
// popup menu ids. in layer manager
|
||||
enum LAYER_MANAGER
|
||||
{
|
||||
ID_LAYER_MANAGER_START = wxID_HIGHEST+1,
|
||||
ID_SHOW_ALL_LAYERS = ID_LAYER_MANAGER_START,
|
||||
ID_SHOW_NO_LAYERS,
|
||||
ID_SHOW_NO_LAYERS_BUT_ACTIVE,
|
||||
ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE,
|
||||
ID_SORT_GBR_LAYERS,
|
||||
ID_LAYER_MANAGER_END = ID_SORT_GBR_LAYERS,
|
||||
};
|
||||
|
||||
/**
|
||||
* Class GERBER_LAYER_WIDGET
|
||||
* is here to implement the abtract functions of LAYER_WIDGET so they
|
||||
|
@ -45,11 +57,6 @@ class GERBER_LAYER_WIDGET : public LAYER_WIDGET
|
|||
bool m_alwaysShowActiveLayer; // If true: Only shows the current active layer
|
||||
// even if it is changed
|
||||
|
||||
// popup menu ids.
|
||||
#define ID_SHOW_ALL_LAYERS wxID_HIGHEST
|
||||
#define ID_SHOW_NO_LAYERS (wxID_HIGHEST+1)
|
||||
#define ID_SHOW_NO_LAYERS_BUT_ACTIVE (wxID_HIGHEST+2)
|
||||
#define ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE (wxID_HIGHEST+3)
|
||||
|
||||
/**
|
||||
* Function OnRightDownLayers
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <gerbview.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <class_GERBER.h>
|
||||
#include <pcbplot.h>
|
||||
|
||||
static double s_ScaleList[] =
|
||||
|
@ -163,7 +164,7 @@ void DIALOG_PRINT_USING_PRINTER::InitValues( )
|
|||
msg << wxT( " " ) << ii + 1;
|
||||
m_BoxSelectLayer[ii] = new wxCheckBox( this, -1, msg );
|
||||
|
||||
if( g_GERBER_List[ii] == NULL ) // Nothing loaded on this draw layer
|
||||
if( g_GERBER_List.GetGbrImage( ii ) == NULL ) // Nothing loaded on this draw layer
|
||||
m_BoxSelectLayer[ii]->Enable( false );
|
||||
|
||||
if( ii < 16 )
|
||||
|
|
|
@ -214,14 +214,16 @@ void GBR_LAYOUT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
|
|||
|
||||
bool end = false;
|
||||
|
||||
for( int layer = 0; !end; ++layer )
|
||||
// Draw layers from bottom to top, and active layer last
|
||||
// in non transparent modes, the last layer drawn mask mask previously drawn layer
|
||||
for( int layer = GERBER_DRAWLAYERS_COUNT-1; !end; --layer )
|
||||
{
|
||||
int active_layer = gerbFrame->getActiveLayer();
|
||||
|
||||
if( layer == active_layer ) // active layer will be drawn after other layers
|
||||
continue;
|
||||
|
||||
if( layer == GERBER_DRAWLAYERS_COUNT ) // last loop: draw active layer
|
||||
if( layer < 0 ) // last loop: draw active layer
|
||||
{
|
||||
end = true;
|
||||
layer = active_layer;
|
||||
|
@ -230,7 +232,7 @@ void GBR_LAYOUT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
|
|||
if( !gerbFrame->IsLayerVisible( layer ) )
|
||||
continue;
|
||||
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[layer];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
|
||||
|
||||
if( gerber == NULL ) // Graphic layer not yet used
|
||||
continue;
|
||||
|
|
|
@ -234,7 +234,7 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
|||
|
||||
void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event )
|
||||
{
|
||||
GERBER_IMAGE* gerber_image = g_GERBER_List[getActiveLayer()];
|
||||
GERBER_IMAGE* gerber_image = g_GERBER_List.GetGbrImage( getActiveLayer() );
|
||||
|
||||
if( gerber_image )
|
||||
{
|
||||
|
@ -266,7 +266,7 @@ void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event )
|
|||
void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event )
|
||||
{
|
||||
int layer = getActiveLayer();
|
||||
GERBER_IMAGE* gerber_layer = g_GERBER_List[layer];
|
||||
GERBER_IMAGE* gerber_layer = g_GERBER_List.GetGbrImage( layer );
|
||||
|
||||
if( gerber_layer )
|
||||
{
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2011 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
||||
* Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 1992-2014 Jean-Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2014 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
|
||||
|
@ -75,6 +75,7 @@
|
|||
#include <class_GERBER.h>
|
||||
#include <class_excellon.h>
|
||||
#include <kicad_string.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -93,18 +94,24 @@ extern double ReadDouble( char*& text, bool aSkipSeparator = true );
|
|||
extern void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||
APERTURE_T aAperture,
|
||||
int Dcode_index,
|
||||
int aLayer,
|
||||
int aLayer,
|
||||
const wxPoint& aPos,
|
||||
wxSize aSize,
|
||||
bool aLayerNegative );
|
||||
void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||
int Dcode_index,
|
||||
int aLayer,
|
||||
int aLayer,
|
||||
const wxPoint& aStart,
|
||||
const wxPoint& aEnd,
|
||||
wxSize aPenSize,
|
||||
bool aLayerNegative );
|
||||
|
||||
// Getber X2 files have a file attribute which specify the type of image
|
||||
// (copper, solder paste ... and sides tpo, bottom or inner copper layers)
|
||||
// Excellon drill files do not have attributes, so, just to identify the image
|
||||
// In gerbview, we add this attribute, like a Gerber drill file
|
||||
static const char file_attribute[] = ".FileFunction,Other,Drill*";
|
||||
|
||||
static EXCELLON_CMD excellonHeaderCmdList[] =
|
||||
{
|
||||
{ "M0", DRILL_M_END, -1 }, // End of Program - No Rewind
|
||||
|
@ -168,14 +175,21 @@ static EXCELLON_CMD excellon_G_CmdList[] =
|
|||
bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName )
|
||||
{
|
||||
wxString msg;
|
||||
int layer = getActiveLayer(); // current layer used in GerbView
|
||||
int layerId = getActiveLayer(); // current layer used in GerbView
|
||||
EXCELLON_IMAGE* drill_Layer = (EXCELLON_IMAGE*) g_GERBER_List.GetGbrImage( layerId );
|
||||
|
||||
if( g_GERBER_List[layer] == NULL )
|
||||
if( drill_Layer == NULL )
|
||||
{
|
||||
g_GERBER_List[layer] = new EXCELLON_IMAGE( this, layer );
|
||||
drill_Layer = new EXCELLON_IMAGE( this, layerId );
|
||||
layerId = g_GERBER_List.AddGbrImage( drill_Layer, layerId );
|
||||
}
|
||||
|
||||
if( layerId < 0 )
|
||||
{
|
||||
DisplayError( this, _( "No room to load file" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
EXCELLON_IMAGE* drill_Layer = (EXCELLON_IMAGE*) g_GERBER_List[layer];
|
||||
ClearMessageList();
|
||||
|
||||
/* Read the gerber file */
|
||||
|
@ -183,7 +197,7 @@ bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName )
|
|||
if( file == NULL )
|
||||
{
|
||||
msg.Printf( _( "File %s not found" ), GetChars( aFullFileName ) );
|
||||
DisplayError( this, msg, 10 );
|
||||
DisplayError( this, msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -213,7 +227,7 @@ bool EXCELLON_IMAGE::Read_EXCELLON_File( FILE * aFile,
|
|||
m_FileName = aFullFileName;
|
||||
m_Current_File = aFile;
|
||||
|
||||
SetLocaleTo_C_standard();
|
||||
LOCALE_IO toggleIo;
|
||||
|
||||
// FILE_LINE_READER will close the file.
|
||||
if( m_Current_File == NULL )
|
||||
|
@ -282,7 +296,16 @@ bool EXCELLON_IMAGE::Read_EXCELLON_File( FILE * aFile,
|
|||
} // End switch
|
||||
}
|
||||
}
|
||||
SetLocaleTo_Default();
|
||||
|
||||
// Add our file attribute, to identify the drill file
|
||||
X2_ATTRIBUTE dummy;
|
||||
char* text = (char*)file_attribute;
|
||||
dummy.ParseAttribCmd( m_Current_File, NULL, 0, text );
|
||||
delete m_FileFunction;
|
||||
m_FileFunction = new X2_ATTRIBUTE_FILEFUNCTION( dummy );
|
||||
|
||||
m_InUse = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <gerbview.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <class_gerber_draw_item.h>
|
||||
#include <class_GERBER.h>
|
||||
#include <select_layers_to_pcb.h>
|
||||
#include <build_version.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
@ -159,7 +160,7 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event )
|
|||
// Count the Gerber layers which are actually currently used
|
||||
for( LAYER_NUM ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
|
||||
{
|
||||
if( g_GERBER_List[ii] != NULL )
|
||||
if( g_GERBER_List.GetGbrImage( ii ) )
|
||||
layercount++;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
|
|||
Zoom_Automatique( false );
|
||||
m_canvas->Refresh();
|
||||
ClearMsgPanel();
|
||||
ReFillLayerWidget();
|
||||
break;
|
||||
|
||||
case ID_GERBVIEW_LOAD_DRILL_FILE:
|
||||
|
@ -200,6 +201,7 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
|
|||
Zoom_Automatique( false );
|
||||
|
||||
// Synchronize layers tools with actual active layer:
|
||||
ReFillLayerWidget();
|
||||
setActiveLayer( getActiveLayer() );
|
||||
m_LayersManager->UpdateLayerIcons();
|
||||
syncLayerBox();
|
||||
|
@ -282,6 +284,7 @@ bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName )
|
|||
Zoom_Automatique( false );
|
||||
|
||||
// Synchronize layers tools with actual active layer:
|
||||
ReFillLayerWidget();
|
||||
setActiveLayer( getActiveLayer() );
|
||||
m_LayersManager->UpdateLayerIcons();
|
||||
syncLayerBox();
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
|
||||
// Colors for layers and items
|
||||
COLORS_DESIGN_SETTINGS g_ColorsSettings;
|
||||
int g_Default_GERBER_Format;
|
||||
|
||||
|
||||
const wxChar* g_GerberPageSizeList[] = {
|
||||
|
@ -60,9 +59,6 @@ const wxChar* g_GerberPageSizeList[] = {
|
|||
};
|
||||
|
||||
|
||||
GERBER_IMAGE* g_GERBER_List[32];
|
||||
|
||||
|
||||
namespace GERBV {
|
||||
|
||||
static struct IFACE : public KIFACE_I
|
||||
|
|
|
@ -109,6 +109,4 @@ enum Gerb_Analyse_Cmd
|
|||
ENTER_RS274X_CMD
|
||||
};
|
||||
|
||||
extern GERBER_IMAGE* g_GERBER_List[GERBER_DRAWLAYERS_COUNT];
|
||||
|
||||
#endif // ifndef GERBVIEW_H
|
||||
|
|
|
@ -348,7 +348,7 @@ int GERBVIEW_FRAME::getNextAvailableLayer( int aLayer ) const
|
|||
|
||||
for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; ++i )
|
||||
{
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[ layer ];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
|
||||
|
||||
if( gerber == NULL || gerber->m_FileName.IsEmpty() )
|
||||
return layer;
|
||||
|
@ -378,9 +378,11 @@ void GERBVIEW_FRAME::syncLayerWidget()
|
|||
*/
|
||||
void GERBVIEW_FRAME::syncLayerBox()
|
||||
{
|
||||
m_SelLayerBox->Resync();
|
||||
m_SelLayerBox->SetSelection( getActiveLayer() );
|
||||
|
||||
int dcodeSelected = -1;
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[getActiveLayer()];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( getActiveLayer() );
|
||||
|
||||
if( gerber )
|
||||
dcodeSelected = gerber->m_Selected_Tool;
|
||||
|
@ -406,7 +408,7 @@ void GERBVIEW_FRAME::Liste_D_Codes()
|
|||
|
||||
for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
|
||||
{
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[layer];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
|
||||
|
||||
if( gerber == NULL )
|
||||
continue;
|
||||
|
@ -474,7 +476,7 @@ void GERBVIEW_FRAME::Liste_D_Codes()
|
|||
*/
|
||||
void GERBVIEW_FRAME::UpdateTitleAndInfo()
|
||||
{
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[ getActiveLayer() ];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( getActiveLayer() );
|
||||
wxString text;
|
||||
|
||||
// Display the gerber filename
|
||||
|
@ -491,6 +493,8 @@ void GERBVIEW_FRAME::UpdateTitleAndInfo()
|
|||
|
||||
text = _( "File:" );
|
||||
text << wxT( " " ) << gerber->m_FileName;
|
||||
if( gerber->m_IsX2_file )
|
||||
text << wxT( " " ) << _( "(with X2 Attributes)" );
|
||||
SetTitle( text );
|
||||
|
||||
gerber->DisplayImageInfo();
|
||||
|
@ -508,7 +512,13 @@ void GERBVIEW_FRAME::UpdateTitleAndInfo()
|
|||
gerber->m_FmtLen.y - gerber->m_FmtScale.y, gerber->m_FmtScale.y,
|
||||
gerber->m_NoTrailingZeros ? 'T' : 'L' );
|
||||
|
||||
if( gerber->m_IsX2_file )
|
||||
text << wxT(" ") << _( "X2 attr" );
|
||||
|
||||
m_TextInfo->SetValue( text );
|
||||
|
||||
if( EnsureTextCtrlWidth( m_TextInfo, &text ) ) // Resized
|
||||
m_auimgr.Update();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -40,8 +40,6 @@
|
|||
|
||||
bool GERBVIEW_FRAME::Clear_DrawLayers( bool query )
|
||||
{
|
||||
int layer;
|
||||
|
||||
if( GetGerberLayout() == NULL )
|
||||
return false;
|
||||
|
||||
|
@ -53,14 +51,7 @@ bool GERBVIEW_FRAME::Clear_DrawLayers( bool query )
|
|||
|
||||
GetGerberLayout()->m_Drawings.DeleteAll();
|
||||
|
||||
for( layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
|
||||
{
|
||||
if( g_GERBER_List[layer] )
|
||||
{
|
||||
g_GERBER_List[layer]->InitToolTable();
|
||||
g_GERBER_List[layer]->ResetDefaultValues();
|
||||
}
|
||||
}
|
||||
g_GERBER_List.ClearList();
|
||||
|
||||
GetGerberLayout()->SetBoundingBox( EDA_RECT() );
|
||||
|
||||
|
@ -98,11 +89,7 @@ void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query )
|
|||
item->DeleteStructure();
|
||||
}
|
||||
|
||||
if( g_GERBER_List[layer] )
|
||||
{
|
||||
g_GERBER_List[layer]->InitToolTable();
|
||||
g_GERBER_List[layer]->ResetDefaultValues();
|
||||
}
|
||||
g_GERBER_List.ClearImage( layer );
|
||||
|
||||
GetScreen()->SetModify();
|
||||
m_canvas->Refresh();
|
||||
|
|
|
@ -56,7 +56,7 @@ void GERBVIEW_FRAME::OnLeftClick( wxDC* DC, const wxPoint& aPosition )
|
|||
GetScreen()->SetCurItem( DrawStruct );
|
||||
if( DrawStruct == NULL )
|
||||
{
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[getActiveLayer() ];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( getActiveLayer() );
|
||||
if( gerber )
|
||||
gerber->DisplayImageInfo( );
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <html_messagebox.h>
|
||||
#include <macros.h>
|
||||
|
||||
/* Read a gerber file, RS274D or RS274X format.
|
||||
/* Read a gerber file, RS274D, RS274X or RS274X2 format.
|
||||
*/
|
||||
bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName,
|
||||
const wxString& D_Code_FullFileName )
|
||||
|
@ -49,13 +49,14 @@ bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName,
|
|||
int layer; // current layer used in GerbView
|
||||
|
||||
layer = getActiveLayer();
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
|
||||
|
||||
if( g_GERBER_List[layer] == NULL )
|
||||
if( gerber == NULL )
|
||||
{
|
||||
g_GERBER_List[layer] = new GERBER_IMAGE( this, layer );
|
||||
gerber = new GERBER_IMAGE( this, layer );
|
||||
g_GERBER_List.AddGbrImage( gerber, layer );
|
||||
}
|
||||
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[layer];
|
||||
ClearMessageList( );
|
||||
|
||||
/* Set the gerber scale: */
|
||||
|
@ -76,7 +77,7 @@ bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName,
|
|||
if( path != wxEmptyString )
|
||||
wxSetWorkingDirectory( path );
|
||||
|
||||
SetLocaleTo_C_standard();
|
||||
LOCALE_IO toggleIo;
|
||||
|
||||
while( true )
|
||||
{
|
||||
|
@ -170,8 +171,8 @@ bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose( gerber->m_Current_File );
|
||||
SetLocaleTo_Default();
|
||||
|
||||
gerber->m_InUse = true;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <macros.h>
|
||||
#include <class_gerber_draw_item.h>
|
||||
#include <class_GERBER.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -43,7 +44,8 @@
|
|||
* G01 linear interpolation (right trace)
|
||||
* G02, G20, G21 Circular interpolation, meaning trig <0 (clockwise)
|
||||
* G03, G30, G31 Circular interpolation, meaning trigo> 0 (counterclockwise)
|
||||
* G04 = comment
|
||||
* G04 = comment. Since Sept 2014, file attributes can be found here
|
||||
* if the line starts by G04 #@!
|
||||
* G06 parabolic interpolation
|
||||
* G07 Cubic Interpolation
|
||||
* G10 linear interpolation (scale x10)
|
||||
|
@ -473,9 +475,22 @@ bool GERBER_IMAGE::Execute_G_Command( char*& text, int G_command )
|
|||
break;
|
||||
|
||||
case GC_COMMENT:
|
||||
// Skip comment
|
||||
// Skip comment, but only if the line does not start by "G04 #@! TF"
|
||||
// which is a metadata
|
||||
if( strncmp( text, " #@! TF", 7 ) == 0 )
|
||||
{
|
||||
text += 7;
|
||||
X2_ATTRIBUTE dummy;
|
||||
dummy.ParseAttribCmd( m_Current_File, NULL, 0, text );
|
||||
if( dummy.IsFileFunction() )
|
||||
{
|
||||
delete m_FileFunction;
|
||||
m_FileFunction = new X2_ATTRIBUTE_FILEFUNCTION( dummy );
|
||||
}
|
||||
}
|
||||
|
||||
while ( *text && (*text != '*') )
|
||||
text++;
|
||||
text++;
|
||||
break;
|
||||
|
||||
case GC_LINEAR_INTERPOL_10X:
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <gerbview.h>
|
||||
#include <class_GERBER.h>
|
||||
#include <class_X2_gerber_attributes.h>
|
||||
|
||||
extern int ReadInt( char*& text, bool aSkipSeparator = true );
|
||||
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
|
||||
|
@ -78,6 +79,13 @@ enum RS274X_PARAMETERS {
|
|||
AP_DEFINITION = CODE( 'A', 'D' ),
|
||||
AP_MACRO = CODE( 'A', 'M' ),
|
||||
|
||||
// X2 extention attribute commands
|
||||
// Mainly are found standard attributes and user attributes
|
||||
// standard attributes commands are:
|
||||
// TF (file attribute)
|
||||
// TA (aperture attribute) and TD (delete aperture attribute)
|
||||
FILE_ATTRIBUTE = CODE( 'T', 'F' ),
|
||||
|
||||
// Layer specific parameters
|
||||
// May be used singly or may be layer specfic
|
||||
// theses parameters are at the beginning of the file or layer
|
||||
|
@ -307,7 +315,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
m_SwapAxis = true;
|
||||
break;
|
||||
|
||||
case MIRROR_IMAGE: // commanf %MIA0B0*%, %MIA0B1*%, %MIA1B0*%, %MIA1B1*%
|
||||
case MIRROR_IMAGE: // command %MIA0B0*%, %MIA0B1*%, %MIA1B0*%, %MIA1B1*%
|
||||
m_MirrorA = m_MirrorB = 0;
|
||||
while( *text && *text != '*' )
|
||||
{
|
||||
|
@ -341,6 +349,27 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
conv_scale = m_GerbMetric ? IU_PER_MILS / 25.4 : IU_PER_MILS;
|
||||
break;
|
||||
|
||||
case FILE_ATTRIBUTE: // Command %TF ...
|
||||
m_IsX2_file = true;
|
||||
{
|
||||
X2_ATTRIBUTE dummy;
|
||||
dummy.ParseAttribCmd( m_Current_File, buff, GERBER_BUFZ, text );
|
||||
if( dummy.IsFileFunction() )
|
||||
{
|
||||
delete m_FileFunction;
|
||||
m_FileFunction = new X2_ATTRIBUTE_FILEFUNCTION( dummy );
|
||||
}
|
||||
else if( dummy.IsFileMD5() )
|
||||
{
|
||||
m_MD5_value = dummy.GetPrm( 1 );
|
||||
}
|
||||
else if( dummy.IsFilePart() )
|
||||
{
|
||||
m_PartString = dummy.GetPrm( 1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OFFSET: // command: OFAnnBnn (nn = float number) = layer Offset
|
||||
m_Offset.x = m_Offset.y = 0;
|
||||
while( *text != '*' )
|
||||
|
|
|
@ -121,7 +121,7 @@ void LAYERS_MAP_DIALOG::initDialog()
|
|||
m_gerberActiveLayersCount = 0;
|
||||
for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
|
||||
{
|
||||
if( g_GERBER_List[ii] == NULL )
|
||||
if( g_GERBER_List.GetGbrImage( ii ) == NULL )
|
||||
break;
|
||||
|
||||
if( (pcb_layer_num == m_exportBoardCopperLayersCount - 1)
|
||||
|
@ -189,7 +189,7 @@ void LAYERS_MAP_DIALOG::initDialog()
|
|||
wxRIGHT | wxLEFT, 5 );
|
||||
|
||||
/* Add file name and extension without path. */
|
||||
wxFileName fn( g_GERBER_List[ii]->m_FileName );
|
||||
wxFileName fn( g_GERBER_List.GetGbrImage( ii )->m_FileName );
|
||||
label = new wxStaticText( this, wxID_STATIC, fn.GetFullName(),
|
||||
wxDefaultPosition, wxDefaultSize );
|
||||
flexColumnBoxSizer->Add( label, 0,
|
||||
|
|
|
@ -294,7 +294,7 @@ void GERBVIEW_FRAME::OnUpdateShowLayerManager( wxUpdateUIEvent& aEvent )
|
|||
void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent )
|
||||
{
|
||||
int layer = getActiveLayer();
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[layer];
|
||||
GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
|
||||
int selected = ( gerber ) ? gerber->m_Selected_Tool : 0;
|
||||
|
||||
if( m_DCodeSelector && m_DCodeSelector->GetSelectedDCodeId() != selected )
|
||||
|
|
|
@ -333,7 +333,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
|
|||
bSizeRight = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticBoxSizer* sbSizerTW_Result;
|
||||
sbSizerTW_Result = new wxStaticBoxSizer( new wxStaticBox( m_panelTrackWidth, wxID_ANY, _("Tracks Caracteristics (External Layers):") ), wxVERTICAL );
|
||||
sbSizerTW_Result = new wxStaticBoxSizer( new wxStaticBox( m_panelTrackWidth, wxID_ANY, _("Track Characteristics (External Layers):") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerTW_Results;
|
||||
fgSizerTW_Results = new wxFlexGridSizer( 5, 3, 0, 0 );
|
||||
|
@ -409,7 +409,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
|
|||
bSizeRight->Add( sbSizerTW_Result, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerTW_Result1;
|
||||
sbSizerTW_Result1 = new wxStaticBoxSizer( new wxStaticBox( m_panelTrackWidth, wxID_ANY, _("Tracks Caracteristics (Internal Layers):") ), wxVERTICAL );
|
||||
sbSizerTW_Result1 = new wxStaticBoxSizer( new wxStaticBox( m_panelTrackWidth, wxID_ANY, _("Track Characteristics (Internal Layers):") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerTW_Results1;
|
||||
fgSizerTW_Results1 = new wxFlexGridSizer( 6, 3, 0, 0 );
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<property name="size">670,489</property>
|
||||
<property name="style">wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">KIWAY_PLAYER; kiway_player.h</property>
|
||||
<property name="title">Pcb Calculator</property>
|
||||
<property name="title">PCB Calculator</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
|
@ -4687,7 +4687,7 @@
|
|||
<property name="proportion">1</property>
|
||||
<object class="wxStaticBoxSizer" expanded="0">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Tracks Caracteristics (External Layers):</property>
|
||||
<property name="label">Track Characteristics (External Layers):</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizerTW_Result</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
|
@ -6009,7 +6009,7 @@
|
|||
<property name="proportion">1</property>
|
||||
<object class="wxStaticBoxSizer" expanded="0">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Tracks Caracteristics (Internal Layers):</property>
|
||||
<property name="label">Track Characteristics (Internal Layers):</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizerTW_Result1</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
|
|
|
@ -293,7 +293,7 @@ class PCB_CALCULATOR_FRAME_BASE : public KIWAY_PLAYER
|
|||
|
||||
public:
|
||||
|
||||
PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Pcb Calculator"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 670,489 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL );
|
||||
PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("PCB Calculator"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 670,489 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL );
|
||||
|
||||
~PCB_CALCULATOR_FRAME_BASE();
|
||||
|
||||
|
|
|
@ -223,12 +223,12 @@ void PCB_CALCULATOR_FRAME::OnDataFileSelection( wxCommandEvent& event )
|
|||
wxString fullfilename = GetDataFilename();
|
||||
|
||||
wxString wildcard;
|
||||
wildcard.Printf( _("Pcb Calculator data file (*.%s)|*.%s"),
|
||||
wildcard.Printf( _("PCB Calculator data file (*.%s)|*.%s"),
|
||||
GetChars( DataFileNameExt ),
|
||||
GetChars( DataFileNameExt ) );
|
||||
|
||||
wxFileDialog dlg( m_panelRegulators,
|
||||
_("Select a Pcb Calculator data file"),
|
||||
_("Select a PCB Calculator data file"),
|
||||
wxEmptyString, fullfilename,
|
||||
wildcard, wxFD_OPEN );
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
* @brief function to convert shapes of items ( pads, tracks... ) to polygons
|
||||
*/
|
||||
|
||||
/* Function to convert pads and tranck shapes to polygons
|
||||
* Used to fill zones areas
|
||||
/* Function to convert pad and track shapes to polygons
|
||||
* Used to fill zones areas and in 3D viewer
|
||||
*/
|
||||
#include <vector>
|
||||
|
||||
|
@ -520,22 +520,19 @@ void TRACK:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
|
|||
* clearance when the circle is approximated by segment bigger or equal
|
||||
* to the real clearance value (usually near from 1.0)
|
||||
*/
|
||||
#include <clipper.hpp>
|
||||
void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer,
|
||||
int aClearanceValue,
|
||||
int aCircleToSegmentsCount,
|
||||
double aCorrectionFactor ) const
|
||||
{
|
||||
wxPoint corner_position;
|
||||
double angle;
|
||||
double angle = m_Orient;
|
||||
int dx = (m_Size.x / 2) + aClearanceValue;
|
||||
int dy = (m_Size.y / 2) + aClearanceValue;
|
||||
|
||||
double delta = 3600.0 / aCircleToSegmentsCount; // rot angle in 0.1 degree
|
||||
wxPoint PadShapePos = ShapePos(); /* Note: for pad having a shape offset,
|
||||
wxPoint PadShapePos = ShapePos(); /* 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( GetShape() )
|
||||
{
|
||||
|
@ -547,7 +544,6 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
|
|||
|
||||
case PAD_OVAL:
|
||||
// An oval pad has the same shape as a segment with rounded ends
|
||||
angle = m_Orient;
|
||||
{
|
||||
int width;
|
||||
wxPoint shape_offset;
|
||||
|
@ -573,77 +569,51 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
|
|||
break;
|
||||
|
||||
case PAD_TRAPEZOID:
|
||||
psize.x += std::abs( m_DeltaSize.y );
|
||||
psize.y += std::abs( m_DeltaSize.x );
|
||||
|
||||
// fall through
|
||||
case PAD_RECT:
|
||||
// Easy implementation for rectangular cutouts with rounded corners
|
||||
angle = m_Orient;
|
||||
{
|
||||
wxPoint corners[4];
|
||||
BuildPadPolygon( corners, wxSize( 0, 0 ), angle );
|
||||
|
||||
// Corner rounding radius
|
||||
int rounding_radius = KiROUND( aClearanceValue * aCorrectionFactor );
|
||||
double angle_pg; // Polygon increment angle
|
||||
// We are using ClipperLib to inflate the polygon shape, using
|
||||
// arcs to connect moved segments.
|
||||
ClipperLib::Path outline;
|
||||
ClipperLib::Paths shapeWithClearance;
|
||||
|
||||
for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ )
|
||||
for( int ii = 0; ii < 4; ii++ )
|
||||
outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y );
|
||||
|
||||
ClipperLib::ClipperOffset offset_engine;
|
||||
// Prepare an offset (inflate) transform, with edges connected by arcs
|
||||
offset_engine.AddPath( outline, ClipperLib::jtRound, ClipperLib::etClosedPolygon );
|
||||
|
||||
// Clipper approximates arcs by segments
|
||||
// It uses a value called ArcTolerance which is the max error between the arc
|
||||
// and segments created to approximate this arc
|
||||
// the number of segm per circle is:
|
||||
// n = PI / acos(1 - arc_tolerance / (arc radius))
|
||||
// the arc radius is aClearanceValue
|
||||
// because arc_tolerance is << aClearanceValue and aClearanceValue >= 0
|
||||
// n = PI / (arc_tolerance / aClearanceValue )
|
||||
offset_engine.ArcTolerance = (double)aClearanceValue / 3.14 / aCircleToSegmentsCount;
|
||||
|
||||
double rounding_radius = aClearanceValue * aCorrectionFactor;
|
||||
offset_engine.Execute( shapeWithClearance, rounding_radius );
|
||||
|
||||
// get new outline (only one polygon is expected)
|
||||
// For info, ClipperLib uses long long to handle integer coordinates
|
||||
ClipperLib::Path& polygon = shapeWithClearance[0];
|
||||
|
||||
for( unsigned jj = 0; jj < polygon.size(); jj++ )
|
||||
{
|
||||
corner_position = wxPoint( 0, -rounding_radius );
|
||||
RotatePoint( &corner_position, (1800.0 / 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
|
||||
CPolyPt polypoint( corner_position.x, corner_position.y );
|
||||
aCornerBuffer.Append( polypoint );
|
||||
}
|
||||
|
||||
for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ )
|
||||
{
|
||||
corner_position = wxPoint( -rounding_radius, 0 );
|
||||
RotatePoint( &corner_position, (1800.0 / 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;
|
||||
CPolyPt polypoint( corner_position.x, corner_position.y );
|
||||
aCornerBuffer.Append( polypoint );
|
||||
}
|
||||
|
||||
for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ )
|
||||
{
|
||||
corner_position = wxPoint( 0, rounding_radius );
|
||||
RotatePoint( &corner_position, (1800.0 / aCircleToSegmentsCount) );
|
||||
angle_pg = i * delta;
|
||||
RotatePoint( &corner_position, angle_pg );
|
||||
corner_position += psize / 2;
|
||||
RotatePoint( &corner_position, angle );
|
||||
corner_position += PadShapePos;
|
||||
CPolyPt polypoint( corner_position.x, corner_position.y );
|
||||
aCornerBuffer.Append( polypoint );
|
||||
}
|
||||
|
||||
for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ )
|
||||
{
|
||||
corner_position = wxPoint( rounding_radius, 0 );
|
||||
RotatePoint( &corner_position, (1800.0 / 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.x = int( polygon[jj].X );
|
||||
corner_position.y = int( polygon[jj].Y );
|
||||
corner_position += PadShapePos;
|
||||
CPolyPt polypoint( corner_position.x, corner_position.y );
|
||||
aCornerBuffer.Append( polypoint );
|
||||
}
|
||||
|
||||
aCornerBuffer.CloseLastContour();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1090,10 +1060,90 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer,
|
|||
aCornerBuffer.CloseLastContour();
|
||||
angle = AddAngles( angle, 1800 );
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_TRAPEZOID:
|
||||
{
|
||||
CPOLYGONS_LIST cbuffer;
|
||||
// We need a length to build the stubs of the thermal reliefs
|
||||
// the value is not very important. The pad bounding box gives a reasonable value
|
||||
EDA_RECT bbox = aPad.GetBoundingBox();
|
||||
int stub_len = std::max( bbox.GetWidth(), bbox.GetHeight() );
|
||||
|
||||
aPad.TransformShapeWithClearanceToPolygon( cbuffer, aThermalGap,
|
||||
aCircleToSegmentsCount, aCorrectionFactor );
|
||||
|
||||
// We are using ClipperLib to substract stubs to clearance area (antipad area).
|
||||
ClipperLib::Path antipad; // The full antipad area
|
||||
ClipperLib::Path stub; // A basic stub ( a rectangle)
|
||||
ClipperLib::Paths stubs; // the full stubs shape
|
||||
ClipperLib::Paths thermalShape; // the holes in copper zone
|
||||
|
||||
// cbuffer is expected to contain only one polygon, which is
|
||||
// area of the pad + the thermal gap (the antipad)
|
||||
for( unsigned ii = 0; ii < cbuffer.GetCornersCount(); ii++ )
|
||||
antipad << ClipperLib::IntPoint( cbuffer.GetPos(ii).x, cbuffer.GetPos(ii).y );
|
||||
|
||||
// We now substract the stubs (connections to the copper zone)
|
||||
ClipperLib::Clipper clip_engine;
|
||||
// Prepare a clipping transform
|
||||
clip_engine.AddPath( antipad, ClipperLib::ptSubject, true );
|
||||
|
||||
// Create stubs and add them to clipper engine
|
||||
wxPoint stubBuffer[4];
|
||||
stubBuffer[0].x = stub_len;
|
||||
stubBuffer[0].y = copper_thickness.y/2;
|
||||
stubBuffer[1] = stubBuffer[0];
|
||||
stubBuffer[1].y = -copper_thickness.y/2;
|
||||
stubBuffer[2] = stubBuffer[1];
|
||||
stubBuffer[2].x = -stub_len;
|
||||
stubBuffer[3] = stubBuffer[2];
|
||||
stubBuffer[3].y = copper_thickness.y/2;
|
||||
|
||||
for( unsigned ii = 0; ii < DIM( stubBuffer ); ii++ )
|
||||
{
|
||||
wxPoint cpos = stubBuffer[ii];
|
||||
RotatePoint( &cpos, aPad.GetOrientation() );
|
||||
cpos += PadShapePos;
|
||||
stub << ClipperLib::IntPoint( cpos.x, cpos.y );
|
||||
}
|
||||
|
||||
ClipperLib::Clipper stubs_engine;
|
||||
stubs_engine.AddPath( stub, ClipperLib::ptSubject, true );
|
||||
|
||||
stubBuffer[0].y = stub_len;
|
||||
stubBuffer[0].x = copper_thickness.x/2;
|
||||
stubBuffer[1] = stubBuffer[0];
|
||||
stubBuffer[1].x = -copper_thickness.x/2;
|
||||
stubBuffer[2] = stubBuffer[1];
|
||||
stubBuffer[2].y = -stub_len;
|
||||
stubBuffer[3] = stubBuffer[2];
|
||||
stubBuffer[3].x = copper_thickness.x/2;
|
||||
stub.clear();
|
||||
|
||||
for( unsigned ii = 0; ii < DIM( stubBuffer ); ii++ )
|
||||
{
|
||||
wxPoint cpos = stubBuffer[ii];
|
||||
RotatePoint( &cpos, aPad.GetOrientation() );
|
||||
cpos += PadShapePos;
|
||||
stub << ClipperLib::IntPoint( cpos.x, cpos.y );
|
||||
}
|
||||
|
||||
stubs_engine.AddPath( stub, ClipperLib::ptClip, true );
|
||||
|
||||
// Build the full stubs shape:
|
||||
stubs_engine.Execute( ClipperLib::ctUnion, stubs );
|
||||
|
||||
// remove stubs to antipad area (i.e. add copper stubs)
|
||||
clip_engine.AddPath( stubs[0], ClipperLib::ptClip, true );
|
||||
clip_engine.Execute( ClipperLib::ctDifference, thermalShape );
|
||||
|
||||
// put thermal shapes (holes) to list:
|
||||
aCornerBuffer.ImportFrom( thermalShape );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
|
|
@ -1214,9 +1214,11 @@ NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
|
|||
// the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
|
||||
// zero is reserved for "no connection" and is not used.
|
||||
// NULL is returned for non valid netcodes
|
||||
NETINFO_ITEM* net = m_NetInfo.GetNetItem( aNetcode );
|
||||
|
||||
return net;
|
||||
if( aNetcode == NETINFO_LIST::UNCONNECTED )
|
||||
return &NETINFO_LIST::ORPHANED;
|
||||
else
|
||||
return m_NetInfo.GetNetItem( aNetcode );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,8 +38,6 @@ BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype
|
|||
BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED ),
|
||||
m_Subnet( 0 ), m_ZoneSubnet( 0 )
|
||||
{
|
||||
// The unconnected net is set only in case the item belongs to a BOARD
|
||||
SetNetCode( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,20 +50,15 @@ BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem )
|
|||
|
||||
void BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode )
|
||||
{
|
||||
assert( aNetCode >= 0 );
|
||||
BOARD* board = GetBoard();
|
||||
if( board )
|
||||
{
|
||||
m_netinfo = board->FindNet( aNetCode );
|
||||
|
||||
// The requested net does not exist, mark it as unconnected
|
||||
if( m_netinfo == NULL )
|
||||
m_netinfo = board->FindNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
if( board )
|
||||
m_netinfo = board->FindNet( aNetCode );
|
||||
else
|
||||
{
|
||||
// There is no board that contains list of nets, the item is orphaned
|
||||
m_netinfo = &NETINFO_LIST::ORPHANED;
|
||||
}
|
||||
|
||||
assert( m_netinfo );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -272,14 +272,15 @@ public:
|
|||
* keep arc radius when approximated by segments
|
||||
*/
|
||||
void TransformSolidAreasShapesToPolygonSet( CPOLYGONS_LIST& aCornerBuffer,
|
||||
int aCircleToSegmentsCount,
|
||||
double aCorrectionFactor );
|
||||
int aCircleToSegmentsCount,
|
||||
double aCorrectionFactor );
|
||||
/**
|
||||
* Function BuildFilledSolidAreasPolygons
|
||||
* Build the filled solid areas data from real outlines (stored in m_Poly)
|
||||
* The solid areas can be more thna one on copper layers, and do not have holes
|
||||
* The solid areas can be more than one on copper layers, and do not have holes
|
||||
( holes are linked by overlapping segments to the main outline)
|
||||
* in order to have drawable (and plottable) filled polygons
|
||||
* @return true if OK, false if the solid polygons cannot be built
|
||||
* @param aPcb: the current board (can be NULL for non copper zones)
|
||||
* @param aCornerBuffer: A reference to a buffer to store polygon corners, or NULL
|
||||
* if NULL (default:
|
||||
|
@ -287,13 +288,14 @@ public:
|
|||
* - on copper layers, tracks and other items shapes of other nets are
|
||||
* removed from solid areas
|
||||
* if not null:
|
||||
* Only the zone outline (with holes, if any) are stored in aCornerBuffer
|
||||
* with holes linked. Therfore only one polygon is created
|
||||
* @return true if OK, false if the solid areas cannot be calculated
|
||||
* This function calls AddClearanceAreasPolygonsToPolysList()
|
||||
* to add holes for pads and tracks and other items not in net.
|
||||
* Only the zone outline (with holes, if any) is stored in aOutlineBuffer
|
||||
* with holes linked. Therefore only one polygon is created
|
||||
*
|
||||
* When aOutlineBuffer is not null, his function calls
|
||||
* AddClearanceAreasPolygonsToPolysList() to add holes for pads and tracks
|
||||
* and other items not in net.
|
||||
*/
|
||||
bool BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aCornerBuffer = NULL );
|
||||
bool BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aOutlineBuffer = NULL );
|
||||
|
||||
/**
|
||||
* Function CopyPolygonsFromKiPolygonListToFilledPolysList
|
||||
|
|
|
@ -127,15 +127,20 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad )
|
|||
case PAD_CONN:
|
||||
{
|
||||
LSET lmsk = aPad->GetLayerSet();
|
||||
bool is_copper = false;
|
||||
|
||||
for( int i = 0; i < MAX_CU_LAYERS; i++ )
|
||||
{
|
||||
if( lmsk[i] )
|
||||
{
|
||||
is_copper = true;
|
||||
layers = PNS_LAYERSET( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !is_copper )
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -693,7 +698,7 @@ void PNS_ROUTER::CommitRouting( PNS_NODE* aNode )
|
|||
track->SetEnd( wxPoint( s.B.x, s.B.y ) );
|
||||
track->SetWidth( seg->Width() );
|
||||
track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
|
||||
track->SetNetCode( seg->Net() );
|
||||
track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 );
|
||||
newBI = track;
|
||||
break;
|
||||
}
|
||||
|
@ -705,7 +710,7 @@ void PNS_ROUTER::CommitRouting( PNS_NODE* aNode )
|
|||
via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) );
|
||||
via_board->SetWidth( via->Diameter() );
|
||||
via_board->SetDrill( via->Drill() );
|
||||
via_board->SetNetCode( via->Net() );
|
||||
via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 );
|
||||
via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
|
||||
via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
|
||||
ToLAYER_ID( via->Layers().End() ) );
|
||||
|
|
|
@ -43,22 +43,19 @@
|
|||
( holes are linked by overlapping segments to the main outline)
|
||||
* aPcb: the current board (can be NULL for non copper zones)
|
||||
* aCornerBuffer: A reference to a buffer to store polygon corners, or NULL
|
||||
* if NULL:
|
||||
* if aCornerBuffer == NULL:
|
||||
* - m_FilledPolysList is used to store solid areas polygons.
|
||||
* - on copper layers, tracks and other items shapes of other nets are
|
||||
* removed from solid areas
|
||||
* if not null:
|
||||
* Only the zone outline (with holes, if any) are stored in aCornerBuffer
|
||||
* with holes linked. Therfore only one polygon is created
|
||||
* with holes linked. Therefore only one polygon is created
|
||||
* This function calls AddClearanceAreasPolygonsToPolysList()
|
||||
* to add holes for pads and tracks and other items not in net.
|
||||
*/
|
||||
|
||||
bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aCornerBuffer )
|
||||
bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aOutlineBuffer )
|
||||
{
|
||||
if( aCornerBuffer == NULL )
|
||||
m_FilledPolysList.RemoveAllContours();
|
||||
|
||||
/* convert outlines + holes to outlines without holes (adding extra segments if necessary)
|
||||
* m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
|
||||
* this zone
|
||||
|
@ -90,47 +87,33 @@ bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST*
|
|||
break;
|
||||
}
|
||||
|
||||
if( aCornerBuffer )
|
||||
ConvertPolysListWithHolesToOnePolygon( m_smoothedPoly->m_CornersList, *aCornerBuffer );
|
||||
else
|
||||
ConvertPolysListWithHolesToOnePolygon( m_smoothedPoly->m_CornersList, m_FilledPolysList );
|
||||
if( aOutlineBuffer )
|
||||
aOutlineBuffer->Append( m_smoothedPoly->m_CornersList );
|
||||
|
||||
/* For copper layers, we now must add holes in the Polygon list.
|
||||
* holes are pads and tracks with their clearance area
|
||||
* for non copper layers just recalculate the m_FilledPolysList
|
||||
* with m_ZoneMinThickness taken in account
|
||||
*/
|
||||
if( !aCornerBuffer )
|
||||
else
|
||||
{
|
||||
m_FilledPolysList.RemoveAllContours();
|
||||
|
||||
if( IsOnCopperLayer() )
|
||||
AddClearanceAreasPolygonsToPolysList( aPcb );
|
||||
else
|
||||
{
|
||||
// This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2
|
||||
KI_POLYGON_SET polyset_zone_solid_areas;
|
||||
int margin = m_ZoneMinThickness / 2;
|
||||
|
||||
/* First, creates the main polygon (i.e. the filled area using only one outline)
|
||||
* to reserve a m_ZoneMinThickness/2 margin around the outlines and holes
|
||||
* this margin is the room to redraw outlines with segments having a width set to
|
||||
* m_ZoneMinThickness
|
||||
* so m_ZoneMinThickness is the min thickness of the filled zones areas
|
||||
* the polygon is stored in polyset_zone_solid_areas
|
||||
*/
|
||||
CopyPolygonsFromFilledPolysListToKiPolygonList( polyset_zone_solid_areas );
|
||||
polyset_zone_solid_areas -= margin;
|
||||
// put solid area in m_FilledPolysList:
|
||||
m_FilledPolysList.RemoveAllContours();
|
||||
CopyPolygonsFromKiPolygonListToFilledPolysList( polyset_zone_solid_areas );
|
||||
m_smoothedPoly->m_CornersList.InflateOutline(m_FilledPolysList, margin, true );
|
||||
}
|
||||
|
||||
if( m_FillMode ) // if fill mode uses segments, create them:
|
||||
FillZoneAreasWithSegments();
|
||||
|
||||
m_IsFilled = true;
|
||||
}
|
||||
|
||||
m_IsFilled = true;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -138,6 +138,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
*/
|
||||
s_Correction = 1.0 / cos( M_PI / s_CircleToSegmentsCount );
|
||||
|
||||
// this is a place to store holes (i.e. tracks, pads ... areas as polygons outlines)
|
||||
// static to avoid unnecessary memory allocation when filling many zones.
|
||||
static CPOLYGONS_LIST cornerBufferPolysToSubstract;
|
||||
cornerBufferPolysToSubstract.RemoveAllContours();
|
||||
|
||||
// This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2
|
||||
KI_POLYGON_SET polyset_zone_solid_areas;
|
||||
int margin = m_ZoneMinThickness / 2;
|
||||
|
@ -149,13 +154,35 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
* so m_ZoneMinThickness is the min thickness of the filled zones areas
|
||||
* the main polygon is stored in polyset_zone_solid_areas
|
||||
*/
|
||||
|
||||
CopyPolygonsFromFilledPolysListToKiPolygonList( polyset_zone_solid_areas );
|
||||
polyset_zone_solid_areas -= margin;
|
||||
#if 1
|
||||
m_smoothedPoly->m_CornersList.ExportTo( polyset_zone_solid_areas );
|
||||
|
||||
if( polyset_zone_solid_areas.size() == 0 )
|
||||
return;
|
||||
|
||||
// Extract holes (cutout areas) and add them to the hole buffer
|
||||
KI_POLYGON_SET outlineHoles;
|
||||
|
||||
while( polyset_zone_solid_areas.size() > 1 )
|
||||
{
|
||||
outlineHoles.push_back( polyset_zone_solid_areas.back() );
|
||||
polyset_zone_solid_areas.pop_back();
|
||||
}
|
||||
|
||||
// deflate main outline reserve room for thick outline
|
||||
polyset_zone_solid_areas -= margin;
|
||||
// inflate outline holes
|
||||
if( outlineHoles.size() )
|
||||
outlineHoles += margin;
|
||||
|
||||
if( outlineHoles.size() )
|
||||
cornerBufferPolysToSubstract.ImportFrom( outlineHoles );
|
||||
#else
|
||||
CPOLYGONS_LIST tmp;
|
||||
m_smoothedPoly->m_CornersList.InflateOutline( tmp, -margin, true );
|
||||
tmp.ExportTo( polyset_zone_solid_areas );
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
@ -186,10 +213,6 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
*/
|
||||
int item_clearance;
|
||||
|
||||
// static to avoid unnecessary memory allocation when filling many zones.
|
||||
static CPOLYGONS_LIST cornerBufferPolysToSubstract;
|
||||
cornerBufferPolysToSubstract.RemoveAllContours();
|
||||
|
||||
/* 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
|
||||
|
@ -249,11 +272,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
continue;
|
||||
}
|
||||
|
||||
if( ( GetPadConnection( pad ) == PAD_NOT_IN_ZONE )
|
||||
|| ( pad->GetShape() == 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
|
||||
if( GetPadConnection( pad ) == PAD_NOT_IN_ZONE )
|
||||
{
|
||||
int gap = zone_clearance;
|
||||
int thermalGap = GetThermalReliefGap( pad );
|
||||
|
|
|
@ -51,12 +51,13 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
|
|||
CPOLYGONS_LIST& aCornerBuffer,
|
||||
int aClearanceValue, bool aAddClearance )
|
||||
{
|
||||
// Creates the zone outlines polygon (with linked holes if any)
|
||||
CPOLYGONS_LIST zoneOutines;
|
||||
BuildFilledSolidAreasPolygons( NULL, &zoneOutines );
|
||||
// Creates the zone outline polygon (with linked holes if any)
|
||||
CPOLYGONS_LIST zoneOutline;
|
||||
BuildFilledSolidAreasPolygons( NULL, &zoneOutline );
|
||||
|
||||
// add clearance to outline
|
||||
int clearance = 0;
|
||||
|
||||
if( aAddClearance )
|
||||
{
|
||||
clearance = GetClearance();
|
||||
|
@ -64,51 +65,11 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
|
|||
clearance = aClearanceValue;
|
||||
}
|
||||
// Calculate the polygon with clearance
|
||||
// holes are linked to the main outline, so only one polygon should be created.
|
||||
KI_POLYGON_SET polyset_zone_solid_areas;
|
||||
std::vector<KI_POLY_POINT> cornerslist;
|
||||
unsigned ic = 0;
|
||||
unsigned corners_count = zoneOutines.GetCornersCount();
|
||||
while( ic < corners_count )
|
||||
{
|
||||
cornerslist.clear();
|
||||
KI_POLYGON poly;
|
||||
{
|
||||
for( ; ic < corners_count; ic++ )
|
||||
{
|
||||
CPolyPt* corner = &zoneOutines[ic];
|
||||
cornerslist.push_back( KI_POLY_POINT( corner->x, corner->y ) );
|
||||
if( corner->end_contour )
|
||||
{
|
||||
ic++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bpl::set_points( poly, cornerslist.begin(), cornerslist.end() );
|
||||
polyset_zone_solid_areas.push_back( poly );
|
||||
}
|
||||
}
|
||||
|
||||
polyset_zone_solid_areas += clearance;
|
||||
|
||||
// Put the resulting polygon in aCornerBuffer corners list
|
||||
for( unsigned ii = 0; ii < polyset_zone_solid_areas.size(); ii++ )
|
||||
{
|
||||
KI_POLYGON& poly = polyset_zone_solid_areas[ii];
|
||||
CPolyPt corner( 0, 0, false );
|
||||
|
||||
for( unsigned jj = 0; jj < poly.size(); jj++ )
|
||||
{
|
||||
KI_POLY_POINT point = *(poly.begin() + jj);
|
||||
corner.x = point.x();
|
||||
corner.y = point.y();
|
||||
corner.end_contour = false;
|
||||
aCornerBuffer.Append( corner );
|
||||
}
|
||||
|
||||
aCornerBuffer.CloseLastContour();
|
||||
}
|
||||
// holes are linked to the main outline, so only one polygon is created.
|
||||
if( clearance )
|
||||
zoneOutline.InflateOutline( aCornerBuffer, clearance, true );
|
||||
else
|
||||
ConvertPolysListWithHolesToOnePolygon( zoneOutline, aCornerBuffer );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1347,6 +1347,44 @@ void CPOLYGONS_LIST::ExportTo( KI_POLYGON_SET& aPolygons ) const
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy all contours to a ClipperLib::Paths& aPolygons
|
||||
* Each contour is copied into a ClipperLib::Path, and each ClipperLib::Path
|
||||
* is append to aPolygons
|
||||
*/
|
||||
void CPOLYGONS_LIST::ExportTo( ClipperLib::Paths& aPolygons ) const
|
||||
{
|
||||
unsigned corners_count = GetCornersCount();
|
||||
|
||||
// Count the number of polygons in aCornersBuffer
|
||||
int polycount = 0;
|
||||
|
||||
for( unsigned ii = 0; ii < corners_count; ii++ )
|
||||
{
|
||||
if( IsEndContour( ii ) )
|
||||
polycount++;
|
||||
}
|
||||
|
||||
aPolygons.reserve( polycount );
|
||||
|
||||
for( unsigned icnt = 0; icnt < corners_count; )
|
||||
{
|
||||
ClipperLib::Path poly;
|
||||
unsigned ii;
|
||||
|
||||
for( ii = icnt; ii < corners_count; ii++ )
|
||||
{
|
||||
poly << ClipperLib::IntPoint( GetX( ii ), GetY( ii ) );
|
||||
|
||||
if( IsEndContour( ii ) )
|
||||
break;
|
||||
}
|
||||
|
||||
aPolygons.push_back( poly );
|
||||
icnt = ii + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Imports all polygons found in a KI_POLYGON_SET in list
|
||||
*/
|
||||
|
@ -1372,6 +1410,72 @@ void CPOLYGONS_LIST::ImportFrom( KI_POLYGON_SET& aPolygons )
|
|||
}
|
||||
|
||||
|
||||
/* Imports all polygons found in a ClipperLib::Paths in list
|
||||
*/
|
||||
void CPOLYGONS_LIST::ImportFrom( ClipperLib::Paths& aPolygons )
|
||||
{
|
||||
CPolyPt corner;
|
||||
|
||||
for( unsigned ii = 0; ii < aPolygons.size(); ii++ )
|
||||
{
|
||||
ClipperLib::Path& polygon = aPolygons[ii];
|
||||
|
||||
for( unsigned jj = 0; jj < polygon.size(); jj++ )
|
||||
{
|
||||
corner.x = int( polygon[jj].X );
|
||||
corner.y = int( polygon[jj].Y );
|
||||
corner.end_contour = false;
|
||||
AddCorner( corner );
|
||||
}
|
||||
|
||||
CloseLastContour();
|
||||
}
|
||||
}
|
||||
|
||||
/* Inflate the outline stored in m_cornersList.
|
||||
* The first polygon is the external outline. It is inflated
|
||||
* The other polygons are holes. they are deflated
|
||||
* aResult = the Inflated outline
|
||||
* aInflateValue = the Inflate value. when < 0, this is a deflate transform
|
||||
* aLinkHoles = if true, aResult contains only one polygon,
|
||||
* with holes linked by overlapping segments
|
||||
*/
|
||||
void CPOLYGONS_LIST::InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue, bool aLinkHoles )
|
||||
{
|
||||
KI_POLYGON_SET polyset_outline;
|
||||
ExportTo( polyset_outline );
|
||||
|
||||
// Extract holes (cutout areas) and add them to the hole buffer
|
||||
KI_POLYGON_SET outlineHoles;
|
||||
|
||||
while( polyset_outline.size() > 1 )
|
||||
{
|
||||
outlineHoles.push_back( polyset_outline.back() );
|
||||
polyset_outline.pop_back();
|
||||
}
|
||||
|
||||
// inflate main outline
|
||||
if( polyset_outline.size() )
|
||||
polyset_outline += aInflateValue;
|
||||
|
||||
// deflate outline holes
|
||||
if( outlineHoles.size() )
|
||||
outlineHoles -= aInflateValue;
|
||||
|
||||
// Copy modified polygons
|
||||
if( !aLinkHoles )
|
||||
{
|
||||
aResult.ImportFrom( polyset_outline );
|
||||
|
||||
if( outlineHoles.size() )
|
||||
aResult.ImportFrom( outlineHoles );
|
||||
}
|
||||
else
|
||||
{
|
||||
polyset_outline -= outlineHoles;
|
||||
aResult.ImportFrom( polyset_outline );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ConvertPolysListWithHolesToOnePolygon
|
||||
|
@ -1438,26 +1542,14 @@ void ConvertPolysListWithHolesToOnePolygon( const CPOLYGONS_LIST& aPolysListWith
|
|||
polysholes.push_back( poly_tmp );
|
||||
}
|
||||
}
|
||||
|
||||
mainpoly -= polysholes;
|
||||
|
||||
// copy polygon with no holes to destination
|
||||
// Because all holes are now linked to the main outline
|
||||
// by overlapping segments, we should have only one polygon in list
|
||||
wxASSERT( mainpoly.size() == 1 );
|
||||
|
||||
KI_POLYGON& poly_nohole = mainpoly[0];
|
||||
CPolyPt corner( 0, 0, false );
|
||||
|
||||
for( unsigned jj = 0; jj < poly_nohole.size(); jj++ )
|
||||
{
|
||||
KI_POLY_POINT point = *(poly_nohole.begin() + jj);
|
||||
corner.x = point.x();
|
||||
corner.y = point.y();
|
||||
corner.end_contour = false;
|
||||
aOnePolyList.AddCorner( corner );
|
||||
}
|
||||
|
||||
aOnePolyList.CloseLastContour();
|
||||
aOnePolyList.ImportFrom( mainpoly );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1553,3 +1645,22 @@ bool CPolyLine::IsPolygonSelfIntersecting()
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* converts the outline aOnePolyList (only one contour,
|
||||
* holes are linked by overlapping segments) to
|
||||
* to one main polygon and holes (polygons inside main polygon)
|
||||
* aOnePolyList = a only one polygon ( holes are linked )
|
||||
* aPolysListWithHoles = the list of corners of contours
|
||||
* (main outline and holes)
|
||||
*/
|
||||
void ConvertOnePolygonToPolysListWithHoles( const CPOLYGONS_LIST& aOnePolyList,
|
||||
CPOLYGONS_LIST& aPolysListWithHoles )
|
||||
{
|
||||
ClipperLib::Paths initialPoly;
|
||||
ClipperLib::Paths modifiedPoly;
|
||||
|
||||
aOnePolyList.ExportTo( initialPoly );
|
||||
SimplifyPolygon(initialPoly[0], modifiedPoly );
|
||||
aPolysListWithHoles.ImportFrom( modifiedPoly );
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <layers_id_colors_and_visibility.h> // for LAYER_NUM definition
|
||||
#include <class_eda_rect.h> // for EDA_RECT definition
|
||||
#include <polygons_defs.h>
|
||||
#include <clipper.hpp>
|
||||
|
||||
class CSegment
|
||||
{
|
||||
|
@ -186,28 +187,6 @@ public:
|
|||
m_cornersList.insert( m_cornersList.begin() + aPosition + 1, aItem );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ExportTo
|
||||
* Copy all contours to a KI_POLYGON_SET
|
||||
* @param aPolygons = the KI_POLYGON_WITH_HOLES to populate
|
||||
*/
|
||||
void ExportTo( KI_POLYGON_SET& aPolygons ) const;
|
||||
|
||||
/**
|
||||
* Function ExportTo
|
||||
* Copy the contours to a KI_POLYGON_WITH_HOLES
|
||||
* The first contour is the main outline, others are holes
|
||||
* @param aPolygoneWithHole = the KI_POLYGON_WITH_HOLES to populate
|
||||
*/
|
||||
void ExportTo( KI_POLYGON_WITH_HOLES& aPolygoneWithHole ) const;
|
||||
|
||||
/**
|
||||
* Function ImportFrom
|
||||
* Copy all polygons from a KI_POLYGON_SET in list
|
||||
* @param aPolygons = the KI_POLYGON_SET to import
|
||||
*/
|
||||
void ImportFrom( KI_POLYGON_SET& aPolygons );
|
||||
|
||||
/**
|
||||
* function AddCorner
|
||||
* add a corner to the list
|
||||
|
@ -226,6 +205,56 @@ public:
|
|||
if( m_cornersList.size() > 0 )
|
||||
m_cornersList.back().end_contour = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ExportTo
|
||||
* Copy all contours to a KI_POLYGON_SET, each contour is exported
|
||||
* to a KI_POLYGON
|
||||
* @param aPolygons = the KI_POLYGON_SET to populate
|
||||
*/
|
||||
void ExportTo( KI_POLYGON_SET& aPolygons ) const;
|
||||
|
||||
/**
|
||||
* Function ExportTo
|
||||
* Copy the contours to a KI_POLYGON_WITH_HOLES
|
||||
* The first contour is the main outline, others are holes
|
||||
* @param aPolygoneWithHole = the KI_POLYGON_WITH_HOLES to populate
|
||||
*/
|
||||
void ExportTo( KI_POLYGON_WITH_HOLES& aPolygoneWithHole ) const;
|
||||
|
||||
/**
|
||||
* Function ExportTo
|
||||
* Copy all contours to a ClipperLib::Paths, each contour is exported
|
||||
* to a ClipperLib::Path
|
||||
* @param aPolygons = the ClipperLib::Paths to populate
|
||||
*/
|
||||
void ExportTo( ClipperLib::Paths& aPolygons ) const;
|
||||
|
||||
/**
|
||||
* Function ImportFrom
|
||||
* Copy all polygons from a KI_POLYGON_SET in list
|
||||
* @param aPolygons = the KI_POLYGON_SET to import
|
||||
*/
|
||||
void ImportFrom( KI_POLYGON_SET& aPolygons );
|
||||
|
||||
/**
|
||||
* Function ImportFrom
|
||||
* Copy all polygons from a ClipperLib::Paths in list
|
||||
* @param aPolygons = the ClipperLib::Paths to import
|
||||
*/
|
||||
void ImportFrom( ClipperLib::Paths& aPolygons );
|
||||
|
||||
/**
|
||||
* Function InflateOutline
|
||||
* Inflate the outline stored in m_cornersList.
|
||||
* The first polygon is the external outline. It is inflated
|
||||
* The other polygons are holes. they are deflated
|
||||
* @param aResult = the Inflated outline
|
||||
* @param aInflateValue = the Inflate value. when < 0, this is a deflate transform
|
||||
* @param aLinkHoles = if true, aResult contains only one polygon,
|
||||
* with holes linked by overlapping segments
|
||||
*/
|
||||
void InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue, bool aLinkHoles );
|
||||
};
|
||||
|
||||
class CPolyLine
|
||||
|
@ -489,4 +518,17 @@ public:
|
|||
void ConvertPolysListWithHolesToOnePolygon( const CPOLYGONS_LIST& aPolysListWithHoles,
|
||||
CPOLYGONS_LIST& aOnePolyList );
|
||||
|
||||
/**
|
||||
* Function ConvertOnePolygonToPolysListWithHoles
|
||||
* converts the outline aOnePolyList (only one contour,
|
||||
* holes are linked by overlapping segments) to
|
||||
* to one main polygon and holes (polygons inside main polygon)
|
||||
* @param aOnePolyList = a polygon with no holes
|
||||
* @param aPolysListWithHoles = the list of corners of contours
|
||||
* (main outline and holes)
|
||||
*/
|
||||
void ConvertOnePolygonToPolysListWithHoles( const CPOLYGONS_LIST& aOnePolyList,
|
||||
CPOLYGONS_LIST& aPolysListWithHoles );
|
||||
|
||||
|
||||
#endif // #ifndef POLYLINE_H
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
# $1 wxWidgets/wxPython source folder (relative to current dir)
|
||||
# $2 Target bin folder
|
||||
# $3 KiCad source folder (relative to current dir)
|
||||
# $4 Make options (e.g., "-j4")
|
||||
# $4 OSX target version (e.g., "10.8")
|
||||
# $5 Extra make options (e.g., "-j4")
|
||||
|
||||
createPaths() {
|
||||
echo "*** Creating/wiping build and bin folder..."
|
||||
|
@ -59,10 +60,8 @@ wxWidgets_configure() {
|
|||
--with-zlib=builtin \
|
||||
--with-expat=builtin \
|
||||
--without-liblzma \
|
||||
--with-macosx-version-min=10.5 \
|
||||
--with-macosx-version-min=$3 \
|
||||
--enable-universal-binary=i386,x86_64 \
|
||||
CPPFLAGS="-stdlib=libstdc++" \
|
||||
LDFLAGS="-stdlib=libstdc++" \
|
||||
CC=clang \
|
||||
CXX=clang++
|
||||
if [ $? -ne 0 ];
|
||||
|
@ -119,16 +118,17 @@ wxPython_buildInst() {
|
|||
|
||||
|
||||
# check parameters
|
||||
if [ "$#" -lt 3 ];
|
||||
if [ "$#" -lt 4 ];
|
||||
then
|
||||
echo "OSX wxWidgets/wxPython build script"
|
||||
echo
|
||||
echo "Usage:"
|
||||
echo " osx_build_wx.sh <src> <bin> <kicad> <makeopts>"
|
||||
echo " osx_build_wx.sh <src> <bin> <kicad> <osxtarget> [makeopts]"
|
||||
echo " <src> wxWidgets/wxPython source folder"
|
||||
echo " <bin> Destination folder"
|
||||
echo " <kicad> KiCad folder"
|
||||
echo " <makeopts> Optional: make options for building wxWidgets (e.g., -j4)"
|
||||
echo " <osxtarget> OSX target (e.g., 10.7)"
|
||||
echo " [makeopts] Optional: make options for building wxWidgets (e.g., -j4)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -142,8 +142,8 @@ doPatch "$1" "$3/patches/wxwidgets-3.0.0_macosx_bug_15908.patch"
|
|||
doPatch "$1" "$3/patches/wxwidgets-3.0.0_macosx_soname.patch"
|
||||
|
||||
# configure and build wxWidgets
|
||||
wxWidgets_configure "$1" "$2"
|
||||
wxWidgets_buildInst "$4"
|
||||
wxWidgets_configure "$1" "$2" "$4"
|
||||
wxWidgets_buildInst "$5"
|
||||
|
||||
# check if source is wxPython
|
||||
if [ -d $1/wxPython ];
|
||||
|
|
Loading…
Reference in New Issue