unit uexploradorCF;

{$MODE Delphi}

interface

uses
  SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls,
  xmatdefs, uEstados, ufechas, AlgebraC, MatReal, MatCPX, IntPoint,
  isocurvas, utrazosxy, usigmoide, uneuronas,
  utipos_xcf,
  ufxgx, uresfxgx, uproblema,
  uescalacolores, uparseadorsupersimple, uauxiliares, Math,
  u_kml_map_util,
  u_latlon_utm,
  ugoogle_altitude;

type

  { TForm1 }

  TForm1 = class(TForm)
    btAproxNeuron01: TButton;
    btBellmanParaOpergen: TButton;
    btCalcAproLin: TButton;
    btCFSelect: TButton;
    btCF_div_10: TButton;
    btCompararCFs: TButton;
    btCopiarYTranspornerUltima7Filas: TButton;
    btDumpPrimerFrame_2CFs: TButton;
    bTest02: TButton;
    btIsoCurvas: TButton;
    btTest01: TButton;
    btVer: TButton;
    bt_DumpToXlt: TButton;
    btLoadCF: TButton;
    btDibujarNeuronas: TButton;
    btCrearCerebro: TButton;
    btScanAltitudes: TButton;
    Button1: TButton;
    btCompress16: TButton;
    cbAuto: TCheckBox;
    cbSaveCerebro: TCheckBox;
    ekPaso: TEdit;
    eNeuronasPorCapa: TLabeledEdit;
    ePaso: TEdit;
    eValCosto: TEdit;
    eDimensionEspacioX: TLabeledEdit;
    eFechaIni: TLabeledEdit;
    eFechaFin: TLabeledEdit;
    ekPasoT: TLabeledEdit;
    eFechaDelPasoT: TLabeledEdit;
    eNPasosT: TLabeledEdit;
    memo_scanaltitudes: TMemo;
    nPuntosLon: TLabeledEdit;
    nPuntosLat: TLabeledEdit;
    Lon2: TLabeledEdit;
    Lat2: TLabeledEdit;
    Lon1: TLabeledEdit;
    Lat1: TLabeledEdit;
    Memo1: TMemo;
    mseval: TMemo;
    OpenDialog1: TOpenDialog;
    PageControl1: TPageControl;
    PaintBox1: TPaintBox;
    PaintBox2: TPaintBox;
    sbKPaso: TScrollBar;
    sbKPaso1: TScrollBar;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    procedure btAproxNeuron01Click(Sender: TObject);
    procedure btCalcAproLinClick(Sender: TObject);
    procedure btCFSelectClick(Sender: TObject);
    procedure btCompress16Click(Sender: TObject);
    procedure btCrearCerebroClick(Sender: TObject);
    procedure btDibujarNeuronasClick(Sender: TObject);
    procedure btIsoCurvasClick(Sender: TObject);
    procedure btScanAltitudesClick(Sender: TObject);
    procedure btTest01Click(Sender: TObject);
    procedure btVerClick(Sender: TObject);
    procedure bt_DumpToXltClick(Sender: TObject);
    procedure btBellmanParaOpergenClick(Sender: TObject);
    procedure btCopiarYTranspornerUltima7FilasClick(Sender: TObject);
    procedure btCF_div_10Click(Sender: TObject);
    procedure btCompararCFsClick(Sender: TObject);
    procedure btDumpPrimerFrame_2CFsClick(Sender: TObject);
    procedure bTest02Click(Sender: TObject);
    procedure btLoadCFClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure cbAutoChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: integer);
    procedure sbKPaso1Change(Sender: TObject);
    procedure sbKPasoChange(Sender: TObject);
  private
    procedure PlotIsoCurvas(M: TMatR; vx, vy: TVectR; M2: TMatR;
      vx2, vy2: TVectR; niveles: array of NReal; etiquetas: array of string);
    { Private declarations }
  public
    { Public declarations }
    CF: TAdminEstados;
    kPasoT: integer;
    evaluador: TEvaluadorExpresionesSimples;
    mcf: TMatR;
    vx, vy: TVectR;
    mcf2: TMatR;
    vx2, vy2: TVectR;
    niveles: TDAOfNReal;
    etiquetas: TDAOfString;
    escalaColor: TEscalaColor;

    // dimensiones del esapcio de estado del CF cargado.
    Dim_EspacioX: integer;
    Cerebro: TCerebro;

    // Para exportar un KML
    aDoc_KML: TKML_Document;

  end;



var
  Form1: TForm1;

implementation

{$R *.lfm}


procedure TForm1.btBellmanParaOpergenClick(Sender: TObject);
var
  archi: string;
  fCosto: TMatOfNReal;
  nPasos, nEstrellas: integer;
  kPasoT: integer;
  anio, semana, H, Stock: integer;
  dCFdX_Inc, dCFdX_Dec: NReal;
  fecha: TFecha;
  semana_: integer;
  fsal_bellman: textfile;
  error_str: string;
  CF1, CF2: NReal;

begin

  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    archi := OpenDialog1.FileName;
    CF := TAdminEstados.CreateLoadFromArchi(archi);

    // antes de seguir chequeamos que se trate de una CF
    // con solo dos variables de estado y que sean Bonete y H en ese orden.
    error_str := '';
    if CF.nVarsContinuas <> 2 then
      error_str := error_str + '; CF.nVarsContinuas <> 2';
    if CF.nVarsDiscretas <> 0 then
      error_str := error_str + '; CF.nVarsDiscretas <> 2';
    if CF.xr_def[0].NPuntos <= 1 then
      error_str := error_str + '; CF.xr_def[0].NPuntos <= 1';
    if CF.xr_def[0].nombre <> 'Bonete_Vol' then
      error_str := error_str + '; CF.xr_def[0].nombre <> ''Bonete_Vol''';
    if CF.xr_def[1].nombre <> 'Estado_H' then
      error_str := error_str + '; CF.xr_def[1].nombre <> ''Estado_H''';
    if error_str <> '' then
    begin
      CF.Free;
      CF := nil;
      raise Exception.Create('El archivo CF.bin no tiene las definiciones esperadas.' +
        error_str);
    end;

    fecha := TFecha.Create_Clone(CF.fechaIni);
    fCosto := CF.constelacion.fCosto;
    nPasos := length(fCosto);
    nEstrellas := length(fCosto[0]);


    assignfile(fsal_bellman, 'bellman_paraOperGen.txt');
    rewrite(fsal_bellman);

    semana_ := 0;
    for kPasoT := 1 to nPasos - 1 do
    begin
      anio := fecha.anio;
      semana := fecha.semana52;
      if semana_ <> semana then
      begin
        semana_ := semana;
        for H := 1 to CF.xr_def[1].NPuntos do
          for Stock := 0 to CF.xr_def[0].NPuntos - 1 do
          begin
