Commit 90a6daa7 authored by jean-pierre charras's avatar jean-pierre charras

Cleanup math_for_graphic code

parent dfdd2cfd
......@@ -387,8 +387,8 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
yf2 = poly2->GetY( is2 );
}
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, STRAIGHT,
xi2, yi2, xf2, yf2, STRAIGHT );
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1,
xi2, yi2, xf2, yf2 );
if( n_int )
return true;
}
......@@ -498,8 +498,8 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
yf2 = poly2->GetY( is2 );
}
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, STRAIGHT,
xi2, yi2, xf2, yf2, STRAIGHT );
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1,
xi2, yi2, xf2, yf2 );
if( n_int )
{
bInt = true;
......@@ -844,10 +844,8 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
int x, y;
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
STRAIGHT,
0,
ax1, ay1, ax2, ay2,
STRAIGHT,
0,
zone2zoneClearance,
&x, &y );
......@@ -987,9 +985,9 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
}
int x, y; // variables containing the intersecting point coordinates
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, STRAIGHT,
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
0,
ax1, ay1, ax2, ay2, STRAIGHT,
ax1, ay1, ax2, ay2,
0,
zone_clearance,
&x, &y );
......
......@@ -1112,7 +1112,6 @@ void CPolyLine::Hatch()
m_CornersList[ic].x, m_CornersList[ic].y,
m_CornersList[i_start_contour].x,
m_CornersList[i_start_contour].y,
STRAIGHT,
&x, &y, &x2, &y2 );
i_start_contour = ic + 1;
}
......@@ -1121,7 +1120,6 @@ void CPolyLine::Hatch()
ok = FindLineSegmentIntersection( a, slope,
m_CornersList[ic].x, m_CornersList[ic].y,
m_CornersList[ic + 1].x, m_CornersList[ic + 1].y,
STRAIGHT,
&x, &y, &x2, &y2 );
}
......@@ -1387,9 +1385,9 @@ int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth )
by2 = GetY( ic2 + 1 );
}
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, STRAIGHT, 0,
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, 0,
aStart.x, aStart.y, aEnd.x, aEnd.y,
STRAIGHT, aWidth,
aWidth,
1, // min clearance, should be > 0
NULL, NULL );
......@@ -1689,9 +1687,7 @@ bool CPolyLine::IsPolygonSelfIntersecting()
int x2f = GetX( is2_next );
int y2f = GetY( is2_next );
int ret = FindSegmentIntersections( x1i, y1i, x1f, y1f,
STRAIGHT,
x2i, y2i, x2f, y2f,
STRAIGHT );
x2i, y2i, x2f, y2f );
if( ret )
{
// intersection between non-adjacent sides
......
......@@ -11,42 +11,13 @@
#include <PolyLine.h>
#include <math_for_graphics.h>
#define NM_PER_MIL 25400
typedef struct PointTag
{
double X,Y;
} PointT;
typedef struct EllipseTag
{
PointT Center; /* ellipse center */
double xrad, yrad; // radii on x and y
double theta1, theta2; // start and end angle for arc
} EllipseKH;
static bool InRange( double x, double xi, double xf );
double Distance( double x1, double y1, double x2, double y2 )
{
double dx = x1 - x2;
double dy = y1 - y2;
double d = sqrt( dx * dx + dy * dy );
return d;
return hypot( x1 - x2, y1 - y2 );
}
static bool Quadratic( double a, double b, double c, double *x1, double *x2 );
static bool FindLineEllipseIntersections( double a, double b, double c, double d, double *x1, double *x2 );
static bool FindVerticalLineEllipseIntersections( double a, double b, double x, double *y1, double *y2 );
static int GetArcIntersections( EllipseKH * el1, EllipseKH * el2,
double * x1=NULL, double * y1=NULL,
double * x2=NULL, double * y2=NULL );
static bool InRange( double x, double xi, double xf );
enum m_SideStyle { STRAIGHT, ARC_CW, ARC_CCW }; // side styles
/**
* Function TestLineHit
* test for hit on line segment i.e. a point within a given distance from segment
......@@ -109,271 +80,33 @@ bool TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist )
}
// set EllipseKH struct to describe the ellipse for an arc
//
int MakeEllipseFromArc( int xi, int yi, int xf, int yf, int style, EllipseKH* el )
{
// arc (quadrant of ellipse)
// convert to clockwise arc
int xxi, xxf, yyi, yyf;
if( style == ARC_CCW )
{
xxi = xf;
xxf = xi;
yyi = yf;
yyf = yi;
}
else
{
xxi = xi;
xxf = xf;
yyi = yi;
yyf = yf;
}
// find center and radii of ellipse
double xo = 0, yo = 0;
if( xxf > xxi && yyf > yyi )
{
xo = xxf;
yo = yyi;
el->theta1 = M_PI;
el->theta2 = M_PI / 2.0;
}
else if( xxf < xxi && yyf > yyi )
{
xo = xxi;
yo = yyf;
el->theta1 = -M_PI / 2.0;
el->theta2 = -M_PI;
}
else if( xxf < xxi && yyf < yyi )
{
xo = xxf;
yo = yyi;
el->theta1 = 0.0;
el->theta2 = -M_PI / 2.0;
}
else if( xxf > xxi && yyf < yyi )
{
xo = xxi;
yo = yyf;
el->theta1 = M_PI / 2.0;
el->theta2 = 0.0;
}
el->Center.X = xo;
el->Center.Y = yo;
el->xrad = abs( xf - xi );
el->yrad = abs( yf - yi );
#if 0
el->Phi = 0.0;
el->MaxRad = el->xrad;
el->MinRad = el->yrad;
if( el->MaxRad < el->MinRad )
{
el->MaxRad = el->yrad;
el->MinRad = el->xrad;
el->Phi = M_PI / 2.0;
}
#endif
return 0;
}
// find intersections between line segment (xi,yi) to (xf,yf)
// and line segment (xi2,yi2) to (xf2,yf2)
// the line segments may be arcs (i.e. quadrant of an ellipse) or straight
// returns number of intersections found (max of 2)
// returns coords of intersections in arrays x[2], y[2]
//
int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style,
int xi2, int yi2, int xf2, int yf2, int style2,
double x[], double y[] )
/* Function FindSegmentIntersections
* find intersections between line segment (xi,yi) to (xf,yf)
* and line segment (xi2,yi2) to (xf2,yf2)
* returns true if intersection found
*/
bool FindSegmentIntersections( int xi, int yi, int xf, int yf,
int xi2, int yi2, int xf2, int yf2 )
{
double xr[12], yr[12];
int iret = 0;
if( max( xi, xf ) < min( xi2, xf2 )
|| min( xi, xf ) > max( xi2, xf2 )
|| max( yi, yf ) < min( yi2, yf2 )
|| min( yi, yf ) > max( yi2, yf2 ) )
return 0;
if( style != STRAIGHT && style2 != STRAIGHT )
{
// two identical arcs intersect
if( style == style2 && xi == xi2 && yi == yi2 && xf == xf2 && yf == yf2 )
{
if( x && y )
{
x[0] = xi;
y[0] = yi;
}
return 1;
}
else if( style != style2 && xi == xf2 && yi == yf2 && xf == xi2 && yf == yi2 )
{
if( x && y )
{
x[0] = xi;
y[0] = yi;
}
return 1;
}
}
if( style == STRAIGHT && style2 == STRAIGHT )
{
// both straight-line segments
int x, y;
bool bYes = TestForIntersectionOfStraightLineSegments( xi,
yi,
xf,
yf,
xi2,
yi2,
xf2,
yf2,
&x,
&y );
if( !bYes )
return 0;
xr[0] = x;
yr[0] = y;
iret = 1;
}
else if( style == STRAIGHT )
{
// first segment is straight, second segment is an arc
int ret;
double x1r, y1r, x2r, y2r;
if( xf == xi )
{
// vertical first segment
double a = xi;
double b = DBL_MAX / 2.0;
ret = FindLineSegmentIntersection( a, b, xi2, yi2, xf2, yf2, style2,
&x1r, &y1r, &x2r, &y2r );
}
else
{
double b = (double) (yf - yi) / (double) (xf - xi);
double a = yf - b * xf;
ret = FindLineSegmentIntersection( a, b, xi2, yi2, xf2, yf2, style2,
&x1r, &y1r, &x2r, &y2r );
}
if( ret == 0 )
return 0;
if( InRange( x1r, xi, xf ) && InRange( y1r, yi, yf ) )
{
xr[iret] = x1r;
yr[iret] = y1r;
iret++;
}
if( ret == 2 )
{
if( InRange( x2r, xi, xf ) && InRange( y2r, yi, yf ) )
{
xr[iret] = x2r;
yr[iret] = y2r;
iret++;
}
}
}
else if( style2 == STRAIGHT )
{
// first segment is an arc, second segment is straight
int ret;
double x1r, y1r, x2r, y2r;
if( xf2 == xi2 )
{
// vertical second segment
double a = xi2;
double b = DBL_MAX / 2.0;
ret = FindLineSegmentIntersection( a, b, xi, yi, xf, yf, style,
&x1r, &y1r, &x2r, &y2r );
}
else
{
double b = (double) (yf2 - yi2) / (double) (xf2 - xi2);
double a = yf2 - b * xf2;
ret = FindLineSegmentIntersection( a, b, xi, yi, xf, yf, style,
&x1r, &y1r, &x2r, &y2r );
}
if( ret == 0 )
return 0;
if( InRange( x1r, xi2, xf2 ) && InRange( y1r, yi2, yf2 ) )
{
xr[iret] = x1r;
yr[iret] = y1r;
iret++;
}
if( ret == 2 )
{
if( InRange( x2r, xi2, xf2 ) && InRange( y2r, yi2, yf2 ) )
{
xr[iret] = x2r;
yr[iret] = y2r;
iret++;
}
}
}
else
{
// both segments are arcs
EllipseKH el1;
EllipseKH el2;
MakeEllipseFromArc( xi, yi, xf, yf, style, &el1 );
MakeEllipseFromArc( xi2, yi2, xf2, yf2, style2, &el2 );
int n;
if( el1.xrad + el1.yrad > el2.xrad + el2.yrad )
n = GetArcIntersections( &el1, &el2 );
else
n = GetArcIntersections( &el2, &el1 );
iret = n;
}
if( x && y )
{
for( int i = 0; i<iret; i++ )
{
x[i] = xr[i];
y[i] = yr[i];
}
}
return false;
return iret;
return TestForIntersectionOfStraightLineSegments( xi, yi, xf, yf,
xi2, yi2, xf2, yf2 );
}
// find intersection between line y = a + bx and line segment (xi,yi) to (xf,yf)
// if b > DBL_MAX/10, assume vertical line at x = a
// the line segment may be an arc (i.e. quadrant of an ellipse)
// return 0 if no intersection
// returns 1 or 2 if intersections found
// sets coords of intersections in *x1, *y1, *x2, *y2
// if no intersection, returns min distance in dist
//
int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf, int style,
/* Function FindLineSegmentIntersection
* find intersection between line y = a + bx and line segment (xi,yi) to (xf,yf)
* if b > DBL_MAX/10, assume vertical line at x = a
* return false if no intersection or true if intersect
* return coords of intersections in *x1, *y1, *x2, *y2
* if no intersection, returns min distance in dist
*/
bool FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf,
double* x1, double* y1, double* x2, double* y2,
double* dist )
{
......@@ -383,188 +116,66 @@ int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int
if( b > DBL_MAX / 10.0 )
bVert = true;
if( xf != xi )
if( xf != xi ) // non-vertical segment, get intersection
{
// non-vertical segment, get intersection
if( style == STRAIGHT || yf == yi )
{
// horizontal or oblique straight segment
// put into form y = c + dx;
double d = (double) (yf - yi) / (double) (xf - xi);
double c = yf - d * xf;
// horizontal or oblique straight segment
// put into form y = c + dx;
double d = (double) (yf - yi) / (double) (xf - xi);
double c = yf - d * xf;
if( bVert )
{
// if vertical line, easy
if( InRange( a, xi, xf ) )
{
*x1 = a;
*y1 = c + d * a;
return 1;
}
else
{
if( dist )
*dist = min( abs( a - xi ), abs( a - xf ) );
return 0;
}
}
if( fabs( b - d ) < 1E-12 )
{
// parallel lines
if( dist )
{
*dist = GetPointToLineDistance( a, b, xi, xf );
}
return 0; // lines parallel
}
// calculate intersection
xx = (c - a) / (b - d);
yy = a + b * (xx);
// see if intersection is within the line segment
if( yf == yi )
{
// horizontal line
if( (xx>=xi && xx>xf) || (xx<=xi && xx<xf) )
return 0;
}
else
{
// oblique line
if( (xx>=xi && xx>xf) || (xx<=xi && xx<xf)
|| (yy>yi && yy>yf) || (yy<yi && yy<yf) )
return 0;
}
}
else if( style == ARC_CW || style == ARC_CCW )
if( bVert )
{
// arc (quadrant of ellipse)
// convert to clockwise arc
int xxi, xxf, yyi, yyf;
if( style == ARC_CCW )
// if vertical line, easy
if( InRange( a, xi, xf ) )
{
xxi = xf;
xxf = xi;
yyi = yf;
yyf = yi;
*x1 = a;
*y1 = c + d * a;
return 1;
}
else
{
xxi = xi;
xxf = xf;
yyi = yi;
yyf = yf;
}
// find center and radii of ellipse
double xo = xxf, yo = yyi, rx, ry; // Init made to avoid C compil warnings
if( dist )
*dist = min( abs( a - xi ), abs( a - xf ) );
if( xxf > xxi && yyf > yyi )
{
xo = xxf;
yo = yyi;
return false;
}
else if( xxf < xxi && yyf > yyi )
{
xo = xxi;
yo = yyf;
}
else if( xxf < xxi && yyf < yyi )
{
xo = xxf;
yo = yyi;
}
else if( xxf > xxi && yyf < yyi )
{
xo = xxi;
yo = yyf;
}
rx = fabs( (double) (xxi - xxf) );
ry = fabs( (double) (yyi - yyf) );
bool test;
double xx1, xx2, yy1, yy2, aa;
}
if( bVert )
{
// shift vertical line to coordinate system of ellipse
aa = a - xo;
test = FindVerticalLineEllipseIntersections( rx, ry, aa, &yy1, &yy2 );
if( !test )
return 0;
// shift back to PCB coordinates
yy1 += yo;
yy2 += yo;
xx1 = a;
xx2 = a;
}
else
if( fabs( b - d ) < 1E-12 )
{
// parallel lines
if( dist )
{
// shift line to coordinate system of ellipse
aa = a + b * xo - yo;
test = FindLineEllipseIntersections( rx, ry, aa, b, &xx1, &xx2 );
if( !test )
return 0;
// shift back to PCB coordinates
yy1 = aa + b * xx1;
xx1 += xo;
yy1 += yo;
yy2 = aa + b * xx2;
xx2 += xo;
yy2 += yo;
*dist = GetPointToLineDistance( a, b, xi, xf );
}
int npts = 0;
if( (xxf>xxi && xx1<xxf && xx1>xxi) || (xxf<xxi && xx1<xxi && xx1>xxf) )
{
if( (yyf>yyi && yy1<yyf && yy1>yyi) || (yyf<yyi && yy1<yyi && yy1>yyf) )
{
*x1 = xx1;
*y1 = yy1;
npts = 1;
}
}
return false; // lines parallel
}
if( (xxf>xxi && xx2<xxf && xx2>xxi) || (xxf<xxi && xx2<xxi && xx2>xxf) )
{
if( (yyf>yyi && yy2<yyf && yy2>yyi) || (yyf<yyi && yy2<yyi && yy2>yyf) )
{
if( npts == 0 )
{
*x1 = xx2;
*y1 = yy2;
npts = 1;
}
else
{
*x2 = xx2;
*y2 = yy2;
npts = 2;
}
}
}
// calculate intersection
xx = (c - a) / (b - d);
yy = a + b * (xx);
return npts;
// see if intersection is within the line segment
if( yf == yi )
{
// horizontal line
if( (xx>=xi && xx>xf) || (xx<=xi && xx<xf) )
return false;
}
else
wxASSERT( 0 );
{
// oblique line
if( (xx>=xi && xx>xf) || (xx<=xi && xx<xf)
|| (yy>yi && yy>yf) || (yy<yi && yy<yf) )
return false;
}
}
else
{
// vertical line segment
if( bVert )
return 0;
return false;
xx = xi;
yy = a + b * xx;
......@@ -575,7 +186,7 @@ int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int
*x1 = xx;
*y1 = yy;
return 1;
return true;
}
......@@ -645,7 +256,7 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
a = (double) y2i - b * x2i;
double x1, y1, x2, y2;
int test = FindLineSegmentIntersection( a, b, x1i, y1i, x1f, y1f, STRAIGHT,
int test = FindLineSegmentIntersection( a, b, x1i, y1i, x1f, y1f,
&x1, &y1, &x2, &y2 );
if( test )
......@@ -673,7 +284,7 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
a = (double) y2i - b * x2i;
double x1, y1, x2, y2;
int test = FindLineSegmentIntersection( a, b, x1i, y1i, x1f, y1f, STRAIGHT,
int test = FindLineSegmentIntersection( a, b, x1i, y1i, x1f, y1f,
&x1, &y1, &x2, &y2 );
if( test )
......@@ -701,7 +312,7 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
a = (double) y1i - b * x1i;
double x1, y1, x2, y2;
int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f, STRAIGHT,
int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f,
&x1, &y1, &x2, &y2 );
if( test )
......@@ -729,7 +340,7 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
a = (double) y1i - b * x1i;
double x1, y1, x2, y2;
int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f, STRAIGHT,
int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f,
&x1, &y1, &x2, &y2 );
if( test )
......@@ -759,17 +370,8 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
a = (double) y1i - b * x1i;
double x1, y1, x2, y2;
int test = FindLineSegmentIntersection( a,
b,
x2i,
y2i,
x2f,
y2f,
STRAIGHT,
&x1,
&y1,
&x2,
&y2 );
int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f,
&x1, &y1, &x2, &y2 );
// both segments oblique
if( test )
......@@ -836,62 +438,13 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
}
/*solves the Quadratic equation = a*x*x + b*x + c
/* Function GetClearanceBetweenSegments
* Get clearance between 2 segments
* Returns coordinates of the closest point between these 2 segments in x, y
* If clearance > max_cl, just returns max_cl+1 and doesn't return x,y
*/
bool Quadratic( double a, double b, double c, double* x1, double* x2 )
{
double root = b * b - 4.0 * a * c;
if( root < 0.0 )
return false;
root = sqrt( root );
*x1 = (-b + root) / (2.0 * a);
*x2 = (-b - root) / (2.0 * a);
return true;
}
// finds intersections of vertical line at x
// with ellipse defined by (x^2)/(a^2) + (y^2)/(b^2) = 1;
// returns true if solution exist, with solutions in y1 and y2
// else returns false
//
bool FindVerticalLineEllipseIntersections( double a, double b, double x, double* y1, double* y2 )
{
double y_sqr = ( 1.0 - (x * x) / (a * a) ) * b * b;
if( y_sqr < 0.0 )
return false;
*y1 = sqrt( y_sqr );
*y2 = -*y1;
return true;
}
// finds intersections of straight line y = c + dx
// with ellipse defined by (x^2)/(a^2) + (y^2)/(b^2) = 1;
// returns true if solution exist, with solutions in x1 and x2
// else returns false
//
bool FindLineEllipseIntersections( double a, double b, double c, double d, double* x1, double* x2 )
{
// quadratic terms
double A = d * d + b * b / (a * a);
double B = 2.0 * c * d;
double C = c * c - b * b;
return Quadratic( A, B, C, x1, x2 );
}
// Get clearance between 2 segments
// Returns point in segment closest to other segment in x, y
// in clearance > max_cl, just returns max_cl+1 and doesn't return x,y
//
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 GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int w1,
int x2i, int y2i, int x2f, int y2f, int w2,
int max_cl, int* x, int* y )
{
// check clearance between bounding rectangles
......@@ -909,205 +462,29 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
if( min( y2i, y2f ) - max( y1i, y1f ) > min_dist )
return max_cl+1;
if( style1 == STRAIGHT && style1 == STRAIGHT )
{
// both segments are straight lines
int xx, yy;
double dd;
TestForIntersectionOfStraightLineSegments( x1i, y1i, x1f, y1f,
x2i, y2i, x2f, y2f, &xx, &yy, &dd );
int d = (int) dd - ( (w1 + w2) / 2 );
if( d < 0 )
d = 0;
if( x )
*x = xx;
if( y )
*y = yy;
return d;
}
// not both straight-line segments
// see if segments intersect
double xr[2];
double yr[2];
int count =
FindSegmentIntersections( x1i, y1i, x1f, y1f, style1, x2i, y2i, x2f, y2f, style2, xr, yr );
if( count )
{
if( x )
*x = (int) xr[0];
if( y )
*y = (int) yr[0];
return 0;
}
// at least one segment is an arc
EllipseKH el1;
EllipseKH el2;
bool bArcs;
int xi = 0, yi = 0, xf = 0, yf = 0;
if( style2 == STRAIGHT )
{
// style1 = arc, style2 = straight
MakeEllipseFromArc( x1i, y1i, x1f, y1f, style1, &el1 );
xi = x2i;
yi = y2i;
xf = x2f;
yf = y2f;
bArcs = false;
}
else if( style1 == STRAIGHT )
{
// style2 = arc, style1 = straight
xi = x1i;
yi = y1i;
xf = x1f;
yf = y1f;
MakeEllipseFromArc( x2i, y2i, x2f, y2f, style2, &el1 );
bArcs = false;
}
else
{
// style1 = arc, style2 = arc
MakeEllipseFromArc( x1i, y1i, x1f, y1f, style1, &el1 );
MakeEllipseFromArc( x2i, y2i, x2f, y2f, style2, &el2 );
bArcs = true;
}
const int NSTEPS = 32;
if( el1.theta2 > el1.theta1 )
{
wxASSERT( 0 );
}
if( bArcs && el2.theta2 > el2.theta1 )
{
wxASSERT( 0 );
}
// test multiple points in both segments
double th1;
double th2;
double len2;
if( bArcs )
{
th1 = el2.theta1;
th2 = el2.theta2;
len2 = max( el2.xrad, el2.yrad );
}
else
{
th1 = 1.0;
th2 = 0.0;
len2 = abs( xf - xi ) + abs( yf - yi );
}
double s_start = el1.theta1;
double s_end = el1.theta2;
double s_start2 = th1;
double s_end2 = th2;
double dmin = DBL_MAX;
double xmin = 0, ymin = 0, smin = 0, smin2 = 0; // Init made to avoid C compil warnings
int nsteps = NSTEPS;
int nsteps2 = NSTEPS;
double step = (s_start - s_end) / (nsteps - 1);
double step2 = (s_start2 - s_end2) / (nsteps2 - 1);
while( ( step * max( el1.xrad, el1.yrad ) ) > 0.1 * NM_PER_MIL
&& (step2 * len2) > 0.1 * NM_PER_MIL )
{
step = (s_start - s_end) / (nsteps - 1);
for( int i = 0; i<nsteps; i++ )
{
double s;
if( i < nsteps - 1 )
s = s_start - i * step;
else
s = s_end;
double x = el1.Center.X + el1.xrad * cos( s );
double y = el1.Center.Y + el1.yrad * sin( s );
// if not an arc, use s2 as fractional distance along line
step2 = (s_start2 - s_end2) / (nsteps2 - 1);
for( int i2 = 0; i2<nsteps2; i2++ )
{
double s2;
if( i2 < nsteps2 - 1 )
s2 = s_start2 - i2 * step2;
else
s2 = s_end2;
double x2, y2;
if( !bArcs )
{
x2 = xi + (xf - xi) * s2;
y2 = yi + (yf - yi) * s2;
}
else
{
x2 = el2.Center.X + el2.xrad* cos( s2 );
y2 = el2.Center.Y + el2.yrad* sin( s2 );
}
double d = Distance( x, y, x2, y2 );
if( d < dmin )
{
dmin = d;
xmin = x;
ymin = y;
smin = s;
smin2 = s2;
}
}
}
if( step > step2 )
{
s_start = min( el1.theta1, smin + step );
s_end = max( el1.theta2, smin - step );
step = (s_start - s_end) / nsteps;
}
else
{
s_start2 = min( th1, smin2 + step2 );
s_end2 = max( th2, smin2 - step2 );
step2 = (s_start2 - s_end2) / nsteps2;
}
}
int xx, yy;
double dist;
TestForIntersectionOfStraightLineSegments( x1i, y1i, x1f, y1f,
x2i, y2i, x2f, y2f, &xx, &yy, &dist );
int d = (int) dist - ( (w1 + w2) / 2 );
if( d < 0 )
d = 0;
if( x )
*x = (int) xmin;
*x = xx;
if( y )
*y = (int) ymin;
*y = yy;
return max( 0, (int) dmin - w1 / 2 - w2 / 2 ); // allow for widths
return d;
}
// Get min. distance from (x,y) to line y = a + bx
// if b > DBL_MAX/10, assume vertical line at x = a
// returns closest point on line in xp, yp
//
/* Function GetPointToLineDistance
* Get min. distance from (x,y) to line y = a + bx
* if b > DBL_MAX/10, assume vertical line at x = a
* returns closest point on line in xpp, ypp
*/
double GetPointToLineDistance( double a, double b, int x, int y, double* xpp, double* ypp )
{
if( b > DBL_MAX / 10 )
......@@ -1141,9 +518,6 @@ double GetPointToLineDistance( double a, double b, int x, int y, double* xpp, do
}
/***********************************************************************************/
double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf )
/***********************************************************************************/
/**
* Function GetPointToLineSegmentDistance
* Get distance between line segment and point
......@@ -1152,6 +526,7 @@ double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int
* @param xf,yf End point of the line segment
* @return the distance
*/
double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf )
{
// test for vertical or horizontal segment
if( xf==xi )
......@@ -1195,7 +570,6 @@ double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int
// test for value within range
//
bool InRange( double x, double xi, double xf )
{
if( xf > xi )
......@@ -1211,211 +585,3 @@ bool InRange( double x, double xi, double xf )
return false;
}
// this finds approximate solutions
// note: this works best if el2 is smaller than el1
//
int GetArcIntersections( EllipseKH* el1, EllipseKH* el2,
double* x1, double* y1, double* x2, double* y2 )
{
if( el1->theta2 > el1->theta1 )
{
wxASSERT( 0 );
}
if( el2->theta2 > el2->theta1 )
{
wxASSERT( 0 );
}
const int NSTEPS = 32;
double xret[2], yret[2];
double xscale = 1.0 / el1->xrad;
double yscale = 1.0 / el1->yrad;
// now transform params of second ellipse into reference frame
// with origin at center if first ellipse,
// scaled so the first ellipse is a circle of radius = 1.0
double xo = (el2->Center.X - el1->Center.X) * xscale;
double yo = (el2->Center.Y - el1->Center.Y) * yscale;
double xr = el2->xrad * xscale;
double yr = el2->yrad * yscale;
// now test NSTEPS positions in arc, moving clockwise (ie. decreasing theta)
double step = M_PI / ( (NSTEPS - 1) * 2.0 );
double d_prev = 0;
double th_interp;
double th1;
int n = 0;
for( int i = 0; i<NSTEPS; i++ )
{
double theta;
if( i < NSTEPS - 1 )
theta = el2->theta1 - i * step;
else
theta = el2->theta2;
double x = xo + xr * cos( theta );
double y = yo + yr * sin( theta );
double d = 1.0 - sqrt( x * x + y * y );
if( i>0 )
{
bool bInt = false;
if( d >= 0.0 && d_prev <= 0.0 )
{
th_interp = theta + ( step * (-d_prev) ) / (d - d_prev);
bInt = true;
}
else if( d <= 0.0 && d_prev >= 0.0 )
{
th_interp = theta + (step * d_prev) / (d_prev - d);
bInt = true;
}
if( bInt )
{
x = xo + xr * cos( th_interp );
y = yo + yr * sin( th_interp );
th1 = atan2( y, x );
if( th1 <= el1->theta1 && th1 >= el1->theta2 )
{
xret[n] = x * el1->xrad + el1->Center.X;
yret[n] = y * el1->yrad + el1->Center.Y;
n++;
if( n > 2 )
{
wxASSERT( 0 );
}
}
}
}
d_prev = d;
}
if( x1 )
*x1 = xret[0];
if( y1 )
*y1 = yret[0];
if( x2 )
*x2 = xret[1];
if( y2 )
*y2 = yret[1];
return n;
}
// this finds approximate solution
//
// double GetSegmentClearance( EllipseKH * el1, EllipseKH * el2,
double GetArcClearance( EllipseKH* el1, EllipseKH* el2,
double* x1, double* y1 )
{
const int NSTEPS = 32;
if( el1->theta2 > el1->theta1 )
{
wxASSERT( 0 );
}
if( el2->theta2 > el2->theta1 )
{
wxASSERT( 0 );
}
// test multiple positions in both arcs, moving clockwise (ie. decreasing theta)
double th_start = el1->theta1;
double th_end = el1->theta2;
double th_start2 = el2->theta1;
double th_end2 = el2->theta2;
double dmin = DBL_MAX;
double xmin = 0, ymin = 0, thmin = 0, thmin2 = 0;
int nsteps = NSTEPS;
int nsteps2 = NSTEPS;
double step = (th_start - th_end) / (nsteps - 1);
double step2 = (th_start2 - th_end2) / (nsteps2 - 1);
while( ( step * max( el1->xrad, el1->yrad ) ) > 1.0 * NM_PER_MIL
&& ( step2 * max( el2->xrad, el2->yrad ) ) > 1.0 * NM_PER_MIL )
{
step = (th_start - th_end) / (nsteps - 1);
for( int i = 0; i<nsteps; i++ )
{
double theta;
if( i < nsteps - 1 )
theta = th_start - i * step;
else
theta = th_end;
double x = el1->Center.X + el1->xrad * cos( theta );
double y = el1->Center.Y + el1->yrad * sin( theta );
step2 = (th_start2 - th_end2) / (nsteps2 - 1);
for( int i2 = 0; i2<nsteps2; i2++ )
{
double theta2;
if( i2 < nsteps2 - 1 )
theta2 = th_start2 - i2 * step2;
else
theta2 = th_end2;
double x2 = el2->Center.X + el2->xrad * cos( theta2 );
double y2 = el2->Center.Y + el2->yrad * sin( theta2 );
double d = Distance( x, y, x2, y2 );
if( d < dmin )
{
dmin = d;
xmin = x;
ymin = y;
thmin = theta;
thmin2 = theta2;
}
}
}
if( step > step2 )
{
th_start = min( el1->theta1, thmin + step );
th_end = max( el1->theta2, thmin - step );
step = (th_start - th_end) / nsteps;
}
else
{
th_start2 = min( el2->theta1, thmin2 + step2 );
th_end2 = max( el2->theta2, thmin2 - step2 );
step2 = (th_start2 - th_end2) / nsteps2;
}
}
if( x1 )
*x1 = xmin;
if( y1 )
*y1 = ymin;
return dmin;
}
......@@ -10,12 +10,23 @@
*/
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,
/* Function FindLineSegmentIntersection
* find intersection between line y = a + bx and line segment (xi,yi) to (xf,yf)
* if b > DBL_MAX/10, assume vertical line at x = a
* return false if no intersection or true if intersect
* return coords of intersections in *x1, *y1, *x2, *y2
* if no intersection, returns min distance in dist
*/
bool FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf,
double * x1, double * y1, double * x2, double * y2, double * dist=NULL );
int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style,
int xi2, int yi2, int xf2, int yf2, int style2,
double x[]=NULL, double y[]=NULL );
/* Function FindSegmentIntersections
* find intersections between line segment (xi,yi) to (xf,yf)
* and line segment (xi2,yi2) to (xf2,yf2)
* returns true if intersection found
*/
bool FindSegmentIntersections( int xi, int yi, int xf, int yf,
int xi2, int yi2, int xf2, int yf2 );
/**
* Function TestForIntersectionOfStraightLineSegments
......@@ -34,8 +45,13 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
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,
/* Function GetClearanceBetweenSegments
* Get clearance between 2 segments
* Returns coordinates of the closest point between these 2 segments in x, y
* If clearance > max_cl, just returns max_cl+1 and doesn't return x,y
*/
int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int w1,
int x2i, int y2i, int x2f, int y2f, int w2,
int max_cl, int * x, int * y );
/**
......@@ -47,6 +63,11 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
*/
double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf );
/* Function GetPointToLineDistance
* Get min. distance from (x,y) to line y = a + bx
* if b > DBL_MAX/10, assume vertical line at x = a
* returns closest point on line in xpp, ypp
*/
double GetPointToLineDistance( double a, double b, int x, int y, double * xp=NULL, double * yp=NULL );
double Distance( double x1, double y1, double x2, double y2 );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment