mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-17 00:29:06 +00:00
pcbnew: Optimized zone filling algorithm.
This commit is contained in:
parent
8b68a1736a
commit
316ddadec1
CMakeLists.txt
common
include
pcbnew
CMakeLists.txtclass_zone.cppclass_zone.hconnectivity_algo.cppconnectivity_algo.hconnectivity_data.cppconnectivity_data.hpcb_draw_panel_gal.cpppcb_draw_panel_gal.hpcb_painter.cpp
tools
zone_filling_algorithm.cppzones_by_polygon_fill_functions.cppzones_convert_brd_items_to_polygons_with_Boost.cppzones_polygons_insulated_copper_islands.cpppolygon
CMakeLists.txt
poly2tri
qa
@ -478,6 +478,7 @@ include( CheckFindPackageResult )
|
||||
find_package( OpenMP )
|
||||
|
||||
if( OPENMP_FOUND )
|
||||
message( "FOUND OPENMP" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" )
|
||||
add_definitions( -DUSE_OPENMP )
|
||||
|
@ -179,6 +179,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/indicator_icon.cpp
|
||||
widgets/text_ctrl_eval.cpp
|
||||
widgets/unit_binder.cpp
|
||||
widgets/progress_reporter.cpp
|
||||
)
|
||||
|
||||
set( COMMON_PAGE_LAYOUT_SRCS
|
||||
@ -273,6 +274,7 @@ set( COMMON_SRCS
|
||||
kiway_player.cpp
|
||||
lib_table_base.cpp
|
||||
lockfile.cpp
|
||||
md5_hash.cpp
|
||||
msgpanel.cpp
|
||||
netlist_keywords.cpp
|
||||
observable.cpp
|
||||
|
@ -776,9 +776,52 @@ void OPENGL_GAL::DrawPolygon( const VECTOR2D aPointList[], int aListSize )
|
||||
drawPolygon( points.get(), aListSize );
|
||||
}
|
||||
|
||||
void OPENGL_GAL::drawTriangulatedPolyset( const SHAPE_POLY_SET& aPolySet )
|
||||
{
|
||||
currentManager->Shader( SHADER_NONE );
|
||||
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||
|
||||
|
||||
if ( isFillEnabled )
|
||||
{
|
||||
for( int j = 0; j < aPolySet.OutlineCount(); ++j )
|
||||
{
|
||||
auto triPoly = aPolySet.TriangulatedPolygon( j );
|
||||
|
||||
for ( int i = 0; i < triPoly->m_triangleCount; i++ )
|
||||
{
|
||||
VECTOR2I a, b, c;
|
||||
triPoly->GetTriangle( i ,a,b,c);
|
||||
currentManager->Vertex( a.x, a.y, layerDepth );
|
||||
currentManager->Vertex( b.x, b.y, layerDepth );
|
||||
currentManager->Vertex( c.x, c.y, layerDepth );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( isStrokeEnabled )
|
||||
{
|
||||
for( int j = 0; j < aPolySet.OutlineCount(); ++j )
|
||||
{
|
||||
const auto& poly = aPolySet.Polygon( j );
|
||||
|
||||
for( const auto& lc : poly )
|
||||
{
|
||||
DrawPolyline( lc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawPolygon( const SHAPE_POLY_SET& aPolySet )
|
||||
{
|
||||
if ( aPolySet.IsTriangulationUpToDate() )
|
||||
{
|
||||
drawTriangulatedPolyset( aPolySet );
|
||||
return;
|
||||
}
|
||||
|
||||
for( int j = 0; j < aPolySet.OutlineCount(); ++j )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& outline = aPolySet.COutline( j );
|
||||
@ -1470,7 +1513,6 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa
|
||||
Restore();
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::drawPolygon( GLdouble* aPoints, int aPointCount )
|
||||
{
|
||||
currentManager->Shader( SHADER_NONE );
|
||||
|
File diff suppressed because it is too large
Load Diff
250
common/md5_hash.cpp
Normal file
250
common/md5_hash.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
// Code by: B-Con (http://b-con.us)
|
||||
// Released under the GNU GPL
|
||||
// MD5 Hash Digest implementation (little endian byte order)
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#include <md5_hash.h>
|
||||
|
||||
// DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it
|
||||
#define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - c) ++b; a += c;
|
||||
#define ROTLEFT(a,b) ((a << b) | (a >> (32-b)))
|
||||
|
||||
#define F(x,y,z) ((x & y) | (~x & z))
|
||||
#define G(x,y,z) ((x & z) | (y & ~z))
|
||||
#define H(x,y,z) (x ^ y ^ z)
|
||||
#define I(x,y,z) (y ^ (x | ~z))
|
||||
|
||||
#define FF(a,b,c,d,m,s,t) { a += F(b,c,d) + m + t; \
|
||||
a = b + ROTLEFT(a,s); }
|
||||
#define GG(a,b,c,d,m,s,t) { a += G(b,c,d) + m + t; \
|
||||
a = b + ROTLEFT(a,s); }
|
||||
#define HH(a,b,c,d,m,s,t) { a += H(b,c,d) + m + t; \
|
||||
a = b + ROTLEFT(a,s); }
|
||||
#define II(a,b,c,d,m,s,t) { a += I(b,c,d) + m + t; \
|
||||
a = b + ROTLEFT(a,s); }
|
||||
|
||||
|
||||
|
||||
|
||||
MD5_HASH::MD5_HASH()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
MD5_HASH::MD5_HASH( const MD5_HASH& aOther )
|
||||
{
|
||||
m_valid = aOther.m_valid;
|
||||
m_ctx = aOther.m_ctx;
|
||||
memcpy( m_hash, aOther.m_hash, 16 );
|
||||
}
|
||||
|
||||
MD5_HASH::~MD5_HASH()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MD5_HASH& MD5_HASH::operator=( const MD5_HASH& aOther )
|
||||
{
|
||||
m_valid = aOther.m_valid;
|
||||
m_ctx = aOther.m_ctx;
|
||||
memcpy( m_hash, aOther.m_hash, 16 );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void MD5_HASH::Init()
|
||||
{
|
||||
//printf("%p init\n", this);
|
||||
m_valid = false;
|
||||
md5_init(&m_ctx);
|
||||
}
|
||||
|
||||
void MD5_HASH::Hash ( uint8_t *data, uint32_t length )
|
||||
{
|
||||
md5_update(&m_ctx, data, length);
|
||||
}
|
||||
|
||||
void MD5_HASH::Hash ( int value )
|
||||
{
|
||||
md5_update(&m_ctx, (uint8_t*) &value, sizeof(int) );
|
||||
}
|
||||
|
||||
void MD5_HASH::Finalize()
|
||||
{
|
||||
//printf("%p final\n", this);
|
||||
md5_final(&m_ctx, m_hash);
|
||||
m_valid = true;
|
||||
|
||||
}
|
||||
|
||||
bool MD5_HASH::operator==( const MD5_HASH& aOther ) const
|
||||
{
|
||||
return ( memcmp( m_hash, aOther.m_hash, 16 ) == 0 );
|
||||
}
|
||||
|
||||
bool MD5_HASH::operator!=( const MD5_HASH& aOther ) const
|
||||
{
|
||||
return ( memcmp( m_hash, aOther.m_hash, 16 ) != 0 );
|
||||
}
|
||||
|
||||
|
||||
void MD5_HASH::md5_transform(MD5_CTX *ctx, uint8_t data[])
|
||||
{
|
||||
uint32_t a,b,c,d,m[16],i,j;
|
||||
|
||||
// MD5 specifies big endian byte order, but this implementation assumes a little
|
||||
// endian byte order CPU. Reverse all the bytes upon input, and re-reverse them
|
||||
// on output (in md5_final()).
|
||||
for (i=0,j=0; i < 16; ++i, j += 4)
|
||||
m[i] = (data[j]) + (data[j+1] << 8) + (data[j+2] << 16) + (data[j+3] << 24);
|
||||
|
||||
a = ctx->state[0];
|
||||
b = ctx->state[1];
|
||||
c = ctx->state[2];
|
||||
d = ctx->state[3];
|
||||
|
||||
FF(a,b,c,d,m[0], 7,0xd76aa478);
|
||||
FF(d,a,b,c,m[1], 12,0xe8c7b756);
|
||||
FF(c,d,a,b,m[2], 17,0x242070db);
|
||||
FF(b,c,d,a,m[3], 22,0xc1bdceee);
|
||||
FF(a,b,c,d,m[4], 7,0xf57c0faf);
|
||||
FF(d,a,b,c,m[5], 12,0x4787c62a);
|
||||
FF(c,d,a,b,m[6], 17,0xa8304613);
|
||||
FF(b,c,d,a,m[7], 22,0xfd469501);
|
||||
FF(a,b,c,d,m[8], 7,0x698098d8);
|
||||
FF(d,a,b,c,m[9], 12,0x8b44f7af);
|
||||
FF(c,d,a,b,m[10],17,0xffff5bb1);
|
||||
FF(b,c,d,a,m[11],22,0x895cd7be);
|
||||
FF(a,b,c,d,m[12], 7,0x6b901122);
|
||||
FF(d,a,b,c,m[13],12,0xfd987193);
|
||||
FF(c,d,a,b,m[14],17,0xa679438e);
|
||||
FF(b,c,d,a,m[15],22,0x49b40821);
|
||||
|
||||
GG(a,b,c,d,m[1], 5,0xf61e2562);
|
||||
GG(d,a,b,c,m[6], 9,0xc040b340);
|
||||
GG(c,d,a,b,m[11],14,0x265e5a51);
|
||||
GG(b,c,d,a,m[0], 20,0xe9b6c7aa);
|
||||
GG(a,b,c,d,m[5], 5,0xd62f105d);
|
||||
GG(d,a,b,c,m[10], 9,0x02441453);
|
||||
GG(c,d,a,b,m[15],14,0xd8a1e681);
|
||||
GG(b,c,d,a,m[4], 20,0xe7d3fbc8);
|
||||
GG(a,b,c,d,m[9], 5,0x21e1cde6);
|
||||
GG(d,a,b,c,m[14], 9,0xc33707d6);
|
||||
GG(c,d,a,b,m[3], 14,0xf4d50d87);
|
||||
GG(b,c,d,a,m[8], 20,0x455a14ed);
|
||||
GG(a,b,c,d,m[13], 5,0xa9e3e905);
|
||||
GG(d,a,b,c,m[2], 9,0xfcefa3f8);
|
||||
GG(c,d,a,b,m[7], 14,0x676f02d9);
|
||||
GG(b,c,d,a,m[12],20,0x8d2a4c8a);
|
||||
|
||||
HH(a,b,c,d,m[5], 4,0xfffa3942);
|
||||
HH(d,a,b,c,m[8], 11,0x8771f681);
|
||||
HH(c,d,a,b,m[11],16,0x6d9d6122);
|
||||
HH(b,c,d,a,m[14],23,0xfde5380c);
|
||||
HH(a,b,c,d,m[1], 4,0xa4beea44);
|
||||
HH(d,a,b,c,m[4], 11,0x4bdecfa9);
|
||||
HH(c,d,a,b,m[7], 16,0xf6bb4b60);
|
||||
HH(b,c,d,a,m[10],23,0xbebfbc70);
|
||||
HH(a,b,c,d,m[13], 4,0x289b7ec6);
|
||||
HH(d,a,b,c,m[0], 11,0xeaa127fa);
|
||||
HH(c,d,a,b,m[3], 16,0xd4ef3085);
|
||||
HH(b,c,d,a,m[6], 23,0x04881d05);
|
||||
HH(a,b,c,d,m[9], 4,0xd9d4d039);
|
||||
HH(d,a,b,c,m[12],11,0xe6db99e5);
|
||||
HH(c,d,a,b,m[15],16,0x1fa27cf8);
|
||||
HH(b,c,d,a,m[2], 23,0xc4ac5665);
|
||||
|
||||
II(a,b,c,d,m[0], 6,0xf4292244);
|
||||
II(d,a,b,c,m[7], 10,0x432aff97);
|
||||
II(c,d,a,b,m[14],15,0xab9423a7);
|
||||
II(b,c,d,a,m[5], 21,0xfc93a039);
|
||||
II(a,b,c,d,m[12], 6,0x655b59c3);
|
||||
II(d,a,b,c,m[3], 10,0x8f0ccc92);
|
||||
II(c,d,a,b,m[10],15,0xffeff47d);
|
||||
II(b,c,d,a,m[1], 21,0x85845dd1);
|
||||
II(a,b,c,d,m[8], 6,0x6fa87e4f);
|
||||
II(d,a,b,c,m[15],10,0xfe2ce6e0);
|
||||
II(c,d,a,b,m[6], 15,0xa3014314);
|
||||
II(b,c,d,a,m[13],21,0x4e0811a1);
|
||||
II(a,b,c,d,m[4], 6,0xf7537e82);
|
||||
II(d,a,b,c,m[11],10,0xbd3af235);
|
||||
II(c,d,a,b,m[2], 15,0x2ad7d2bb);
|
||||
II(b,c,d,a,m[9], 21,0xeb86d391);
|
||||
|
||||
ctx->state[0] += a;
|
||||
ctx->state[1] += b;
|
||||
ctx->state[2] += c;
|
||||
ctx->state[3] += d;
|
||||
}
|
||||
|
||||
void MD5_HASH::md5_init(MD5_CTX *ctx)
|
||||
{
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen[0] = 0;
|
||||
ctx->bitlen[1] = 0;
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void MD5_HASH::md5_update(MD5_CTX *ctx, uint8_t data[], uint32_t len)
|
||||
{
|
||||
uint32_t t,i;
|
||||
|
||||
for (i=0; i < len; ++i) {
|
||||
ctx->data[ctx->datalen] = data[i];
|
||||
ctx->datalen++;
|
||||
if (ctx->datalen == 64) {
|
||||
md5_transform(ctx,ctx->data);
|
||||
DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512);
|
||||
ctx->datalen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MD5_HASH::md5_final(MD5_CTX *ctx, uint8_t hash[])
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
i = ctx->datalen;
|
||||
|
||||
// Pad whatever data is left in the buffer.
|
||||
if (ctx->datalen < 56) {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 56)
|
||||
ctx->data[i++] = 0x00;
|
||||
}
|
||||
else if (ctx->datalen >= 56) {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 64)
|
||||
ctx->data[i++] = 0x00;
|
||||
md5_transform(ctx,ctx->data);
|
||||
memset(ctx->data,0,56);
|
||||
}
|
||||
|
||||
// Append to the padding the total message's length in bits and transform.
|
||||
DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],8 * ctx->datalen);
|
||||
ctx->data[56] = ctx->bitlen[0];
|
||||
ctx->data[57] = ctx->bitlen[0] >> 8;
|
||||
ctx->data[58] = ctx->bitlen[0] >> 16;
|
||||
ctx->data[59] = ctx->bitlen[0] >> 24;
|
||||
ctx->data[60] = ctx->bitlen[1];
|
||||
ctx->data[61] = ctx->bitlen[1] >> 8;
|
||||
ctx->data[62] = ctx->bitlen[1] >> 16;
|
||||
ctx->data[63] = ctx->bitlen[1] >> 24;
|
||||
md5_transform(ctx,ctx->data);
|
||||
|
||||
// Since this implementation uses little endian byte ordering and MD uses big endian,
|
||||
// reverse all the bytes when copying the final state to the output hash.
|
||||
for (i=0; i < 4; ++i) {
|
||||
hash[i] = (ctx->state[0] >> (i*8)) & 0x000000ff;
|
||||
hash[i+4] = (ctx->state[1] >> (i*8)) & 0x000000ff;
|
||||
hash[i+8] = (ctx->state[2] >> (i*8)) & 0x000000ff;
|
||||
hash[i+12] = (ctx->state[3] >> (i*8)) & 0x000000ff;
|
||||
}
|
||||
}
|
102
common/widgets/progress_reporter.cpp
Normal file
102
common/widgets/progress_reporter.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <widgets/progress_reporter.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
PROGRESS_REPORTER::PROGRESS_REPORTER( int aNumPhases ) :
|
||||
m_phase( 0 ),
|
||||
m_progress( 0 ),
|
||||
m_maxProgress( 1 ),
|
||||
m_numPhases( aNumPhases )
|
||||
{
|
||||
};
|
||||
|
||||
void PROGRESS_REPORTER::BeginPhase( int aPhase )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_lock );
|
||||
m_phase = aPhase;
|
||||
m_progress = 0;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
void PROGRESS_REPORTER::AdvancePhase( )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_lock );
|
||||
m_phase++;
|
||||
m_progress = 0;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
void PROGRESS_REPORTER::Report( const wxString& aMessage )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_lock );
|
||||
m_message = aMessage;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
void PROGRESS_REPORTER::SetMaxProgress ( int aMaxProgress )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_lock );
|
||||
m_maxProgress = aMaxProgress;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
void PROGRESS_REPORTER::AdvanceProgress( )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_lock );
|
||||
m_progress++;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
int PROGRESS_REPORTER::currentProgress() const
|
||||
{
|
||||
double current = (1.0 / (double)m_numPhases) * ( (double) m_phase + ( (double) m_progress / (double) m_maxProgress ) );
|
||||
|
||||
return (int)(current * 1000);
|
||||
}
|
||||
|
||||
WX_PROGRESS_REPORTER::WX_PROGRESS_REPORTER( wxWindow* aParent,
|
||||
const wxString& aTitle,
|
||||
int aNumPhases ) :
|
||||
PROGRESS_REPORTER( aNumPhases ),
|
||||
wxProgressDialog( aTitle, wxT( "" ), 1, aParent, wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
|
||||
wxPD_APP_MODAL | wxPD_ELAPSED_TIME )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WX_PROGRESS_REPORTER::~WX_PROGRESS_REPORTER()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
void WX_PROGRESS_REPORTER::updateUI()
|
||||
{
|
||||
int cur = currentProgress();
|
||||
SetRange( 1000 );
|
||||
Update( cur, m_message );
|
||||
}
|
@ -387,6 +387,12 @@ private:
|
||||
*/
|
||||
void drawPolygon( GLdouble* aPoints, int aPointCount );
|
||||
|
||||
/**
|
||||
* @brief Draws a set of polygons with a cached triangulation. Way faster than drawPolygon.
|
||||
*/
|
||||
void drawTriangulatedPolyset( const SHAPE_POLY_SET& aPoly );
|
||||
|
||||
|
||||
/**
|
||||
* @brief Draws a single character using bitmap font.
|
||||
* Its main purpose is to be used in BitmapText() function.
|
||||
|
@ -102,6 +102,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==( const SEG& aSeg ) const
|
||||
{
|
||||
return (A == aSeg.A && B == aSeg.B) ;
|
||||
}
|
||||
|
||||
bool operator!=( const SEG& aSeg ) const
|
||||
{
|
||||
return (A != aSeg.A || B != aSeg.B);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function LineProject()
|
||||
*
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
#include "clipper.hpp"
|
||||
|
||||
#include <md5_hash.h>
|
||||
|
||||
|
||||
/**
|
||||
* Class SHAPE_POLY_SET
|
||||
@ -57,6 +59,42 @@ class SHAPE_POLY_SET : public SHAPE
|
||||
///> the remaining (if any), are the holes
|
||||
typedef std::vector<SHAPE_LINE_CHAIN> POLYGON;
|
||||
|
||||
struct TRIANGULATED_POLYGON
|
||||
{
|
||||
~TRIANGULATED_POLYGON();
|
||||
|
||||
struct TRI
|
||||
{
|
||||
TRI(){};
|
||||
|
||||
int a, b, c;
|
||||
};
|
||||
|
||||
void Clear();
|
||||
|
||||
void AllocateVertices( int aSize );
|
||||
void AllocateTriangles ( int aSize );
|
||||
|
||||
void GetTriangle( int index, VECTOR2I& a, VECTOR2I& b, VECTOR2I& c ) const
|
||||
{
|
||||
auto tri = &m_triangles[ index ];
|
||||
a = m_vertices[ tri->a ];
|
||||
b = m_vertices[ tri->b ];
|
||||
c = m_vertices[ tri->c ];
|
||||
}
|
||||
|
||||
int AddVertex( const VECTOR2I& aP )
|
||||
{
|
||||
m_vertices[ m_vertexCount ] = aP;
|
||||
return (m_vertexCount++);
|
||||
}
|
||||
|
||||
TRI* m_triangles = nullptr;
|
||||
VECTOR2I* m_vertices = nullptr;
|
||||
int m_vertexCount = 0;
|
||||
int m_triangleCount = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct VERTEX_INDEX
|
||||
*
|
||||
@ -538,6 +576,17 @@ class SHAPE_POLY_SET : public SHAPE
|
||||
return m_polys[aIndex];
|
||||
}
|
||||
|
||||
const POLYGON& Polygon( int aIndex ) const
|
||||
{
|
||||
return m_polys[aIndex];
|
||||
}
|
||||
|
||||
const TRIANGULATED_POLYGON* TriangulatedPolygon( int aIndex ) const
|
||||
{
|
||||
return m_triangulatedPolys[aIndex];
|
||||
}
|
||||
|
||||
|
||||
const SHAPE_LINE_CHAIN& COutline( int aIndex ) const
|
||||
{
|
||||
return m_polys[aIndex][0];
|
||||
@ -761,6 +810,8 @@ class SHAPE_POLY_SET : public SHAPE
|
||||
///> For aFastMode meaning, see function booleanOp
|
||||
void Fracture( POLYGON_MODE aFastMode );
|
||||
|
||||
void Unfracture( POLYGON_MODE aFastMode );
|
||||
|
||||
///> Returns true if the polygon set has any holes.
|
||||
bool HasHoles() const;
|
||||
|
||||
@ -990,6 +1041,7 @@ class SHAPE_POLY_SET : public SHAPE
|
||||
|
||||
|
||||
void fractureSingle( POLYGON& paths );
|
||||
void unfractureSingle ( POLYGON& path );
|
||||
void importTree( ClipperLib::PolyTree* tree );
|
||||
|
||||
/** Function booleanOp
|
||||
@ -1039,6 +1091,8 @@ class SHAPE_POLY_SET : public SHAPE
|
||||
FILLETED
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function chamferFilletPolygon
|
||||
* Returns the camfered or filleted version of the aIndex-th polygon in the set, depending
|
||||
@ -1059,6 +1113,21 @@ class SHAPE_POLY_SET : public SHAPE
|
||||
typedef std::vector<POLYGON> POLYSET;
|
||||
|
||||
POLYSET m_polys;
|
||||
|
||||
public:
|
||||
|
||||
void CacheTriangulation();
|
||||
bool IsTriangulationUpToDate() const;
|
||||
|
||||
private:
|
||||
void triangulateSingle( const POLYGON& aPoly, SHAPE_POLY_SET::TRIANGULATED_POLYGON& aResult );
|
||||
|
||||
MD5_HASH checksum() const;
|
||||
|
||||
std::vector<TRIANGULATED_POLYGON*> m_triangulatedPolys;
|
||||
bool m_triangulationValid = false;
|
||||
MD5_HASH m_hash;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
50
include/md5_hash.h
Normal file
50
include/md5_hash.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Code by: B-Con (http://b-con.us)
|
||||
// Released under the GNU GPL
|
||||
// MD5 Hash Digest implementation (little endian byte order)
|
||||
|
||||
#ifndef __MD5_HASH_H
|
||||
#define __MD5_HASH_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class MD5_HASH
|
||||
{
|
||||
|
||||
public:
|
||||
MD5_HASH();
|
||||
MD5_HASH( const MD5_HASH& aOther );
|
||||
|
||||
~MD5_HASH();
|
||||
|
||||
void Init();
|
||||
void Hash ( uint8_t *data, uint32_t length );
|
||||
void Hash ( int value );
|
||||
void Finalize();
|
||||
bool IsValid() const { return m_valid; };
|
||||
|
||||
void SetValid( bool aValid ) { m_valid = aValid; }
|
||||
|
||||
MD5_HASH& operator=( const MD5_HASH& aOther );
|
||||
|
||||
bool operator==( const MD5_HASH& aOther ) const;
|
||||
bool operator!=( const MD5_HASH& aOther ) const;
|
||||
|
||||
private:
|
||||
struct MD5_CTX {
|
||||
uint8_t data[64];
|
||||
uint32_t datalen;
|
||||
uint32_t bitlen[2];
|
||||
uint32_t state[4];
|
||||
};
|
||||
|
||||
void md5_transform(MD5_CTX *ctx, uint8_t data[]);
|
||||
void md5_init(MD5_CTX *ctx);
|
||||
void md5_update(MD5_CTX *ctx, uint8_t data[], uint32_t len);
|
||||
void md5_final(MD5_CTX *ctx, uint8_t hash[]);
|
||||
|
||||
bool m_valid;
|
||||
MD5_CTX m_ctx;
|
||||
uint8_t m_hash[16];
|
||||
};
|
||||
|
||||
#endif
|
69
include/widgets/progress_reporter.h
Normal file
69
include/widgets/progress_reporter.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __PROGRESS_REPORTER
|
||||
#define __PROGRESS_REPORTER
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <wx/progdlg.h>
|
||||
|
||||
class PROGRESS_REPORTER
|
||||
{
|
||||
public:
|
||||
|
||||
PROGRESS_REPORTER( int aNumPhases );
|
||||
PROGRESS_REPORTER( const PROGRESS_REPORTER& ) = delete;
|
||||
|
||||
void BeginPhase( int aPhase );
|
||||
void AdvancePhase( );
|
||||
void Report ( const wxString& aMessage );
|
||||
void SetMaxProgress ( int aMaxProgress );
|
||||
void AdvanceProgress( );
|
||||
|
||||
protected:
|
||||
|
||||
int currentProgress() const;
|
||||
virtual void updateUI() = 0;
|
||||
|
||||
wxString m_message;
|
||||
int m_phase, m_numPhases;
|
||||
int m_progress, m_maxProgress;
|
||||
|
||||
std::mutex m_lock;
|
||||
};
|
||||
|
||||
class WX_PROGRESS_REPORTER : public PROGRESS_REPORTER, public wxProgressDialog
|
||||
{
|
||||
public:
|
||||
|
||||
WX_PROGRESS_REPORTER( wxWindow *aParent, const wxString &aTitle, int aNumPhases );
|
||||
~WX_PROGRESS_REPORTER();
|
||||
|
||||
private:
|
||||
|
||||
virtual void updateUI() override;
|
||||
};
|
||||
|
||||
#endif
|
@ -315,6 +315,7 @@ set( PCBNEW_CLASS_SRCS
|
||||
tools/tool_event_utils.cpp
|
||||
tools/size_menu.cpp
|
||||
tools/selection.cpp
|
||||
tools/zone_filler_tool.cpp
|
||||
|
||||
footprint_preview_panel.cpp
|
||||
)
|
||||
|
@ -1312,3 +1312,8 @@ void ZONE_CONTAINER::SwapData( BOARD_ITEM* aImage )
|
||||
|
||||
std::swap( *((ZONE_CONTAINER*) this), *((ZONE_CONTAINER*) aImage) );
|
||||
}
|
||||
|
||||
void ZONE_CONTAINER::CacheTriangulation()
|
||||
{
|
||||
m_FilledPolysList.CacheTriangulation();
|
||||
}
|
||||
|
@ -170,11 +170,11 @@ public:
|
||||
int GetClearance( BOARD_CONNECTED_ITEM* aItem = NULL ) const override;
|
||||
|
||||
/**
|
||||
* Function TestForCopperIslandAndRemoveInsulatedIslands
|
||||
* Function RemoveInsulatedCopperIslands
|
||||
* Remove insulated copper islands found in m_FilledPolysList.
|
||||
* @param aPcb = the board to analyze
|
||||
*/
|
||||
void TestForCopperIslandAndRemoveInsulatedIslands( BOARD* aPcb );
|
||||
void RemoveInsulatedCopperIslands( BOARD* aPcb );
|
||||
|
||||
/**
|
||||
* Function IsOnCopperLayer
|
||||
@ -329,7 +329,7 @@ public:
|
||||
bool BuildFilledSolidAreasPolygons( BOARD* aPcb, SHAPE_POLY_SET* aOutlineBuffer = NULL );
|
||||
|
||||
/**
|
||||
* Function AddClearanceAreasPolygonsToPolysList
|
||||
* Function ComputeRawFilledAreas
|
||||
* Add non copper areas polygons (pads and tracks with clearance)
|
||||
* to a filled copper area
|
||||
* used in BuildFilledSolidAreasPolygons when calculating filled areas in a zone
|
||||
@ -340,8 +340,7 @@ public:
|
||||
* @param aPcb: the current board
|
||||
* _NG version uses SHAPE_POLY_SET instead of Boost.Polygon
|
||||
*/
|
||||
void AddClearanceAreasPolygonsToPolysList( BOARD* aPcb );
|
||||
void AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb );
|
||||
void ComputeRawFilledAreas( BOARD* aPcb );
|
||||
|
||||
|
||||
/**
|
||||
@ -602,6 +601,8 @@ public:
|
||||
return m_FilledPolysList;
|
||||
}
|
||||
|
||||
void CacheTriangulation();
|
||||
|
||||
/**
|
||||
* Function AddFilledPolysList
|
||||
* sets the list of filled polygons.
|
||||
@ -728,7 +729,6 @@ public:
|
||||
|
||||
const std::vector<SEG>& GetHatchLines() const { return m_HatchLines; }
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
@ -810,6 +810,8 @@ private:
|
||||
int m_hatchPitch; // for DIAGONAL_EDGE, distance between 2 hatch lines
|
||||
std::vector<SEG> m_HatchLines; // hatch lines
|
||||
|
||||
std::vector<int> m_insulatedIslands;
|
||||
|
||||
/**
|
||||
* Union to handle conversion between references to wxPoint and to VECTOR2I.
|
||||
*
|
||||
|
@ -23,6 +23,10 @@
|
||||
*/
|
||||
|
||||
#include <connectivity_algo.h>
|
||||
#include <widgets/progress_reporter.h>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#ifdef PROFILE
|
||||
#include <profile.h>
|
||||
@ -289,9 +293,11 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
{
|
||||
std::mutex cnListLock;
|
||||
|
||||
//PROF_COUNTER cnt("search");
|
||||
int totalDirtyCount = 0;
|
||||
|
||||
if( m_lastSearchWithZones != aIncludeZones )
|
||||
@ -304,7 +310,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
|
||||
m_lastSearchWithZones = aIncludeZones;
|
||||
|
||||
auto checkForConnection = [] ( const CN_ANCHOR_PTR point, CN_ITEM* aRefItem, int aMaxDist = 0 )
|
||||
auto checkForConnection = [ &cnListLock ] ( const CN_ANCHOR_PTR point, CN_ITEM* aRefItem, int aMaxDist = 0 )
|
||||
{
|
||||
const auto parent = aRefItem->Parent();
|
||||
|
||||
@ -331,7 +337,10 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
case PCB_VIA_T:
|
||||
|
||||
if( parent->HitTest( wxPoint( point->Pos().x, point->Pos().y ) ) )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( cnListLock );
|
||||
CN_ITEM::Connect( aRefItem, point->Item() );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -344,7 +353,10 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
|
||||
if( d_start.EuclideanNorm() < aMaxDist
|
||||
|| d_end.EuclideanNorm() < aMaxDist )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( cnListLock );
|
||||
CN_ITEM::Connect( aRefItem, point->Item() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -363,6 +375,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
|
||||
if( zoneItem->ContainsAnchor( point ) )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( cnListLock );
|
||||
CN_ITEM::Connect( zoneItem, point->Item() );
|
||||
}
|
||||
|
||||
@ -374,7 +387,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
}
|
||||
};
|
||||
|
||||
auto checkInterZoneConnection = [] ( CN_ZONE* testedZone, CN_ZONE* aRefZone )
|
||||
auto checkInterZoneConnection = [ &cnListLock ] ( CN_ZONE* testedZone, CN_ZONE* aRefZone )
|
||||
{
|
||||
const auto parentZone = static_cast<const ZONE_CONTAINER*>( aRefZone->Parent() );
|
||||
|
||||
@ -399,6 +412,8 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
{
|
||||
if( testedZone->ContainsPoint( outline.CPoint( i ) ) )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( cnListLock );
|
||||
|
||||
CN_ITEM::Connect( aRefZone, testedZone );
|
||||
return;
|
||||
}
|
||||
@ -412,6 +427,8 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
{
|
||||
if( aRefZone->ContainsPoint( outline2.CPoint( i ) ) )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( cnListLock );
|
||||
|
||||
CN_ITEM::Connect( aRefZone, testedZone );
|
||||
return;
|
||||
}
|
||||
@ -496,8 +513,19 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
|
||||
if( aIncludeZones )
|
||||
{
|
||||
for( auto& item : m_zoneList )
|
||||
int cnt = 0;
|
||||
|
||||
if( m_progressReporter )
|
||||
{
|
||||
m_progressReporter->SetMaxProgress( m_zoneList.Size() );
|
||||
}
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel for schedule(dynamic)
|
||||
#endif
|
||||
for(int i = 0; i < m_zoneList.Size(); i++ )
|
||||
{
|
||||
auto item = m_zoneList[i];
|
||||
auto zoneItem = static_cast<CN_ZONE *> (item);
|
||||
auto searchZones = std::bind( checkForConnection, _1, zoneItem );
|
||||
|
||||
@ -509,6 +537,16 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
||||
m_padList.FindNearby( zoneItem->BBox(), searchZones );
|
||||
m_zoneList.FindNearbyZones( zoneItem->BBox(), std::bind( checkInterZoneConnection, _1, zoneItem ) );
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( cnListLock );
|
||||
cnt++;
|
||||
|
||||
if (m_progressReporter)
|
||||
{
|
||||
m_progressReporter->AdvanceProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_zoneList.ClearDirtyFlags();
|
||||
@ -589,6 +627,7 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST
|
||||
CN_ITEM* head = nullptr;
|
||||
CLUSTERS clusters;
|
||||
|
||||
|
||||
if( isDirty() )
|
||||
searchConnections( includeZones );
|
||||
|
||||
@ -798,7 +837,6 @@ void CN_CONNECTIVITY_ALGO::PropagateNets()
|
||||
propagateConnections();
|
||||
}
|
||||
|
||||
|
||||
void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands )
|
||||
{
|
||||
if( aZone->GetFilledPolysList().IsEmpty() )
|
||||
@ -828,6 +866,40 @@ void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std
|
||||
wxLogTrace( "CN", "Found %u isolated islands\n", (unsigned)aIslands.size() );
|
||||
}
|
||||
|
||||
void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
|
||||
{
|
||||
for ( auto& z : aZones )
|
||||
{
|
||||
if( z.m_zone->GetFilledPolysList().IsEmpty() )
|
||||
continue;
|
||||
|
||||
Remove( z.m_zone );
|
||||
Add( z.m_zone );
|
||||
}
|
||||
|
||||
m_connClusters = SearchClusters( CSM_CONNECTIVITY_CHECK );
|
||||
|
||||
for ( auto& zone : aZones )
|
||||
{
|
||||
if( zone.m_zone->GetFilledPolysList().IsEmpty() )
|
||||
continue;
|
||||
|
||||
for( auto cluster : m_connClusters )
|
||||
{
|
||||
if( cluster->Contains( zone.m_zone ) && cluster->IsOrphaned() )
|
||||
{
|
||||
for( auto z : *cluster )
|
||||
{
|
||||
if( z->Parent() == zone.m_zone )
|
||||
{
|
||||
zone.m_islands.push_back( static_cast<CN_ZONE*>(z)->SubpolyIndex() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const CN_CONNECTIVITY_ALGO::CLUSTERS& CN_CONNECTIVITY_ALGO::GetClusters()
|
||||
{
|
||||
@ -995,3 +1067,8 @@ bool CN_ANCHOR::IsDangling() const
|
||||
|
||||
return validCount <= 1;
|
||||
}
|
||||
|
||||
void CN_CONNECTIVITY_ALGO::SetProgressReporter( PROGRESS_REPORTER* aReporter )
|
||||
{
|
||||
m_progressReporter = aReporter;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ class BOARD;
|
||||
class BOARD_CONNECTED_ITEM;
|
||||
class BOARD_ITEM;
|
||||
class ZONE_CONTAINER;
|
||||
class PROGRESS_REPORTER;
|
||||
|
||||
class CN_ANCHOR
|
||||
{
|
||||
@ -439,6 +440,8 @@ public:
|
||||
ITER begin() { return m_items.begin(); };
|
||||
ITER end() { return m_items.end(); };
|
||||
|
||||
CN_ITEM* operator[] ( int aIndex ) { return m_items[aIndex]; }
|
||||
|
||||
std::vector<CN_ANCHOR_PTR>& Anchors() { return m_anchors; }
|
||||
|
||||
template <class T>
|
||||
@ -806,6 +809,7 @@ public:
|
||||
CLUSTERS m_connClusters;
|
||||
CLUSTERS m_ratsnestClusters;
|
||||
std::vector<bool> m_dirtyNets;
|
||||
PROGRESS_REPORTER* m_progressReporter = nullptr;
|
||||
|
||||
void searchConnections( bool aIncludeZones = false );
|
||||
|
||||
@ -883,6 +887,8 @@ public:
|
||||
|
||||
void PropagateNets();
|
||||
void FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands );
|
||||
void FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones );
|
||||
|
||||
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
|
||||
|
||||
const CLUSTERS& GetClusters();
|
||||
@ -894,6 +900,7 @@ public:
|
||||
void ForEachItem( std::function<void(CN_ITEM*)> aFunc );
|
||||
|
||||
void MarkNetAsDirty( int aNet );
|
||||
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
|
||||
|
||||
};
|
||||
|
||||
|
@ -218,6 +218,10 @@ void CONNECTIVITY_DATA::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone,
|
||||
m_connAlgo->FindIsolatedCopperIslands( aZone, aIslands );
|
||||
}
|
||||
|
||||
void CONNECTIVITY_DATA::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
|
||||
{
|
||||
m_connAlgo->FindIsolatedCopperIslands( aZones );
|
||||
}
|
||||
|
||||
void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>& aItems )
|
||||
{
|
||||
@ -617,3 +621,9 @@ void CONNECTIVITY_DATA::MarkItemNetAsDirty( BOARD_ITEM *aItem )
|
||||
m_connAlgo->MarkNetAsDirty( static_cast<BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode() );
|
||||
}
|
||||
}
|
||||
|
||||
void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter )
|
||||
{
|
||||
m_progressReporter = aReporter;
|
||||
m_connAlgo->SetProgressReporter( m_progressReporter );
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ class RN_DATA;
|
||||
class RN_NET;
|
||||
class TRACK;
|
||||
class D_PAD;
|
||||
class PROGRESS_REPORTER;
|
||||
|
||||
struct CN_DISJOINT_NET_ENTRY
|
||||
{
|
||||
@ -53,6 +54,12 @@ struct CN_DISJOINT_NET_ENTRY
|
||||
VECTOR2I anchorA, anchorB;
|
||||
};
|
||||
|
||||
struct CN_ZONE_ISOLATED_ISLAND_LIST
|
||||
{
|
||||
ZONE_CONTAINER *m_zone;
|
||||
std::vector<int> m_islands;
|
||||
};
|
||||
|
||||
struct RN_DYNAMIC_LINE
|
||||
{
|
||||
int netCode;
|
||||
@ -136,6 +143,7 @@ public:
|
||||
* @param aIslands list of islands that have no connections (outline indices in the polygon set)
|
||||
*/
|
||||
void FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands );
|
||||
void FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones );
|
||||
|
||||
/**
|
||||
* Function RecalculateRatsnest()
|
||||
@ -216,6 +224,8 @@ public:
|
||||
|
||||
void MarkItemNetAsDirty( BOARD_ITEM* aItem );
|
||||
|
||||
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
|
||||
|
||||
private:
|
||||
|
||||
void updateRatsnest();
|
||||
@ -226,6 +236,8 @@ private:
|
||||
|
||||
std::vector<RN_DYNAMIC_LINE> m_dynamicRatsnest;
|
||||
std::vector<RN_NET*> m_nets;
|
||||
|
||||
PROGRESS_REPORTER* m_progressReporter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -136,13 +136,16 @@ PCB_DRAW_PANEL_GAL::~PCB_DRAW_PANEL_GAL()
|
||||
}
|
||||
|
||||
|
||||
void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard )
|
||||
void PCB_DRAW_PANEL_GAL::DisplayBoard( BOARD* aBoard )
|
||||
{
|
||||
m_view->Clear();
|
||||
|
||||
// Load zones
|
||||
for( int i = 0; i < aBoard->GetAreaCount(); ++i )
|
||||
m_view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) );
|
||||
for( auto zone : aBoard->Zones() )
|
||||
{
|
||||
zone->CacheTriangulation();
|
||||
m_view->Add( zone );
|
||||
}
|
||||
|
||||
// Load drawings
|
||||
for( auto drawing : const_cast<BOARD*>(aBoard)->Drawings() )
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
* adds all items from the current board to the VIEW, so they can be displayed by GAL.
|
||||
* @param aBoard is the PCB to be loaded.
|
||||
*/
|
||||
void DisplayBoard( const BOARD* aBoard );
|
||||
void DisplayBoard( BOARD* aBoard );
|
||||
|
||||
/**
|
||||
* Function SetWorksheet
|
||||
@ -106,7 +106,7 @@ public:
|
||||
protected:
|
||||
|
||||
KIGFX::PCB_VIEW* view() const;
|
||||
|
||||
|
||||
///> Reassigns layer order to the initial settings.
|
||||
void setDefaultLayerOrder();
|
||||
|
||||
|
@ -1143,6 +1143,9 @@ void PCB_PAINTER::draw( const ZONE_CONTAINER* aZone, int aLayer )
|
||||
m_gal->SetIsStroke( true );
|
||||
}
|
||||
|
||||
m_gal->DrawPolygon( polySet );
|
||||
|
||||
#if 0
|
||||
for( int i = 0; i < polySet.OutlineCount(); i++ )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& outline = polySet.COutline( i );
|
||||
@ -1164,9 +1167,12 @@ void PCB_PAINTER::draw( const ZONE_CONTAINER* aZone, int aLayer )
|
||||
m_gal->DrawPolyline( corners );
|
||||
}
|
||||
|
||||
|
||||
corners.clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <cstdint>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include "pcb_editor_control.h"
|
||||
#include "pcb_actions.h"
|
||||
@ -55,6 +57,12 @@
|
||||
#include <origin_viewitem.h>
|
||||
#include <profile.h>
|
||||
|
||||
#include <widgets/progress_reporter.h>
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif /* USE_OPENMP */
|
||||
|
||||
#include <tools/tool_event_utils.h>
|
||||
|
||||
#include <functional>
|
||||
@ -82,24 +90,6 @@ TOOL_ACTION PCB_ACTIONS::trackViaSizeChanged( "pcbnew.EditorControl.trackViaSize
|
||||
AS_GLOBAL, 0,
|
||||
"", "", NULL, AF_NOTIFY );
|
||||
|
||||
|
||||
// Zone actions
|
||||
TOOL_ACTION PCB_ACTIONS::zoneFill( "pcbnew.EditorControl.zoneFill",
|
||||
AS_GLOBAL, 0,
|
||||
_( "Fill" ), _( "Fill zone(s)" ), fill_zone_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneFillAll( "pcbnew.EditorControl.zoneFillAll",
|
||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_FILL_OR_REFILL ),
|
||||
_( "Fill All" ), _( "Fill all zones" ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneUnfill( "pcbnew.EditorControl.zoneUnfill",
|
||||
AS_GLOBAL, 0,
|
||||
_( "Unfill" ), _( "Unfill zone(s)" ), zone_unfill_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneUnfillAll( "pcbnew.EditorControl.zoneUnfillAll",
|
||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_REMOVE_FILLED ),
|
||||
_( "Unfill All" ), _( "Unfill all zones" ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneMerge( "pcbnew.EditorControl.zoneMerge",
|
||||
AS_GLOBAL, 0,
|
||||
_( "Merge Zones" ), _( "Merge zones" ) );
|
||||
@ -175,6 +165,7 @@ public:
|
||||
Add( PCB_ACTIONS::drawSimilarZone );
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
CONTEXT_MENU* create() const override
|
||||
{
|
||||
@ -655,139 +646,6 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Zone actions
|
||||
int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( auto item : selection )
|
||||
{
|
||||
assert( item->Type() == PCB_ZONE_AREA_T );
|
||||
|
||||
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*> ( item );
|
||||
|
||||
commit.Modify( zone );
|
||||
|
||||
m_frame->Fill_Zone( zone );
|
||||
zone->SetIsFilled( true );
|
||||
}
|
||||
|
||||
commit.Push( _( "Fill Zone" ) );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
int areaCount = board->GetAreaCount();
|
||||
const wxString fmt = _( "Filling zone %d out of %d (net %s)..." );
|
||||
wxString msg;
|
||||
bool aborted = false;
|
||||
|
||||
// Create a message with a long net name, and build a wxProgressDialog
|
||||
// with a correct size to show this long net name
|
||||
msg.Printf( fmt, 000, areaCount, wxT("XXXXXXXXXXXXXXXXX" ) );
|
||||
|
||||
auto progressDialog = new wxProgressDialog( _( "Fill All Zones" ), msg,
|
||||
areaCount, frame(),
|
||||
wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
|
||||
wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( int i = 0; i < areaCount; ++i )
|
||||
{
|
||||
ZONE_CONTAINER* zone = board->GetArea( i );
|
||||
|
||||
msg.Printf( fmt, i, areaCount, GetChars( zone->GetNetname() ) );
|
||||
|
||||
commit.Modify( zone );
|
||||
|
||||
if( !progressDialog->Update( i, msg ) )
|
||||
{
|
||||
aborted = true;
|
||||
break; // Aborted by user
|
||||
}
|
||||
|
||||
m_frame->Fill_Zone( zone );
|
||||
zone->SetIsFilled( true );
|
||||
}
|
||||
|
||||
if( aborted )
|
||||
commit.Revert();
|
||||
else
|
||||
commit.Push( _( "Fill All Zones" ) );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
progressDialog->Destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( auto item : selection )
|
||||
{
|
||||
assert( item->Type() == PCB_ZONE_AREA_T );
|
||||
|
||||
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
|
||||
|
||||
commit.Modify( zone );
|
||||
|
||||
zone->SetIsFilled( false );
|
||||
zone->ClearFilledPolysList();
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill Zone" ) );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( int i = 0; i < board->GetAreaCount(); ++i )
|
||||
{
|
||||
ZONE_CONTAINER* zone = board->GetArea( i );
|
||||
|
||||
commit.Modify( zone );
|
||||
|
||||
zone->SetIsFilled( false );
|
||||
zone->ClearFilledPolysList();
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill All Zones" ) );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool mergeZones( BOARD_COMMIT& aCommit, std::vector<ZONE_CONTAINER *>& aOriginZones,
|
||||
std::vector<ZONE_CONTAINER *>& aMergedZones )
|
||||
{
|
||||
@ -819,6 +677,7 @@ static bool mergeZones( BOARD_COMMIT& aCommit, std::vector<ZONE_CONTAINER *>& aO
|
||||
|
||||
aOriginZones[0]->SetLocalFlags( 1 );
|
||||
aOriginZones[0]->Hatch();
|
||||
aOriginZones[0]->CacheTriangulation();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1250,10 +1109,6 @@ void PCB_EDITOR_CONTROL::setTransitions()
|
||||
Go( &PCB_EDITOR_CONTROL::ViaSizeDec, PCB_ACTIONS::viaSizeDec.MakeEvent() );
|
||||
|
||||
// Zone actions
|
||||
Go( &PCB_EDITOR_CONTROL::ZoneFill, PCB_ACTIONS::zoneFill.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::ZoneFillAll, PCB_ACTIONS::zoneFillAll.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::ZoneUnfill, PCB_ACTIONS::zoneUnfill.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::ZoneUnfillAll, PCB_ACTIONS::zoneUnfillAll.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::ZoneMerge, PCB_ACTIONS::zoneMerge.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::ZoneDuplicate, PCB_ACTIONS::zoneDuplicate.MakeEvent() );
|
||||
|
||||
|
@ -57,10 +57,6 @@ public:
|
||||
int ViaSizeDec( const TOOL_EVENT& aEvent );
|
||||
|
||||
// Zone actions
|
||||
int ZoneFill( const TOOL_EVENT& aEvent );
|
||||
int ZoneFillAll( const TOOL_EVENT& aEvent );
|
||||
int ZoneUnfill( const TOOL_EVENT& aEvent );
|
||||
int ZoneUnfillAll( const TOOL_EVENT& aEvent );
|
||||
int ZoneMerge( const TOOL_EVENT& aEvent );
|
||||
|
||||
///> Duplicates a zone onto a layer (prompts for new layer)
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <tools/pad_tool.h>
|
||||
#include <tools/microwave_tool.h>
|
||||
#include <tools/position_relative_tool.h>
|
||||
#include <tools/zone_filler_tool.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
|
||||
#include <router/router_tool.h>
|
||||
@ -62,4 +63,5 @@ void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
|
||||
aToolManager->RegisterTool( new ALIGN_DISTRIBUTE_TOOL );
|
||||
aToolManager->RegisterTool( new MICROWAVE_TOOL );
|
||||
aToolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
|
||||
aToolManager->RegisterTool( new ZONE_FILLER_TOOL );
|
||||
}
|
||||
|
327
pcbnew/tools/zone_filler_tool.cpp
Normal file
327
pcbnew/tools/zone_filler_tool.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2017 CERN
|
||||
* Copyright (C) 2014-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#include <cstdint>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <painter.h>
|
||||
#include <project.h>
|
||||
#include <pcbnew_id.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <class_board.h>
|
||||
#include <class_zone.h>
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
#include <class_module.h>
|
||||
#include <connectivity_data.h>
|
||||
#include <board_commit.h>
|
||||
|
||||
#include <widgets/progress_reporter.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <bitmaps.h>
|
||||
#include <hotkeys.h>
|
||||
|
||||
#include "pcb_actions.h"
|
||||
#include "selection_tool.h"
|
||||
#include "zone_filler_tool.h"
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif /* USE_OPENMP */
|
||||
|
||||
// Zone actions
|
||||
TOOL_ACTION PCB_ACTIONS::zoneFill( "pcbnew.ZoneFiller.zoneFill",
|
||||
AS_GLOBAL, 0,
|
||||
_( "Fill" ), _( "Fill zone(s)" ), fill_zone_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneFillAll( "pcbnew.ZoneFiller.zoneFillAll",
|
||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_FILL_OR_REFILL ),
|
||||
_( "Fill All" ), _( "Fill all zones" ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneUnfill( "pcbnew.ZoneFiller.zoneUnfill",
|
||||
AS_GLOBAL, 0,
|
||||
_( "Unfill" ), _( "Unfill zone(s)" ), zone_unfill_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneUnfillAll( "pcbnew.ZoneFiller.zoneUnfillAll",
|
||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_REMOVE_FILLED ),
|
||||
_( "Unfill All" ), _( "Unfill all zones" ) );
|
||||
|
||||
|
||||
class ZONE_FILLER
|
||||
{
|
||||
public:
|
||||
ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit );
|
||||
~ZONE_FILLER();
|
||||
|
||||
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
|
||||
void Fill( std::vector<ZONE_CONTAINER*> aZones );
|
||||
void Unfill( std::vector<ZONE_CONTAINER*> aZones );
|
||||
|
||||
private:
|
||||
COMMIT* m_commit;
|
||||
PROGRESS_REPORTER* m_progressReporter;
|
||||
BOARD* m_board;
|
||||
};
|
||||
|
||||
ZONE_FILLER::ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit ) :
|
||||
m_commit( aCommit ),
|
||||
m_board( aBoard )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZONE_FILLER::~ZONE_FILLER()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZONE_FILLER::SetProgressReporter( PROGRESS_REPORTER* aReporter )
|
||||
{
|
||||
m_progressReporter = aReporter;
|
||||
}
|
||||
|
||||
|
||||
void ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones )
|
||||
{
|
||||
std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> toFill;
|
||||
|
||||
assert( m_commit );
|
||||
|
||||
// Remove segment zones
|
||||
m_board->m_Zone.DeleteAll();
|
||||
|
||||
int ii;
|
||||
|
||||
for( auto zone : aZones )
|
||||
{
|
||||
// Keepout zones are not filled
|
||||
if( zone->GetIsKeepout() )
|
||||
continue;
|
||||
|
||||
CN_ZONE_ISOLATED_ISLAND_LIST l;
|
||||
|
||||
l.m_zone = zone;
|
||||
|
||||
toFill.push_back( l );
|
||||
}
|
||||
|
||||
int zoneCount = m_board->GetAreaCount();
|
||||
|
||||
for( int i = 0; i < toFill.size(); i++ )
|
||||
{
|
||||
m_commit->Modify( toFill[i].m_zone );
|
||||
}
|
||||
|
||||
if( m_progressReporter )
|
||||
{
|
||||
m_progressReporter->Report( _( "Calculating zone fills..." ) );
|
||||
m_progressReporter->SetMaxProgress( toFill.size() );
|
||||
}
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel for schedule(dynamic)
|
||||
#endif
|
||||
for( int i = 0; i < toFill.size(); i++ )
|
||||
{
|
||||
toFill[i].m_zone->BuildFilledSolidAreasPolygons( m_board );
|
||||
|
||||
m_progressReporter->AdvanceProgress();
|
||||
}
|
||||
|
||||
if( m_progressReporter )
|
||||
{
|
||||
m_progressReporter->AdvancePhase();
|
||||
m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
|
||||
}
|
||||
|
||||
m_board->GetConnectivity()->SetProgressReporter( m_progressReporter );
|
||||
m_board->GetConnectivity()->FindIsolatedCopperIslands( toFill );
|
||||
|
||||
for( auto& zone : toFill )
|
||||
{
|
||||
std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
|
||||
SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
|
||||
|
||||
for( auto idx : zone.m_islands )
|
||||
{
|
||||
poly.DeletePolygon( idx );
|
||||
}
|
||||
|
||||
zone.m_zone->AddFilledPolysList( poly );
|
||||
}
|
||||
|
||||
if( m_progressReporter )
|
||||
{
|
||||
m_progressReporter->AdvancePhase();
|
||||
m_progressReporter->Report( _( "Caching polygon triangulations..." ) );
|
||||
m_progressReporter->SetMaxProgress( toFill.size() );
|
||||
}
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel for schedule(dynamic)
|
||||
#endif
|
||||
for( int i = 0; i < toFill.size(); i++ )
|
||||
{
|
||||
m_progressReporter->AdvanceProgress();
|
||||
toFill[i].m_zone->CacheTriangulation();
|
||||
}
|
||||
|
||||
m_progressReporter->AdvancePhase();
|
||||
m_progressReporter->Report( _( "Committing changes..." ) );
|
||||
|
||||
m_commit->Push( _( "Fill Zones" ), false );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ZONE_FILLER_TOOL::ZONE_FILLER_TOOL() :
|
||||
PCB_TOOL( "pcbnew.ZoneFiller" )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZONE_FILLER_TOOL::~ZONE_FILLER_TOOL()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZONE_FILLER_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
}
|
||||
|
||||
// Zone actions
|
||||
int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
std::vector<ZONE_CONTAINER*> toFill;
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( auto item : selection )
|
||||
{
|
||||
assert( item->Type() == PCB_ZONE_AREA_T );
|
||||
|
||||
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*> ( item );
|
||||
|
||||
toFill.push_back(zone);
|
||||
}
|
||||
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> progressReporter(
|
||||
new WX_PROGRESS_REPORTER( frame(), _( "Fill Zones" ), 3 )
|
||||
);
|
||||
|
||||
ZONE_FILLER filler( board(), &commit );
|
||||
filler.SetProgressReporter( progressReporter.get() );
|
||||
filler.Fill( toFill );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ZONE_FILLER_TOOL::ZoneFillAll( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
std::vector<ZONE_CONTAINER*> toFill;
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( auto zone : board()->Zones() )
|
||||
{
|
||||
toFill.push_back(zone);
|
||||
}
|
||||
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> progressReporter(
|
||||
new WX_PROGRESS_REPORTER( frame(), _( "Fill All Zones" ), 3 )
|
||||
);
|
||||
|
||||
ZONE_FILLER filler( board(), &commit );
|
||||
filler.SetProgressReporter( progressReporter.get() );
|
||||
filler.Fill( toFill );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ZONE_FILLER_TOOL::ZoneUnfill( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( auto item : selection )
|
||||
{
|
||||
assert( item->Type() == PCB_ZONE_AREA_T );
|
||||
|
||||
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
|
||||
|
||||
commit.Modify( zone );
|
||||
|
||||
zone->SetIsFilled( false );
|
||||
zone->ClearFilledPolysList();
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill Zone" ) );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ZONE_FILLER_TOOL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
for( int i = 0; i < board->GetAreaCount(); ++i )
|
||||
{
|
||||
ZONE_CONTAINER* zone = board->GetArea( i );
|
||||
|
||||
commit.Modify( zone );
|
||||
|
||||
zone->SetIsFilled( false );
|
||||
zone->ClearFilledPolysList();
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill All Zones" ) );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ZONE_FILLER_TOOL::setTransitions()
|
||||
{
|
||||
// Zone actions
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFill, PCB_ACTIONS::zoneFill.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFillAll, PCB_ACTIONS::zoneFillAll.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneUnfill, PCB_ACTIONS::zoneUnfill.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneUnfillAll, PCB_ACTIONS::zoneUnfillAll.MakeEvent() );
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user