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

Fix bug in PolyLine.cpp, Fix bug in DRC calculations (see changelog). Cvpcb:...

Fix bug in PolyLine.cpp, Fix bug in DRC calculations (see changelog). Cvpcb: move dialog files in dialogs/
parent 52cfa9ae
...@@ -4,6 +4,17 @@ KiCad ChangeLog 2010 ...@@ -4,6 +4,17 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. 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> 2010-oct-26 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
================================================================================ ================================================================================
++EESchema ++EESchema
......
...@@ -4,6 +4,7 @@ add_definitions(-DCVPCB) ...@@ -4,6 +4,7 @@ add_definitions(-DCVPCB)
# Includes # Includes
### ###
include_directories(${CMAKE_CURRENT_SOURCE_DIR} include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/dialogs
${Boost_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
../3d-viewer ../3d-viewer
../pcbnew ../pcbnew
...@@ -13,6 +14,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ...@@ -13,6 +14,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
### ###
# Sources # 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 set(CVPCB_SRCS
autosel.cpp autosel.cpp
cfg.cpp cfg.cpp
...@@ -22,10 +30,6 @@ set(CVPCB_SRCS ...@@ -22,10 +30,6 @@ set(CVPCB_SRCS
class_footprints_listbox.cpp class_footprints_listbox.cpp
cvframe.cpp cvframe.cpp
cvpcb.cpp cvpcb.cpp
dialog_cvpcb_config.cpp
dialog_cvpcb_config_fbp.cpp
dialog_display_options.cpp
dialog_display_options_base.cpp
dummy_functions.cpp dummy_functions.cpp
genequiv.cpp genequiv.cpp
init.cpp init.cpp
...@@ -69,6 +73,7 @@ endif(APPLE) ...@@ -69,6 +73,7 @@ endif(APPLE)
### ###
add_executable(cvpcb WIN32 MACOSX_BUNDLE add_executable(cvpcb WIN32 MACOSX_BUNDLE
${CVPCB_SRCS} ${CVPCB_SRCS}
${CVPCB_DIALOGS}
${CVPCB_RESOURCES}) ${CVPCB_RESOURCES})
### ###
......
add_definitions(-DEESCHEMA) add_definitions(-DEESCHEMA)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/dialogs
${CMAKE_SOURCE_DIR}/common ${CMAKE_SOURCE_DIR}/common
${CMAKE_SOURCE_DIR}/dialogs
${Boost_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
) )
......
...@@ -93,7 +93,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const ...@@ -93,7 +93,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
else else
{ {
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetClearance(): NULL netclass") ); wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetClearance():NULL netclass,type %d"), Type() );
#endif #endif
} }
...@@ -116,7 +116,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const ...@@ -116,7 +116,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const
if( board == NULL ) // Should not occurs if( board == NULL ) // Should not occurs
{ {
#ifdef __WXDEBUG__ #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 #endif
return NULL; return NULL;
} }
...@@ -129,7 +129,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const ...@@ -129,7 +129,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
if( netclass == NULL ) if( netclass == NULL )
{ {
wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetNetClass(): NULL netclass") ); wxLogWarning(wxT("BOARD_CONNECTED_ITEM::GetNetClass():NULL netclass,type %d"), Type());
} }
#endif #endif
} }
......
...@@ -213,8 +213,8 @@ void D_PAD::Copy( D_PAD* source ) ...@@ -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 * 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 * returned clearance is the greater of this object's clearance and
* aItem's clearance. If \a aItem is NULL, then this objects * aItem's clearance. If \a aItem is NULL, then this objects
* clearance * clearance is returned.
* 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 * @param aItem is another BOARD_CONNECTED_ITEM or NULL
* @return int - the clearance in internal units. * @return int - the clearance in internal units.
*/ */
...@@ -224,16 +224,24 @@ int D_PAD::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const ...@@ -224,16 +224,24 @@ int D_PAD::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
// overrides its NETCLASS clearance value // overrides its NETCLASS clearance value
int clearance = m_LocalClearance; int clearance = m_LocalClearance;
if( clearance == 0 ) // if not on copper layers, this pad has no netclass,
{ // If local clearance is 0, use the parent footprint clearance value // So return just use its local clearance
if( GetParent() && ( (MODULE*) GetParent() )->m_LocalClearance ) // Old versions of pcbnew allow a hole in a pad which is not on copper layers
clearance = ( (MODULE*) GetParent() )->m_LocalClearance; // (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 )
clearance = ( (MODULE*) GetParent() )->m_LocalClearance;
}
if( clearance == 0 ) // If the parent footprint clearance value = 0, use NETCLASS value if( clearance == 0 ) // If the parent footprint clearance value = 0, use NETCLASS value
return BOARD_CONNECTED_ITEM::GetClearance( aItem ); 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, return the biggest clearance
if( aItem ) if( aItem )
{ {
......
...@@ -556,10 +556,14 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, ...@@ -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; int layerMask = aRefPad->m_Masque_Layer & ALL_CU_LAYERS;
// used to test DRC pad to holes: this dummypad is a pad hole to test /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
// pad to pad hole DRC, using pad to pad DRC test. * to test pad to pad hole DRC, using the pad to pad DRC test function.
// this dummy pad is a circle or an oval. * Therefore, this dummy pad is a circle or an oval.
static D_PAD dummypad( (MODULE*) NULL ); * 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_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 dummypad.m_LocalClearance = 1; /* Use the minimal local clerance value for the dummy pad
* the clearance of the active pad will be used * the clearance of the active pad will be used
......
...@@ -264,9 +264,16 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) ...@@ -264,9 +264,16 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
/* Phase 1 : test DRC track to pads : */ /* Phase 1 : test DRC track to pads : */
/******************************************/ /******************************************/
// Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers /* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
// but having a hole * but having a hole
D_PAD dummypad( (MODULE*) NULL ); // construct this once outside following loop * 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 dummypad.m_Masque_Layer = ALL_CU_LAYERS; // Ensure the hole is on all layers
// Compute the min distance to pads // Compute the min distance to pads
......
...@@ -173,7 +173,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -173,7 +173,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
static std::vector <CPolyPt> cornerBufferPolysToSubstract; static std::vector <CPolyPt> cornerBufferPolysToSubstract;
cornerBufferPolysToSubstract.clear(); 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; D_PAD* nextpad;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{ {
...@@ -190,11 +198,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -190,11 +198,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
continue; continue;
// Use a dummy pad to calculate a hole shape that have the same dimension as the pad hole // 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_Size = pad->m_Drill;
dummyPad.m_Orient = pad->m_Orient; dummypad.m_Orient = pad->m_Orient;
dummyPad.m_PadShape = pad->m_DrillShape; dummypad.m_PadShape = pad->m_DrillShape;
dummyPad.m_Pos = pad->m_Pos; dummypad.m_Pos = pad->m_Pos;
pad = &dummyPad; pad = &dummypad;
} }
if( pad->GetNet() != GetNet() ) if( pad->GetNet() != GetNet() )
......
...@@ -209,7 +209,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -209,7 +209,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
static std::vector <CPolyPt> cornerBufferPolysToSubstract; static std::vector <CPolyPt> cornerBufferPolysToSubstract;
cornerBufferPolysToSubstract.clear(); 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; D_PAD* nextpad;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{ {
...@@ -226,11 +234,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -226,11 +234,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
continue; continue;
// Use a dummy pad to calculate a hole shape that have the same dimension as the pad hole // 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_Size = pad->m_Drill;
dummyPad.m_Orient = pad->m_Orient; dummypad.m_Orient = pad->m_Orient;
dummyPad.m_PadShape = pad->m_DrillShape; dummypad.m_PadShape = pad->m_DrillShape;
dummyPad.m_Pos = pad->m_Pos; dummypad.m_Pos = pad->m_Pos;
pad = &dummyPad; pad = &dummypad;
} }
if( pad->GetNet() != GetNet() ) if( pad->GetNet() != GetNet() )
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "PolyLine.h" #include "PolyLine.h"
#include "gr_basic.h" #include "gr_basic.h"
#include "bezier_curves.h" #include "bezier_curves.h"
#include "polygon_test_point_inside.h"
using namespace std; using namespace std;
...@@ -1366,150 +1367,25 @@ bool CPolyLine::TestPointInside( int px, int py ) ...@@ -1366,150 +1367,25 @@ bool CPolyLine::TestPointInside( int px, int py )
wxASSERT( 0 ); wxASSERT( 0 );
} }
// define line passing through (x,y), with slope = 2/3; // Test all polygons.
// get intersection points // Since the first is the main outline, and other are hole,
int xx, yy; // if the tested point is inside only one contour, it is inside the whole polygon
double slope = (double) 2.0 / 3.0; // (in fact inside the main outline, and outside all holes).
double a = py - slope * px; // if inside 2 contours (the main outline + an hole), it is outside the poly.
int nloops = 0; int polycount = GetNumContours();
int npts; bool inside = false;
bool inside = false; for( int icont = 0; icont < polycount; icont++ )
// 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++ )
{
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 )
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 istart = GetContourStart( icont );
int iend = GetContourEnd( icont ); int iend = GetContourEnd( icont );
for( int ic = istart; ic<=iend; ic++ ) // Test this polygon:
{ if( TestPointInsidePolygon( corner, istart, iend, px, py) ) // test point inside the current polygon
double x, y, x2, y2; inside = not inside;
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; return inside;
} }
// copy data from another poly, but don't draw it // copy data from another poly, but don't draw it
// //
void CPolyLine::Copy( CPolyLine* src ) void CPolyLine::Copy( CPolyLine* src )
......
...@@ -145,7 +145,6 @@ public: ...@@ -145,7 +145,6 @@ public:
CRect GetCornerBounds( int icont ); CRect GetCornerBounds( int icont );
void Copy( CPolyLine* src ); void Copy( CPolyLine* src );
bool TestPointInside( int x, int y ); bool TestPointInside( int x, int y );
bool TestPointInsideContour( int icont, int x, int y );
bool IsCutoutContour( int icont ); bool IsCutoutContour( int icont );
void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num );
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* Because the starting point of a segment is also the ending point of the previous, only one must be used. * 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. * 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 * 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 * 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 * and the ending point below or equal the Y reference position is NOT used
* Obviously, others cases are irrelevant because there is not intersection. * Obviously, others cases are irrelevant because there is not intersection.
...@@ -35,10 +35,9 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList, ...@@ -35,10 +35,9 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
/** Function TestPointInsidePolygon /** Function TestPointInsidePolygon
* test if a point is inside or outside a polygon. * test if a point is inside or outside a polygon.
* the polygon must have only lines (not arcs) for outlines. * 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 aPolysList: the list of polygons
* @param aIdxstart: the starting point of a given polygon in m_FilledPolysList. * @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 * @param aRefx, aRefy: the point coordinate to test
* @return true if the point is inside, false for outside * @return true if the point is inside, false for outside
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment