more about zones. current No DRC for outlines

This commit is contained in:
CHARRAS 2008-01-04 12:27:16 +00:00
parent 945c14d4ea
commit ffd3a7133a
17 changed files with 1844 additions and 458 deletions

View File

@ -11,12 +11,12 @@ const char * add_zone_cutout[] = {
" ..............",
".... ........",
"... ++++ .......",
".. + + .....",
". + + ...",
". + + ..",
". + + ..",
". + + .",
".. + + ..",
".. +++++++ .....",
". ++ ++ ...",
". ++ ++ ..",
". ++ ++ ..",
". ++ ++ .",
".. ++++++++++ ..",
"... +++++++ ... ",
".... .... ",
"............ ",

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 );
}

View File

@ -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);
};
/*******************/

View File

@ -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:

View File

@ -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);

View File

@ -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\

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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: