unit uSkyMap;

// fixed Hr Angle calculation 2006-12-21
// Removed imgSkyMap.Repaint;   // Then repaint the form. IN REFRESH  2011-03-17
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, ComCtrls, _GClass, AbLabel, AbNumEdit,
  AbLED, Buttons, AbSwitch, Gauges,
  ImgList, Menus, uSETITypes, System.ImageList, SDL_NumLab;

type
  TClientProcedureAsParameter = procedure;

  TfrmSkyMap = class(TForm)
    pnlSkyMap: TPanel;
    imgTemp: TImage;
    imgSkyMap: TImage;
    pnlVertScroll: TPanel;
    pnlControls: TPanel;
    pnlMapControls: TPanel;
    btnCloseMap: TButton;
    statusControls: TStatusBar;
    btnFindStar: TBitBtn;
    btnFindAnt: TBitBtn;

    statusbarImageList: TImageList;
    pnlStatusBars: TPanel;
    sbAnt: TStatusBar;
    sbStar: TStatusBar;
    lblAnt: TLabel;
    lblStar: TLabel;
    ledLocked: TAbLED;
    swSearch: TAbToggleSwitch;
    neTest: TAbNumEdit;
    lblTest: TLabel;

    procedure imgSkyMapMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure scrollHorizontalScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);

    procedure imgSkyMapMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure btnCloseMapClick(Sender: TObject);
    procedure sbhImageScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
    procedure sbvImageScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);

    procedure btnFindStarClick(Sender: TObject);
    procedure btnFindAntClick(Sender: TObject);
    procedure swSearchStatusChanged(Sender: TObject);

  private
    { Private declarations }

    Units: TPoint;
    RAPixPerHour, DECPixPerDeg, DECDegPerPix: Real;

    FNewAntAvailable: boolean;

    FAntRA: THours;
    FAntDEC: TDegrees;
    FAntHa: THours;
    FNewStarAvailable: boolean;
    FStarDEC: TDegrees;
    FStarRA: THours;
    FLocked: boolean;

    FL4Ra: THours;
    FL5Ra: THours;
    FL4DEC: TDegrees;
    FL5DEC: TDegrees;

    FMouseAz: TDegrees;
    FMouseEl: TDegrees;

    FStarAz: TDegrees;
    FStarEl: TDegrees;
    FSearching: boolean;

    procedure setStarDEC(value: THours);

    procedure setStarRa(value: THours);
    function getStarAz: TDegrees;
    procedure setStarAz(value: TDegrees);
    function getStarEl: TDegrees;
    procedure setStarEl(value: TDegrees);

    procedure DrawSunrise(ElMin: TDegrees);
    procedure RAToPix(RA: THours; var PixX: Integer);
    // Convert RA to pixel point on SkyMap
    procedure DECToPix(DEC: TDegrees; var PixY: Integer);
    // Convert DEC to pixel point on Skymap
    procedure PicCoorToRealCoor(px, py: Integer; var RA: THours; var DEC: TDegrees);
    procedure DrawCross(Canvas: TCanvas; X, Y: Integer; Color: Integer);

    function getNewStarAvailable: boolean;
    function getNewAntAvailable: boolean;
    function getStarHa: TDegrees;

    function getAntRA: THours;
    function getAntDEC: TDegrees;
    function getAntHa: TDegrees;
    procedure DrawL4L5;
    procedure DrawStar;

    procedure DrawAntenna;
    procedure Refresh;

    procedure setSearching(value: boolean);
  public
    { Public declarations }
    InUse: boolean;

    procedure DrawSearchArea;
    procedure SnapShot(fileName: string);
    property Locked: boolean read FLocked;

    property MouseAz: TDegrees read FMouseAz;
    property MouseEl: TDegrees read FMouseEl;

    property AntennaRa: THours read getAntRA;
    property AntennaDEC: TDegrees read getAntDEC;
    property AntennaHa: TDegrees Read getAntHa;

    property NewAntAvailable: boolean read getNewAntAvailable;
    property NewStarAvailable: boolean read getNewStarAvailable;
    property StarRa: THours read FStarRA write setStarRa;
    property StarDEC: TDegrees read FStarDEC write setStarDEC;
    property StarAz: TDegrees read getStarAz write setStarAz;
    Property StarEl: TDegrees read getStarEl write setStarEl;
    property StarHa: TDegrees Read getStarHa;

    property L4Ra: THours read FL4Ra;
    property L4DEC: TDegrees read FL4DEC;

    property L5Ra: THours read FL5Ra;
    property L5DEC: TDegrees read FL5DEC;
    property Searching: boolean read FSearching write setSearching;
  end;

