|
|
#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; } }
|