00001
00019
00020
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
00032
00033 #include <math.h>
00034 #include <stdio.h>
00035 #include <assert.h>
00036
00037
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
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
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
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00256
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
00275
00276
00277
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 }
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 }
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
00374 Class->ProtoLengths = (UINT8 *) Erealloc (Class->ProtoLengths,
00375 MaxNumIntProtosIn (Class) *
00376 sizeof (UINT8));
00377 }
00378
00379
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 }
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 }
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 }
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 }
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 }
00540
00541
00542
00554 #ifndef GRAPHICS_DISABLED
00555 void UpdateMatchDisplay() {
00556 if (IntMatchWindow != NULL)
00557 c_make_current(IntMatchWindow);
00558 }
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 }
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
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 }
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 }
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 }
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 }
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 }
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
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
00789 }
00790 Class->ProtoLengths = (UINT8 *) Emalloc (MaxNumIntProtosIn (Class) *
00791 sizeof (UINT8));
00792
00793 return (Class);
00794
00795 }
00796
00797
00798
00802 void free_int_class(
00803 INT_CLASS int_class) {
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
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 }
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
00880 Templates = NewIntTemplates ();
00881
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
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
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
00930 for (i = 0; i < NumClassesIn (Templates); i++) {
00931
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
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
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 }
00983
00984
00985
00998 #ifndef GRAPHICS_DISABLED
00999 void ShowMatchDisplay() {
01000 void *window;
01001
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
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 }
01046 #endif
01047
01048
01061 void WriteIntTemplates(FILE *File, INT_TEMPLATES Templates) {
01062 int i, j;
01063 INT_CLASS Class;
01064
01065
01066 fwrite ((char *) Templates, sizeof (INT_TEMPLATES_STRUCT), 1, File);
01067
01068
01069 for (i = 0; i < NumClassPrunersIn (Templates); i++)
01070 fwrite ((char *) (Templates->ClassPruner[i]),
01071 sizeof (CLASS_PRUNER_STRUCT), 1, File);
01072
01073
01074 for (i = 0; i < NumClassesIn (Templates); i++) {
01075 Class = ClassForIndex (Templates, i);
01076
01077
01078 fwrite ((char *) Class, sizeof (INT_CLASS_STRUCT), 1, File);
01079
01080
01081 fwrite ((char *) (Class->ProtoLengths), sizeof (UINT8),
01082 MaxNumIntProtosIn (Class), File);
01083
01084
01085 for (j = 0; j < NumProtoSetsIn (Class); j++)
01086 fwrite ((char *) ProtoSetIn (Class, j),
01087 sizeof (PROTO_SET_STRUCT), 1, File);
01088 }
01089 }
01090
01091
01092
01093
01094
01095
01110 FLOAT32 BucketStart(int Bucket, FLOAT32 Offset, int NumBuckets) {
01111 return (((FLOAT32) Bucket / NumBuckets) - Offset);
01112
01113 }
01114
01115
01116
01131 FLOAT32 BucketEnd(int Bucket, FLOAT32 Offset, int NumBuckets) {
01132 return (((FLOAT32) (Bucket + 1) / NumBuckets) - Offset);
01133 }
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 }
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 }
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
01247 if (i == LastBucket)
01248 break;
01249 }
01250
01251 }
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 }
01292
01293
01294
01304 #ifndef GRAPHICS_DISABLED
01305 CLASS_ID GetClassToDebug(const char *Prompt) {
01306 return window_wait (IntMatchWindow);
01307
01308 }
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 }
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 }
01386
01387
01388
01402 void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill) {
01403 FILL_SWITCH *Next;
01404
01405
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
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 {
01427 break;
01428 }
01429 Filler->NextSwitch++;
01430 Next = &(Filler->Switch[Filler->NextSwitch]);
01431 }
01432
01433
01434 Filler->X++;
01435 Filler->YStart += Filler->StartDelta;
01436 Filler->YEnd += Filler->EndDelta;
01437
01438 }
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
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
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
01508
01509 if (Angle > 0.0 && Angle < 0.25 || Angle > 0.5 && Angle < 0.75) {
01510
01511 Angle *= 2.0 * PI;
01512 Cos = fabs (cos (Angle));
01513 Sin = fabs (sin (Angle));
01514
01515
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
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
01564 Angle *= 2.0 * PI;
01565 Cos = fabs (cos (Angle));
01566 Sin = fabs (sin (Angle));
01567
01568
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
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 }
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 }
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
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 }
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 }