var
  frmSkyMap: TfrmSkyMap;

implementation

{$R *.DFM}
{$IF Defined(Clock)}

uses uMount, uTime, DateUtils, SDL_stringl, uClock;

{$ENDIF}
{$IF Defined(SETI)}

uses uMount, uTime, DateUtils, SDL_stringl, uAntenna;

{$ENDIF}
{$IF Defined(SkyMap)}

uses
  uTime, SDL_stringl, DateUtils, uMount, uAntenna;
{$ENDIF}
//
{$IF Defined(Mount)}

uses
  uTime, SDL_stringl, DateUtils, uMount;
{$ENDIF}
//

{$IF Defined(Antenna)}

uses
  SDL_stringl, uTime, DateUtils, uMount, uAntenna;
{$ENDIF}

const

  XRangeLower = 0;

procedure TfrmSkyMap.setSearching(value: boolean);
begin
  FSearching := value;
  swSearch.Checked := value;

end;

function TfrmSkyMap.getStarAz: TDegrees;
begin
  result := FStarAz;
end;

procedure TfrmSkyMap.setStarAz(value: TDegrees);
begin
  FStarAz := value;
  FNewStarAvailable := True;
end;

procedure TfrmSkyMap.setStarEl(value: TDegrees);
begin

  FStarEl := value;
  FNewStarAvailable := True;
end;

function TfrmSkyMap.getStarEl: TDegrees;
begin
  result := FStarEl;
end;

procedure TfrmSkyMap.setStarDEC(value: THours);
begin
  FStarDEC := value;
  FNewStarAvailable := True;
end;

procedure TfrmSkyMap.setStarRa(value: THours);
begin
  FStarRA := value;
  FNewStarAvailable := True;
end;

procedure TfrmSkyMap.SnapShot(fileName: string);
begin
  imgSkyMap.Picture.SaveToFile(fileName);
end;

function TfrmSkyMap.getNewStarAvailable: boolean;
begin
  result := FNewStarAvailable;
  FNewStarAvailable := False;
end;

function TfrmSkyMap.getNewAntAvailable: boolean;
begin
  result := FNewAntAvailable;
  FNewAntAvailable := False;
end;

(* S k y   M a p   C r e a t e *)
procedure TfrmSkyMap.FormCreate(Sender: TObject);

begin
  // SkyMap.Left:= 1680;
  pnlSkyMap.Left := pnlVertScroll.Width;
  pnlSkyMap.Top := pnlControls.Height;

  pnlSkyMap.Width := 950;
  Width := pnlSkyMap.Width + pnlVertScroll.Width + 20;
  pnlSkyMap.Height := 490;
  Height := pnlSkyMap.Height + pnlMapControls.Height + 55;

  imgSkyMap.Top := pnlSkyMap.Top - pnlControls.Height;
  imgTemp.Top := imgSkyMap.Top;

  imgSkyMap.Left := pnlSkyMap.Left - pnlVertScroll.Width;
  imgTemp.Left := imgSkyMap.Left;

  imgSkyMap.Height := 485;
  // This is the actual pixal width and height of SkyMap9.bmp
  imgTemp.Height := imgSkyMap.Height;

  imgSkyMap.Width := 942;
  imgTemp.Width := imgSkyMap.Width;
  pnlVertScroll.Height := pnlSkyMap.Height;

  RAPixPerHour := imgSkyMap.Width / 24; // Order is important big Jim
  DECPixPerDeg := imgSkyMap.Height / 180;
  DECDegPerPix := 1 / DECPixPerDeg;
{$IF Defined(SkyMap) }
  Visible := True
{$ELSE}
  Visible := False;
{$IFEND}
end;
(* G e t t e r s   a n d   S e t t e r s *)

function TfrmSkyMap.getAntRA: THours;

begin
  result := HaToRA(AntennaHa, frmMount.Longitude);
end;

