@@ -55,16 +55,17 @@ typedef enum CompactPathResultCode
55
55
#define FAILURE 0
56
56
#define SUCCESS 1
57
57
58
- static CompactPathResultCode CompactPathSubproblemSolver (DVector2D * pPointArray ,
58
+ static CompactPathResultCode compactPathSubproblemSolver (DVector2D * pPointArray ,
59
59
int iPointsInCurrentPath , DVector2D * pResultPointArray ,
60
- int * piPointsInResultPath , int * piDivisionIndex , double dEpsilon );
60
+ int * piPointsInResultPath , int * piDivisionIndex , double dEpsilon ,
61
+ DeviationMetric deviationMetric );
61
62
62
63
// The call stack will start able to hold this many calls and grow by this amount whenever it needs
63
64
// to grow in size.
64
65
#define COMPACT_PATH_CALL_STACK_UNIT 2048
65
66
66
67
// callStackBase is a double pointer because realloc might move the base pointer.
67
- static int CompactPathCallStackPush (CompactPathSubproblemCall * * ppCallStackBase ,
68
+ static int compactPathCallStackPush (CompactPathSubproblemCall * * ppCallStackBase ,
68
69
int * piCallStackCapacity , int * piNumCallsInStack ,
69
70
CompactPathSubproblemCall * pCall )
70
71
{
@@ -89,7 +90,7 @@ static int CompactPathCallStackPush(CompactPathSubproblemCall **ppCallStackBase,
89
90
return SUCCESS ;
90
91
}
91
92
92
- static int CompactPathCallStackPop (CompactPathSubproblemCall * pCallStackBase ,
93
+ static int compactPathCallStackPop (CompactPathSubproblemCall * pCallStackBase ,
93
94
int * piNumCallsInStack , CompactPathSubproblemCall * pPoppedCall )
94
95
{
95
96
// Check if there is a call to pop.
@@ -124,8 +125,9 @@ static int CompactPathCallStackPop(CompactPathSubproblemCall *pCallStackBase,
124
125
// and resultPointArray, keeping in mind that doing so will likely alter pointArray.
125
126
// Returns a true value (1) on successful completion, and returns a false value (0) otherwise.
126
127
// On failure, pointsInResultPath and the contents of resultPointArray are undefined.
127
- int CompactPath (DVector2D * pPointArray , int iPointsInCurrentPath ,
128
- DVector2D * pResultPointArray , int * piPointsInResultPath , double dEpsilon )
128
+ int compactPath (DVector2D * pPointArray , int iPointsInCurrentPath ,
129
+ DVector2D * pResultPointArray , int * piPointsInResultPath , double dEpsilon ,
130
+ DeviationMetric deviationMetric )
129
131
{
130
132
CompactPathSubproblemCall current , firstSubproblem , secondSubproblem ;
131
133
int iDivisionIndex ; // Where should we split the problem into subproblems?
@@ -164,22 +166,22 @@ int CompactPath(DVector2D *pPointArray, int iPointsInCurrentPath,
164
166
current .iPointsInCurrentPath = iPointsInCurrentPath ;
165
167
166
168
// Add the first instance to the stack
167
- if (!CompactPathCallStackPush (& pCallStackBase , & iCallStackCapacity , & iNumCallsInStack , & current ))
169
+ if (!compactPathCallStackPush (& pCallStackBase , & iCallStackCapacity , & iNumCallsInStack , & current ))
168
170
{
169
171
COMPACT_PATH_RETURN (FAILURE );
170
172
}
171
173
172
174
// As long as there are calls on the stack, pop one and process it.
173
175
while (iNumCallsInStack > 0 )
174
176
{
175
- if (!CompactPathCallStackPop (pCallStackBase , & iNumCallsInStack , & current ))
177
+ if (!compactPathCallStackPop (pCallStackBase , & iNumCallsInStack , & current ))
176
178
{
177
179
COMPACT_PATH_RETURN (FAILURE );
178
180
}
179
181
180
- subproblemResultCode = CompactPathSubproblemSolver (current .pPointArray ,
182
+ subproblemResultCode = compactPathSubproblemSolver (current .pPointArray ,
181
183
current .iPointsInCurrentPath , current .pResultPointArray , & iPointsInResultPath ,
182
- & iDivisionIndex , dEpsilon );
184
+ & iDivisionIndex , dEpsilon , deviationMetric );
183
185
184
186
if (subproblemResultCode == COMPACT_PATH_RESULT_CODE_DIVIDE )
185
187
{
@@ -199,7 +201,7 @@ int CompactPath(DVector2D *pPointArray, int iPointsInCurrentPath,
199
201
secondSubproblem .pPointArray = current .pPointArray + iDivisionIndex ;
200
202
secondSubproblem .pResultPointArray = current .pResultPointArray + iDivisionIndex ;
201
203
secondSubproblem .iPointsInCurrentPath = current .iPointsInCurrentPath - iDivisionIndex ;
202
- if (!CompactPathCallStackPush (& pCallStackBase , & iCallStackCapacity ,
204
+ if (!compactPathCallStackPush (& pCallStackBase , & iCallStackCapacity ,
203
205
& iNumCallsInStack , & secondSubproblem ))
204
206
{
205
207
COMPACT_PATH_RETURN (FAILURE );
@@ -208,7 +210,7 @@ int CompactPath(DVector2D *pPointArray, int iPointsInCurrentPath,
208
210
firstSubproblem .pPointArray = current .pPointArray ;
209
211
firstSubproblem .pResultPointArray = current .pResultPointArray ;
210
212
firstSubproblem .iPointsInCurrentPath = iDivisionIndex + 1 ;
211
- if (!CompactPathCallStackPush (& pCallStackBase , & iCallStackCapacity ,
213
+ if (!compactPathCallStackPush (& pCallStackBase , & iCallStackCapacity ,
212
214
& iNumCallsInStack , & firstSubproblem ))
213
215
{
214
216
COMPACT_PATH_RETURN (FAILURE );
@@ -251,12 +253,12 @@ int CompactPath(DVector2D *pPointArray, int iPointsInCurrentPath,
251
253
// If the result is COMPACT_PATH_RESULT_CODE_SOLVED, it means that the algorithm does not need to
252
254
// do any further work on the subproblem, because it is already solved. In this case, divisionIndex
253
255
// is not set.
254
- static CompactPathResultCode CompactPathSubproblemSolver (DVector2D * pPointArray ,
256
+ static CompactPathResultCode compactPathSubproblemSolver (DVector2D * pPointArray ,
255
257
int iPointsInCurrentPath , DVector2D * pResultPointArray ,
256
- int * piPointsInResultPath , int * piDivisionIndex , double dEpsilon )
258
+ int * piPointsInResultPath , int * piDivisionIndex , double dEpsilon ,
259
+ DeviationMetric deviationMetric )
257
260
{
258
- double dSquareSegLen , dDX , dDY , dArea , dSquareDeviation , dMaxSquareDeviationInThisSegment ,
259
- ax , ay , bx , by , cx , cy ;
261
+ double dSquareSegLen , dSquareDeviation , dMaxSquareDeviationInThisSegment , dDX , dDY ;
260
262
int i , iMaxPointIndex ;
261
263
262
264
// If there are fewer than three points provided, the problem is solved already.
@@ -272,22 +274,16 @@ static CompactPathResultCode CompactPathSubproblemSolver(DVector2D *pPointArray,
272
274
}
273
275
274
276
dMaxSquareDeviationInThisSegment = 0.0 ;
275
- ax = pPointArray [0 ].dX ;
276
- ay = pPointArray [0 ].dY ;
277
- cx = pPointArray [iPointsInCurrentPath - 1 ].dX ;
278
- cy = pPointArray [iPointsInCurrentPath - 1 ].dY ;
279
- dDX = cx - ax ;
280
- dDY = cy - ay ;
277
+
278
+ dDX = pPointArray [iPointsInCurrentPath - 1 ].dX - pPointArray [0 ].dX ;
279
+ dDY = pPointArray [iPointsInCurrentPath - 1 ].dY - pPointArray [0 ].dY ;
281
280
dSquareSegLen = dDX * dDX + dDY * dDY ;
282
281
283
282
for (i = 1 ; i < iPointsInCurrentPath - 1 ; ++ i )
284
283
{
285
- bx = pPointArray [i ].dX ;
286
- by = pPointArray [i ].dY ;
287
- // TODO: optionally use the endpoint distance if the triangle is skew.
288
- dArea = ax * (by - cy ) + bx * (cy - ay ) + cx * (ay - by );
289
-
290
- dSquareDeviation = dArea * dArea / dSquareSegLen ;
284
+ dSquareDeviation = deviationMetric (pPointArray [0 ],
285
+ pPointArray [iPointsInCurrentPath - 1 ], pPointArray [i ], dSquareSegLen );
286
+
291
287
if (dSquareDeviation > dMaxSquareDeviationInThisSegment )
292
288
{
293
289
iMaxPointIndex = i ;
@@ -311,4 +307,3 @@ static CompactPathResultCode CompactPathSubproblemSolver(DVector2D *pPointArray,
311
307
return COMPACT_PATH_RESULT_CODE_DIVIDE ;
312
308
}
313
309
}
314
-
0 commit comments