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
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})
###
......
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,16 +224,24 @@ int D_PAD::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
// overrides its NETCLASS clearance value
int clearance = m_LocalClearance;
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 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 )
clearance = ( (MODULE*) GetParent() )->m_LocalClearance;
}
if( clearance == 0 ) // If the parent footprint clearance value = 0, use NETCLASS value
return BOARD_CONNECTED_ITEM::GetClearance( aItem );
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;
bool inside = false;
// make this a loop so if my homebrew algorithm screws up, we try it again
do
// 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;
for( int icont = 0; icont < polycount; icont++ )
{
// 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 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
// Test this polygon:
if( TestPointInsidePolygon( corner, istart, iend, px, py) ) // test point inside the current polygon
inside = not inside;
}
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
*/
......
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