function TfrmSkyMap.getStarHa: THours;
var
  tRa: THours;
  tDEC: TDegrees;
begin
  result := RAToHa(FStarRA, frmMount.Longitude);
end;

function TfrmSkyMap.getAntHa: THours;
var
  tRa: THours;
  tDEC: TDegrees;
begin
  result := RAToHa(FAntRA, frmMount.Longitude);
end;

function TfrmSkyMap.getAntDEC: TDegrees;
var
  tRa: THours;
  tDEC: TDegrees;
begin
  AzElToRaDec(frmMount.getAzBlack, frmMount.getElBlack, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
  result := tDEC;
end;

procedure TfrmSkyMap.DrawCross(Canvas: TCanvas; X, Y: Integer; Color: Integer);
(* D r a w   C r o s s *)
begin
  with imgSkyMap.Canvas do
  begin
    MoveTo(X, Y - 2);
    LineTo(X, Y - 7);
    MoveTo(X + 2, Y);
    LineTo(X + 7, Y);
    MoveTo(X, Y + 2);
    LineTo(X, Y + 7);
    MoveTo(X - 2, Y);
    LineTo(X - 7, Y);
  end;
end;

procedure TfrmSkyMap.DrawStar;
(* D r a w   S t a r *)
var
  X, Y: Integer;
begin
  RAToPix(StarRa, X);
  DECToPix(StarDEC, Y);

  with imgSkyMap.Canvas do
  begin
    Pen.Color := clWhite; // Draw the cross
    Pen.Width := 1;
    Pen.Mode := pmWhite;
    RAToPix(StarRa, X);
    DECToPix(StarDEC, Y);

    MoveTo(X - 2, Y - 2); // Draw 'X' for Star position
    LineTo(X - 7, Y - 7);

    MoveTo(X + 2, Y + 2);
    LineTo(X + 7, Y + 7);

    MoveTo(X - 2, Y + 2);
    LineTo(X - 7, Y + 7);

    MoveTo(X + 2, Y - 2);
    LineTo(X + 7, Y - 7);
  end;
end;

procedure TfrmSkyMap.DrawAntenna;
(* D r a w    A n t *)
var

  BWX1, BWY1, BWX2, BWY2, AX1, AX2, AY1, AY2, X, Y: Integer;

  tHa: THours;
  tRa: THours;
  tDEC: TDegrees;
begin

  with imgSkyMap.Canvas do
  begin

    Pen.Color := clWhite;
    Pen.Width := 1;
    // Pen.Mode := pmCopy;
    Pen.Mode := pmWhite;

    AzElToRaDec(frmMount.getAzBlack, frmMount.getElBlack, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
    FAntRA := tRa; // These two update the current antenna Ra and DEC
    FAntDEC := tDEC;
    RAToPix(FAntRA, X); // Draw antenna pointer cross on map
    DECToPix(tDEC, Y);
    DrawCross(imgSkyMap.Canvas, X, Y, clYellow);

    AzElToRaDec((frmMount.getAzBlack - frmMount.HPBW), frmMount.getElBlack, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

    RAToPix(tRa, BWX1); // Get BWX1 point on map

    AzElToRaDec(frmMount.getAzBlack, frmMount.getElBlack - frmMount.HPBW, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

    DECToPix(tDEC, BWY1); // Get BWY1 point on map

    AzElToRaDec(frmMount.getAzBlack + frmMount.HPBW, frmMount.getElBlack, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

    RAToPix(tRa, BWX2); // Get BWX2 point on map

    AzElToRaDec(frmMount.getAzBlack, frmMount.getElBlack + frmMount.HPBW, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

    DECToPix(tDEC, BWY2); // Get BWY2 point on map

    if (BWX1 < BWX2) then
    begin // Find which way it is orented for X1 X2
      AX1 := BWX1;
      AX2 := BWX2
    end
    else
    begin
      AX2 := BWX1;
      AX1 := BWX2
    end;

    if (BWY1 < BWY2) then
    begin
      AY1 := BWY1;
      AY2 := BWY2;
    end
    else
    begin
      AY2 := BWY1;
      AY1 := BWY2;
    end;

    Arc(AX1, AY1, AX2, AY2, AX1, AY1, AX1, AY1);
  end;
end;

procedure TfrmSkyMap.RAToPix(RA: THours; var PixX: Integer);
// Convert RA to pixel point on SkyMap
begin
  PixX := imgSkyMap.Width - Trunc(RA * RAPixPerHour);
end; { RAToPix }

procedure TfrmSkyMap.DECToPix(DEC: TDegrees; var PixY: Integer);
// Convert DEC to pixel point on Skymap
begin
  if (DEC > 0) then // Above the zero line
    PixY := Trunc((imgSkyMap.Height div 2) - (DEC * DECPixPerDeg))
    // Pix per degree of DEC
  else
    PixY := Trunc((imgSkyMap.Height div 2) + (abs(DEC) * DECPixPerDeg));
end;

procedure TfrmSkyMap.DrawSearchArea;
(* D R A W   S E A R C H   A R E A *)
var
  PixX, PixY: Integer;
  X, lastX: Integer;
  tRa: THours;
  tDEC: TDegrees;
begin // If image is flashing its because you need to: imgSkyMap.Stretch := True.
  Refresh;
  DrawL4L5;
  DrawStar;
  DrawAntenna;
  with imgSkyMap.Canvas do
  begin

    DrawSunrise(frmMount.ElStart);

    { Lower Right to Lower Left }
    AzElToRaDec(frmMount.AzStart, frmMount.ElStart, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

    RAToPix(tRa, PixX);
    DECToPix(tDEC, PixY);
    MoveTo(PixX, PixY);
    lastX := PixX;
    X := Trunc(frmMount.AzStop);
    while X >= Trunc(frmMount.AzStart) do
    begin
      AzElToRaDec(X, frmMount.ElStart, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
      RAToPix(tRa, PixX);
      DECToPix(tDEC, PixY);
      if abs(lastX - PixX) > 100 then // Gona jump captn.
        MoveTo(PixX, PixY) // To BIG just move
      else
        LineTo(PixX, PixY);
      X := X - 1;
      lastX := PixX;
    end;

    { Upper Right to Upper Left }
    AzElToRaDec(frmMount.AzStart, frmMount.ElStart, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
    RAToPix(tRa, PixX);
    DECToPix(tDEC, PixY);
    MoveTo(PixX, PixY);
    lastX := PixX;
    X := Trunc(frmMount.AzStart);
    while X >= Trunc(frmMount.AzStart) do
    begin
      AzElToRaDec(X, frmMount.ElStop, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
      RAToPix(tRa, PixX);
      DECToPix(tDEC, PixY);
      if abs(lastX - PixX) > 100 then
        MoveTo(PixX, PixY)
      else
        LineTo(PixX, PixY);
      lastX := PixX;
      X := X - 1;
    end;

    { Right Sidebar - Top to Bottom }
    AzElToRaDec(frmMount.AzStop, frmMount.ElStop, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
    RAToPix(tRa, PixX);
    DECToPix(tDEC, PixY);
    MoveTo(PixX, PixY);
    lastX := PixX;
    X := Trunc(frmMount.ElStop);
    while X >= Trunc(frmMount.ElStart) do
    begin
      AzElToRaDec(frmMount.AzStop, X, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
      RAToPix(tRa, PixX);
      DECToPix(tDEC, PixY);
      if abs(lastX - PixX) > 100 then
        MoveTo(PixX, PixY)
      else
        LineTo(PixX, PixY);
      lastX := PixX;
      X := X - 1;
    end;

    { Left Sidebar - Top to Bottom }
    AzElToRaDec(frmMount.AzStart, frmMount.ElStop, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
    RAToPix(tRa, PixX);
    DECToPix(tDEC, PixY);
    MoveTo(PixX, PixY);
    lastX := PixX;
    X := Trunc(frmMount.ElStop);
    while X >= Trunc(frmMount.ElStart) do
    begin
      AzElToRaDec(frmMount.AzStart, X, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);
      RAToPix(tRa, PixX);
      DECToPix(tDEC, PixY);
      if abs(lastX - PixX) > 100 then
        MoveTo(PixX, PixY)
      else
        LineTo(PixX, PixY);
      lastX := PixX;
      X := X - 1;
    end;
    { with SkyMap }

  end; { with imgSkyMap.Canvas }
end; { DrawSearchArea }

procedure TfrmSkyMap.PicCoorToRealCoor(px, py: Integer; var RA: THours; var DEC: TDegrees);
(* P I C   C O O R   T O   R E A L   C O O R *)
begin
  RA := (imgSkyMap.Width - px) / RAPixPerHour;

  if (py > imgSkyMap.Height div 2) then // lower half of screen
    DEC := ((py * DECDegPerPix) - 90) * -1
  else
    DEC := (90 - (py * DECDegPerPix)); // upper half of screen
end;

procedure TfrmSkyMap.imgSkyMapMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
(* S k y   M a p   M o u s e   M o v e *)
var
  Azdeg, Eldeg: TDegrees;
  RA: THours;
  DEC: TDegrees;
begin
  PicCoorToRealCoor(X, Y, RA, DEC);
  if (RA > 23.99) then
    RA := 23.99;
  if (RA < -23.99) then
    RA := -23.99;
  if (DEC < -88.99) then
    DEC := -88.99;
  if (DEC > 88.99) then
    DEC := 88.99;
  RaDecToAzEl(RA, DEC, frmMount.Latitude, frmMount.Longitude, Azdeg, Eldeg);

  with statusControls do
  begin
    Panels[0].Text := 'RA:' + HrsToSex(RA);
    FMouseAz := Azdeg;
    FMouseEl := Eldeg;
    Panels[1].Text := 'DEC:' + DegsToSex(DEC);

    Panels[2].Text := 'AZ:' + DegsToSex(Azdeg);
    Panels[3].Text := 'EL:' + DegsToSex(Eldeg);

    Panels[4].Text := 'HA:' + DegsToSex(RAToHa(RA, frmMount.Longitude));

    Panels[5].Text := 'pixX:' + IntToStr(X);
    Panels[6].Text := 'pixY:' + IntToStr(Y);

  end; { with }
end;

procedure TfrmSkyMap.swSearchStatusChanged(Sender: TObject);
begin
  FSearching := swSearch.Checked;
end;

procedure TfrmSkyMap.scrollHorizontalScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
  imgSkyMap.Left := -Units.X * ScrollPos
end;

procedure TfrmSkyMap.imgSkyMapMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
(* S k y   M a p   M o u s e   D o w n *)

var
  tempNewAntAz, tempNewAntEl: TDegrees;
  MouseRA: THours;
  MouseDEC: TDegrees;
begin
  if (Button = mbRight) then // Set new star position
  begin { Set current star to mouse position }
    PicCoorToRealCoor(X, Y, MouseRA, MouseDEC);
    StarDEC := MouseDEC;
    StarRa := MouseRA;
    RaDecToAzEl(FStarRA, FStarDEC, frmMount.Latitude, frmMount.Longitude, FStarAz, FStarEl);
    DrawStar;
    FNewStarAvailable := True;
  end;

  if (Button = mbLeft) then // Set new antenna position
  begin
    PicCoorToRealCoor(X, Y, MouseRA, MouseDEC);
    RaDecToAzEl(MouseRA, MouseDEC, frmMount.Latitude, frmMount.Longitude, tempNewAntAz, tempNewAntEl);
    DrawAntenna;
    FNewAntAvailable := True;
  end;
end;

procedure TfrmSkyMap.btnCloseMapClick(Sender: TObject);
begin
  frmSkyMap.Close
end;

procedure TfrmSkyMap.sbhImageScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
  pnlSkyMap.Left := -((5 * ScrollPos) - pnlVertScroll.Width);
end;

procedure TfrmSkyMap.sbvImageScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
  pnlSkyMap.Top := -((5 * ScrollPos) - pnlControls.Height);

end;
{$REGION 'Find Star and Antenna'}

procedure TfrmSkyMap.btnFindStarClick(Sender: TObject);
(* F i n d   S t a r *)
var
  X, Y: Integer;
begin

  RAToPix(StarRa, X); // Get  point on map
  DECToPix(StarDEC, Y);
  with imgSkyMap.Canvas do
  begin
    Pen.Color := clYellow;

    MoveTo(X - 10, Y - 10); // Draw Large X
    LineTo(X - 50, Y - 50);

    MoveTo(X + 10, Y + 10);
    LineTo(X + 50, Y + 50);

    MoveTo(X + 10, Y - 10);
    LineTo(X + 50, Y - 50);

    MoveTo(X - 10, Y + 10);
    LineTo(X - 50, Y + 50);

    Pen.Color := clWhite;
  end;
  DrawStar;
end;

procedure TfrmSkyMap.btnFindAntClick(Sender: TObject);
(* F i n d   A n t e n n a *)
var
  tRa: THours;
  tDEC: TDegrees;
  X, Y: Integer;
begin
  AzElToRaDec(frmMount.getAzBlack, frmMount.getElBlack, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

  RAToPix(tRa, X); // Get  point on map
  DECToPix(tDEC, Y);

  with imgSkyMap.Canvas do
  begin
    Pen.Color := clYellow;
    MoveTo(X, Y - 20);
    LineTo(X, Y - 70);

    MoveTo(X + 20, Y);
    LineTo(X + 70, Y);

    MoveTo(X, Y + 20);
    LineTo(X, Y + 70);

    MoveTo(X - 20, Y);
    LineTo(X - 70, Y);
    Pen.Color := clWhite;
  end; // with imgSkyMap

  DrawStar;
end; { FindAntenna }
{$ENDREGION}

procedure TfrmSkyMap.Refresh;
(* R e f r e s h *)
var
  tRa: TDegrees;
  tDEC: TDegrees;
  tempAz, tempEl: TDegrees;
  HalfHPBW: TDegrees;
  AzLock, ElLock: boolean;
begin
  with imgSkyMap.Canvas do
    Draw(0, 0, imgTemp.Picture.Graphic); // Copies imgTemp to imgSkyMa
  imgSkyMap.Canvas.Refresh;
  // After changing the image you must refresh the canvas.

  RaDecToAzEl(StarRa, StarDEC, frmMount.Latitude, frmMount.Longitude, FStarAz, FStarEl);
  if Searching then
  begin // S E A R C H I N G
    tempAz := frmMount.getAzBlack;
    tempEl := frmMount.getElBlack;
    HalfHPBW := frmMount.HPBW / 2;
    // if ((abs(tempAz - StarAz) < (frmMount.HPBW / 2)) AND (abs(tempEl - StarEl) < (frmMount.HPBW / 2)))
    // if ((abs(tempAz - StarAz AND (abs(tempEl - StarEl) < HalfHPBW)) then
    If (abs(tempAz - StarAz) < HalfHPBW) then
      AzLock := True
    else
    begin
      AzLock := False;
{$IF Not Defined(Clock)}
      frmAntenna.AzYellow := StarAz;

{$ENDIF}
    end;

    if (abs(tempEl - StarEl) < HalfHPBW) then
      ElLock := True
    else
    begin
      ElLock := False;
{$IF Not Defined(Clock)}
      frmAntenna.ElYellow := StarEl;
{$ENDIF}
    end;

    if AzLock AND ElLock then

    begin // Locked
      FLocked := True; // We are all locked up on the star
      ledLocked.LED.ColorOn := clLime;
      ledLocked.Checked := True;
    end
    else

    begin // Not Locked
      FLocked := False; // Closing but not there yet
      ledLocked.LED.ColorOn := clYellow;
      ledLocked.Checked := True;

    end;
  end

  else
  begin
    // N O T   S E A R C H I N G
    swSearch.Checked := False;
    ledLocked.LED.ColorOff := clSilver;
    ledLocked.Checked := False;
  end;
  // Calculate where antenna is

  AzElToRaDec(frmMount.Azimuth, frmMount.Elevation, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

  sbAnt.Panels[0].Text := 'RA:  ' + FormatData(AntennaRa, 6, 2); // FormatData is part of SDL_stringl
  sbAnt.Panels[1].Text := 'DEC: ' + FormatData(AntennaDEC, 6, 2);
  sbAnt.Panels[2].Text := 'AZ:  ' + FormatData(frmMount.Azimuth, 6, 2);
  sbAnt.Panels[3].Text := 'EL:  ' + FormatData(frmMount.Elevation, 6, 2);
  sbAnt.Panels[4].Text := 'Hr:  ' + FormatData(getAntHa, 6, 2);

  // Update the bottom status bar for  antenna and star DEC/Ra
  sbStar.Panels[0].Text := 'RA:  ' + FormatData(StarRa, 6, 2);
  sbStar.Panels[1].Text := 'DEC: ' + FormatData(StarDEC, 6, 2);
  RaDecToAzEl(StarRa, StarDEC, frmMount.Latitude, frmMount.Longitude, FStarAz, FStarEl);
  // Find current star  position
  sbStar.Panels[2].Text := 'AZ:  ' + FormatData(StarAz, 6, 2);
  sbStar.Panels[3].Text := 'EL:  ' + FormatData(StarEl, 6, 2);

  sbStar.Panels[4].Text := 'Hr:  ' + FormatData(RAToHa(StarRa, frmMount.Longitude), 6, 2);

end; // refresh

procedure TfrmSkyMap.DrawSunrise(ElMin: TDegrees);
var
  PixX, PixY: Integer;
  X, lastX: Integer;
  tRa: THours;
  tDEC: TDegrees;
  tHa: THours;
begin

  with imgSkyMap.Canvas do
  begin
    AzElToRaDec(frmMount.AzStart, frmMount.ElStart, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

    RAToPix(0, PixX);
    DECToPix(tDEC, PixY);
    MoveTo(PixX, PixY);
    lastX := PixX;

    X := 941;
    while X >= 0 do
    begin

      AzElToRaDec(X, ElMin, frmMount.Latitude, frmMount.Longitude, tRa, tDEC);

      RAToPix(tRa, PixX);
      DECToPix(tDEC, PixY);
      if abs(lastX - PixX) > 100 then // Gona jump captn.
        MoveTo(PixX, PixY) // To BIG just move
      else
        LineTo(PixX, PixY);
      X := X - 1;
      lastX := PixX;
    end;

  end;
end;

procedure TfrmSkyMap.DrawL4L5;

var
  L4RaDEC, L5RaDEC: TEquatorialStarLoc;
  timesetL4, timesetL5: Ttimeset;

  intsec60Deg: Int64;
  dateL4: TDateTime; // Earth position + 60 degrees
  strDateL4: string;
  dateL5: TDateTime; // Earth position - 60 degrees
  strDateL5: string;
  X, Y: Integer;

begin // Julian year aj of exactly 31557600 seconds

  intsec60Deg := Trunc(secSIyear);
  dateL4 := IncSecond(Now, intsec60Deg);
  // Add 60 degrees worth of seconds to today
  strDateL4 := DateTimeToStr(dateL4);

  with timesetL4 do
  begin // yr, mo, dy, hr, mi, se, hu: word;
    yr := YearOf(dateL4);
    mo := MonthOf(dateL4);
    dy := DayOf(dateL4);
    hr := HourOf(dateL4);
    mi := MinuteOf(dateL4);
    se := SecondOf(dateL4);
    hu := 0;
  end;
  L4RaDEC := getSunPosition(timesetL4);
  FL4Ra := L4RaDEC.RA;
  FL4DEC := L4RaDEC.DEC;

  with imgSkyMap.Canvas do
  begin

    Brush.Color := clYellow;
    Brush.Style := bsSolid;

    Pen.Color := clWhite; // Draw the cross
    Pen.Width := 1;
    Pen.Mode := pmWhite;
    RAToPix(L4RaDEC.RA, X);
    DECToPix(L4RaDEC.DEC, Y);

    TextOut(X, Y, ' L4 ');

  end;
  dateL5 := IncSecond(Now, -intsec60Deg);
  // Subtract 60 degrees worth of seconds to today
  strDateL5 := DateTimeToStr(dateL5);
  with timesetL5 do
  begin // yr, mo, dy, hr, mi, se, hu: word;
    yr := YearOf(dateL5);
    mo := MonthOf(dateL5);
    dy := DayOf(dateL5);
    hr := HourOf(dateL5);
    mi := MinuteOf(dateL5);
    se := SecondOf(dateL5);
    hu := 0;
  end;
  L5RaDEC := getSunPosition(timesetL5);

  with imgSkyMap.Canvas do
  begin

    Brush.Color := clYellow;
    Brush.Style := bsSolid;

    Pen.Color := clWhite; // Draw the cross
    Pen.Width := 1;
    Pen.Mode := pmWhite;
    RAToPix(L5RaDEC.RA, X);
    DECToPix(L5RaDEC.DEC, Y);

    TextOut(X, Y, ' L5 ');

  end;

  FL5Ra := L5RaDEC.RA;
  FL5DEC := L5RaDEC.DEC;
end;

end.
