diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index 00cada3d40..63e7a1fe79 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -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 ); diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 130cc00ef7..d79f3628ee 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -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 diff --git a/polygon/math_for_graphics.cpp b/polygon/math_for_graphics.cpp index 5f360dc252..a1b06b393d 100644 --- a/polygon/math_for_graphics.cpp +++ b/polygon/math_for_graphics.cpp @@ -11,42 +11,13 @@ #include #include -#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 ) +/* 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 ) { - // 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[] ) -{ - 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; + return false; - 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 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; + + if( bVert ) { - // 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 ) ) { - // 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=xi && xx>xf) || (xx<=xi && xxyi && yy>yf) || (yy xxi && yyf > yyi ) - { - xo = xxf; - yo = yyi; - } - 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; - } + // calculate intersection + xx = (c - a) / (b - d); + yy = a + b * (xx); - 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 - { - // 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; - } - - int npts = 0; - - if( (xxf>xxi && xx1xxi) || (xxfxxf) ) - { - if( (yyf>yyi && yy1yyi) || (yyfyyf) ) - { - *x1 = xx1; - *y1 = yy1; - npts = 1; - } - } - - if( (xxf>xxi && xx2xxi) || (xxfxxf) ) - { - if( (yyf>yyi && yy2yyi) || (yyfyyf) ) - { - if( npts == 0 ) - { - *x1 = xx2; - *y1 = yy2; - npts = 1; - } - else - { - *x2 = xx2; - *y2 = yy2; - npts = 2; - } - } - } - - return npts; + // see if intersection is within the line segment + if( yf == yi ) + { + // horizontal line + if( (xx>=xi && xx>xf) || (xx<=xi && xx=xi && xx>xf) || (xx<=xi && xxyi && yy>yf) || (yy 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 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; itheta1 - 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; iCenter.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; i2Center.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; -} diff --git a/polygon/math_for_graphics.h b/polygon/math_for_graphics.h index 86ef869874..2319330eb8 100644 --- a/polygon/math_for_graphics.h +++ b/polygon/math_for_graphics.h @@ -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 );