FitCurveNoChangeGeometry Class Reference

This class uses the fit curve functionality to reduce the number of points in a path, whereas keeping the geometry as close to the original as possible. More...

#include <fitcurve.h>

List of all members.

Static Public Member Functions

static void SmoothPath (Path *pPath, double Error)
 Smooths the path, eliminating all unnecessary points Notes : For example of use, see NodeCntr.cpp, GenerateContour() function.

Private Member Functions

 CC_DECLARE_MEMDUMP (CurveFitObject)

Static Private Member Functions

static void SmoothPathNoChangeGeometry (Path *pPath, double Error)
 Smooths the path, eliminating all unnecessary points but maintaining geometry as much as possible - doesn't eliminate colinear points Notes: Assumes the path is flattened.
static void EliminateColinearPointsFromPath (Path *pPath)
 Eliminates Notes: Do after SmoothPathNoChangeGeometry.


Detailed Description

This class uses the fit curve functionality to reduce the number of points in a path, whereas keeping the geometry as close to the original as possible.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/1/2000

Definition at line 257 of file fitcurve.h.


Member Function Documentation

FitCurveNoChangeGeometry::CC_DECLARE_MEMDUMP CurveFitObject   )  [private]
 

void FitCurveNoChangeGeometry::EliminateColinearPointsFromPath Path pPath  )  [static, private]
 

Eliminates Notes: Do after SmoothPathNoChangeGeometry.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/1/2000
Parameters:
pPath - The path to smooth (must have NO sub-paths) [INPUTS]

Definition at line 1316 of file fitcurve.cpp.

01317 {
01318     // make sure the flags are initialised on the path
01319     pPath->InitialiseFlags();
01320     
01321     NormCoord Vec1, Vec2;
01322     double dot = 0;
01323 //  double OriginalDot = 0;
01324 
01325     BOOL bClose = FALSE;
01326 
01327     if ((pPath->GetVerbArray()[pPath->GetNumCoords() - 1] & PT_CLOSEFIGURE) != 0)
01328     {
01329         pPath->GetVerbArray()[pPath->GetNumCoords() - 1] -= PT_CLOSEFIGURE;
01330         bClose = TRUE;
01331     }
01332 
01333     INT32 StartIndex = 0;
01334     INT32 MidIndex = 0;
01335     INT32 EndIndex = 0;
01336 
01337     // threshold is one degree
01338     const double Thres = cos (1.0 * 3.142 / 180.0);
01339 
01340     BOOL bDelete = FALSE;
01341 
01342     for (INT32 i = 0 ; i < pPath->GetNumCoords() - 2; 
01343                 i ++)
01344     {
01345         // set up the start, mid & end points of the section to test
01346         StartIndex = -1;
01347         MidIndex = -1;
01348         EndIndex = -1;
01349 
01350         if (pPath->GetVerbArray()[i] == PT_MOVETO ||
01351             pPath->GetVerbArray()[i] == PT_LINETO)
01352         {
01353             StartIndex = i;
01354             MidIndex = i+1;
01355         }
01356         else if (pPath->GetVerbArray()[i] == PT_BEZIERTO)
01357         {
01358             if (pPath->GetFlagArray()[i].IsEndPoint)
01359             {
01360                 StartIndex = i;
01361                 MidIndex = i + 1;
01362             }
01363             else if (i < pPath->GetNumCoords()-1 && pPath->GetFlagArray()[i+1].IsEndPoint)
01364             {
01365                 StartIndex = i + 1;
01366                 MidIndex = i + 2;
01367             }
01368             else if (i < pPath->GetNumCoords()-2 && pPath->GetFlagArray()[i+2].IsEndPoint)
01369             {
01370                 StartIndex = i + 2;
01371                 MidIndex = i + 3;
01372             }
01373             else
01374             {
01375                 ERROR3("Path Flags not initialised");
01376             }
01377         }
01378         else
01379         {
01380             ERROR3("Unrecognised path element");
01381         }
01382 
01383         // so we now have the start & mid points, let's get the end point the same way
01384         if (StartIndex >= 0 && MidIndex >= 0)
01385         {
01386             if (pPath->GetVerbArray()[MidIndex] == PT_LINETO ||
01387                 pPath->GetVerbArray()[MidIndex] == PT_MOVETO)
01388             {
01389                 EndIndex = MidIndex + 1;
01390             }
01391             else if (pPath->GetVerbArray()[MidIndex] == PT_BEZIERTO)
01392             {
01393                 EndIndex = MidIndex + 3;
01394             }
01395             else
01396             {
01397                 ERROR3("Unrecognised path element");
01398             }
01399         }
01400 
01401         // if we have valid points, check all vectors imbetween
01402         if (StartIndex >= 0 && MidIndex >= 0 && EndIndex >= 0)
01403         {
01404             bDelete = TRUE;
01405 
01406             if (EndIndex < StartIndex + 2)
01407                 bDelete = FALSE;
01408 
01409             for (INT32 j = StartIndex; j <= EndIndex-2; j++)
01410             {
01411                 if (j == StartIndex)
01412                 {
01413                     Vec1.x = pPath->GetCoordArray()[j+1].x - pPath->GetCoordArray()[j].x;
01414                     Vec1.y = pPath->GetCoordArray()[j+1].y - pPath->GetCoordArray()[j].y;
01415                     Vec1.Normalise();
01416                 }
01417                 else
01418                 {
01419                     Vec1 = Vec2;
01420                 }
01421 
01422                 Vec2.x = pPath->GetCoordArray()[j+2].x - pPath->GetCoordArray()[j+1].x;
01423                 Vec2.y = pPath->GetCoordArray()[j+2].y - pPath->GetCoordArray()[j+1].y;
01424 
01425                 Vec2.Normalise();
01426 
01427                 dot = (Vec1.x * Vec2.x) + (Vec1.y * Vec2.y);
01428 
01429                 if (dot < Thres)
01430                 {
01431                     // angle is greater than the threshold, so don't delete this section
01432                     bDelete = FALSE;
01433                     break;
01434                 }
01435                 else
01436                 {
01437                     bDelete = TRUE;
01438                 }
01439             }
01440 
01441             if (bDelete)
01442             {
01443                 if (pPath->GetVerbArray()[MidIndex] == PT_LINETO)
01444                 {
01445                     // delete this point
01446                     pPath->DeleteSection(MidIndex, 1);
01447                 }
01448                 else if (pPath->GetVerbArray()[MidIndex] == PT_BEZIERTO)
01449                 {
01450                     pPath->DeleteSection(MidIndex, 3);
01451                 }
01452 
01453                 // start again at this point
01454                 i --;
01455             }
01456         }
01457     }   
01458 
01459     if (bClose)
01460     {
01461         pPath->GetVerbArray()[pPath->GetNumCoords() - 1] |= PT_CLOSEFIGURE;
01462     }
01463 }