(*
            // Posicionamos el estado Borde inferior del stock
            CF.xr[0] := CF.xr_def[0].x[stock - 1];
            CF.xr[1] := CF.xr_def[1].x[H - 1];
            // Guardamos el valor de Bellman en el extremo inferior
            CF1      := CF.costoContinuo(kPasoT);
*)
            // Posicionamos el estado Borde superior del stock
            CF.xr[0] := CF.xr_def[0].x[stock];
            CF.xr[1] := CF.xr_def[1].x[H - 1];
            // Guardamos el valor de Bellman en el extremo inferior
            CF2 := CF.costoContinuo(kPasoT);


          (*  imprimimos según formato enviado por Milton
          AÑO      NUMBER(4)
          SEMANA   NUMBER(2)
          CLASE    NUMBER(2)
          PASO     NUMBER(2)
          BELLMAN  NUMBER(15,3)
           *)
           (*
            writeln(fsal_bellman, anio: 4, ' ', semana: 2, ' ', H: 2, ' ',
              Stock: 2, (CF1 + CF2) / 2.0: 15: 3);
*)
            writeln(fsal_bellman, anio: 4, ' ', semana: 2, ' ', H: 2, ' ',
              Stock: 2, CF2: 15: 3);

          end;
      end;
      fecha.dt := fecha.dt + CF.horasDelPaso / 24.0;
    end;
    closefile(fsal_bellman);
  end;
end;

procedure TForm1.bt_DumpToXltClick(Sender: TObject);
var
  archi: string;
  fCosto: TMatOfNReal;
  nPasos, nEstrellas: integer;
  k, j: integer;
begin
  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    archi := OpenDialog1.FileName;
    CF := TAdminEstados.CreateLoadFromArchi(archi);
    CF.dumpToTextFile('c:\basura\cf.xlt');
    CF.Free;
    CF := nil;
  end;
end;

procedure TForm1.btCalcAproLinClick(Sender: TObject);
var
  archi: string;
  kPasoT: integer;

  XXt: TMatR;
  XYt: TMatR;
  N: integer;
  x: TVectR;
  y: NReal;
  jj, j: integer;

  res: boolean;
  exp10: integer;

  vectores_A: TDAofVectR;
  k: integer;
  aProm: TVectR;
  avr: TVectR;

  fsal: textfile;

  minCF, maxCF, deltaCF: NReal;

begin
  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    archi := OpenDialog1.FileName;
    CF := TAdminEstados.CreateLoadFromArchi(archi);

    N := CF.nVarsContinuas + CF.nVarsDiscretas + 1;
    XXt := TMatR.Create_Init(N, N);
    XYt := TMatR.Create_Init(N, 1);
    x := TVectR.Create_Init(N);


   CF.constelacion.CalcMinMax( minCF, maxCF );
   deltaCF:= (maxCF - minCF)/1e6;



    setlength(vectores_A, CF.nPuntosT - 1);
    for kPasoT := 1 to CF.nPuntosT - 1 do
    begin
      XXt.Ceros;
      XYt.Ceros;
      CF.setEstrellaCERO;
      repeat
        CF.SetEstadoToEstrella;
        y := CF.costoEstrella(kPasoT)/1e6;

        x.pon_e(1, 1);
        jj := 2;

        for j := 0 to CF.nVarsContinuas - 1 do
        begin
          x.pon_e(jj, (CF.xr[j] - CF.xr_def[j].minval)/CF.xr_def[j].deltaval );
          Inc(jj);
        end;

        for j := 0 to CF.nVarsDiscretas - 1 do
        begin
          x.pon_e(jj, ( CF.xd[j] - CF.xr_def[j].minval )/CF.xd_def[j].deltaval );
          Inc(jj);
        end;

        for k := 1 to N do
        begin
          for j := 1 to N do
            XXt.acum_e(k, j, x.e(k) * x.e(j));
          XYt.acum_e(k, 1, x.e(k) * y);
        end;

      until not CF.IncEstrella;

      XXt.Escaler(XYt, res, exp10);
      if not res then
        raise Exception.Create('No se puede resolver por mínimos cuadrados!!!');

      vectores_A[kPasoT - 1] := TVectR.Create_Init(N);
      XYt.CopyColVect(vectores_A[kPasoT - 1], 1);

    end; // Recorrido de los pasos T.

    assignfile(fsal, 'aproplin_CF.xlt');
    rewrite(fsal);

    aProm := TVectR.Create_Init(N);
    aProm.Ceros;

    Write(fsal, 'vmin');
    for j := 1 to N do
    begin
      if j = 1 then
        Write(fsal, #9, minCF )
      else if (j - 2) <= high(CF.xr_def) then
        Write(fsal, #9, CF.xr_def[j-2].minval)
      else
        Write(fsal, #9, CF.xd_def[j - 2 - length(CF.xr_def)].minval);
    end;
    writeln(fsal);

    Write(fsal, 'Rango');
    for j := 1 to N do
    begin
      if j = 1 then
        Write(fsal, #9, deltaCF )
      else if (j - 2) <= high(CF.xr_def) then
        Write(fsal, #9, CF.xr_def[j - 2].deltaval)
      else
        Write(fsal, #9, CF.xd_def[j - 2 - length(CF.xr_def)].deltaval );
    end;
    writeln(fsal);


    Write(fsal, 'Fecha');
    for j := 1 to N do
    begin
      if j = 1 then
        Write(fsal, #9, 'a0')
      else if (j - 2) <= high(CF.xr_def) then
        Write(fsal, #9, CF.xr_def[j - 2].nombre)
      else
        Write(fsal, #9, CF.xd_def[j - 2 - length(CF.xr_def)].nombre);

    end;
    writeln(fsal);

    for k := 0 to high(vectores_A) do
    begin
      Write(fsal, DateTimeToIsoStr(CF.fechaIni.dt + CF.horasDelPaso * k / 24.0));
      avr := vectores_A[k];
      for j := 1 to N do
      begin
        Write(fsal, #9, avr.e(j));
        aProm.acum_e(j, avr.e(j));
      end;
      writeln(fsal);
    end;

    writeln(fsal, '---------------- PROMEDIO ----------------');

    for j := 1 to N do
      Write(fsal, #9, aProm.e(j) / length(vectores_A));

    writeln(fsal);
    closefile(fsal);
  end;
end;

// Calcula la salida del conjunto de neuronas
function Calc_CFAprox(const alfa: TDAOfVectR; const x0, c_min, dc: TDAOfNReal;
  const X: TVectR; Nivel: integer // 1..NNeuronas nivel a considerar
  ): NReal;
var
  kNeurona: integer;
  res: NReal;
  SalidaAnterior, z, Salida: NReal;
begin
  Salida := 0;
  for kNeurona := Nivel - 1 downto 0 do
  begin
    SalidaAnterior := Salida;
    z := alfa[kNeurona].PEV(X) - x0[kNeurona] + SalidaAnterior;
    Salida := c_min[kNeurona] + sigmoide(z) * dc[kNeurona];
  end;
  Result := Salida;
end;

procedure TForm1.btAproxNeuron01Click(Sender: TObject);
var
  XCF: TDAOfRecXCF;
  aRec: TRecXCF;
  dimX: integer;
  k, j: integer;
  alfa: TDAOfVectR;

  x0, c_min, dc: NReal;

  sal: TextFile;
  nivel: integer;
  CFAprox: NReal;

  arrNeuronasPorCapa: TDAOfNInt;
  cerebro: TCerebro;
  kRec, jEntrada, kNeurona: integer;
  derr: TDAofNReal;

  NIters: integer;
  kIter: integer;
  paso, normGrad: NREal;
  abs_eprom, eprom: NReal;
  cnt_ok: integer;
  ADN: TDAOfNReal;

  CFX_Entrenador: TCF_fEntrenador;

  f0, fs: NReal;
  resErr: NReal;
  resNIters: integer;
  resValCosto, resValLagrangiana, resdFrontera2: NReal;
  resConvergio: boolean;
  NCapas: integer;
  cnt_Exitos: integer;

  kCapa, kNeuron: integer;
  aNeurona: TNeuronaConEntradas;
  min_resValCosto: NReal;

begin
  kPasoT:= 1;

  setlength(XCF, CF.nEstrellasPorPuntoT);
  dimX := CF.nVarsContinuas + CF.nVarsDiscretas;
  CF.setEstrellaCERO;
  repeat
    CF.SetEstadoToEstrella;
    aRec := TRecXCF.Create(dimX, 1);
    for k := 0 to CF.nVarsContinuas - 1 do
      aRec.X.pon_e(k + 1, CF.xr[k]);
    for k := 0 to CF.nVarsDiscretas - 1 do
      aRec.X.pon_e(k + CF.nVarsContinuas, CF.xd[k]);
    aRec.CF := CF.costoEstrella(kPasoT) / 1.0E6;
    XCF[CF.ordinalEstrellaActual] := aRec;
  until not CF.IncEstrella;
  NCapas := 2;

  setlength(arrNeuronasPorCapa, NCapas);
  setlength(derr, 1);

  for k := 0 to high(arrNeuronasPorCapa) - 1 do
    arrNeuronasPorCapa[k] := DimX;
  arrNeuronasPorCapa[high(arrNeuronasPorCapa)] := 1;

  Normalizar_conjuntoXCF(c_min, dc, XCF, 0.7);

  cerebro := TCerebro.Create(dimX, // Cantidad de entradas
    arrNeuronasPorCapa, // Cantidad de capas (sin contar la entrada)
    True); // Indica si saturar la salida de la última capa.

  PaintBox2.Canvas.Pen.color := ClRed;
  PaintBox2.Canvas.MoveTo(0, PaintBox2.Height - 1);
  for kRec := 0 to high(XCF) do
  begin
    aRec := XCF[kRec];
    PaintBox2.Canvas.LineTo(trunc(kRec / length(XCF) * PaintBOx2.Width),
      trunc(PaintBox2.Height * (1 - aRec.CF)));
  end;

  application.ProcessMessages;

  randomize;
  Cerebro.RandomInit(0.01);
  //  Cerebro.Iniciar_OptUltimaNeurona(XCF);


  PaintBox2.Canvas.Pen.color := ClGreen;
  PaintBox2.Canvas.MoveTo(0, PaintBox2.Height - 1);
  for kRec := 0 to high(XCF) do
  begin
    aRec := XCF[kRec];
    Cerebro.SetEntradas(aRec.X);
    Cerebro.evaluar;
    CFAprox := Cerebro.Salida_CapaN.Neuronas[0].salida;

    PaintBox2.Canvas.LineTo(
      trunc(kRec / length(XCF) * PaintBOx2.Width),
      trunc(PaintBox2.Height * (1 - CFAprox))
      );
  end;


  writeln('Inicio Opt por Problema ... ');
  Paso := 0.1;
  PaintBox2.Canvas.Pen.color := ClYellow;
  PaintBox2.Canvas.Pen.Width := 4;
  aRec := XCF[0];
  PaintBox2.Canvas.MoveTo(0, trunc(PaintBox2.Height * (1 - aRec.CF)));
  for kRec := 1 to high(XCF) do
  begin
    aRec := XCF[kRec];
    PaintBox2.Canvas.LineTo(trunc(kRec / length(XCF) * PaintBOx2.Width),
      trunc(PaintBox2.Height * (1 - aRec.CF)));
  end;

  kCapa := 0;
  kNeurona := 0;
  for kIter := 1 to 100000 do
  begin
    (*
    resValCosto := EntrenarCerebro(Cerebro, XCF, 10, resConvergio,
      resNIters, kCapa, kNeurona);
      *)
resValCosto :=EntrenarCerebro_EBP( Cerebro, // Cerebro
  XCF,  // Datos de entrenamiento
  paso );
(*

 resValCosto :=EntrenarCerebro_rnd( Cerebro, // Cerebro
  XCF,  // Datos de entrenamiento
  12, // Número máximo de iteracciones
  paso,  cnt_Exitos );
  *)

  if kIter = 1 then
    min_resValCosto:= resValCosto;

    if resValCosto <  min_resValCosto then
    begin
      min_resValCosto:= resValcosto;
      paso := paso * 1.5;
      eValCosto.Text := FloatToStr(resValCosto);

      PaintBox2.Canvas.Pen.color := ClYellow;
      PaintBox2.Canvas.Pen.Width := 4;
      aRec := XCF[0];
      PaintBox2.Canvas.MoveTo(0, trunc(PaintBox2.Height * (1 - aRec.CF)));
      for kRec := 1 to high(XCF) do
      begin
        aRec := XCF[kRec];
        PaintBox2.Canvas.LineTo(trunc(kRec / length(XCF) * PaintBOx2.Width),
          trunc(PaintBox2.Height * (1 - aRec.CF)));
      end;

      if (kIter mod 2 )= 1 then
        PaintBox2.Canvas.Pen.color := ClGreen
      else
        PaintBox2.Canvas.Pen.color := clFuchsia;

      PaintBox2.Canvas.Pen.Width := 4;
      PaintBox2.Canvas.MoveTo(0, PaintBox2.Height - 1);
      for kRec := 0 to high(XCF) do
      begin
        aRec := XCF[kRec];
        for jEntrada := 0 to dimX - 1 do
          Cerebro.SetEntrada(jEntrada, aRec.X.e(jEntrada + 1));
        Cerebro.evaluar;
        CFAprox := Cerebro.Salida_CapaN.Neuronas[0].salida;

        PaintBox2.Canvas.LineTo(
          trunc(kRec / length(XCF) * PaintBOx2.Width),
          trunc(PaintBox2.Height * (1 - CFAprox))
          );
      end;
    end
    else
      Paso := 0.7 * paso;

    aNeurona := Cerebro.ProximaNeuronaConEntradas(kCapa, kNeurona);
    if aNeurona = nil then
      aNeurona := Cerebro.PrimerNeuronaConEntradas(kCapa, kNeurona);

    application.ProcessMessages;
  end;

  setlength(arrNeuronasPorCapa, 0);
  setlength(derr, 0);
  Cerebro.StoreInArchi('cerebro_mp.txt');
  Cerebro.Free;

end;

procedure TForm1.btCFSelectClick(Sender: TObject);
var
  i: integer;
begin
  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    if evaluador <> nil then
    begin
      evaluador.Free;
      evaluador := nil;
    end;

    if vx <> nil then
    begin
      vx.Free;
      vy.Free;
      mcf.Free;
    end;

    vx := TVectR.Create_INit(PaintBox1.Width);
    vy := TVectR.Create_init(PaintBox1.Height);
    mcf := TMatR.Create_Init(PaintBox1.Width, PaintBox1.Height);


    CF := TAdminEstados.CreateLoadFromArchi(OpenDialog1.FileName);
    eFechaIni.Text := CF.fechaIni.AsStr;
    eFechaFin.Text := CF.fechaFin.AsStr;
    eNPasosT.Text := IntToStr(CF.nPuntosT);
    kPasoT := 0;
    ekPasoT.Text := IntToStr(0);
    eFechaDelPasoT.Text := DateTimeToStr((CF.fechaFin.dt - CF.fechaIni.dt) /
      (CF.nPuntosT - 1));



    Dim_EspacioX := CF.nVarsContinuas + CF.nVarsDiscretas;

    sbkPaso.Min := 1;
    sbkPaso.Max := CF.nPuntosT;

    evaluador := TEvaluadorExpresionesSimples.Create;


    memo1.Append(CF.VariablesDeEstado_lst.Text);


    //inicializamos variables "X" en entorno de cálculo
    for i := 0 to CF.nVarsContinuas - 1 do
    begin
      evaluador.Ejecutar('$X_' + CF.xr_Def[i].nombre + ':= 0.0;');

      if CF.xr_Def[i].traduccion <> nil then
        evaluador.Ejecutar('$T_' + CF.xr_Def[i].Traduccion.nombre + ':= 0.0;');

      mseval.Lines.add('$X_' + CF.xr_Def[i].nombre + ':= ' +
        FloatToStr(CF.xr_Def[i].minval) + ' + ' +
        FloatToStr(CF.xr_Def[i].deltaval) + ' * x + 1.0 * y;');

    end;

    for i := 0 to CF.nVarsDiscretas - 1 do
    begin
      evaluador.Ejecutar('$X_' + CF.xd_Def[i].nombre + ':= 0;');
      if CF.xd_Def[i].traduccion <> nil then
        evaluador.Ejecutar('$T_' + CF.xd_Def[i].nombre + ':= 0;');
      mseval.Lines.add('$X_' + CF.xr_Def[i].nombre + ':= 0.0 + 1.0 * x + 1.0 * y;');
    end;

    // Inicializamos variables
    evaluador.Ejecutar('x := 0.0');
    evaluador.Ejecutar('y := 0.0');

  end;
end;

procedure TForm1.btCompress16Click(Sender: TObject);
var
  camino: string;
  nombre: string;
  archi, archi_dest: string;
begin
  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    archi := OpenDialog1.FileName;
    CF := TAdminEstados.CreateLoadFromArchi(archi);
    camino:= ExtractFileDir( archi );
    nombre:= ExtractFileName( archi );
    archi_dest:= Camino +DirectorySeparator+'z16_'+nombre;
    CF.StoreInArchi( archi_dest );
    CF.Free;
    CF:= nil;
  end;
end;

procedure TForm1.btCrearCerebroClick(Sender: TObject);
var
  nCapas: integer;
  arrCntNeuronasPOrCapa: TDAofNInt;
  pal: string;
  kCapa: integer;
  s: string;
  nNeuronas: integer;

begin
  nCapas := 100;
  if Cerebro <> nil then
    Cerebro.Free;
  setlength(arrCntNeuronasPOrCapa, nCapas);
  s := eNeuronasPorCapa.Text;
  pal := nextpal(s);
  kCapa := 0;
  while pal <> '' do
  begin
    if pal = 'N' then
      nNeuronas := Dim_EspacioX
    else
      nNeuronas := StrToInt(pal);
    arrCntNeuronasPOrCapa[kCapa] := nNeuronas;
    Inc(kCapa);
    pal := nextpal(s);
  end;
  setlength(arrCntNeuronasPOrCapa, kCapa);
  Cerebro := TCerebro.Create(Dim_EspacioX, arrCntNeuronasPOrCapa, false );

end;

procedure TForm1.btDibujarNeuronasClick(Sender: TObject);
var
  c: TCanvas;
  w, h: integer;
  nFils, nCols: integer;
  cnt, kCapa, kNeurona: integer;
  aCapa: TCapaNeuronasBase;
  aNeurona: TNeurona;
  aNeuronaConEntradas: TNeuronaConEntradas;
  xCentro, yCentro, radio: integer;

begin
  if Cerebro <> nil then
  begin
    w := PaintBox2.Width;
    h := PaintBox2.Height;
    c := PaintBox2.Canvas;

    c.Brush.Color := clWhite;
    c.Rectangle(0, 0, w - 1, h - 1);

    // una columna a la izquierda, capaEntrada, las capas y una a la derecha
    nCols := 1 + 1 + length(Cerebro.capas) + 1;
    nFils := Cerebro.CapaEntrada.NNeuronas;
    for kCapa := 0 to high(Cerebro.Capas) do
    begin
      cnt := Cerebro.Capas[kCapa].NNeuronas;
      if cnt > nFils then
        nFils := cnt;
    end;

    radio := trunc(min(w / nCols, h / nFils) / 8);

    // Dibujamos la capa de entrada
    c.Pen.Color := clBlack;
    c.Brush.Color := clGray;
    c.Pen.Width := 1;
    aCapa := Cerebro.CapaEntrada;
    for kNeurona := 0 to aCapa.NNeuronas - 1 do
    begin
      kCapa := -1;
      xCentro := trunc((kCapa + 0.5 + 2) / nCols * w);
      yCentro := trunc((1 - (kNeurona + 0.5) / aCapa.NNeuronas) * h);

      c.Ellipse(xCentro - radio, yCentro - radio, xCentro + radio, yCentro + Radio);
    end;

    // Dibujamos las capas con entrada
    c.Pen.Color := clBlack;
    c.Brush.Color := clGreen;
    c.Pen.Width := 1;
    for kCapa := 0 to high(Cerebro.capas) do
    begin
      aCapa := Cerebro.capas[kCapa];
      for kNeurona := 0 to aCapa.NNeuronas - 1 do
      begin
        xCentro := trunc((kCapa + 0.5 + 2) / nCols * w);
        yCentro := trunc((1 - (kNeurona + 0.5) / aCapa.NNeuronas) * h);
        c.Ellipse(xCentro - radio, yCentro - radio, xCentro + radio, yCentro + Radio);
      end;
    end;

  end;
end;


procedure TForm1.PlotIsoCurvas(M: TMatR; vx, vy: TVectR; M2: TMatR;
  vx2, vy2: TVectR; niveles: array of NReal; etiquetas: array of string);

var
  IsoScanner: TIsoScannerMatricial;
  px, py: NReal;
  pol: TPoligonalXY;
  res: boolean;
  ramaDirecta: boolean;
  plabel_x, plabel_y: NReal;
  lblxy: TLabelXY;
  color: TColor;
  trx: TfrmDllForm;
  sal: textfile;
  archi: string;

  procedure PlotCurvas(m: TMatR; vx, vy: TVectR);
  var
    knivel: integer;
    idPol: integer;
  begin

    for knivel := 0 to high(niveles) do
    begin
      archi:= 'isocurva_n'+IntToStr(kNivel)+'_cm'+IntToStr( round( niveles[kNivel] * 100 ))+'.scr';
      assignfile( sal, archi );
      rewrite( sal );

      IsoScanner := TIsoScannerMatricial.Create( m, vx, vy, niveles[knivel]);
      color := escalaColor.Color(niveles[knivel]);
      pol := TPoligonalxy.Create(trx.tr1, 'p', False, color);
      idPol:= 1;

      ramaDirecta := True;
      plabel_y := 100000;

      repeat
        res := IsoScanner.GetPunto(px, py);  {pedimos un punto a iso90}
        if IsoScanner.Estado = Reversa then
          ramaDirecta := not ramaDirecta;

        if res then   {Si el punto es valido lo dibuja}
        begin
          if py < plabel_y then   {elige el punto más bajo}
          begin
            plabel_x := px;
            plabel_y := py;          {para poner la etiqueta}
          end;
          if ramaDirecta then
            pol.nuevoPunto(px, py)
          else
            pol.nuevoPuntoAlInicio(px, py);
        end;

        if IsoScanner.Estado = Semiactivo then   {termino con una curva}
        begin
          pol.AppendToAutocadSCR( sal );
          if aDoc_KML <> nil then
            pol.AppendToKMLDocumento( aDoc_KML, archi+'_'+IntToStr( idPol ) );

          pol := TPoligonalxy.Create(trx.tr1, 'p', False, color);
          inc( idPol );
          ramaDirecta := True;
          lblxy := TLabelXY.Create(trx.tr1, 'l', plabel_x, plabel_y,
            etiquetas[knivel], color, 10);
          plabel_y := 10000;
        end;
      until IsoScanner.Estado = fin;       {hasta terminar}
      IsoScanner.Free;
      pol.AppendToAutocadSCR( sal );
      closefile( sal );
    end;
  end;

begin
  trx := TfrmDllForm.Create(form1);

  trx.CrearDiagramaXY(
    'Costo Futuro', // Nombres
    512, // MaxNPuntos
    True, // ciruclar
    'x', // nombre_sx
    '', // nombre_sy1: pchar;
    clRed, //  color_sy1: TColor;
    vx.e(1), vx.e(vx.n), //  x1, x2,
    vy.e(1), vy.e(vy.n), //y1, y2
    10, 10    // NDivX, NDivY
    );

  trx.Show;
  trx.dbj_gridx;
  trx.dbj_gridy;
  trx.dbj_borde;
  trx.titulo('Costo Futuro');
  trx.etiquetas_x(vx.e(1), vx.e(vx.n));
  trx.etiquetas_y(vy.e(1), vy.e(vy.n));
  trx.xlabel('x');
  trx.ylabel('y');


  PlotCurvas(m, vx, vy);
  if m2 <> nil then
    PlotCurvas(m2, vx2, vy2);

  trx.tr1.RePlot;
end;


procedure TForm1.btIsoCurvasClick(Sender: TObject);
begin
  PlotIsoCurvas(mcf, vx, vy, nil, nil, nil, niveles, etiquetas);
end;

procedure TForm1.btScanAltitudesClick(Sender: TObject);
var
  k, j: integer;
  lats, lons: TVectR;
  z: TMatR;
  nLats, nLons: integer;
  xE, yN: TVectR;
  x0, x, dx: NReal;

  min_z, max_z: NReal;
  nNiveles: integer;
  UTME, UTMN: NReal;
  UTMZona: char;
  UTMHuso: integer;
  delta_z: NReal;

begin

  aDoc_KML:= TKML_Document.CreateNew('Lupi' );
  aDoc_KML.AddMarcador('p1',  StrToFloat( lat1.text ), StrToFloat( lon1.text ), 1);
  aDoc_KML.AddMarcador('p2',  StrToFloat( lat2.text ), StrToFloat( lon2.text ), 1);

  nLats:= StrToInt( nPuntosLat.text );
  nLons:= StrToInt( nPuntosLon.text );
  lats:= TVectR.Create_Init( nLats );
  lons:= TVectR.Create_Init( nLons );

  x0:= StrToFloat( Lat1.text );
  dx:= (StrToFloat( lat2.text ) - x0 ) / ( nLats - 1 );
  for k:= 1 to nLats do
    lats.pon_e( k, x0 + (k-1) * dx );

  x0:= StrToFloat( lon1.text );
  dx:= (StrToFloat( lon2.text ) - x0 ) / ( nLons - 1 );
  for k:= 1 to nLons do
    lons.pon_e( k, x0 + (k-1) * dx );

  z:= TMatR.CreateFromArchiXLT( 'altitudes_.xlt' );
//  z:= Elevation_scanMat( lats, lons );

  if z <> nil then
  begin
    lats.WriteXLTSimple_archi( 'latitudes.xlt' );
    lons.WriteXLTSimple_archi( 'longitudes.xlt' );

    // supongo que es un rectángulo chico y paso a metros
    j:= round(( lons.n - 1 ) / 2 + 1 );
    yN:= TVectR.Create_Init( lats.n );
    for k:= 1 to lats.n do
    begin
      LatLonToUTM( UTME, UTMN, UTMZona, UTMHuso, C_Ellipsoid_URUGUAY,  Lats.e(k), lons.e(j) );
      yN.pon_e(k, UTMN );
    end;

    k:= round(( lats.n - 1 ) / 2 + 1 );
    xE:= TVectR.Create_Init( lons.n );
    for j:= 1 to lons.n do
    begin
      LatLonToUTM( UTME, UTMN, UTMZona, UTMHuso, C_Ellipsoid_URUGUAY,  Lats.e(k), lons.e(j) );
      xE.pon_e(j, UTME );
    end;
    xE.WriteXLTSimple_archi( 'coordenadas_xE.xlt' );
    yN.WriteXLTSimple_archi('coordenadas_yN.xlt' );

    z.WriteArchiXLT( 'altitudes_.xlt' );
    z.MinMax( min_z, max_z );

    EscalaColor := TEscalaColor.Create( min_z, max_z );

     // ahora buscamos la aproximación a 0.5m
    min_z:= ceil( min_z * 2 ) / 2;
    max_z:= floor( max_z * 2 ) / 2;
    nNiveles:= round( (max_z - min_z)*2 + 1 );
    if nNiveles > 1 then
    begin
      delta_z:= ( max_z - min_z ) / ( nNiveles-1 );
      setlength( niveles, nNiveles );
      setlength( etiquetas, nNiveles );
      for k:= 0 to high( niveles ) do
      begin
        niveles[k]:= min_z + k * delta_z;
        etiquetas[k]:= FloatToStrF( niveles[k], ffFixed, 12, 1 );
      end;
      // transpongo porque espera que las filas sena el x y las columnas los y
    z.Transponer;
  //    self.PlotIsoCurvas( z, lons, lats, nil, nil, nil, niveles, etiquetas );
      self.PlotIsoCurvas( z, xE, yN, nil, nil, nil, niveles, etiquetas );
    end;
  end;

  aDoc_KML.WriteArchi_kml('puntos_lu.kml' );
  aDoc_KML.Free;
  aDoc_KML:= nil;

end;

procedure TForm1.btTest01Click(Sender: TObject);
var
  XCF: TDAOfRecXCF;
  aRec: TRecXCF;
  dimX: integer;
  arrNeuronasPorCapa: TDAofNInt;
  nParametros: integer;
  flog: textfile;
  c_min, dc: NReal;
  cerebro: TCerebro;
  X, Xs: TVectR;
  kRec: integer;
  CFAprox: NReal;
  derr: TDAOfNReal;
begin
  dimX := 1;
  XCF := Crear_XCF_Test01(dimX, 2, 31);

  Normalizar_conjuntoXCF(c_min, dc, XCF, 0.7);

  setlength(arrNeuronasPorCapa, 2);
  arrNeuronasPorCapa[0] := dimX;
  arrNeuronasPorCapa[1] := 1;
  cerebro := TCerebro.Create(dimX, // Cantidad de entradas
    arrNeuronasPorCapa, // Cantidad de capas (sin contar la entrada)
    True); // Indica si saturar la salida de la última capa.

  nparametros := cerebro.DimParametros;
  X := TVectR.Create_init(nparametros);
  Xs := TVectR.Create_init(nparametros);
  randSeed := 131;
  X.random;
  Cerebro.SetParametros(X);
  setlength(derr, 1);

  assignfile(flog, 'cerebro_db.xlt');
  rewrite(flog);
  for kRec := 0 to high(XCF) do
  begin
    Cerebro.BackPropagation_init;
    aRec := XCF[kRec];
    Cerebro.SetEntradas(aRec.X);
    Cerebro.evaluar;
    CFAprox := Cerebro.Salida_CapaN.Neuronas[0].salida;
    derr[0] := (CFAprox - aRec.CF);
    Cerebro.BackPropagation_ClearErr;
    Cerebro.BackPropagation_addMuestra(derr);
    writeln(flog, '***************');
    writeln(flog, 'Muestra:', kRec, #9, CFAprox, #9, aRec.CF);
    Cerebro.print_debug(flog);
  end;
  closefile(flog);

end;



procedure TForm1.btVerClick(Sender: TObject);
var
  k, j, i: integer;
  x, y: NReal;
  ss: TStringList;
  s: string;
  xVar, yVar: TVar;
  vxVar: array of TVar;
  vcf_min, vcf_max, vcf: NReal;
  color: TCOlor;
  klin, iPosBarraBarra: integer;
  ts: string;
  aScript: TExprLst;

begin

  kPasoT := StrToInt(ekPaso.Text);
  s := mseval.Text;

  xVar := evaluador.FindVar('x');
  yVar := evaluador.FindVar('y');

  setlength(vxVar, CF.nVarsContinuas + CF.nVarsDiscretas);

  for i := 0 to CF.nVarsContinuas - 1 do
    vxVar[i] := evaluador.FindVar('$X_' + CF.xr_Def[i].nombre);
  for i := 0 to CF.nVarsDiscretas - 1 do
    vxVar[CF.nVarsContinuas + i] := evaluador.FindVar('$X_' + CF.xd_def[i].nombre);

  ss := TStringList.Create;
  ss.AddStrings(mseval.Lines);

  for klin := 0 to ss.Count - 1 do
  begin
    ts := trim(ss[klin]);
    iPosBarraBarra := pos('//', ts);
    if iPosBarraBarra > 0 then
      ts := copy(ts, 1, iPosBarraBarra - 1);
    ss[klin] := trim(ts);
  end;
  ss.LineBreak := ' ';
  s := ss.Text;
  ss.Free;

  aScript := evaluador.GetExprLst(s);
  for k := 0 to PaintBox1.Width - 1 do
    for j := 0 to PaintBox1.Height - 1 do
    begin
      x := k / (PaintBox1.Width - 1);
      y := (PaintBox1.Height - j - 1) / (PaintBox1.Height - 1);

      vx.pon_e(k + 1, x);
      vy.pon_e(PaintBox1.Height - j, y);

      xVar.val.val_F := x;
      yVar.val.val_F := y;


      aScript.Evaluar;
      // evaluador.Ejecutar(s);

      for i := 0 to CF.nVarsContinuas - 1 do
        CF.xr[i] := vxVar[i].ValAsFloat;
      for i := 0 to CF.nVarsDiscretas - 1 do
        CF.xd[i] := vxVar[CF.nVarsContinuas + i].ValAsInt;

      vcf := CF.costoContinuo(kPasoT);

      mcf.pon_e(k + 1, PaintBox1.Height - j, vcf);
    end;

  mcf.MinMax(vcf_min, vcf_max);
  EscalaColor := TEscalaColor.Create(vcf_min, vcf_max);

  setlength(niveles, 50);
  setlength(etiquetas, length(niveles));
  for k := 0 to high(niveles) do
  begin
    niveles[k] := vcf_min + (vcf_max - vcf_min) / length(niveles) * (k + 0.5);
    etiquetas[k] := FloatToStr(round(niveles[k] / 1e6 * 10) / 10);
  end;

  for k := 0 to PaintBox1.Width - 1 do
    for j := 0 to PaintBox1.Height - 1 do
    begin
      vcf := mcf.e(k + 1, PaintBox1.Height - j);
      color := escalaColor.Color(vcf);
      PaintBox1.Canvas.Pixels[k, j] := color;
    end;

end;



function nextpal(var s: string): string;
var
  i: integer;
  res: string;
begin
  i := pos(#9, s);
  if i > 0 then
  begin
    res := copy(s, 1, i - 1);
    Delete(s, 1, i);
  end
  else
  begin
    res := s;
    s := '';
  end;
  Result := s;
end;

procedure TForm1.btCopiarYTranspornerUltima7FilasClick(Sender: TObject);
var
  archi: string;
  buff: array[1..10] of TDAOfNReal;
  //array [1..10*5*5*5] of NReal;
  ent, sal: textfile;
  i: integer;
  r: string;
  pal: string;
  N: integer;
  paux: TDAOfNreal;
begin
  N := 10 * 5 * 5 * 5;

  if OpenDialog1.Execute then
  begin
    archi := OpenDialog1.FileName;
    assignfile(ent, archi);
    reset(ent);

    for i := 1 to 10 do
      setlength(buff[i], N);

    while not EOF(ent) do
    begin
      readln(ent, r);

      paux := buff[1];
      for i := 1 to 9 do
        buff[i] := buff[i + 1];
      buff[10] := paux;

      for i := 0 to N - 1 do
      begin
        pal := nextpal(r);
        paux[i] := StrToFloat(pal);
      end;

    end;
    closefile(ent);

  end;
end;

procedure TForm1.btCF_div_10Click(Sender: TObject);
var
  archi: string;
  fCosto: TMatOfNReal;
  nPasos, nEstrellas: integer;
  k, j: integer;
begin
  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    archi := OpenDialog1.FileName;
    CF := TAdminEstados.CreateLoadFromArchi(archi);
    fCosto := CF.constelacion.fCosto;
    nPasos := length(fCosto);
    nEstrellas := length(fCosto[0]);
    for k := 0 to nPasos - 1 do
      for j := 0 to nEstrellas - 1 do
        fCosto[k][j] := fCosto[k][j] / 10;
    CF.storeInArchi(archi);
  end;
end;




procedure TForm1.btCompararCFsClick(Sender: TObject);
var
  fCosto: TMatOfNReal;
  nPasos, nEstrellas: integer;
  k, j: integer;
  archi2: string;
  archi1: string;

  CF1, CF2: TAdminEstados;
  fCosto1: TMatOfNReal;
  nPasos1: integer;
  nEstrellas1: integer;
  fCosto2: TMatOfNReal;
  nPasos2: integer;
  nEstrellas2: integer;

  iguales: boolean;
  dist: NReal;
  dist_: extended;
begin
  iguales := True;
  if OpenDialog1.Execute then
  begin
    archi1 := OpenDialog1.FileName;
    if OpenDialog1.Execute then
    begin
      archi2 := OpenDialog1.FileName;
      CF1 := TAdminEstados.CreateLoadFromArchi(archi1);
      CF2 := TAdminEstados.CreateLoadFromArchi(archi2);

      fCosto1 := CF1.constelacion.fCosto;
      nPasos1 := length(fCosto1);
      nEstrellas1 := length(fCosto1[0]);
      fCosto2 := CF2.constelacion.fCosto;
      nPasos2 := length(fCosto2);
      nEstrellas2 := length(fCosto2[0]);

      dist := 0;
      if ((nPasos1 <> nPasos2) and (nEstrellas1 <> nEstrellas2)) then
        iguales := False
      else
      begin
        for k := nPasos1 - 1 downto 0 do
        begin
          //readln;
          for j := 0 to nEstrellas1 - 1 do
          begin

            dist_ := (abs(fCosto1[k][j] - fCosto2[k][j])) * 1000000;
            if dist_ > dist then
              dist := dist_;
            //  abs(fCosto1[k][j]-fCosto2[k][j]);
            //Break;

            writeln(k, ', ', j, ' : ', fCosto1[k][j], ' : ', fCosto2[k][j]);

            if fCosto1[k][j] <> fCosto2[k][j] then
            begin
              iguales := False;
              readln;
            end;
          end;

        end;
      end;
      writeln(iguales, ' ', k, ' ', j, ' ', dist);
    end;
  end;
end;


procedure TForm1.btDumpPrimerFrame_2CFsClick(Sender: TObject);
var
  fCosto: TMatOfNReal;
  nPasos, nEstrellas: integer;
  k, j: integer;
  archi2: string;
  archi1: string;

  CF1, CF2: TAdminEstados;
  fCosto1: TMatOfNReal;
  nPasos1: integer;
  nEstrellas1: integer;
  fCosto2: TMatOfNReal;
  nPasos2: integer;
  nEstrellas2: integer;

  iguales: boolean;
  dist: NReal;
  dist_: extended;
  sal: textfile;

begin
  iguales := True;
  if OpenDialog1.Execute then
  begin
    archi1 := OpenDialog1.FileName;
    if OpenDialog1.Execute then
    begin
      archi2 := OpenDialog1.FileName;
      CF1 := TAdminEstados.CreateLoadFromArchi(archi1);
      CF2 := TAdminEstados.CreateLoadFromArchi(archi2);

      fCosto1 := CF1.constelacion.fCosto;
      nPasos1 := length(fCosto1);
      nEstrellas1 := length(fCosto1[0]);
      fCosto2 := CF2.constelacion.fCosto;
      nPasos2 := length(fCosto2);
      nEstrellas2 := length(fCosto2[0]);

      dist := 0;
      if ((nPasos1 <> nPasos2) and (nEstrellas1 <> nEstrellas2)) then
        iguales := False
      else
      begin
        assignfile(sal, 'c:\basura\primerframetranspuesto_2cfs.xlt');
        rewrite(sal);
        k := 1;
        begin
          for j := 0 to nEstrellas1 - 1 do
            writeln(sal, j, #9, fCosto1[k][j], #9, fCosto2[k][j]);
        end;
        closefile(sal);
      end;
    end;
  end;
end;

procedure TForm1.bTest02Click(Sender: TObject);
var
  cerebro: TCerebro;
  XCF: TDAOfRecXCF;
  arrNeuronasPorCapa: TDAOfNInt;

  resConvergio: boolean;
  resNIters: integer;
  x, y, e: TVectR;
  e2: NReal;
  sal: textfile;
  iter: integer;

begin

  XCF := Crear_XCF_Test02_(1000, 31);

  setlength(arrNeuronasPorCapa, 1);
  arrNeuronasPorCapa[0] := 1;

  cerebro := TCerebro.Create(1, // Cantidad de entradas
    arrNeuronasPorCapa, // Cantidad de capas (sin contar la entrada)
    True); // Indica si saturar la salida de la última capa.

  x := TVectR.Create_Init(1);
  y := TVectR.Create_Init(1);
  e := TVectR.Create_Init(1);
  randomize;
  cerebro.RandomInit(1);

  assignfile(sal, 'test02.txt');
  rewrite(sal);
  x.pon_e(1, 0.6);
  for iter := 1 to 1000000 do
  begin
    x.pon_e(1, 100 * (random - 0.5));
    if x.e(1) < 0.5 then
      y.pon_e(1, 1)
    else
      y.pon_e(1, 0); // x < 0.5

    cerebro.SetEntradas(x);
    cerebro.BackPropagation_init;
    cerebro.evaluar;

    e2 := cerebro.calc_err2(e, y);

    cerebro.BackPropagation_addMuestra(e);
    //    cerebro.print_debug( sal );
    cerebro.BackPropagation_DarPaso(100);

    writeln(sal, 'iter: ', iter, #9, 'e2: ', e2);
  end;
  closefile(sal);
  Cerebro.StoreInArchi('cerebro_ebp.txt');

  EntrenarCerebro(cerebro, XCF, 1000, resConvergio, resNIters, -1, -1);

  Cerebro.StoreInArchi('cerebro_mp.txt');
  Cerebro.Free;
  free_Data_xcf(XCF);
end;

procedure TForm1.btLoadCFClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    if CF <> nil then
      CF.Free;
    CF := TAdminEstados.CreateLoadFromArchi(OpenDialog1.FileName);
    Dim_EspacioX := CF.nVarsContinuas + CF.nVarsDiscretas;
    eDimensionEspacioX.Text := IntToStr(Dim_EspacioX);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//  googlemaps_open( StrToFloat( lat1.text ), StrToFloat( lon1.text ) );
  aDoc_KML:= TKML_Document.CreateNew('Lupi' );
  aDoc_KML.AddMarcador('p1',  StrToFloat( lat1.text ), StrToFloat( lon1.text ), 1);
  aDoc_KML.AddMarcador('p2',  StrToFloat( lat2.text ), StrToFloat( lon2.text ), 1);
  aDoc_KML.WriteArchi_kml('puntos_lu.kml' );
  aDoc_KML.Free;
  aDoc_KML:= nil;
end;


procedure TForm1.cbAutoChange(Sender: TObject);
begin
  while (sbKPaso.Position < sbKPaso.Max) and cbAuto.Checked do
  begin
    application.ProcessMessages;
    sbkpaso.Position := sbkpaso.Position + 12;
    application.ProcessMessages;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  aDoc_KML:= nil;
end;

procedure TForm1.PageControl1Change(Sender: TObject);
begin

end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
begin

end;

procedure TForm1.sbKPaso1Change(Sender: TObject);
begin
  ePaso.Text := FloatToStr(sbkPaso1.position / 1000);
end;

procedure TForm1.sbKPasoChange(Sender: TObject);
begin
  if evaluador <> nil then
  begin
    ekPaso.Text := IntToStr(sbKPaso.Position);
    btVerClick(Sender);
  end;
end;

end.
