לדלג לתוכן

תכנות וזיהוי/קובץ ללימוד בשעת ריצת התוכנית

מתוך ויקיספר, אוסף הספרים והמדריכים החופשי

הקובץ AtLearn.cpp

[עריכה]
/* AtLearn.cpp
קובץ מקור זה מכיל פונקציות העוזרות
להפיק מידע על כל אות ואות
בעזרת תמונת מפת הסיביות של
מופעי האות
הקריטריון לקביעת תכונה מאפינת
הוא צירוף של מספר מרכיבי תכונה
כל מרכיב מבדיל בין האות לאות אחרת
צירוף של מספר מרכיבים יוצר מפתח
או בשם אחר תכונה
המבדיל בין אות אחת לכל שאר האותיות
הקריטריון לקביעת מרכיב מאפיין הוא
מלבן התופס חלק מגודל האות
אם ממוצע הבהירות בו
שונה באופן ברור בין
המופעים של שתי אותיות */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
/* לשם יצירת מספרים אקראיים */
#include <time.h>
#include <math.h> // sqrt(x)
#include "MyProcs.h"

/* פונקציה לשם יצירת קובץ תמליל */
FILE *fopen();
/* מערך המכיל לכל המופעים של האוביקט
את מרכיבי התכונות האפשריים */
int MeanMap[AllComps][ObjectsMax][NumVariants];
/* ממוצע של המערך הקודם עבור מופעי האוביקטים */
int MeanMeanMap[AllComps][ObjectsMax];
/* סטיות מהממוצע עבור מופעי האוביקטים */
int MeanDeltaMap[AllComps][ObjectsMax];
/* סטיות מהממוצע עבור האוביקטים
2->( ציון,מרכיב )*/
int ArryAtt[ObjectsMax][2];
int ScanAtt[AllComps][ObjectsMax];
/* לכל אוביקט המערך מכיל את מרכבי התכונות שלו
מכיל עד 3 תכונות ללא מרכיבי תכונות חוזרים */
int WinKeys[ObjectsMax][3][ObjectsMax];
int TheAttributs[AllComps];
/* דגימת תמונה */
int OneImage[RowsPerPic][ColsPerPic];
/* מלבנים*/
int RectsMap[AllComps][ComponDefSet];
/* מספרים ממשיים העוזרים לתפוס
תמונה שהיא חלק מהתמונה */
/* מרחק מאוזן בין שתי תמונות
הכולל גם את רוחב התמונה */
float DeltaRow2Pic1;
float DeltaCol2Pic1;/* מרחק מאונך */
/* המרחק בין התמונה הראשונה
לצד השמאלי של המסך */
float FirstPicRow1;
/* המרחק בין התמונה הראשונה
לצד העליון של המסך */
float FirstPicCol1;
/* רוחב של קטע נדגם ביחידות של פיקסלים
לכן אפילו אם בחלק התמונה הנדגם היו 32
פיקסלים, התוצאה תהיה מערך ברוחב של 8 שלמים */
float PixPerRowDot1;
float PixPerColDot1;/* גובה של קטע נבחר */
/* מספר האוביקטים שניבחרו */
int NumObjects;

/* בדוק אם שורת דוח היא מפתח */
bool IsKeyInL(int LineAtt[])
{
  int TheAtt ,MoneMinus=0 ;
  for(TheAtt=0;TheAtt<NumObjects;TheAtt++)
    if (LineAtt[TheAtt] == -1) MoneMinus++ ;
  return (MoneMinus == 1);
}
 /* הוסף את מספרי התכונות
 משורת דוח לתוך מערך צובר */
void AddLine2AllAttsInL(int ALine[],
                     int AtAll[AllComps])
{ int TheAtt,Locate;
  for(TheAtt=0;TheAtt<NumObjects;TheAtt++)
    for(Locate=0;
        (Locate<AllComps)&&
         /* בדוק אם הוא כבר נמצא */
          (AtAll[Locate]!=ALine[TheAtt]);
        Locate++)
      /* טען במקום ריק במערך */
       if(AtAll[Locate]==-1)
        {AtAll[Locate]=ALine[TheAtt];
         Locate=AllComps ;}

}

/* יצירת קובץ המכיל את המספר הסודר
של מרכיבי התכונות השאובים מהדוח
המכיל את תעודות הזהות של העצמים */
void SumAllAttsInL()
{int MySign,MoneKeys,TheAtt,Locate;
 int AllAtts[AllComps],Atts,Save,Locate2;
 int LineAtt[NumObjects];
 FILE *Rfp,*Compnfp;
 for(Locate=0;Locate<AllComps;Locate++)
   AllAtts[Locate]= -1;
 Rfp=fopen(ReportFile,"r");
 for(MySign=0;MySign<NumObjects;MySign++)
 {NewLinesInC(Rfp,1,NumObjects); /* קפוץ על שורת הכותרת */
  for(MoneKeys=0;MoneKeys<KeysPerObject;MoneKeys++)
   {for(TheAtt=0;TheAtt<NumObjects;TheAtt++)
       fscanf(Rfp,"%d",&LineAtt[TheAtt]);
    if (IsKeyInL(LineAtt)) AddLine2AllAttsInL(LineAtt,AllAtts);
     NewLinesInC(Rfp,2,NumObjects); /* קפוץ על הציונים */
   }
  }
 fclose(Rfp);
 /* מנה*/
 for(Locate=0;Locate<AllComps;Locate++)
   if(AllAtts[Locate]==-1)break;
 Atts=Locate;

 /* מיין*/
 for(Locate=0;Locate<Atts;Locate++)
  for(Locate2=Locate+1;Locate2<Atts;Locate2++)
   if(AllAtts[Locate2]<AllAtts[Locate])
   {Save=AllAtts[Locate];
    AllAtts[Locate]=AllAtts[Locate2];
    AllAtts[Locate2]=Save;
   }
 /* שמור בקובץ*/
 EmptyFileInF( ElementsInSerial);
 Compnfp=fopen(ElementsInSerial,"w");
   fprintf(Compnfp,"%5d \n",Atts);
   for(Locate=0;Locate<Atts;Locate++)
     fprintf(Compnfp,"%5d",AllAtts[Locate]);
 fclose(Compnfp);
 }


/* טען מערך בדגימת תמונת מופע של אוביקט */
void SelectFileMatInL(HDC hdcMe,int Variant,int Object,
    LineBrightness FilterKind, int ColorLimit )
{RECT Rc;

 Rc=PicLocationInL(Object,Variant);
 SelectPicInC(hdcMe,
   float(Rc.left),float(Rc.top),
   float(Rc.right),float(Rc.bottom),// קודם רוחב ואחר כך גובה
   OneImage,FilterKind,ColorLimit);
}


/* בדיקה אם הישר עובר ליד המרכז
ולכן התוצאות שלו חשובות יותר
:מבוסס על משוואןת מהגאומטריה האנליטית
 משוואת מציאת מרחק נקודה - המרכז:מישר
(x1,y1 ) מרחק הנקודה
Ax+By+C=0 מו הישר
מרחק = abs(Ax1+By1+C /sqrt(A*A+B*B))
וגם על משואת הישר על פי שתי נקודות
(x1,y1),(x2,y2)
Y-y1=[(y2-x1)/(x2-x1)](X-x1)*/
bool IsPassByTheCenterInL(
   POINT  Start, POINT  End ,POINT Center)
{ float A,B,C,Mone,Mechane,Delta;
  bool Out = false;
 if (End.x-Start.x==0) return Out;
 A = float(End.y-Start.y)/float(End.x-Start.x) ;
 B = float(-1);
 C = B*A* float(Start.x);
 Mone= A*float(Center.x)+B*float(Center.y)+C;
 Mechane = sqrt(A*A + B*B);
 Delta =Mone /Mechane;
 if (Delta<0) Delta = Delta*B;
 if ( (Delta< float(Center.x) /2.0)&&
      (Delta< float(Center.y) /2.0)  )
   Out = true;
 return Out;
}


