PolyLine and math_for_graphics code cleanup: remove arc support in CPolyLine class:
This is an obscure legacy code from FreePCB, never used, never tested, never maintained.
This commit is contained in:
commit
ef39c5f38e
|
@ -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:
|
||||||
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 :
|
bool OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
|
||||||
* -1 if arcs intersect other sides, so polygon can't be clipped
|
ZONE_CONTAINER* modified_area );
|
||||||
* 0 if no intersecting sides
|
|
||||||
* 1 if intersecting sides, polygon clipped
|
|
||||||
*/
|
|
||||||
int AreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
|
|
||||||
ZONE_CONTAINER* modified_area,
|
|
||||||
bool bMessageBoxArc,
|
|
||||||
bool bMessageBoxInt );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function CombineAllAreasInNet
|
* Function CombineAllAreasInNet
|
||||||
|
@ -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,19 +1124,17 @@ 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 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Test_Drc_Areas_Outlines_To_Areas_Outlines
|
* Function Test_Drc_Areas_Outlines_To_Areas_Outlines
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
|
#include <polygon_test_point_inside.h>
|
||||||
|
|
||||||
|
|
||||||
int D_PAD::m_PadSketchModePenSize = 0; // Pen size used to draw pads in sketch mode
|
int D_PAD::m_PadSketchModePenSize = 0; // Pen size used to draw pads in sketch mode
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <pcbnew.h>
|
#include <pcbnew.h>
|
||||||
#include <zones.h>
|
#include <zones.h>
|
||||||
#include <math_for_graphics.h>
|
#include <math_for_graphics.h>
|
||||||
|
#include <polygon_test_point_inside.h>
|
||||||
|
|
||||||
|
|
||||||
ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) :
|
ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) :
|
||||||
|
@ -65,7 +66,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 +102,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) :
|
||||||
|
|
||||||
|
|
||||||
utility = aZone.utility;
|
utility = aZone.utility;
|
||||||
utility2 = aZone.utility;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <class_zone.h>
|
#include <class_zone.h>
|
||||||
#include <class_marker_pcb.h>
|
#include <class_marker_pcb.h>
|
||||||
#include <math_for_graphics.h>
|
#include <math_for_graphics.h>
|
||||||
|
#include <polygon_test_point_inside.h>
|
||||||
|
|
||||||
|
|
||||||
/* compare 2 trapezoids (can be rectangle) and return true if distance > aDist
|
/* compare 2 trapezoids (can be rectangle) and return true if distance > aDist
|
||||||
|
|
|
@ -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 )
|
||||||
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*
|
||||||
|
|
||||||
// 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 )
|
||||||
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 )
|
||||||
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 )
|
||||||
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 );
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include <pcbnew.h>
|
#include <pcbnew.h>
|
||||||
#include <zones.h>
|
#include <zones.h>
|
||||||
|
#include <polygon_test_point_inside.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include <algorithm> // sort
|
#include <algorithm> // sort
|
||||||
|
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
|
@ -40,6 +39,7 @@
|
||||||
|
|
||||||
#include <pcbnew.h>
|
#include <pcbnew.h>
|
||||||
#include <zones.h>
|
#include <zones.h>
|
||||||
|
#include <polygon_test_point_inside.h>
|
||||||
|
|
||||||
static bool CmpZoneSubnetValue( const BOARD_CONNECTED_ITEM* a, const BOARD_CONNECTED_ITEM* b );
|
static bool CmpZoneSubnetValue( const BOARD_CONNECTED_ITEM* a, const BOARD_CONNECTED_ITEM* b );
|
||||||
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
|
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
|
||||||
|
|
|
@ -43,11 +43,7 @@
|
||||||
#include <drc_stuff.h>
|
#include <drc_stuff.h>
|
||||||
#include <math_for_graphics.h>
|
#include <math_for_graphics.h>
|
||||||
|
|
||||||
|
#define STRAIGHT 0 // To be remove after math_for_graphics code cleanup
|
||||||
static bool bDontShowSelfIntersectionArcsWarning;
|
|
||||||
static bool bDontShowSelfIntersectionWarning;
|
|
||||||
static bool bDontShowIntersectionArcsWarning;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function AddArea
|
* Function AddArea
|
||||||
|
@ -126,199 +122,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 )
|
// mark all areas as unmodified except this one, if modified
|
||||||
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
|
|
||||||
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,60 +168,45 @@ 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++ )
|
||||||
{
|
if( m_ZoneDescriptorList[ia]->GetLayer() == layer )
|
||||||
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
|
m_ZoneDescriptorList[ia]->BuildFilledPolysListData( this );
|
||||||
if( m_ZoneDescriptorList[ia]->GetLayer() == layer )
|
|
||||||
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:
|
||||||
|
@ -408,33 +221,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 +267,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 +284,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 +295,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 +352,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 +365,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 +374,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 +387,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,
|
||||||
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
|
xi2, yi2, xf2, yf2 );
|
||||||
xi2, yi2, xf2, yf2, style2 );
|
|
||||||
if( n_int )
|
if( n_int )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -640,7 +433,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 +447,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 +463,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 +476,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 +485,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 +498,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,
|
||||||
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
|
xi2, yi2, xf2, yf2 );
|
||||||
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 +539,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 +546,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 +685,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 +819,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 +841,11 @@ 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,
|
||||||
0,
|
0,
|
||||||
ax1, ay1, ax2,
|
ax1, ay1, ax2, ay2,
|
||||||
ay2, astyle,
|
|
||||||
0,
|
0,
|
||||||
zone2zoneClearance,
|
zone2zoneClearance,
|
||||||
&x, &y );
|
&x, &y );
|
||||||
|
@ -1196,7 +957,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 +984,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,
|
||||||
0,
|
0,
|
||||||
ax1, ay1, ax2, ay2, astyle,
|
ax1, ay1, ax2, ay2,
|
||||||
0,
|
0,
|
||||||
zone_clearance,
|
zone_clearance,
|
||||||
&x, &y );
|
&x, &y );
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#include <bezier_curves.h>
|
#include <bezier_curves.h>
|
||||||
#include <polygon_test_point_inside.h>
|
#include <polygon_test_point_inside.h>
|
||||||
#include <math_for_graphics.h>
|
#include <math_for_graphics.h>
|
||||||
|
#include <polygon_test_point_inside.h>
|
||||||
|
|
||||||
|
enum m_SideStyle { STRAIGHT }; // side styles
|
||||||
|
|
||||||
|
|
||||||
CPolyLine::CPolyLine()
|
CPolyLine::CPolyLine()
|
||||||
{
|
{
|
||||||
|
@ -57,12 +61,11 @@ 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 <void*> hole_array; // list of holes
|
std::vector <void*> hole_array; // list of holes
|
||||||
std::vector<int>* hole; // used to store corners for a given hole
|
std::vector<int>* hole; // used to store corners for a given hole
|
||||||
CPolyLine* polyline;
|
CPolyLine* polyline;
|
||||||
|
@ -74,10 +77,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();
|
||||||
|
|
||||||
|
@ -111,7 +111,6 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
|
||||||
{
|
{
|
||||||
// first external contour, replace this poly
|
// first external contour, replace this poly
|
||||||
m_CornersList.clear();
|
m_CornersList.clear();
|
||||||
m_SideStyle.clear();
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
while( m_Kbool_Poly_Engine->PolygonHasMorePoints() )
|
while( m_Kbool_Poly_Engine->PolygonHasMorePoints() )
|
||||||
|
@ -203,16 +202,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;
|
||||||
|
|
||||||
|
@ -263,12 +259,10 @@ int CPolyLine::AddPolygonsToBoolEng( Bool_Engine* aBooleng, GroupType aGroup )
|
||||||
/**
|
/**
|
||||||
* 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
|
* normalize self-intersecting contours
|
||||||
* 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 )
|
||||||
{
|
{
|
||||||
|
@ -279,15 +273,9 @@ int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array )
|
||||||
if( !GetClosed() )
|
if( !GetClosed() )
|
||||||
return 1; // error
|
return 1; // error
|
||||||
|
|
||||||
int n_arcs = 0;
|
|
||||||
int polycount = GetContoursCount();
|
int polycount = GetContoursCount();
|
||||||
int last_contour = polycount - 1;
|
int last_contour = polycount - 1;
|
||||||
|
|
||||||
if( arc_array )
|
|
||||||
arc_array->clear();
|
|
||||||
|
|
||||||
int iarc = 0;
|
|
||||||
|
|
||||||
for( int icont = 0; icont <= last_contour; icont++ )
|
for( int icont = 0; icont <= last_contour; icont++ )
|
||||||
{
|
{
|
||||||
// Fill a kbool engine for this contour,
|
// Fill a kbool engine for this contour,
|
||||||
|
@ -314,8 +302,6 @@ int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// first, calculate number of vertices in contour
|
|
||||||
int n_vertices = 0;
|
|
||||||
int ic_st = GetContourStart( icont );
|
int ic_st = GetContourStart( icont );
|
||||||
int ic_end = GetContourEnd( icont );
|
int ic_end = GetContourEnd( icont );
|
||||||
|
|
||||||
|
@ -325,159 +311,12 @@ int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array )
|
||||||
return 1; // error
|
return 1; // error
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int ic = ic_st; ic<=ic_end; ic++ )
|
// Enter this contour to booleng
|
||||||
|
for( int ic = ic_st; ic <= ic_end; ic++ )
|
||||||
{
|
{
|
||||||
int style = m_SideStyle[ic];
|
|
||||||
|
|
||||||
if( style == STRAIGHT )
|
|
||||||
n_vertices++;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// style is ARC_CW or ARC_CCW
|
|
||||||
int n = CArc::ARC_STEPS;
|
|
||||||
n_vertices += n;
|
|
||||||
n_arcs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now enter this contour to booleng
|
|
||||||
int ivtx = 0;
|
|
||||||
|
|
||||||
for( int ic = ic_st; ic<=ic_end; ic++ )
|
|
||||||
{
|
|
||||||
int style = m_SideStyle[ic];
|
|
||||||
int x1 = m_CornersList[ic].x;
|
int x1 = m_CornersList[ic].x;
|
||||||
int y1 = m_CornersList[ic].y;
|
int y1 = m_CornersList[ic].y;
|
||||||
int x2, y2;
|
booleng->AddPoint( x1, y1 );
|
||||||
|
|
||||||
if( ic < ic_end )
|
|
||||||
{
|
|
||||||
x2 = m_CornersList[ic + 1].x;
|
|
||||||
y2 = m_CornersList[ic + 1].y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x2 = m_CornersList[ic_st].x;
|
|
||||||
y2 = m_CornersList[ic_st].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( style == STRAIGHT )
|
|
||||||
{
|
|
||||||
booleng->AddPoint( x1, y1 );
|
|
||||||
ivtx++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// style is arc_cw or arc_ccw
|
|
||||||
int n; // number of steps for arcs
|
|
||||||
n = CArc::ARC_STEPS;
|
|
||||||
double xo, yo, theta1, theta2, a, b;
|
|
||||||
a = fabs( (double) (x1 - x2) );
|
|
||||||
b = fabs( (double) (y1 - y2) );
|
|
||||||
|
|
||||||
if( style == CPolyLine::ARC_CW )
|
|
||||||
{
|
|
||||||
// clockwise arc (ie.quadrant of ellipse)
|
|
||||||
if( x2 > x1 && y2 > y1 )
|
|
||||||
{
|
|
||||||
// first quadrant, draw second quadrant of ellipse
|
|
||||||
xo = x2;
|
|
||||||
yo = y1;
|
|
||||||
theta1 = M_PI;
|
|
||||||
theta2 = M_PI / 2.0;
|
|
||||||
}
|
|
||||||
else if( x2 < x1 && y2 > y1 )
|
|
||||||
{
|
|
||||||
// second quadrant, draw third quadrant of ellipse
|
|
||||||
xo = x1;
|
|
||||||
yo = y2;
|
|
||||||
theta1 = 3.0 * M_PI / 2.0;
|
|
||||||
theta2 = M_PI;
|
|
||||||
}
|
|
||||||
else if( x2 < x1 && y2 < y1 )
|
|
||||||
{
|
|
||||||
// third quadrant, draw fourth quadrant of ellipse
|
|
||||||
xo = x2;
|
|
||||||
yo = y1;
|
|
||||||
theta1 = 2.0 * M_PI;
|
|
||||||
theta2 = 3.0 * M_PI / 2.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xo = x1; // fourth quadrant, draw first quadrant of ellipse
|
|
||||||
yo = y2;
|
|
||||||
theta1 = M_PI / 2.0;
|
|
||||||
theta2 = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// counter-clockwise arc
|
|
||||||
if( x2 > x1 && y2 > y1 )
|
|
||||||
{
|
|
||||||
xo = x1; // first quadrant, draw fourth quadrant of ellipse
|
|
||||||
yo = y2;
|
|
||||||
theta1 = 3.0 * M_PI / 2.0;
|
|
||||||
theta2 = 2.0 * M_PI;
|
|
||||||
}
|
|
||||||
else if( x2 < x1 && y2 > y1 )
|
|
||||||
{
|
|
||||||
xo = x2; // second quadrant
|
|
||||||
yo = y1;
|
|
||||||
theta1 = 0.0;
|
|
||||||
theta2 = M_PI / 2.0;
|
|
||||||
}
|
|
||||||
else if( x2 < x1 && y2 < y1 )
|
|
||||||
{
|
|
||||||
xo = x1; // third quadrant
|
|
||||||
yo = y2;
|
|
||||||
theta1 = M_PI / 2.0;
|
|
||||||
theta2 = M_PI;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xo = x2; // fourth quadrant
|
|
||||||
yo = y1;
|
|
||||||
theta1 = M_PI;
|
|
||||||
theta2 = 3.0 * M_PI / 2.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now write steps for arc
|
|
||||||
if( arc_array )
|
|
||||||
{
|
|
||||||
CArc new_arc;
|
|
||||||
new_arc.style = style;
|
|
||||||
new_arc.n_steps = n;
|
|
||||||
new_arc.xi = x1;
|
|
||||||
new_arc.yi = y1;
|
|
||||||
new_arc.xf = x2;
|
|
||||||
new_arc.yf = y2;
|
|
||||||
arc_array->push_back( new_arc );
|
|
||||||
iarc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( int is = 0; is<n; is++ )
|
|
||||||
{
|
|
||||||
double theta = theta1 + ( (theta2 - theta1) * (double) is ) / n;
|
|
||||||
double x = xo + a* cos( theta );
|
|
||||||
double y = yo + b* sin( theta );
|
|
||||||
|
|
||||||
if( is == 0 )
|
|
||||||
{
|
|
||||||
x = x1;
|
|
||||||
y = y1;
|
|
||||||
}
|
|
||||||
|
|
||||||
booleng->AddPoint( x, y );
|
|
||||||
ivtx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( n_vertices != ivtx )
|
|
||||||
{
|
|
||||||
wxASSERT( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close list added to the bool engine
|
// close list added to the bool engine
|
||||||
|
@ -604,194 +443,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;
|
||||||
|
@ -800,27 +468,19 @@ void CPolyLine::Start( int layer, int x, int y, int hatch )
|
||||||
poly_pt.end_contour = false;
|
poly_pt.end_contour = false;
|
||||||
|
|
||||||
m_CornersList.push_back( poly_pt );
|
m_CornersList.push_back( poly_pt );
|
||||||
m_SideStyle.push_back( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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 );
|
||||||
poly_pt.end_contour = false;
|
poly_pt.end_contour = false;
|
||||||
|
|
||||||
// add entries for new corner and side
|
// add entries for new corner
|
||||||
m_CornersList.push_back( poly_pt );
|
m_CornersList.push_back( poly_pt );
|
||||||
m_SideStyle.push_back( style );
|
|
||||||
|
|
||||||
if( m_CornersList.size() > 0 && !m_CornersList[m_CornersList.size() - 1].end_contour )
|
|
||||||
m_SideStyle[m_CornersList.size() - 1] = style;
|
|
||||||
|
|
||||||
if( bDraw )
|
|
||||||
Hatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -845,40 +505,32 @@ 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 );
|
||||||
int istart = GetContourStart( icont );
|
|
||||||
int iend = GetContourEnd( icont );
|
int iend = GetContourEnd( icont );
|
||||||
bool bClosed = icont < GetContoursCount() - 1 || GetClosed();
|
bool closed = icont < GetContoursCount() - 1 || GetClosed();
|
||||||
|
|
||||||
if( !bClosed )
|
if( !closed )
|
||||||
{
|
{
|
||||||
// open contour, must be last contour
|
// open contour, must be last contour
|
||||||
m_CornersList.erase( m_CornersList.begin() + ic );
|
m_CornersList.erase( m_CornersList.begin() + ic );
|
||||||
|
|
||||||
if( ic != istart )
|
|
||||||
m_SideStyle.erase( m_SideStyle.begin() + ic - 1 );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// closed contour
|
// closed contour
|
||||||
m_CornersList.erase( m_CornersList.begin() + ic );
|
m_CornersList.erase( m_CornersList.begin() + ic );
|
||||||
m_SideStyle.erase( m_SideStyle.begin() + ic );
|
|
||||||
|
|
||||||
if( ic == iend )
|
if( ic == iend )
|
||||||
m_CornersList[ic - 1].end_contour = true;
|
m_CornersList[ic - 1].end_contour = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bClosed && GetContourSize( icont ) < 3 )
|
if( closed && GetContourSize( icont ) < 3 )
|
||||||
{
|
{
|
||||||
// delete the entire contour
|
// delete the entire contour
|
||||||
RemoveContour( icont );
|
RemoveContour( icont );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bDraw )
|
|
||||||
Hatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -907,7 +559,6 @@ void CPolyLine::RemoveContour( int icont )
|
||||||
{
|
{
|
||||||
// remove last contour
|
// remove last contour
|
||||||
m_CornersList.erase( m_CornersList.begin() + istart, m_CornersList.end() );
|
m_CornersList.erase( m_CornersList.begin() + istart, m_CornersList.end() );
|
||||||
m_SideStyle.erase( m_SideStyle.begin() + istart, m_SideStyle.end() );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -915,7 +566,6 @@ void CPolyLine::RemoveContour( int icont )
|
||||||
for( int ic = iend; ic>=istart; ic-- )
|
for( int ic = iend; ic>=istart; ic-- )
|
||||||
{
|
{
|
||||||
m_CornersList.erase( m_CornersList.begin() + ic );
|
m_CornersList.erase( m_CornersList.begin() + ic );
|
||||||
m_SideStyle.erase( m_SideStyle.begin() + ic );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1140,7 +790,6 @@ void CPolyLine::RemoveAllContours( void )
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
m_CornersList.clear();
|
m_CornersList.clear();
|
||||||
m_SideStyle.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1157,12 +806,10 @@ void CPolyLine::InsertCorner( int ic, int x, int y )
|
||||||
if( (unsigned) (ic) >= m_CornersList.size() )
|
if( (unsigned) (ic) >= m_CornersList.size() )
|
||||||
{
|
{
|
||||||
m_CornersList.push_back( CPolyPt( x, y ) );
|
m_CornersList.push_back( CPolyPt( x, y ) );
|
||||||
m_SideStyle.push_back( STRAIGHT );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_CornersList.insert( m_CornersList.begin() + ic + 1, CPolyPt( x, y ) );
|
m_CornersList.insert( m_CornersList.begin() + ic + 1, CPolyPt( x, y ) );
|
||||||
m_SideStyle.insert( m_SideStyle.begin() + ic + 1, STRAIGHT );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (unsigned) (ic + 1) < m_CornersList.size() )
|
if( (unsigned) (ic + 1) < m_CornersList.size() )
|
||||||
|
@ -1348,41 +995,6 @@ int CPolyLine::GetContourSize( int icont )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CPolyLine::SetSideStyle( int is, int style )
|
|
||||||
{
|
|
||||||
UnHatch();
|
|
||||||
wxPoint p1, p2;
|
|
||||||
|
|
||||||
if( is == (int) (m_CornersList.size() - 1) )
|
|
||||||
{
|
|
||||||
p1.x = m_CornersList[m_CornersList.size() - 1].x;
|
|
||||||
p1.y = m_CornersList[m_CornersList.size() - 1].y;
|
|
||||||
p2.x = m_CornersList[0].x;
|
|
||||||
p2.y = m_CornersList[0].y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p1.x = m_CornersList[is].x;
|
|
||||||
p1.y = m_CornersList[is].y;
|
|
||||||
p2.x = m_CornersList[is + 1].x;
|
|
||||||
p2.y = m_CornersList[is + 1].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( p1.x == p2.x || p1.y == p2.y )
|
|
||||||
m_SideStyle[is] = STRAIGHT;
|
|
||||||
else
|
|
||||||
m_SideStyle[is] = style;
|
|
||||||
|
|
||||||
Hatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int CPolyLine::GetSideStyle( int is )
|
|
||||||
{
|
|
||||||
return m_SideStyle[is];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int CPolyLine::GetClosed()
|
int CPolyLine::GetClosed()
|
||||||
{
|
{
|
||||||
if( m_CornersList.size() == 0 )
|
if( m_CornersList.size() == 0 )
|
||||||
|
@ -1500,7 +1112,6 @@ void CPolyLine::Hatch()
|
||||||
m_CornersList[ic].x, m_CornersList[ic].y,
|
m_CornersList[ic].x, m_CornersList[ic].y,
|
||||||
m_CornersList[i_start_contour].x,
|
m_CornersList[i_start_contour].x,
|
||||||
m_CornersList[i_start_contour].y,
|
m_CornersList[i_start_contour].y,
|
||||||
m_SideStyle[ic],
|
|
||||||
&x, &y, &x2, &y2 );
|
&x, &y, &x2, &y2 );
|
||||||
i_start_contour = ic + 1;
|
i_start_contour = ic + 1;
|
||||||
}
|
}
|
||||||
|
@ -1509,7 +1120,6 @@ void CPolyLine::Hatch()
|
||||||
ok = FindLineSegmentIntersection( a, slope,
|
ok = FindLineSegmentIntersection( a, slope,
|
||||||
m_CornersList[ic].x, m_CornersList[ic].y,
|
m_CornersList[ic].x, m_CornersList[ic].y,
|
||||||
m_CornersList[ic + 1].x, m_CornersList[ic + 1].y,
|
m_CornersList[ic + 1].x, m_CornersList[ic + 1].y,
|
||||||
m_SideStyle[ic],
|
|
||||||
&x, &y, &x2, &y2 );
|
&x, &y, &x2, &y2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1625,8 +1235,6 @@ void CPolyLine::Copy( CPolyLine* src )
|
||||||
m_hatchPitch = src->m_hatchPitch;
|
m_hatchPitch = src->m_hatchPitch;
|
||||||
// copy corners, using vector copy
|
// copy corners, using vector copy
|
||||||
m_CornersList = src->m_CornersList;
|
m_CornersList = src->m_CornersList;
|
||||||
// copy side styles, using vector copy
|
|
||||||
m_SideStyle = src->m_SideStyle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1683,7 +1291,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 +1310,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1776,10 +1385,9 @@ int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth )
|
||||||
by2 = GetY( ic2 + 1 );
|
by2 = GetY( ic2 + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int bstyle = GetSideStyle( ic2 );
|
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, 0,
|
||||||
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, bstyle, 0,
|
|
||||||
aStart.x, aStart.y, aEnd.x, aEnd.y,
|
aStart.x, aStart.y, aEnd.x, aEnd.y,
|
||||||
CPolyLine::STRAIGHT, aWidth,
|
aWidth,
|
||||||
1, // min clearance, should be > 0
|
1, // min clearance, should be > 0
|
||||||
NULL, NULL );
|
NULL, NULL );
|
||||||
|
|
||||||
|
@ -1835,12 +1443,9 @@ int CPolyLine::Distance( const wxPoint& aPoint )
|
||||||
by2 = GetY( ic2 + 1 );
|
by2 = GetY( ic2 + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we expect only straight lines for vertices
|
|
||||||
// (no arcs, not yet supported in Pcbnew)
|
|
||||||
int d = KiROUND( GetPointToLineSegmentDistance( aPoint.x, aPoint.y,
|
int d = KiROUND( GetPointToLineSegmentDistance( aPoint.x, aPoint.y,
|
||||||
bx1, by1, bx2, by2 ) );
|
bx1, by1, bx2, by2 ) );
|
||||||
|
|
||||||
|
|
||||||
if( distance > d )
|
if( distance > d )
|
||||||
distance = d;
|
distance = d;
|
||||||
|
|
||||||
|
@ -2000,3 +1605,100 @@ 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,
|
||||||
|
x2i, y2i, x2f, y2f );
|
||||||
|
if( ret )
|
||||||
|
{
|
||||||
|
// intersection between non-adjacent sides
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
#include <polygons_defs.h>
|
#include <polygons_defs.h>
|
||||||
|
|
||||||
// inflection modes for DS_LINE and DS_LINE_VERTEX, used in math_for_graphics.cpp
|
// inflection modes for DS_LINE and DS_LINE_VERTEX, used in math_for_graphics.cpp
|
||||||
enum {
|
/*enum {
|
||||||
IM_NONE = 0,
|
IM_NONE = 0,
|
||||||
IM_90_45,
|
IM_90_45,
|
||||||
IM_45_90,
|
IM_45_90,
|
||||||
IM_90
|
IM_90
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
class CRect
|
class CRect
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
class CArc
|
class CArc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -67,7 +68,7 @@ public:
|
||||||
int n_steps; // number of straight-line segments in gpc_poly
|
int n_steps; // number of straight-line segments in gpc_poly
|
||||||
bool bFound;
|
bool bFound;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
class CPolyPt : public wxPoint
|
class CPolyPt : public wxPoint
|
||||||
{
|
{
|
||||||
|
@ -98,27 +99,41 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#include <polygon_test_point_inside.h>
|
|
||||||
|
|
||||||
class CPolyLine
|
class CPolyLine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum m_SideStyle { STRAIGHT, ARC_CW, ARC_CCW }; // side styles
|
|
||||||
enum HATCH_STYLE { NO_HATCH, DIAGONAL_FULL, DIAGONAL_EDGE }; // hatch styles
|
enum HATCH_STYLE { NO_HATCH, DIAGONAL_FULL, DIAGONAL_EDGE }; // hatch styles
|
||||||
|
|
||||||
// constructors/destructor
|
// constructors/destructor
|
||||||
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.
|
||||||
|
@ -180,7 +195,6 @@ public:
|
||||||
|
|
||||||
int GetUtility( int ic ) { return m_CornersList[ic].m_utility; };
|
int GetUtility( int ic ) { return m_CornersList[ic].m_utility; };
|
||||||
void SetUtility( int ic, int utility ) { m_CornersList[ic].m_utility = utility; };
|
void SetUtility( int ic, int utility ) { m_CornersList[ic].m_utility = utility; };
|
||||||
int GetSideStyle( int is );
|
|
||||||
|
|
||||||
int GetHatchPitch() { return m_hatchPitch; }
|
int GetHatchPitch() { return m_hatchPitch; }
|
||||||
static int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils
|
static int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils
|
||||||
|
@ -197,7 +211,6 @@ public:
|
||||||
void SetX( int ic, int x );
|
void SetX( int ic, int x );
|
||||||
void SetY( int ic, int y );
|
void SetY( int ic, int y );
|
||||||
void SetEndContour( int ic, bool end_contour );
|
void SetEndContour( int ic, bool end_contour );
|
||||||
void SetSideStyle( int is, int style );
|
|
||||||
|
|
||||||
void SetHatchStyle( enum HATCH_STYLE style )
|
void SetHatchStyle( enum HATCH_STYLE style )
|
||||||
{
|
{
|
||||||
|
@ -206,10 +219,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 +242,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 +255,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 );
|
||||||
|
@ -280,7 +295,6 @@ private:
|
||||||
Bool_Engine* m_Kbool_Poly_Engine; // polygons set in kbool engine data
|
Bool_Engine* m_Kbool_Poly_Engine; // polygons set in kbool engine data
|
||||||
public:
|
public:
|
||||||
std::vector <CPolyPt> m_CornersList; // array of points for corners
|
std::vector <CPolyPt> m_CornersList; // array of points for corners
|
||||||
std::vector <int> m_SideStyle; // array of styles for sides
|
|
||||||
std::vector <CSegment> m_HatchLines; // hatch lines showing the polygon area
|
std::vector <CSegment> m_HatchLines; // hatch lines showing the polygon area
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,5 @@
|
||||||
// math stuff for graphics, from FreePCB
|
// math stuff for graphics, from FreePCB
|
||||||
|
|
||||||
|
|
||||||
// math stuff for graphics
|
|
||||||
bool Quadratic( double a, double b, double c, double *x1, double *x2 );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function TestLineHit
|
* Function TestLineHit
|
||||||
* test for hit on line segment i.e. a point within a given distance from segment
|
* test for hit on line segment i.e. a point within a given distance from segment
|
||||||
|
@ -14,13 +10,23 @@ bool Quadratic( double a, double b, double c, double *x1, double *x2 );
|
||||||
*/
|
*/
|
||||||
bool TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist );
|
bool TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist );
|
||||||
|
|
||||||
int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf, int style,
|
/* Function FindLineSegmentIntersection
|
||||||
|
* find intersection between line y = a + bx and line segment (xi,yi) to (xf,yf)
|
||||||
|
* if b > DBL_MAX/10, assume vertical line at x = a
|
||||||
|
* return false if no intersection or true if intersect
|
||||||
|
* return coords of intersections in *x1, *y1, *x2, *y2
|
||||||
|
* if no intersection, returns min distance in dist
|
||||||
|
*/
|
||||||
|
bool FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf,
|
||||||
double * x1, double * y1, double * x2, double * y2, double * dist=NULL );
|
double * x1, double * y1, double * x2, double * y2, double * dist=NULL );
|
||||||
int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style,
|
|
||||||
int xi2, int yi2, int xf2, int yf2, int style2,
|
/* Function FindSegmentIntersections
|
||||||
double x[]=NULL, double y[]=NULL );
|
* find intersections between line segment (xi,yi) to (xf,yf)
|
||||||
bool FindLineEllipseIntersections( double a, double b, double c, double d, double *x1, double *x2 );
|
* and line segment (xi2,yi2) to (xf2,yf2)
|
||||||
bool FindVerticalLineEllipseIntersections( double a, double b, double x, double *y1, double *y2 );
|
* returns true if intersection found
|
||||||
|
*/
|
||||||
|
bool FindSegmentIntersections( int xi, int yi, int xf, int yf,
|
||||||
|
int xi2, int yi2, int xf2, int yf2 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function TestForIntersectionOfStraightLineSegments
|
* Function TestForIntersectionOfStraightLineSegments
|
||||||
|
@ -39,8 +45,13 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
|
||||||
int x2i, int y2i, int x2f, int y2f,
|
int x2i, int y2i, int x2f, int y2f,
|
||||||
int * x=NULL, int * y=NULL, double * dist=NULL );
|
int * x=NULL, int * y=NULL, double * dist=NULL );
|
||||||
|
|
||||||
int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1,
|
/* Function GetClearanceBetweenSegments
|
||||||
int x2i, int y2i, int x2f, int y2f, int style2, int w2,
|
* Get clearance between 2 segments
|
||||||
|
* Returns coordinates of the closest point between these 2 segments in x, y
|
||||||
|
* If clearance > max_cl, just returns max_cl+1 and doesn't return x,y
|
||||||
|
*/
|
||||||
|
int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int w1,
|
||||||
|
int x2i, int y2i, int x2f, int y2f, int w2,
|
||||||
int max_cl, int * x, int * y );
|
int max_cl, int * x, int * y );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +63,11 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
|
||||||
*/
|
*/
|
||||||
double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf );
|
double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf );
|
||||||
|
|
||||||
|
/* Function GetPointToLineDistance
|
||||||
|
* Get min. distance from (x,y) to line y = a + bx
|
||||||
|
* if b > DBL_MAX/10, assume vertical line at x = a
|
||||||
|
* returns closest point on line in xpp, ypp
|
||||||
|
*/
|
||||||
double GetPointToLineDistance( double a, double b, int x, int y, double * xp=NULL, double * yp=NULL );
|
double GetPointToLineDistance( double a, double b, int x, int y, double * xp=NULL, double * yp=NULL );
|
||||||
|
|
||||||
double Distance( double x1, double y1, double x2, double y2 );
|
double Distance( double x1, double y1, double x2, double y2 );
|
||||||
|
|
Loading…
Reference in New Issue