Commit ae05cd80 authored by jean-pierre charras's avatar jean-pierre charras

Remove arcs support in zone outlines: this is a legacy code from FreePCB,...

Remove arcs support in zone outlines: this is a legacy code from FreePCB, never used, never tested, never maintained.
parent f96d557e
...@@ -1041,7 +1041,7 @@ public: ...@@ -1041,7 +1041,7 @@ public:
* @param aLayer = the layer of area * @param aLayer = the layer of area
* @param aStartPointPosition = position of the first point of the polygon outline of this area * @param aStartPointPosition = position of the first point of the polygon outline of this area
* @param aHatch = hatch option * @param aHatch = hatch option
* @return pointer to the new area * @return a reference to the new area
*/ */
ZONE_CONTAINER* AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, ZONE_CONTAINER* AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
int aLayer, wxPoint aStartPointPosition, int aHatch ); int aLayer, wxPoint aStartPointPosition, int aHatch );
...@@ -1054,58 +1054,30 @@ public: ...@@ -1054,58 +1054,30 @@ public:
ZONE_CONTAINER* InsertArea( int netcode, int iarea, int layer, int x, int y, int hatch ); ZONE_CONTAINER* InsertArea( int netcode, int iarea, int layer, int x, int y, int hatch );
/** /**
* Function TestAreaPolygon * Function NormalizeAreaPolygon
* Test an area for self-intersection. * Process an area that has been modified, by normalizing its polygon against itself.
* * i.e. convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s)
* @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. * This may change the number and order of copper areas in the net.
* @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful * @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new created areas pickers
* in undo commands) can be NULL
* @param aCurrArea = the zone to process * @param aCurrArea = the zone to process
* @param bMessageBoxInt == true, shows message when clipping occurs. * @return true if changes are made
* @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs.
* @param bRetainArcs = true to handle arcs (not really used in KiCad)
* @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 * Also sets areas->utility1 flags if areas are modified
*/ */
int ClipAreaPolygon( PICKED_ITEMS_LIST* aNewZonesList, bool NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList,
ZONE_CONTAINER* aCurrArea, ZONE_CONTAINER* aCurrArea );
bool bMessageBoxArc,
bool bMessageBoxInt,
bool bRetainArcs = true );
/** /**
* Process an area that has been modified, by clipping its polygon against * Function OnAreaPolygonModified
* itself and the polygons for any other areas on the same net. * Process an area that has been modified, by normalizing its polygon
* and merging the intersecting polygons for any other areas on the same net.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param aModifiedZonesList = a PICKED_ITEMS_LIST * where to store deleted or added areas * @param aModifiedZonesList = a PICKED_ITEMS_LIST * where to store deleted or added areas
* (useful in undo commands. Can be NULL * (useful in undo commands can be NULL
* @param modified_area = area to test * @param modified_area = area to test
* @param bMessageBoxInt : if true, shows message boxes when clipping occurs. * @return true if some areas modified
* @param bMessageBoxArc if 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, polygon clipped
*/ */
int AreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, bool OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
ZONE_CONTAINER* modified_area, ZONE_CONTAINER* modified_area );
bool bMessageBoxArc,
bool bMessageBoxInt );
/** /**
* Function CombineAllAreasInNet * Function CombineAllAreasInNet
...@@ -1113,15 +1085,13 @@ public: ...@@ -1113,15 +1085,13 @@ public:
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful
* in undo commands can be NULL * in undo commands can be NULL
* @param aNetCode = net to consider * @param aNetCode = net to consider
* @param bMessageBox : if true display warning message box * @param aUseUtility : if true, don't check areas if both utility flags are 0
* @param bUseUtility : if true, don't check areas if both utility flags are 0
* Sets utility flag = 1 for any areas modified * Sets utility flag = 1 for any areas modified
* If an area has self-intersecting arcs, doesn't try to combine it * @return true if some areas modified
*/ */
int CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, bool CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList,
int aNetCode, int aNetCode,
bool bMessageBox, bool aUseUtility );
bool bUseUtility );
/** /**
* Function RemoveArea * Function RemoveArea
...@@ -1154,17 +1124,15 @@ public: ...@@ -1154,17 +1124,15 @@ public:
/** /**
* Function CombineAreas * Function CombineAreas
* If possible, combine 2 copper areas * If possible, combine 2 copper areas
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas
* in undo commands can be NULL * (useful for undo).
* @param area_ref = the main area (zone) * @param area_ref = the main area (zone)
* @param area_to_combine = the zone that can be merged with area_ref * @param area_to_combine = the zone that can be merged with area_ref
* area_ref must be BEFORE area_to_combine * area_ref must be BEFORE area_to_combine
* area_to_combine will be deleted, if areas are combined * area_to_combine will be deleted, if areas are combined
* @return : 0 if no intersection * @return : true if area_to_combine is combined with area_ref (and therefore be deleted)
* 1 if intersection
* 2 if arcs intersect
*/ */
int CombineAreas( PICKED_ITEMS_LIST* aDeletedList, bool CombineAreas( PICKED_ITEMS_LIST* aDeletedList,
ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ref,
ZONE_CONTAINER* area_to_combine ); ZONE_CONTAINER* area_to_combine );
......
...@@ -65,7 +65,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) : ...@@ -65,7 +65,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) :
SetDoNotAllowTracks( true ); // has meaning only if m_isKeepout == true SetDoNotAllowTracks( true ); // has meaning only if m_isKeepout == true
m_cornerRadius = 0; m_cornerRadius = 0;
utility = 0; // flags used in polygon calculations utility = 0; // flags used in polygon calculations
utility2 = 0; // flags used in polygon calculations
m_Poly = new CPolyLine(); // Outlines m_Poly = new CPolyLine(); // Outlines
aBoard->GetZoneSettings().ExportSetting( *this ); aBoard->GetZoneSettings().ExportSetting( *this );
} }
...@@ -102,7 +101,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) : ...@@ -102,7 +101,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) :
utility = aZone.utility; utility = aZone.utility;
utility2 = aZone.utility;
} }
......
...@@ -573,7 +573,7 @@ public: ...@@ -573,7 +573,7 @@ public:
// thickness of the copper bridge in thermal reliefs // thickness of the copper bridge in thermal reliefs
int m_ThermalReliefCopperBridge; int m_ThermalReliefCopperBridge;
int utility, utility2; // flags used in polygon calculations int utility; // flags used in polygon calculations
// true when a zone was filled, false after deleting the filled areas // true when a zone was filled, false after deleting the filled areas
bool m_IsFilled; bool m_IsFilled;
......
...@@ -44,8 +44,6 @@ ...@@ -44,8 +44,6 @@
#include <zones_functions_for_undo_redo.h> #include <zones_functions_for_undo_redo.h>
#include <drc_stuff.h> #include <drc_stuff.h>
bool s_Verbose = false; // false if zone outline diags must not be shown
// Outline creation: // Outline creation:
static void Abort_Zone_Create_Outline( EDA_DRAW_PANEL* Panel, wxDC* DC ); static void Abort_Zone_Create_Outline( EDA_DRAW_PANEL* Panel, wxDC* DC );
static void Show_New_Edge_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC, static void Show_New_Edge_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
...@@ -141,7 +139,7 @@ void PCB_EDIT_FRAME::duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ) ...@@ -141,7 +139,7 @@ void PCB_EDIT_FRAME::duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone )
GetScreen()->SetCurItem( NULL ); // This outline may be deleted when merging outlines GetScreen()->SetCurItem( NULL ); // This outline may be deleted when merging outlines
// Combine zones if possible // Combine zones if possible
GetBoard()->AreaPolygonModified( &_AuxiliaryList, newZone, true, s_Verbose ); GetBoard()->OnAreaPolygonModified( &_AuxiliaryList, newZone );
// Redraw zones // Redraw zones
GetBoard()->RedrawAreasOutlines( m_canvas, aDC, GR_OR, newZone->GetLayer() ); GetBoard()->RedrawAreasOutlines( m_canvas, aDC, GR_OR, newZone->GetLayer() );
...@@ -334,7 +332,7 @@ void PCB_EDIT_FRAME::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER* ...@@ -334,7 +332,7 @@ void PCB_EDIT_FRAME::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER*
// Combine zones if possible // Combine zones if possible
wxBusyCursor dummy; wxBusyCursor dummy;
GetBoard()->AreaPolygonModified( &_AuxiliaryList, aZone, true, s_Verbose ); GetBoard()->OnAreaPolygonModified( &_AuxiliaryList, aZone );
m_canvas->Refresh(); m_canvas->Refresh();
...@@ -389,7 +387,7 @@ void PCB_EDIT_FRAME::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* aZone ) ...@@ -389,7 +387,7 @@ void PCB_EDIT_FRAME::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* aZone )
aZone->m_Poly->DeleteCorner( aZone->m_CornerSelection ); aZone->m_Poly->DeleteCorner( aZone->m_CornerSelection );
// modify zones outlines according to the new aZone shape // modify zones outlines according to the new aZone shape
GetBoard()->AreaPolygonModified( &_AuxiliaryList, aZone, true, s_Verbose ); GetBoard()->OnAreaPolygonModified( &_AuxiliaryList, aZone );
if( DC ) if( DC )
{ {
...@@ -768,7 +766,7 @@ bool PCB_EDIT_FRAME::End_Zone( wxDC* DC ) ...@@ -768,7 +766,7 @@ bool PCB_EDIT_FRAME::End_Zone( wxDC* DC )
GetScreen()->SetCurItem( NULL ); // This outline can be deleted when merging outlines GetScreen()->SetCurItem( NULL ); // This outline can be deleted when merging outlines
// Combine zones if possible : // Combine zones if possible :
GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone, true, s_Verbose ); GetBoard()->OnAreaPolygonModified( &_AuxiliaryList, zone );
// Redraw the real edge zone : // Redraw the real edge zone :
GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, layer ); GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, layer );
...@@ -898,7 +896,7 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone ) ...@@ -898,7 +896,7 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone )
aZone->SetNetName( net->GetNetname() ); aZone->SetNetName( net->GetNetname() );
// Combine zones if possible // Combine zones if possible
GetBoard()->AreaPolygonModified( &_AuxiliaryList, aZone, true, s_Verbose ); GetBoard()->OnAreaPolygonModified( &_AuxiliaryList, aZone );
// Redraw the real new zone outlines // Redraw the real new zone outlines
GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, -1 ); GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, -1 );
......
...@@ -44,11 +44,6 @@ ...@@ -44,11 +44,6 @@
#include <math_for_graphics.h> #include <math_for_graphics.h>
static bool bDontShowSelfIntersectionArcsWarning;
static bool bDontShowSelfIntersectionWarning;
static bool bDontShowIntersectionArcsWarning;
/** /**
* Function AddArea * Function AddArea
* Add an empty copper area to board areas list * Add an empty copper area to board areas list
...@@ -126,199 +121,31 @@ ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, int layer, int x, int ...@@ -126,199 +121,31 @@ ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, int layer, int x, int
/** /**
* Function TestAreaPolygon * Function NormalizeAreaPolygon
* Test an area for self-intersection. * Process an area that has been modified, by normalizing its polygon against itself.
* * i.e. convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s)
* @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->m_Poly;
// first, check for sides intersecting other sides, especially arcs
bool bInt = false;
bool bArcInt = false;
int n_cont = p->GetContoursCount();
// 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. * This may change the number and order of copper areas in the net.
* @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful in * @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new created areas
* undo commands) can be NULL
* @param aCurrArea = the zone to process * @param aCurrArea = the zone to process
* @param bMessageBoxInt == true, shows message when clipping occurs. * @return true if changes are made
* @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs.
* @param bRetainArcs = true to handle arcs (not really used in KiCad)
* @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 * Also sets areas->utility1 flags if areas are modified
*/ */
int BOARD::ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList,
ZONE_CONTAINER* aCurrArea, ZONE_CONTAINER* aCurrArea )
bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs )
{ {
CPolyLine* curr_polygon = aCurrArea->m_Poly; CPolyLine* curr_polygon = aCurrArea->m_Poly;
int test = TestAreaPolygon( aCurrArea ); // 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 %08lX of net \"%s\" has arcs intersecting other sides.\n" ),
aCurrArea->GetTimeStamp(), GetChars( aCurrArea->GetNetName() ) );
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 );
}
return -1; // arcs intersect with other sides, error // mark all areas as unmodified except this one, if modified
}
// mark all areas as unmodified except this one
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ ) for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
m_ZoneDescriptorList[ia]->utility = 0; m_ZoneDescriptorList[ia]->utility = 0;
aCurrArea->utility = 1; aCurrArea->utility = 1;
if( test == 1 ) if( curr_polygon->IsPolygonSelfIntersecting() )
{
// non-arc intersections, clip the polygon
if( bMessageBoxInt && bDontShowSelfIntersectionWarning == false )
{
wxString str;
str.Printf( wxT( "Area %08lX of net \"%s\" is self-intersecting and will be clipped.\n" ),
aCurrArea->GetTimeStamp(), GetChars( aCurrArea->GetNetName() ) );
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 );
}
}
{ {
std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>; std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>;
curr_polygon->UnHatch(); curr_polygon->UnHatch();
int n_poly = aCurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs ); int n_poly = aCurrArea->m_Poly->NormalizeAreaOutlines( pa );
// If clipping has created some polygons, we must add these new copper areas. // If clipping has created some polygons, we must add these new copper areas.
if( n_poly > 1 ) if( n_poly > 1 )
...@@ -340,61 +167,46 @@ int BOARD::ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ...@@ -340,61 +167,46 @@ int BOARD::ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList,
NewArea->utility = 1; NewArea->utility = 1;
} }
} }
curr_polygon->Hatch();
delete pa; delete pa;
} }
return test; curr_polygon->Hatch();
return true;
} }
/** /**
* Process an area that has been modified, by clipping its polygon against * Process an area that has been modified, by normalizing its polygon
* itself and the polygons for any other areas on the same net. * and merging the intersecting polygons for any other areas on the same net.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param aModifiedZonesList = a PICKED_ITEMS_LIST * where to store deleted or added areas * @param aModifiedZonesList = a PICKED_ITEMS_LIST * where to store deleted or added areas
* (useful in undo commands can be NULL * (useful in undo commands can be NULL
* @param modified_area = area to test * @param modified_area = area to test
* @param bMessageBoxArc if true, shows message when clipping can't be done due to arcs. * @return true if some areas modified
* @param bMessageBoxInt == true, shows message 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( PICKED_ITEMS_LIST* aModifiedZonesList, bool BOARD::OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
ZONE_CONTAINER* modified_area, ZONE_CONTAINER* modified_area )
bool bMessageBoxArc,
bool bMessageBoxInt )
{ {
// clip polygon against itself // clip polygon against itself
int test = ClipAreaPolygon( aModifiedZonesList, modified_area, bMessageBoxArc, bMessageBoxInt ); bool modified = NormalizeAreaPolygon( aModifiedZonesList, modified_area );
if( test == -1 )
return test;
// now see if we need to clip against other areas // now see if we need to clip against other areas
int layer = modified_area->GetLayer(); int layer = modified_area->GetLayer();
bool bCheckAllAreas = false; bool bCheckAllAreas = TestAreaIntersections( modified_area );
if( test == 1 )
bCheckAllAreas = true;
else
bCheckAllAreas = TestAreaIntersections( modified_area );
if( bCheckAllAreas ) if( bCheckAllAreas )
CombineAllAreasInNet( aModifiedZonesList, modified_area->GetNet(), bMessageBoxInt, true ); {
modified = true;
CombineAllAreasInNet( aModifiedZonesList, modified_area->GetNet(), true );
}
if( layer >= FIRST_NO_COPPER_LAYER ) // Refill non copper zones on this layer if( layer >= FIRST_NO_COPPER_LAYER ) // Refill non copper zones on this layer
{
if( m_ZoneDescriptorList.size() > 0 )
{ {
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ ) for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
if( m_ZoneDescriptorList[ia]->GetLayer() == layer ) if( m_ZoneDescriptorList[ia]->GetLayer() == layer )
m_ZoneDescriptorList[ia]->BuildFilledPolysListData( this ); m_ZoneDescriptorList[ia]->BuildFilledPolysListData( this );
} }
}
// Test for bad areas: all zones must have more than 2 corners: // Test for bad areas: all zones must have more than 2 corners:
// Note: should not happen, but just in case. // Note: should not happen, but just in case.
...@@ -408,33 +220,29 @@ int BOARD::AreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, ...@@ -408,33 +220,29 @@ int BOARD::AreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
RemoveArea( aModifiedZonesList, zone ); RemoveArea( aModifiedZonesList, zone );
} }
return test; return modified;
} }
/** /**
* Function CombineAllAreasInNet * Function CombineAllAreasInNet
* Checks all copper areas in net for intersections, combining them if found * Checks all copper areas in net for intersections, combining them if found
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful
* undo commands can be NULL * in undo commands can be NULL
* @param aNetCode = net to consider * @param aNetCode = net to consider
* @param bMessageBox : if true display warning message box * @param aUseUtility : if true, don't check areas if both utility flags are 0
* @param bUseUtility : if true, don't check areas if both utility flags are 0
* Sets utility flag = 1 for any areas modified * Sets utility flag = 1 for any areas modified
* If an area has self-intersecting arcs, doesn't try to combine it * @return true if some areas modified
*/ */
int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, bool BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
bool bMessageBox, bool bUseUtility ) bool aUseUtility )
{ {
if( m_ZoneDescriptorList.size() <= 1 ) if( m_ZoneDescriptorList.size() <= 1 )
return 0; return false;
// start by testing all area polygons to set utility2 flags bool modified = false;
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
if( m_ZoneDescriptorList[ia]->GetNet() == aNetCode )
TestAreaPolygon( m_ZoneDescriptorList[ia] );
// now loop through all combinations //Loop through all combinations
for( unsigned ia1 = 0; ia1 < m_ZoneDescriptorList.size() - 1; ia1++ ) for( unsigned ia1 = 0; ia1 < m_ZoneDescriptorList.size() - 1; ia1++ )
{ {
ZONE_CONTAINER* curr_area = m_ZoneDescriptorList[ia1]; ZONE_CONTAINER* curr_area = m_ZoneDescriptorList[ia1];
...@@ -458,15 +266,14 @@ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, ...@@ -458,15 +266,14 @@ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) if( curr_area->GetIsKeepout() != area2->GetIsKeepout() )
continue; continue;
if( curr_area->GetLayer() == area2->GetLayer() if( curr_area->GetLayer() == area2->GetLayer() )
&& curr_area->utility2 != -1 && area2->utility2 != -1 )
{ {
CRect b2 = area2->m_Poly->GetCornerBounds(); CRect b2 = area2->m_Poly->GetCornerBounds();
if( !( b1.left > b2.right || b1.right < b2.left if( !( b1.left > b2.right || b1.right < b2.left
|| b1.bottom > b2.top || b1.top < b2.bottom ) ) || b1.bottom > b2.top || b1.top < b2.bottom ) )
{ {
// check area2 against curr_area // check area2 against curr_area
if( curr_area->utility || area2->utility || bUseUtility == false ) if( curr_area->utility || area2->utility || aUseUtility == false )
{ {
int ret = TestAreaIntersection( curr_area, area2 ); int ret = TestAreaIntersection( curr_area, area2 );
...@@ -476,19 +283,7 @@ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, ...@@ -476,19 +283,7 @@ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
if( ret == 1 ) if( ret == 1 )
{ {
mod_ia1 = true; mod_ia1 = true;
} modified = 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,
GetChars( curr_area->GetNetName() ) );
str += wxT( "Therefore, these areas can't be combined." );
wxMessageBox( str );
}
} }
} }
} }
...@@ -499,7 +294,7 @@ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, ...@@ -499,7 +294,7 @@ int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
ia1--; // if modified, we need to check it again ia1--; // if modified, we need to check it again
} }
return 0; return modified;
} }
...@@ -556,7 +351,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) ...@@ -556,7 +351,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
{ {
int xi1 = poly1->GetX( ic1 ); int xi1 = poly1->GetX( ic1 );
int yi1 = poly1->GetY( ic1 ); int yi1 = poly1->GetY( ic1 );
int xf1, yf1, style1; int xf1, yf1;
if( ic1 < ie1 ) if( ic1 < ie1 )
{ {
...@@ -569,8 +364,6 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) ...@@ -569,8 +364,6 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
yf1 = poly1->GetY( is1 ); yf1 = poly1->GetY( is1 );
} }
style1 = poly1->GetSideStyle( ic1 );
for( int icont2 = 0; icont2 < poly2->GetContoursCount(); icont2++ ) for( int icont2 = 0; icont2 < poly2->GetContoursCount(); icont2++ )
{ {
int is2 = poly2->GetContourStart( icont2 ); int is2 = poly2->GetContourStart( icont2 );
...@@ -580,7 +373,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) ...@@ -580,7 +373,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
{ {
int xi2 = poly2->GetX( ic2 ); int xi2 = poly2->GetX( ic2 );
int yi2 = poly2->GetY( ic2 ); int yi2 = poly2->GetY( ic2 );
int xf2, yf2, style2; int xf2, yf2;
if( ic2 < ie2 ) if( ic2 < ie2 )
{ {
...@@ -593,9 +386,8 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) ...@@ -593,9 +386,8 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
yf2 = poly2->GetY( is2 ); yf2 = poly2->GetY( is2 );
} }
style2 = poly2->GetSideStyle( ic2 ); int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, CPolyLine::STRAIGHT,
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1, xi2, yi2, xf2, yf2, CPolyLine::STRAIGHT );
xi2, yi2, xf2, yf2, style2 );
if( n_int ) if( n_int )
return true; return true;
} }
...@@ -640,7 +432,6 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) ...@@ -640,7 +432,6 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
* @param area_to_test = area to compare for intersection calculations * @param area_to_test = area to compare for intersection calculations
* @return : 0 if no intersection * @return : 0 if no intersection
* 1 if intersection * 1 if intersection
* 2 if arcs intersect
*/ */
int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test ) int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test )
{ {
...@@ -655,15 +446,12 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -655,15 +446,12 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
CRect b1 = poly1->GetCornerBounds(); CRect b1 = poly1->GetCornerBounds();
CRect b2 = poly2->GetCornerBounds(); CRect b2 = poly2->GetCornerBounds();
if( b1.bottom > b2.top if( b1.bottom > b2.top || b1.top < b2.bottom ||
|| b1.top < b2.bottom b1.left > b2.right || b1.right < b2.left )
|| b1.left > b2.right
|| b1.right < b2.left )
return 0; return 0;
// now test for intersecting segments // now test for intersecting segments
bool bInt = false; bool bInt = false;
bool bArcInt = false;
for( int icont1 = 0; icont1<poly1->GetContoursCount(); icont1++ ) for( int icont1 = 0; icont1<poly1->GetContoursCount(); icont1++ )
{ {
...@@ -674,7 +462,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -674,7 +462,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
{ {
int xi1 = poly1->GetX( ic1 ); int xi1 = poly1->GetX( ic1 );
int yi1 = poly1->GetY( ic1 ); int yi1 = poly1->GetY( ic1 );
int xf1, yf1, style1; int xf1, yf1;
if( ic1 < ie1 ) if( ic1 < ie1 )
{ {
...@@ -687,8 +475,6 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -687,8 +475,6 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
yf1 = poly1->GetY( is1 ); yf1 = poly1->GetY( is1 );
} }
style1 = poly1->GetSideStyle( ic1 );
for( int icont2 = 0; icont2<poly2->GetContoursCount(); icont2++ ) for( int icont2 = 0; icont2<poly2->GetContoursCount(); icont2++ )
{ {
int is2 = poly2->GetContourStart( icont2 ); int is2 = poly2->GetContourStart( icont2 );
...@@ -698,7 +484,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -698,7 +484,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
{ {
int xi2 = poly2->GetX( ic2 ); int xi2 = poly2->GetX( ic2 );
int yi2 = poly2->GetY( ic2 ); int yi2 = poly2->GetY( ic2 );
int xf2, yf2, style2; int xf2, yf2;
if( ic2 < ie2 ) if( ic2 < ie2 )
{ {
...@@ -711,37 +497,20 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -711,37 +497,20 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
yf2 = poly2->GetY( is2 ); yf2 = poly2->GetY( is2 );
} }
style2 = poly2->GetSideStyle( ic2 ); int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, CPolyLine::STRAIGHT,
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1, xi2, yi2, xf2, yf2, CPolyLine::STRAIGHT );
xi2, yi2, xf2, yf2, style2 );
if( n_int ) if( n_int )
{ {
bInt = true; bInt = true;
if( style1 != CPolyLine::STRAIGHT || style2 != CPolyLine::STRAIGHT )
bArcInt = true;
break; break;
} }
} }
if( bArcInt )
break;
} }
if( bArcInt )
break;
} }
if( bArcInt )
break;
} }
if( !bInt ) if( !bInt )
{ {
if( bArcInt )
return 0;
// If a contour is inside an other contour, no segments intersects, but the zones // If a contour is inside an other contour, no segments intersects, but the zones
// can be combined test a corner inside an outline (only one corner is enought) // can be combined test a corner inside an outline (only one corner is enought)
for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ ) for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ )
...@@ -769,9 +538,6 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -769,9 +538,6 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
return 0; return 0;
} }
if( bArcInt )
return 2;
return 1; return 1;
} }
...@@ -779,24 +545,22 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -779,24 +545,22 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
/** /**
* Function CombineAreas * Function CombineAreas
* Merge 2 copper areas (which are expected intersecting) * Merge 2 copper areas (which are expected intersecting)
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas
* commands can be NULL * (useful for undo command)
* @param area_ref = the main area (zone) * @param area_ref = the main area (zone)
* @param area_to_combine = the zone that can be merged with area_ref * @param area_to_combine = the zone that can be merged with area_ref
* area_ref must be BEFORE area_to_combine * area_ref must be BEFORE area_to_combine
* area_to_combine will be deleted, if areas are combined * area_to_combine will be deleted, if areas are combined
* @return : 0 if no intersection * @return : true if area_to_combine is combined with area_ref (and therefore be deleted)
* 1 if intersection
* 2 if arcs intersect (Currently not supported)
*/ */
int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_ref, bool BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_ref,
ZONE_CONTAINER* area_to_combine ) ZONE_CONTAINER* area_to_combine )
{ {
if( area_ref == area_to_combine ) if( area_ref == area_to_combine )
{ {
wxASSERT( 0 ); wxASSERT( 0 );
return 0; return false;
} }
// polygons intersect, combine them // polygons intersect, combine them
...@@ -920,7 +684,7 @@ int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_r ...@@ -920,7 +684,7 @@ int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_r
area_ref->utility = 1; area_ref->utility = 1;
area_ref->m_Poly->Hatch(); area_ref->m_Poly->Hatch();
return 1; return true;
} }
...@@ -1054,8 +818,6 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E ...@@ -1054,8 +818,6 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
ay2 = refSmoothedPoly->GetY( ic + 1 ); ay2 = refSmoothedPoly->GetY( ic + 1 );
} }
int astyle = refSmoothedPoly->GetSideStyle( ic );
for( int icont2 = 0; icont2 < testSmoothedPoly->GetContoursCount(); icont2++ ) for( int icont2 = 0; icont2 < testSmoothedPoly->GetContoursCount(); icont2++ )
{ {
int ic_start2 = testSmoothedPoly->GetContourStart( icont2 ); int ic_start2 = testSmoothedPoly->GetContourStart( icont2 );
...@@ -1078,13 +840,13 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E ...@@ -1078,13 +840,13 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
by2 = testSmoothedPoly->GetY( ic2 + 1 ); by2 = testSmoothedPoly->GetY( ic2 + 1 );
} }
int bstyle = testSmoothedPoly->GetSideStyle( ic2 );
int x, y; int x, y;
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, bstyle, int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
CPolyLine::STRAIGHT,
0, 0,
ax1, ay1, ax2, ax1, ay1, ax2, ay2,
ay2, astyle, CPolyLine::STRAIGHT,
0, 0,
zone2zoneClearance, zone2zoneClearance,
&x, &y ); &x, &y );
...@@ -1196,7 +958,6 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex ) ...@@ -1196,7 +958,6 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
} }
// now test spacing between areas // now test spacing between areas
int astyle = CPolyLine::STRAIGHT;
int ax1 = start.x; int ax1 = start.x;
int ay1 = start.y; int ay1 = start.y;
int ax2 = end.x; int ax2 = end.x;
...@@ -1224,11 +985,10 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex ) ...@@ -1224,11 +985,10 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
by2 = area_to_test->m_Poly->GetY( ic2 + 1 ); by2 = area_to_test->m_Poly->GetY( ic2 + 1 );
} }
int bstyle = area_to_test->m_Poly->GetSideStyle( ic2 );
int x, y; // variables containing the intersecting point coordinates int x, y; // variables containing the intersecting point coordinates
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, bstyle, int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, CPolyLine::STRAIGHT,
0, 0,
ax1, ay1, ax2, ay2, astyle, ax1, ay1, ax2, ay2, CPolyLine::STRAIGHT,
0, 0,
zone_clearance, zone_clearance,
&x, &y ); &x, &y );
......
...@@ -57,10 +57,10 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false ); ...@@ -57,10 +57,10 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false );
* because copper areas have only one outside contour * because copper areas have only one outside contour
* Therefore, if this results in new CPolyLines, return them as std::vector pa * Therefore, if this results in new CPolyLines, return them as std::vector pa
* @param aExtraPolyList: pointer on a std::vector<CPolyLine*> to store extra CPolyLines * @param aExtraPolyList: pointer on a std::vector<CPolyLine*> to store extra CPolyLines
* @param bRetainArcs == true, try to retain arcs in polys * (when after normalization, there is more than one polygon with holes)
* @return number of external contours, or -1 if error * @return number of external contours, or -1 if error
*/ */
int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool bRetainArcs ) int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList )
{ {
std::vector<CArc> arc_array; std::vector<CArc> arc_array;
std::vector <void*> hole_array; // list of holes std::vector <void*> hole_array; // list of holes
...@@ -74,10 +74,7 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool ...@@ -74,10 +74,7 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
* will be converted in non self crossing polygons by inserting extra points at the crossing locations * will be converted in non self crossing polygons by inserting extra points at the crossing locations
* True holes are combined if possible * True holes are combined if possible
*/ */
if( bRetainArcs ) MakeKboolPoly();
MakeKboolPoly( &arc_array );
else
MakeKboolPoly( NULL );
UnHatch(); UnHatch();
...@@ -203,16 +200,13 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool ...@@ -203,16 +200,13 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
{ {
int x = (*hole)[ii]; ii++; int x = (*hole)[ii]; ii++;
int y = (*hole)[ii]; int y = (*hole)[ii];
polyline->AppendCorner( x, y, STRAIGHT, false ); polyline->AppendCorner( x, y );
} }
polyline->CloseLastContour(); polyline->CloseLastContour();
} }
} }
if( bRetainArcs )
RestoreArcs( &arc_array, aExtraPolyList );
delete m_Kbool_Poly_Engine; delete m_Kbool_Poly_Engine;
m_Kbool_Poly_Engine = NULL; m_Kbool_Poly_Engine = NULL;
...@@ -265,10 +259,9 @@ int CPolyLine::AddPolygonsToBoolEng( Bool_Engine* aBooleng, GroupType aGroup ) ...@@ -265,10 +259,9 @@ int CPolyLine::AddPolygonsToBoolEng( Bool_Engine* aBooleng, GroupType aGroup )
* fill a kbool engine with a closed polyline contour * fill a kbool engine with a closed polyline contour
* approximates arcs with multiple straight-line segments * approximates arcs with multiple straight-line segments
* combining intersecting contours if possible * combining intersecting contours if possible
* @param arc_array : return corners computed from arcs approximations in arc_array
* @return error: 0 if Ok, 1 if error * @return error: 0 if Ok, 1 if error
*/ */
int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array ) int CPolyLine::MakeKboolPoly()
{ {
if( m_Kbool_Poly_Engine ) if( m_Kbool_Poly_Engine )
{ {
...@@ -276,6 +269,8 @@ int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array ) ...@@ -276,6 +269,8 @@ int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array )
m_Kbool_Poly_Engine = NULL; m_Kbool_Poly_Engine = NULL;
} }
std::vector<CArc>* arc_array = NULL; // Remove me
if( !GetClosed() ) if( !GetClosed() )
return 1; // error return 1; // error
...@@ -604,194 +599,23 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) ...@@ -604,194 +599,23 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles )
} }
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* pa, bool bRetainArcs ) /**
* Function NormalizeAreaOutlines
* Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s)
* @param aNewPolygonList = a std::vector<CPolyLine*> reference where to store new CPolyLine
* needed by the normalization
* @return the polygon count (always >= 1, becuse there is at lesat one polygon)
* There are new polygons only if the polygon count is > 1
*/
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList )
{ {
return NormalizeWithKbool( pa, bRetainArcs ); return NormalizeWithKbool( aNewPolygonList );
} }
// Restore arcs to a polygon where they were replaced with steps /* initialize a contour
// If pa != NULL, also use polygons in pa array * set layer, hatch style, and starting point
// */
int CPolyLine::RestoreArcs( std::vector<CArc>* arc_array, std::vector<CPolyLine*>* pa )
{
// get poly info
int n_polys = 1;
if( pa )
n_polys += pa->size();
CPolyLine* poly;
// undraw polys and clear m_utility flag for all corners
for( int ip = 0; ip<n_polys; ip++ )
{
if( ip == 0 )
poly = this;
else
poly = (*pa)[ip - 1];
poly->UnHatch();
for( int ic = 0; ic<poly->GetNumCorners(); ic++ )
poly->SetUtility( ic, 0 );
// clear m_utility flag
}
// find arcs and replace them
bool bFound;
int arc_start = 0;
int arc_end = 0;
for( unsigned iarc = 0; iarc<arc_array->size(); iarc++ )
{
int arc_xi = (*arc_array)[iarc].xi;
int arc_yi = (*arc_array)[iarc].yi;
int arc_xf = (*arc_array)[iarc].xf;
int arc_yf = (*arc_array)[iarc].yf;
int n_steps = (*arc_array)[iarc].n_steps;
int style = (*arc_array)[iarc].style;
bFound = false;
// loop through polys
for( int ip = 0; ip<n_polys; ip++ )
{
if( ip == 0 )
poly = this;
else
poly = (*pa)[ip - 1];
int polycount = poly->GetContoursCount();
for( int icont = 0; icont < polycount; icont++ )
{
int ic_start = poly->GetContourStart( icont );
int ic_end = poly->GetContourEnd( icont );
if( (ic_end - ic_start) > n_steps )
{
for( int ic = ic_start; ic<=ic_end; ic++ )
{
int ic_next = ic + 1;
if( ic_next > ic_end )
ic_next = ic_start;
int xi = poly->GetX( ic );
int yi = poly->GetY( ic );
if( xi == arc_xi && yi == arc_yi )
{
// test for forward arc
int ic2 = ic + n_steps;
if( ic2 > ic_end )
ic2 = ic2 - ic_end + ic_start - 1;
int xf = poly->GetX( ic2 );
int yf = poly->GetY( ic2 );
if( xf == arc_xf && yf == arc_yf )
{
// arc from ic to ic2
bFound = true;
arc_start = ic;
arc_end = ic2;
}
else
{
// try reverse arc
ic2 = ic - n_steps;
if( ic2 < ic_start )
ic2 = ic2 - ic_start + ic_end + 1;
xf = poly->GetX( ic2 );
yf = poly->GetY( ic2 );
if( xf == arc_xf && yf == arc_yf )
{
// arc from ic2 to ic
bFound = true;
arc_start = ic2;
arc_end = ic;
style = 3 - style;
}
}
if( bFound )
{
poly->m_SideStyle[arc_start] = style;
// mark corners for deletion from arc_start+1 to arc_end-1
for( int i = arc_start + 1; i!=arc_end; )
{
if( i > ic_end )
i = ic_start;
poly->SetUtility( i, 1 );
if( i == ic_end )
i = ic_start;
else
i++;
}
break;
}
}
if( bFound )
break;
}
}
if( bFound )
break;
}
}
if( bFound )
(*arc_array)[iarc].bFound = true;
}
// now delete all marked corners
for( int ip = 0; ip<n_polys; ip++ )
{
if( ip == 0 )
poly = this;
else
poly = (*pa)[ip - 1];
for( int ic = poly->GetNumCorners() - 1; ic>=0; ic-- )
{
if( poly->GetUtility( ic ) )
poly->DeleteCorner( ic, false );
}
}
return 0;
}
// initialize new polyline
// set layer, width, selection box size, starting point, id and pointer
//
// if sel_box = 0, don't create selection elements at all
//
// if polyline is board outline, enter with:
// id.type = ID_BOARD
// id.st = ID_BOARD_OUTLINE
// id.i = 0
// ptr = NULL
//
// if polyline is copper area, enter with:
// id.type = ID_NET;
// id.st = ID_AREA
// id.i = index to area
// ptr = pointer to net
//
void CPolyLine::Start( int layer, int x, int y, int hatch ) void CPolyLine::Start( int layer, int x, int y, int hatch )
{ {
m_layer = layer; m_layer = layer;
...@@ -806,7 +630,7 @@ void CPolyLine::Start( int layer, int x, int y, int hatch ) ...@@ -806,7 +630,7 @@ void CPolyLine::Start( int layer, int x, int y, int hatch )
// add a corner to unclosed polyline // add a corner to unclosed polyline
// //
void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw ) void CPolyLine::AppendCorner( int x, int y )
{ {
UnHatch(); UnHatch();
CPolyPt poly_pt( x, y ); CPolyPt poly_pt( x, y );
...@@ -814,13 +638,10 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw ) ...@@ -814,13 +638,10 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw )
// add entries for new corner and side // add entries for new corner and side
m_CornersList.push_back( poly_pt ); m_CornersList.push_back( poly_pt );
m_SideStyle.push_back( style ); m_SideStyle.push_back( STRAIGHT );
if( m_CornersList.size() > 0 && !m_CornersList[m_CornersList.size() - 1].end_contour ) if( m_CornersList.size() > 0 && !m_CornersList[m_CornersList.size() - 1].end_contour )
m_SideStyle[m_CornersList.size() - 1] = style; m_SideStyle[m_CornersList.size() - 1] = STRAIGHT;
if( bDraw )
Hatch();
} }
...@@ -845,7 +666,7 @@ void CPolyLine::MoveCorner( int ic, int x, int y ) ...@@ -845,7 +666,7 @@ void CPolyLine::MoveCorner( int ic, int x, int y )
// delete corner and adjust arrays // delete corner and adjust arrays
// //
void CPolyLine::DeleteCorner( int ic, bool bDraw ) void CPolyLine::DeleteCorner( int ic )
{ {
UnHatch(); UnHatch();
int icont = GetContour( ic ); int icont = GetContour( ic );
...@@ -876,9 +697,6 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) ...@@ -876,9 +697,6 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw )
// delete the entire contour // delete the entire contour
RemoveContour( icont ); RemoveContour( icont );
} }
if( bDraw )
Hatch();
} }
...@@ -1683,7 +1501,8 @@ void CPolyLine::SetEndContour( int ic, bool end_contour ) ...@@ -1683,7 +1501,8 @@ void CPolyLine::SetEndContour( int ic, bool end_contour )
} }
/* /*
* AppendArc adds segments to current contour to approximate the given arc * AppendArc:
* adds segments to current contour to approximate the given arc
*/ */
void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ) void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num )
{ {
...@@ -1701,7 +1520,7 @@ void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int n ...@@ -1701,7 +1520,7 @@ void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int n
{ {
int x = KiROUND( xc + radius * cos( theta ) ); int x = KiROUND( xc + radius * cos( theta ) );
int y = KiROUND( yc + radius * sin( theta ) ); int y = KiROUND( yc + radius * sin( theta ) );
AppendCorner( x, y, STRAIGHT, 0 ); AppendCorner( x, y );
theta += th_d; theta += th_d;
} }
...@@ -2000,3 +1819,102 @@ void ConvertPolysListWithHolesToOnePolygon( const std::vector<CPolyPt>& aPolysL ...@@ -2000,3 +1819,102 @@ void ConvertPolysListWithHolesToOnePolygon( const std::vector<CPolyPt>& aPolysL
aOnePolyList.push_back( corner ); aOnePolyList.push_back( corner );
} }
} }
/**
* Function IsPolygonSelfIntersecting
* Test a CPolyLine for self-intersection of vertex (all contours).
*
* @return :
* false if no intersecting sides
* true if intersecting sides
* When a CPolyLine is self intersectic, it need to be normalized.
* (converted to non intersecting polygons)
*/
bool CPolyLine::IsPolygonSelfIntersecting()
{
// first, check for sides intersecting other sides
int n_cont = GetContoursCount();
// 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( GetCornerBounds( icont ) );
for( int icont = 0; icont<n_cont; icont++ )
{
int is_start = GetContourStart( icont );
int is_end = 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 x1i = GetX( is );
int y1i = GetY( is );
int x1f = GetX( is_next );
int y1f = 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 = GetContourStart( icont2 );
int is2_end = 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 x2i = GetX( is2 );
int y2i = GetY( is2 );
int x2f = GetX( is2_next );
int y2f = GetY( is2_next );
int ret = FindSegmentIntersections( x1i, y1i, x1f, y1f,
CPolyLine::STRAIGHT,
x2i, y2i, x2f, y2f,
CPolyLine::STRAIGHT );
if( ret )
{
// intersection between non-adjacent sides
return true;
}
}
}
}
}
}
}
return false;
}
...@@ -110,15 +110,32 @@ public: ...@@ -110,15 +110,32 @@ public:
CPolyLine(); CPolyLine();
~CPolyLine(); ~CPolyLine();
// functions for modifying polyline // functions for modifying the CPolyLine contours
/* initialize a contour
* set layer, hatch style, and starting point
*/
void Start( int layer, int x, int y, int hatch ); void Start( int layer, int x, int y, int hatch );
void AppendCorner( int x, int y, int style = STRAIGHT, bool bDraw = false );
void AppendCorner( int x, int y );
void InsertCorner( int ic, int x, int y ); void InsertCorner( int ic, int x, int y );
void DeleteCorner( int ic, bool bDraw = false ); void DeleteCorner( int ic );
void MoveCorner( int ic, int x, int y ); void MoveCorner( int ic, int x, int y );
void CloseLastContour(); void CloseLastContour();
void RemoveContour( int icont ); void RemoveContour( int icont );
/**
* Function IsPolygonSelfIntersecting
* Test a CPolyLine for self-intersection of vertex (all contours).
*
* @return :
* false if no intersecting sides
* true if intersecting sides
* When a CPolyLine is self intersectic, it need to be normalized.
* (converted to non intersecting polygons)
*/
bool IsPolygonSelfIntersecting();
/** /**
* Function Chamfer * Function Chamfer
* returns a chamfered version of a polygon. * returns a chamfered version of a polygon.
...@@ -206,10 +223,15 @@ public: ...@@ -206,10 +223,15 @@ public:
void SetHatchPitch( int pitch ) { m_hatchPitch = pitch; } void SetHatchPitch( int pitch ) { m_hatchPitch = pitch; }
int RestoreArcs( std::vector<CArc>* arc_array, std::vector<CPolyLine*>* pa = NULL ); /**
* Function NormalizeAreaOutlines
int NormalizeAreaOutlines( std::vector<CPolyLine*>* pa = NULL, * Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s)
bool bRetainArcs = false ); * @param aNewPolygonList = a std::vector<CPolyLine*> reference where to store new CPolyLine
* needed by the normalization
* @return the polygon count (always >= 1, becuse there is at lesat one polygon)
* There are new polygons only if the polygon count is > 1
*/
int NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList );
// KBOOL functions // KBOOL functions
...@@ -224,12 +246,9 @@ public: ...@@ -224,12 +246,9 @@ public:
/** /**
* Function MakeKboolPoly * Function MakeKboolPoly
* fill a kbool engine with a closed polyline contour * fill a kbool engine with a closed polyline contour
* approximates arcs with multiple straight-line segments
* combining intersecting contours if possible
* @param arc_array : return data on arcs in arc_array
* @return error: 0 if Ok, 1 if error * @return error: 0 if Ok, 1 if error
*/ */
int MakeKboolPoly( std::vector<CArc>* arc_array = NULL ); int MakeKboolPoly();
/** /**
* Function NormalizeWithKbool * Function NormalizeWithKbool
...@@ -240,10 +259,10 @@ public: ...@@ -240,10 +259,10 @@ public:
* because copper areas have only one outside contour * because copper areas have only one outside contour
* Therefore, if this results in new CPolyLines, return them as std::vector pa * Therefore, if this results in new CPolyLines, return them as std::vector pa
* @param aExtraPolyList: pointer on a std::vector<CPolyLine*> to store extra CPolyLines * @param aExtraPolyList: pointer on a std::vector<CPolyLine*> to store extra CPolyLines
* @param bRetainArcs == false, try to retain arcs in polys * (when after normalization, there is more than one polygon with holes)
* @return number of external contours, or -1 if error * @return number of contours, or -1 if error
*/ */
int NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool bRetainArcs ); int NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList );
// Bezier Support // Bezier Support
void AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3 ); void AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment