//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#pragma hdrstop

#include "GrapFunc.h"
#include "ListConst.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

TGrapFunc    GrapFunc;

/*--------------------------------------------------------*/
void TGrapFunc::pSet(GrapOpt* nop, int n_fun, int n_result, int *index_fun, float *x_result, float **matr_result)
{
   this->x_result = x_result;
   this->matr_result = matr_result;
   this->index_fun = index_fun;
   this->n_fun = n_fun;
   this->n_result = n_result;

   Scale_grap = nop->Scale_grap;
   repy = 0;
   memcpy(marker, "012345", 6);
   mark_size = 5;
   hi = 0;
   hs = 0.75*nop->h_font/Scale_grap;
   H0 = nop->pict_y*Scale_grap;

}
/*--------------------------------------------------------*/
/*   Последовательный вывод функций                       */
/*--------------------------------------------------------*/
void TGrapFunc::pFunc(TMetafileCanvas *pCanvas, GrapOpt* nop)
{
   int i,rc;
   for (i=0; i<n_fun; i++) {
       //strcpy(nop->fi, func[i].fi);
       //strcpy(nop->nf, func[i].nf);
       //strcpy(nop->gf, func[i].gf);
       //strcpy(nop->ei, func[i].ei);
       //nop->mf = func[i].mf;
       nop->mf = 1;
       //marker[0] = func[i].mark[0];
       //mark_size = func[i].mark_size;
       //mark_step = func[i].mark_step;
       //mark_shift = func[i].mark_shift;
      pCanvas->Pen->Width = 2;
      rc = g_fun_out(pCanvas, nop, index_fun[i]);
      pCanvas->Pen->Width = 1;
   }

}
/*--------------------------------------------------------*/
/*   вывод   функции                                      */
/*--------------------------------------------------------*/
int TGrapFunc::g_fun_out(TMetafileCanvas *pCanvas, GrapOpt* nop, int num_fun)
{
    int i;
    float *rez;
    double X0, Y0, x, y, Mt, Mf, mark_shift, yr0, up;
    int j,k,rc;
    double mark_step;
    double max_f, min_f;
    AnsiString format;
    double numf;
    char str_dummy[240];

    j=nop->yr/(2*nop->sty);
    mark_step = nop->stx;
    yr0=j*nop->sty*2;
    max_f=-1e20;
    min_f=1e20;

    format=", max="+(AnsiString)nop->formx+", min="+(AnsiString)nop->formy;
    j = num_fun;  // номер функции
    X0=nop->x;
    Y0=nop->y + yr0*0.5*(nop->py + 1);
    Mf=nop->mf/nop->my[j];
    Mt=1/nop->mx;

    rez = matr_result[0];
    max_f=min_f=rez[j]*nop->mf;

    y = Y0 + (rez[j] - nop->y00)*Mf;
    if (nop->flag_log)
       x = X0 + (x_result[0] - nop->x0)*Mt;
    else {
       if (x_result[0]<=0)
           x=X0;
       else
           x = X0 + (log10(x_result[0]) - nop->x0)*Mt;
    }
    g_ot_(pCanvas, x, y);
    mark_shift = (num_fun+1)*mark_step*0.1;   // начальный сдвиг маркера
    for (i = 1;  i< n_result; i++)   {
        rez = matr_result[i];

        max_f = MAX(max_f, rez[j]*nop->mf);
        min_f = MIN(min_f, rez[j]*nop->mf);
        y = Y0 + (rez[j] - nop->y00)*Mf;
        if (!nop->flag_log)
           x = X0 + (x_result[i] - nop->x0)*Mt;
        else {
           if (x_result[i]<=0)
                x=X0;
           else
                x = X0 + (log10(x_result[i]) - nop->x0)*Mt;
        }
        g_bot_(pCanvas,x, y);
        if (nop->flag_marker) {
           if (x > mark_shift)  {
               g_mout_(pCanvas,x,y);
               mark_shift += mark_step;
           }
        }
    }
    x += 1;
    g_str_(pCanvas, x, y, nop->gf[j]);
    pCanvas->Pen->Width=1;
    numf = 7.0;
    //if (nop->flag_scale)  {
    //    up = numf + 2;
    //    g_ot_(pCanvas,nop->x,nop->y - up - 0.5*hs);
    //    g_bot_( pCanvas,nop->x + 20, nop->y - up - 0.5*hs);
    //    g_mout_(pCanvas,nop->x + 10, nop->y - up );
    //    sprintf(str_dummy," %8s - %25s, масштаб 1 мм = %8.2f %s", nop->nf[j], nop->gf[j], nop->my[j],
    //        nop->ei[j]);
    //    g_str_(pCanvas,nop->x + 20,nop->y - up - hi, str_dummy);
    //    numf += hs+2;
    //}
    if (nop->flag_max_min) {
        up = numf+ 2;
        g_ot_(pCanvas,nop->x,nop->y - up - 0.5*hs);
        g_bot_( pCanvas,nop->x + 10, nop->y - up - 0.5*hs);
        g_ot_(pCanvas,nop->x+5,nop->y - up - 0.5*hs);
        g_mout_(pCanvas,nop->x + 5, nop->y - up );
        if (nop->ei[0][j]=='.')
           sprintf(str_dummy,"  %s ",nop->gf);
        else {
           sprintf(str_dummy,"  %s (%s)",nop->gf[j],nop->ei[j]);
        //if (flag_q>1) {  // вывод MAX/MIN
           sprintf(str_dummy+strlen(str_dummy),format.c_str(),max_f, min_f);
           g_str_(pCanvas, nop->x + 15,nop->y - up -hi*0.75 , str_dummy);
        }
        g_str_(pCanvas,nop->x + 15,nop->y - up -hi*0.75 , str_dummy);
        numf += hs+2;
    }

    return 0;
}   // g_fun_
/*--------------------------------------------------------*/
/*   Установка шрифта                                     */
/*--------------------------------------------------------*/
void TGrapFunc::pFont(TMetafileCanvas *pCanvas, GrapOpt* nop)
{
   int h;
   TFont * TheFont;

   TheFont = new TFont();
   TheFont->Name = (AnsiString)nop->NameFont;
   TheFont->Height = (int)nop->h_font;
   if (nop->flag_italic)
      TheFont->Style=TFontStyles()<<fsItalic;
   pCanvas->Font=TheFont;
   //h=pCanvas->Font->Height;
}
/*--------------------------------------------------------*/
/*   сетка                                                */
/*--------------------------------------------------------*/
void TGrapFunc::pSetka(TMetafileCanvas *pCanvas, GrapOpt* nop)
{
    double t;
    int j, i, it;
    double xx, yy, ss;
    int num_dev;

        num_dev = 1;
        for (t = nop->x; t < nop->x + nop->xr; t += nop->stx ) {
            g_ot_(pCanvas, (double) t, (double)nop->y);
            g_bot_(pCanvas, (double) t, (double)(nop->y + nop->yr));
            if (nop->flag_log) {
                t = it;
                xx=nop->stx*nop->mx;
                ss=pow(10e0,xx);
                yy=ss/num_dev;
                for (i=1, ss=yy; i<num_dev; i++) {
                    xx=log10(ss);
                    xx /= nop->mx;
                    g_ot_(pCanvas,t+xx, nop->y);
                    g_bot_(pCanvas,t+xx, nop->y + nop->yr);
                    ss += yy;
                }
            }
        }
        g_ot_(pCanvas, (double) (nop->x+nop->xr), (double)nop->y);
        g_bot_(pCanvas,nop->x+nop->xr, nop->y + nop->yr);
        for (t=nop->y; t < nop->y + nop->yr; t += nop->sty)
        {
            g_ot_(pCanvas,nop->x, t);
            g_bot_(pCanvas,nop->x + nop->xr, t);
        }
        g_ot_(pCanvas,nop->x, nop->y + nop->yr);
        g_bot_(pCanvas,nop->x + nop->xr, nop->y + nop->yr);
}
/*--------------------------------------------------------*/
/*   Вывод текста                                                */
/*--------------------------------------------------------*/
void TGrapFunc::pText(TMetafileCanvas *pCanvas, GrapOpt* nop)
{
    int j,i;
    double x,y;

    for (i=0; i<n_text; i++) {
      g_str_(pCanvas, x_text[i], y_text[i], out_text[i]);
   }
}
/*--------------------------------------------------------*/
/*   Оформление оси X                                     */
/*--------------------------------------------------------*/
void TGrapFunc::pAx_X(TMetafileCanvas *pCanvas, GrapOpt* nop)
{
    double t,x,y;
    double yr0;
    char str[124];
    int j,l;
    double xx,yy;

    j=nop->yr/(2*nop->sty);
    yr0=j*nop->sty*2;
    x = nop->x;
    y = nop->y + yr0*(nop->pf+1)*0.5 - nop->h_font + 1;
    if (!nop->flag_log) {
        for (t=x+nop->stx+1; t<=x+nop->xr+1; t += nop->stx) {
            sprintf(str,nop->formx,(t-nop->x-1)*nop->mx + nop->x0);
            g_vir_(pCanvas,t,y,str);
        }
    }
    else {
        for (t=x+1; t<=x+nop->xr+1; t += nop->stx) {
            xx = (t-nop->x-1)*nop->mx + nop->x0;
            yy=pow(10e0,xx);
            sprintf(str,nop->formx,yy);
            g_vir_(pCanvas,t,y,str);
        }
    }
    t= x+nop->xr+1;
    y = nop->y + yr0*(nop->pf+1)*0.5 + 1 + nop->h_font;
    g_str_(pCanvas,t,y,nop->gx);
    return;
}
/*--------------------------------------------------------*/
/*   оформление оси y                                     */
/*--------------------------------------------------------*/
void TGrapFunc::pAx_Y(TMetafileCanvas *pCanvas, GrapOpt* nop)
{
    double t,x,y;
    double yr0;
    double ss;
    char str[120];
    int i, j, k;

    repy=0;
    j=nop->yr/(2*nop->sty);
    yr0=j*nop->sty*2;
    x = nop->x - 1 + repy;
    y = nop->y;
    if (repy != 0)
    {
        g_ot_(pCanvas,x+1,y);
        g_bot_(pCanvas,x+1,y+yr0);
    }
    k = index_fun[0];
    //g_an(90e0);
    for (t=y; t<=y+nop->yr+1; t += nop->sty)
    {
        if (repy != 0)
        {
            g_ot_(pCanvas,x-nop->h_font/2+1,t);
            g_bot_(pCanvas,x+nop->h_font/2+1,t);
        }
        ss = (t-nop->y-yr0*0.5*(nop->py+1))*nop->my[k] + nop->y00;
        sprintf(str,nop->formy,ss);
        for (i=0; i<9; i++)
            if (str[i] != ' ')
                break;
        g_str_(pCanvas,x + 0.5*hs, t+0.5, str+i);
    }
    t -= nop->sty;
    g_str_(pCanvas,x+1+hi , t+10, nop->ny);
    repy -= nop->stx*0.75;
    //g_an(nop->an);
}
//------------------------------------
void TGrapFunc::g_vir_(TMetafileCanvas *pCanvas, double t, double y, char *str)
{
    char *st0;
    int i,l;
    st0=strchr(str,(int)'.');
    if (st0 != NULL) {
        l=strlen(str);
        for (i=l-1; i>0; i--)
            if (str[i]!='0') break;
        str[i+1]='\0';
    }
    for (i=0; i<9; i++)
        if (str[i] != ' ')
            break;
    g_str_(pCanvas,t,y,str+i);
}
//--------------------------------------------------------
void TGrapFunc::g_ot_(TMetafileCanvas *pCanvas, double x, double y) {
    bx=x;
    by=y;
}
//--------------------------------------------------------
void TGrapFunc::g_bot_(TMetafileCanvas *pCanvas, double x, double y) {
    double dy = ABS(y-by);
    if (dy > 10)
    if ((x-bx)/dy <0.01)
       x = bx;
    pCanvas->MoveTo((int)(bx*Scale_grap), H0-(int)(by*Scale_grap) );
    pCanvas->LineTo((int)(x*Scale_grap), H0-(int)(y*Scale_grap) );
    bx=x;
    by=y;
}
/*--------------------------------------------------------*/
/*   вывод   строки                                       */
/*--------------------------------------------------------*/
void TGrapFunc::g_str_(TMetafileCanvas *pCanvas,double x, double y, char *str)
{
      pCanvas->TextOut((int)(x*Scale_grap), H0 - (int)(y*Scale_grap),
                       (AnsiString)str);
}
/*--------------------------------------------------------*/
/*   вывод   маркера                                      */
/*--------------------------------------------------------*/
void TGrapFunc::g_mout_(TMetafileCanvas *pCanvas, double x, double y)
{
    if (marker[0] != '0')
    {
      switch (marker[0]) {
      case 'A': g_cyrc_(pCanvas,0.5*mark_size);
      break;
      case 'B': g_squar_(pCanvas);
      break;
      case 'C': g_trian_(pCanvas,1.0);
      break;
      case 'D': g_smul_(pCanvas);
      break;
      case 'E': g_ssum_(pCanvas);
      break;
      case 'F':
           g_squar_(pCanvas);g_smul_(pCanvas);
      break;
      case 'G':
           g_squar_(pCanvas);g_ssum_(pCanvas);
      break;
      case 'H':
           g_squar_(pCanvas);g_cyrc_(pCanvas,0.5*mark_size);
      break;
      case 'I':
           g_cyrc_(pCanvas,0.5*mark_size);g_ssum_(pCanvas);
      break;
      case 'J':
           g_cyrc_(pCanvas,0.5*mark_size);g_smul_(pCanvas);
      break;
      case 'K':
           g_cyrc_(pCanvas,0.5*mark_size);g_trian_(pCanvas,1.0);
      break;
      default:
           g_trian_(pCanvas,1.0); g_trian_(pCanvas,-1.0);
      }
    }

}  /* g_mout */
/*--------------------------------------------------------*/
/*   Окружность                                           */
/*--------------------------------------------------------*/
void TGrapFunc::g_cyrc_(TMetafileCanvas *pCanvas,double rad)
{
     pCanvas->Brush->Style=bsClear;
     pCanvas->Ellipse((int)((bx-rad)*Scale_grap), H0-(int)((by-rad)*Scale_grap),
                    (int)((bx+rad)*Scale_grap), H0-(int)((by+rad)*Scale_grap));
     pCanvas->Brush->Style=bsSolid;
}
/*--------------------------------------------------------*/
/*   прямоугольник                                        */
/*--------------------------------------------------------*/
void TGrapFunc::g_squar_(TMetafileCanvas *pCanvas)
{
     double u,v,ut,vt;

     u=bx;
     v=by;

     bx -= mark_size*0.5;
     ut = bx;
     by -= mark_size*0.5;
     vt = by;
     g_bot_(pCanvas,ut,vt+mark_size);
     g_bot_(pCanvas,ut+mark_size,vt+mark_size);
     g_bot_(pCanvas,ut+mark_size,vt);
     g_bot_(pCanvas,ut,vt);
     bx=u; by=v;
}
/*--------------------------------------------------------*/
/*   треугольник                                          */
/*--------------------------------------------------------*/
void TGrapFunc::g_trian_(TMetafileCanvas *pCanvas,double ss)
{
     double u,v,ut,vt,h;

     h = mark_size*ss;
     u = bx;
     v = by;
     bx -= h*0.5*0.866;
     ut = bx;
     by -= h*0.25;
     vt = by;
     g_bot_(pCanvas,u,v+h*0.5);
     g_bot_(pCanvas,ut+h*0.866,vt);
     g_bot_(pCanvas,ut,vt);
     bx=u; by=v;
}
/*--------------------------------------------------------*/
/*   крест - умножение                                    */
/*--------------------------------------------------------*/
void TGrapFunc::g_smul_(TMetafileCanvas *pCanvas)
{
     double u,v,g;
     u=bx;
     v=by;
     g= mark_size*0.5;
     bx -= g;
     by -= g;
     g_bot_(pCanvas,u+g,v+g);
     bx = u + g;
     by = v - g;
     g_bot_(pCanvas,u-g,v+g);
     bx=u;by=v;
}
/*--------------------------------------------------------*/
/*   крест - cложение                                     */
/*--------------------------------------------------------*/
void TGrapFunc::g_ssum_(TMetafileCanvas *pCanvas)
{
     double u,v,g;
     u=bx;
     v=by;
     g= mark_size*0.5;
     by -= g;
     g_bot_(pCanvas,u,v+g);
     bx = u - g;
     by = v;
     g_bot_(pCanvas,u+g,v);
     bx=u;by=v;
}











