#include <pressure.h>
Public Member Functions | |
PressureSmoother () | |
Constructor. | |
~PressureSmoother () | |
Destructor. | |
ValueFunction * | Smooth (Path *pSourceData, INT32 LineWidth) |
Reads raw recorded pressure information from a path and smooths it, creating a new ValueFunction object representing the pressure function. | |
Private Member Functions | |
CC_DECLARE_MEMDUMP (PressureSmoother) |
Author; Jason
Definition at line 123 of file pressure.h.
|
Constructor. Author; Jason
Definition at line 125 of file pressure.cpp.
|
|
Destructor. Author; Jason
Definition at line 141 of file pressure.cpp.
|
|
|
|
Reads raw recorded pressure information from a path and smooths it, creating a new ValueFunction object representing the pressure function.
2) Smooth the straight line segments in this graph into curve segments At present, this is done by replacing everything between 2 local minima/maxima by an S-shaped curve. This interpolation can be done by a ValueFunctionPressureS object in real-time, so we create one of them. Definition at line 179 of file pressure.cpp. 00180 { 00181 ERROR3IF(pSourceData == NULL, "Illegal NULL param"); 00182 00183 // Find the recorded pressure values (if any) 00184 PathWidth *pWidthArray = pSourceData->GetWidthArray(); 00185 if (pWidthArray == NULL) 00186 return(NULL); 00187 00188 const INT32 NumCoords = pSourceData->GetNumCoords(); 00189 DocCoord *pCoords = pSourceData->GetCoordArray(); 00190 00191 if (NumCoords < 2) 00192 return(NULL); 00193 00194 // Create a ValueFunction to return. We use an "S" curve interpolated pressure function 00195 ValueFunctionPressure *pValFunc = new ValueFunctionPressureS; 00196 if (pValFunc == NULL) 00197 return(NULL); 00198 00199 // Calculate the maximum pressure value recorded. This should be EXTRAVALUEMAX 00200 // but sometimes we seem to get bigger values. 00201 INT32 MaxPressure = pWidthArray[0]; 00202 for (INT32 i = 1; i < NumCoords; i++) 00203 { 00204 if (pCoords[i].y > MaxPressure) 00205 MaxPressure = pWidthArray[i]; 00206 } 00207 00208 // If this pressure was smaller than EXTRAVALUEMAX, then we use that as the maximum, 00209 // because we don't want to scale thin strokes up to max width! 00210 if (MaxPressure < (INT32)EXTRAVALUEMAX) 00211 MaxPressure = EXTRAVALUEMAX; 00212 00213 float Position = 0.0f; 00214 float LastPosition = Position; 00215 INT32 Diff = 0; 00216 INT32 LastDiff = pWidthArray[1] - pWidthArray[0]; 00217 00218 pValFunc->AddPressure(Position, (float)pWidthArray[0] / (float)MaxPressure); 00219 00220 // --- Now loop through the pressure samples, scaling them into the correct range, calculating 00221 // proper "position" values for them, and smoothing the data (by replacing all points between 00222 // minima and maxima with s-shaped interpolated segments) 00223 for (INT32 Index = 1; Index < NumCoords - 1; Index++) 00224 { 00225 // Record the pressure sample. We chuck away all samples between minima/maxima 00226 // as we go, and also wheedle out any zero-length sections that might crop up. 00227 // Then the ValueFunction will interpolate between the values as it sees fit (with S-shaped curves) 00228 if (Position > LastPosition) 00229 { 00230 LastPosition = Position; 00231 00232 Diff = pWidthArray[Index] - pWidthArray[Index - 1]; 00233 if ((Diff > 0 && LastDiff <= 0) || (Diff < 0 && LastDiff >= 0)) 00234 { 00235 // We have found a min/maximum. Record this point. 00236 pValFunc->AddPressure(Position, (float)pWidthArray[Index] / (float)MaxPressure); 00237 LastDiff = Diff; 00238 } 00239 } 00240 00241 // Work out approximate "travel" along the path so each width sample has a known position 00242 // [This should be calculated in the same way as in TrapEdgeList::ProcessEdgePositions, pathtrap.cpp] 00243 00244 #if TRUE 00245 // This now simply calculates distance down the centreline. 00246 // Much faster & simpler, and it turns out it gives better results after all! 00247 const double dx = (double) (pCoords[Index-1].x - pCoords[Index].x); 00248 const double dy = (double) (pCoords[Index-1].y - pCoords[Index].y); 00249 Position += (float) sqrt((dx * dx) + (dy * dy)); 00250 #else 00251 /* 00252 // Calculate the line normals to the left and right of the point 00253 NormCoord Normal1; 00254 NormCoord Normal2; 00255 Normal1.SetNormalToLine(pCoords[Index], pCoords[Index - 1]); 00256 Normal2.SetNormalToLine(pCoords[Index + 1], pCoords[Index]); 00257 00258 // Calculate the "left" parallel edge 00259 DocCoord P1( pCoords[Index-1].x + (INT32)((double) LineWidth * Normal1.x), 00260 pCoords[Index-1].y + (INT32)((double) LineWidth * Normal1.y)); 00261 DocCoord P2( pCoords[Index ].x + (INT32)((double) LineWidth * Normal2.x), 00262 pCoords[Index ].y + (INT32)((double) LineWidth * Normal2.y)); 00263 double dx = P1.x - P2.x; 00264 double dy = P1.y - P2.y; 00265 double LeftTravel = sqrt((dx * dx) + (dy * dy)); 00266 00267 // Calculate the "right" parallel edge 00268 P1 = DocCoord( pCoords[Index-1].x - (INT32)((double) LineWidth * Normal1.x), 00269 pCoords[Index-1].y - (INT32)((double) LineWidth * Normal1.y)); 00270 P2 = DocCoord( pCoords[Index ].x - (INT32)((double) LineWidth * Normal2.x), 00271 pCoords[Index ].y - (INT32)((double) LineWidth * Normal2.y)); 00272 dx = P1.x - P2.x; 00273 dy = P1.y - P2.y; 00274 double RightTravel = sqrt((dx * dx) + (dy * dy)); 00275 00276 // And increment Position by the larger of the 2 travel distances 00277 Position += (float)( (LeftTravel > RightTravel) ? LeftTravel : RightTravel ); 00278 */ 00279 #endif 00280 } 00281 00282 // And always add a knot at the very end of the curve 00283 pValFunc->AddPressure(Position, (float)pWidthArray[NumCoords - 1] / (float)MaxPressure); 00284 00285 pValFunc->NormalisePositions(); // And normalise all positions to lie between 0.0 and 1.0 00286 00287 return(pValFunc); 00288 }
|