/* מצא מספר שינויים
לאורך מסלול
המתחיל בדופן ומסתיים בדופן */
int FindBarInL(POINT  Start, POINT  End ,
             int Mat[ColsPerPic][RowsPerPic])
{// FILE *DebMat;
 POINT Center;
 bool WasMetLine = FALSE;
 int  SignX=-1 ,SignY=-1 ,Out = 0 ,X,Y;
 int  Previous=BrightLevels-1 ; // רקע צבע לבן = 7
 int  XInMat = Start.x;
 int  YInMat = Start.y;
 int  DeltaX=AbsDelta(Start.x,End.x);
 int  DeltaY=AbsDelta(Start.y,End.y);
 if  (Start.x < End.x) SignX=1;
 if  (Start.y < End.y) SignY=1;
   X=0 ;Y= 0 ;
   for (;X < DeltaX+1 , Y < DeltaY+1; X++,Y++ )
   {if (DeltaX > DeltaY) // נוע לאט
    { XInMat = Start.x + (X*DeltaY*SignX)/DeltaX   ;
      YInMat = Start.y + Y*SignY   ;
    }
    if (DeltaX < DeltaY)
    { XInMat = Start.x +  X*SignX   ;
      YInMat = Start.y +  (Y*DeltaX*SignY)/DeltaY   ;
    }
    if (WasMetLine)
        {if (Mat[XInMat][YInMat]> Previous)
          { Out++; WasMetLine=FALSE;} }
    else if (Mat[XInMat][YInMat]< Previous)
          { Out++; WasMetLine=TRUE;}
    Previous = Mat[XInMat][YInMat];
     // אם לא הגיע לדופן השלם את המסלול
   //  if ( Y == DeltaY && X< DeltaX ) Y-- ;
   //  if ( X == DeltaX && Y< DeltaY ) X-- ;
   }// אם יצאת החוצה ולפני זה ישבת על קו
 if (WasMetLine) Out++; // סימן שחתחת קו
  if (Out>0)
  { Center.x = ColsPerPic/2;
    Center.y = RowsPerPic/2;
    if( IsPassByTheCenterInL(Start,End,Center))
      Out++;
  }
 if  ( abs(Start.x-End.x)< ColsPerPic/2 &&
       abs(Start.x-End.x)< RowsPerPic/2 &&
       abs(Start.y-End.y)< ColsPerPic/2 &&
       abs(Start.y-End.y)< RowsPerPic/2    )
    Out=0;    // הקטע קטן מידי

 return Out; // מספר השינויים
}

int AddMaxVecsInL(int MyCompi,
             int Mat[ColsPerPic][RowsPerPic])
{int x,y,Max=0,Strikes;
 POINT  Start,  End ;
 if (MyCompi == RecComps)
  for (x=0;x < ColsPerPic ; x++ )
  {Start.x = x;
   Start.y = 0;
   End.x   = x;
   End.y   = RowsPerPic-1;
   Strikes = FindBarInL(  Start, End ,Mat);
   if (Strikes > Max)Max = Strikes;
  }
 if (MyCompi == RecComps+1)
  for (y=0;y < RowsPerPic ; y++ )
  {Start.x = 0;
   Start.y = y;
   End.x   = ColsPerPic-1;
   End.y   = y;
   Strikes = FindBarInL(  Start, End ,Mat);
    if (Strikes > Max)Max = Strikes;
  }
 return Max;//(Max/4);
}

int FindSumVec(int DistanceX,
   int DistanceY, bool IsVertical,
   int Mat[ColsPerPic][RowsPerPic])
{int Mone,Sum=0,Strikes;
 POINT  Start,  End ;
 if (IsVertical)
   for (Mone=0;Mone < DistanceX ; Mone++ )
    {Start.x = Mone;
     Start.y = 0;
     End.x   = Mone;
     End.y   = DistanceY-1;
     Strikes = FindBarInL(  Start, End ,Mat);
     Sum = Strikes+Sum;
   }
  if (!IsVertical)
   for (Mone=0;Mone < DistanceY ; Mone++ )
    {Start.x = 0;
     Start.y = Mone;
     End.x   = DistanceX-1;
     End.y   = Mone;
     Strikes = FindBarInL(  Start, End ,Mat);
     Sum = Strikes+Sum;
  }
 return Sum/4;//(Sum/4);
}

int FindSumDiagsInL(int DistanceX,
   int DistanceY, bool IsDownRight,
   bool IsUpTriangle,
   int Mat[ColsPerPic][RowsPerPic])
{int MoneX=0,MoneY=0,Sum=0,Strikes;
 POINT  Start,  End ;
 if (IsDownRight&&IsUpTriangle)
  for (;MoneX < DistanceX||MoneX<DistanceY;MoneX++)
    {Start.x = MoneX;
     Start.y = 0;
     End.x   = DistanceX -1;
     End.y   = DistanceY-MoneX-1;
     Strikes = FindBarInL(  Start, End ,Mat);
     Sum = Strikes+Sum;
   }
  if (IsDownRight&&!IsUpTriangle)
   for (;MoneY<DistanceY||MoneY<DistanceX;MoneY++)
    {Start.x = 0;
     Start.y = MoneY;
     End.x   = DistanceX-MoneY-1;
     End.y   = DistanceY-1;
     Strikes = FindBarInL(  Start, End ,Mat);
     Sum = Strikes+Sum;
  }
  if (!IsDownRight&&IsUpTriangle)//IsDownleft
  for (;MoneX < DistanceX||MoneX<DistanceY;MoneX++)
    {Start.x = DistanceX-MoneX-1;
     Start.y = 0;
     End.x   = 0;
     End.y   = DistanceY-MoneX-1;
     Strikes = FindBarInL(  Start, End ,Mat);
     Sum = Strikes+Sum;
   }
  if (!IsDownRight&&!IsUpTriangle)
   for (;MoneY<DistanceY||MoneY<DistanceX;MoneY++)
    {Start.x = 0;
     Start.y = MoneY;
     End.x   = MoneY;
     End.y   = DistanceY-1;
     Strikes = FindBarInL(  Start, End ,Mat);
     Sum = Strikes+Sum;
  }
 
 return Sum/4;//(Sum/2);
}




int AddSumVecsInL(int MyCompi,
             int Mat[ColsPerPic][RowsPerPic])
{int Width  = ColsPerPic;
 int Length = RowsPerPic;
 int Start =  RecComps+MaxComps;
 if (MyCompi == Start)
  return  FindSumVec(Width,Length,true,Mat);
 if (MyCompi == Start+1)
  return  FindSumVec(Width,Length,false,Mat);
 if (MyCompi == Start+2)
  return  FindSumVec(Width/2,Length,true,Mat);
 if (MyCompi == Start+3)
  return  FindSumVec(Width,Length/2,false,Mat);
 if (MyCompi == Start+4)
  return  FindSumDiagsInL(Width,Length,true,true,Mat);
 if (MyCompi == Start+5)
  return  FindSumDiagsInL(Width,Length,true,false,Mat);
 if (MyCompi == Start+6)
  return  FindSumDiagsInL(Width,Length,false,true,Mat);
 if (MyCompi == Start+7)
  return  FindSumDiagsInL(Width,Length,false,false,Mat);
}

void FindMeanInL(HDC hdc, int MyFeature,
              int RowDigit,int ColDigit)
{POINT From ,To ;
 int Result=0;
 From.x = RectsMap[MyFeature][0];
 From.y = RectsMap[MyFeature][1];
 To.x   = RectsMap[MyFeature][2];
 To.y   = RectsMap[MyFeature][3];
 if (MyFeature< RecComps ) // תכונת החיתוכים
   Result = FindBarInL(From,To,OneImage);
 if (MyFeature>= RecComps &&
     MyFeature< RecComps+MaxComps)
  Result =AddMaxVecsInL(MyFeature,OneImage);
 if (MyFeature>= RecComps+MaxComps)
  Result =AddSumVecsInL(MyFeature,OneImage);
 MeanMap[MyFeature][RowDigit][ColDigit]=Result;
}

void FollowMatInL()
{FILE *Deb;
 int X,Y;
 Deb=fopen("Debug.txt","w");
   fprintf(Deb,"\n");
   for(Y=0;Y<RowsPerPic;Y++)
   { for(X=0;X<ColsPerPic;X++)
        fprintf(Deb,"%d",OneImage[X][Y]);
     fprintf(Deb,"\n");
   }
   fprintf(Deb,"\n");
 fclose(Deb);
}

void FollowAttInL(int Attri,
   int MatIm[ColsPerPic][RowsPerPic])
{FILE *Deb;
 int X,Y,W,L;
 GetCupAttsInL(RectsMap);
 POINT From ,To ;
 From.x = RectsMap[Attri][0];
 From.y = RectsMap[Attri][1];
 To.x   = RectsMap[Attri][2];
 To.y   = RectsMap[Attri][3];
  if (From.x>To.x)
 {X = To.x;    // החלף
  To.x= From.x;
  From.x= X;
 }
 if (From.y>To.y)
 {Y = To.y;    // החלף
  To.y= From.y;
  From.y= Y;
 }
  W = To.x;
  L = To.y;
  if (From.x==0)
  {
  Deb=fopen("Debug.txt","a");
    fprintf(Deb,"\nAttribute  %5d\n",Attri);
    fprintf(Deb,"X1%5d Y1%5d Width%5d Length%5d \n",
          int( From.x),int(From.y),W,L);
     for(Y=From.y;Y<From.y+L ;Y++)
     { for(X=From.x;X<From.x+W;X++)
         fprintf(Deb,"%5d",MatIm[X][Y]);
       fprintf(Deb,"\n");
     }
  fclose(Deb);
 }
}



/* טען מערך בכל מרכיבי התכונות על פני כל התמונה */
void FillMeanMapInL(HDC hdcMe,
     LineBrightness AFilterKind, int MyLimit)
{int PicRowNum,PicNum,TheFeature;
 for(PicRowNum=0;PicRowNum<NumObjects;PicRowNum++)
  for(PicNum=0;PicNum<NumVariants;PicNum++)
  {SelectFileMatInL(hdcMe,PicRowNum,PicNum,
                 AFilterKind,MyLimit);
 //  if (PicRowNum==20)FollowMat();
   for(TheFeature=0;TheFeature<AllComps;TheFeature++)
     { //if (TheFeature<270)
       // FollowAtt(TheFeature,OneImage);
      FindMeanInL(hdcMe,TheFeature,PicRowNum,PicNum);
     }
  }
}


//////////////////////////////////////
///// חלק 2 טען מערכים בסטטיסטיקה ////
/////////////////////////////////////

/* חשב לכל עצם את הממוצע של המופעים
MeanMap  במערך
MeanMeanMap שמור את התוצאה במערך */
void FillMeanMeanMapInL()
{int PicRowNum,PicNum,TheFeature ;
 int Sum=0;
 for(TheFeature=0;TheFeature<AllComps;TheFeature++)
  for(PicRowNum=0;PicRowNum<NumObjects;PicRowNum++)
  { for(PicNum=0;PicNum<NumVariants;PicNum++)
      Sum=Sum+
        MeanMap[TheFeature][PicRowNum][PicNum];
    MeanMeanMap[TheFeature][PicRowNum]=
           Sum/NumVariants;
    /* אם יש שארית גדולה עגל כלפי מעלה */
    if ((Sum % NumVariants)*2 > NumVariants)
       MeanMeanMap[TheFeature][PicRowNum]++ ;
    Sum=0;
  }
}

/* לכל עצם חשב את השונות
MeanMeanMap של המופעים במערך
MeanDeltaMap שמור את התוצאה במערך */
void FillMeanDeltaMapInL()
{int PicRowNum,PicNum,TheFeature;
 int Sum=0;

 for(TheFeature=0;TheFeature<AllComps;TheFeature++)
  for(PicRowNum=0;PicRowNum<NumObjects;PicRowNum++)
  { for(PicNum=0;PicNum<NumVariants;PicNum++)
      Sum = Sum + AbsDelta(
          MeanMap[TheFeature][PicRowNum][PicNum],
          MeanMeanMap[TheFeature][PicRowNum]);
    MeanDeltaMap[TheFeature][PicRowNum]
               = Sum /NumVariants;
     /* אם יש שארית גדולה עגל כלפי מעלה */
    if ((Sum % NumVariants)*2 > NumVariants)
      MeanDeltaMap[TheFeature][PicRowNum]++ ;
    Sum=0;
  }
}



/* שלושת הפונקציות הבאות
מאתחלות מערכים בערכים שליליים
לפני שפונקציות אחרות
משתמשות באותם מערכים
זה עוזר לדעת אם מקומות
מסוימים במערך עדיין לא הישתמשו בהם
כי אנחנו נטען במערכים בהמשך
רק מספרים חיוביים */
void InitWinKeysInL()
{int MySign,TheWinKey,ExPicRows;

 for(MySign=0;MySign<NumObjects;MySign++)
  for(TheWinKey=0;TheWinKey<KeysPerObject;TheWinKey++)
   for(ExPicRows=0;ExPicRows<NumObjects;ExPicRows++)
    WinKeys[MySign][TheWinKey][ExPicRows]= -2 ;
}

void InitArryAttInL()
{int ExPicRowNum;
 for(ExPicRowNum=0;ExPicRowNum<NumObjects;ExPicRowNum++)
   { ArryAtt[ExPicRowNum][0]= -1; /* התכונה */
     ArryAtt[ExPicRowNum][1]= -1 ; /* הציון */
   }
}

void InitScanAttInL()
{int TheFeature,ExPicRowNum;
 for(TheFeature=0;TheFeature<AllComps;TheFeature++)
   for(ExPicRowNum=0;ExPicRowNum<NumObjects;ExPicRowNum++)
   /* שימוש במספר שלילי אחר כי אולי נטען ערכים
   ממערך אחד במערך  שני */
    ScanAtt[TheFeature][ExPicRowNum]= -4 ;
}



/* ScanAtt מצא תכונה מאפינת והצב אותה במערך
 לך לפי שני עקרונות
 יש הבדל משמעותי בציון של התכונה
 עבור העצם והעצם המושווה
 אין הבדל משמעותי בציון של התכונה
 עבור המופעים השונים של אותו עצם
 וגם של העצם המושווה   */
void GradingPerSignInL(int TheSign)
{ int TheFeature,ExPicRowNum;
  int MyAverage,ExAverage;
  int TheVariance,MyVariance,SumVariance,Delta;
  InitScanAttInL();
  for(TheFeature=0;TheFeature<AllComps;TheFeature++)
  { TheVariance=MeanDeltaMap[TheFeature][TheSign];
    MyAverage  =MeanMeanMap[TheFeature][TheSign];
    for(ExPicRowNum=0;ExPicRowNum<NumObjects;ExPicRowNum++)
    {MyVariance =MeanDeltaMap[TheFeature][ExPicRowNum];
     ExAverage  =MeanMeanMap[TheFeature][ExPicRowNum];
     Delta      =AbsDelta(MyAverage,ExAverage);
     SumVariance=MyVariance+TheVariance;
     if((SumVariance <= MaxVariance)&&
        (Delta       >= MinDelta   ))
        /* אם שני העקרונות נכונים
        אנחנו יכולים להסיק משהוא */
      ScanAtt[TheFeature][ExPicRowNum]=
          Delta-SumVariance;
    }/* ExPicRowNum סוף לולאת */
  } /* TheFeature סוף לולאת */
}



/* בדוק אם שתי תכונות דומות */
bool Is2AttsAlikeInL(int Compon1,int Compon2)
{ int Ydelta= RowsPerPic/2;
  int Xdelta= ColsPerPic/2;
int Comp1X1   =  RectsMap[Compon1][0];
int Comp1Y1   =  RectsMap[Compon1][1];
int Comp1X2   =  RectsMap[Compon1][2];
int Comp1Y2   =  RectsMap[Compon1][3];
int Comp2X1   =  RectsMap[Compon2][0];
int Comp2Y1   =  RectsMap[Compon2][1];
int Comp2X2   =  RectsMap[Compon2][2];
int Comp2Y2   =  RectsMap[Compon2][3];
 if  ((AbsDelta(Comp1X1,Comp2X1)< Xdelta)&&
      (AbsDelta(Comp1Y1,Comp2Y1)< Ydelta)&&
      (AbsDelta(Comp1X2,Comp2X2)< Xdelta)&&
      (AbsDelta(Comp1Y2,Comp2Y2)< Ydelta))
      return true;
return false;
}

/* בדוק חפיפה במלבני מרכיבי התכונות
מפני שהתכונות המנצחות
המאפינות אוביקט אחד
נוטות להיות מורכבות ממלבנים
המכסים אותו שטח בתמונה
ואז במקום שהיו לנו שלוש
תכונות לא תלויות
יש לנו 3 תכונות שהן בעצם
תכונה אחת */
bool IsOverlapInL(int MyFeature,
               int Location,int TheSign)
{int TheWinKey , PrevAtt;

for(TheWinKey=0;
    TheWinKey<KeysPerObject;
    TheWinKey++)
{ PrevAtt =  WinKeys[TheSign][TheWinKey][Location];
  /*   אם המרכיב המושווה לא קיים
       לא קרה אסון המשך הלאה */
  if ( PrevAtt > -1 )
  { if ( MyFeature< RecComps &&
         PrevAtt< RecComps    )
       if(Is2AttsAlikeInL(PrevAtt, MyFeature))
         return true;
  }
}
return false;
}

/* בדוק אם התכונה שמצאת
המפתח הקודם משתמש בה
!אל תשתמש בה פעמיים
מפני שאותה תכונה לא תתן
לנו יותר מידע */
bool Is_Not_UsedInL(int MyFeature,int TheSign)
{int MySign,TheWinKey;
 for(MySign=0;MySign<NumObjects;MySign++)
  for(TheWinKey=0;TheWinKey<KeysPerObject;TheWinKey++)
   if(WinKeys[TheSign][TheWinKey][MySign]==MyFeature)
     return false;
 return true;
}
/* עבור כל אוביקט
טען מערך בתכונות המנצחות
השתמש בשתי דרגות קינון
של משפטי תנאי
 בתוך שתי דרגות קינון
 של משפטי לולאה */
