Loading pcbnew/zones_polygons_test_connections.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -153,7 +153,6 @@ void BOARD::Test_Connections_To_Copper_Areas( int aNetcode ) if( (old_subnet > 0) && (old_subnet != subnet) ) // Merge previous subnet with the current { //printf(" merge subnets: %d et %d (%d)\n", old_subnet, subnet,item->Type()); for( unsigned jj = 0; jj < Candidates.size(); jj++ ) { BOARD_CONNECTED_ITEM* item_to_merge = Candidates[jj]; Loading Loading @@ -233,7 +232,6 @@ void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ) if( !found ) // No zone with this netcode, therefore no connection by zone return; printf(" Merge_SubNets net = %d\n", aNetcode); std::vector <BOARD_CONNECTED_ITEM*> Candidates; // list of pads and tracks candidates to test. // Build a list of candidates connected to the net: Loading polygon/math_for_graphics.cpp +0 −451 Original line number Diff line number Diff line Loading @@ -13,143 +13,6 @@ using namespace std; #include "PolyLine.h" // function to find inflection-pont to create a "dogleg" of two straight-line segments // where one segment is vertical or horizontal and the other is at 45 degrees or 90 degrees // enter with: // pi = start point // pf = end point // mode = IM_90_45 or IM_45_90 or IM_90 // CPoint GetInflectionPoint( CPoint pi, CPoint pf, int mode ) { CPoint p = pi; if( mode == IM_NONE ) return p; int dx = pf.x - pi.x; int dy = pf.y - pi.y; if( dx == 0 || dy == 0 || abs(dx) == abs(dy) ) { // only one segment needed } else { if( abs(dy) > abs(dx) ) { // vertical > horizontal if( mode == IM_90 ) { p.x = pi.x; p.y = pf.y; } else if( mode == IM_45_90 || mode == IM_90_45 ) { int vert; // length of vertical line needed if( dy > 0 ) vert = dy - abs(dx); // positive else vert = dy + abs(dx); // negative if( mode == IM_90_45 ) p.y = pi.y + vert; else if( mode == IM_45_90 ) { p.y = pf.y - vert; p.x = pf.x; } } else wxASSERT(0); } else { // horizontal > vertical if( mode == IM_90 ) { p.x = pf.x; p.y = pi.y; } else if( mode == IM_45_90 || mode == IM_90_45 ) { int hor; // length of horizontal line needed if( dx > 0 ) hor = dx - abs(dy); // positive else hor = dx + abs(dy); // negative if( mode == IM_90_45 ) p.x = pi.x + hor; else if( mode == IM_45_90 ) { p.x = pf.x - hor; p.y = pf.y; } } else wxASSERT(0); } } return p; } // // function to rotate a point clockwise about another point // currently, angle must be 0, 90, 180 or 270 // void RotatePoint( CPoint *p, int angle, CPoint org ) { if( angle == 90 ) { int tempy = org.y + (org.x - p->x); p->x = org.x + (p->y - org.y); p->y = tempy; } else if( angle > 90 ) { for( int i=0; i<(angle/90); i++ ) RotatePoint( p, 90, org ); } } // function to rotate a rectangle clockwise about a point // angle must be 0, 90, 180 or 270 // on exit, r->top > r.bottom, r.right > r.left // void RotateRect( CRect *r, int angle, CPoint org ) { CRect tr; if( angle == 90 ) { tr.left = org.x + (r->bottom - org.y); tr.right = org.x + (r->top - org.y); tr.top = org.y + (org.x - r->right); tr.bottom = org.y + (org.x - r->left); if( tr.left > tr.right ) { int temp = tr.right; tr.left = tr.right; tr.left = temp; } if( tr.left > tr.right ) { int temp = tr.right; tr.left = tr.right; tr.left = temp; } if( tr.bottom > tr.top ) { int temp = tr.bottom; tr.bottom = tr.top; tr.top = temp; } } else if( angle > 90 ) { tr = *r; for( int i=0; i<(angle/90); i++ ) RotateRect( &tr, 90, org ); } *r = tr; } // test for hit on line segment // i.e. cursor within a given distance from segment // enter with: x,y = cursor coords Loading Loading @@ -206,15 +69,6 @@ int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist ) } // find intersection between y = a + bx and y = c + dx; // int FindLineIntersection( double a, double b, double c, double d, double * x, double * y ) { *x = (c-a)/(b-d); *y = a + b*(*x); return 0; } // set EllipseKH struct to describe the ellipse for an arc // int MakeEllipseFromArc( int xi, int yi, int xf, int yf, int style, EllipseKH * el ) Loading Loading @@ -875,250 +729,6 @@ bool FindLineEllipseIntersections( double a, double b, double c, double d, doubl } #if 0 // draw a straight line or an arc between xi,yi and xf,yf // void DrawArc( CDC * pDC, int shape, int xxi, int yyi, int xxf, int yyf, bool bMeta ) { int xi, yi, xf, yf; if( shape == DL_LINE || xxi == xxf || yyi == yyf ) { // draw straight line pDC->MoveTo( xxi, yyi ); pDC->LineTo( xxf, yyf ); } else if( shape == DL_ARC_CCW || shape == DL_ARC_CW ) { // set endpoints so we can always draw counter-clockwise arc if( shape == DL_ARC_CW ) { xi = xxf; yi = yyf; xf = xxi; yf = yyi; } else { xi = xxi; yi = yyi; xf = xxf; yf = yyf; } pDC->MoveTo( xi, yi ); if( xf > xi && yf > yi ) { // quadrant 1 int w = (xf-xi)*2; int h = (yf-yi)*2; if( !bMeta ) pDC->Arc( xf-w, yi+h, xf, yi, xi, yi, xf, yf ); else pDC->Arc( xf-w, yi, xf, yi+h, xf, yf, xi, yi ); } else if( xf < xi && yf > yi ) { // quadrant 2 int w = -(xf-xi)*2; int h = (yf-yi)*2; if( !bMeta ) pDC->Arc( xi-w, yf, xi, yf-h, xi, yi, xf, yf ); else pDC->Arc( xi-w, yf-h, xi, yf, xf, yf, xi, yi ); } else if( xf < xi && yf < yi ) { // quadrant 3 int w = -(xf-xi)*2; int h = -(yf-yi)*2; if( !bMeta ) pDC->Arc( xf, yi, xf+w, yi-h, xi, yi, xf, yf ); else pDC->Arc( xf, yi-h, xf+w, yi, xf, yf, xi, yi ); } else if( xf > xi && yf < yi ) { // quadrant 4 int w = (xf-xi)*2; int h = -(yf-yi)*2; if( !bMeta ) pDC->Arc( xi, yf+h, xi+w, yf, xi, yi, xf, yf ); else pDC->Arc( xi, yf, xi+w, yf+h, xf, yf, xi, yi ); } pDC->MoveTo( xxf, yyf ); } else wxASSERT(0); // oops } #endif // Get arrays of circles, rects and line segments to represent pad // for purposes of drawing pad or calculating clearances // margins of circles and line segments represent pad outline // circles and rects are used to find points inside pad // void GetPadElements( int type, int x, int y, int wid, int len, int radius, int angle, int * nr, my_rect r[], int * nc, my_circle c[], int * ns, my_seg s[] ) { *nc = 0; *nr = 0; *ns = 0; if( type == PAD_ROUND ) { *nc = 1; c[0] = my_circle(x,y,wid/2); return; } if( type == PAD_SQUARE ) { *nr = 1; r[0] = my_rect(x-wid/2, y-wid/2,x+wid/2, y+wid/2); *ns = 4; s[0] = my_seg(x-wid/2, y+wid/2,x+wid/2, y+wid/2); // top s[1] = my_seg(x-wid/2, y-wid/2,x+wid/2, y-wid/2); // bottom s[2] = my_seg(x-wid/2, y-wid/2,x-wid/2, y+wid/2); // left s[3] = my_seg(x+wid/2, y-wid/2,x+wid/2, y+wid/2); // right return; } if( type == PAD_OCTAGON ) { const double pi = 3.14159265359; *nc = 1; // circle represents inside of polygon c[0] = my_circle(x, y, wid/2); *ns = 8; // now create sides of polygon double theta = pi/8.0; double radius = 0.5*(double)wid/cos(theta); double last_x = x + radius*cos(theta); double last_y = y + radius*sin(theta); for( int is=0; is<8; is++ ) { theta += pi/4.0; double dx = x + radius*cos(theta); double dy = y + radius*sin(theta); s[is] = my_seg((int) last_x, (int) last_y, x, y); last_x = dx; last_y = dy; } return; } // int h; int v; if( angle == 90 || angle == 270 ) { h = wid; v = len; } else { v = wid; h = len; } if( type == PAD_RECT ) { *nr = 1; r[0] = my_rect(x-h/2, y-v/2, x+h/2, y+v/2); *ns = 4; s[0] = my_seg(x-h/2, y+v/2,x+h/2, y+v/2); // top s[1] = my_seg(x-h/2, y-v/2,x+h/2, y-v/2); // bottom s[2] = my_seg(x-h/2, y-v/2,x-h/2, y+v/2); // left s[3] = my_seg(x+h/2, y-v/2,x+h/2, y+v/2); // right return; } if( type == PAD_RRECT ) { *nc = 4; c[0] = my_circle(x-h/2+radius, y-v/2+radius, radius); // bottom left circle c[1] = my_circle(x+h/2-radius, y-v/2+radius, radius); // bottom right circle c[2] = my_circle(x-h/2+radius, y+v/2-radius, radius); // top left circle c[3] = my_circle(x+h/2-radius, y+v/2-radius, radius); // top right circle *ns = 4; s[0] = my_seg(x-h/2+radius, y+v/2, x+h/2-radius, y+v/2); // top s[1] = my_seg(x-h/2+radius, y-v/2, x+h/2-radius, y+v/2); // bottom s[2] = my_seg(x-h/2, y-v/2+radius, x-h/2, y+v/2-radius); // left s[3] = my_seg(x+h/2, y-v/2+radius, x+h/2, y+v/2-radius); // right return; } if( type == PAD_OVAL ) { if( h > v ) { // horizontal *nc = 2; c[0] = my_circle(x-h/2+v/2, y, v/2); // left circle c[1] = my_circle(x+h/2-v/2, y, v/2); // right circle *nr = 1; r[0] = my_rect(x-h/2+v/2, y-v/2, x+h/2-v/2, y+v/2); *ns = 2; s[0] = my_seg(x-h/2+v/2, y+v/2, x+h/2-v/2, y+v/2); // top s[1] = my_seg(x-h/2+v/2, y-v/2, x+h/2-v/2, y-v/2); // bottom } else { // vertical *nc = 2; c[0] = my_circle(x, y+v/2-h/2, h/2); // top circle c[1] = my_circle(x, y-v/2+h/2, h/2); // bottom circle *nr = 1; r[0] = my_rect(x-h/2, y-v/2+h/2, x+h/2, y+v/2-h/2); *ns = 2; s[0] = my_seg(x-h/2, y-v/2+h/2, x-h/2, y+v/2-h/2); // left s[1] = my_seg(x+h/2, y-v/2+h/2, x+h/2, y+v/2-h/2); // left } return; } wxASSERT(0); } // Find distance from a staright line segment to a pad // int GetClearanceBetweenSegmentAndPad( int x1, int y1, int x2, int y2, int w, int type, int x, int y, int wid, int len, int radius, int angle ) { if( type == PAD_NONE ) return INT_MAX; else { int nc, nr, ns; my_circle c[4]; my_rect r[2]; my_seg s[8]; GetPadElements( type, x, y, wid, len, radius, angle, &nr, r, &nc, c, &ns, s ); // first test for endpoints of line segment in rectangle for( int ir=0; ir<nr; ir++ ) { if( x1 >= r[ir].xlo && x1 <= r[ir].xhi && y1 >= r[ir].ylo && y1 <= r[ir].yhi ) return 0; if( x2 >= r[ir].xlo && x2 <= r[ir].xhi && y2 >= r[ir].ylo && y2 <= r[ir].yhi ) return 0; } // now get distance from elements of pad outline int dist = INT_MAX; for( int ic=0; ic<nc; ic++ ) { int d = (int)GetPointToLineSegmentDistance( c[ic].x, c[ic].y, x1, y1, x2, y2 ) - c[ic].r - w/2; dist = min(dist,d); } for( int is=0; is<ns; is++ ) { double d; TestForIntersectionOfStraightLineSegments( s[is].xi, s[is].yi, s[is].xf, s[is].yf, x1, y1, x2, y2, NULL, NULL, &d ); dist = min(dist, (int)d - w/2); } return max(0,dist); } } // Get clearance between 2 segments // Returns point in segment closest to other segment in x, y Loading Loading @@ -1300,67 +910,6 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, // Find clearance between pads // For each pad: // type = PAD_ROUND, PAD_SQUARE, etc. // x, y = center position // w, l = width and length // r = corner radius // angle = 0 or 90 (if 0, pad length is along x-axis) // int GetClearanceBetweenPads( int type1, int x1, int y1, int w1, int l1, int r1, int angle1, int type2, int x2, int y2, int w2, int l2, int r2, int angle2 ) { if( type1 == PAD_NONE ) return INT_MAX; if( type2 == PAD_NONE ) return INT_MAX; int dist = INT_MAX; int nr, nc, ns, nrr, ncc, nss; my_rect r[2], rr[2]; my_circle c[4], cc[4]; my_seg s[8], ss[8]; GetPadElements( type1, x1, y1, w1, l1, r1, angle1, &nr, r, &nc, c, &ns, s ); GetPadElements( type2, x2, y2, w2, l2, r2, angle2, &nrr, rr, &ncc, cc, &nss, ss ); // now find distance from every element of pad1 to every element of pad2 for( int ic=0; ic<nc; ic++ ) { for( int icc=0; icc<ncc; icc++ ) { int d = (int) Distance( c[ic].x, c[ic].y, cc[icc].x, cc[icc].y ) - c[ic].r - cc[icc].r; dist = min(dist,d); } for( int iss=0; iss<nss; iss++ ) { int d = (int) GetPointToLineSegmentDistance( c[ic].x, c[ic].y, ss[iss].xi, ss[iss].yi, ss[iss].xf, ss[iss].yf ) - c[ic].r; dist = min(dist,d); } } for( int is=0; is<ns; is++ ) { for( int icc=0; icc<ncc; icc++ ) { int d = (int) GetPointToLineSegmentDistance( cc[icc].x, cc[icc].y, s[is].xi, s[is].yi, s[is].xf, s[is].yf ) - cc[icc].r; dist = min(dist,d); } for( int iss=0; iss<nss; iss++ ) { double d; TestForIntersectionOfStraightLineSegments( s[is].xi, s[is].yi, s[is].xf, s[is].yf, ss[iss].xi, ss[iss].yi, ss[iss].xf, ss[iss].yf, NULL, NULL, &d ); dist = min(dist, (int)d); } } return max(dist,0); } // 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 Loading polygon/math_for_graphics.h +0 −54 Original line number Diff line number Diff line Loading @@ -19,56 +19,10 @@ typedef struct EllipseTag double theta1, theta2; // start and end angle for arc } EllipseKH; const CPoint zero(0,0); class my_circle { public: my_circle(){}; my_circle( int xx, int yy, int rr ) { x = xx; y = yy; r = rr; }; int x, y, r; }; class my_rect { public: my_rect(){}; my_rect( int xi, int yi, int xf, int yf ) { xlo = MIN(xi,xf); xhi = MAX(xi,xf); ylo = MIN(yi,yf); yhi = MAX(yi,yf); }; int xlo, ylo, xhi, yhi; }; class my_seg { public: my_seg(){}; my_seg( int xxi, int yyi, int xxf, int yyf ) { xi = xxi; yi = yyi; xf = xxf; yf = yyf; }; int xi, yi, xf, yf; }; // math stuff for graphics #if 0 void DrawArc( CDC * pDC, int shape, int xxi, int yyi, int xxf, int yyf, bool bMeta=FALSE ); #endif bool Quadratic( double a, double b, double c, double *x1, double *x2 ); void RotatePoint( CPoint *p, int angle, CPoint org ); void RotateRect( CRect *r, int angle, CPoint org ); int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist ); int FindLineIntersection( double a, double b, double c, double d, double * x, double * y ); int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf, int style, double * x1, double * y1, double * x2, double * y2, double * dist=NULL ); int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style, Loading @@ -79,13 +33,6 @@ bool FindVerticalLineEllipseIntersections( double a, double b, double x, double bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f, int x2i, int y2i, int x2f, int y2f, int * x=NULL, int * y=NULL, double * dist=NULL ); void GetPadElements( int type, int x, int y, int wid, int len, int radius, int angle, int * nr, my_rect r[], int * nc, my_circle c[], int * ns, my_seg s[] ); int GetClearanceBetweenPads( int type1, int x1, int y1, int w1, int l1, int r1, int angle1, int type2, int x2, int y2, int w2, int l2, int r2, int angle2 ); int GetClearanceBetweenSegmentAndPad( int x1, int y1, int x2, int y2, int w, int type, int x, int y, int wid, int len, int radius, int angle ); int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1, int x2i, int y2i, int x2f, int y2f, int style2, int w2, int max_cl, int * x, int * y ); Loading @@ -104,5 +51,4 @@ double Distance( int x1, int y1, int x2, int y2 ); int GetArcIntersections( EllipseKH * el1, EllipseKH * el2, double * x1=NULL, double * y1=NULL, double * x2=NULL, double * y2=NULL ); CPoint GetInflectionPoint( CPoint pi, CPoint pf, int mode ); polygon/polygon_test_point_inside.cpp +42 −40 Original line number Diff line number Diff line Loading @@ -15,6 +15,10 @@ using namespace std; * At each crossing, the ray switches between inside and outside. * If odd count, the test point is inside the polygon * This is called the Jordan curve theorem, or sometimes referred to as the "even-odd" test. * Take care to starting and ending points of segments outlines: * Only one must be used because the startingpoint of a segemnt is also the ending point of the previous. * And we do no use twice the same segment, so we do NOT use both starting and ending points of segments. * So we must use starting point but not ending point of each segment when calculating intersections */ /* 2 versions are given. Loading @@ -22,7 +26,7 @@ using namespace std; * the first version is for explanations and tests (used to test the second version) * both use the same algorithm. */ #if 1 #if 0 /* This text and the algorithm come from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html * Loading Loading @@ -291,7 +295,6 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList, /** Function TestPointInsidePolygon * test if a point is inside or outside a polygon. * if a point is on a outline segment, it is considered outside the polygon * the polygon must have only lines (not arcs) for outlines. * Use TestPointInside or TestPointInsideContour for more complex polygons * @param aPolysList: the list of polygons Loading @@ -301,55 +304,54 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList, * @return true if the point is inside, false for outside */ { #define OUTSIDE_IF_ON_SIDE 0 // = 1 if we consider point on a side outside the polygon // define line passing through (x,y), with slope = 0 (horizontal line) // get intersection points // count intersection points to right of (x,y), if odd (x,y) is inside polyline int xx, yy; double slope = 0; // Using an horizontal line. double a = refy - slope * refx; // count intersection points to right of (refx,refy), if odd (refx,refy) is inside polyline int ics, ice; bool inside = false; // find all intersection points of line with polyline sides for( ics = istart, ice = iend; ics <= iend; ice = ics++ ) { double intersectx1, intersecty1, intersectx2, intersecty2; int ok; ok = FindLineSegmentIntersection( a, slope, aPolysList[ics].x, aPolysList[ics].y, aPolysList[ice].x, aPolysList[ice].y, CPolyLine::STRAIGHT, &intersectx1, &intersecty1, &intersectx2, &intersecty2 ); int seg_startX = aPolysList[ics].x; int seg_startY = aPolysList[ics].y; int seg_endX = aPolysList[ice].x; int seg_endY = aPolysList[ice].y; /* FindLineSegmentIntersection() returns 0, 1 or 2 coordinates (ok = 0, 1, 2) * for straight line segments, only 0 or 1 are possible * (2 intersections points are possible only with arcs /* Trivial cases: skip if ref above or below the segment to test * Note: end point segment is skipped, because we do not test twice the same point: * If the start point of segments is tested, the end point must be skipped, because * this is also the starting point of the next segment */ if( ok ) // Intersection found { xx = (int) intersectx1; yy = (int) intersecty1; // segment above ref point: skip if( ( seg_startY > refy ) && (seg_endY > refy ) ) continue; /* if the intersection point is on the start point of the current segment, * do not count it, * because it was already counted, as ending point of the previous segment */ if( xx == aPolysList[ics].x && yy == aPolysList[ics].y ) // segment below ref point, or its end on ref point: skip // Note: also we skip vertical segments // So points on vertical segments outlines are seen as outside the polygon if( ( seg_startY <= refy ) && (seg_endY <= refy ) ) continue; #if OUTSIDE_IF_ON_SIDE if( xx == refx && yy == refy ) return false; // (x,y) is on a side, call it outside else #endif if( xx > refx ) /* refy is between seg_startY and seg_endY. * see if an horizontal 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)(refx - seg_startX); double newrefy = (double) (refy - 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 is slope = seg_endY/seg_endX; // and the x pos relative to the new origin is intersec_x = refy/slope // Note: because vertical segments are skipped, slope exists (seg_end_y not O) double intersec_x = newrefy * seg_endX / seg_endY; if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from -infinite to refx inside = not inside; } } return inside; } #endif Loading
pcbnew/zones_polygons_test_connections.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -153,7 +153,6 @@ void BOARD::Test_Connections_To_Copper_Areas( int aNetcode ) if( (old_subnet > 0) && (old_subnet != subnet) ) // Merge previous subnet with the current { //printf(" merge subnets: %d et %d (%d)\n", old_subnet, subnet,item->Type()); for( unsigned jj = 0; jj < Candidates.size(); jj++ ) { BOARD_CONNECTED_ITEM* item_to_merge = Candidates[jj]; Loading Loading @@ -233,7 +232,6 @@ void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ) if( !found ) // No zone with this netcode, therefore no connection by zone return; printf(" Merge_SubNets net = %d\n", aNetcode); std::vector <BOARD_CONNECTED_ITEM*> Candidates; // list of pads and tracks candidates to test. // Build a list of candidates connected to the net: Loading
polygon/math_for_graphics.cpp +0 −451 Original line number Diff line number Diff line Loading @@ -13,143 +13,6 @@ using namespace std; #include "PolyLine.h" // function to find inflection-pont to create a "dogleg" of two straight-line segments // where one segment is vertical or horizontal and the other is at 45 degrees or 90 degrees // enter with: // pi = start point // pf = end point // mode = IM_90_45 or IM_45_90 or IM_90 // CPoint GetInflectionPoint( CPoint pi, CPoint pf, int mode ) { CPoint p = pi; if( mode == IM_NONE ) return p; int dx = pf.x - pi.x; int dy = pf.y - pi.y; if( dx == 0 || dy == 0 || abs(dx) == abs(dy) ) { // only one segment needed } else { if( abs(dy) > abs(dx) ) { // vertical > horizontal if( mode == IM_90 ) { p.x = pi.x; p.y = pf.y; } else if( mode == IM_45_90 || mode == IM_90_45 ) { int vert; // length of vertical line needed if( dy > 0 ) vert = dy - abs(dx); // positive else vert = dy + abs(dx); // negative if( mode == IM_90_45 ) p.y = pi.y + vert; else if( mode == IM_45_90 ) { p.y = pf.y - vert; p.x = pf.x; } } else wxASSERT(0); } else { // horizontal > vertical if( mode == IM_90 ) { p.x = pf.x; p.y = pi.y; } else if( mode == IM_45_90 || mode == IM_90_45 ) { int hor; // length of horizontal line needed if( dx > 0 ) hor = dx - abs(dy); // positive else hor = dx + abs(dy); // negative if( mode == IM_90_45 ) p.x = pi.x + hor; else if( mode == IM_45_90 ) { p.x = pf.x - hor; p.y = pf.y; } } else wxASSERT(0); } } return p; } // // function to rotate a point clockwise about another point // currently, angle must be 0, 90, 180 or 270 // void RotatePoint( CPoint *p, int angle, CPoint org ) { if( angle == 90 ) { int tempy = org.y + (org.x - p->x); p->x = org.x + (p->y - org.y); p->y = tempy; } else if( angle > 90 ) { for( int i=0; i<(angle/90); i++ ) RotatePoint( p, 90, org ); } } // function to rotate a rectangle clockwise about a point // angle must be 0, 90, 180 or 270 // on exit, r->top > r.bottom, r.right > r.left // void RotateRect( CRect *r, int angle, CPoint org ) { CRect tr; if( angle == 90 ) { tr.left = org.x + (r->bottom - org.y); tr.right = org.x + (r->top - org.y); tr.top = org.y + (org.x - r->right); tr.bottom = org.y + (org.x - r->left); if( tr.left > tr.right ) { int temp = tr.right; tr.left = tr.right; tr.left = temp; } if( tr.left > tr.right ) { int temp = tr.right; tr.left = tr.right; tr.left = temp; } if( tr.bottom > tr.top ) { int temp = tr.bottom; tr.bottom = tr.top; tr.top = temp; } } else if( angle > 90 ) { tr = *r; for( int i=0; i<(angle/90); i++ ) RotateRect( &tr, 90, org ); } *r = tr; } // test for hit on line segment // i.e. cursor within a given distance from segment // enter with: x,y = cursor coords Loading Loading @@ -206,15 +69,6 @@ int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist ) } // find intersection between y = a + bx and y = c + dx; // int FindLineIntersection( double a, double b, double c, double d, double * x, double * y ) { *x = (c-a)/(b-d); *y = a + b*(*x); return 0; } // set EllipseKH struct to describe the ellipse for an arc // int MakeEllipseFromArc( int xi, int yi, int xf, int yf, int style, EllipseKH * el ) Loading Loading @@ -875,250 +729,6 @@ bool FindLineEllipseIntersections( double a, double b, double c, double d, doubl } #if 0 // draw a straight line or an arc between xi,yi and xf,yf // void DrawArc( CDC * pDC, int shape, int xxi, int yyi, int xxf, int yyf, bool bMeta ) { int xi, yi, xf, yf; if( shape == DL_LINE || xxi == xxf || yyi == yyf ) { // draw straight line pDC->MoveTo( xxi, yyi ); pDC->LineTo( xxf, yyf ); } else if( shape == DL_ARC_CCW || shape == DL_ARC_CW ) { // set endpoints so we can always draw counter-clockwise arc if( shape == DL_ARC_CW ) { xi = xxf; yi = yyf; xf = xxi; yf = yyi; } else { xi = xxi; yi = yyi; xf = xxf; yf = yyf; } pDC->MoveTo( xi, yi ); if( xf > xi && yf > yi ) { // quadrant 1 int w = (xf-xi)*2; int h = (yf-yi)*2; if( !bMeta ) pDC->Arc( xf-w, yi+h, xf, yi, xi, yi, xf, yf ); else pDC->Arc( xf-w, yi, xf, yi+h, xf, yf, xi, yi ); } else if( xf < xi && yf > yi ) { // quadrant 2 int w = -(xf-xi)*2; int h = (yf-yi)*2; if( !bMeta ) pDC->Arc( xi-w, yf, xi, yf-h, xi, yi, xf, yf ); else pDC->Arc( xi-w, yf-h, xi, yf, xf, yf, xi, yi ); } else if( xf < xi && yf < yi ) { // quadrant 3 int w = -(xf-xi)*2; int h = -(yf-yi)*2; if( !bMeta ) pDC->Arc( xf, yi, xf+w, yi-h, xi, yi, xf, yf ); else pDC->Arc( xf, yi-h, xf+w, yi, xf, yf, xi, yi ); } else if( xf > xi && yf < yi ) { // quadrant 4 int w = (xf-xi)*2; int h = -(yf-yi)*2; if( !bMeta ) pDC->Arc( xi, yf+h, xi+w, yf, xi, yi, xf, yf ); else pDC->Arc( xi, yf, xi+w, yf+h, xf, yf, xi, yi ); } pDC->MoveTo( xxf, yyf ); } else wxASSERT(0); // oops } #endif // Get arrays of circles, rects and line segments to represent pad // for purposes of drawing pad or calculating clearances // margins of circles and line segments represent pad outline // circles and rects are used to find points inside pad // void GetPadElements( int type, int x, int y, int wid, int len, int radius, int angle, int * nr, my_rect r[], int * nc, my_circle c[], int * ns, my_seg s[] ) { *nc = 0; *nr = 0; *ns = 0; if( type == PAD_ROUND ) { *nc = 1; c[0] = my_circle(x,y,wid/2); return; } if( type == PAD_SQUARE ) { *nr = 1; r[0] = my_rect(x-wid/2, y-wid/2,x+wid/2, y+wid/2); *ns = 4; s[0] = my_seg(x-wid/2, y+wid/2,x+wid/2, y+wid/2); // top s[1] = my_seg(x-wid/2, y-wid/2,x+wid/2, y-wid/2); // bottom s[2] = my_seg(x-wid/2, y-wid/2,x-wid/2, y+wid/2); // left s[3] = my_seg(x+wid/2, y-wid/2,x+wid/2, y+wid/2); // right return; } if( type == PAD_OCTAGON ) { const double pi = 3.14159265359; *nc = 1; // circle represents inside of polygon c[0] = my_circle(x, y, wid/2); *ns = 8; // now create sides of polygon double theta = pi/8.0; double radius = 0.5*(double)wid/cos(theta); double last_x = x + radius*cos(theta); double last_y = y + radius*sin(theta); for( int is=0; is<8; is++ ) { theta += pi/4.0; double dx = x + radius*cos(theta); double dy = y + radius*sin(theta); s[is] = my_seg((int) last_x, (int) last_y, x, y); last_x = dx; last_y = dy; } return; } // int h; int v; if( angle == 90 || angle == 270 ) { h = wid; v = len; } else { v = wid; h = len; } if( type == PAD_RECT ) { *nr = 1; r[0] = my_rect(x-h/2, y-v/2, x+h/2, y+v/2); *ns = 4; s[0] = my_seg(x-h/2, y+v/2,x+h/2, y+v/2); // top s[1] = my_seg(x-h/2, y-v/2,x+h/2, y-v/2); // bottom s[2] = my_seg(x-h/2, y-v/2,x-h/2, y+v/2); // left s[3] = my_seg(x+h/2, y-v/2,x+h/2, y+v/2); // right return; } if( type == PAD_RRECT ) { *nc = 4; c[0] = my_circle(x-h/2+radius, y-v/2+radius, radius); // bottom left circle c[1] = my_circle(x+h/2-radius, y-v/2+radius, radius); // bottom right circle c[2] = my_circle(x-h/2+radius, y+v/2-radius, radius); // top left circle c[3] = my_circle(x+h/2-radius, y+v/2-radius, radius); // top right circle *ns = 4; s[0] = my_seg(x-h/2+radius, y+v/2, x+h/2-radius, y+v/2); // top s[1] = my_seg(x-h/2+radius, y-v/2, x+h/2-radius, y+v/2); // bottom s[2] = my_seg(x-h/2, y-v/2+radius, x-h/2, y+v/2-radius); // left s[3] = my_seg(x+h/2, y-v/2+radius, x+h/2, y+v/2-radius); // right return; } if( type == PAD_OVAL ) { if( h > v ) { // horizontal *nc = 2; c[0] = my_circle(x-h/2+v/2, y, v/2); // left circle c[1] = my_circle(x+h/2-v/2, y, v/2); // right circle *nr = 1; r[0] = my_rect(x-h/2+v/2, y-v/2, x+h/2-v/2, y+v/2); *ns = 2; s[0] = my_seg(x-h/2+v/2, y+v/2, x+h/2-v/2, y+v/2); // top s[1] = my_seg(x-h/2+v/2, y-v/2, x+h/2-v/2, y-v/2); // bottom } else { // vertical *nc = 2; c[0] = my_circle(x, y+v/2-h/2, h/2); // top circle c[1] = my_circle(x, y-v/2+h/2, h/2); // bottom circle *nr = 1; r[0] = my_rect(x-h/2, y-v/2+h/2, x+h/2, y+v/2-h/2); *ns = 2; s[0] = my_seg(x-h/2, y-v/2+h/2, x-h/2, y+v/2-h/2); // left s[1] = my_seg(x+h/2, y-v/2+h/2, x+h/2, y+v/2-h/2); // left } return; } wxASSERT(0); } // Find distance from a staright line segment to a pad // int GetClearanceBetweenSegmentAndPad( int x1, int y1, int x2, int y2, int w, int type, int x, int y, int wid, int len, int radius, int angle ) { if( type == PAD_NONE ) return INT_MAX; else { int nc, nr, ns; my_circle c[4]; my_rect r[2]; my_seg s[8]; GetPadElements( type, x, y, wid, len, radius, angle, &nr, r, &nc, c, &ns, s ); // first test for endpoints of line segment in rectangle for( int ir=0; ir<nr; ir++ ) { if( x1 >= r[ir].xlo && x1 <= r[ir].xhi && y1 >= r[ir].ylo && y1 <= r[ir].yhi ) return 0; if( x2 >= r[ir].xlo && x2 <= r[ir].xhi && y2 >= r[ir].ylo && y2 <= r[ir].yhi ) return 0; } // now get distance from elements of pad outline int dist = INT_MAX; for( int ic=0; ic<nc; ic++ ) { int d = (int)GetPointToLineSegmentDistance( c[ic].x, c[ic].y, x1, y1, x2, y2 ) - c[ic].r - w/2; dist = min(dist,d); } for( int is=0; is<ns; is++ ) { double d; TestForIntersectionOfStraightLineSegments( s[is].xi, s[is].yi, s[is].xf, s[is].yf, x1, y1, x2, y2, NULL, NULL, &d ); dist = min(dist, (int)d - w/2); } return max(0,dist); } } // Get clearance between 2 segments // Returns point in segment closest to other segment in x, y Loading Loading @@ -1300,67 +910,6 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, // Find clearance between pads // For each pad: // type = PAD_ROUND, PAD_SQUARE, etc. // x, y = center position // w, l = width and length // r = corner radius // angle = 0 or 90 (if 0, pad length is along x-axis) // int GetClearanceBetweenPads( int type1, int x1, int y1, int w1, int l1, int r1, int angle1, int type2, int x2, int y2, int w2, int l2, int r2, int angle2 ) { if( type1 == PAD_NONE ) return INT_MAX; if( type2 == PAD_NONE ) return INT_MAX; int dist = INT_MAX; int nr, nc, ns, nrr, ncc, nss; my_rect r[2], rr[2]; my_circle c[4], cc[4]; my_seg s[8], ss[8]; GetPadElements( type1, x1, y1, w1, l1, r1, angle1, &nr, r, &nc, c, &ns, s ); GetPadElements( type2, x2, y2, w2, l2, r2, angle2, &nrr, rr, &ncc, cc, &nss, ss ); // now find distance from every element of pad1 to every element of pad2 for( int ic=0; ic<nc; ic++ ) { for( int icc=0; icc<ncc; icc++ ) { int d = (int) Distance( c[ic].x, c[ic].y, cc[icc].x, cc[icc].y ) - c[ic].r - cc[icc].r; dist = min(dist,d); } for( int iss=0; iss<nss; iss++ ) { int d = (int) GetPointToLineSegmentDistance( c[ic].x, c[ic].y, ss[iss].xi, ss[iss].yi, ss[iss].xf, ss[iss].yf ) - c[ic].r; dist = min(dist,d); } } for( int is=0; is<ns; is++ ) { for( int icc=0; icc<ncc; icc++ ) { int d = (int) GetPointToLineSegmentDistance( cc[icc].x, cc[icc].y, s[is].xi, s[is].yi, s[is].xf, s[is].yf ) - cc[icc].r; dist = min(dist,d); } for( int iss=0; iss<nss; iss++ ) { double d; TestForIntersectionOfStraightLineSegments( s[is].xi, s[is].yi, s[is].xf, s[is].yf, ss[iss].xi, ss[iss].yi, ss[iss].xf, ss[iss].yf, NULL, NULL, &d ); dist = min(dist, (int)d); } } return max(dist,0); } // 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 Loading
polygon/math_for_graphics.h +0 −54 Original line number Diff line number Diff line Loading @@ -19,56 +19,10 @@ typedef struct EllipseTag double theta1, theta2; // start and end angle for arc } EllipseKH; const CPoint zero(0,0); class my_circle { public: my_circle(){}; my_circle( int xx, int yy, int rr ) { x = xx; y = yy; r = rr; }; int x, y, r; }; class my_rect { public: my_rect(){}; my_rect( int xi, int yi, int xf, int yf ) { xlo = MIN(xi,xf); xhi = MAX(xi,xf); ylo = MIN(yi,yf); yhi = MAX(yi,yf); }; int xlo, ylo, xhi, yhi; }; class my_seg { public: my_seg(){}; my_seg( int xxi, int yyi, int xxf, int yyf ) { xi = xxi; yi = yyi; xf = xxf; yf = yyf; }; int xi, yi, xf, yf; }; // math stuff for graphics #if 0 void DrawArc( CDC * pDC, int shape, int xxi, int yyi, int xxf, int yyf, bool bMeta=FALSE ); #endif bool Quadratic( double a, double b, double c, double *x1, double *x2 ); void RotatePoint( CPoint *p, int angle, CPoint org ); void RotateRect( CRect *r, int angle, CPoint org ); int TestLineHit( int xi, int yi, int xf, int yf, int x, int y, double dist ); int FindLineIntersection( double a, double b, double c, double d, double * x, double * y ); int FindLineSegmentIntersection( double a, double b, int xi, int yi, int xf, int yf, int style, double * x1, double * y1, double * x2, double * y2, double * dist=NULL ); int FindSegmentIntersections( int xi, int yi, int xf, int yf, int style, Loading @@ -79,13 +33,6 @@ bool FindVerticalLineEllipseIntersections( double a, double b, double x, double bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f, int x2i, int y2i, int x2f, int y2f, int * x=NULL, int * y=NULL, double * dist=NULL ); void GetPadElements( int type, int x, int y, int wid, int len, int radius, int angle, int * nr, my_rect r[], int * nc, my_circle c[], int * ns, my_seg s[] ); int GetClearanceBetweenPads( int type1, int x1, int y1, int w1, int l1, int r1, int angle1, int type2, int x2, int y2, int w2, int l2, int r2, int angle2 ); int GetClearanceBetweenSegmentAndPad( int x1, int y1, int x2, int y2, int w, int type, int x, int y, int wid, int len, int radius, int angle ); int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1, int x2i, int y2i, int x2f, int y2f, int style2, int w2, int max_cl, int * x, int * y ); Loading @@ -104,5 +51,4 @@ double Distance( int x1, int y1, int x2, int y2 ); int GetArcIntersections( EllipseKH * el1, EllipseKH * el2, double * x1=NULL, double * y1=NULL, double * x2=NULL, double * y2=NULL ); CPoint GetInflectionPoint( CPoint pi, CPoint pf, int mode );
polygon/polygon_test_point_inside.cpp +42 −40 Original line number Diff line number Diff line Loading @@ -15,6 +15,10 @@ using namespace std; * At each crossing, the ray switches between inside and outside. * If odd count, the test point is inside the polygon * This is called the Jordan curve theorem, or sometimes referred to as the "even-odd" test. * Take care to starting and ending points of segments outlines: * Only one must be used because the startingpoint of a segemnt is also the ending point of the previous. * And we do no use twice the same segment, so we do NOT use both starting and ending points of segments. * So we must use starting point but not ending point of each segment when calculating intersections */ /* 2 versions are given. Loading @@ -22,7 +26,7 @@ using namespace std; * the first version is for explanations and tests (used to test the second version) * both use the same algorithm. */ #if 1 #if 0 /* This text and the algorithm come from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html * Loading Loading @@ -291,7 +295,6 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList, /** Function TestPointInsidePolygon * test if a point is inside or outside a polygon. * if a point is on a outline segment, it is considered outside the polygon * the polygon must have only lines (not arcs) for outlines. * Use TestPointInside or TestPointInsideContour for more complex polygons * @param aPolysList: the list of polygons Loading @@ -301,55 +304,54 @@ bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList, * @return true if the point is inside, false for outside */ { #define OUTSIDE_IF_ON_SIDE 0 // = 1 if we consider point on a side outside the polygon // define line passing through (x,y), with slope = 0 (horizontal line) // get intersection points // count intersection points to right of (x,y), if odd (x,y) is inside polyline int xx, yy; double slope = 0; // Using an horizontal line. double a = refy - slope * refx; // count intersection points to right of (refx,refy), if odd (refx,refy) is inside polyline int ics, ice; bool inside = false; // find all intersection points of line with polyline sides for( ics = istart, ice = iend; ics <= iend; ice = ics++ ) { double intersectx1, intersecty1, intersectx2, intersecty2; int ok; ok = FindLineSegmentIntersection( a, slope, aPolysList[ics].x, aPolysList[ics].y, aPolysList[ice].x, aPolysList[ice].y, CPolyLine::STRAIGHT, &intersectx1, &intersecty1, &intersectx2, &intersecty2 ); int seg_startX = aPolysList[ics].x; int seg_startY = aPolysList[ics].y; int seg_endX = aPolysList[ice].x; int seg_endY = aPolysList[ice].y; /* FindLineSegmentIntersection() returns 0, 1 or 2 coordinates (ok = 0, 1, 2) * for straight line segments, only 0 or 1 are possible * (2 intersections points are possible only with arcs /* Trivial cases: skip if ref above or below the segment to test * Note: end point segment is skipped, because we do not test twice the same point: * If the start point of segments is tested, the end point must be skipped, because * this is also the starting point of the next segment */ if( ok ) // Intersection found { xx = (int) intersectx1; yy = (int) intersecty1; // segment above ref point: skip if( ( seg_startY > refy ) && (seg_endY > refy ) ) continue; /* if the intersection point is on the start point of the current segment, * do not count it, * because it was already counted, as ending point of the previous segment */ if( xx == aPolysList[ics].x && yy == aPolysList[ics].y ) // segment below ref point, or its end on ref point: skip // Note: also we skip vertical segments // So points on vertical segments outlines are seen as outside the polygon if( ( seg_startY <= refy ) && (seg_endY <= refy ) ) continue; #if OUTSIDE_IF_ON_SIDE if( xx == refx && yy == refy ) return false; // (x,y) is on a side, call it outside else #endif if( xx > refx ) /* refy is between seg_startY and seg_endY. * see if an horizontal 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)(refx - seg_startX); double newrefy = (double) (refy - 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 is slope = seg_endY/seg_endX; // and the x pos relative to the new origin is intersec_x = refy/slope // Note: because vertical segments are skipped, slope exists (seg_end_y not O) double intersec_x = newrefy * seg_endX / seg_endY; if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from -infinite to refx inside = not inside; } } return inside; } #endif