classify/intproto.cpp

Go to the documentation of this file.
00001 
00019 /* =================
00020  Include Files and Type Defines
00021  ==================== */
00022 #include "intproto.h"
00023 #include "picofeat.h"
00024 #include "debug.h"
00025 #include "mfoutline.h"
00026 #include "emalloc.h"
00027 #include "const.h"
00028 #include "ndminx.h"
00029 #include "adaptmatch.h"
00030 
00031 //extern GetPicoFeatureLength();
00032 
00033 #include <math.h>
00034 #include <stdio.h>
00035 #include <assert.h>
00036 
00037 /* match debug display constants*/
00038 #define DISPLAY_OFFSET  (0.5  * INT_CHAR_NORM_RANGE)
00039 #define PROTO_PRUNER_SCALE  (4.0)
00040 
00041 #define INT_DESCENDER (0.0  * INT_CHAR_NORM_RANGE - DISPLAY_OFFSET)
00042 #define INT_BASELINE  (0.25 * INT_CHAR_NORM_RANGE - DISPLAY_OFFSET)
00043 #define INT_XHEIGHT (0.75 * INT_CHAR_NORM_RANGE - DISPLAY_OFFSET)
00044 #define INT_CAPHEIGHT (1.0  * INT_CHAR_NORM_RANGE - DISPLAY_OFFSET)
00045 
00046 #define INT_XCENTER (0.5  * INT_CHAR_NORM_RANGE - DISPLAY_OFFSET)
00047 #define INT_YCENTER (0.5  * INT_CHAR_NORM_RANGE - DISPLAY_OFFSET)
00048 #define INT_XRADIUS (0.2  * INT_CHAR_NORM_RANGE)
00049 #define INT_YRADIUS (0.2  * INT_CHAR_NORM_RANGE)
00050 #define INT_MIN_X (- DISPLAY_OFFSET)
00051 #define INT_MIN_Y (- DISPLAY_OFFSET)
00052 #define INT_MAX_X (  DISPLAY_OFFSET)
00053 #define INT_MAX_Y (  DISPLAY_OFFSET)
00054 #define DOUBLE_OFFSET 0.095
00055 
00058 #define HV_TOLERANCE  (0.0025)
00059 
00064 typedef enum
00065 {
00066    StartSwitch,
00067    EndSwitch,
00068    LastSwitch
00069 } SWITCH_TYPE;
00070 
00071 #define MAX_NUM_SWITCHES  3
00072 
00077 typedef struct
00078 {
00079   SWITCH_TYPE Type;
00080   INT8 X, Y;
00081   INT16 YInit;
00082   INT16 Delta;
00083 } FILL_SWITCH;
00084 
00089 typedef struct
00090 {
00091   UINT8 NextSwitch;
00092   UINT8 AngleStart, AngleEnd;
00093   INT8 X;
00094   INT16 YStart, YEnd;
00095   INT16 StartDelta, EndDelta;
00096   FILL_SWITCH Switch[MAX_NUM_SWITCHES];
00097 } TABLE_FILLER;
00098 
00103 typedef struct
00104 {
00105   INT8 X;
00106   INT8 YStart, YEnd;
00107   UINT8 AngleStart, AngleEnd;
00108 } FILL_SPEC;
00109 
00110 /* =================
00111  Macros
00112  ==================== */
00114 #define CircularIncrement(i,r)  (((i) < (r) - 1)?((i)++):((i) = 0))
00115 
00117 #define MapParam(P,O,N)   (floor (((P) + (O)) * (N)))
00118 
00119 /*---------------------------------------------------------------------------
00120             Private Function Prototypes
00121 ----------------------------------------------------------------------------*/
00122 FLOAT32 BucketStart(int Bucket, FLOAT32 Offset, int NumBuckets);
00123 
00124 FLOAT32 BucketEnd(int Bucket, FLOAT32 Offset, int NumBuckets);
00125 
00126 void DoFill(FILL_SPEC *FillSpec,
00127             CLASS_PRUNER Pruner,
00128             register UINT32 ClassMask,
00129             register UINT32 ClassCount,
00130             register UINT32 WordIndex);
00131 
00132 BOOL8 FillerDone(TABLE_FILLER *Filler);
00133 
00134 void FillPPCircularBits (UINT32
00135 ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR],
00136 int Bit, FLOAT32 Center, FLOAT32 Spread);
00137 
00138 void FillPPLinearBits (UINT32 ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR],
00139 int Bit, FLOAT32 Center, FLOAT32 Spread);
00140 
00141 #ifndef GRAPHICS_DISABLED
00142 CLASS_ID GetClassToDebug(const char *Prompt);
00143 #endif
00144 
00145 void GetCPPadsForLevel(int Level,
00146                        FLOAT32 *EndPad,
00147                        FLOAT32 *SidePad,
00148                        FLOAT32 *AnglePad);
00149 
00150 C_COL GetMatchColorFor(FLOAT32 Evidence);
00151 
00152 void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill);
00153 
00154 void InitTableFiller(FLOAT32 EndPad,
00155                      FLOAT32 SidePad,
00156                      FLOAT32 AnglePad,
00157                      PROTO Proto,
00158                      TABLE_FILLER *Filler);
00159 
00160 #ifndef GRAPHICS_DISABLED
00161 void RenderIntFeature(void *window, INT_FEATURE Feature, C_COL Color);
00162 
00163 void RenderIntProto(void *window,
00164                     INT_CLASS Class,
00165                     PROTO_ID ProtoId,
00166                     C_COL Color);
00167 #endif
00168 
00169 int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id);
00170 
00171 /*
00172 #if defined(__STDC__) || defined(__cplusplus)
00173 # define _ARGS(s) s
00174 #else
00175 # define _ARGS(s) ()
00176 #endif*/
00177 
00178 /* /users/danj/wiseowl/src/danj/microfeatures/intproto.c
00179 FLOAT32 BucketStart
00180   _ARGS((int Bucket,
00181   FLOAT32 Offset,
00182   int NumBuckets));
00183 
00184 FLOAT32 BucketEnd
00185   _ARGS((int Bucket,
00186   FLOAT32 Offset,
00187   int NumBuckets));
00188 
00189 void DoFill
00190   _ARGS((FILL_SPEC *FillSpec,
00191   CLASS_PRUNER Pruner,
00192   UINT32 ClassMask,
00193   UINT32 ClassCount,
00194   UINT32 WordIndex));
00195 
00196 BOOL8 FillerDone
00197   _ARGS((TABLE_FILLER *Filler));
00198 
00199 void FillPPCircularBits
00200   _ARGS((UINT32 ParamTable [NUM_PP_BUCKETS ][WERDS_PER_PP_VECTOR ],
00201   int Bit,
00202   FLOAT32 Center,
00203   FLOAT32 Spread));
00204 
00205 void FillPPLinearBits
00206   _ARGS((UINT32 ParamTable [NUM_PP_BUCKETS ][WERDS_PER_PP_VECTOR ],
00207   int Bit,
00208   FLOAT32 Center,
00209   FLOAT32 Spread));
00210 
00211 void GetCPPadsForLevel
00212   _ARGS((int Level,
00213   FLOAT32 *EndPad,
00214   FLOAT32 *SidePad,
00215   FLOAT32 *AnglePad));
00216 
00217 C_COL GetMatchColorFor
00218   _ARGS((FLOAT32 Evidence));
00219 
00220 void GetNextFill
00221   _ARGS((TABLE_FILLER *Filler,
00222   FILL_SPEC *Fill));
00223 
00224 void InitTableFiller
00225   _ARGS((FLOAT32 EndPad,
00226   FLOAT32 SidePad,
00227   FLOAT32 AnglePad,
00228   PROTO Proto,
00229   TABLE_FILLER *Filler));
00230 
00231 void RenderIntFeature
00232   _ARGS((SHAPE_LIST ShapeList,
00233   INT_FEATURE Feature,
00234   char *Color));
00235 
00236 void RenderIntProto
00237   _ARGS((SHAPE_LIST ShapeList,
00238   INT_CLASS Class,
00239   PROTO_ID ProtoId,
00240   char *Color));
00241 
00242 int TruncateParam
00243   _ARGS((FLOAT32 Param,
00244   int Min,
00245   int Max,
00246   char *Id));
00247 
00248 #undef _ARGS
00249 */
00250 
00251 /* =================
00252         Global Data Definitions and Declarations
00253  ==================== */
00256 /* control knobs */
00257 make_int_const (NumCPLevels, 3, MakeNumCPLevels);
00258 make_float_const (CPAnglePadLoose, 45.0, MakeCPAnglePadLoose);
00259 make_float_const (CPAnglePadMedium, 20.0, MakeCPAnglePadMedium);
00260 make_float_const (CPAnglePadTight, 10.0, MakeCPAnglePadTight);
00261 make_float_const (CPEndPadLoose, 0.5, MakeCPEndPadLoose);
00262 make_float_const (CPEndPadMedium, 0.5, MakeCPEndPadMedium);
00263 make_float_const (CPEndPadTight, 0.5, MakeCPEndPadTight);
00264 make_float_const (CPSidePadLoose, 2.5, MakeCPSidePadLoose);
00265 make_float_const (CPSidePadMedium, 1.2, MakeCPSidePadMedium);
00266 make_float_const (CPSidePadTight, 0.6, MakeCPSidePadTight);
00267 make_float_const (PPAnglePad, 45.0, MakePPAnglePad);
00268 make_float_const (PPEndPad, 0.5, MakePPEndPad);
00269 make_float_const (PPSidePad, 2.5, MakePPSidePad);
00273 void *IntMatchWindow = NULL;
00274 //extern int LearningDebugLevel;
00275 
00276 /* =================
00277  Public Code
00278  ==================== */
00289 int AddIntClass(INT_TEMPLATES Templates, CLASS_ID ClassId, INT_CLASS Class) { 
00290   int Index;
00291   int Pruner;
00292   UINT32 *Word;
00293 
00294   assert (LegalClassId (ClassId));
00295   assert (UnusedClassIdIn (Templates, ClassId));
00296 
00297   Index = NumClassesIn (Templates);
00298   IndexForClassId (Templates, ClassId) = Index;
00299   ClassIdForIndex (Templates, Index) = ClassId;
00300 
00301   NumClassesIn (Templates)++;
00302   ClassForIndex (Templates, Index) = Class;
00303 
00304   if (NumClassesIn (Templates) > MaxNumClassesIn (Templates)) {
00305     Pruner = NumClassPrunersIn (Templates);
00306     NumClassPrunersIn (Templates)++;
00307     Templates->ClassPruner[Pruner] =
00308       (CLASS_PRUNER) Emalloc (sizeof (CLASS_PRUNER_STRUCT));
00309 
00310     for (Word = (UINT32 *) (Templates->ClassPruner[Pruner]);
00311       Word < (UINT32 *) (Templates->ClassPruner[Pruner]) + WERDS_PER_CP;
00312       *Word++ = 0);
00313   }
00314 
00315   return (Index);
00316 
00317 }                                /* AddIntClass */
00318 
00319 
00320 /* =============================== */
00329 int AddIntConfig(INT_CLASS Class) { 
00330   int Index;
00331 
00332   assert (NumIntConfigsIn (Class) < MAX_NUM_CONFIGS);
00333 
00334   Index = NumIntConfigsIn (Class);
00335   NumIntConfigsIn (Class)++;
00336   LengthForConfigId (Class, Index) = 0;
00337   return (Index);
00338 }                                /* AddIntConfig */
00339 
00340 
00341 /* =============================== */
00350 int AddIntProto(INT_CLASS Class) { 
00351   int Index;
00352   int ProtoSetId;
00353   PROTO_SET ProtoSet;
00354   INT_PROTO Proto;
00355   register UINT32 *Word;
00356 
00357   if (NumIntProtosIn (Class) >= MAX_NUM_PROTOS)
00358     return (NO_PROTO);
00359 
00360   Index = NumIntProtosIn (Class);
00361   NumIntProtosIn (Class)++;
00362 
00363   if (NumIntProtosIn (Class) > MaxNumIntProtosIn (Class)) {
00364     ProtoSetId = NumProtoSetsIn (Class);
00365     NumProtoSetsIn (Class)++;
00366 
00367     ProtoSet = (PROTO_SET) Emalloc (sizeof (PROTO_SET_STRUCT));
00368     ProtoSetIn (Class, ProtoSetId) = ProtoSet;
00369     for (Word = (UINT32 *) (ProtoPrunerFor (ProtoSet));
00370       Word < (UINT32 *) (ProtoPrunerFor (ProtoSet)) + WERDS_PER_PP;
00371       *Word++ = 0);
00372 
00373     /* reallocate space for the proto lengths and install in class */
00374     Class->ProtoLengths = (UINT8 *) Erealloc (Class->ProtoLengths,
00375       MaxNumIntProtosIn (Class) *
00376       sizeof (UINT8));
00377   }
00378 
00379   /* initialize proto so its length is zero and it isn't in any configs */
00380   LengthForProtoId (Class, Index) = 0;
00381   Proto = ProtoForProtoId (Class, Index);
00382   for (Word = Proto->Configs;
00383     Word < Proto->Configs + WERDS_PER_CONFIG_VEC; *Word++ = 0);
00384 
00385   return (Index);
00386 
00387 }                                /* AddIntProto */
00388 
00389 
00390 /* =============================== */
00403 void
00404 AddProtoToClassPruner (PROTO Proto, CLASS_ID ClassId, INT_TEMPLATES Templates)
00405 #define MAX_LEVEL     2
00406 {
00407   CLASS_PRUNER Pruner;
00408   UINT32 ClassMask;
00409   UINT32 ClassCount;
00410   CLASS_INDEX ClassIndex;
00411   UINT32 WordIndex;
00412   int Level;
00413   FLOAT32 EndPad, SidePad, AnglePad;
00414   TABLE_FILLER TableFiller;
00415   FILL_SPEC FillSpec;
00416 
00417   ClassIndex = IndexForClassId (Templates, ClassId);
00418   Pruner = CPrunerFor (Templates, ClassIndex);
00419   WordIndex = CPrunerWordIndexFor (ClassIndex);
00420   ClassMask = CPrunerMaskFor (MAX_LEVEL, ClassIndex);
00421 
00422   for (Level = NumCPLevels - 1; Level >= 0; Level--) {
00423     GetCPPadsForLevel(Level, &EndPad, &SidePad, &AnglePad);
00424     ClassCount = CPrunerMaskFor (Level, ClassIndex);
00425     InitTableFiller(EndPad, SidePad, AnglePad, Proto, &TableFiller);
00426 
00427     while (!FillerDone (&TableFiller)) {
00428       GetNextFill(&TableFiller, &FillSpec);
00429       DoFill(&FillSpec, Pruner, ClassMask, ClassCount, WordIndex);
00430     }
00431   }
00432 }                                /* AddProtoToClassPruner */
00433 
00434 
00435 /* =============================== */
00447 void AddProtoToProtoPruner(PROTO Proto, int ProtoId, INT_CLASS Class) { 
00448   FLOAT32 Angle, X, Y, Length;
00449   FLOAT32 Pad;
00450   int Index;
00451   PROTO_SET ProtoSet;
00452 
00453   if (ProtoId >= NumIntProtosIn (Class))
00454     cprintf ("AddProtoToProtoPruner:assert failed: %d < %d",
00455       ProtoId, NumIntProtosIn (Class));
00456   assert (ProtoId < NumIntProtosIn (Class));
00457 
00458   Index = IndexForProto (ProtoId);
00459   ProtoSet = ProtoSetIn (Class, SetForProto (ProtoId));
00460 
00461   Angle = ProtoAngle (Proto);
00462   FillPPCircularBits (ProtoSet->ProtoPruner[PRUNER_ANGLE], Index,
00463     Angle + ANGLE_SHIFT, PPAnglePad / 360.0);
00464 
00465   Angle *= 2.0 * PI;
00466   Length = ProtoLength (Proto);
00467 
00468   X = ProtoX (Proto) + X_SHIFT;
00469   Pad = max (fabs (cos (Angle)) * (Length / 2.0 +
00470     PPEndPad * GetPicoFeatureLength ()),
00471     fabs (sin (Angle)) * (PPSidePad * GetPicoFeatureLength ()));
00472 
00473   FillPPLinearBits (ProtoSet->ProtoPruner[PRUNER_X], Index, X, Pad);
00474 
00475   Y = ProtoY (Proto) + Y_SHIFT;
00476   Pad = max (fabs (sin (Angle)) * (Length / 2.0 +
00477     PPEndPad * GetPicoFeatureLength ()),
00478     fabs (cos (Angle)) * (PPSidePad * GetPicoFeatureLength ()));
00479 
00480   FillPPLinearBits (ProtoSet->ProtoPruner[PRUNER_Y], Index, Y, Pad);
00481 
00482 }                                /* AddProtoToProtoPruner */
00483 
00484 
00485 /* =============================== */
00501 int BucketFor(FLOAT32 Param, FLOAT32 Offset, int NumBuckets) { 
00502   int Bucket;
00503 
00504   Bucket = (int) MapParam (Param, Offset, NumBuckets);
00505   if (Bucket < 0)
00506     Bucket = 0;
00507   else if (Bucket >= NumBuckets)
00508     Bucket = NumBuckets - 1;
00509   return (Bucket);
00510 
00511 }                                /* BucketFor */
00512 
00513 
00514 /* =============================== */
00529 int CircBucketFor(FLOAT32 Param, FLOAT32 Offset, int NumBuckets) { 
00530   int Bucket;
00531 
00532   Bucket = (int) MapParam (Param, Offset, NumBuckets);
00533   if (Bucket < 0)
00534     Bucket += NumBuckets;
00535   else if (Bucket >= NumBuckets)
00536     Bucket -= NumBuckets;
00537   return (Bucket);
00538 
00539 }                                /* CircBucketFor */
00540 
00541 
00542 /* =============================== */
00554 #ifndef GRAPHICS_DISABLED
00555 void UpdateMatchDisplay() { 
00556   if (IntMatchWindow != NULL)
00557     c_make_current(IntMatchWindow);
00558 }                                /* ClearMatchDisplay */
00559 #endif
00560 
00561 /* =============================== */
00578 void ConvertConfig(BIT_VECTOR Config, int ConfigId, INT_CLASS Class) { 
00579   int ProtoId;
00580   INT_PROTO Proto;
00581   int TotalLength;
00582 
00583   for (ProtoId = 0, TotalLength = 0;
00584     ProtoId < NumIntProtosIn (Class); ProtoId++)
00585   if (test_bit (Config, ProtoId)) {
00586     Proto = ProtoForProtoId (Class, ProtoId);
00587     SET_BIT (Proto->Configs, ConfigId);
00588     TotalLength += LengthForProtoId (Class, ProtoId);
00589   }
00590   LengthForConfigId (Class, ConfigId) = TotalLength;
00591 }                                /* ConvertConfig */
00592 
00593 
00594 /* =============================== */
00605 void ConvertProto(PROTO Proto, int ProtoId, INT_CLASS Class) { 
00606   INT_PROTO P;
00607   FLOAT32 Param;
00608 
00609   assert (ProtoId < NumIntProtosIn (Class));
00610 
00611   P = ProtoForProtoId (Class, ProtoId);
00612 
00613   Param = CoefficientA (Proto) * 128;
00614   P->A = TruncateParam (Param, -128, 127, NULL);
00615 
00616   Param = -CoefficientB (Proto) * 256;
00617   P->B = TruncateParam (Param, 0, 255, NULL);
00618 
00619   Param = CoefficientC (Proto) * 128;
00620   P->C = TruncateParam (Param, -128, 127, NULL);
00621 
00622   Param = ProtoAngle (Proto) * 256;
00623   if (Param < 0 || Param >= 256)
00624     P->Angle = 0;
00625   else
00626     P->Angle = (UINT8) Param;
00627 
00628   /* round proto length to nearest integer number of pico-features */
00629   Param = (ProtoLength (Proto) / GetPicoFeatureLength ()) + 0.5;
00630   LengthForProtoId (Class, ProtoId) = TruncateParam (Param, 1, 255, NULL);
00631   if (LearningDebugLevel >= 2)
00632     cprintf ("Converted ffeat to (A=%d,B=%d,C=%d,L=%d)",
00633       P->A, P->B, P->C, LengthForProtoId (Class, ProtoId));
00634 }                                /* ConvertProto */
00635 
00636 
00637 /* =============================== */
00646 INT_TEMPLATES CreateIntTemplates(CLASSES FloatProtos) { 
00647   INT_TEMPLATES IntTemplates;
00648   CLASS_TYPE FClass;
00649   INT_CLASS IClass;
00650   int ClassId;
00651   int ProtoId;
00652   int ConfigId;
00653 
00654   IntTemplates = NewIntTemplates ();
00655 
00656   for (ClassId = 0; ClassId < NUMBER_OF_CLASSES; ClassId++) {
00657     FClass = &(FloatProtos[ClassId]);
00658     if (NumProtosIn (FClass) > 0) {
00659       assert (UnusedClassIdIn (IntTemplates, ClassId));
00660 
00661       IClass = NewIntClass (NumProtosIn (FClass), NumConfigsIn (FClass));
00662       AddIntClass(IntTemplates, ClassId, IClass);
00663 
00664       for (ProtoId = 0; ProtoId < NumProtosIn (FClass); ProtoId++) {
00665         AddIntProto(IClass);
00666         ConvertProto (ProtoIn (FClass, ProtoId), ProtoId, IClass);
00667         AddProtoToProtoPruner (ProtoIn (FClass, ProtoId), ProtoId,
00668           IClass);
00669         AddProtoToClassPruner (ProtoIn (FClass, ProtoId), ClassId,
00670           IntTemplates);
00671       }
00672 
00673       for (ConfigId = 0; ConfigId < NumConfigsIn (FClass); ConfigId++) {
00674         AddIntConfig(IClass);
00675         ConvertConfig (ConfigIn (FClass, ConfigId), ConfigId, IClass);
00676       }
00677     }
00678   }
00679   return (IntTemplates);
00680 }                                /* CreateIntTemplates */
00681 
00682 
00683 /* =============================== */
00694 #ifndef GRAPHICS_DISABLED
00695 void DisplayIntFeature(INT_FEATURE Feature, FLOAT32 Evidence) { 
00696   C_COL Color;
00697 
00698   Color = GetMatchColorFor (Evidence);
00699   RenderIntFeature(IntMatchWindow, Feature, Color);
00700 }                                /* DisplayIntFeature */
00701 
00702 
00703 /* =============================== */
00715 void DisplayIntProto(INT_CLASS Class, PROTO_ID ProtoId, FLOAT32 Evidence) { 
00716   C_COL Color;
00717 
00718   Color = GetMatchColorFor (Evidence);
00719   RenderIntProto(IntMatchWindow, Class, ProtoId, Color);
00720 
00721 }                                /* DisplayIntProto */
00722 #endif
00723 
00724 /* =============================== */
00733 void InitIntProtoVars() { 
00734   MakeNumCPLevels();
00735   MakeCPAnglePadLoose();
00736   MakeCPAnglePadMedium();
00737   MakeCPAnglePadTight();
00738   MakeCPEndPadLoose();
00739   MakeCPEndPadMedium();
00740   MakeCPEndPadTight();
00741   MakeCPSidePadLoose();
00742   MakeCPSidePadMedium();
00743   MakeCPSidePadTight();
00744   MakePPAnglePad();
00745   MakePPEndPad();
00746   MakePPSidePad();
00747 }                                /* InitIntProtoVars */
00748 
00749 
00750 /* =============================== */
00763 INT_CLASS NewIntClass(int MaxNumProtos, int MaxNumConfigs) { 
00764   INT_CLASS Class;
00765   PROTO_SET ProtoSet;
00766   int i;
00767   register UINT32 *Word;
00768 
00769   assert (MaxNumConfigs <= MAX_NUM_CONFIGS);
00770 
00771   Class = (INT_CLASS) Emalloc (sizeof (INT_CLASS_STRUCT));
00772   NumProtoSetsIn (Class) = ((MaxNumProtos + PROTOS_PER_PROTO_SET - 1) /
00773     PROTOS_PER_PROTO_SET);
00774 
00775   assert (NumProtoSetsIn (Class) <= MAX_NUM_PROTO_SETS);
00776 
00777   NumIntProtosIn (Class) = 0;
00778   NumIntConfigsIn (Class) = 0;
00779 
00780   for (i = 0; i < NumProtoSetsIn (Class); i++) {
00781     /* allocate space for a proto set, install in class, and initialize */
00782     ProtoSet = (PROTO_SET) Emalloc (sizeof (PROTO_SET_STRUCT));
00783     ProtoSetIn (Class, i) = ProtoSet;
00784     for (Word = (UINT32 *) (ProtoPrunerFor (ProtoSet));
00785       Word < (UINT32 *) (ProtoPrunerFor (ProtoSet)) + WERDS_PER_PP;
00786       *Word++ = 0);
00787 
00788     /* allocate space for the proto lengths and install in class */
00789   }
00790   Class->ProtoLengths = (UINT8 *) Emalloc (MaxNumIntProtosIn (Class) *
00791     sizeof (UINT8));
00792 
00793   return (Class);
00794 
00795 }                                /* NewIntClass */
00796 
00797 
00798 /* =============================== */
00802 void free_int_class(
00803                     INT_CLASS int_class) {  /*class to free */
00804   int i;
00805 
00806   for (i = 0; i < NumProtoSetsIn (int_class); i++) {
00807     Efree (ProtoSetIn (int_class, i));
00808   }
00809   Efree (int_class->ProtoLengths);
00810   Efree(int_class);
00811 }
00812 
00813 
00814 /* =============================== */
00823 INT_TEMPLATES NewIntTemplates() { 
00824   INT_TEMPLATES T;
00825   int i;
00826 
00827   T = (INT_TEMPLATES) Emalloc (sizeof (INT_TEMPLATES_STRUCT));
00828   NumClassesIn (T) = 0;
00829   NumClassPrunersIn (T) = 0;
00830 
00831   /* initialize mapping tables */
00832   for (i = 0; i <= MAX_CLASS_ID; i++)
00833     IndexForClassId (T, i) = ILLEGAL_CLASS;
00834   for (i = 0; i < MAX_NUM_CLASSES; i++)
00835     ClassIdForIndex (T, i) = NO_CLASS;
00836 
00837   return (T);
00838 
00839 }                                /* NewIntTemplates */
00840 
00841 
00842 /* =============================== */
00846 void free_int_templates(INT_TEMPLATES templates) { 
00847   int i;
00848 
00849   for (i = 0; i < NumClassesIn (templates); i++)
00850     free_int_class (ClassForIndex (templates, i));
00851   for (i = 0; i < NumClassPrunersIn (templates); i++)
00852     Efree (templates->ClassPruner[i]);
00853   Efree(templates);
00854 }
00855 
00856 
00857 /* =============================== */
00870 INT_TEMPLATES ReadIntTemplates(FILE *File, BOOL8 swap) { 
00871   int i, j, x, y, z;
00872   int nread;
00873   INT_TEMPLATES Templates;
00874   CLASS_PRUNER Pruner;
00875   INT_CLASS Class;
00876   UINT8 *Lengths;
00877   PROTO_SET ProtoSet;
00878 
00879   /* first read the high level template struct */
00880   Templates = NewIntTemplates ();
00881   // Read Templates in parts for 64 bit compatibility.
00882   if (fread(&Templates->NumClasses, sizeof(int), 1, File) != 1 ||
00883       fread(&Templates->NumClassPruners, sizeof(int), 1, File) != 1)
00884     cprintf ("Bad read of inttemp!\n");
00885   for (i = 0; i <= MAX_CLASS_ID; ++i) {
00886     if (fread(&Templates->IndexFor[i], sizeof(CLASS_INDEX), 1, File) != 1)
00887       cprintf("Bad read of inttemp!\n");
00888   }
00889   for (i = 0; i < MAX_NUM_CLASSES; ++i) {
00890     if (fread(&Templates->ClassIdFor[i], sizeof(CLASS_ID), 1, File) != 1)
00891       cprintf("Bad read of inttemp!\n");
00892   }
00893   for (i = 0; i < MAX_NUM_CLASSES + MAX_NUM_CLASS_PRUNERS; ++i) {
00894     int junk;
00895     if (fread(&junk, sizeof(junk), 1, File) != 1)
00896       cprintf("Bad read of inttemp!\n");
00897   }
00898   // Swap status is determined automatically.
00899   swap = Templates->NumClassPruners < 0 ||
00900          Templates->NumClassPruners > MAX_NUM_CLASS_PRUNERS;
00901   if (swap) {
00902     reverse32 (&Templates->NumClassPruners);
00903     reverse32 (&Templates->NumClasses);
00904     for (i = 0; i < MAX_CLASS_ID + 1; i++)
00905       reverse16 (&Templates->IndexFor[i]);
00906   }
00907 
00908   /* then read in the class pruners */
00909   for (i = 0; i < NumClassPrunersIn (Templates); i++) {
00910     Pruner = (CLASS_PRUNER) Emalloc (sizeof (CLASS_PRUNER_STRUCT));
00911     if ((nread =
00912       fread ((char *) Pruner, 1, sizeof (CLASS_PRUNER_STRUCT),
00913       File)) != sizeof (CLASS_PRUNER_STRUCT))
00914       cprintf ("Bad read of inttemp!\n");
00915     if (swap) {
00916       for (j = 0; j < NUM_CP_BUCKETS; j++) {
00917         for (x = 0; x < NUM_CP_BUCKETS; x++) {
00918           for (y = 0; y < NUM_CP_BUCKETS; y++) {
00919             for (z = 0; z < WERDS_PER_CP_VECTOR; z++) {
00920               reverse32 (&Pruner[j][x][y][z]);
00921             }
00922           }
00923         }
00924       }
00925     }
00926     Templates->ClassPruner[i] = Pruner;
00927   }
00928 
00929   /* then read in each class */
00930   for (i = 0; i < NumClassesIn (Templates); i++) {
00931     /* first read in the high level struct for the class */
00932     Class = (INT_CLASS) Emalloc (sizeof (INT_CLASS_STRUCT));
00933     if (fread(&Class->NumProtos, sizeof(Class->NumProtos), 1, File) != 1 ||
00934         fread(&Class->NumProtoSets, sizeof(Class->NumProtoSets), 1, File) != 1 ||
00935         fread(&Class->NumConfigs, sizeof(Class->NumConfigs), 1, File) != 1)
00936       cprintf ("Bad read of inttemp!\n");
00937     for (j = 0; j <= MAX_NUM_PROTO_SETS; ++j) {
00938       int junk;
00939       if (fread(&junk, sizeof(junk), 1, File) != 1)
00940         cprintf ("Bad read of inttemp!\n");
00941     }
00942     for (j = 0; j < MAX_NUM_CONFIGS; ++j) {
00943       if (fread(&Class->ConfigLengths[j], sizeof(UINT16), 1, File) != 1)
00944         cprintf ("Bad read of inttemp!\n");
00945     }
00946     if (swap) {
00947       reverse16 (&Class->NumProtos);
00948       for (j = 0; j < MAX_NUM_CONFIGS; j++)
00949         reverse16 (&Class->ConfigLengths[j]);
00950     }
00951     ClassForIndex (Templates, i) = Class;
00952 
00953     /* then read in the proto lengths */
00954     Lengths = (UINT8 *) Emalloc (sizeof (UINT8) *
00955       MaxNumIntProtosIn (Class));
00956     if ((nread = fread ((char *) Lengths, sizeof (UINT8),
00957       MaxNumIntProtosIn (Class),
00958       File)) != MaxNumIntProtosIn (Class))
00959       cprintf ("Bad read of inttemp!\n");
00960     Class->ProtoLengths = Lengths;
00961 
00962     /* then read in the proto sets */
00963     for (j = 0; j < NumProtoSetsIn (Class); j++) {
00964       ProtoSet = (PROTO_SET) Emalloc (sizeof (PROTO_SET_STRUCT));
00965       if ((nread =
00966         fread ((char *) ProtoSet, 1, sizeof (PROTO_SET_STRUCT),
00967         File)) != sizeof (PROTO_SET_STRUCT))
00968         cprintf ("Bad read of inttemp!\n");
00969       if (swap) {
00970         for (x = 0; x < NUM_PP_PARAMS; x++)
00971           for (y = 0; y < NUM_PP_BUCKETS; y++)
00972             for (z = 0; z < WERDS_PER_PP_VECTOR; z++)
00973               reverse32 (&ProtoSet->ProtoPruner[x][y][z]);
00974         for (x = 0; x < PROTOS_PER_PROTO_SET; x++)
00975           for (y = 0; y < WERDS_PER_CONFIG_VEC; y++)
00976             reverse32 (&ProtoSet->Protos[x].Configs[y]);
00977       }
00978       ProtoSetIn (Class, j) = ProtoSet;
00979     }
00980   }
00981   return (Templates);
00982 }                                /* ReadIntTemplates */
00983 
00984 
00985 /* =============================== */
00998 #ifndef GRAPHICS_DISABLED
00999 void ShowMatchDisplay() { 
01000   void *window;
01001   /* Size of drawable */
01002   if (IntMatchWindow == NULL) {
01003     IntMatchWindow = c_create_window ("IntMatchWindow", 50, 200,
01004       520, 520,
01005       -130.0, 130.0, -130.0, 130.0);
01006   }
01007   else
01008     c_clear_window(IntMatchWindow);
01009 
01010   window = IntMatchWindow;
01011   c_line_color_index(window, Grey);
01012   /* Default size of drawing */
01013   if (NormMethod == baseline) {
01014     c_move (window, -1000.0, INT_BASELINE);
01015     c_draw (window, 1000.0, INT_BASELINE);
01016     c_move (window, -1000.0, INT_DESCENDER);
01017     c_draw (window, 1000.0, INT_DESCENDER);
01018     c_move (window, -1000.0, INT_XHEIGHT);
01019     c_draw (window, 1000.0, INT_XHEIGHT);
01020     c_move (window, -1000.0, INT_CAPHEIGHT);
01021     c_draw (window, 1000.0, INT_CAPHEIGHT);
01022     c_move (window, INT_MIN_X, -1000.0);
01023     c_draw (window, INT_MIN_X, 1000.0);
01024     c_move (window, INT_MAX_X, -1000.0);
01025     c_draw (window, INT_MAX_X, 1000.0);
01026   }
01027   else {
01028     c_move (window, INT_XCENTER - INT_XRADIUS, INT_YCENTER - INT_YRADIUS);
01029     c_draw (window, INT_XCENTER + INT_XRADIUS, INT_YCENTER - INT_YRADIUS);
01030     c_move (window, INT_XCENTER - INT_XRADIUS, INT_YCENTER + INT_YRADIUS);
01031     c_draw (window, INT_XCENTER + INT_XRADIUS, INT_YCENTER + INT_YRADIUS);
01032     c_move (window, INT_XCENTER - INT_XRADIUS, INT_YCENTER - INT_YRADIUS);
01033     c_draw (window, INT_XCENTER - INT_XRADIUS, INT_YCENTER + INT_YRADIUS);
01034     c_move (window, INT_XCENTER + INT_XRADIUS, INT_YCENTER - INT_YRADIUS);
01035     c_draw (window, INT_XCENTER + INT_XRADIUS, INT_YCENTER + INT_YRADIUS);
01036     c_move(window, INT_MIN_X, INT_MIN_Y);
01037     c_draw(window, INT_MIN_X, INT_MAX_Y);
01038     c_move(window, INT_MIN_X, INT_MIN_Y);
01039     c_draw(window, INT_MAX_X, INT_MIN_Y);
01040     c_move(window, INT_MAX_X, INT_MAX_Y);
01041     c_draw(window, INT_MIN_X, INT_MAX_Y);
01042     c_move(window, INT_MAX_X, INT_MAX_Y);
01043     c_draw(window, INT_MAX_X, INT_MIN_Y);
01044   }
01045 }                                /* ShowMatchDisplay */
01046 #endif
01047 
01048 /* =============================== */
01061 void WriteIntTemplates(FILE *File, INT_TEMPLATES Templates) { 
01062   int i, j;
01063   INT_CLASS Class;
01064 
01065   /* first write the high level template struct */
01066   fwrite ((char *) Templates, sizeof (INT_TEMPLATES_STRUCT), 1, File);
01067 
01068   /* then write out the class pruners */
01069   for (i = 0; i < NumClassPrunersIn (Templates); i++)
01070     fwrite ((char *) (Templates->ClassPruner[i]),
01071       sizeof (CLASS_PRUNER_STRUCT), 1, File);
01072 
01073   /* then write out each class */
01074   for (i = 0; i < NumClassesIn (Templates); i++) {
01075     Class = ClassForIndex (Templates, i);
01076 
01077     /* first write out the high level struct for the class */
01078     fwrite ((char *) Class, sizeof (INT_CLASS_STRUCT), 1, File);
01079 
01080     /* then write out the proto lengths */
01081     fwrite ((char *) (Class->ProtoLengths), sizeof (UINT8),
01082       MaxNumIntProtosIn (Class), File);
01083 
01084     /* then write out the proto sets */
01085     for (j = 0; j < NumProtoSetsIn (Class); j++)
01086       fwrite ((char *) ProtoSetIn (Class, j),
01087         sizeof (PROTO_SET_STRUCT), 1, File);
01088   }
01089 }                                /* WriteIntTemplates */
01090 
01091 
01092 /* =================
01093               Private Code
01094  ==================== */
01095 /* =============================== */
01110 FLOAT32 BucketStart(int Bucket, FLOAT32 Offset, int NumBuckets) { 
01111   return (((FLOAT32) Bucket / NumBuckets) - Offset);
01112 
01113 }                                /* BucketStart */
01114 
01115 
01116 /* =============================== */
01131 FLOAT32 BucketEnd(int Bucket, FLOAT32 Offset, int NumBuckets) { 
01132   return (((FLOAT32) (Bucket + 1) / NumBuckets) - Offset);
01133 }                                /* BucketEnd */
01134 
01135 
01136 /* =============================== */
01151 void DoFill(FILL_SPEC *FillSpec,
01152             CLASS_PRUNER Pruner,
01153             register UINT32 ClassMask,
01154             register UINT32 ClassCount,
01155             register UINT32 WordIndex) {
01156   register int X, Y, Angle;
01157   register UINT32 OldWord;
01158 
01159   X = FillSpec->X;
01160   if (X < 0)
01161     X = 0;
01162   if (X >= NUM_CP_BUCKETS)
01163     X = NUM_CP_BUCKETS - 1;
01164 
01165   if (FillSpec->YStart < 0)
01166     FillSpec->YStart = 0;
01167   if (FillSpec->YEnd >= NUM_CP_BUCKETS)
01168     FillSpec->YEnd = NUM_CP_BUCKETS - 1;
01169 
01170   for (Y = FillSpec->YStart; Y <= FillSpec->YEnd; Y++)
01171     for (Angle = FillSpec->AngleStart;
01172   TRUE; CircularIncrement (Angle, NUM_CP_BUCKETS)) {
01173     OldWord = Pruner[X][Y][Angle][WordIndex];
01174     if (ClassCount > (OldWord & ClassMask)) {
01175       OldWord &= ~ClassMask;
01176       OldWord |= ClassCount;
01177       Pruner[X][Y][Angle][WordIndex] = OldWord;
01178     }
01179     if (Angle == FillSpec->AngleEnd)
01180       break;
01181   }
01182 }                                /* DoFill */
01183 
01184 
01185 /* =============================== */
01195 BOOL8 FillerDone(TABLE_FILLER *Filler) { 
01196   FILL_SWITCH *Next;
01197 
01198   Next = &(Filler->Switch[Filler->NextSwitch]);
01199 
01200   if (Filler->X > Next->X && Next->Type == LastSwitch)
01201     return (TRUE);
01202   else
01203     return (FALSE);
01204 
01205 }                                /* FillerDone */
01206 
01207 
01208 /* =============================== */
01226 void
01227 FillPPCircularBits (UINT32 ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR],
01228 int Bit, FLOAT32 Center, FLOAT32 Spread) {
01229   int i, FirstBucket, LastBucket;
01230 
01231   if (Spread > 0.5)
01232     Spread = 0.5;
01233 
01234   FirstBucket = (int) floor ((Center - Spread) * NUM_PP_BUCKETS);
01235   if (FirstBucket < 0)
01236     FirstBucket += NUM_PP_BUCKETS;
01237 
01238   LastBucket = (int) floor ((Center + Spread) * NUM_PP_BUCKETS);
01239   if (LastBucket >= NUM_PP_BUCKETS)
01240     LastBucket -= NUM_PP_BUCKETS;
01241   if (LearningDebugLevel >= 2)
01242     cprintf ("Circular fill from %d to %d", FirstBucket, LastBucket);
01243   for (i = FirstBucket; TRUE; CircularIncrement (i, NUM_PP_BUCKETS)) {
01244     SET_BIT (ParamTable[i], Bit);
01245 
01246     /* exit loop after we have set the bit for the last bucket */
01247     if (i == LastBucket)
01248       break;
01249   }
01250 
01251 }                                /* FillPPCircularBits */
01252 
01253 
01254 /* =============================== */
01273 void
01274 FillPPLinearBits (UINT32 ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR],
01275 int Bit, FLOAT32 Center, FLOAT32 Spread) {
01276   int i, FirstBucket, LastBucket;
01277 
01278   FirstBucket = (int) floor ((Center - Spread) * NUM_PP_BUCKETS);
01279   if (FirstBucket < 0)
01280     FirstBucket = 0;
01281 
01282   LastBucket = (int) floor ((Center + Spread) * NUM_PP_BUCKETS);
01283   if (LastBucket >= NUM_PP_BUCKETS)
01284     LastBucket = NUM_PP_BUCKETS - 1;
01285 
01286   if (LearningDebugLevel >= 2)
01287     cprintf ("Linear fill from %d to %d", FirstBucket, LastBucket);
01288   for (i = FirstBucket; i <= LastBucket; i++)
01289     SET_BIT (ParamTable[i], Bit);
01290 
01291 }                                /* FillPPLinearBits */
01292 
01293 
01294 /* =============================== */
01304 #ifndef GRAPHICS_DISABLED
01305 CLASS_ID GetClassToDebug(const char *Prompt) { 
01306   return window_wait (IntMatchWindow);
01307 
01308 }                                /* GetClassToDebug */
01309 #endif
01310 
01311 /* =============================== */
01328 void GetCPPadsForLevel(int Level,
01329                        FLOAT32 *EndPad,
01330                        FLOAT32 *SidePad,
01331                        FLOAT32 *AnglePad) {
01332   switch (Level) {
01333     case 0:
01334       *EndPad = CPEndPadLoose * GetPicoFeatureLength ();
01335       *SidePad = CPSidePadLoose * GetPicoFeatureLength ();
01336       *AnglePad = CPAnglePadLoose / 360.0;
01337       break;
01338 
01339     case 1:
01340       *EndPad = CPEndPadMedium * GetPicoFeatureLength ();
01341       *SidePad = CPSidePadMedium * GetPicoFeatureLength ();
01342       *AnglePad = CPAnglePadMedium / 360.0;
01343       break;
01344 
01345     case 2:
01346       *EndPad = CPEndPadTight * GetPicoFeatureLength ();
01347       *SidePad = CPSidePadTight * GetPicoFeatureLength ();
01348       *AnglePad = CPAnglePadTight / 360.0;
01349       break;
01350 
01351     default:
01352       *EndPad = CPEndPadTight * GetPicoFeatureLength ();
01353       *SidePad = CPSidePadTight * GetPicoFeatureLength ();
01354       *AnglePad = CPAnglePadTight / 360.0;
01355       break;
01356   }
01357   if (*AnglePad > 0.5)
01358     *AnglePad = 0.5;
01359 
01360 }                                /* GetCPPadsForLevel */
01361 
01362 
01363 /* =============================== */
01373 C_COL GetMatchColorFor(FLOAT32 Evidence) { 
01374   assert (Evidence >= 0.0);
01375   assert (Evidence <= 1.0);
01376 
01377   if (Evidence >= 0.90)
01378     return White;
01379   else if (Evidence >= 0.75)
01380     return Green;
01381   else if (Evidence >= 0.50)
01382     return Red;
01383   else
01384     return Blue;
01385 }                                /* GetMatchColorFor */
01386 
01387 
01388 /* =============================== */
01402 void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill) { 
01403   FILL_SWITCH *Next;
01404 
01405   /* compute the fill assuming no switches will be encountered */
01406   Fill->AngleStart = Filler->AngleStart;
01407   Fill->AngleEnd = Filler->AngleEnd;
01408   Fill->X = Filler->X;
01409   Fill->YStart = Filler->YStart >> 8;
01410   Fill->YEnd = Filler->YEnd >> 8;
01411 
01412   /* update the fill info and the filler for ALL switches at this X value */
01413   Next = &(Filler->Switch[Filler->NextSwitch]);
01414   while (Filler->X >= Next->X) {
01415     Fill->X = Filler->X = Next->X;
01416     if (Next->Type == StartSwitch) {
01417       Fill->YStart = Next->Y;
01418       Filler->StartDelta = Next->Delta;
01419       Filler->YStart = Next->YInit;
01420     }
01421     else if (Next->Type == EndSwitch) {
01422       Fill->YEnd = Next->Y;
01423       Filler->EndDelta = Next->Delta;
01424       Filler->YEnd = Next->YInit;
01425     }
01426     else {                       /* Type must be LastSwitch */
01427       break;
01428     }
01429     Filler->NextSwitch++;
01430     Next = &(Filler->Switch[Filler->NextSwitch]);
01431   }
01432 
01433   /* prepare the filler for the next call to this routine */
01434   Filler->X++;
01435   Filler->YStart += Filler->StartDelta;
01436   Filler->YEnd += Filler->EndDelta;
01437 
01438 }                                /* GetNextFill */
01439 
01440 
01441 /* =============================== */
01459 void
01460 InitTableFiller (FLOAT32 EndPad,
01461 FLOAT32 SidePad,
01462 FLOAT32 AnglePad, PROTO Proto, TABLE_FILLER * Filler)
01463 #define XS          X_SHIFT
01464 #define YS          Y_SHIFT
01465 #define AS          ANGLE_SHIFT
01466 #define NB          NUM_CP_BUCKETS
01467 {
01468   FLOAT32 Angle;
01469   FLOAT32 X, Y, HalfLength;
01470   FLOAT32 Cos, Sin;
01471   FLOAT32 XAdjust, YAdjust;
01472   FPOINT Start, Switch1, Switch2, End;
01473   int S1 = 0;
01474   int S2 = 1;
01475 
01476   Angle = ProtoAngle (Proto);
01477   X = ProtoX (Proto);
01478   Y = ProtoY (Proto);
01479   HalfLength = ProtoLength (Proto) / 2.0;
01480 
01481   Filler->AngleStart = CircBucketFor (Angle - AnglePad, AS, NB);
01482   Filler->AngleEnd = CircBucketFor (Angle + AnglePad, AS, NB);
01483   Filler->NextSwitch = 0;
01484 
01485   if (fabs (Angle - 0.0) < HV_TOLERANCE || fabs (Angle - 0.5) < HV_TOLERANCE) {
01486     /* horizontal proto - handle as special case */
01487     Filler->X = BucketFor (X - HalfLength - EndPad, XS, NB);
01488     Filler->YStart = BucketFor (Y - SidePad, YS, NB * 256);
01489     Filler->YEnd = BucketFor (Y + SidePad, YS, NB * 256);
01490     Filler->StartDelta = 0;
01491     Filler->EndDelta = 0;
01492     Filler->Switch[0].Type = LastSwitch;
01493     Filler->Switch[0].X = BucketFor (X + HalfLength + EndPad, XS, NB);
01494   }
01495   else if (fabs (Angle - 0.25) < HV_TOLERANCE ||
01496   fabs (Angle - 0.75) < HV_TOLERANCE) {
01497     /* vertical proto - handle as special case */
01498     Filler->X = BucketFor (X - SidePad, XS, NB);
01499     Filler->YStart = BucketFor (Y - HalfLength - EndPad, YS, NB * 256);
01500     Filler->YEnd = BucketFor (Y + HalfLength + EndPad, YS, NB * 256);
01501     Filler->StartDelta = 0;
01502     Filler->EndDelta = 0;
01503     Filler->Switch[0].Type = LastSwitch;
01504     Filler->Switch[0].X = BucketFor (X + SidePad, XS, NB);
01505   }
01506   else {
01507     /* diagonal proto */
01508 
01509     if (Angle > 0.0 && Angle < 0.25 || Angle > 0.5 && Angle < 0.75) {
01510       /* rising diagonal proto */
01511       Angle *= 2.0 * PI;
01512       Cos = fabs (cos (Angle));
01513       Sin = fabs (sin (Angle));
01514 
01515       /* compute the positions of the corners of the acceptance region */
01516       Start.x = X - (HalfLength + EndPad) * Cos - SidePad * Sin;
01517       Start.y = Y - (HalfLength + EndPad) * Sin + SidePad * Cos;
01518       End.x = 2.0 * X - Start.x;
01519       End.y = 2.0 * Y - Start.y;
01520       Switch1.x = X - (HalfLength + EndPad) * Cos + SidePad * Sin;
01521       Switch1.y = Y - (HalfLength + EndPad) * Sin - SidePad * Cos;
01522       Switch2.x = 2.0 * X - Switch1.x;
01523       Switch2.y = 2.0 * Y - Switch1.y;
01524 
01525       if (Switch1.x > Switch2.x) {
01526         S1 = 1;
01527         S2 = 0;
01528       }
01529 
01530       /* translate into bucket positions and deltas */
01531       Filler->X = (INT8) MapParam (Start.x, XS, NB);
01532       Filler->StartDelta = -(INT16) ((Cos / Sin) * 256);
01533       Filler->EndDelta = (INT16) ((Sin / Cos) * 256);
01534 
01535       XAdjust = BucketEnd (Filler->X, XS, NB) - Start.x;
01536       YAdjust = XAdjust * Cos / Sin;
01537       Filler->YStart = (INT16) MapParam (Start.y - YAdjust, YS, NB * 256);
01538       YAdjust = XAdjust * Sin / Cos;
01539       Filler->YEnd = (INT16) MapParam (Start.y + YAdjust, YS, NB * 256);
01540 
01541       Filler->Switch[S1].Type = StartSwitch;
01542       Filler->Switch[S1].X = (INT8) MapParam (Switch1.x, XS, NB);
01543       Filler->Switch[S1].Y = (INT8) MapParam (Switch1.y, YS, NB);
01544       XAdjust = Switch1.x - BucketStart (Filler->Switch[S1].X, XS, NB);
01545       YAdjust = XAdjust * Sin / Cos;
01546       Filler->Switch[S1].YInit =
01547         (INT16) MapParam (Switch1.y - YAdjust, YS, NB * 256);
01548       Filler->Switch[S1].Delta = Filler->EndDelta;
01549 
01550       Filler->Switch[S2].Type = EndSwitch;
01551       Filler->Switch[S2].X = (INT8) MapParam (Switch2.x, XS, NB);
01552       Filler->Switch[S2].Y = (INT8) MapParam (Switch2.y, YS, NB);
01553       XAdjust = Switch2.x - BucketStart (Filler->Switch[S2].X, XS, NB);
01554       YAdjust = XAdjust * Cos / Sin;
01555       Filler->Switch[S2].YInit =
01556         (INT16) MapParam (Switch2.y + YAdjust, YS, NB * 256);
01557       Filler->Switch[S2].Delta = Filler->StartDelta;
01558 
01559       Filler->Switch[2].Type = LastSwitch;
01560       Filler->Switch[2].X = (INT8) MapParam (End.x, XS, NB);
01561     }
01562     else {
01563       /* falling diagonal proto */
01564       Angle *= 2.0 * PI;
01565       Cos = fabs (cos (Angle));
01566       Sin = fabs (sin (Angle));
01567 
01568       /* compute the positions of the corners of the acceptance region */
01569       Start.x = X - (HalfLength + EndPad) * Cos - SidePad * Sin;
01570       Start.y = Y + (HalfLength + EndPad) * Sin - SidePad * Cos;
01571       End.x = 2.0 * X - Start.x;
01572       End.y = 2.0 * Y - Start.y;
01573       Switch1.x = X - (HalfLength + EndPad) * Cos + SidePad * Sin;
01574       Switch1.y = Y + (HalfLength + EndPad) * Sin + SidePad * Cos;
01575       Switch2.x = 2.0 * X - Switch1.x;
01576       Switch2.y = 2.0 * Y - Switch1.y;
01577 
01578       if (Switch1.x > Switch2.x) {
01579         S1 = 1;
01580         S2 = 0;
01581       }
01582 
01583       /* translate into bucket positions and deltas */
01584       Filler->X = (INT8) MapParam (Start.x, XS, NB);
01585       Filler->StartDelta = -(INT16) ((Sin / Cos) * 256);
01586       Filler->EndDelta = (INT16) ((Cos / Sin) * 256);
01587 
01588       XAdjust = BucketEnd (Filler->X, XS, NB) - Start.x;
01589       YAdjust = XAdjust * Sin / Cos;
01590       Filler->YStart = (INT16) MapParam (Start.y - YAdjust, YS, NB * 256);
01591       YAdjust = XAdjust * Cos / Sin;
01592       Filler->YEnd = (INT16) MapParam (Start.y + YAdjust, YS, NB * 256);
01593 
01594       Filler->Switch[S1].Type = EndSwitch;
01595       Filler->Switch[S1].X = (INT8) MapParam (Switch1.x, XS, NB);
01596       Filler->Switch[S1].Y = (INT8) MapParam (Switch1.y, YS, NB);
01597       XAdjust = Switch1.x - BucketStart (Filler->Switch[S1].X, XS, NB);
01598       YAdjust = XAdjust * Sin / Cos;
01599       Filler->Switch[S1].YInit =
01600         (INT16) MapParam (Switch1.y + YAdjust, YS, NB * 256);
01601       Filler->Switch[S1].Delta = Filler->StartDelta;
01602 
01603       Filler->Switch[S2].Type = StartSwitch;
01604       Filler->Switch[S2].X = (INT8) MapParam (Switch2.x, XS, NB);
01605       Filler->Switch[S2].Y = (INT8) MapParam (Switch2.y, YS, NB);
01606       XAdjust = Switch2.x - BucketStart (Filler->Switch[S2].X, XS, NB);
01607       YAdjust = XAdjust * Cos / Sin;
01608       Filler->Switch[S2].YInit =
01609         (INT16) MapParam (Switch2.y - YAdjust, YS, NB * 256);
01610       Filler->Switch[S2].Delta = Filler->EndDelta;
01611 
01612       Filler->Switch[2].Type = LastSwitch;
01613       Filler->Switch[2].X = (INT8) MapParam (End.x, XS, NB);
01614     }
01615   }
01616 }                                /* InitTableFiller */
01617 
01618 
01619 /* =============================== */
01630 #ifndef GRAPHICS_DISABLED
01631 void RenderIntFeature(void *window, INT_FEATURE Feature, C_COL Color) { 
01632   FLOAT32 X, Y, Dx, Dy, Length;
01633 
01634   c_line_color_index(window, Color);
01635   assert (Feature != NULL);
01636   assert (Color != 0);
01637 
01638   X = Feature->X - DISPLAY_OFFSET;
01639   Y = Feature->Y - DISPLAY_OFFSET;
01640   Length = GetPicoFeatureLength () * 0.7 * INT_CHAR_NORM_RANGE;
01641   Dx = (Length / 2.0) * cos ((Feature->Theta / 256.0) * 2.0 * PI);
01642   Dy = (Length / 2.0) * sin ((Feature->Theta / 256.0) * 2.0 * PI);
01643 
01644   c_move (window, X - Dx, Y - Dy);
01645   c_draw (window, X + Dx, Y + Dy);
01646   c_move (window, X - Dx - Dy * DOUBLE_OFFSET, Y - Dy + Dx * DOUBLE_OFFSET);
01647   c_draw (window, X + Dx - Dy * DOUBLE_OFFSET, Y + Dy + Dx * DOUBLE_OFFSET);
01648 }                                /* RenderIntFeature */
01649 
01650 
01651 /* =============================== */
01665 void RenderIntProto(void *window,
01666                     INT_CLASS Class,
01667                     PROTO_ID ProtoId,
01668                     C_COL Color) {
01669   PROTO_SET ProtoSet;
01670   INT_PROTO Proto;
01671   int ProtoSetIndex;
01672   int ProtoWordIndex;
01673   FLOAT32 Length;
01674   int Xmin, Xmax, Ymin, Ymax;
01675   FLOAT32 X, Y, Dx, Dy;
01676   UINT32 ProtoMask;
01677   int Bucket;
01678 
01679   assert (ProtoId >= 0);
01680   assert (Class != NULL);
01681   assert (ProtoId < NumIntProtosIn (Class));
01682   assert (Color != 0);
01683   c_line_color_index(window, Color);
01684 
01685   ProtoSet = ProtoSetIn (Class, SetForProto (ProtoId));
01686   ProtoSetIndex = IndexForProto (ProtoId);
01687   Proto = &(ProtoSet->Protos[ProtoSetIndex]);
01688   Length = (LengthForProtoId (Class, ProtoId) *
01689     GetPicoFeatureLength () * INT_CHAR_NORM_RANGE);
01690   ProtoMask = PPrunerMaskFor (ProtoId);
01691   ProtoWordIndex = PPrunerWordIndexFor (ProtoId);
01692 
01693   // find the x and y extent of the proto from the proto pruning table
01694   Xmin = Ymin = NUM_PP_BUCKETS;
01695   Xmax = Ymax = 0;
01696   for (Bucket = 0; Bucket < NUM_PP_BUCKETS; Bucket++) {
01697     if (ProtoMask & ProtoSet->ProtoPruner[PRUNER_X][Bucket][ProtoWordIndex])
01698       if (Bucket < Xmin)
01699         Xmin = Bucket;
01700     else if (Bucket > Xmax)
01701       Xmax = Bucket;
01702 
01703     if (ProtoMask & ProtoSet->ProtoPruner[PRUNER_Y][Bucket][ProtoWordIndex])
01704       if (Bucket < Ymin)
01705         Ymin = Bucket;
01706     else if (Bucket > Ymax)
01707       Ymax = Bucket;
01708   }
01709   X = (Xmin + Xmax + 1) / 2.0 * PROTO_PRUNER_SCALE - DISPLAY_OFFSET;
01710   Y = (Ymin + Ymax + 1) / 2.0 * PROTO_PRUNER_SCALE - DISPLAY_OFFSET;
01711   Dx = (Length / 2.0) * cos ((Proto->Angle / 256.0) * 2.0 * PI);
01712   Dy = (Length / 2.0) * sin ((Proto->Angle / 256.0) * 2.0 * PI);
01713 
01714   c_move (window, X - Dx, Y - Dy);
01715   c_draw (window, X + Dx, Y + Dy);
01716 }                                /* RenderIntProto */
01717 #endif
01718 
01719 /* =============================== */
01734 int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id) { 
01735   if (Param < Min) {
01736     if (Id)
01737       cprintf ("Warning: Param %s truncated from %f to %d!\n",
01738         Id, Param, Min);
01739     Param = Min;
01740   }
01741   else if (Param > Max) {
01742     if (Id)
01743       cprintf ("Warning: Param %s truncated from %f to %d!\n",
01744         Id, Param, Max);
01745     Param = Max;
01746   }
01747   return (int) floor (Param);
01748 
01749 }                                /* TruncateParam */

Generated on Wed Feb 28 19:49:10 2007 for Tesseract by  doxygen 1.5.1