void FindComposedAttribInL(int MySign)
{int TheFeature,ExPicRowNum;
 int PreMark,NewMark;
 bool AttDontUsed=true;
 bool RelateCompsDontOverlap=true;

 InitArryAttInL();
 for(TheFeature=0;TheFeature<AllComps;TheFeature++)
   for(ExPicRowNum=0;ExPicRowNum<NumObjects;ExPicRowNum++)
   {NewMark=ScanAtt[TheFeature][ExPicRowNum];
    PreMark=ArryAtt[ExPicRowNum][1];
    if(NewMark > PreMark)
    {AttDontUsed=Is_Not_UsedInL(TheFeature,MySign);
     RelateCompsDontOverlap=!IsOverlapInL(
            TheFeature,ExPicRowNum,MySign);
     if(AttDontUsed && RelateCompsDontOverlap)
     {ArryAtt[ExPicRowNum][0]= TheFeature ;
      ArryAtt[ExPicRowNum][1] = NewMark ;
     }/* סוף התנאי  - לא השתמשו בתכונה */
    } /* סוף התנאי - ציון התכונה טוב יותר */
   } /* סוף הלולאה הכפולה */
}

/* רשום את התכונה המנצחת */
void RegisterAttribInL(int TheKey,int TheSign)
{int MySign;
 for(MySign=0;MySign<NumObjects;MySign++)
  WinKeys[TheSign][TheKey][MySign]=
    /*תכונה , אחרי הנצחון הציון לא מעניין Att <-- [0]  */
      int(ArryAtt[MySign][0]);
}

/* שמור את המפתח המנצח בסוף קובץ */
void ReportAttsInL(int TheSign)
{int MoneKeys,MoneSign,TheAttMark;
 FILE *Rfp2;

 Rfp2=fopen(ReportFile,"a");
 for(MoneSign=0;MoneSign<NumObjects;MoneSign++)
   fprintf(Rfp2,"%5d",TheSign); /* שורת כותרת */
 fprintf(Rfp2,"\n");
 for(MoneKeys=0;MoneKeys<KeysPerObject;MoneKeys++)
 {for(MoneSign=0;MoneSign<NumObjects;MoneSign++)
  {TheAttMark=WinKeys[TheSign][MoneKeys][MoneSign];
   /* ציון לתכונה עבור האוביקט */
   fprintf(Rfp2,"%5d",TheAttMark);
  }
  fprintf(Rfp2,"\n");
  for(MoneSign=0;MoneSign<NumObjects;MoneSign++)
  {TheAttMark=WinKeys[TheSign][MoneKeys][MoneSign];
   fprintf(Rfp2,"%5d",MeanMeanMap[TheAttMark][TheSign]);
  }
  fprintf(Rfp2,"\n");
  for(MoneSign=0;MoneSign<NumObjects;MoneSign++)
  {TheAttMark=WinKeys[TheSign][MoneKeys][MoneSign];
   /* ציון לתכונה עבור האוביקט המושווה */
   fprintf(Rfp2,"%5d",
           MeanMeanMap[TheAttMark][MoneSign]);
  }
  fprintf(Rfp2,"\n");
 }
 fclose(Rfp2);
}

bool NotOnTheSameColOrLineInL(POINT P1,POINT P2)
{ bool Out =true;
  int MaxY= RowsPerPic-1;
  int MaxX= ColsPerPic-1;
  if (P1.y ==P2.y) // שתי הנקודות למעלה או למטה
   if ((P1.y == 0)||(P1.y == MaxY))
     if (AbsDelta(P1.x,P2.x)<MaxX)
      Out =false ;
  if (P1.x ==P2.x)//שתי הנקודות בדופן שמאל או ימין
   if ((P1.x == 0)||(P1.x == MaxX))
    if (AbsDelta(P1.y,P2.y)<MaxY)
      Out =false ;
 return Out;
}


// הנקודות על מסגרת מלבנית
// X | X0 Xmax X2   0
// Y | 0  Y1   Ymax Y3
int GetCupAttsInL(
    int TempRects[AllComps][ComponDefSet])
{ int X,Y,Mone=0;
  POINT P;
  CupDefine WasIn;
  int W = ColsPerPic;
  int L = RowsPerPic;
  const int RecPerimeter= ((W-1)+(L-1))*2  ;
  POINT Points[RecPerimeter];
  P.x =0;
  P.y =0;
  WasIn=Point1;
 for(X=0;X<RecPerimeter;X++)
 { switch(WasIn){
       case Point1: // צלע עליונה
          P.x++;
          break;
       case Point2: // צלע ימנית
          P.y++ ;
          break;
       case Point3: // צלע תחתונה
          P.x-- ;
          break;
       case Point4: // צלע שמאלית
          P.y-- ;
          break;
       }// End Switch
    Points[X].x=P.x ;
    Points[X].y=P.y ;
   if ((P.x==W-1)&&(P.y==0))  WasIn=Point2;
   if ((P.x==W-1)&&(P.y==L-1))WasIn=Point3;
   if ((P.x==0)&&(P.y==L-1))  WasIn=Point4;
  } // End for
 for(X=0;X<RecPerimeter;X++)
  for(Y=0;Y<RecPerimeter;Y++)
   if (NotOnTheSameColOrLineInL(Points[X],Points[Y]))
     {TempRects[Mone][0]=Points[X].x;
      TempRects[Mone][1]=Points[X].y;
      TempRects[Mone][2]=Points[Y].x;
      TempRects[Mone][3]=Points[Y].y;
      Mone++;
    }

for(X=0;X<SumComps+MaxComps;X++)
     for(Y=0;Y<ComponDefSet;Y++)
      TempRects[Mone+X][Y]=0;

 return 1;
}


/* קבץ קבועים למציאת המלבן הנדגם בתמונה */
void GetRecsConstsInL()
{
 FirstPicRow1  = DataRecs[0];
 FirstPicCol1  = DataRecs[1];
 float DeltaX  = DataRecs[2];
 float DeltaY  = DataRecs[3];
 float DeltaX2 = DataRecs[4];
 float DeltaY2 = DataRecs[5];

 PixPerRowDot1 = DeltaX/fXSections;
 PixPerColDot1 = DeltaY/fYSections;
 DeltaRow2Pic1 = DeltaX + DeltaX2;
 DeltaCol2Pic1 = DeltaY + DeltaY2;
}
// :בדוק כשל בזיהוי
// אם אי אפשר להבחין
// בו זוג אותיות בודד
// זיהוי כל האותיות נהרס
int CkeckTheObjectsInL()
{
 int TheSign;
 for(TheSign=0;TheSign<NumObjects;TheSign++)
     CkeckNumKeysInC(TheSign);
 return 1;
}
//////////////////////////////////////
///// חלק 3 התוכנית הראשית ////
/////////////////////////////////////

/* חפש ושמור תכונות */
void FindAttribsInL()
{int MySign,TheWinKey;

 InitWinKeysInL();
 for(MySign=0;MySign<NumObjects;MySign++)
 {
   GradingPerSignInL(MySign);
   for(TheWinKey=0;TheWinKey<KeysPerObject;TheWinKey++)
   {FindComposedAttribInL(MySign); /* מצא 3 תכונות */
    RegisterAttribInL(TheWinKey,MySign);
   }
   ReportAttsInL(MySign);
 }
 SumAllAttsInL();
}


/* הראה תמונה המראה את מופעי העצמים
קרא את גבולות מלבני  מרכיבי התכונות
מצא את התכונות המנצחות לכל עצם */
int MainInitInL(HDC hdc,int Objects_Num)
{int X1,X2,Y1,Y2;
 HDC hdcMemory;
 BITMAP bm;
 HBITMAP hbmRects;

 NumObjects=Objects_Num;
 hbmRects=LoadBMPFileInF(BmpRectsFile);
 GetObject(hbmRects,sizeof(bm),&bm);
 X1=0;Y1=0;X2=bm.bmWidth;Y2=bm.bmHeight;
 hdcMemory=CreateCompatibleDC(hdc);
 SelectObject(hdcMemory,hbmRects);
 BitBlt(hdc,0,0,
        X2,Y2,hdcMemory,X1,Y1,SRCCOPY);
 EmptyFileInF(ReportFile);
 SetCapture(NULL); /* זה עלול לקחת הרבה זמו */
 SetCursor(LoadCursor(NULL,IDC_WAIT)); /* ידע את המשתמש */
 GetCupAttsInL(RectsMap);
 GetRecsConstsInL();
 FillMeanMapInL(hdcMemory,AnyChange,0);
 FillMeanMeanMapInL();
 FillMeanDeltaMapInL();
 FindAttribsInL();
 CkeckTheObjectsInL();
 DeleteDC(hdcMemory);
 ReleaseCapture();
 return 1;
}