more about zones. current No DRC for outlines
This commit is contained in:
parent
945c14d4ea
commit
ffd3a7133a
|
@ -11,12 +11,12 @@ const char * add_zone_cutout[] = {
|
|||
" ..............",
|
||||
".... ........",
|
||||
"... ++++ .......",
|
||||
".. + + .....",
|
||||
". + + ...",
|
||||
". + + ..",
|
||||
". + + ..",
|
||||
". + + .",
|
||||
".. + + ..",
|
||||
".. +++++++ .....",
|
||||
". ++ ++ ...",
|
||||
". ++ ++ ..",
|
||||
". ++ ++ ..",
|
||||
". ++ ++ .",
|
||||
".. ++++++++++ ..",
|
||||
"... +++++++ ... ",
|
||||
".... .... ",
|
||||
"............ ",
|
||||
|
|
|
@ -4,6 +4,14 @@ Started 2007-June-11
|
|||
Please add newer entries at the top, list the date and your name with
|
||||
email address.
|
||||
|
||||
2008-jan-04 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
|
||||
================================================================================
|
||||
+pcbnew:
|
||||
More about zones:
|
||||
Outlines can be edited. Outlines are merged if needeed.
|
||||
Current No DRC for outlines
|
||||
|
||||
|
||||
2008-jan-01 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
|
||||
================================================================================
|
||||
+all
|
||||
|
|
|
@ -529,6 +529,24 @@ public:
|
|||
*/
|
||||
int Fill_All_Zones( wxDC* DC, bool verbose = TRUE );
|
||||
|
||||
|
||||
/**
|
||||
* Function Add_Zone_Cutout
|
||||
* Add a cutout zone to a given zone outline
|
||||
* @param DC = current Device Context
|
||||
* @param zone_container = parent zone outline
|
||||
*/
|
||||
void Add_Zone_Cutout( wxDC* DC , ZONE_CONTAINER * zone_container );
|
||||
|
||||
/**
|
||||
* Function Add_Similar_Zone
|
||||
* Add a zone to a given zone outline.
|
||||
* if the zones are overlappeing they will be merged
|
||||
* @param DC = current Device Context
|
||||
* @param zone_container = parent zone outline
|
||||
*/
|
||||
void Add_Similar_Zone( wxDC* DC , ZONE_CONTAINER * zone_container );
|
||||
|
||||
/**
|
||||
* Function Edit_Zone_Params
|
||||
* Edit params (layer, clearance, ...) for a zone outline
|
||||
|
@ -548,6 +566,13 @@ public:
|
|||
*/
|
||||
void End_Move_Zone_Corner( wxDC* DC , ZONE_CONTAINER * zone_container );
|
||||
|
||||
/**
|
||||
* Function End_Move_Zone_Corner
|
||||
* Remove the currently selected corner in a zone outline
|
||||
* the .m_CornerSelection is used as corner selection
|
||||
*/
|
||||
void Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER * zone_container );
|
||||
|
||||
// Target handling
|
||||
MIREPCB* Create_Mire( wxDC* DC );
|
||||
void Delete_Mire( MIREPCB* MirePcb, wxDC* DC );
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -224,6 +224,123 @@ public:
|
|||
void Show( int nestLevel, std::ostream& os );
|
||||
|
||||
#endif
|
||||
|
||||
/* Functions used in test, merge and cut outlines */
|
||||
/**
|
||||
* Function AddArea
|
||||
* add empty copper area to net
|
||||
* @return pointer to the new area
|
||||
*/
|
||||
ZONE_CONTAINER* AddArea( int netcode, int layer, int x, int y, int hatch );
|
||||
|
||||
/**
|
||||
* remove copper area from net
|
||||
* @param area = area to remove
|
||||
* @return 0
|
||||
*/
|
||||
int RemoveArea( ZONE_CONTAINER* area_to_remove );
|
||||
|
||||
/**
|
||||
* Function InsertArea
|
||||
* add empty copper area to net, inserting after m_ZoneDescriptorList[iarea]
|
||||
* @return pointer to the new area
|
||||
*/
|
||||
ZONE_CONTAINER* InsertArea( int netcode, int iarea, int layer, int x, int y, int hatch );
|
||||
|
||||
/**
|
||||
Function CompleteArea
|
||||
* complete copper area contour by adding a line from last to first corner
|
||||
* if there is only 1 or 2 corners, remove (delete) the area
|
||||
* @param area_to_complete = area to complete or remove
|
||||
* @param style = style of last corner
|
||||
* @return 1 if Ok, 0 if area removed
|
||||
*/
|
||||
int CompleteArea( ZONE_CONTAINER* area_to_complete, int style );
|
||||
|
||||
/**
|
||||
* Function TestAreaPolygon
|
||||
* Test an area for self-intersection.
|
||||
*
|
||||
* @param CurrArea = copper area to test
|
||||
* @return :
|
||||
* -1 if arcs intersect other sides
|
||||
* 0 if no intersecting sides
|
||||
* 1 if intersecting sides, but no intersecting arcs
|
||||
* Also sets utility2 flag of area with return value
|
||||
*/
|
||||
int TestAreaPolygon( ZONE_CONTAINER* CurrArea );
|
||||
|
||||
/**
|
||||
* Function ClipAreaPolygon
|
||||
* Process an area that has been modified, by clipping its polygon against itself.
|
||||
* This may change the number and order of copper areas in the net.
|
||||
* @param bMessageBoxInt == TRUE, shows message when clipping occurs.
|
||||
* @param bMessageBoxArc == TRUE, shows message when clipping can't be done due to arcs.
|
||||
* @return:
|
||||
* -1 if arcs intersect other sides, so polygon can't be clipped
|
||||
* 0 if no intersecting sides
|
||||
* 1 if intersecting sides
|
||||
* Also sets areas->utility1 flags if areas are modified
|
||||
*/
|
||||
int ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
|
||||
bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs = TRUE );
|
||||
|
||||
/**
|
||||
* Process an area that has been modified, by clipping its polygon against
|
||||
* itself and the polygons for any other areas on the same net.
|
||||
* This may change the number and order of copper areas in the net.
|
||||
* @param modified_area = area to test
|
||||
* @param bMessageBox : if TRUE, shows message boxes when clipping occurs.
|
||||
* @return :
|
||||
* -1 if arcs intersect other sides, so polygon can't be clipped
|
||||
* 0 if no intersecting sides
|
||||
* 1 if intersecting sides, polygon clipped
|
||||
*/
|
||||
int AreaPolygonModified( ZONE_CONTAINER* modified_area,
|
||||
bool bMessageBoxArc,
|
||||
bool bMessageBoxInt );
|
||||
|
||||
/**
|
||||
* Function CombineAllAreasInNet
|
||||
* Checks all copper areas in net for intersections, combining them if found
|
||||
* @param aNetCode = net to consider
|
||||
* @param bMessageBox : if true display warning message box
|
||||
* @param bUseUtility : if true, don't check areas if both utility flags are 0
|
||||
* Sets utility flag = 1 for any areas modified
|
||||
* If an area has self-intersecting arcs, doesn't try to combine it
|
||||
*/
|
||||
int CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtility );
|
||||
|
||||
/**
|
||||
* Function TestAreaIntersections
|
||||
* Check for intersection of a given copper area with other areas in same net
|
||||
* @param area_to_test = area to compare to all other areas in the same net
|
||||
*/
|
||||
bool TestAreaIntersections( ZONE_CONTAINER* area_to_test );
|
||||
|
||||
/**
|
||||
* Function TestAreaIntersection
|
||||
* Test for intersection of 2 copper areas
|
||||
* area_to_test must be after area_ref in m_ZoneDescriptorList
|
||||
* @param area_ref = area reference
|
||||
* @param area_to_test = area to compare for intersection calculations
|
||||
* @return : 0 if no intersection
|
||||
* 1 if intersection
|
||||
* 2 if arcs intersect
|
||||
*/
|
||||
int TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test );
|
||||
|
||||
/**
|
||||
* Function CombineAreas
|
||||
* If possible, combine 2 copper areas
|
||||
* area_ref must be BEFORE area_to_combine
|
||||
* area_to_combine will be deleted, if areas are combined
|
||||
* @return : 0 if no intersection
|
||||
* 1 if intersection
|
||||
* 2 if arcs intersect
|
||||
*/
|
||||
int CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine );
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifndef CLASS_BOARD_H
|
||||
|
|
|
@ -8,30 +8,9 @@
|
|||
#include "gr_basic.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "PolyLine.h"
|
||||
#include "pcbnew.h"
|
||||
|
||||
/************************/
|
||||
/* class ZONE_CONTAINER */
|
||||
/************************/
|
||||
|
||||
ZONE_CONTAINER::ZONE_CONTAINER( BOARD* parent ) :
|
||||
BOARD_ITEM( parent, TYPEZONE_CONTAINER )
|
||||
, CPolyLine( NULL )
|
||||
|
||||
{
|
||||
m_NetCode = -1; // Net number for fast comparisons
|
||||
m_CornerSelection = -1;
|
||||
m_ZoneClearance = 200; // a reasonnable clerance value
|
||||
m_GridFillValue = 50; // a reasonnable grid used for filling
|
||||
m_PadOption = THERMAL_PAD;
|
||||
}
|
||||
|
||||
|
||||
ZONE_CONTAINER::~ZONE_CONTAINER()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**********************/
|
||||
/* Class EDGE_ZONE */
|
||||
/**********************/
|
||||
|
@ -49,7 +28,6 @@ EDGE_ZONE:: ~EDGE_ZONE()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/****************************************/
|
||||
bool EDGE_ZONE::Save( FILE* aFile ) const
|
||||
/****************************************/
|
||||
|
@ -57,6 +35,51 @@ bool EDGE_ZONE::Save( FILE* aFile ) const
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/************************/
|
||||
/* class ZONE_CONTAINER */
|
||||
/************************/
|
||||
|
||||
ZONE_CONTAINER::ZONE_CONTAINER( BOARD* parent ) :
|
||||
BOARD_ITEM( parent, TYPEZONE_CONTAINER )
|
||||
|
||||
{
|
||||
m_NetCode = -1; // Net number for fast comparisons
|
||||
m_CornerSelection = -1;
|
||||
m_ZoneClearance = 200; // a reasonnable clerance value
|
||||
m_GridFillValue = 50; // a reasonnable grid used for filling
|
||||
m_PadOption = THERMAL_PAD;
|
||||
utility = 0; // flags used in polygon calculations
|
||||
utility2 = 0; // flags used in polygon calculations
|
||||
m_Poly = new CPolyLine( NULL ); // Outlines
|
||||
|
||||
}
|
||||
|
||||
|
||||
ZONE_CONTAINER::~ZONE_CONTAINER()
|
||||
{
|
||||
delete m_Poly;
|
||||
m_Poly = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************/
|
||||
void ZONE_CONTAINER::SetNet( int anet_code )
|
||||
/*******************************************/
|
||||
{
|
||||
m_NetCode = anet_code;
|
||||
if ( m_Parent )
|
||||
{
|
||||
EQUIPOT* net = ((BOARD*) m_Parent)->FindNet( g_HightLigth_NetCode );
|
||||
if( net )
|
||||
m_Netname = net->m_Netname;
|
||||
else m_Netname.Empty();
|
||||
}
|
||||
else m_Netname.Empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************/
|
||||
bool ZONE_CONTAINER::Save( FILE* aFile ) const
|
||||
/********************************************/
|
||||
|
@ -66,7 +89,7 @@ bool ZONE_CONTAINER::Save( FILE* aFile ) const
|
|||
|
||||
unsigned item_pos;
|
||||
int ret;
|
||||
unsigned corners_count = corner.size();
|
||||
unsigned corners_count = m_Poly->corner.size();
|
||||
int outline_hatch;
|
||||
|
||||
fprintf( aFile, "$CZONE_OUTLINE\n");
|
||||
|
@ -79,16 +102,16 @@ bool ZONE_CONTAINER::Save( FILE* aFile ) const
|
|||
ret = fprintf( aFile, "ZLayer %d\n", m_Layer );
|
||||
if ( ret < 1 ) return false;
|
||||
// Save the ouline aux info
|
||||
switch ( m_HatchStyle )
|
||||
switch ( m_Poly->GetHatchStyle() )
|
||||
{
|
||||
default:
|
||||
case NO_HATCH:
|
||||
case CPolyLine::NO_HATCH:
|
||||
outline_hatch = 'N';
|
||||
break;
|
||||
case DIAGONAL_EDGE:
|
||||
case CPolyLine::DIAGONAL_EDGE:
|
||||
outline_hatch = 'E';
|
||||
break;
|
||||
case DIAGONAL_FULL:
|
||||
case CPolyLine::DIAGONAL_FULL:
|
||||
outline_hatch = 'F';
|
||||
break;
|
||||
}
|
||||
|
@ -99,8 +122,8 @@ bool ZONE_CONTAINER::Save( FILE* aFile ) const
|
|||
for ( item_pos = 0; item_pos < corners_count; item_pos++ )
|
||||
{
|
||||
ret = fprintf( aFile, "ZCorner %d %d %d \n",
|
||||
corner[item_pos].x, corner[item_pos].y,
|
||||
corner[item_pos].end_contour );
|
||||
m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].y,
|
||||
m_Poly->corner[item_pos].end_contour );
|
||||
if ( ret < 3 ) return false;
|
||||
}
|
||||
fprintf( aFile, "$endCZONE_OUTLINE\n");
|
||||
|
@ -122,7 +145,7 @@ int ZONE_CONTAINER::ReadDescr( FILE* aFile, int* aLineNum )
|
|||
char netname_buffer[1024];
|
||||
int ret;
|
||||
int n_corner_item = 0;
|
||||
int outline_hatch = NO_HATCH;
|
||||
int outline_hatch = CPolyLine::NO_HATCH;
|
||||
bool error = false, has_corner = false;
|
||||
|
||||
netname_buffer[0] = 0;
|
||||
|
@ -137,13 +160,13 @@ int ZONE_CONTAINER::ReadDescr( FILE* aFile, int* aLineNum )
|
|||
else
|
||||
{
|
||||
if ( ! has_corner )
|
||||
Start( m_Layer, 0, 0,
|
||||
m_Poly->Start( m_Layer, 0, 0,
|
||||
x, y,
|
||||
outline_hatch );
|
||||
else
|
||||
AppendCorner( x, y );
|
||||
m_Poly->AppendCorner( x, y );
|
||||
has_corner = true;
|
||||
if ( flag ) Close();
|
||||
if ( flag ) m_Poly->Close();
|
||||
}
|
||||
}
|
||||
if( strnicmp(Line, "ZInfo", 5 ) == 0 ) // general info found
|
||||
|
@ -182,15 +205,15 @@ int ZONE_CONTAINER::ReadDescr( FILE* aFile, int* aLineNum )
|
|||
{
|
||||
case 'n':
|
||||
case 'N':
|
||||
outline_hatch = NO_HATCH;
|
||||
outline_hatch = CPolyLine::NO_HATCH;
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
outline_hatch = DIAGONAL_EDGE;
|
||||
outline_hatch = CPolyLine::DIAGONAL_EDGE;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
outline_hatch = DIAGONAL_FULL;
|
||||
outline_hatch = CPolyLine::DIAGONAL_FULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -245,32 +268,32 @@ void ZONE_CONTAINER::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& off
|
|||
|
||||
// draw the lines
|
||||
int i_start_contour = 0;
|
||||
for( unsigned ic = 0; ic < corner.size(); ic++ )
|
||||
for( unsigned ic = 0; ic < m_Poly->corner.size(); ic++ )
|
||||
{
|
||||
int xi = corner[ic].x + offset.x;
|
||||
int yi = corner[ic].y + offset.y;
|
||||
int xi = m_Poly->corner[ic].x + offset.x;
|
||||
int yi = m_Poly->corner[ic].y + offset.y;
|
||||
int xf, yf;
|
||||
if( corner[ic].end_contour == FALSE && ic < corner.size() - 1 )
|
||||
if( m_Poly->corner[ic].end_contour == FALSE && ic < m_Poly->corner.size() - 1 )
|
||||
{
|
||||
xf = corner[ic + 1].x + offset.x;
|
||||
yf = corner[ic + 1].y + offset.y;
|
||||
xf = m_Poly->corner[ic + 1].x + offset.x;
|
||||
yf = m_Poly->corner[ic + 1].y + offset.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xf = corner[i_start_contour].x + offset.x;
|
||||
yf = corner[i_start_contour].y + offset.y;
|
||||
xf = m_Poly->corner[i_start_contour].x + offset.x;
|
||||
yf = m_Poly->corner[i_start_contour].y + offset.y;
|
||||
i_start_contour = ic + 1;
|
||||
}
|
||||
GRLine( &panel->m_ClipBox, DC, xi, yi, xf, yf, 0, color );
|
||||
}
|
||||
|
||||
// draw hatches
|
||||
for( unsigned ic = 0; ic < m_HatchLines.size(); ic++ )
|
||||
for( unsigned ic = 0; ic < m_Poly->m_HatchLines.size(); ic++ )
|
||||
{
|
||||
int xi = m_HatchLines[ic].xi + offset.x;
|
||||
int yi = m_HatchLines[ic].yi + offset.y;
|
||||
int xf = m_HatchLines[ic].xf + offset.x;
|
||||
int yf =m_HatchLines[ic].yf + offset.y;
|
||||
int xi = m_Poly->m_HatchLines[ic].xi + offset.x;
|
||||
int yi = m_Poly->m_HatchLines[ic].yi + offset.y;
|
||||
int xf = m_Poly->m_HatchLines[ic].xf + offset.x;
|
||||
int yf =m_Poly->m_HatchLines[ic].yf + offset.y;
|
||||
GRLine( &panel->m_ClipBox, DC, xi, yi, xf, yf, 0, color );
|
||||
}
|
||||
|
||||
|
@ -307,7 +330,7 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
|
|||
#define MIN_DIST_IN_PIXELS 5
|
||||
int dist;
|
||||
unsigned item_pos, lim;
|
||||
lim = corner.size();
|
||||
lim = m_Poly->corner.size();
|
||||
|
||||
// Min distance to hit = MIN_DIST_IN_PIXELS pixels :
|
||||
WinEDA_BasePcbFrame* frame = ((BOARD*)GetParent())->m_PcbFrame;
|
||||
|
@ -315,7 +338,7 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
|
|||
|
||||
for ( item_pos = 0; item_pos < lim; item_pos++ )
|
||||
{
|
||||
dist = abs( corner[item_pos].x - refPos.x ) + abs( corner[item_pos].y - refPos.y );
|
||||
dist = abs( m_Poly->corner[item_pos].x - refPos.x ) + abs( m_Poly->corner[item_pos].y - refPos.y );
|
||||
if( dist <= min_dist )
|
||||
return item_pos;
|
||||
}
|
||||
|
@ -335,7 +358,7 @@ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
|
|||
#define MIN_DIST_IN_PIXELS 5
|
||||
int dist;
|
||||
unsigned item_pos, lim;
|
||||
lim = corner.size();
|
||||
lim = m_Poly->corner.size();
|
||||
|
||||
// Min distance to hit = MIN_DIST_IN_PIXELS pixels :
|
||||
WinEDA_BasePcbFrame* frame = ((BOARD*)GetParent())->m_PcbFrame;
|
||||
|
@ -351,7 +374,7 @@ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
|
|||
* the last segment of the current outline starts at current corner, and ends
|
||||
* at the first corner of the outline
|
||||
*/
|
||||
if( corner[item_pos].end_contour || end_segm >= lim)
|
||||
if( m_Poly->corner[item_pos].end_contour || end_segm >= lim)
|
||||
{
|
||||
unsigned tmp = first_corner_pos;
|
||||
first_corner_pos = end_segm; // first_corner_pos is now the beginning of the next outline
|
||||
|
@ -361,10 +384,10 @@ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
|
|||
/* test the dist between segment and ref point */
|
||||
dist = (int) GetPointToLineSegmentDistance( refPos.x,
|
||||
refPos.y,
|
||||
corner[item_pos].x,
|
||||
corner[item_pos].y,
|
||||
corner[end_segm].x,
|
||||
corner[end_segm].y );
|
||||
m_Poly->corner[item_pos].x,
|
||||
m_Poly->corner[item_pos].y,
|
||||
m_Poly->corner[end_segm].x,
|
||||
m_Poly->corner[end_segm].y );
|
||||
if( dist <= min_dist )
|
||||
return item_pos;
|
||||
}
|
||||
|
@ -407,10 +430,10 @@ void ZONE_CONTAINER::Display_Infos( WinEDA_DrawFrame* frame )
|
|||
Affiche_1_Parametre( frame, text_pos, _( "Layer" ), msg, BROWN );
|
||||
|
||||
text_pos += 8;
|
||||
msg.Printf( wxT( "%d" ), corner.size() );
|
||||
msg.Printf( wxT( "%d" ), m_Poly->corner.size() );
|
||||
Affiche_1_Parametre( frame, text_pos, _( "Corners" ), msg, BLUE );
|
||||
|
||||
text_pos += 8;
|
||||
msg.Printf( wxT( "%d" ), m_HatchLines.size() );
|
||||
msg.Printf( wxT( "%d" ), m_Poly->m_HatchLines.size() );
|
||||
Affiche_1_Parametre( frame, text_pos, _( "Hatch lines" ), msg, BLUE );
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* others polygons inside this main polygon are holes.
|
||||
*/
|
||||
|
||||
class ZONE_CONTAINER : public BOARD_ITEM, public CPolyLine
|
||||
class ZONE_CONTAINER : public BOARD_ITEM
|
||||
{
|
||||
public:
|
||||
enum m_PadInZone { // How pads are covered by copper in zone
|
||||
|
@ -24,10 +24,12 @@ public:
|
|||
PAD_IN_ZONE // pads are covered by copper
|
||||
};
|
||||
wxString m_Netname; // Net Name
|
||||
CPolyLine * m_Poly; // outlines
|
||||
int m_CornerSelection; // For corner moving, corner index to drag, or -1 if no selection
|
||||
int m_ZoneClearance; // clearance value
|
||||
int m_GridFillValue; // Grid used for filling
|
||||
m_PadInZone m_PadOption; // see m_PadInZone
|
||||
int utility, utility2; // flags used in polygon calculations
|
||||
|
||||
private:
|
||||
int m_NetCode; // Net number for fast comparisons
|
||||
|
@ -55,7 +57,7 @@ public:
|
|||
const wxPoint& offset, int draw_mode );
|
||||
|
||||
int GetNet( void ) { return m_NetCode; }
|
||||
void SetNet( int anet_code ) { m_NetCode = anet_code; }
|
||||
void SetNet( int anet_code );
|
||||
/**
|
||||
* Function HitTest
|
||||
* tests if the given wxPoint is within the bounds of this object.
|
||||
|
@ -90,7 +92,6 @@ public:
|
|||
* @return error level (0 = no error)
|
||||
*/
|
||||
int Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose = TRUE);
|
||||
|
||||
};
|
||||
|
||||
/*******************/
|
||||
|
|
|
@ -281,7 +281,7 @@ void WinEDA_ZoneFrame::CreateControls()
|
|||
}
|
||||
|
||||
if ( m_Zone_Container )
|
||||
s_Zone_Hatching = m_Zone_Container->GetHatch();
|
||||
s_Zone_Hatching = m_Zone_Container->m_Poly->GetHatchStyle();
|
||||
switch( s_Zone_Hatching )
|
||||
{
|
||||
case CPolyLine::NO_HATCH:
|
||||
|
|
|
@ -450,11 +450,13 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
|
|||
break;
|
||||
|
||||
case ID_POPUP_PCB_ZONE_ADD_SIMILAR_ZONE:
|
||||
wxMessageBox(wxT("ToDo"));
|
||||
DrawPanel->MouseToCursorSchema();
|
||||
Add_Similar_Zone( &dc, (ZONE_CONTAINER*) GetCurItem() );
|
||||
break;
|
||||
|
||||
case ID_POPUP_PCB_ZONE_ADD_CUTOUT_ZONE:
|
||||
wxMessageBox(wxT("ToDo"));
|
||||
DrawPanel->MouseToCursorSchema();
|
||||
Add_Zone_Cutout( &dc, (ZONE_CONTAINER*) GetCurItem() );
|
||||
break;
|
||||
|
||||
case ID_POPUP_PCB_DELETE_ZONE_CONTAINER:
|
||||
|
@ -469,23 +471,9 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
case ID_POPUP_PCB_DELETE_ZONE_CORNER:
|
||||
{
|
||||
DrawPanel->MouseToCursorSchema();
|
||||
ZONE_CONTAINER * zone_cont = (ZONE_CONTAINER*)GetCurItem();
|
||||
zone_cont->Draw(DrawPanel,&dc, wxPoint(0,0), GR_XOR);
|
||||
if ( zone_cont->GetNumCorners() <= 3 )
|
||||
{
|
||||
Delete_Zone( &dc, NULL, zone_cont->m_TimeStamp );
|
||||
m_Pcb->Delete( zone_cont );
|
||||
}
|
||||
else
|
||||
{
|
||||
zone_cont->DeleteCorner(zone_cont->m_CornerSelection);
|
||||
zone_cont->Draw(DrawPanel,&dc, wxPoint(0,0), GR_XOR);
|
||||
}
|
||||
Remove_Zone_Corner( &dc, (ZONE_CONTAINER*)GetCurItem() );
|
||||
SetCurItem( NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_POPUP_PCB_MOVE_ZONE_CORNER:
|
||||
{
|
||||
|
@ -505,7 +493,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
|
|||
* and start move the new corner
|
||||
*/
|
||||
zone_cont->Draw(DrawPanel, &dc, wxPoint(0,0), GR_XOR);
|
||||
zone_cont->InsertCorner( zone_cont->m_CornerSelection, pos.x, pos.y );
|
||||
zone_cont->m_Poly->InsertCorner( zone_cont->m_CornerSelection, pos.x, pos.y );
|
||||
zone_cont->m_CornerSelection++;
|
||||
zone_cont->Draw(DrawPanel, &dc, wxPoint(0,0), GR_XOR);
|
||||
Start_Move_Zone_Corner(&dc, zone_cont, zone_cont->m_CornerSelection, true);
|
||||
|
|
|
@ -10,8 +10,10 @@ LIBVIEWER3D = ../3d-viewer/3d-viewer.a
|
|||
ZONE_FILES = zones_by_polygon.o
|
||||
#ZONE_FILES = zones.o
|
||||
|
||||
|
||||
OBJECTS= $(TARGET).o classpcb.o\
|
||||
$(ZONE_FILES)\
|
||||
zones_test_and_combine_areas.o\
|
||||
zone_filling_algorithm.o\
|
||||
lay2plot.o\
|
||||
modedit_undo_redo.o\
|
||||
|
|
|
@ -658,10 +658,10 @@ void WinEDA_PcbFrame::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu
|
|||
|
||||
aPopMenu->AppendSeparator();
|
||||
ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_ZONE_ADD_SIMILAR_ZONE,
|
||||
_( "Add Similar Zone" ), fill_zone_xpm );
|
||||
_( "Add Similar Zone" ), add_zone_xpm );
|
||||
|
||||
ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_ZONE_ADD_CUTOUT_ZONE,
|
||||
_( "Add Cutout Zone" ), add_zone_cutout );
|
||||
_( "Add Cutout Area" ), add_zone_cutout );
|
||||
aPopMenu->AppendSeparator();
|
||||
|
||||
ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_FILL_ZONE,
|
||||
|
|
|
@ -112,20 +112,20 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose )
|
|||
|
||||
// trace the zone edges into the routing matrix
|
||||
int i_start_contour = 0;
|
||||
for( unsigned ic = 0; ic < corner.size(); ic++ )
|
||||
for( unsigned ic = 0; ic < m_Poly->corner.size(); ic++ )
|
||||
{
|
||||
int xi = corner[ic].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
int yi = corner[ic].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
int xi = m_Poly->corner[ic].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
int yi = m_Poly->corner[ic].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
int xf, yf;
|
||||
if( corner[ic].end_contour == FALSE && ic < corner.size() - 1 )
|
||||
if( m_Poly->corner[ic].end_contour == FALSE && ic < m_Poly->corner.size() - 1 )
|
||||
{
|
||||
xf = corner[ic + 1].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = corner[ic + 1].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
xf = m_Poly->corner[ic + 1].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = m_Poly->corner[ic + 1].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xf = corner[i_start_contour].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = corner[i_start_contour].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
xf = m_Poly->corner[i_start_contour].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = m_Poly->corner[i_start_contour].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
i_start_contour = ic + 1;
|
||||
}
|
||||
TraceLignePcb( xi, yi, xf, yf, -1, HOLE | CELL_is_EDGE, WRITE_CELL );
|
||||
|
@ -136,9 +136,8 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose )
|
|||
int cells_count = 0;
|
||||
for( ii = 0, pad = frame->m_Pcb->m_Pads; ii < frame->m_Pcb->m_NbPads; ii++, pad++ )
|
||||
{
|
||||
int icont = 0;
|
||||
wxPoint pos;
|
||||
if( TestPointInsideContour( icont, (*pad)->m_Pos.x, (*pad)->m_Pos.y ) )
|
||||
if( m_Poly->TestPointInside( (*pad)->m_Pos.x, (*pad)->m_Pos.y ) )
|
||||
{
|
||||
ZoneStartFill.x = ( (*pad)->m_Pos.x - Pcb->m_BoundaryBox.m_Pos.x +
|
||||
(g_GridRoutingSize / 2) ) / g_GridRoutingSize;
|
||||
|
@ -196,20 +195,20 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose )
|
|||
/* Recreate zone limits on the routing matrix
|
||||
* (could be deleted by PlaceCells()) : */
|
||||
i_start_contour = 0;
|
||||
for( unsigned ic = 0; ic < corner.size(); ic++ )
|
||||
for( unsigned ic = 0; ic < m_Poly->corner.size(); ic++ )
|
||||
{
|
||||
int xi = corner[ic].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
int yi = corner[ic].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
int xi = m_Poly->corner[ic].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
int yi = m_Poly->corner[ic].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
int xf, yf;
|
||||
if( corner[ic].end_contour == FALSE && ic < corner.size() - 1 )
|
||||
if( m_Poly->corner[ic].end_contour == FALSE && ic < m_Poly->corner.size() - 1 )
|
||||
{
|
||||
xf = corner[ic + 1].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = corner[ic + 1].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
xf = m_Poly->corner[ic + 1].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = m_Poly->corner[ic + 1].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xf = corner[i_start_contour].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = corner[i_start_contour].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
xf = m_Poly->corner[i_start_contour].x - Pcb->m_BoundaryBox.m_Pos.x;
|
||||
yf = m_Poly->corner[i_start_contour].y - Pcb->m_BoundaryBox.m_Pos.y;
|
||||
i_start_contour = ic + 1;
|
||||
}
|
||||
TraceLignePcb( xi, yi, xf, yf, -1, HOLE | CELL_is_EDGE, WRITE_CELL );
|
||||
|
@ -219,9 +218,8 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose )
|
|||
* (could be deleted by PlaceCells()) : */
|
||||
for( ii = 0, pad = frame->m_Pcb->m_Pads; ii < frame->m_Pcb->m_NbPads; ii++, pad++ )
|
||||
{
|
||||
int icont = 0;
|
||||
wxPoint pos;
|
||||
if( TestPointInsideContour( icont, (*pad)->m_Pos.x, (*pad)->m_Pos.y ) )
|
||||
if( m_Poly->TestPointInside( (*pad)->m_Pos.x, (*pad)->m_Pos.y ) )
|
||||
{
|
||||
ZoneStartFill.x = ( (*pad)->m_Pos.x - Pcb->m_BoundaryBox.m_Pos.x +
|
||||
(g_GridRoutingSize / 2) ) / g_GridRoutingSize;
|
||||
|
|
|
@ -27,10 +27,9 @@ using namespace std;
|
|||
|
||||
#include "common.h"
|
||||
#include "pcbnew.h"
|
||||
|
||||
#include "autorout.h"
|
||||
#include "cell.h"
|
||||
#include "trigo.h"
|
||||
|
||||
#include "id.h"
|
||||
|
||||
#include "protos.h"
|
||||
|
||||
|
@ -45,13 +44,15 @@ static void Abort_Zone_Move_Corner( WinEDA_DrawPanel* Panel, wxDC* DC );
|
|||
static void Show_Zone_Corner_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
|
||||
|
||||
/* Local variables */
|
||||
static bool Zone_45_Only = FALSE;
|
||||
static bool Zone_45_Only = FALSE;
|
||||
static ZONE_CONTAINER::m_PadInZone s_Zone_Pad_Options = ZONE_CONTAINER::THERMAL_PAD;
|
||||
static int s_Zone_Layer; // Layer used to create the current zone
|
||||
static int s_Zone_Hatching; // Option to show the zone area (outlines only, short hatches or full hatches
|
||||
static int s_NetcodeSelection; // Net code selection for the current zone
|
||||
static wxPoint s_CornerInitialPosition; // Used to abort a move corner command
|
||||
static bool s_CornerIsNew; // Used to abort a move corner command (if it is a new corner, it must be deleted)
|
||||
static int s_Zone_Layer; // Layer used to create the current zone
|
||||
static int s_Zone_Hatching; // Option to show the zone area (outlines only, short hatches or full hatches
|
||||
static int s_NetcodeSelection; // Net code selection for the current zone
|
||||
static wxPoint s_CornerInitialPosition; // Used to abort a move corner command
|
||||
static bool s_CornerIsNew; // Used to abort a move corner command (if it is a new corner, it must be deleted)
|
||||
static bool s_AddCutoutToCurrentZone; // if true, the next outline will be addes to s_CurrentZone
|
||||
static ZONE_CONTAINER* s_CurrentZone; // if != NULL, these ZONE_CONTAINER params will be used for the next zone
|
||||
|
||||
// key used to store net sort option in config file :
|
||||
#define ZONE_NET_SORT_OPTION_KEY wxT( "Zone_NetSort_Opt" )
|
||||
|
@ -63,6 +64,44 @@ enum zone_cmd {
|
|||
|
||||
#include "dialog_zones_by_polygon.cpp"
|
||||
|
||||
/**********************************************************************************/
|
||||
void WinEDA_PcbFrame::Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container )
|
||||
/**********************************************************************************/
|
||||
|
||||
/**
|
||||
* Function Add_Similar_Zone
|
||||
* Add a zone to a given zone outline.
|
||||
* if the zones are overlappeing they will be merged
|
||||
* @param DC = current Device Context
|
||||
* @param zone_container = parent zone outline
|
||||
*/
|
||||
{
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = zone_container;
|
||||
wxCommandEvent evt;
|
||||
evt.SetId( ID_PCB_ZONES_BUTT );
|
||||
Process_Special_Functions( evt );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************/
|
||||
void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container )
|
||||
/**********************************************************************************/
|
||||
|
||||
/**
|
||||
* Function Add_Zone_Cutout
|
||||
* Add a cutout zone to a given zone outline
|
||||
* @param DC = current Device Context
|
||||
* @param zone_container = parent zone outline
|
||||
*/
|
||||
{
|
||||
s_AddCutoutToCurrentZone = true;
|
||||
s_CurrentZone = zone_container;
|
||||
wxCommandEvent evt;
|
||||
evt.SetId( ID_PCB_ZONES_BUTT );
|
||||
Process_Special_Functions( evt );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
void WinEDA_PcbFrame::Delete_Zone( wxDC* DC, SEGZONE* aZone, long aTimestamp )
|
||||
|
@ -174,6 +213,8 @@ static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC )
|
|||
Panel->ManageCurseur = NULL;
|
||||
Panel->ForceCloseManageCurseur = NULL;
|
||||
pcbframe->SetCurItem( NULL );
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -228,9 +269,11 @@ void WinEDA_PcbFrame::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_con
|
|||
zone_container->m_Flags = IN_EDIT;
|
||||
DrawPanel->ManageCurseur = Show_Zone_Corner_While_Move_Mouse;
|
||||
DrawPanel->ForceCloseManageCurseur = Abort_Zone_Move_Corner;
|
||||
s_CornerInitialPosition.x = zone_container->GetX( corner_id );
|
||||
s_CornerInitialPosition.y = zone_container->GetY( corner_id );
|
||||
s_CornerInitialPosition.x = zone_container->m_Poly->GetX( corner_id );
|
||||
s_CornerInitialPosition.y = zone_container->m_Poly->GetY( corner_id );
|
||||
s_CornerIsNew = IsNewCorner;
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -248,6 +291,72 @@ void WinEDA_PcbFrame::End_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_conta
|
|||
DrawPanel->ForceCloseManageCurseur = NULL;
|
||||
zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
GetScreen()->SetModify();
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = NULL;
|
||||
|
||||
SetCurItem( NULL ); // This outine can be deleted when merging outlines
|
||||
|
||||
/* Combine zones if possible */
|
||||
int layer = zone_container->GetLayer();
|
||||
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
if( layer == edge_zone->GetLayer() )
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
}
|
||||
|
||||
m_Pcb->AreaPolygonModified( zone_container, true, false );
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
if( layer == edge_zone->GetLayer() )
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************/
|
||||
void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER * zone_container )
|
||||
/*************************************************************************************/
|
||||
/**
|
||||
* Function End_Move_Zone_Corner
|
||||
* Remove the currently selected corner in a zone outline
|
||||
* the .m_CornerSelection is used as corner selection
|
||||
*/
|
||||
{
|
||||
if ( zone_container->m_Poly->GetNumCorners() <= 3 )
|
||||
{
|
||||
Delete_Zone( DC, NULL, zone_container->m_TimeStamp );
|
||||
m_Pcb->Delete( zone_container );
|
||||
return;
|
||||
}
|
||||
|
||||
int layer = zone_container->GetLayer();
|
||||
|
||||
if ( DC )
|
||||
{
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
if( layer == edge_zone->GetLayer() )
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
}
|
||||
}
|
||||
|
||||
zone_container->m_Poly->DeleteCorner(zone_container->m_CornerSelection);
|
||||
|
||||
// modify zones outlines accordiing to the new zone_container shape
|
||||
m_Pcb->AreaPolygonModified( zone_container, true, false );
|
||||
if ( DC )
|
||||
{
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
if( layer == edge_zone->GetLayer() )
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,19 +376,21 @@ void Abort_Zone_Move_Corner( WinEDA_DrawPanel* Panel, wxDC* DC )
|
|||
|
||||
if( s_CornerIsNew )
|
||||
{
|
||||
zone_container->DeleteCorner( zone_container->m_CornerSelection );
|
||||
zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxPoint pos = s_CornerInitialPosition;
|
||||
zone_container->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y );
|
||||
zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y );
|
||||
}
|
||||
zone_container->Draw( Panel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
|
||||
Panel->ManageCurseur = NULL;
|
||||
Panel->ForceCloseManageCurseur = NULL;
|
||||
pcbframe->SetCurItem( NULL );
|
||||
zone_container->m_Flags = 0;
|
||||
zone_container->m_Flags = 0;
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -299,7 +410,7 @@ void Show_Zone_Corner_While_Move_Mouse( WinEDA_DrawPanel* Panel, wxDC* DC, bool
|
|||
}
|
||||
|
||||
wxPoint pos = pcbframe->GetScreen()->m_Curseur;
|
||||
zone_container->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y );
|
||||
zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y );
|
||||
zone_container->Draw( Panel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
}
|
||||
|
||||
|
@ -317,36 +428,61 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC )
|
|||
EDGE_ZONE* oldedge;
|
||||
EDGE_ZONE* newedge = NULL;
|
||||
|
||||
// verify if s_CurrentZone exists:
|
||||
unsigned ii;
|
||||
|
||||
for( ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
if( s_CurrentZone == m_Pcb->m_ZoneDescriptorList[ii] )
|
||||
break;
|
||||
}
|
||||
|
||||
if( ii == m_Pcb->m_ZoneDescriptorList.size() ) // Not found: coul be deleted since last selection
|
||||
{
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = NULL;
|
||||
}
|
||||
|
||||
oldedge = m_Pcb->m_CurrentLimitZone;
|
||||
|
||||
if( m_Pcb->m_CurrentLimitZone == NULL ) /* Start a new contour: init zone params (net and layer) */
|
||||
{
|
||||
DrawPanel->m_IgnoreMouseEvents = TRUE;
|
||||
WinEDA_ZoneFrame* frame = new WinEDA_ZoneFrame( this );
|
||||
if( s_CurrentZone == NULL )
|
||||
{
|
||||
DrawPanel->m_IgnoreMouseEvents = TRUE;
|
||||
WinEDA_ZoneFrame* frame = new WinEDA_ZoneFrame( this );
|
||||
|
||||
int diag = frame->ShowModal();
|
||||
frame->Destroy();
|
||||
DrawPanel->MouseToCursorSchema();
|
||||
DrawPanel->m_IgnoreMouseEvents = FALSE;
|
||||
|
||||
if( diag == ZONE_ABORT )
|
||||
return NULL;
|
||||
|
||||
GetScreen()->m_Active_Layer = s_Zone_Layer;
|
||||
int diag = frame->ShowModal();
|
||||
frame->Destroy();
|
||||
DrawPanel->MouseToCursorSchema();
|
||||
DrawPanel->m_IgnoreMouseEvents = FALSE;
|
||||
|
||||
if( diag == ZONE_ABORT )
|
||||
return NULL;
|
||||
}
|
||||
else /* Start a new contour: init zone params (net and layer) from an existing zone */
|
||||
{
|
||||
GetScreen()->m_Active_Layer = s_Zone_Layer = s_CurrentZone->GetLayer();
|
||||
s_Zone_Hatching = s_CurrentZone->m_Poly->GetHatchStyle();
|
||||
}
|
||||
/* Show the Net */
|
||||
if( (g_HightLigth_NetCode > 0) && (g_HightLigth_NetCode != s_NetcodeSelection) )
|
||||
{
|
||||
Hight_Light( DC ); // Remove old hightlight selection
|
||||
}
|
||||
|
||||
if( s_CurrentZone )
|
||||
s_NetcodeSelection = s_CurrentZone->GetNet();
|
||||
g_HightLigth_NetCode = s_NetcodeSelection;
|
||||
if( !g_HightLigt_Status )
|
||||
Hight_Light( DC );
|
||||
|
||||
if( !s_AddCutoutToCurrentZone )
|
||||
s_CurrentZone = NULL; // the zone is used only once
|
||||
}
|
||||
|
||||
// if first segment
|
||||
if( (m_Pcb->m_CurrentLimitZone == NULL ) /* Initial startt of a new outline */
|
||||
if( (m_Pcb->m_CurrentLimitZone == NULL ) /* Initial start of a new outline */
|
||||
|| (DrawPanel->ManageCurseur == NULL) ) /* reprise d'un trace complementaire */
|
||||
{
|
||||
newedge = new EDGE_ZONE( m_Pcb );
|
||||
|
@ -400,6 +536,7 @@ void WinEDA_PcbFrame::End_Zone( wxDC* DC )
|
|||
*/
|
||||
{
|
||||
EDGE_ZONE* edge;
|
||||
int layer = GetScreen()->m_Active_Layer;
|
||||
|
||||
if( m_Pcb->m_CurrentLimitZone )
|
||||
{
|
||||
|
@ -431,39 +568,74 @@ void WinEDA_PcbFrame::End_Zone( wxDC* DC )
|
|||
DrawPanel->ManageCurseur = NULL;
|
||||
DrawPanel->ForceCloseManageCurseur = NULL;
|
||||
|
||||
/* Put edges in list */
|
||||
ZONE_CONTAINER* polygon = new ZONE_CONTAINER( m_Pcb );
|
||||
polygon->SetLayer( GetScreen()->m_Active_Layer );
|
||||
polygon->SetNet( g_HightLigth_NetCode );
|
||||
polygon->m_TimeStamp = GetTimeStamp();
|
||||
|
||||
EQUIPOT* net = m_Pcb->FindNet( g_HightLigth_NetCode );
|
||||
if( net )
|
||||
polygon->m_Netname = net->m_Netname;
|
||||
edge = m_Pcb->m_CurrentLimitZone;
|
||||
polygon->Start( GetScreen()->m_Active_Layer, 0, 0,
|
||||
edge->m_Start.x, edge->m_Start.y,
|
||||
s_Zone_Hatching );
|
||||
edge = edge->Next();
|
||||
while( edge )
|
||||
// Undraw old drawings, because they can have important changes
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
polygon->AppendCorner( edge->m_Start.x, edge->m_Start.y );
|
||||
edge = edge->Next();
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
if( layer == edge_zone->GetLayer() )
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
}
|
||||
|
||||
polygon->Close(); // Close the current corner list
|
||||
polygon->SetHatch( s_Zone_Hatching );
|
||||
polygon->m_PadOption = s_Zone_Pad_Options;
|
||||
polygon->m_ZoneClearance = g_DesignSettings.m_ZoneClearence;
|
||||
polygon->m_GridFillValue = g_GridRoutingSize;
|
||||
/* Put edges in list */
|
||||
ZONE_CONTAINER* new_zone_container;
|
||||
if( s_CurrentZone == NULL )
|
||||
{
|
||||
new_zone_container = new ZONE_CONTAINER( m_Pcb );
|
||||
new_zone_container->SetLayer( layer );
|
||||
new_zone_container->SetNet( g_HightLigth_NetCode );
|
||||
new_zone_container->m_TimeStamp = GetTimeStamp();
|
||||
|
||||
m_Pcb->m_ZoneDescriptorList.push_back( polygon );
|
||||
edge = m_Pcb->m_CurrentLimitZone;
|
||||
new_zone_container->m_Poly->Start( layer, 0, 0,
|
||||
edge->m_Start.x, edge->m_Start.y,
|
||||
s_Zone_Hatching );
|
||||
edge = edge->Next();
|
||||
while( edge )
|
||||
{
|
||||
new_zone_container->m_Poly->AppendCorner( edge->m_Start.x, edge->m_Start.y );
|
||||
edge = edge->Next();
|
||||
}
|
||||
|
||||
new_zone_container->m_Poly->Close(); // Close the current corner list
|
||||
new_zone_container->m_Poly->SetHatch( s_Zone_Hatching );
|
||||
new_zone_container->m_PadOption = s_Zone_Pad_Options;
|
||||
new_zone_container->m_ZoneClearance = g_DesignSettings.m_ZoneClearence;
|
||||
new_zone_container->m_GridFillValue = g_GridRoutingSize;
|
||||
|
||||
m_Pcb->m_ZoneDescriptorList.push_back( new_zone_container );
|
||||
}
|
||||
else // Append this outline as a cutout to an existing zone
|
||||
{
|
||||
new_zone_container = s_CurrentZone;
|
||||
edge = m_Pcb->m_CurrentLimitZone;
|
||||
while( edge )
|
||||
{
|
||||
new_zone_container->m_Poly->AppendCorner( edge->m_Start.x, edge->m_Start.y );
|
||||
edge = edge->Next();
|
||||
}
|
||||
|
||||
new_zone_container->m_Poly->Close(); // Close the current corner list
|
||||
}
|
||||
|
||||
s_AddCutoutToCurrentZone = false;
|
||||
s_CurrentZone = NULL;
|
||||
|
||||
/* Remove the current temporary list */
|
||||
DelLimitesZone( DC, TRUE );
|
||||
|
||||
/* Redraw the real edge zone */
|
||||
polygon->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
new_zone_container->m_Flags = 0;
|
||||
SetCurItem( NULL ); // This outine can be deleted when merging outlines
|
||||
|
||||
// Combine zones if possible :
|
||||
m_Pcb->AreaPolygonModified( new_zone_container, true, false );
|
||||
|
||||
// Redraw the real edge zone :
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
if( layer == edge_zone->GetLayer() )
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
}
|
||||
|
||||
GetScreen()->SetModify();
|
||||
}
|
||||
|
@ -540,19 +712,32 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container
|
|||
if( diag == ZONE_ABORT )
|
||||
return;
|
||||
|
||||
zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
// Undraw old zone outlines
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
|
||||
}
|
||||
|
||||
zone_container->SetLayer( s_Zone_Layer );
|
||||
zone_container->SetNet( s_NetcodeSelection );
|
||||
EQUIPOT* net = m_Pcb->FindNet( s_NetcodeSelection );
|
||||
if( net )
|
||||
zone_container->m_Netname = net->m_Netname;
|
||||
zone_container->SetHatch( s_Zone_Hatching );
|
||||
zone_container->m_Poly->SetHatch( s_Zone_Hatching );
|
||||
zone_container->m_PadOption = s_Zone_Pad_Options;
|
||||
zone_container->m_ZoneClearance = g_DesignSettings.m_ZoneClearence;
|
||||
zone_container->m_GridFillValue = g_GridRoutingSize;
|
||||
|
||||
zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
// Combine zones if possible :
|
||||
m_Pcb->AreaPolygonModified( zone_container, true, false );
|
||||
|
||||
// Redraw the real new zone outlines:
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
|
||||
}
|
||||
|
||||
GetScreen()->SetModify();
|
||||
}
|
||||
|
@ -587,11 +772,11 @@ int WinEDA_PcbFrame::Fill_Zone( wxDC* DC, ZONE_CONTAINER* zone_container, bool v
|
|||
s_NetcodeSelection = zone_container->GetNet();
|
||||
if( (g_HightLigth_NetCode > 0) && (g_HightLigth_NetCode != s_NetcodeSelection) && DC )
|
||||
{
|
||||
Hight_Light( DC ); // Remove old hightlight selection
|
||||
Hight_Light( DC ); // Remove old hightlight selection
|
||||
}
|
||||
|
||||
g_HightLigth_NetCode = s_NetcodeSelection;
|
||||
if( !g_HightLigt_Status && DC)
|
||||
if( !g_HightLigt_Status && DC )
|
||||
Hight_Light( DC );
|
||||
|
||||
if( g_HightLigth_NetCode > 0 )
|
||||
|
@ -613,7 +798,7 @@ int WinEDA_PcbFrame::Fill_Zone( wxDC* DC, ZONE_CONTAINER* zone_container, bool v
|
|||
msg = _( "No Net" );
|
||||
|
||||
Affiche_1_Parametre( this, 22, _( "NetName" ), msg, RED );
|
||||
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
|
||||
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
|
||||
zone_container->m_PadOption = s_Zone_Pad_Options;
|
||||
zone_container->m_ZoneClearance = g_DesignSettings.m_ZoneClearence;
|
||||
zone_container->m_GridFillValue = g_GridRoutingSize;
|
||||
|
@ -641,22 +826,22 @@ int WinEDA_PcbFrame::Fill_All_Zones( wxDC* DC, bool verbose )
|
|||
ZONE_CONTAINER* zone_container;
|
||||
int error_level = 0;
|
||||
|
||||
// Remove all zones :
|
||||
if ( m_Pcb->m_Zone )
|
||||
{
|
||||
m_Pcb->m_Zone->DeleteStructList();
|
||||
m_Pcb->m_Zone = NULL;
|
||||
m_Pcb->m_NbSegmZone = 0;
|
||||
}
|
||||
// Remove all zones :
|
||||
if( m_Pcb->m_Zone )
|
||||
{
|
||||
m_Pcb->m_Zone->DeleteStructList();
|
||||
m_Pcb->m_Zone = NULL;
|
||||
m_Pcb->m_NbSegmZone = 0;
|
||||
}
|
||||
|
||||
for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ )
|
||||
{
|
||||
zone_container = m_Pcb->m_ZoneDescriptorList[ii];
|
||||
error_level = Fill_Zone( NULL, zone_container, verbose );
|
||||
if( error_level && ! verbose )
|
||||
if( error_level && !verbose )
|
||||
break;
|
||||
}
|
||||
|
||||
DrawPanel->Refresh(true);
|
||||
DrawPanel->Refresh( true );
|
||||
return error_level;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,975 @@
|
|||
/****************************************************************************/
|
||||
/* functions to test, merges and cut polygons used as copper areas outlines */
|
||||
/****************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "fctsys.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "pcbnew.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#undef ASSERT
|
||||
#define ASSERT wxASSERT
|
||||
|
||||
bool bDontShowSelfIntersectionArcsWarning;
|
||||
bool bDontShowSelfIntersectionWarning;
|
||||
bool bDontShowIntersectionArcsWarning;
|
||||
bool bDontShowIntersectionWarning;
|
||||
|
||||
|
||||
#define poly m_Poly
|
||||
|
||||
// carea: describes a copper area
|
||||
#define carea ZONE_CONTAINER
|
||||
|
||||
|
||||
/**
|
||||
* Function AddArea
|
||||
* add empty copper area to net
|
||||
* @return pointer to the new area
|
||||
*/
|
||||
ZONE_CONTAINER* BOARD::AddArea( int netcode, int layer, int x, int y, int hatch )
|
||||
{
|
||||
ZONE_CONTAINER* new_area = InsertArea( netcode, m_ZoneDescriptorList.size(
|
||||
) - 1, layer, x, y, hatch );
|
||||
|
||||
return new_area;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* remove copper area from net
|
||||
* @param area = area to remove
|
||||
* @return 0
|
||||
*/
|
||||
int BOARD::RemoveArea( ZONE_CONTAINER* area_to_remove )
|
||||
{
|
||||
Delete( area_to_remove );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function InsertArea
|
||||
* add empty copper area to net, inserting after m_ZoneDescriptorList[iarea]
|
||||
* @return pointer to the new area
|
||||
*/
|
||||
ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, int layer, int x, int y, int hatch )
|
||||
{
|
||||
ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
|
||||
|
||||
new_area->SetNet( netcode );
|
||||
new_area->SetLayer( layer );
|
||||
new_area->m_TimeStamp = GetTimeStamp();
|
||||
if( iarea < (int) ( m_ZoneDescriptorList.size() - 1) )
|
||||
m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + iarea + 1, new_area );
|
||||
else
|
||||
m_ZoneDescriptorList.push_back( new_area );
|
||||
|
||||
new_area->poly->Start( layer, 1, 10 * NM_PER_MIL, x, y,
|
||||
hatch );
|
||||
return new_area;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function CompleteArea
|
||||
* complete copper area contour by adding a line from last to first corner
|
||||
* if there is only 1 or 2 corners, remove (delete) the area
|
||||
* @param area_to_complete = area to complete or remove
|
||||
* @param style = style of last corner
|
||||
* @return 1 if Ok, 0 if area removed
|
||||
*/
|
||||
int BOARD::CompleteArea( ZONE_CONTAINER* area_to_complete, int style )
|
||||
{
|
||||
if( area_to_complete->poly->GetNumCorners() > 2 )
|
||||
{
|
||||
area_to_complete->poly->Close( style );
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveArea( area_to_complete );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function TestAreaPolygon
|
||||
* Test an area for self-intersection.
|
||||
*
|
||||
* @param CurrArea = copper area to test
|
||||
* @return :
|
||||
* -1 if arcs intersect other sides
|
||||
* 0 if no intersecting sides
|
||||
* 1 if intersecting sides, but no intersecting arcs
|
||||
* Also sets utility2 flag of area with return value
|
||||
*/
|
||||
int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea )
|
||||
{
|
||||
CPolyLine* p = CurrArea->poly;
|
||||
|
||||
// first, check for sides intersecting other sides, especially arcs
|
||||
bool bInt = false;
|
||||
bool bArcInt = false;
|
||||
int n_cont = p->GetNumContours();
|
||||
|
||||
// make bounding rect for each contour
|
||||
std::vector<CRect> cr;
|
||||
cr.reserve( n_cont );
|
||||
for( int icont = 0; icont<n_cont; icont++ )
|
||||
cr.push_back( p->GetCornerBounds( icont ) );
|
||||
|
||||
for( int icont = 0; icont<n_cont; icont++ )
|
||||
{
|
||||
int is_start = p->GetContourStart( icont );
|
||||
int is_end = p->GetContourEnd( icont );
|
||||
for( int is = is_start; is<=is_end; is++ )
|
||||
{
|
||||
int is_prev = is - 1;
|
||||
if( is_prev < is_start )
|
||||
is_prev = is_end;
|
||||
int is_next = is + 1;
|
||||
if( is_next > is_end )
|
||||
is_next = is_start;
|
||||
int style = p->GetSideStyle( is );
|
||||
int x1i = p->GetX( is );
|
||||
int y1i = p->GetY( is );
|
||||
int x1f = p->GetX( is_next );
|
||||
int y1f = p->GetY( is_next );
|
||||
|
||||
// check for intersection with any other sides
|
||||
for( int icont2 = icont; icont2<n_cont; icont2++ )
|
||||
{
|
||||
if( cr[icont].left > cr[icont2].right
|
||||
|| cr[icont].bottom > cr[icont2].top
|
||||
|| cr[icont2].left > cr[icont].right
|
||||
|| cr[icont2].bottom > cr[icont].top )
|
||||
{
|
||||
// rectangles don't overlap, do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
int is2_start = p->GetContourStart( icont2 );
|
||||
int is2_end = p->GetContourEnd( icont2 );
|
||||
for( int is2 = is2_start; is2<=is2_end; is2++ )
|
||||
{
|
||||
int is2_prev = is2 - 1;
|
||||
if( is2_prev < is2_start )
|
||||
is2_prev = is2_end;
|
||||
int is2_next = is2 + 1;
|
||||
if( is2_next > is2_end )
|
||||
is2_next = is2_start;
|
||||
if( icont != icont2
|
||||
|| (is2 != is && is2 != is_prev && is2 != is_next && is != is2_prev
|
||||
&& is !=
|
||||
is2_next ) )
|
||||
{
|
||||
int style2 = p->GetSideStyle( is2 );
|
||||
int x2i = p->GetX( is2 );
|
||||
int y2i = p->GetY( is2 );
|
||||
int x2f = p->GetX( is2_next );
|
||||
int y2f = p->GetY( is2_next );
|
||||
int ret = FindSegmentIntersections( x1i,
|
||||
y1i,
|
||||
x1f,
|
||||
y1f,
|
||||
style,
|
||||
x2i,
|
||||
y2i,
|
||||
x2f,
|
||||
y2f,
|
||||
style2 );
|
||||
if( ret )
|
||||
{
|
||||
// intersection between non-adjacent sides
|
||||
bInt = TRUE;
|
||||
if( style != CPolyLine::STRAIGHT || style2 != CPolyLine::STRAIGHT )
|
||||
{
|
||||
bArcInt = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( bArcInt )
|
||||
break;
|
||||
}
|
||||
|
||||
if( bArcInt )
|
||||
break;
|
||||
}
|
||||
|
||||
if( bArcInt )
|
||||
break;
|
||||
}
|
||||
|
||||
if( bArcInt )
|
||||
CurrArea->utility2 = -1;
|
||||
else if( bInt )
|
||||
CurrArea->utility2 = 1;
|
||||
else
|
||||
CurrArea->utility2 = 0;
|
||||
return CurrArea->utility2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function ClipAreaPolygon
|
||||
* Process an area that has been modified, by clipping its polygon against itself.
|
||||
* This may change the number and order of copper areas in the net.
|
||||
* @param bMessageBoxInt == TRUE, shows message when clipping occurs.
|
||||
* @param bMessageBoxArc == TRUE, shows message when clipping can't be done due to arcs.
|
||||
* @return:
|
||||
* -1 if arcs intersect other sides, so polygon can't be clipped
|
||||
* 0 if no intersecting sides
|
||||
* 1 if intersecting sides
|
||||
* Also sets areas->utility1 flags if areas are modified
|
||||
*/
|
||||
int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
|
||||
bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs )
|
||||
{
|
||||
CPolyLine* p = CurrArea->poly;
|
||||
int test = TestAreaPolygon( CurrArea ); // this sets utility2 flag
|
||||
|
||||
if( test == -1 && !bRetainArcs )
|
||||
test = 1;
|
||||
if( test == -1 )
|
||||
{
|
||||
// arc intersections, don't clip unless bRetainArcs == false
|
||||
if( bMessageBoxArc && bDontShowSelfIntersectionArcsWarning == false )
|
||||
{
|
||||
wxString str;
|
||||
str.Printf( wxT( "Area %X of net \"%s\" has arcs intersecting other sides.\n" ),
|
||||
CurrArea->m_TimeStamp, CurrArea->m_Netname.GetData() );
|
||||
str += wxT( "This may cause problems with other editing operations,\n" );
|
||||
str += wxT( "such as adding cutouts. It can't be fixed automatically.\n" );
|
||||
str += wxT( "Manual correction is recommended." );
|
||||
wxMessageBox( str );
|
||||
|
||||
// bDontShowSelfIntersectionArcsWarning = dlg.bDontShowBoxState;
|
||||
}
|
||||
return -1; // arcs intersect with other sides, error
|
||||
}
|
||||
|
||||
// mark all areas as unmodified except this one
|
||||
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
|
||||
m_ZoneDescriptorList[ia]->utility = 0;
|
||||
|
||||
CurrArea->utility = 1;
|
||||
|
||||
if( test == 1 )
|
||||
{
|
||||
// non-arc intersections, clip the polygon
|
||||
if( bMessageBoxInt && bDontShowSelfIntersectionWarning == false )
|
||||
{
|
||||
wxString str;
|
||||
str.Printf( wxT( "Area %d of net \"%s\" is self-intersecting and will be clipped.\n" ),
|
||||
CurrArea->m_TimeStamp, CurrArea->m_Netname.GetData() );
|
||||
str += wxT( "This may result in splitting the area.\n" );
|
||||
str += wxT( "If the area is complex, this may take a few seconds." );
|
||||
wxMessageBox( str );
|
||||
|
||||
// bDontShowSelfIntersectionWarning = dlg.bDontShowBoxState;
|
||||
}
|
||||
}
|
||||
|
||||
//** TODO test for cutouts outside of area
|
||||
//** if( test == 1 )
|
||||
{
|
||||
std::vector<CPolyLine*> * pa = new std::vector<CPolyLine*>;
|
||||
p->Undraw();
|
||||
int n_poly = CurrArea->poly->NormalizeWithGpc( pa, bRetainArcs );
|
||||
if( n_poly > 1 ) // i.e if clippinf has created some polygons, we must add these new copper areas
|
||||
{
|
||||
for( int ip = 1; ip < n_poly; ip++ )
|
||||
{
|
||||
// create new copper area and copy poly into it
|
||||
CPolyLine* new_p = (*pa)[ip - 1];
|
||||
CurrArea = AddArea( CurrArea->GetNet(), CurrArea->GetLayer(), 0, 0, 0 );
|
||||
|
||||
// remove the poly that was automatically created for the new area
|
||||
// and replace it with a poly from NormalizeWithGpc
|
||||
delete CurrArea->poly;
|
||||
CurrArea->poly = new_p;
|
||||
CurrArea->poly->Draw();
|
||||
CurrArea->utility = 1;
|
||||
}
|
||||
}
|
||||
p->Draw();
|
||||
delete pa;
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process an area that has been modified, by clipping its polygon against
|
||||
* itself and the polygons for any other areas on the same net.
|
||||
* This may change the number and order of copper areas in the net.
|
||||
* @param modified_area = area to test
|
||||
* @param bMessageBox : if TRUE, shows message boxes when clipping occurs.
|
||||
* @return :
|
||||
* -1 if arcs intersect other sides, so polygon can't be clipped
|
||||
* 0 if no intersecting sides
|
||||
* 1 if intersecting sides, polygon clipped
|
||||
*/
|
||||
int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area,
|
||||
bool bMessageBoxArc,
|
||||
bool bMessageBoxInt )
|
||||
{
|
||||
// clip polygon against itself
|
||||
int test = ClipAreaPolygon( modified_area, bMessageBoxArc, bMessageBoxInt );
|
||||
|
||||
if( test == -1 )
|
||||
return test;
|
||||
|
||||
// now see if we need to clip against other areas
|
||||
bool bCheckAllAreas = false;
|
||||
if( test == 1 )
|
||||
bCheckAllAreas = TRUE;
|
||||
else
|
||||
bCheckAllAreas = TestAreaIntersections( modified_area );
|
||||
if( bCheckAllAreas )
|
||||
CombineAllAreasInNet( modified_area->GetNet(), bMessageBoxInt, TRUE );
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function CombineAllAreasInNet
|
||||
* Checks all copper areas in net for intersections, combining them if found
|
||||
* @param aNetCode = net to consider
|
||||
* @param bMessageBox : if true display warning message box
|
||||
* @param bUseUtility : if true, don't check areas if both utility flags are 0
|
||||
* Sets utility flag = 1 for any areas modified
|
||||
* If an area has self-intersecting arcs, doesn't try to combine it
|
||||
*/
|
||||
int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtility )
|
||||
{
|
||||
if( m_ZoneDescriptorList.size() > 1 )
|
||||
{
|
||||
// start by testing all area polygons to set utility2 flags
|
||||
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
|
||||
if( m_ZoneDescriptorList[ia]->GetNet() == aNetCode )
|
||||
TestAreaPolygon( m_ZoneDescriptorList[ia] );
|
||||
|
||||
// now loop through all combinations
|
||||
for( unsigned ia1 = 0; ia1 < m_ZoneDescriptorList.size() - 1; ia1++ )
|
||||
{
|
||||
ZONE_CONTAINER* curr_area = m_ZoneDescriptorList[ia1];
|
||||
if( curr_area->GetNet() != aNetCode )
|
||||
continue;
|
||||
|
||||
// legal polygon
|
||||
CRect b1 = curr_area->poly->GetCornerBounds();
|
||||
bool mod_ia1 = false;
|
||||
for( unsigned ia2 = m_ZoneDescriptorList.size() - 1; ia2 > ia1; ia2-- )
|
||||
{
|
||||
ZONE_CONTAINER* area2 = m_ZoneDescriptorList[ia2];
|
||||
if( curr_area->poly->GetLayer() == area2->poly->GetLayer()
|
||||
&& curr_area->utility2 != -1 && area2->utility2 != -1 )
|
||||
{
|
||||
CRect b2 = area2->poly->GetCornerBounds();
|
||||
if( !( b1.left > b2.right || b1.right < b2.left
|
||||
|| b1.bottom > b2.top || b1.top < b2.bottom ) )
|
||||
{
|
||||
// check ia2 against 1a1
|
||||
if( curr_area->utility || area2->utility || bUseUtility ==
|
||||
false )
|
||||
{
|
||||
int ret = TestAreaIntersection( curr_area, area2 );
|
||||
if( ret == 1 )
|
||||
ret = CombineAreas( curr_area, area2 );
|
||||
if( ret == 1 )
|
||||
{
|
||||
if( bMessageBox && bDontShowIntersectionWarning == false )
|
||||
{
|
||||
wxString str;
|
||||
str.Printf(
|
||||
wxT(
|
||||
"Areas %d and %d of net \"%s\" intersect and will be combined.\n" ),
|
||||
ia1 + 1,
|
||||
ia2 + 1,
|
||||
curr_area->m_Netname.GetData() );
|
||||
str += wxT(
|
||||
"If they are complex, this may take a few seconds." );
|
||||
wxMessageBox( str );
|
||||
|
||||
// bDontShowIntersectionWarning = dlg.bDontShowBoxState;
|
||||
}
|
||||
mod_ia1 = TRUE;
|
||||
}
|
||||
else if( ret == 2 )
|
||||
{
|
||||
if( bMessageBox && bDontShowIntersectionArcsWarning == false )
|
||||
{
|
||||
wxString str;
|
||||
str.Printf(
|
||||
wxT(
|
||||
"Areas %d and %d of net \"%s\" intersect, but some of the intersecting sides are arcs.\n" ),
|
||||
ia1 + 1,
|
||||
ia2 + 1,
|
||||
curr_area->m_Netname.GetData() );
|
||||
str += wxT( "Therefore, these areas can't be combined." );
|
||||
wxMessageBox( str );
|
||||
|
||||
// bDontShowIntersectionArcsWarning = dlg.bDontShowBoxState;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( mod_ia1 )
|
||||
ia1--; // if modified, we need to check it again
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function TestAreaIntersections
|
||||
* Check for intersection of a given copper area with other areas in same net
|
||||
* @param area_to_test = area to compare to all other areas in the same net
|
||||
*/
|
||||
bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
|
||||
{
|
||||
CPolyLine* poly1 = area_to_test->poly;
|
||||
|
||||
for( unsigned ia2 = 0; ia2 < m_ZoneDescriptorList.size(); ia2++ )
|
||||
{
|
||||
ZONE_CONTAINER* area2 = m_ZoneDescriptorList[ia2];
|
||||
if( area_to_test->GetNet() != area_to_test->GetNet() )
|
||||
continue;
|
||||
if( area_to_test != area2 )
|
||||
{
|
||||
// see if areas are on same layer
|
||||
if( area_to_test->GetLayer() != area2->GetLayer() )
|
||||
continue;
|
||||
|
||||
CPolyLine* poly2 = area2->poly;
|
||||
|
||||
// test bounding rects
|
||||
CRect b1 = poly1->GetCornerBounds();
|
||||
CRect b2 = poly2->GetCornerBounds();
|
||||
if( b1.bottom > b2.top
|
||||
|| b1.top < b2.bottom
|
||||
|| b1.left > b2.right
|
||||
|| b1.right < b2.left )
|
||||
continue;
|
||||
|
||||
// test for intersecting segments
|
||||
for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
|
||||
{
|
||||
int is1 = poly1->GetContourStart( icont1 );
|
||||
int ie1 = poly1->GetContourEnd( icont1 );
|
||||
for( int ic1 = is1; ic1<=ie1; ic1++ )
|
||||
{
|
||||
int xi1 = poly1->GetX( ic1 );
|
||||
int yi1 = poly1->GetY( ic1 );
|
||||
int xf1, yf1, style1;
|
||||
if( ic1 < ie1 )
|
||||
{
|
||||
xf1 = poly1->GetX( ic1 + 1 );
|
||||
yf1 = poly1->GetY( ic1 + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
xf1 = poly1->GetX( is1 );
|
||||
yf1 = poly1->GetY( is1 );
|
||||
}
|
||||
style1 = poly1->GetSideStyle( ic1 );
|
||||
for( int icont2 = 0; icont2<poly2->GetNumContours(); icont2++ )
|
||||
{
|
||||
int is2 = poly2->GetContourStart( icont2 );
|
||||
int ie2 = poly2->GetContourEnd( icont2 );
|
||||
for( int ic2 = is2; ic2<=ie2; ic2++ )
|
||||
{
|
||||
int xi2 = poly2->GetX( ic2 );
|
||||
int yi2 = poly2->GetY( ic2 );
|
||||
int xf2, yf2, style2;
|
||||
if( ic2 < ie2 )
|
||||
{
|
||||
xf2 = poly2->GetX( ic2 + 1 );
|
||||
yf2 = poly2->GetY( ic2 + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
xf2 = poly2->GetX( is2 );
|
||||
yf2 = poly2->GetY( is2 );
|
||||
}
|
||||
style2 = poly2->GetSideStyle( ic2 );
|
||||
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
|
||||
xi2, yi2, xf2, yf2, style2 );
|
||||
if( n_int )
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function TestAreaIntersection
|
||||
* Test for intersection of 2 copper areas
|
||||
* area_to_test must be after area_ref in m_ZoneDescriptorList
|
||||
* @param area_ref = area reference
|
||||
* @param area_to_test = area to compare for intersection calculations
|
||||
* @return : 0 if no intersection
|
||||
* 1 if intersection
|
||||
* 2 if arcs intersect
|
||||
*/
|
||||
int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test )
|
||||
{
|
||||
// see if areas are on same layer
|
||||
if( area_ref->GetLayer() != area_to_test->GetLayer() )
|
||||
return 0;
|
||||
|
||||
CPolyLine* poly1 = area_ref->poly;
|
||||
CPolyLine* poly2 = area_to_test->poly;
|
||||
|
||||
// test bounding rects
|
||||
CRect b1 = poly1->GetCornerBounds();
|
||||
CRect b2 = poly2->GetCornerBounds();
|
||||
if( b1.bottom > b2.top
|
||||
|| b1.top < b2.bottom
|
||||
|| b1.left > b2.right
|
||||
|| b1.right < b2.left )
|
||||
return 0;
|
||||
|
||||
// now test for intersecting segments
|
||||
bool bInt = false;
|
||||
bool bArcInt = false;
|
||||
for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
|
||||
{
|
||||
int is1 = poly1->GetContourStart( icont1 );
|
||||
int ie1 = poly1->GetContourEnd( icont1 );
|
||||
for( int ic1 = is1; ic1<=ie1; ic1++ )
|
||||
{
|
||||
int xi1 = poly1->GetX( ic1 );
|
||||
int yi1 = poly1->GetY( ic1 );
|
||||
int xf1, yf1, style1;
|
||||
if( ic1 < ie1 )
|
||||
{
|
||||
xf1 = poly1->GetX( ic1 + 1 );
|
||||
yf1 = poly1->GetY( ic1 + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
xf1 = poly1->GetX( is1 );
|
||||
yf1 = poly1->GetY( is1 );
|
||||
}
|
||||
style1 = poly1->GetSideStyle( ic1 );
|
||||
for( int icont2 = 0; icont2<poly2->GetNumContours(); icont2++ )
|
||||
{
|
||||
int is2 = poly2->GetContourStart( icont2 );
|
||||
int ie2 = poly2->GetContourEnd( icont2 );
|
||||
for( int ic2 = is2; ic2<=ie2; ic2++ )
|
||||
{
|
||||
int xi2 = poly2->GetX( ic2 );
|
||||
int yi2 = poly2->GetY( ic2 );
|
||||
int xf2, yf2, style2;
|
||||
if( ic2 < ie2 )
|
||||
{
|
||||
xf2 = poly2->GetX( ic2 + 1 );
|
||||
yf2 = poly2->GetY( ic2 + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
xf2 = poly2->GetX( is2 );
|
||||
yf2 = poly2->GetY( is2 );
|
||||
}
|
||||
style2 = poly2->GetSideStyle( ic2 );
|
||||
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
|
||||
xi2, yi2, xf2, yf2, style2 );
|
||||
if( n_int )
|
||||
{
|
||||
bInt = TRUE;
|
||||
if( style1 != CPolyLine::STRAIGHT || style2 != CPolyLine::STRAIGHT )
|
||||
bArcInt = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( bArcInt )
|
||||
break;
|
||||
}
|
||||
|
||||
if( bArcInt )
|
||||
break;
|
||||
}
|
||||
|
||||
if( bArcInt )
|
||||
break;
|
||||
}
|
||||
|
||||
if( !bInt )
|
||||
return 0;
|
||||
if( bArcInt )
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function CombineAreas
|
||||
* If possible, combine 2 copper areas
|
||||
* area_ref must be BEFORE area_to_combine in m_ZoneDescriptorList
|
||||
* area_to_combine will be deleted, if areas are combined
|
||||
* @return : 0 if no intersection
|
||||
* 1 if intersection
|
||||
* 2 if arcs intersect
|
||||
*/
|
||||
int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine )
|
||||
{
|
||||
if( area_ref == area_to_combine )
|
||||
ASSERT( 0 );
|
||||
#if 0
|
||||
|
||||
// test for intersection
|
||||
int test = TestAreaIntersection( area_ref, area_to_combine );
|
||||
if( test != 1 )
|
||||
return test; // no intersection
|
||||
#endif
|
||||
|
||||
// polygons intersect, combine them
|
||||
CPolyLine* poly1 = area_ref->poly;
|
||||
CPolyLine* poly2 = area_to_combine->poly;
|
||||
std::vector<CArc> arc_array1;
|
||||
std::vector<CArc> arc_array2;
|
||||
poly1->MakeGpcPoly( -1, &arc_array1 );
|
||||
poly2->MakeGpcPoly( -1, &arc_array2 );
|
||||
int n_ext_cont1 = 0;
|
||||
for( int ic = 0; ic<poly1->GetGpcPoly()->num_contours; ic++ )
|
||||
if( !( (poly1->GetGpcPoly()->hole)[ic] ) )
|
||||
n_ext_cont1++;
|
||||
|
||||
int n_ext_cont2 = 0;
|
||||
for( int ic = 0; ic<poly2->GetGpcPoly()->num_contours; ic++ )
|
||||
if( !( (poly2->GetGpcPoly()->hole)[ic] ) )
|
||||
n_ext_cont2++;
|
||||
|
||||
gpc_polygon* union_gpc = new gpc_polygon;
|
||||
gpc_polygon_clip( GPC_UNION, poly1->GetGpcPoly(), poly2->GetGpcPoly(), union_gpc );
|
||||
|
||||
// get number of outside contours
|
||||
int n_union_ext_cont = 0;
|
||||
for( int ic = 0; ic<union_gpc->num_contours; ic++ )
|
||||
if( !( (union_gpc->hole)[ic] ) )
|
||||
n_union_ext_cont++;
|
||||
|
||||
// if no intersection, free new gpc and return
|
||||
if( n_union_ext_cont == n_ext_cont1 + n_ext_cont2 )
|
||||
{
|
||||
gpc_free_polygon( union_gpc );
|
||||
delete union_gpc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// intersection, replace area_ref->m_Poly with combined areas and remove area_to_combine
|
||||
RemoveArea( area_to_combine );
|
||||
area_ref->m_Poly->RemoveAllContours();
|
||||
|
||||
// create area with external contour
|
||||
for( int ic = 0; ic<union_gpc->num_contours; ic++ )
|
||||
{
|
||||
if( !(union_gpc->hole)[ic] )
|
||||
{
|
||||
// external contour, replace this poly
|
||||
for( int i = 0; i<union_gpc->contour[ic].num_vertices; i++ )
|
||||
{
|
||||
int x = ( (union_gpc->contour)[ic].vertex )[i].x;
|
||||
int y = ( (union_gpc->contour)[ic].vertex )[i].y;
|
||||
if( i==0 )
|
||||
{
|
||||
area_ref->m_Poly->Start( area_ref->GetLayer(), 0, 0, x, y, area_ref->m_Poly->GetHatchStyle() );
|
||||
}
|
||||
else
|
||||
area_ref->m_Poly->AppendCorner( x, y );
|
||||
}
|
||||
|
||||
area_ref->m_Poly->Close();
|
||||
}
|
||||
}
|
||||
|
||||
// add holes
|
||||
for( int ic = 0; ic<union_gpc->num_contours; ic++ )
|
||||
{
|
||||
if( (union_gpc->hole)[ic] )
|
||||
{
|
||||
// hole
|
||||
for( int i = 0; i<union_gpc->contour[ic].num_vertices; i++ )
|
||||
{
|
||||
int x = ( (union_gpc->contour)[ic].vertex )[i].x;
|
||||
int y = ( (union_gpc->contour)[ic].vertex )[i].y;
|
||||
area_ref->m_Poly->AppendCorner( x, y );
|
||||
}
|
||||
|
||||
area_ref->m_Poly->Close();
|
||||
}
|
||||
}
|
||||
|
||||
area_ref->utility = 1;
|
||||
area_ref->m_Poly->RestoreArcs( &arc_array1 );
|
||||
area_ref->m_Poly->RestoreArcs( &arc_array2 );
|
||||
area_ref->m_Poly->Draw();
|
||||
gpc_free_polygon( union_gpc );
|
||||
delete union_gpc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void dra_areas( CDlgLog* log, int copper_layers,
|
||||
int units, BOOL check_unrouted,
|
||||
CArray<CPolyLine> * board_outline,
|
||||
DesignRules* dr, DRErrorList* drelist )
|
||||
{
|
||||
CString d_str, x_str, y_str;
|
||||
CString str;
|
||||
CString str2;
|
||||
long nerrors = 0;
|
||||
|
||||
// now iterate through all areas
|
||||
for( int ia = 0; ia<net->nareas; ia++ )
|
||||
{
|
||||
carea* a = &net->area[ia];
|
||||
|
||||
// iterate through all nets again
|
||||
POSITION pos2 = pos;
|
||||
void* ptr2;
|
||||
CString name2;
|
||||
while( pos2 != NULL )
|
||||
{
|
||||
m_nlist->m_map.GetNextAssoc( pos2, name2, ptr2 );
|
||||
cnet* net2 = (cnet*) ptr2;
|
||||
for( int ia2 = 0; ia2<net2->nareas; ia2++ )
|
||||
{
|
||||
carea* a2 = &net2->area[ia2];
|
||||
|
||||
// test for same layer
|
||||
if( a->poly->GetLayer() == a2->poly->GetLayer() )
|
||||
{
|
||||
// test for points inside one another
|
||||
for( int ic = 0; ic<a->poly->GetNumCorners(); ic++ )
|
||||
{
|
||||
int x = a->poly->GetX( ic );
|
||||
int y = a->poly->GetY( ic );
|
||||
if( a2->poly->TestPointInside( x, y ) )
|
||||
{
|
||||
// COPPERAREA_COPPERAREA error
|
||||
id id_a = net->id;
|
||||
id_a.st = ID_AREA;
|
||||
id_a.i = ia;
|
||||
id_a.sst = ID_SEL_CORNER;
|
||||
id_a.ii = ic;
|
||||
str.Format(
|
||||
"%ld: \"%s\" copper area inside \"%s\" inside copper area\r\n",
|
||||
nerrors + 1,
|
||||
net->name,
|
||||
net2->name );
|
||||
DRError* dre = drelist->Add( nerrors,
|
||||
DRError::COPPERAREA_INSIDE_COPPERAREA,
|
||||
&str,
|
||||
&net->name,
|
||||
&net2->name,
|
||||
id_a,
|
||||
id_a,
|
||||
x,
|
||||
y,
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
0 );
|
||||
if( dre )
|
||||
{
|
||||
nerrors++;
|
||||
if( log )
|
||||
log->AddLine( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int ic2 = 0; ic2<a2->poly->GetNumCorners(); ic2++ )
|
||||
{
|
||||
int x = a2->poly->GetX( ic2 );
|
||||
int y = a2->poly->GetY( ic2 );
|
||||
if( a->poly->TestPointInside( x, y ) )
|
||||
{
|
||||
// COPPERAREA_COPPERAREA error
|
||||
id id_a = net2->id;
|
||||
id_a.st = ID_AREA;
|
||||
id_a.i = ia2;
|
||||
id_a.sst = ID_SEL_CORNER;
|
||||
id_a.ii = ic2;
|
||||
str.Format( "%ld: \"%s\" copper area inside \"%s\" copper area\r\n",
|
||||
nerrors + 1, net2->name, net->name );
|
||||
DRError* dre = drelist->Add( nerrors,
|
||||
DRError::COPPERAREA_INSIDE_COPPERAREA,
|
||||
&str,
|
||||
&net2->name,
|
||||
&net->name,
|
||||
id_a,
|
||||
id_a,
|
||||
x,
|
||||
y,
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
0 );
|
||||
if( dre )
|
||||
{
|
||||
nerrors++;
|
||||
if( log )
|
||||
log->AddLine( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now test spacing between areas
|
||||
for( int icont = 0; icont<a->poly->GetNumContours(); icont++ )
|
||||
{
|
||||
int ic_start = a->poly->GetContourStart( icont );
|
||||
int ic_end = a->poly->GetContourEnd( icont );
|
||||
for( int ic = ic_start; ic<=ic_end; ic++ )
|
||||
{
|
||||
id id_a = net->id;
|
||||
id_a.st = ID_AREA;
|
||||
id_a.i = ia;
|
||||
id_a.sst = ID_SIDE;
|
||||
id_a.ii = ic;
|
||||
int ax1 = a->poly->GetX( ic );
|
||||
int ay1 = a->poly->GetY( ic );
|
||||
int ax2, ay2;
|
||||
if( ic == ic_end )
|
||||
{
|
||||
ax2 = a->poly->GetX( ic_start );
|
||||
ay2 = a->poly->GetY( ic_start );
|
||||
}
|
||||
else
|
||||
{
|
||||
ax2 = a->poly->GetX( ic + 1 );
|
||||
ay2 = a->poly->GetY( ic + 1 );
|
||||
}
|
||||
int astyle = a->poly->GetSideStyle( ic );
|
||||
for( int icont2 = 0; icont2<a2->poly->GetNumContours(); icont2++ )
|
||||
{
|
||||
int ic_start2 = a2->poly->GetContourStart( icont2 );
|
||||
int ic_end2 = a2->poly->GetContourEnd( icont2 );
|
||||
for( int ic2 = ic_start2; ic2<=ic_end2; ic2++ )
|
||||
{
|
||||
id id_b = net2->id;
|
||||
id_b.st = ID_AREA;
|
||||
id_b.i = ia2;
|
||||
id_b.sst = ID_SIDE;
|
||||
id_b.ii = ic2;
|
||||
int bx1 = a2->poly->GetX( ic2 );
|
||||
int by1 = a2->poly->GetY( ic2 );
|
||||
int bx2, by2;
|
||||
if( ic2 == ic_end2 )
|
||||
{
|
||||
bx2 = a2->poly->GetX( ic_start2 );
|
||||
by2 = a2->poly->GetY( ic_start2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
bx2 = a2->poly->GetX( ic2 + 1 );
|
||||
by2 = a2->poly->GetY( ic2 + 1 );
|
||||
}
|
||||
int bstyle = a2->poly->GetSideStyle( ic2 );
|
||||
int x, y;
|
||||
int d = ::GetClearanceBetweenSegments( bx1,
|
||||
by1,
|
||||
bx2,
|
||||
by2,
|
||||
bstyle,
|
||||
0,
|
||||
ax1,
|
||||
ay1,
|
||||
ax2,
|
||||
ay2,
|
||||
astyle,
|
||||
0,
|
||||
dr->copper_copper,
|
||||
&x,
|
||||
&y );
|
||||
if( d < dr->copper_copper )
|
||||
{
|
||||
// COPPERAREA_COPPERAREA error
|
||||
::MakeCStringFromDimension( &d_str,
|
||||
d,
|
||||
units,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1 );
|
||||
::MakeCStringFromDimension( &x_str,
|
||||
x,
|
||||
units,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1 );
|
||||
::MakeCStringFromDimension( &y_str,
|
||||
y,
|
||||
units,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1 );
|
||||
str.Format(
|
||||
"%ld: \"%s\" copper area to \"%s\" copper area = %s, x=%s, y=%s\r\n",
|
||||
nerrors + 1,
|
||||
net->name,
|
||||
net2->name,
|
||||
d_str,
|
||||
x_str,
|
||||
y_str );
|
||||
DRError* dre = drelist->Add(
|
||||
nerrors,
|
||||
DRError::
|
||||
COPPERAREA_COPPERAREA,
|
||||
&str,
|
||||
&net->name,
|
||||
&net2->name,
|
||||
id_a,
|
||||
id_b,
|
||||
x,
|
||||
y,
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
0 );
|
||||
if( dre )
|
||||
{
|
||||
nerrors++;
|
||||
if( log )
|
||||
log->AddLine( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -748,6 +748,19 @@ void CPolyLine::RemoveContour( int icont )
|
|||
Draw();
|
||||
}
|
||||
|
||||
|
||||
void CPolyLine::RemoveAllContours( void )
|
||||
/**
|
||||
* function RemoveAllContours
|
||||
* removes all corners from the lists.
|
||||
* Others params are not chnaged
|
||||
*/
|
||||
{
|
||||
corner.clear( );
|
||||
side_style.clear( );
|
||||
}
|
||||
|
||||
|
||||
/** Function InsertCorner
|
||||
* insert a new corner between two existing corners
|
||||
* @param ic = index for the insertion point: the corner is inserted AFTER ic
|
||||
|
|
|
@ -81,6 +81,7 @@ public:
|
|||
void MoveCorner( int ic, int x, int y );
|
||||
void Close( int style = STRAIGHT, BOOL bDraw=TRUE );
|
||||
void RemoveContour( int icont );
|
||||
void RemoveAllContours( void );
|
||||
|
||||
// drawing functions
|
||||
void HighlightSide( int is );
|
||||
|
@ -107,6 +108,7 @@ public:
|
|||
|
||||
|
||||
// access functions
|
||||
int GetLayer() { return m_layer;}
|
||||
int GetNumCorners();
|
||||
int GetNumSides();
|
||||
int GetClosed();
|
||||
|
@ -125,7 +127,7 @@ public:
|
|||
id GetId();
|
||||
int GetSelBoxSize();
|
||||
CDisplayList * GetDisplayList(){ return m_dlist; };
|
||||
int GetHatch(){ return m_HatchStyle; }
|
||||
int GetHatchStyle(){ return m_HatchStyle; }
|
||||
void SetHatch( int hatch ){ Undraw(); m_HatchStyle = hatch; Draw(); };
|
||||
void SetX( int ic, int x );
|
||||
void SetY( int ic, int y );
|
||||
|
@ -159,14 +161,14 @@ private:
|
|||
int m_Width; // line width
|
||||
int m_sel_box; // corner selection box width/2
|
||||
int utility;
|
||||
protected:
|
||||
public:
|
||||
std::vector <CPolyPt> corner; // array of points for corners
|
||||
std::vector <int> side_style; // array of styles for sides
|
||||
private:
|
||||
std::vector <dl_element*> dl_side; // graphic elements
|
||||
std::vector <dl_element*> dl_side_sel;
|
||||
std::vector <dl_element*> dl_corner_sel;
|
||||
protected:
|
||||
public:
|
||||
int m_HatchStyle; // hatch style, see enum above
|
||||
std::vector <CSegment> m_HatchLines; // hatch lines
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue