PathUtil Class Reference

Base class for path utility static functions. These functions operate on sections of paths, ie lists of doc coords, but do not process complete paths and hence cannot be included as member functions of the paths class. The class contains no member variables, just static member functions which would otherwise be global if not for the fabby idea of encompasing them together under a class structure. More...

#include <pathutil.h>

List of all members.

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 &centre, 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.


Detailed Description

Base class for path utility static functions. These functions operate on sections of paths, ie lists of doc coords, but do not process complete paths and hence cannot be included as member functions of the paths class. The class contains no member variables, just static member functions which would otherwise be global if not for the fabby idea of encompasing them together under a class structure.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/8/94

Definition at line 142 of file pathutil.h.


Member Function Documentation

void PathUtil::GetCurveCoefs const DocCoord coords,
PtCoefs coefs
[static]
 

Converts a curve from Bezier form to Canonical form.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
coords = a pointer to 4 control point doccoords defining a curve [INPUTS]
coefs = a set of curve coefficients. [OUTPUTS]
Returns:
None

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 }

DocCoord PathUtil::PointOnCurve double  t,
const DocCoord plist
[static]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
t = parameter to evaluate curve at [INPUTS] plist = pointer to list of 4 curve control points.
[OUTPUTS] 
Returns:
A DocCoord describing the point on the curve

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 }

DocCoord PathUtil::PointOnLine const double  t,
const DocCoord ptlist
[static]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
t = parameter at which to evaluate point [INPUTS] ptlist = pointer to two doc coords describing start and end of the line
[OUTPUTS] 
Returns:
DocCoord, an evaluation of a point on the specified line

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 }

DocCoord PathUtil::PointOnSemiCircle const DocCoord centre,
const DocCoord radialp,
double  t
[static]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/03/97
Parameters:
centre = the centre point of the circle [INPUTS] radialp = another point (anywhere, but assumed to be somewhere on the radius of the circle. t = a parameter (0..1) defining the parametric locus about the centre from 0 to pi radians.
- [OUTPUTS]
Returns:
A new doc coord which is a point on the circles perimeter which corresponds to the parameter t. At t==1 the function will evaluate to radialp At t==0 the function will evaluate to centre-(radialp-centre)

Errors: None.

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 }

BOOL PathUtil::SplitCurve const double  t,
const DocCoord plist,
UINT32 NumElements,
PathVerb OutVerbs,
DocCoord OutCoords
[static]
 

Splits a curve element into two curves, returning the lists of new control points and verbs.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
t = parameter at which to split the curve [INPUTS] plist = pointer to 4 curve control points to split
NumElements = number of elements generated [OUTPUTS] OutVerbs = output verbs list OutCoords = output coords list
Returns:
True if the curve could be split, False if not.

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 }

BOOL PathUtil::SplitLine const double  t,
const DocCoord plist,
UINT32 NumElements,
PathVerb Verbs,
DocCoord Coords
[static]
 

Splits a line element into two lines, returning the lists of new coord points and verbs.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
t = parameter at which to split the line [INPUTS] plist = pointer to 2 doc coords describing the line
NumElements = number of elements generated after split [OUTPUTS] OutVerbs = pointer to verbs list to output data to OutCoords = pointer to coords list to output data to
Returns:
True if the line can be split, False if not.

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 }

double PathUtil::SqrDistance const DocCoord p1,
const DocCoord p2
[static]
 

Accurate squared distance function.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/8/94
Parameters:
two coordinates [INPUTS]
None [OUTPUTS]
Returns:
the squared distance between the two coordinates

Errors: None.

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 }

double PathUtil::SqrDistanceToCurve const UINT32  split,
const DocCoord V,
const DocCoord P,
double *  mu
[static]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
split = max level at which to split the curve (usually 64) [INPUTS] P = The user-supplied point V = Control points of cubic Bezier
mu holds the parameter value of the closest point on the curve, 0<=mu<=1 [OUTPUTS]
Returns:
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 }

double PathUtil::SqrDistanceToLine const DocCoord plist,
const DocCoord p1,
double *  t
[static]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
plist = a pointer to two doc coordinates describing a line [INPUTS] p1 = the point to find the squared distance to
t = the parameter at which the closest point exists [OUTPUTS]
Returns:
a double, the distance a given point is away from a line element

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 }

double PathUtil::SqrDistanceToSemiCircle const DocCoord plist,
const DocCoord p,
double *  param
[static]
 

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).

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
plist = a pointer to two doc coordinates describing a half circle [INPUTS] p1 = the point to find the squared distance to
param = the parameter at which the closest point exists [OUTPUTS]
Returns:
a double, the distance a given point is away from a line element

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 }


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:59:41 2007 for Camelot by  doxygen 1.4.4