Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

674 lines
18 KiB

#include "common.h"
#include "crane.h"
// Convert 0-360 angle to absolute angle from Positive X axis.
__inline int Angle2XAngle(int angle)
{
return angle <= 180 ? angle : 360 - angle;
}
// Convert 0-360 angle to absolute angle from Positive Y axis.
__inline int Angle2YAngle(int angle)
{
// Convert to angle from Y axis.
angle = (angle + 90) % 360;
return Angle2XAngle(angle);
}
// Find scaled perpendiculare distance from stroke (end points) to a point.
// Note that cStroke is the point number of the start of the stroke.
int FindPerpDist(int cStoke, int cPoint, short *pX, short *pY)
{
int dX, dY;
int away;
// Get delta X and delta Y of (end - start of stroke) for our calculations.
dX = pX[cStoke + 1] - pX[cStoke];
dY = pY[cStoke + 1] - pY[cStoke];
// If both dX and dY are 0, force an X distance of 1.
if (dX == 0 && dY == 0) {
dX = 1;
}
// First calculate the away offset.
away = pY[cPoint] * dX - pX[cPoint] * dY;
// Then normalize the offset.
away -= pY[cStoke] * dX - pX[cStoke] * dY;
// Finally normalize the scale.
away *= 1000;
away /= dX * dX + dY * dY;
return away;
}
// Build up a bounding rectangle from a list of bounding rectangles.
void
BuildBoundingBox(RECTS *pRectsOut, RECTS *pRectsList, int first, int last)
{
short x1, x2, y1, y2;
ASSERT (first <= last);
// Always grab the first rect
x1 = pRectsList[first].x1;
x2 = pRectsList[first].x2;
if (x1 <= x2) {
pRectsOut->x1 = x1;
pRectsOut->x2 = x2;
} else {
pRectsOut->x1 = x2;
pRectsOut->x2 = x1;
}
y1 = pRectsList[first].y1;
y2 = pRectsList[first].y2;
if (y1 <= y2) {
pRectsOut->y1 = y1;
pRectsOut->y2 = y2;
} else {
pRectsOut->y1 = y2;
pRectsOut->y2 = y1;
}
// Now add in any additional rects
for (++first ; first <= last; ++first) {
x1 = pRectsList[first].x1;
x2 = pRectsList[first].x2;
if (x1 <= x2) {
if (pRectsOut->x1 > x1) {
pRectsOut->x1 = x1;
}
if (pRectsOut->x2 < x2) {
pRectsOut->x2 = x2;
}
} else {
if (pRectsOut->x1 > x2) {
pRectsOut->x1 = x2;
}
if (pRectsOut->x2 < x1) {
pRectsOut->x2 = x1;
}
}
y1 = pRectsList[first].y1;
y2 = pRectsList[first].y2;
if (y1 <= y2) {
if (pRectsOut->y1 > y1) {
pRectsOut->y1 = y1;
}
if (pRectsOut->y2 < y2) {
pRectsOut->y2 = y2;
}
} else {
if (pRectsOut->y1 > y1) {
pRectsOut->y1 = y1;
}
if (pRectsOut->y2 < y2) {
pRectsOut->y2 = y2;
}
}
}
}
// Answer a question
// Check if the answer to a question on the sample is Greater.
void AnswerQuestion(
WORD questionType, // What type of question, delta X, delta Y current choices
WORD part1, // Question constant part 1
WORD part2, // Question constant part 2
SAMPLE_INFO *pSamples,
int cSamples)
{
int ii;
int deltaX, deltaY;
int cStrokes, cPoints;
short *pByPointsX, *pByPointsY;
END_POINTS *pendX, *pendY;
SAMPLE_INFO *pLimit;
RECTS rects;
cStrokes = pSamples->pSample->cstrk; // All samples have the same stroke count
cPoints = cStrokes * 2;
pLimit = pSamples + cSamples;
switch (questionType)
{
case questionX:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = (int) ((short *)(pSamples->pSample->apfeat[FEATURE_XPOS]->data))[part1];
}
break;
case questionY:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = (int) ((short *)(pSamples->pSample->apfeat[FEATURE_YPOS]->data))[part1];
}
break;
case questionXDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pSamples->iAnswer = (int) pByPointsX[part1] - (int) pByPointsX[part2];
}
break;
case questionYDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
pSamples->iAnswer = (int)pByPointsY[part1] - (int)pByPointsY[part2];
}
break;
case questionXAngle:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaX = (int)pByPointsX[part2] - (int)pByPointsX[part1];
deltaY = (int)pByPointsY[part2] - (int)pByPointsY[part1];
pSamples->iAnswer = Angle2XAngle(Arctan2(deltaY, deltaX));
}
break;
case questionYAngle:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaX = (int)pByPointsX[part2] - (int)pByPointsX[part1];
deltaY = (int)pByPointsY[part2] - (int)pByPointsY[part1];
pSamples->iAnswer = Angle2YAngle(Arctan2(deltaY, deltaX));
}
break;
case questionDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaX = (int)pByPointsX[part2] - (int)pByPointsX[part1];
deltaY = (int)pByPointsY[part2] - (int)pByPointsY[part1];
pSamples->iAnswer = Distance(deltaX, deltaY);
}
break;
case questionDakuTen:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = pSamples->pSample->fDakuten;
}
break;
case questionNetAngle:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = ((short *) (pSamples->pSample->apfeat[FEATURE_ANGLE_NET]->data))[part1];
}
break;
case questionCnsAngle :
for ( ; pSamples < pLimit; ++pSamples) {
int iAbsNetAngle, iAbsAngle;
// Get absolute value of net angle
iAbsNetAngle = ((SHORT *) (pSamples->pSample->apfeat[FEATURE_ANGLE_NET]->data))[part1];
if (iAbsNetAngle < 0) {
iAbsNetAngle = -iAbsNetAngle;
}
// Get absolute angle.
iAbsAngle = ((USHORT *) (pSamples->pSample->apfeat[FEATURE_ANGLE_ABS]->data))[part1];
// Answer is the difference
pSamples->iAnswer = iAbsAngle - iAbsNetAngle;
}
break;
case questionAbsAngle:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = ((USHORT *) (pSamples->pSample->apfeat[FEATURE_ANGLE_ABS]->data))[part1];
}
break;
case questionCSteps:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = ((BYTE *) (pSamples->pSample->apfeat[FEATURE_STEPS]->data))[part1];
}
break;
case questionCFeatures:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = ((BYTE *) (pSamples->pSample->apfeat[FEATURE_FEATURES]->data))[part1];
}
break;
case questionXPointsRight:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pSamples->iAnswer = 0;
for (ii = 0; ii < cPoints; ++ii)
{
if (pByPointsX[ii] > pByPointsX[part1])
{
++pSamples->iAnswer;
}
}
}
break;
case questionYPointsBelow:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
pSamples->iAnswer = 0;
for (ii = 0; ii < cPoints; ++ii)
{
if (pByPointsY[ii] > pByPointsY[part1])
{
++pSamples->iAnswer;
}
}
}
break;
case questionPerpDist:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer =
FindPerpDist(part1, part2,
((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data),
((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data));
}
break;
case questionSumXDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pSamples->iAnswer = 0;
for (ii = 0; ii < cPoints; ii += 2)
{
pSamples->iAnswer += (int) pByPointsX[ii + 1] - (int) pByPointsX[ii];
}
}
break;
case questionSumYDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
pSamples->iAnswer = 0;
for (ii = 0; ii < cPoints; ii += 2)
{
pSamples->iAnswer += (int) pByPointsY[ii + 1] - (int) pByPointsY[ii];
}
}
break;
case questionSumDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
pSamples->iAnswer = 0;
for (ii = 0; ii < cPoints; ii += 2)
{
deltaX = (int) pByPointsX[ii + 1] - (int) pByPointsX[ii];
deltaY = (int) pByPointsY[ii + 1] - (int) pByPointsY[ii];
pSamples->iAnswer += Distance(deltaX, deltaY);
}
}
break;
case questionSumNetAngle:
for ( ; pSamples < pLimit; ++pSamples)
{
short *pNetAngle;
pNetAngle = (short *) pSamples->pSample->apfeat[FEATURE_ANGLE_NET]->data;
pSamples->iAnswer = 0;
for (ii = 0; ii < cStrokes; ++ii)
{
pSamples->iAnswer += (int) pNetAngle[ii];
}
}
break;
case questionSumAbsAngle:
for ( ; pSamples < pLimit; ++pSamples)
{
WORD *pAbsAngle;
pAbsAngle = (WORD *) pSamples->pSample->apfeat[FEATURE_ANGLE_ABS]->data;
pSamples->iAnswer = 0;
for (ii = 0; ii < cStrokes; ++ii)
{
pSamples->iAnswer += (int)pAbsAngle[ii];
}
}
break;
case questionCompareXDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
deltaX = (int) pByPointsX[part1 + 1] - (int) pByPointsX[part1];
pSamples->iAnswer = (deltaX >= 0) ? deltaX : - deltaX;
deltaX = (int) pByPointsX[part2 + 1] - (int) pByPointsX[part2];
pSamples->iAnswer -= (deltaX >= 0) ? deltaX : - deltaX;
}
break;
case questionCompareYDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaY = (int) pByPointsY[part1 + 1] - (int) pByPointsY[part1];
pSamples->iAnswer = (deltaY >= 0) ? deltaY : - deltaY;
deltaY = (int) pByPointsY[part2 + 1] - (int) pByPointsY[part2];
pSamples->iAnswer -= (deltaY >= 0) ? deltaY : - deltaY;
}
break;
case questionCompareDelta:
for ( ; pSamples < pLimit; ++pSamples)
{
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaX = (int) pByPointsX[part1 + 1] - (int) pByPointsX[part1];
deltaY = (int) pByPointsY[part1 + 1] - (int) pByPointsY[part1];
pSamples->iAnswer = Distance(deltaX, deltaY);
deltaX = (int) pByPointsX[part2 + 1] - (int) pByPointsX[part2];
deltaY = (int) pByPointsY[part2 + 1] - (int) pByPointsY[part2];
pSamples->iAnswer -= Distance(deltaX, deltaY);
}
break;
case questionCompareAngle:
for ( ; pSamples < pLimit; ++pSamples) {
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaX = (int) pByPointsX[part1 + 1] - (int) pByPointsX[part1];
deltaY = (int) pByPointsY[part1 + 1] - (int) pByPointsY[part1];
pSamples->iAnswer = Arctan2(deltaY, deltaX);
deltaX = (int) pByPointsX[part1 + 1] - (int) pByPointsX[part1];
deltaY = (int) pByPointsY[part1 + 1] - (int) pByPointsY[part1];
pSamples->iAnswer -= Arctan2(deltaY, deltaX);
if (pSamples->iAnswer < -180)
{
pSamples->iAnswer += 180;
}
else if (pSamples->iAnswer > 180)
{
pSamples->iAnswer -= 180;
}
}
break;
case questionPointsInBBox:
for ( ; pSamples < pLimit; ++pSamples)
{
int lowerX, upperX, lowerY, upperY;
pByPointsX = ((short *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pByPointsY = ((short *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
if (pByPointsX[part1] <= pByPointsX[part2])
{
lowerX = pByPointsX[part1];
upperX = pByPointsX[part2];
}
else
{
lowerX = pByPointsX[part2];
upperX = pByPointsX[part1];
}
if (pByPointsY[part1] <= pByPointsY[part2])
{
lowerY = pByPointsY[part1];
upperY = pByPointsY[part2];
}
else
{
lowerY = pByPointsY[part2];
upperY = pByPointsY[part1];
}
pSamples->iAnswer = 0;
for (ii = 0; ii < cPoints; ++ii)
{
if ((lowerX <= pByPointsX[ii]) &&
(pByPointsX[ii] <= upperX) &&
(lowerY <= pByPointsY[ii]) &&
(pByPointsY[ii] <= upperY))
{
++pSamples->iAnswer;
}
}
}
break;
case questionCharLeft:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = pSamples->pSample->drcs.x;
}
break;
case questionCharTop:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = pSamples->pSample->drcs.y;
}
break;
case questionCharWidth:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = pSamples->pSample->drcs.w;
}
break;
case questionCharHeight:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = pSamples->pSample->drcs.h;
}
break;
case questionCharDiagonal:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = Distance(pSamples->pSample->drcs.w, pSamples->pSample->drcs.h);
}
break;
case questionCharTheta:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = Arctan2(pSamples->pSample->drcs.h, pSamples->pSample->drcs.w);
}
break;
case questionStrokeLeft:
for ( ; pSamples < pLimit; ++pSamples)
{
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
pSamples->iAnswer = rects.x1;
}
break;
case questionStrokeTop:
for ( ; pSamples < pLimit; ++pSamples)
{
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
pSamples->iAnswer = rects.y1;
}
break;
case questionStrokeWidth:
for ( ; pSamples < pLimit; ++pSamples)
{
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
pSamples->iAnswer = rects.x2 - rects.x1;
}
break;
case questionStrokeHeight:
for ( ; pSamples < pLimit; ++pSamples)
{
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
pSamples->iAnswer = rects.y2 - rects.y1;
}
break;
case questionStrokeDiagonal:
for ( ; pSamples < pLimit; ++pSamples)
{
short w, h;
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
w = rects.x2 - rects.x1;
h = rects.y2 - rects.y1;
pSamples->iAnswer = Distance(w, h);
}
break;
case questionStrokeTheta:
for ( ; pSamples < pLimit; ++pSamples)
{
short w, h;
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
w = rects.x2 - rects.x1;
h = rects.y2 - rects.y1;
pSamples->iAnswer = Arctan2(h, w);
}
break;
case questionStrokeRight:
for ( ; pSamples < pLimit; ++pSamples)
{
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
pSamples->iAnswer = rects.x2;
}
break;
case questionStrokeBottom:
for ( ; pSamples < pLimit; ++pSamples)
{
BuildBoundingBox(&rects,
(RECTS *)(pSamples->pSample->apfeat[FEATURE_STROKE_BBOX]->data), part1, part2
);
pSamples->iAnswer = rects.y2;
}
break;
case questionStrokeLength:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = ((USHORT *)(pSamples->pSample->apfeat[FEATURE_LENGTH]->data))[part1];
}
break;
case questionStrokeCurve:
for ( ; pSamples < pLimit; ++pSamples)
{
pendX = ((END_POINTS *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pendY = ((END_POINTS *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
deltaX = pendX[part1].end - pendX[part1].start;
deltaY = pendY[part1].end - pendY[part1].start;
pSamples->iAnswer = ((USHORT *)(pSamples->pSample->apfeat[FEATURE_LENGTH]->data))[part1] - Distance(deltaX, deltaY);
}
break;
case questionCharLength:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = 0;
for (ii = 0; ii < cStrokes; ii++)
pSamples->iAnswer += ((USHORT *)(pSamples->pSample->apfeat[FEATURE_LENGTH]->data))[ii];
}
break;
case questionCharCurve:
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = 0;
pendX = ((END_POINTS *) pSamples->pSample->apfeat[FEATURE_XPOS]->data);
pendY = ((END_POINTS *) pSamples->pSample->apfeat[FEATURE_YPOS]->data);
for (ii = 0; ii < cStrokes; ii++)
{
deltaX = pendX[ii].end - pendX[ii].start;
deltaY = pendY[ii].end - pendY[ii].start;
pSamples->iAnswer += ((USHORT *)(pSamples->pSample->apfeat[FEATURE_LENGTH]->data))[ii] - Distance(deltaX, deltaY);
}
}
break;
case questionAltList :
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = MAX_RECOG_ALTS * 2;
for (ii = 0; ii < MAX_RECOG_ALTS; ++ii) {
if (pSamples->pSample->awchAlts[ii] == (wchar_t)part1) {
pSamples->iAnswer = ii;
break;
}
}
}
break;
default:
ASSERT(FALSE); // Should never get here.
for ( ; pSamples < pLimit; ++pSamples)
{
pSamples->iAnswer = 0;
}
break;
}
}