#include <pathutil.h>
Static Public Member Functions | |
static BOOL | SplitLine (const double, const DocCoord *, UINT32 *, PathVerb *, DocCoord *) |
Splits a line element into two lines, returning the lists of new coord points and verbs. | |
static BOOL | SplitCurve (const double, const DocCoord *, UINT32 *, PathVerb *, DocCoord *) |
Splits a curve element into two curves, returning the lists of new control points and verbs. | |
static void | GetCurveCoefs (const DocCoord *, PtCoefs *) |
Converts a curve from Bezier form to Canonical form. | |
static DocCoord | PointOnLine (const double, const DocCoord *) |
Given a parameter t go and evaluate the point on the described line segment If t is out of range, ie t>1 or t<0 the end points of the line will be returned. ie the routine will not evaluate unbounded points. | |
static DocCoord | PointOnSemiCircle (const DocCoord ¢re, const DocCoord &radialp, double t) |
Find a point on the circumference of a semicircle. The semicircle is specified by two points, it's centre and a point on the circumference. If c=0,0 and p=(1,0) then the semicircle exists in the y positive half of the plane from sweeping from (-1,0) at t==0 to (1.0) at t==1.0. | |
static DocCoord | PointOnCurve (double, const DocCoord *) |
This function returns the distance to the closest point on the curve and the parameter of this pointEvaluate a bezier curve, given a pointer to a set of control points and a parameter value. | |
static double | SqrDistance (const DocCoord &p1, const DocCoord &p2) |
Accurate squared distance function. | |
static double | SqrDistanceToLine (const DocCoord *, const DocCoord &, double *) |
Calculates the distance p1 is away from a line segment. The perpendicular distance is returned only when p1 is within the volume created by sweeping the line in the orthoganal direction. Otherwise the distance to the closest end point is returned. | |
static double | SqrDistanceToSemiCircle (const DocCoord *, const DocCoord &, double *) |
Calculates the distance p1 is away from a semi circle segment. plist[0] describes the centre of the semi circle plist[1] describes a point on the circumference of the circle. For instance say c the centre is (0,0) and cp the circumference point is (1,0) then the semicircle exists in the positive y half of the place and sweeps from (-1,0) to (1,0). Parameter space is param==0 at (-1,0) param==1 at ( 1,0) param==0.5 at ( 0,1). | |
static double | SqrDistanceToCurve (const UINT32, const DocCoord *, const DocCoord &, double *) |
Compute the parameter value of the point on a Bezier curve segment closest to some arbtitrary, user-input point. Return the squared distance to the curve. |
Definition at line 142 of file pathutil.h.
|
Converts a curve from Bezier form to Canonical form.
Definition at line 492 of file pathutil.cpp. 00493 { 00494 // Read the curve coordinates. 00495 00496 INT32 X0,Y0,X1,Y1,X2,Y2,X3,Y3; 00497 00498 X0 = coords->x; 00499 Y0 = coords->y; 00500 coords++; 00501 X1 = coords->x; 00502 Y1 = coords->y; 00503 coords++; 00504 X2 = coords->x; 00505 Y2 = coords->y; 00506 coords++; 00507 X3 = coords->x; 00508 Y3 = coords->y; 00509 00510 // Calculate the curve coefficients. 00511 00512 coefs->ax = X3-X0+3*(X1-X2); 00513 coefs->ay = Y3-Y0+3*(Y1-Y2); 00514 coefs->bx = 3*(X2-2*X1+X0); 00515 coefs->by = 3*(Y2-2*Y1+Y0); 00516 coefs->cx = 3*(X1-X0); 00517 coefs->cy = 3*(Y1-Y0); 00518 00519 }
|
|
This function returns the distance to the closest point on the curve and the parameter of this pointEvaluate a bezier curve, given a pointer to a set of control points and a parameter value.
Definition at line 897 of file pathutil.cpp. 00898 { 00899 PtCoefs p; 00900 DocCoord c; 00901 00902 PathUtil::GetCurveCoefs(plist, &p); // calculate coefs block 00903 00904 if (t<0) t=0; // clamp range of parameter 00905 if (t>1) t=1; 00906 00907 // Eval bezier at specified parameter 00908 00909 double dx = t*(p.cx+t*(p.bx+t*p.ax)); 00910 double dy = t*(p.cy+t*(p.by+t*p.ay)); 00911 00912 c.x = plist->x + (INT32)(dx+0.5); 00913 c.y = plist->y + (INT32)(dy+0.5); 00914 00915 return c; 00916 }
|
|
Given a parameter t go and evaluate the point on the described line segment If t is out of range, ie t>1 or t<0 the end points of the line will be returned. ie the routine will not evaluate unbounded points.
Definition at line 621 of file pathutil.cpp. 00622 { 00623 INT32 x0,y0,x1,y1; 00624 00625 x0 = ptlist[0].x; 00626 y0 = ptlist[0].y; 00627 x1 = ptlist[1].x; 00628 y1 = ptlist[1].y; 00629 00630 DocCoord d; 00631 00632 if (t<=0.0) 00633 { 00634 d.x = x0; 00635 d.y = y0; 00636 return d; 00637 } 00638 00639 if (t>=1.0) 00640 { 00641 d.x = x1; 00642 d.y = y1; 00643 return d; 00644 } 00645 00646 d.x = x0 + (INT32)(t*(x1-x0)+0.5); 00647 d.y = y0 + (INT32)(t*(y1-y0)+0.5); 00648 00649 return d; 00650 }
|
|
Find a point on the circumference of a semicircle. The semicircle is specified by two points, it's centre and a point on the circumference. If c=0,0 and p=(1,0) then the semicircle exists in the y positive half of the plane from sweeping from (-1,0) at t==0 to (1.0) at t==1.0.
Definition at line 143 of file pathutil.cpp. 00144 { 00145 double X = (double)(radialp.x - centre.x); 00146 double Y = (double)(radialp.y - centre.y); 00147 double p = t * XS_PI; 00148 00149 // spin clockwise. 00150 double s = sin(p); 00151 double c = -cos(p); 00152 00153 DocCoord r; 00154 00155 // circular rounding maybe? 00156 r.x = (INT32)(X*c - Y*s) + centre.x; 00157 r.y = (INT32)(X*s + Y*c) + centre.y; 00158 00159 return r; 00160 }
|
|
Splits a curve element into two curves, returning the lists of new control points and verbs.
Definition at line 406 of file pathutil.cpp. 00411 { 00412 // check t is in range for this split. 00413 00414 if (t < SPLIT_EPSILON) return FALSE; 00415 if (t > (1.0 - SPLIT_EPSILON)) return FALSE; 00416 00417 // fill in the path verb array, these are all curveto's 00418 00419 for (INT32 i=0; i<6; i++) 00420 OutVerbs[i] = PT_BEZIERTO; 00421 00422 // read the four curve control points 00423 00424 INT32 x0,y0,x1,y1,x2,y2,x3,y3; 00425 00426 x0 = plist[0].x; // note this should be move,line,curve 00427 y0 = plist[0].y; 00428 x1 = plist[1].x; // these should all be curveto's 00429 y1 = plist[1].y; 00430 x2 = plist[2].x; 00431 y2 = plist[2].y; 00432 x3 = plist[3].x; 00433 y3 = plist[3].y; 00434 00435 // now calculate six new coordinates from the given 4 00436 00437 double tx,ty; 00438 00439 tx = x1+t*(x2-x1); 00440 ty = y1+t*(y2-y1); 00441 00442 double Lx1,Ly1,Lx2,Ly2,Rx0,Ry0,Rx1,Ry1,Rx2,Ry2; 00443 00444 Lx1 = x0+t*(x1-x0); 00445 Ly1 = y0+t*(y1-y0); 00446 Rx2 = x2+t*(x3-x2); 00447 Ry2 = y2+t*(y3-y2); 00448 Lx2 = Lx1+t*(tx-Lx1); 00449 Ly2 = Ly1+t*(ty-Ly1); 00450 Rx1 = tx+t*(Rx2-tx); 00451 Ry1 = ty+t*(Ry2-ty); 00452 Rx0 = Lx2+t*(Rx1-Lx2); 00453 Ry0 = Ly2+t*(Ry1-Ly2); 00454 00455 // set the return values 00456 00457 OutCoords[0].x = (INT32)(Lx1+0.5); 00458 OutCoords[0].y = (INT32)(Ly1+0.5); 00459 OutCoords[1].x = (INT32)(Lx2+0.5); 00460 OutCoords[1].y = (INT32)(Ly2+0.5); 00461 OutCoords[2].x = (INT32)(Rx0+0.5); 00462 OutCoords[2].y = (INT32)(Ry0+0.5); 00463 OutCoords[3].x = (INT32)(Rx1+0.5); 00464 OutCoords[3].y = (INT32)(Ry1+0.5); 00465 OutCoords[4].x = (INT32)(Rx2+0.5); 00466 OutCoords[4].y = (INT32)(Ry2+0.5); 00467 OutCoords[5].x = x3; 00468 OutCoords[5].y = y3; 00469 00470 // Set the output number of elements. 00471 00472 *NumElements = 6; 00473 00474 return TRUE; 00475 }
|
|
Splits a line element into two lines, returning the lists of new coord points and verbs.
Definition at line 317 of file pathutil.cpp. 00322 { 00323 // check t is in range for this split. 00324 00325 if (t < SPLIT_EPSILON) return FALSE; 00326 if (t > (1.0 - SPLIT_EPSILON)) return FALSE; 00327 00328 // read the lines start and end points 00329 00330 INT32 x0,y0,x1,y1; 00331 00332 x0 = plist[0].x; 00333 y0 = plist[0].y; 00334 x1 = plist[1].x; 00335 y1 = plist[1].y; 00336 00337 // fill in the output block details 00338 00339 Verbs[0] = PT_LINETO; 00340 Coords[0].x = x0 + (INT32)(t*(x1-x0)+0.5); 00341 Coords[0].y = y0 + (INT32)(t*(y1-y0)+0.5); 00342 00343 Verbs[1] = PT_LINETO; 00344 Coords[1].x = x1; 00345 Coords[1].y = y1; 00346 00347 *NumElements = 2; 00348 00349 return TRUE; 00350 00351 }
|
|
Accurate squared distance function.
Definition at line 264 of file pathutil.cpp. 00265 { 00266 double dx = (double) (p2.x - p1.x); 00267 double dy = (double) (p2.y - p1.y); 00268 00269 return ((dx*dx)+(dy*dy)); 00270 00271 }
|
|
Compute the parameter value of the point on a Bezier curve segment closest to some arbtitrary, user-input point. Return the squared distance to the curve.
Definition at line 1407 of file pathutil.cpp. 01411 { 01412 Point2 *w; // Ctrl pts for 5th-degree equ 01413 Point2 lcurve[DEGREE+1]; // Local double version of control polygon 01414 double t_candidate[W_DEGREE]; // Possible roots 01415 INT32 n_solutions; // Number of roots found 01416 double t; // Parameter value of closest pt 01417 double dist; // Closest squared distance to curve 01418 01419 // Convert control polygon to double type 01420 01421 for (INT32 i=0; i < DEGREE+1; i++) 01422 { 01423 lcurve[i].x = (double) V[i].x; 01424 lcurve[i].y = (double) V[i].y; 01425 } 01426 01427 Point2 p; 01428 p.x = (double) P.x; 01429 p.y = (double) P.y; 01430 01431 // Convert problem to 5th-degree Bezier form 01432 01433 w = ConvertToBezierForm(p, lcurve); 01434 01435 // Find all possible roots of 5th-degree equation 01436 01437 n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0); 01438 CCFree((char *)w); 01439 01440 // Compare distances of P to all candidates, and to t=0, and t=1 01441 01442 { double new_dist; 01443 Point2 q; 01444 Vector2 v; 01445 01446 // Check distance to beginning of curve, where t = 0 01447 01448 dist = V2SquaredLength(V2Sub(&p, lcurve, &v)); 01449 t = 0.0; 01450 01451 // Find distances for candidate points 01452 01453 for (INT32 i = 0; i < n_solutions; i++) 01454 { 01455 q = Bezier(lcurve, DEGREE, t_candidate[i], NULL, NULL); 01456 new_dist = V2SquaredLength(V2Sub(&p, &q, &v)); 01457 if (new_dist < dist) 01458 { 01459 dist = new_dist; 01460 t = t_candidate[i]; 01461 } 01462 } 01463 01464 // Finally, look at distance to end point, where t = 1 01465 01466 new_dist = V2SquaredLength(V2Sub(&p, &(lcurve[DEGREE]), &v)); 01467 if (new_dist < dist) 01468 { 01469 dist = new_dist; 01470 t = 1.0; 01471 } 01472 } 01473 01474 *mu = t; 01475 return dist; 01476 01477 }
|
|
Calculates the distance p1 is away from a line segment. The perpendicular distance is returned only when p1 is within the volume created by sweeping the line in the orthoganal direction. Otherwise the distance to the closest end point is returned.
Definition at line 541 of file pathutil.cpp. 00545 { 00546 00547 // get hold of the lines end point coordinates 00548 00549 INT32 x0,y0,x1,y1; 00550 00551 x0 = plist[0].x; 00552 y0 = plist[0].y; 00553 x1 = plist[1].x; 00554 y1 = plist[1].y; 00555 00556 INT32 pdx = (x1-x0); 00557 INT32 pdy = (y1-y0); 00558 00559 // calculate the parameter at which the closest point exists 00560 // on an infinite line passing through (x0,y0),(x1,y1) 00561 // t=numdot/dendot. 00562 00563 double numdot,dendot; 00564 00565 numdot = (double)(p1.x - plist[0].x)*pdx + (double)(p1.y-plist[0].y)*pdy; 00566 dendot = (double)pdx*pdx + (double)pdy*pdy; 00567 00568 // if t is less then zero then the closest point lies behind 00569 // the start point of the vector, hence return the squared 00570 // distance to the startpoint 00571 00572 if (numdot<=0 || dendot<=0) 00573 { 00574 *t = 0.0; 00575 return (SqrDistance(p1, plist[0])); 00576 } 00577 00578 // if t is greater than or equal to 1 then the closest point 00579 // lies beyond the line segment, ie on the projected line 00580 // beyond (x1,y1). So return the squared distance to that end 00581 // point. 00582 00583 if (dendot<=numdot) 00584 { 00585 *t = 1.0; 00586 return (SqrDistance(p1,plist[1])); 00587 } 00588 00589 // ok the closest point lies somewhere inside the line segment 00590 // (x0,y0),(x1,y1) so return its parameter and the squared 00591 // distance to it. 00592 00593 *t = numdot/dendot; 00594 00595 double c = (double)pdy*p1.x - (double)pdx*p1.y; 00596 double d = (double)y1*x0 - (double)y0*x1; 00597 double e = (c-d)*(c-d); 00598 00599 return fabs(e/dendot); 00600 00601 }
|
|
Calculates the distance p1 is away from a semi circle segment. plist[0] describes the centre of the semi circle plist[1] describes a point on the circumference of the circle. For instance say c the centre is (0,0) and cp the circumference point is (1,0) then the semicircle exists in the positive y half of the place and sweeps from (-1,0) to (1,0). Parameter space is param==0 at (-1,0) param==1 at ( 1,0) param==0.5 at ( 0,1).
Definition at line 188 of file pathutil.cpp. 00191 { 00192 double ex,ey,px,py,Px,Py,l,t; 00193 00194 DocCoord c = plist[0]; // the centre point 00195 DocCoord e = plist[1]; // the end point 00196 DocCoord q; 00197 00198 // translate to origin 00199 ex = e.x-c.x; 00200 ey = e.y-c.y; 00201 px = p.x-c.x; 00202 py = p.y-c.y; 00203 00204 // build a (ex,ey) based transform 00205 l = sqrt(ex*ex+ey*ey); 00206 if (l!=0) 00207 { 00208 ex=ex/l; 00209 ey=ex/l; 00210 } 00211 00212 // transform the click point to local canonical 00213 Px = px*ex+py*ey; 00214 Py = py*ex-px*ey; 00215 00216 // are we below the half circle 00217 if (Py>0) 00218 { 00219 // no then calculate the dot product angle 00220 l = sqrt(Px*Px+Py*Py); 00221 if (l!=0) 00222 Px=Px/l; 00223 t = (XS_PI - acos(Px))/XS_PI; 00224 q = PathUtil::PointOnSemiCircle(c,p,t); 00225 } 00226 else 00227 { 00228 // yes then decide start point or endpoint 00229 if (Px>0) 00230 { 00231 t=1.0; 00232 q=e; 00233 } 00234 else 00235 { 00236 t=0.0; 00237 q=e-(c-e); 00238 } 00239 } 00240 00241 // set the output parameter 00242 (*param)=t; 00243 // calculate the squared distance 00244 return PathUtil::SqrDistance(p,q); 00245 }
|