void FitCurveNoChangeGeometry::SmoothPath Path pPath,
double  Error
[static]
 

Smooths the path, eliminating all unnecessary points Notes : For example of use, see NodeCntr.cpp, GenerateContour() function.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/1/2000
Parameters:
pPath - The path to smooth [INPUTS] Error - The error to pass into Path::Smooth()

Definition at line 1195 of file fitcurve.cpp.

01196 {
01197     Path SubPath;
01198     SubPath.Initialise();
01199 
01200     Path QuantPath;
01201     QuantPath.Initialise();
01202 
01203     Path RetnPath;
01204     RetnPath.Initialise();
01205     
01206     // split the path into sub-paths
01207     INT32 NumSubPaths = pPath->GetNumSubpaths();
01208     for (INT32 i = 0; i < NumSubPaths ; i++)
01209     {
01210         // seperate out all sub-paths and smooth them individually
01211         SubPath.ClearPath();
01212         pPath->MakePathFromSubPath(i, &SubPath);
01213 
01214         // quantise this path
01215         QuantPath.ClearPath();
01216         SubPath.Quantise(20, &QuantPath);
01217 
01218         SmoothPathNoChangeGeometry(&QuantPath, Error);
01219         EliminateColinearPointsFromPath(&QuantPath);
01220         
01221         RetnPath.MergeTwoPaths(QuantPath);
01222     }
01223 
01224     pPath->ClearPath();
01225     pPath->CloneFrom(RetnPath);
01226 }

void FitCurveNoChangeGeometry::SmoothPathNoChangeGeometry Path pPath,
double  Error
[static, private]
 

Smooths the path, eliminating all unnecessary points but maintaining geometry as much as possible - doesn't eliminate colinear points Notes: Assumes the path is flattened.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/1/2000
Parameters:
pPath - The path to smooth (must have NO sub-paths) [INPUTS] Error - The error to pass into Path::Smooth()

Definition at line 1241 of file fitcurve.cpp.

01242 {
01243     INT32 StartIndex = 0;
01244     INT32 EndIndex = 0;
01245 
01246     NormCoord Vec1;
01247     NormCoord Vec2;
01248 
01249     double dot = 0;
01250 
01251     // threshold for 30 degrees for the dot product
01252     const double Thres = cos(30.0 * 3.142 / 180.0);
01253     
01254     for (INT32 i = 0 ; i < pPath->GetNumCoords(); i++)
01255     {
01256         if (i < pPath->GetNumCoords() - 2)
01257         {
01258             Vec1.x = pPath->GetCoordArray()[i+1].x - pPath->GetCoordArray()[i].x;
01259             Vec1.y = pPath->GetCoordArray()[i+1].y - pPath->GetCoordArray()[i].y;
01260 
01261             Vec2.x = pPath->GetCoordArray()[i+2].x - pPath->GetCoordArray()[i+1].x;
01262             Vec2.y = pPath->GetCoordArray()[i+2].y - pPath->GetCoordArray()[i+1].y;
01263 
01264             Vec1.Normalise();
01265             Vec2.Normalise();
01266 
01267             dot = (Vec1.x * Vec2.x) + (Vec1.y * Vec2.y);
01268 
01269             if (dot < Thres)
01270             {
01271                 // don't smooth this !
01272             }
01273             else
01274             {
01275                 StartIndex = i;
01276                 
01277                 // find the region to smooth
01278                 while (dot > Thres && i < (pPath->GetNumCoords() - 2))
01279                 {
01280                     i++;
01281                     Vec1 = Vec2;
01282                     Vec2.x = pPath->GetCoordArray()[i+2].x - pPath->GetCoordArray()[i+1].x;
01283                     Vec2.y = pPath->GetCoordArray()[i+2].y - pPath->GetCoordArray()[i+1].y;
01284                     Vec2.Normalise();
01285 
01286                     dot = (Vec1.x * Vec2.x) + (Vec1.y * Vec2.y);
01287                 }
01288                  
01289                 i--;
01290 
01291                 EndIndex = i+1;
01292 
01293                 // ok, we've found the region to smooth so do it !
01294                 if (EndIndex > StartIndex && EndIndex < pPath->GetNumCoords())
01295                 {
01296                     pPath->SmoothSection(StartIndex, &EndIndex, Error, 0);
01297                 }
01298 
01299                 i = EndIndex+1;
01300             }
01301         }
01302     }
01303 }


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