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
|
dist.cpp
|
||||||
dragsegm.cpp
|
dragsegm.cpp
|
||||||
drc.cpp
|
drc.cpp
|
||||||
|
drc_clearance_test_functions.cpp
|
||||||
drc_marker_functions.cpp
|
drc_marker_functions.cpp
|
||||||
edgemod.cpp
|
edgemod.cpp
|
||||||
edit.cpp
|
edit.cpp
|
||||||
|
|
|
@ -764,17 +764,15 @@ bool D_PAD::IsOnLayer( int aLayer ) const
|
||||||
*/
|
*/
|
||||||
bool D_PAD::HitTest( const wxPoint& ref_pos )
|
bool D_PAD::HitTest( const wxPoint& ref_pos )
|
||||||
{
|
{
|
||||||
int deltaX, deltaY;
|
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
double dist;
|
double dist;
|
||||||
|
|
||||||
wxPoint shape_pos = ReturnShapePos();
|
wxPoint shape_pos = ReturnShapePos();
|
||||||
|
|
||||||
deltaX = ref_pos.x - shape_pos.x;
|
wxPoint delta = ref_pos - shape_pos;
|
||||||
deltaY = ref_pos.y - shape_pos.y;
|
|
||||||
|
|
||||||
/* Quick test: a test point must be inside the circle. */
|
/* 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;
|
return false;
|
||||||
|
|
||||||
dx = m_Size.x >> 1; // dx also is the radius for rounded pads
|
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 )
|
switch( m_PadShape & 0x7F )
|
||||||
{
|
{
|
||||||
case PAD_CIRCLE:
|
case PAD_CIRCLE:
|
||||||
dist = hypot( deltaX, deltaY );
|
dist = hypot( delta.x, delta.y );
|
||||||
if( wxRound( dist ) <= dx )
|
if( wxRound( dist ) <= dx )
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
@ -792,22 +790,13 @@ bool D_PAD::HitTest( const wxPoint& ref_pos )
|
||||||
{
|
{
|
||||||
wxPoint poly[4];
|
wxPoint poly[4];
|
||||||
BuildPadPolygon( poly, wxSize(0,0), 0 );
|
BuildPadPolygon( poly, wxSize(0,0), 0 );
|
||||||
// Build the same polygon with CPolyPt corners,
|
RotatePoint( &delta, -m_Orient );
|
||||||
// to use TestPointInsidePolygon
|
return TestPointInsidePolygon( poly, 4, delta );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
RotatePoint( &deltaX, &deltaY, -m_Orient );
|
RotatePoint( &delta, -m_Orient );
|
||||||
if( (abs( deltaX ) <= dx ) && (abs( deltaY ) <= dy) )
|
if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) )
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ public:
|
||||||
* Function GetShape
|
* Function GetShape
|
||||||
* @return the shape of this pad.
|
* @return the shape of this pad.
|
||||||
*/
|
*/
|
||||||
int GetShape() { return m_PadShape & 0xFF; }
|
int GetShape() const { return m_PadShape & 0xFF; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetPosition
|
* Function GetPosition
|
||||||
|
@ -239,14 +239,26 @@ public:
|
||||||
void DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo );
|
void DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo );
|
||||||
|
|
||||||
/** function BuildPadPolygon
|
/** 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,
|
* Build the Corner list of the polygonal shape,
|
||||||
* depending on shape, extra size (clearance ...) and orientation
|
* depending on shape, extra size (clearance ...) and orientation
|
||||||
* @param aCoord[4] = a buffer to fill.
|
* @param aCoord[4] = a buffer to fill.
|
||||||
* @param aInflateValue = wxSize: the clearance or margin value. value > 0: inflate, < 0 deflate
|
* @param aInflateValue = wxSize: the clearance or margin value. value > 0: inflate, < 0 deflate
|
||||||
* @param aRotation = full rotation of the polygon
|
* @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
|
// others
|
||||||
void SetPadName( const wxString& name ); // Change pad name
|
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 )
|
void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
|
||||||
{
|
{
|
||||||
wxPoint coord[4];
|
wxPoint coord[4];
|
||||||
int rotdx,
|
int delta_cx, delta_cy;
|
||||||
delta_cx, delta_cy;
|
|
||||||
int angle = m_Orient;
|
int angle = m_Orient;
|
||||||
|
int seg_width;
|
||||||
|
|
||||||
GRSetDrawMode( aDC, aDrawInfo.m_DrawMode );
|
GRSetDrawMode( aDC, aDrawInfo.m_DrawMode );
|
||||||
|
|
||||||
|
@ -392,44 +392,30 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAD_OVAL:
|
case PAD_OVAL:
|
||||||
if( halfsize.x > halfsize.y ) /* horizontal */
|
{
|
||||||
{
|
wxPoint segStart, segEnd;
|
||||||
delta_cx = halfsize.x - halfsize.y;
|
seg_width = BuildSegmentFromOvalShape(segStart, segEnd, angle);
|
||||||
delta_cy = 0;
|
segStart += shape_pos;
|
||||||
rotdx = m_Size.y + ( aDrawInfo.m_Mask_margin.y * 2 );
|
segEnd += shape_pos;
|
||||||
}
|
|
||||||
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 );
|
|
||||||
|
|
||||||
if( aDrawInfo.m_ShowPadFilled )
|
if( aDrawInfo.m_ShowPadFilled )
|
||||||
{
|
{
|
||||||
GRFillCSegm( aClipBox, aDC,
|
GRFillCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y,
|
||||||
shape_pos.x + delta_cx, shape_pos.y + delta_cy,
|
seg_width, aDrawInfo.m_Color );
|
||||||
shape_pos.x - delta_cx, shape_pos.y - delta_cy,
|
|
||||||
rotdx, aDrawInfo.m_Color );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GRCSegm( aClipBox, aDC,
|
GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y,
|
||||||
shape_pos.x + delta_cx, shape_pos.y + delta_cy,
|
seg_width, m_PadSketchModePenSize, aDrawInfo.m_Color );
|
||||||
shape_pos.x - delta_cx, shape_pos.y - delta_cy,
|
|
||||||
rotdx, m_PadSketchModePenSize, aDrawInfo.m_Color );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the isolation line. */
|
/* Draw the isolation line. */
|
||||||
if( aDrawInfo.m_PadClearance )
|
if( aDrawInfo.m_PadClearance )
|
||||||
{
|
{
|
||||||
rotdx = rotdx + 2 * aDrawInfo.m_PadClearance;
|
seg_width += 2 * aDrawInfo.m_PadClearance;
|
||||||
|
GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y,
|
||||||
GRCSegm( aClipBox, aDC, shape_pos.x + delta_cx, shape_pos.y + delta_cy,
|
seg_width, aDrawInfo.m_Color );
|
||||||
shape_pos.x - delta_cx, shape_pos.y - delta_cy,
|
|
||||||
rotdx, aDrawInfo.m_Color );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAD_RECT:
|
case PAD_RECT:
|
||||||
|
@ -486,9 +472,6 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
|
||||||
#else
|
#else
|
||||||
if( aDrawInfo.m_Scale * hole > 1 ) /* draw hole if its size is enough */
|
if( aDrawInfo.m_Scale * hole > 1 ) /* draw hole if its size is enough */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GRFilledCircle( aClipBox, aDC, holepos.x, holepos.y, hole, 0,
|
GRFilledCircle( aClipBox, aDC, holepos.x, holepos.y, hole, 0,
|
||||||
aDrawInfo.m_Color, aDrawInfo.m_HoleColor );
|
aDrawInfo.m_Color, aDrawInfo.m_HoleColor );
|
||||||
break;
|
break;
|
||||||
|
@ -501,18 +484,18 @@ void D_PAD::DrawShape( EDA_Rect* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
|
||||||
{
|
{
|
||||||
delta_cx = halfsize.x - halfsize.y;
|
delta_cx = halfsize.x - halfsize.y;
|
||||||
delta_cy = 0;
|
delta_cy = 0;
|
||||||
rotdx = m_Drill.y;
|
seg_width = m_Drill.y;
|
||||||
}
|
}
|
||||||
else /* vertical */
|
else /* vertical */
|
||||||
{
|
{
|
||||||
delta_cx = 0;
|
delta_cx = 0;
|
||||||
delta_cy = halfsize.y - halfsize.x;
|
delta_cy = halfsize.y - halfsize.x;
|
||||||
rotdx = m_Drill.x;
|
seg_width = m_Drill.x;
|
||||||
}
|
}
|
||||||
RotatePoint( &delta_cx, &delta_cy, angle );
|
RotatePoint( &delta_cx, &delta_cy, angle );
|
||||||
|
|
||||||
GRFillCSegm( aClipBox, aDC, holepos.x + delta_cx, holepos.y + delta_cy,
|
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 );
|
aDrawInfo.m_HoleColor );
|
||||||
break;
|
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
|
/** function BuildPadPolygon
|
||||||
* Has meaning only for polygonal pads (trapeziod and rectangular)
|
* 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 aInflateValue = wxSize: the clearance or margin value. value > 0: inflate, < 0 deflate
|
||||||
* @param aRotation = full rotation of the polygon, usually m_Orient
|
* @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) )
|
if( (GetShape() != PAD_RECT) && (GetShape() != PAD_TRAPEZOID) )
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -44,21 +44,17 @@ bool DIALOG_DRC_CONTROL::Show( bool show )
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
D(printf("%s %d\n", __func__, show );)
|
|
||||||
|
|
||||||
if( show )
|
if( show )
|
||||||
{
|
{
|
||||||
ret = DIALOG_DRC_CONTROL_BASE::Show( show );
|
ret = DIALOG_DRC_CONTROL_BASE::Show( show );
|
||||||
|
|
||||||
if( s_LastPos.x != -1 )
|
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 );
|
SetSize( s_LastPos.x, s_LastPos.y, s_LastSize.x, s_LastSize.y, 0 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D(printf("not setting window pos (%d,%d)\n", s_LastPos.x, s_LastPos.y );)
|
// Do nothing: last position not yet saved.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -66,9 +62,6 @@ bool DIALOG_DRC_CONTROL::Show( bool show )
|
||||||
// Save the dialog's position before hiding
|
// Save the dialog's position before hiding
|
||||||
s_LastPos = GetPosition();
|
s_LastPos = GetPosition();
|
||||||
s_LastSize = GetSize();
|
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 );
|
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
|
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;
|
wxString msg;
|
||||||
m_isFlipped = false;
|
m_isFlipped = false;
|
||||||
if( m_CurrentPad )
|
if( m_CurrentPad )
|
||||||
|
@ -298,7 +297,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
||||||
SetPadLayersList( m_dummyPad->m_Masque_Layer );
|
SetPadLayersList( m_dummyPad->m_Masque_Layer );
|
||||||
|
|
||||||
msg.Clear();
|
msg.Clear();
|
||||||
msg << tmp;
|
msg << m_dummyPad->m_Orient;
|
||||||
m_PadOrientCtrl->SetValue( msg );
|
m_PadOrientCtrl->SetValue( msg );
|
||||||
|
|
||||||
// Pad Orient
|
// Pad Orient
|
||||||
|
@ -350,11 +349,10 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
||||||
m_PadOrientCtrl->SetValue( msg );
|
m_PadOrientCtrl->SetValue( msg );
|
||||||
|
|
||||||
// Selection du type
|
// Selection du type
|
||||||
tmp = m_dummyPad->m_Attribut;
|
|
||||||
m_PadType->SetSelection( 0 );
|
m_PadType->SetSelection( 0 );
|
||||||
for( int ii = 0; ii < NBTYPES; ii++ )
|
for( int ii = 0; ii < NBTYPES; ii++ )
|
||||||
{
|
{
|
||||||
if( CodeType[ii] == tmp )
|
if( CodeType[ii] == m_dummyPad->m_Attribut )
|
||||||
{
|
{
|
||||||
m_PadType->SetSelection( ii );
|
m_PadType->SetSelection( ii );
|
||||||
break;
|
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:
|
/* 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
|
* define the area relative to the ref segment that does not contains anu other segment
|
||||||
*/
|
*/
|
||||||
int m_xcliplo;
|
int m_xcliplo;
|
||||||
int m_ycliplo;
|
int m_ycliplo;
|
||||||
int m_xcliphi;
|
int m_xcliphi;
|
||||||
int m_ycliphi;
|
int m_ycliphi;
|
||||||
|
|
||||||
WinEDA_PcbFrame* m_mainWindow;
|
WinEDA_PcbFrame* m_mainWindow;
|
||||||
BOARD* m_pcb;
|
BOARD* m_pcb;
|
||||||
|
@ -329,30 +329,27 @@ private:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function checkMarginToCircle
|
* Helper function checkMarginToCircle
|
||||||
* @todo this translation is no good, fix this:
|
* Check the distance from a point to
|
||||||
* calculates the distance from a circle (via or round end of track) to the
|
* a segment. the segment is expected starting at 0,0, and on the X axis
|
||||||
* segment of reference on the right hand side.
|
* (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 cx The x coordinate of the circle's center
|
* @param aRadius A "keep out" radius centered over the circle
|
||||||
* @param cy The y coordinate of the circle's center
|
* @param aLength The length of the segment (i.e. coordinate of end, becuase it is on the X axis)
|
||||||
* @param radius A "keep out" radius centered over the circle
|
|
||||||
* @param length The length of the segment (i.e. coordinate of end)
|
|
||||||
* @return bool - true if distance >= radius, else
|
* @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
|
* Function checkLine
|
||||||
* tests to see if one track is in contact with another track.
|
* (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)
|
||||||
* Cette routine controle si la ligne (x1,y1 x2,y2) a une partie s'inscrivant
|
* The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi
|
||||||
* dans le cadre (xcliplo,ycliplo xcliphi,ycliphi) (variables globales,
|
* return true if the line from aSegStart to aSegEnd is outside the bounding box
|
||||||
* locales a ce fichier)
|
|
||||||
*/
|
*/
|
||||||
bool checkLine( int x1, int y1, int x2, int y2 );
|
bool checkLine( wxPoint aSegStart, wxPoint aSegEnd );
|
||||||
|
|
||||||
//-----</single tests>---------------------------------------------
|
//-----</single tests>---------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// math for graphics utility routines, from FreePCB
|
// math for graphics utility routines and RC, from FreePCB
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -13,13 +13,14 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
// test for hit on line segment
|
/** function TestLineHit
|
||||||
// i.e. cursor within a given distance from segment
|
* test for hit on line segment i.e. a point within a given distance from segment
|
||||||
// enter with: x,y = cursor coords
|
* @param x, y = cursor coords
|
||||||
// (xi,yi) and (xf,yf) are the end-points of the line segment
|
* @param xi,yi and xf,yf = the end-points of the line segment
|
||||||
// dist = maximum distance for hit
|
* @param dist = maximum distance for hit
|
||||||
//
|
* return true if dist < distance between the point and the segment
|
||||||
int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
|
*/
|
||||||
|
bool TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
|
||||||
{
|
{
|
||||||
double dd;
|
double dd;
|
||||||
|
|
||||||
|
@ -29,14 +30,14 @@ int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
|
||||||
// vertical segment
|
// vertical segment
|
||||||
dd = fabs( (double)(x-xi) );
|
dd = fabs( (double)(x-xi) );
|
||||||
if( dd<dist && ( (yf>yi && y<yf && y>yi) || (yf<yi && y>yf && y<yi) ) )
|
if( dd<dist && ( (yf>yi && y<yf && y>yi) || (yf<yi && y>yf && y<yi) ) )
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
else if( yf==yi )
|
else if( yf==yi )
|
||||||
{
|
{
|
||||||
// horizontal segment
|
// horizontal segment
|
||||||
dd = fabs( (double)(y-yi) );
|
dd = fabs( (double)(y-yi) );
|
||||||
if( dd<dist && ( (xf>xi && x<xf && x>xi) || (xf<xi && x>xf && x<xi) ) )
|
if( dd<dist && ( (xf>xi && x<xf && x>xi) || (xf<xi && x>xf && x<xi) ) )
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
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
|
// line segment more horizontal than vertical
|
||||||
if( dd<dist && ( (xf>xi && xp<xf && xp>xi) || (xf<xi && xp>xf && xp<xi) ) )
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for intersection of line segments
|
/** function TestForIntersectionOfStraightLineSegments
|
||||||
// If lines are parallel, returns false
|
* Test for intersection of line segments
|
||||||
// If true, returns intersection coords in x, y
|
* If lines are parallel, returns false
|
||||||
// if false, returns min. distance in dist (may be 0.0 if parallel)
|
* If true, returns also intersection coords in x, y
|
||||||
// and coords on nearest point in one of the segments 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,
|
bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f,
|
||||||
int x2i, int y2i, int x2f, int y2f,
|
int x2i, int y2i, int x2f, int y2f,
|
||||||
int * x, int * y, double * d )
|
int * x, int * y, double * d )
|
||||||
|
|
|
@ -13,8 +13,6 @@ typedef struct PointTag
|
||||||
typedef struct EllipseTag
|
typedef struct EllipseTag
|
||||||
{
|
{
|
||||||
PointT Center; /* ellipse center */
|
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 xrad, yrad; // radii on x and y
|
||||||
double theta1, theta2; // start and end angle for arc
|
double theta1, theta2; // start and end angle for arc
|
||||||
} EllipseKH;
|
} EllipseKH;
|
||||||
|
@ -22,7 +20,16 @@ typedef struct EllipseTag
|
||||||
|
|
||||||
// math stuff for graphics
|
// math stuff for graphics
|
||||||
bool Quadratic( double a, double b, double c, double *x1, double *x2 );
|
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,
|
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 );
|
double * x1, double * y1, double * x2, double * y2, double * dist=NULL );
|
||||||
int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style,
|
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 );
|
double x[]=NULL, double y[]=NULL );
|
||||||
bool FindLineEllipseIntersections( double a, double b, double c, double d, double *x1, double *x2 );
|
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 );
|
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,
|
bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f,
|
||||||
int x2i, int y2i, int x2f, int y2f,
|
int x2i, int y2i, int x2f, int y2f,
|
||||||
int * x=NULL, int * y=NULL, double * dist=NULL );
|
int * x=NULL, int * y=NULL, double * dist=NULL );
|
||||||
|
|
||||||
int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1,
|
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 x2i, int y2i, int x2f, int y2f, int style2, int w2,
|
||||||
int max_cl, int * x, int * y );
|
int max_cl, int * x, int * y );
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/**
|
||||||
|
* @file polygon_test_point_inside.cpp
|
||||||
// Name: polygon_test_point_inside.cpp
|
*/
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "PolyLine.h"
|
#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:
|
/* 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)
|
* It run a semi-infinite line horizontally (increasing x, fixed y)
|
||||||
* out from the test point, and count how many edges it crosses.
|
* out from the test point, and count how many edges it crosses.
|
||||||
* At each crossing, the ray switches between inside and outside.
|
* At each crossing, the ray switches between inside and outside.
|
||||||
* If odd count, the test point is inside the polygon
|
* 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.
|
* 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:
|
* 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.
|
* 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.
|
||||||
|
@ -30,16 +27,19 @@ using namespace std;
|
||||||
#define INSIDE true
|
#define INSIDE true
|
||||||
|
|
||||||
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
||||||
int istart, int iend, int refx, int refy )
|
int aIdxstart,
|
||||||
|
int aIdxend,
|
||||||
|
int aRefx,
|
||||||
|
int aRefy)
|
||||||
|
|
||||||
/** 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
|
* Use TestPointInside or TestPointInsideContour for more complex polygons
|
||||||
* @param aPolysList: the list of polygons
|
* @param aPolysList: the list of polygons
|
||||||
* @param istart: the starting point of a given polygon in m_FilledPolysList.
|
* @param aIdxstart: the starting point of a given polygon in m_FilledPolysList.
|
||||||
* @param iend: the ending point of the polygon in m_FilledPolysList.
|
* @param aIdxend: the ending point of the polygon in m_FilledPolysList.
|
||||||
* @param refx,refy: 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
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
// find all intersection points of line with polyline sides
|
// 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_startX = aPolysList[ics].x;
|
||||||
int seg_startY = aPolysList[ics].y;
|
int seg_startY = aPolysList[ics].y;
|
||||||
|
@ -56,14 +56,14 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
||||||
int seg_endY = aPolysList[ice].y;
|
int seg_endY = aPolysList[ice].y;
|
||||||
|
|
||||||
/* Trivial cases: skip if ref above or below the segment to test */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
// segment below ref point, or one of its ends has the same Y pos as the ref point: skip
|
// 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.
|
// So we eliminate one end point of 2 consecutive segments.
|
||||||
// Note: also we skip horizontal segments if ref point is on this horizontal line
|
// 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
|
// 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;
|
continue;
|
||||||
|
|
||||||
/* refy is between seg_startY and seg_endY.
|
/* 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:
|
// this is more easier if we move the X,Y axis origin to the segment start point:
|
||||||
seg_endX -= seg_startX;
|
seg_endX -= seg_startX;
|
||||||
seg_endY -= seg_startY;
|
seg_endY -= seg_startY;
|
||||||
double newrefx = (double) (refx - seg_startX);
|
double newrefx = (double) (aRefx - seg_startX);
|
||||||
double newrefy = (double) (refy - seg_startY);
|
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)
|
// 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
|
// with the horizontal line at the new refy position
|
||||||
|
|
|
@ -2,18 +2,34 @@
|
||||||
// Name: polygon_test_point_inside.h
|
// 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
|
/** Function TestPointInsidePolygon
|
||||||
* test if a point is inside or outside a polygon.
|
* test if a point is inside or outside a polygon.
|
||||||
* @param aPolysList: the list of polygons
|
* @param aPolysList: the list of polygons
|
||||||
* @param istart: the starting point of a given polygon in m_FilledPolysList.
|
* @param aIdxstart: the starting point of a given polygon in m_FilledPolysList.
|
||||||
* @param iend: the ending point of the polygon in m_FilledPolysList.
|
* @param aIdxend: the ending point of the polygon in m_FilledPolysList.
|
||||||
* @param refx, refy: 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
|
||||||
*/
|
*/
|
||||||
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
|
||||||
int istart,
|
int aIdxstart,
|
||||||
int iend,
|
int aIdxend,
|
||||||
int refx,
|
int aRefx,
|
||||||
int refy);
|
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