1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - PRC -
3 File: prc_algo_standard.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro.h>
19 #include <nitro/prc/algo_standard.h>
20
21 /*===========================================================================*
22 Prototype Declarations
23 *===========================================================================*/
CityBlockDistance(const PRCPoint * p1,const PRCPoint * p2)24 static inline int CityBlockDistance(const PRCPoint *p1, const PRCPoint *p2)
25 {
26 int x = p1->x - p2->x;
27 int y = p1->y - p2->y;
28 if (x < 0)
29 x = -x;
30 if (y < 0)
31 y = -y;
32 return (x + y);
33 }
34
GetMiddlePoint(PRCPoint * p,const PRCPoint * p1,const PRCPoint * p2)35 static inline void GetMiddlePoint(PRCPoint *p, const PRCPoint *p1, const PRCPoint *p2)
36 {
37 p->x = (s16)((p1->x + p2->x) / 2);
38 p->y = (s16)((p1->y + p2->y) / 2);
39 }
40
41 /*===========================================================================*
42 Variable Definitions
43 *===========================================================================*/
44
45 /*===========================================================================*
46 Functions
47 *===========================================================================*/
48
49 /*---------------------------------------------------------------------------*
50 Name: PRC_GetRecognitionBufferSizeEx_Standard
51
52 Description: Calculates the work area size required for recognition algorithm.
53
54
55 Arguments: maxPointCount: Upper limit of number of input points (includes pen up marker)
56 maxStrokeCount: Upper limit of stroke count
57 protoDB: Sample DB
58 param: Parameters for recognition processing
59
60 Returns: The memory capacity required for the recognition algorithm.
61 *---------------------------------------------------------------------------*/
62 u32
PRC_GetRecognitionBufferSizeEx_Standard(int maxPointCount,int maxStrokeCount,const PRCPrototypeDB_Standard * protoDB,const PRCRecognizeParam_Standard * param)63 PRC_GetRecognitionBufferSizeEx_Standard(int maxPointCount,
64 int maxStrokeCount,
65 const PRCPrototypeDB_Standard *protoDB,
66 const PRCRecognizeParam_Standard *param)
67 {
68 (void)maxPointCount;
69 (void)maxStrokeCount;
70 (void)protoDB;
71 (void)param;
72
73 return 1; // Because OS_Alloc(0) causes an error
74 }
75
76 /*---------------------------------------------------------------------------*
77 Name: PRC_GetRecognizedEntriesEx_Standard
78
79 Description: Compares and recognizes a specific kind entry and input pattern to return the top numRanking ranking of the result.
80
81
82 Arguments: resultEntries: Pointer to array that holds pointers to recognition results.
83 If less than the requested number could be recognized, fill in remainder with NULL.
84
85 resultScores: Pointer to recognition result score array
86 numRanking: Number of returns to result*
87 buffer: Pointer to memory region used by recognition algorithm
88 (Region size >= return value of PRC_GetRecognitionBufferSize)
89 input: Input pattern
90 protoDB: Sample DB
91 kindMask: Takes the logical AND of the 'kind' values for all the sample DB entries. Considered valid if it is non-zero.
92
93 param: Parameters for recognition processing
94
95 Returns: Number of patterns in the compared sample DBs.
96 *---------------------------------------------------------------------------*/
97 int
PRC_GetRecognizedEntriesEx_Standard(PRCPrototypeEntry ** resultEntries,fx32 * resultScores,int numRanking,void * buffer,const PRCInputPattern_Standard * input,const PRCPrototypeDB_Standard * protoDB,u32 kindMask,const PRCRecognizeParam_Standard * param)98 PRC_GetRecognizedEntriesEx_Standard(PRCPrototypeEntry **resultEntries,
99 fx32 *resultScores,
100 int numRanking,
101 void *buffer,
102 const PRCInputPattern_Standard *input,
103 const PRCPrototypeDB_Standard *protoDB,
104 u32 kindMask, const PRCRecognizeParam_Standard *param)
105 {
106 int i;
107 const PRCiPatternData_Common *inputData;
108 int numCompared;
109 int normalizeSize;
110 int doubleWidth;
111
112 (void)buffer;
113 (void)param;
114
115 SDK_ASSERT(resultEntries);
116 SDK_ASSERT(resultScores);
117 SDK_ASSERT(input);
118 SDK_ASSERT(protoDB);
119 SDK_ASSERT(numRanking > 0);
120
121 for (i = 0; i < numRanking; i++)
122 {
123 resultEntries[i] = NULL;
124 resultScores[i] = 0;
125 }
126
127 normalizeSize = protoDB->normalizeSize;
128 if (normalizeSize < input->normalizeSize)
129 {
130 normalizeSize = input->normalizeSize;
131 }
132 doubleWidth = normalizeSize * 2;
133
134 inputData = &input->data;
135 numCompared = 0;
136
137 {
138 const PRCiPrototypeEntry_Common *proto;
139 int iPattern;
140
141 proto = protoDB->patterns;
142
143 for (iPattern = 0; iPattern < protoDB->patternCount; iPattern++, proto++)
144 {
145 const PRCiPatternData_Common *protoData;
146 int iStroke;
147 fx32 wholeScore;
148 fx32 wholeWeight;
149
150 if (!proto->entry->enabled || !(proto->entry->kind & kindMask))
151 continue;
152
153 protoData = &proto->data;
154
155 if (inputData->strokeCount != protoData->strokeCount)
156 continue;
157
158 wholeScore = 0;
159 wholeWeight = 0;
160
161 for (iStroke = 0; iStroke < inputData->strokeCount; iStroke++)
162 {
163 int iProto, iInput;
164 int protoStrokeIndex, inputStrokeIndex;
165 int protoSize, inputSize;
166 const PRCPoint *protoPoints;
167 const PRCPoint *inputPoints;
168 const u16 *protoAngle;
169 const u16 *inputAngle;
170 const fx16 *protoRatio;
171 const fx16 *inputRatio;
172 // PRCPoint protoMidPoint, inputMidPoint;
173 fx16 protoNextRatio, inputNextRatio;
174 fx32 strokeScore;
175 fx16 strokeRatio;
176
177 strokeScore = 0;
178
179 protoStrokeIndex = protoData->strokes[iStroke];
180 inputStrokeIndex = inputData->strokes[iStroke];
181 protoSize = protoData->strokeSizes[iStroke];
182 inputSize = inputData->strokeSizes[iStroke];
183 protoPoints = &protoData->pointArray[protoStrokeIndex];
184 inputPoints = &inputData->pointArray[inputStrokeIndex];
185 protoAngle = &protoData->lineSegmentAngleArray[protoStrokeIndex];
186 inputAngle = &inputData->lineSegmentAngleArray[inputStrokeIndex];
187 protoRatio = &protoData->lineSegmentRatioToStrokeArray[protoStrokeIndex];
188 inputRatio = &inputData->lineSegmentRatioToStrokeArray[inputStrokeIndex];
189
190 SDK_ASSERT(protoSize >= 2);
191 SDK_ASSERT(inputSize >= 2);
192
193 iProto = iInput = 1;
194 protoNextRatio = protoRatio[iProto];
195 inputNextRatio = inputRatio[iInput];
196 // GetMiddlePoint(&protoMidPoint, &protoPoints[iProto-1], &protoPoints[iProto]);
197 // GetMiddlePoint(&inputMidPoint, &inputPoints[iInput-1], &inputPoints[iInput]);
198 for (i = 0; i < protoSize + inputSize - 3; i++)
199 {
200 int diff, score;
201 SDK_ASSERT(iProto < protoSize);
202 SDK_ASSERT(iInput < inputSize);
203 diff = (s16)(protoAngle[iProto] - inputAngle[iInput]);
204 if (diff < 0)
205 {
206 diff = -diff;
207 }
208 score = ((32768 - diff) / 128);
209 if (protoNextRatio <= inputNextRatio)
210 {
211 // Trace one step in the sample stroke
212 // The distance from the closer of the points in the input stroke is reflected in the score
213 inputNextRatio -= protoNextRatio;
214 score *= (inputNextRatio < inputRatio[iInput] / 2) // Remainder of less than half = Next point is closer
215 ? (doubleWidth -
216 CityBlockDistance(&inputPoints[iInput],
217 &protoPoints[iProto])) : (doubleWidth -
218 CityBlockDistance
219 (&inputPoints
220 [iInput - 1],
221 &protoPoints[iProto]));
222 strokeScore += protoNextRatio * score;
223 iProto++;
224 protoNextRatio = protoRatio[iProto];
225 // GetMiddlePoint(&protoMidPoint, &protoPoints[iProto-1], &protoPoints[iProto]);
226 }
227 else
228 {
229 // Trace one step in the input stroke
230 // The distance from the closer of the points in the sample stroke is reflected in the score
231 protoNextRatio -= inputNextRatio;
232 score *= (protoNextRatio < protoRatio[iProto] / 2) // Remainder of less than half = Next point is closer
233 ? (doubleWidth -
234 CityBlockDistance(&inputPoints[iInput],
235 &protoPoints[iProto])) : (doubleWidth -
236 CityBlockDistance
237 (&inputPoints[iInput],
238 &protoPoints[iProto -
239 1]));
240 strokeScore += inputNextRatio * score;
241 iInput++;
242 inputNextRatio = inputRatio[iInput];
243 // GetMiddlePoint(&inputMidPoint, &inputPoints[iInput-1], &inputPoints[iInput]);
244 }
245 }
246
247 strokeRatio = protoData->strokeRatios[iStroke];
248 if (strokeRatio < inputData->strokeRatios[iStroke])
249 {
250 strokeRatio = inputData->strokeRatios[iStroke];
251 }
252
253 wholeScore += FX_Mul(strokeScore, strokeRatio);
254 wholeWeight += strokeRatio;
255 }
256
257 wholeScore = FX_Div(wholeScore, wholeWeight * doubleWidth);
258 wholeScore /= 256;
259
260 if (proto->entry->correction != 0)
261 {
262 wholeScore = FX_Mul(wholeScore, FX32_ONE - proto->entry->correction)
263 + proto->entry->correction;
264 }
265
266 if (wholeScore < 0)
267 wholeScore = 0;
268 if (wholeScore >= FX32_ONE)
269 wholeScore = FX32_ONE;
270
271 numCompared++;
272 if (resultScores[numRanking - 1] < wholeScore)
273 {
274 resultScores[numRanking - 1] = wholeScore;
275 resultEntries[numRanking - 1] = (PRCPrototypeEntry *)proto->entry;
276 for (i = numRanking - 2; i >= 0; i--)
277 {
278 if (resultScores[i] < resultScores[i + 1])
279 {
280 fx32 tmpScore;
281 PRCPrototypeEntry *tmpEntry;
282 tmpScore = resultScores[i];
283 resultScores[i] = resultScores[i + 1];
284 resultScores[i + 1] = tmpScore;
285 tmpEntry = resultEntries[i];
286 resultEntries[i] = resultEntries[i + 1];
287 resultEntries[i + 1] = tmpEntry;
288 }
289 }
290 }
291 }
292 }
293 // Normalize the score
294
295 return numCompared;
296 }
297
298 /*===========================================================================*
299 Static Functions
300 *===========================================================================*/
301
302
303 /*---------------------------------------------------------------------------*
304 End of file
305 *---------------------------------------------------------------------------*/
306