#include <fitcurve.h>
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. |
Definition at line 257 of file fitcurve.h.
|
|
|
Eliminates Notes: Do after SmoothPathNoChangeGeometry.
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 }
|
|
Smooths the path, eliminating all unnecessary points Notes : For example of use, see NodeCntr.cpp, GenerateContour() function.
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 }
|
|
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.
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 }
|