DRC code cleaning, and added DRC tests for trapezoidal pads. Needs more tests.
This commit is contained in:
commit
d536f9d914
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
1022
pcbnew/drc.cpp
1022
pcbnew/drc.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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>---------------------------------------------
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue