DRC code cleaning, and added DRC tests for trapezoidal pads. Needs more tests.

This commit is contained in:
jean-pierre charras 2010-09-20 18:23:31 +02:00
commit d536f9d914
13 changed files with 1369 additions and 1141 deletions

View File

@ -96,6 +96,7 @@ set(PCBNEW_SRCS
dist.cpp
dragsegm.cpp
drc.cpp
drc_clearance_test_functions.cpp
drc_marker_functions.cpp
edgemod.cpp
edit.cpp

View File

@ -764,17 +764,15 @@ bool D_PAD::IsOnLayer( int aLayer ) const
*/
bool D_PAD::HitTest( const wxPoint& ref_pos )
{
int deltaX, deltaY;
int dx, dy;
double dist;
wxPoint shape_pos = ReturnShapePos();
deltaX = ref_pos.x - shape_pos.x;
deltaY = ref_pos.y - shape_pos.y;
wxPoint delta = ref_pos - shape_pos;
/* Quick test: a test point must be inside the circle. */
if( ( abs( deltaX ) > m_ShapeMaxRadius ) || ( abs( deltaY ) > m_ShapeMaxRadius ) )
if( ( abs( delta.x ) > m_ShapeMaxRadius ) || ( abs( delta.y ) > m_ShapeMaxRadius ) )
return false;
dx = m_Size.x >> 1; // dx also is the radius for rounded pads
@ -783,7 +781,7 @@ bool D_PAD::HitTest( const wxPoint& ref_pos )
switch( m_PadShape & 0x7F )
{
case PAD_CIRCLE:
dist = hypot( deltaX, deltaY );
dist = hypot( delta.x, delta.y );
if( wxRound( dist ) <= dx )
return true;
break;
@ -792,22 +790,13 @@ bool D_PAD::HitTest( const wxPoint& ref_pos )
{
wxPoint poly[4];
BuildPadPolygon( poly, wxSize(0,0), 0 );
// Build the same polygon with CPolyPt corners,
// to use TestPointInsidePolygon
static std::vector <CPolyPt> polysList; // Is static to avoid memory reallocation
polysList.clear();
for(int ii= 0; ii < 4; ii++ )
{
CPolyPt corner(poly[ii].x, poly[ii].y);
polysList.push_back(corner);
}
RotatePoint( &deltaX, &deltaY, -m_Orient );
return TestPointInsidePolygon( polysList, 0, 3, deltaX, deltaY );
RotatePoint( &delta, -m_Orient );
return TestPointInsidePolygon( poly, 4, delta );
}
default:
RotatePoint( &deltaX, &deltaY, -m_Orient );
if( (abs( deltaX ) <= dx ) && (abs( deltaY ) <= dy) )
RotatePoint( &delta, -m_Orient );
if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) )
return true;
break;
}

View File

@ -148,7 +148,7 @@ public:
* Function GetShape
* @return the shape of this pad.
*/
int GetShape() { return m_PadShape & 0xFF; }
int GetShape() const { return m_PadShape & 0xFF; }
/**
* Function GetPosition
@ -239,14 +239,26 @@ public:
void DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo );
/** function BuildPadPolygon
* Has meaning only for polygonal pads (trapeziod and rectangular)
* Has meaning only for polygonal pads (trapezoid and rectangular)
* Build the Corner list of the polygonal shape,
* depending on shape, extra size (clearance ...) and orientation
* @param aCoord[4] = a buffer to fill.
* @param aInflateValue = wxSize: the clearance or margin value. value > 0: inflate, < 0 deflate
* @param aRotation = full rotation of the polygon
*/
void BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, int aRotation );
void BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, int aRotation ) const;
/** function BuildSegmentFromOvalShape
* Has meaning only for OVAL (and ROUND) pads
* Build an equivalent segment having the same shape as the OVAL shape,
* Useful in draw function and in DRC and HitTest functions,
* because segments are already well handled by track tests
* @param aSegStart = the starting point of the equivalent segment, relative to the shape position.
* @param aSegEnd = the ending point of the equivalent segment, relative to the shape position
* @param aRotation = full rotation of the segment
* @return the width of the segment
*/
int BuildSegmentFromOvalShape(wxPoint& aSegStart, wxPoint& aSegEnd, int aRotation) const;
// others
void SetPadName( const wxString& name ); // Change pad name

View File

@ -357,9 +357,9 @@ void D_PAD::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDraw_mode,
void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
{
wxPoint coord[4];
int rotdx,
delta_cx, delta_cy;
int delta_cx, delta_cy;
int angle = m_Orient;
int seg_width;
GRSetDrawMode( aDC, aDrawInfo.m_DrawMode );
@ -392,44 +392,30 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
break;
case PAD_OVAL:
if( halfsize.x > halfsize.y ) /* horizontal */
{
delta_cx = halfsize.x - halfsize.y;
delta_cy = 0;
rotdx = m_Size.y + ( aDrawInfo.m_Mask_margin.y * 2 );
}
else /* vertical */
{
delta_cx = 0;
delta_cy = halfsize.y - halfsize.x;
rotdx = m_Size.x + ( aDrawInfo.m_Mask_margin.x * 2 );
}
RotatePoint( &delta_cx, &delta_cy, angle );
{
wxPoint segStart, segEnd;
seg_width = BuildSegmentFromOvalShape(segStart, segEnd, angle);
segStart += shape_pos;
segEnd += shape_pos;
if( aDrawInfo.m_ShowPadFilled )
{
GRFillCSegm( aClipBox, aDC,
shape_pos.x + delta_cx, shape_pos.y + delta_cy,
shape_pos.x - delta_cx, shape_pos.y - delta_cy,
rotdx, aDrawInfo.m_Color );
GRFillCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y,
seg_width, aDrawInfo.m_Color );
}
else
{
GRCSegm( aClipBox, aDC,
shape_pos.x + delta_cx, shape_pos.y + delta_cy,
shape_pos.x - delta_cx, shape_pos.y - delta_cy,
rotdx, m_PadSketchModePenSize, aDrawInfo.m_Color );
GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y,
seg_width, m_PadSketchModePenSize, aDrawInfo.m_Color );
}
/* Draw the isolation line. */
if( aDrawInfo.m_PadClearance )
{
rotdx = rotdx + 2 * aDrawInfo.m_PadClearance;
GRCSegm( aClipBox, aDC, shape_pos.x + delta_cx, shape_pos.y + delta_cy,
shape_pos.x - delta_cx, shape_pos.y - delta_cy,
rotdx, aDrawInfo.m_Color );
seg_width += 2 * aDrawInfo.m_PadClearance;
GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y,
seg_width, aDrawInfo.m_Color );
}
}
break;
case PAD_RECT:
@ -486,9 +472,6 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
#else
if( aDrawInfo.m_Scale * hole > 1 ) /* draw hole if its size is enough */
#endif
GRFilledCircle( aClipBox, aDC, holepos.x, holepos.y, hole, 0,
aDrawInfo.m_Color, aDrawInfo.m_HoleColor );
break;
@ -501,18 +484,18 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
{
delta_cx = halfsize.x - halfsize.y;
delta_cy = 0;
rotdx = m_Drill.y;
seg_width = m_Drill.y;
}
else /* vertical */
{
delta_cx = 0;
delta_cy = halfsize.y - halfsize.x;
rotdx = m_Drill.x;
seg_width = m_Drill.x;
}
RotatePoint( &delta_cx, &delta_cy, angle );
GRFillCSegm( aClipBox, aDC, holepos.x + delta_cx, holepos.y + delta_cy,
holepos.x - delta_cx, holepos.y - delta_cy, rotdx,
holepos.x - delta_cx, holepos.y - delta_cy, seg_width,
aDrawInfo.m_HoleColor );
break;
@ -637,6 +620,42 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
}
}
/** function BuildSegmentFromOvalShape
* Has meaning only for OVAL (and ROUND) pads.
* Build an equivalent segment having the same shape as the OVAL shape,
* aSegStart and aSegEnd are the ending points of the equivalent segment of the shape
* aRotation is the asked rotation of the segment (usually m_Orient)
*/
int D_PAD::BuildSegmentFromOvalShape(wxPoint& aSegStart, wxPoint& aSegEnd, int aRotation) const
{
int width;
if( m_Size.y < m_Size.x ) // Build an horizontal equiv segment
{
int delta = ( m_Size.x - m_Size.y ) / 2;
aSegStart.x = -delta;
aSegStart.y = 0;
aSegEnd.x = delta;
aSegEnd.y = 0;
width = m_Size.y;
}
else // Vertical oval: build a vertical equiv segment
{
int delta = ( m_Size.y -m_Size.x ) / 2;
aSegStart.x = 0;
aSegStart.y = -delta;
aSegEnd.x = 0;
aSegEnd.y = delta;
width = m_Size.x;
}
if( aRotation )
{
RotatePoint( &aSegStart, aRotation);
RotatePoint( &aSegEnd, aRotation);
}
return width;
}
/** function BuildPadPolygon
* Has meaning only for polygonal pads (trapeziod and rectangular)
@ -646,7 +665,7 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
* @param aInflateValue = wxSize: the clearance or margin value. value > 0: inflate, < 0 deflate
* @param aRotation = full rotation of the polygon, usually m_Orient
*/
void D_PAD::BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, int aRotation )
void D_PAD::BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, int aRotation ) const
{
if( (GetShape() != PAD_RECT) && (GetShape() != PAD_TRAPEZOID) )
return;

View File

@ -44,21 +44,17 @@ bool DIALOG_DRC_CONTROL::Show( bool show )
{
bool ret;
D(printf("%s %d\n", __func__, show );)
if( show )
{
ret = DIALOG_DRC_CONTROL_BASE::Show( show );
if( s_LastPos.x != -1 )
{
D(printf("setting window pos to (%d,%d)\n", s_LastPos.x, s_LastPos.y );)
//SetPosition( s_LastPos );
SetSize( s_LastPos.x, s_LastPos.y, s_LastSize.x, s_LastSize.y, 0 );
}
else
{
D(printf("not setting window pos (%d,%d)\n", s_LastPos.x, s_LastPos.y );)
// Do nothing: last position not yet saved.
}
}
else
@ -66,9 +62,6 @@ bool DIALOG_DRC_CONTROL::Show( bool show )
// Save the dialog's position before hiding
s_LastPos = GetPosition();
s_LastSize = GetSize();
D(printf("saving window pos as (%d,%d)\n", s_LastPos.x, s_LastPos.y );)
ret = DIALOG_DRC_CONTROL_BASE::Show( show );
}

View File

@ -195,8 +195,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
{
SetFocus(); // Required under wxGTK if we want to demiss the dialog with the ESC key
int tmp;
int internalUnits = m_Parent->m_InternalUnits;
int internalUnits = m_Parent->m_InternalUnits;
wxString msg;
m_isFlipped = false;
if( m_CurrentPad )
@ -298,7 +297,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
SetPadLayersList( m_dummyPad->m_Masque_Layer );
msg.Clear();
msg << tmp;
msg << m_dummyPad->m_Orient;
m_PadOrientCtrl->SetValue( msg );
// Pad Orient
@ -350,11 +349,10 @@ void DIALOG_PAD_PROPERTIES::initValues()
m_PadOrientCtrl->SetValue( msg );
// Selection du type
tmp = m_dummyPad->m_Attribut;
m_PadType->SetSelection( 0 );
for( int ii = 0; ii < NBTYPES; ii++ )
{
if( CodeType[ii] == tmp )
if( CodeType[ii] == m_dummyPad->m_Attribut )
{
m_PadType->SetSelection( ii );
break;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -173,10 +173,10 @@ private:
/* variables used in checkLine to test DRC segm to segm:
* define the area relative to the ref segment that does not contains anu other segment
*/
int m_xcliplo;
int m_ycliplo;
int m_xcliphi;
int m_ycliphi;
int m_xcliplo;
int m_ycliplo;
int m_xcliphi;
int m_ycliphi;
WinEDA_PcbFrame* m_mainWindow;
BOARD* m_pcb;
@ -329,30 +329,27 @@ private:
/**
* Function checkMarginToCircle
* @todo this translation is no good, fix this:
* calculates the distance from a circle (via or round end of track) to the
* segment of reference on the right hand side.
*
* @param cx The x coordinate of the circle's center
* @param cy The y coordinate of the circle's center
* @param radius A "keep out" radius centered over the circle
* @param length The length of the segment (i.e. coordinate of end)
* Helper function checkMarginToCircle
* Check the distance from a point to
* a segment. the segment is expected starting at 0,0, and on the X axis
* (used to test DRC between a segment and a round pad, via or round end of a track
* @param aCentre The coordinate of the circle's center
* @param aRadius A "keep out" radius centered over the circle
* @param aLength The length of the segment (i.e. coordinate of end, becuase it is on the X axis)
* @return bool - true if distance >= radius, else
* false when distance < radius
* false when distance < aRadius
*/
static bool checkMarginToCircle( int cx, int cy, int radius, int length );
static bool checkMarginToCircle( wxPoint aCentre, int aRadius, int aLength );
/**
* Function checkLine
* tests to see if one track is in contact with another track.
*
* Cette routine controle si la ligne (x1,y1 x2,y2) a une partie s'inscrivant
* dans le cadre (xcliplo,ycliplo xcliphi,ycliphi) (variables globales,
* locales a ce fichier)
* (helper function used in drc calculations to see if one track is in contact with another track).
* Test if a line intersects a bounding box (a rectangle)
* The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi
* return true if the line from aSegStart to aSegEnd is outside the bounding box
*/
bool checkLine( int x1, int y1, int x2, int y2 );
bool checkLine( wxPoint aSegStart, wxPoint aSegEnd );
//-----</single tests>---------------------------------------------

View File

@ -1,4 +1,4 @@
// math for graphics utility routines, from FreePCB
// math for graphics utility routines and RC, from FreePCB
#include <vector>
@ -13,13 +13,14 @@
using namespace std;
// test for hit on line segment
// i.e. cursor within a given distance from segment
// enter with: x,y = cursor coords
// (xi,yi) and (xf,yf) are the end-points of the line segment
// dist = maximum distance for hit
//
int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
/** function TestLineHit
* test for hit on line segment i.e. a point within a given distance from segment
* @param x, y = cursor coords
* @param xi,yi and xf,yf = the end-points of the line segment
* @param dist = maximum distance for hit
* return true if dist < distance between the point and the segment
*/
bool TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
{
double dd;
@ -29,14 +30,14 @@ int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
// vertical segment
dd = fabs( (double)(x-xi) );
if( dd<dist && ( (yf>yi && y<yf && y>yi) || (yf<yi && y>yf && y<yi) ) )
return 1;
return true;
}
else if( yf==yi )
{
// horizontal segment
dd = fabs( (double)(y-yi) );
if( dd<dist && ( (xf>xi && x<xf && x>xi) || (xf<xi && x>xf && x<xi) ) )
return 1;
return true;
}
else
{
@ -62,10 +63,10 @@ int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
{
// line segment more horizontal than vertical
if( dd<dist && ( (xf>xi && xp<xf && xp>xi) || (xf<xi && xp>xf && xp<xi) ) )
return 1;
return true;
}
}
return 0; // no hit
return false; // no hit
}
@ -482,12 +483,12 @@ int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int
return 1;
}
// Test for intersection of line segments
// If lines are parallel, returns false
// If true, returns intersection coords in x, y
// if false, returns min. distance in dist (may be 0.0 if parallel)
// and coords on nearest point in one of the segments in (x,y)
//
/** function TestForIntersectionOfStraightLineSegments
* Test for intersection of line segments
* If lines are parallel, returns false
* If true, returns also intersection coords in x, y
* if false, returns min. distance in dist (may be 0.0 if parallel)
*/
bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f,
int x2i, int y2i, int x2f, int y2f,
int * x, int * y, double * d )

View File

@ -13,8 +13,6 @@ typedef struct PointTag
typedef struct EllipseTag
{
PointT Center; /* ellipse center */
// double MaxRad,MinRad; /* major and minor axis */
// double Phi; /* major axis rotation */
double xrad, yrad; // radii on x and y
double theta1, theta2; // start and end angle for arc
} EllipseKH;
@ -22,7 +20,16 @@ typedef struct EllipseTag
// math stuff for graphics
bool Quadratic( double a, double b, double c, double *x1, double *x2 );
int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist );
/** function TestLineHit
* test for hit on line segment i.e. a point within a given distance from segment
* @param xi,yi and xf,yf = the end-points of the line segment
* @param dist = maximum distance for hit
* @param x, y = point to test coords
* @return true if hit (i.e dist < distance between the point and the segment, false if not.
*/
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,
double * x1, double * y1, double * x2, double * y2, double * dist=NULL );
int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style,
@ -30,9 +37,23 @@ int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style,
double x[]=NULL, double y[]=NULL );
bool FindLineEllipseIntersections( double a, double b, double c, double d, double *x1, double *x2 );
bool FindVerticalLineEllipseIntersections( double a, double b, double x, double *y1, double *y2 );
/** function TestForIntersectionOfStraightLineSegments
* Test for intersection of line segments
* If lines are parallel, returns false
* If true, returns also intersection coords in x, y
* if false, returns min. distance in dist (may be 0.0 if parallel)
* and coords on nearest point in one of the segments in (x,y)
* @param x1i, y1i, x1f, y1f = integer coordinates of the first segment
* @param x2i, y2i, x2f, y2f = integer coordinates of the other segment
* @param x, y = pointers on 2 integer to store the intersection coordinates (can be NULL)
* @param dist = pointeur on a double to store the dist.
* @return true if intersect.
*/
bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f,
int x2i, int y2i, int x2f, int y2f,
int * x=NULL, int * y=NULL, double * dist=NULL );
int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1,
int x2i, int y2i, int x2f, int y2f, int style2, int w2,
int max_cl, int * x, int * y );

View File

@ -1,21 +1,18 @@
/////////////////////////////////////////////////////////////////////////////
// Name: polygon_test_point_inside.cpp
/////////////////////////////////////////////////////////////////////////////
/**
* @file polygon_test_point_inside.cpp
*/
#include <math.h>
#include <vector>
#include "PolyLine.h"
using namespace std;
/* this algo uses the the Jordan curve theorem to find if a point is inside or outside a polygon:
* It run a semi-infinite line horizontally (increasing x, fixed y)
* out from the test point, and count how many edges it crosses.
* At each crossing, the ray switches between inside and outside.
* If odd count, the test point is inside the polygon
* This is called the Jordan curve theorem, or sometimes referred to as the "even-odd" test.
* Take care to starting and ending points of segments outlines, when the horizontal line crosses a segment outline
* Take care to starting and ending points of segments outlines, when the horizontal line crosses a segment outline
* exactly on an ending point:
* 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.
@ -30,16 +27,19 @@ using namespace std;
#define INSIDE true
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
int istart, int iend, int refx, int refy )
int aIdxstart,
int aIdxend,
int aRefx,
int aRefy)
/** 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 istart: the starting point of a given polygon in m_FilledPolysList.
* @param iend: the ending point of the polygon in m_FilledPolysList.
* @param refx,refy: the point coordinate to test
* @param aIdxstart: the starting point of a given polygon in m_FilledPolysList.
* @param aIdxend: the ending point of the polygon in m_FilledPolysList.
* @param aRefx, aRefy: the point coordinate to test
* @return true if the point is inside, false for outside
*/
{
@ -48,7 +48,7 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
int count = 0;
// find all intersection points of line with polyline sides
for( ics = istart, ice = iend; ics <= iend; ice = ics++ )
for( ics = aIdxstart, ice = aIdxend; ics <= aIdxend; ice = ics++ )
{
int seg_startX = aPolysList[ics].x;
int seg_startY = aPolysList[ics].y;
@ -56,14 +56,14 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
int seg_endY = aPolysList[ice].y;
/* Trivial cases: skip if ref above or below the segment to test */
if( ( seg_startY > refy ) && (seg_endY > refy ) )
if( ( seg_startY > aRefy ) && (seg_endY > aRefy ) )
continue;
// segment below ref point, or one of its ends has the same Y pos as the ref point: skip
// So we eliminate one end point of 2 consecutive segments.
// Note: also we skip horizontal segments if ref point is on this horizontal line
// So reference points on horizontal segments outlines always are seen as outside the polygon
if( ( seg_startY <= refy ) && (seg_endY <= refy ) )
if( ( seg_startY <= aRefy ) && (seg_endY <= aRefy ) )
continue;
/* refy is between seg_startY and seg_endY.
@ -76,8 +76,63 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
// this is more easier if we move the X,Y axis origin to the segment start point:
seg_endX -= seg_startX;
seg_endY -= seg_startY;
double newrefx = (double) (refx - seg_startX);
double newrefy = (double) (refy - seg_startY);
double newrefx = (double) (aRefx - seg_startX);
double newrefy = (double) (aRefy - seg_startY);
// Now calculate the x intersection coordinate of the line from (0,0) to (seg_endX,seg_endY)
// with the horizontal line at the new refy position
// the line slope = seg_endY/seg_endX;
// and the x pos relative to the new origin is intersec_x = refy/slope
// Note: because horizontal segments are skipped, 1/slope exists (seg_end_y never == O)
double intersec_x = newrefy * seg_endX / seg_endY;
if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from refx to infinite
count++;
}
return count & 1 ? INSIDE : OUTSIDE;
}
/* Function TestPointInsidePolygon (overlaid)
* same as previous, but use wxPoint and aCount corners
*/
bool TestPointInsidePolygon( wxPoint *aPolysList, int aCount,wxPoint aRefPoint )
{
// count intersection points to right of (refx,refy). If odd number, point (refx,refy) is inside polyline
int ics, ice;
int count = 0;
// find all intersection points of line with polyline sides
for( ics = 0, ice = aCount-1; ics < aCount; ice = ics++ )
{
int seg_startX = aPolysList[ics].x;
int seg_startY = aPolysList[ics].y;
int seg_endX = aPolysList[ice].x;
int seg_endY = aPolysList[ice].y;
/* Trivial cases: skip if ref above or below the segment to test */
if( ( seg_startY > aRefPoint.y ) && (seg_endY > aRefPoint.y ) )
continue;
// segment below ref point, or one of its ends has the same Y pos as the ref point: skip
// So we eliminate one end point of 2 consecutive segments.
// Note: also we skip horizontal segments if ref point is on this horizontal line
// So reference points on horizontal segments outlines always are seen as outside the polygon
if( ( seg_startY <= aRefPoint.y ) && (seg_endY <= aRefPoint.y ) )
continue;
/* refy is between seg_startY and seg_endY.
* note: here: horizontal segments (seg_startY == seg_endY) are skipped,
* either by the first test or by the second test
* see if an horizontal semi infinite line from refx is intersecting the segment
*/
// calculate the x position of the intersection of this segment and the semi infinite line
// this is more easier if we move the X,Y axis origin to the segment start point:
seg_endX -= seg_startX;
seg_endY -= seg_startY;
double newrefx = (double) (aRefPoint.x - seg_startX);
double newrefy = (double) (aRefPoint.y - seg_startY);
// Now calculate the x intersection coordinate of the line from (0,0) to (seg_endX,seg_endY)
// with the horizontal line at the new refy position

View File

@ -2,18 +2,34 @@
// Name: polygon_test_point_inside.h
/////////////////////////////////////////////////////////////////////////////
using namespace std;
#ifndef __WXWINDOWS__
// define here wxPoint if we want to compile outside wxWidgets
class wxPoint
{
public:
int x, y;
};
#endif
/** Function TestPointInsidePolygon
* test if a point is inside or outside a polygon.
* @param aPolysList: the list of polygons
* @param istart: the starting point of a given polygon in m_FilledPolysList.
* @param iend: the ending point of the polygon in m_FilledPolysList.
* @param refx, refy: the point coordinate to test
* @param aIdxstart: the starting point of a given polygon in m_FilledPolysList.
* @param aIdxend: the ending point of the polygon in m_FilledPolysList.
* @param aRefx, aRefy: the point coordinate to test
* @return true if the point is inside, false for outside
*/
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
int istart,
int iend,
int refx,
int refy);
int aIdxstart,
int aIdxend,
int aRefx,
int aRefy);
/** Function TestPointInsidePolygon (overlaid)
* same as previous, but mainly use wxPoint
* @param aPolysList: the list of polygons
* @param aCount: corners count in aPolysList.
* @param aRefPoint: the point coordinate to test
* @return true if the point is inside, false for outside
*/
bool TestPointInsidePolygon( wxPoint* aPolysList,
int aCount,
wxPoint aRefPoint );