Fix bug in PolyLine.cpp, Fix bug in DRC calculations (see changelog). Cvpcb: move dialog files in dialogs/
This commit is contained in:
parent
52cfa9aec9
commit
fd1c159a59
|
@ -4,6 +4,17 @@ KiCad ChangeLog 2010
|
|||
Please add newer entries at the top, list the date and your name with
|
||||
email address.
|
||||
|
||||
2010-oct-15, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
||||
================================================================================
|
||||
PolyLine.cpp:
|
||||
remove unused method CPolyLine::TestPointInsideContour() which was a duplicate of
|
||||
TestPointInsidePolygon().
|
||||
In CPolyLine::TestPointInside(); replace curious algo (which have a problem)
|
||||
to test a point inside a polygon by TestPointInsidePolygon()
|
||||
++Pcbnew:
|
||||
fix a bug in Drc and clearance calculations when using a dummy pad
|
||||
( in zones calcualtions and to test holes ot tracks and holes to pads DRC).
|
||||
|
||||
2010-oct-26 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
|
||||
================================================================================
|
||||
++EESchema
|
||||
|
|
|
@ -4,6 +4,7 @@ add_definitions(-DCVPCB)
|
|||
# Includes
|
||||
###
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dialogs
|
||||
${Boost_INCLUDE_DIR}
|
||||
../3d-viewer
|
||||
../pcbnew
|
||||
|
@ -13,6 +14,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
|||
###
|
||||
# Sources
|
||||
###
|
||||
set(CVPCB_DIALOGS
|
||||
dialogs/dialog_cvpcb_config.cpp
|
||||
dialogs/dialog_cvpcb_config_fbp.cpp
|
||||
dialogs/dialog_display_options.cpp
|
||||
dialogs/dialog_display_options_base.cpp
|
||||
)
|
||||
|
||||
set(CVPCB_SRCS
|
||||
autosel.cpp
|
||||
cfg.cpp
|
||||
|
@ -22,10 +30,6 @@ set(CVPCB_SRCS
|
|||
class_footprints_listbox.cpp
|
||||
cvframe.cpp
|
||||
cvpcb.cpp
|
||||
dialog_cvpcb_config.cpp
|
||||
dialog_cvpcb_config_fbp.cpp
|
||||
dialog_display_options.cpp
|
||||
dialog_display_options_base.cpp
|
||||
dummy_functions.cpp
|
||||
genequiv.cpp
|
||||
init.cpp
|
||||
|
@ -69,6 +73,7 @@ endif(APPLE)
|
|||
###
|
||||
add_executable(cvpcb WIN32 MACOSX_BUNDLE
|
||||
${CVPCB_SRCS}
|
||||
${CVPCB_DIALOGS}
|
||||
${CVPCB_RESOURCES})
|
||||
|
||||
###
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
add_definitions(-DEESCHEMA)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dialogs
|
||||
${CMAKE_SOURCE_DIR}/common
|
||||
${CMAKE_SOURCE_DIR}/dialogs
|
||||
${Boost_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
|
|||
else
|
||||
{
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetClearance(): NULL netclass") );
|
||||
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetClearance():NULL netclass,type %d"), Type() );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const
|
|||
if( board == NULL ) // Should not occurs
|
||||
{
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetNetClass(): NULL board, type %d"), Type() );
|
||||
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetNetClass():NULL board,type %d"), Type() );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const
|
|||
#ifdef __WXDEBUG__
|
||||
if( netclass == NULL )
|
||||
{
|
||||
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetNetClass(): NULL netclass") );
|
||||
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetNetClass():NULL netclass,type %d"), Type());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -213,8 +213,8 @@ void D_PAD::Copy( D_PAD* source )
|
|||
* returns the clearance in internal units. If \a aItem is not NULL then the
|
||||
* returned clearance is the greater of this object's clearance and
|
||||
* aItem's clearance. If \a aItem is NULL, then this objects
|
||||
* clearance
|
||||
* is returned.
|
||||
* clearance is returned.
|
||||
* note also if the pad is not on copper layers, just ist local clearance is returned
|
||||
* @param aItem is another BOARD_CONNECTED_ITEM or NULL
|
||||
* @return int - the clearance in internal units.
|
||||
*/
|
||||
|
@ -224,6 +224,13 @@ int D_PAD::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
|
|||
// overrides its NETCLASS clearance value
|
||||
int clearance = m_LocalClearance;
|
||||
|
||||
// if not on copper layers, this pad has no netclass,
|
||||
// So return just use its local clearance
|
||||
// Old versions of pcbnew allow a hole in a pad which is not on copper layers
|
||||
// (this is obviously a mistake, but we must support it)
|
||||
// else see other clearance values
|
||||
if( (m_Masque_Layer & ALL_CU_LAYERS) != 0 )
|
||||
{
|
||||
if( clearance == 0 )
|
||||
{ // If local clearance is 0, use the parent footprint clearance value
|
||||
if( GetParent() && ( (MODULE*) GetParent() )->m_LocalClearance )
|
||||
|
@ -232,8 +239,9 @@ int D_PAD::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
|
|||
|
||||
if( clearance == 0 ) // If the parent footprint clearance value = 0, use NETCLASS value
|
||||
return BOARD_CONNECTED_ITEM::GetClearance( aItem );
|
||||
}
|
||||
|
||||
// We have a specific clearance.
|
||||
// We have a specific clearance or a pad with no netclass (not on copper layers).
|
||||
// if aItem, return the biggest clearance
|
||||
if( aItem )
|
||||
{
|
||||
|
|
|
@ -556,10 +556,14 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
|
|||
{
|
||||
int layerMask = aRefPad->m_Masque_Layer & ALL_CU_LAYERS;
|
||||
|
||||
// used to test DRC pad to holes: this dummypad is a pad hole to test
|
||||
// pad to pad hole DRC, using pad to pad DRC test.
|
||||
// this dummy pad is a circle or an oval.
|
||||
static D_PAD dummypad( (MODULE*) NULL );
|
||||
/* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
|
||||
* to test pad to pad hole DRC, using the pad to pad DRC test function.
|
||||
* Therefore, this dummy pad is a circle or an oval.
|
||||
* A pad must have a parent because some functions expect a non null parent
|
||||
* to find the parent board, and some other data
|
||||
*/
|
||||
MODULE dummymodule( m_pcb ); // Creates a dummy parent
|
||||
D_PAD dummypad( &dummymodule );
|
||||
dummypad.m_Masque_Layer |= ALL_CU_LAYERS; // Ensure the hole is on all copper layers
|
||||
dummypad.m_LocalClearance = 1; /* Use the minimal local clerance value for the dummy pad
|
||||
* the clearance of the active pad will be used
|
||||
|
|
|
@ -264,9 +264,16 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
|
|||
/* Phase 1 : test DRC track to pads : */
|
||||
/******************************************/
|
||||
|
||||
// Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
|
||||
// but having a hole
|
||||
D_PAD dummypad( (MODULE*) NULL ); // construct this once outside following loop
|
||||
/* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
|
||||
* but having a hole
|
||||
* This dummy pad has the size and shape of the hole
|
||||
* to test tracks to pad hole DRC, using checkClearanceSegmToPad test function.
|
||||
* Therefore, this dummy pad is a circle or an oval.
|
||||
* A pad must have a parent because some functions expect a non null parent
|
||||
* to find the parent board, and some other data
|
||||
*/
|
||||
MODULE dummymodule( m_pcb ); // Creates a dummy parent
|
||||
D_PAD dummypad( &dummymodule );
|
||||
dummypad.m_Masque_Layer = ALL_CU_LAYERS; // Ensure the hole is on all layers
|
||||
|
||||
// Compute the min distance to pads
|
||||
|
|
|
@ -173,7 +173,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
static std::vector <CPolyPt> cornerBufferPolysToSubstract;
|
||||
cornerBufferPolysToSubstract.clear();
|
||||
|
||||
D_PAD dummyPad( (MODULE*) NULL );
|
||||
/* Use a dummy pad to calculate hole clerance when a pad is not on all copper layers
|
||||
* and this pad has a hole
|
||||
* This dummy pad has the size and shape of the hole
|
||||
* Therefore, this dummy pad is a circle or an oval.
|
||||
* A pad must have a parent because some functions expect a non null parent
|
||||
* to find the parent board, and some other data
|
||||
*/
|
||||
MODULE dummymodule( aPcb ); // Creates a dummy parent
|
||||
D_PAD dummypad( &dummymodule );
|
||||
D_PAD* nextpad;
|
||||
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
|
@ -190,11 +198,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
continue;
|
||||
|
||||
// Use a dummy pad to calculate a hole shape that have the same dimension as the pad hole
|
||||
dummyPad.m_Size = pad->m_Drill;
|
||||
dummyPad.m_Orient = pad->m_Orient;
|
||||
dummyPad.m_PadShape = pad->m_DrillShape;
|
||||
dummyPad.m_Pos = pad->m_Pos;
|
||||
pad = &dummyPad;
|
||||
dummypad.m_Size = pad->m_Drill;
|
||||
dummypad.m_Orient = pad->m_Orient;
|
||||
dummypad.m_PadShape = pad->m_DrillShape;
|
||||
dummypad.m_Pos = pad->m_Pos;
|
||||
pad = &dummypad;
|
||||
}
|
||||
|
||||
if( pad->GetNet() != GetNet() )
|
||||
|
|
|
@ -209,7 +209,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
static std::vector <CPolyPt> cornerBufferPolysToSubstract;
|
||||
cornerBufferPolysToSubstract.clear();
|
||||
|
||||
D_PAD dummyPad( (MODULE*) NULL );
|
||||
/* Use a dummy pad to calculate hole clerance when a pad is not on all copper layers
|
||||
* and this pad has a hole
|
||||
* This dummy pad has the size and shape of the hole
|
||||
* Therefore, this dummy pad is a circle or an oval.
|
||||
* A pad must have a parent because some functions expect a non null parent
|
||||
* to find the parent board, and some other data
|
||||
*/
|
||||
MODULE dummymodule( aPcb ); // Creates a dummy parent
|
||||
D_PAD dummypad( &dummymodule );
|
||||
D_PAD* nextpad;
|
||||
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
|
@ -226,11 +234,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
continue;
|
||||
|
||||
// Use a dummy pad to calculate a hole shape that have the same dimension as the pad hole
|
||||
dummyPad.m_Size = pad->m_Drill;
|
||||
dummyPad.m_Orient = pad->m_Orient;
|
||||
dummyPad.m_PadShape = pad->m_DrillShape;
|
||||
dummyPad.m_Pos = pad->m_Pos;
|
||||
pad = &dummyPad;
|
||||
dummypad.m_Size = pad->m_Drill;
|
||||
dummypad.m_Orient = pad->m_Orient;
|
||||
dummypad.m_PadShape = pad->m_DrillShape;
|
||||
dummypad.m_Pos = pad->m_Pos;
|
||||
pad = &dummypad;
|
||||
}
|
||||
|
||||
if( pad->GetNet() != GetNet() )
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "PolyLine.h"
|
||||
#include "gr_basic.h"
|
||||
#include "bezier_curves.h"
|
||||
#include "polygon_test_point_inside.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -1366,150 +1367,25 @@ bool CPolyLine::TestPointInside( int px, int py )
|
|||
wxASSERT( 0 );
|
||||
}
|
||||
|
||||
// define line passing through (x,y), with slope = 2/3;
|
||||
// get intersection points
|
||||
int xx, yy;
|
||||
double slope = (double) 2.0 / 3.0;
|
||||
double a = py - slope * px;
|
||||
int nloops = 0;
|
||||
int npts;
|
||||
// Test all polygons.
|
||||
// Since the first is the main outline, and other are hole,
|
||||
// if the tested point is inside only one contour, it is inside the whole polygon
|
||||
// (in fact inside the main outline, and outside all holes).
|
||||
// if inside 2 contours (the main outline + an hole), it is outside the poly.
|
||||
int polycount = GetNumContours();
|
||||
bool inside = false;
|
||||
|
||||
// make this a loop so if my homebrew algorithm screws up, we try it again
|
||||
do
|
||||
{
|
||||
// now find all intersection points of line with polyline sides
|
||||
npts = 0;
|
||||
inside = false;
|
||||
for( int icont = 0; icont<GetNumContours(); icont++ )
|
||||
for( int icont = 0; icont < polycount; icont++ )
|
||||
{
|
||||
int istart = GetContourStart( icont );
|
||||
int iend = GetContourEnd( icont );
|
||||
for( int ic = istart; ic<=iend; ic++ )
|
||||
{
|
||||
double x, y, x2, y2;
|
||||
int ok;
|
||||
if( ic == istart )
|
||||
ok = FindLineSegmentIntersection( a, slope,
|
||||
corner[iend].x, corner[iend].y,
|
||||
corner[istart].x, corner[istart].y,
|
||||
side_style[iend],
|
||||
&x, &y, &x2, &y2 );
|
||||
else
|
||||
ok = FindLineSegmentIntersection( a, slope,
|
||||
corner[ic - 1].x, corner[ic - 1].y,
|
||||
corner[ic].x, corner[ic].y,
|
||||
side_style[ic - 1],
|
||||
&x, &y, &x2, &y2 );
|
||||
if( ok )
|
||||
{
|
||||
xx = (int) x;
|
||||
yy = (int) y;
|
||||
if( xx == px && yy == py )
|
||||
return FALSE; // (x,y) is on a side, call it outside
|
||||
else if( xx > px )
|
||||
// Test this polygon:
|
||||
if( TestPointInsidePolygon( corner, istart, iend, px, py) ) // test point inside the current polygon
|
||||
inside = not inside;
|
||||
npts++;
|
||||
}
|
||||
if( ok == 2 )
|
||||
{
|
||||
xx = (int) x2;
|
||||
yy = (int) y2;
|
||||
if( xx == px && yy == py )
|
||||
return FALSE; // (x,y) is on a side, call it outside
|
||||
else if( xx > px )
|
||||
inside = not inside;
|
||||
npts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nloops++;
|
||||
a += PCBU_PER_MIL / 100;
|
||||
} while( npts % 2 != 0 && nloops < 3 );
|
||||
|
||||
wxASSERT( npts % 2==0 ); // odd number of intersection points, error
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
|
||||
// test to see if a point is inside polyline contour
|
||||
//
|
||||
bool CPolyLine::TestPointInsideContour( int icont, int px, int py )
|
||||
{
|
||||
if( icont >= GetNumContours() )
|
||||
return FALSE;
|
||||
if( !GetClosed() )
|
||||
{
|
||||
wxASSERT( 0 );
|
||||
}
|
||||
|
||||
// define line passing through (x,y), with slope = 2/3;
|
||||
// get intersection points
|
||||
int xx, yy;
|
||||
double slope = (double) 2.0 / 3.0;
|
||||
double a = py - slope * px;
|
||||
int nloops = 0;
|
||||
int npts;
|
||||
bool inside = false;
|
||||
|
||||
// make this a loop so if my homebrew algorithm screws up, we try it again
|
||||
do
|
||||
{
|
||||
// now find all intersection points of line with polyline sides
|
||||
npts = 0;
|
||||
inside = false;
|
||||
int istart = GetContourStart( icont );
|
||||
int iend = GetContourEnd( icont );
|
||||
for( int ic = istart; ic<=iend; ic++ )
|
||||
{
|
||||
double x, y, x2, y2;
|
||||
int ok;
|
||||
if( ic == istart )
|
||||
ok = FindLineSegmentIntersection( a, slope,
|
||||
corner[iend].x, corner[iend].y,
|
||||
corner[istart].x, corner[istart].y,
|
||||
side_style[iend],
|
||||
&x, &y, &x2, &y2 );
|
||||
else
|
||||
ok = FindLineSegmentIntersection( a, slope,
|
||||
corner[ic - 1].x, corner[ic - 1].y,
|
||||
corner[ic].x, corner[ic].y,
|
||||
side_style[ic - 1],
|
||||
&x, &y, &x2, &y2 );
|
||||
if( ok )
|
||||
{
|
||||
xx = (int) x;
|
||||
yy = (int) y;
|
||||
npts++;
|
||||
if( xx == px && yy == py )
|
||||
return FALSE; // (x,y) is on a side, call it outside
|
||||
else if( xx > px )
|
||||
inside = not inside;
|
||||
}
|
||||
if( ok == 2 )
|
||||
{
|
||||
xx = (int) x2;
|
||||
yy = (int) y2;
|
||||
npts++;
|
||||
if( xx == px && yy == py )
|
||||
return FALSE; // (x,y) is on a side, call it outside
|
||||
else if( xx > px )
|
||||
inside = not inside;
|
||||
}
|
||||
}
|
||||
|
||||
nloops++;
|
||||
a += PCBU_PER_MIL / 100;
|
||||
} while( npts % 2 != 0 && nloops < 3 );
|
||||
|
||||
wxASSERT( npts % 2==0 ); // odd number of intersection points, error
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
|
||||
// copy data from another poly, but don't draw it
|
||||
//
|
||||
void CPolyLine::Copy( CPolyLine* src )
|
||||
|
|
|
@ -145,7 +145,6 @@ public:
|
|||
CRect GetCornerBounds( int icont );
|
||||
void Copy( CPolyLine* src );
|
||||
bool TestPointInside( int x, int y );
|
||||
bool TestPointInsideContour( int icont, int x, int y );
|
||||
bool IsCutoutContour( int icont );
|
||||
void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num );
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* Because the starting point of a segment is also the ending point of the previous, only one must be used.
|
||||
* And we do no use twice the same segment, so we do NOT use both starting and ending points of these 2 segments.
|
||||
* So we must use only one ending point of each segment when calculating intersections
|
||||
* but it cannot be always the starting or the endind point. This depend on relative position of 2 consectutive segments
|
||||
* but it cannot be always the starting or the ending point. This depend on relative position of 2 consectutive segments
|
||||
* Here, the ending point above the Y reference position is used
|
||||
* and the ending point below or equal the Y reference position is NOT used
|
||||
* Obviously, others cases are irrelevant because there is not intersection.
|
||||
|
@ -35,10 +35,9 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
|||
/** Function TestPointInsidePolygon
|
||||
* test if a point is inside or outside a polygon.
|
||||
* the polygon must have only lines (not arcs) for outlines.
|
||||
* Use TestPointInside or TestPointInsideContour for more complex polygons
|
||||
* @param aPolysList: the list of polygons
|
||||
* @param aIdxstart: the starting point of a given polygon in m_FilledPolysList.
|
||||
* @param aIdxend: the ending point of the polygon in m_FilledPolysList.
|
||||
* @param aIdxend: the ending point of this polygon in m_FilledPolysList.
|
||||
* @param aRefx, aRefy: the point coordinate to test
|
||||
* @return true if the point is inside, false for outside
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue