anchor.diff:      function TimeFolder: string;
     protected
       // tile generation
  -    //procedure GenerateTileLock; virtual; abstract;
       function doGenerateTilePreCalc: Boolean; virtual;
       function GenerateTilePreCalc(aThreadPool: TMyThreadPool): Boolean; virtual;
       function GenerateTileCalc(const aExtent: TExtent; aBitmap: FMX.Graphics.TBitmap; aPixelWidth, aPixelHeight: Double): TGenerateTileStatus; virtual; abstract;
  -    //procedure GenerateTileUnLock; virtual; abstract;
       function getDataValueAtPoint(const aLat, aLon: Double; var aValue: Double): TGenerateTileStatus; virtual;
  +    function GenerateTileCache(const aExtent: TExtent; var aStream: TStream; aWidthPixels, aHeightPixels: Integer; const aFileName, aCacheFolder: string): TGenerateTileStatus;
     public
       function GenerateTile(const aExtent: TExtent; var aStream: TStream; aWidthPixels, aHeightPixels: Integer; const aFileName, aCacheFolder: string; aThreadPool: TMyThreadPool=nil): Integer; virtual;
       function PointValue(const aLat, aLon: Double; aThreadPool: TMyThreadPool=nil): Double; virtual;
  
positive.code:   rpLat = 'lat';
    rpLon = 'lon';
    rpTime = 'time'; // yyyymmddhhmmss
    //rpNewURL = 'url';
  
    SliceTimeIDFormat = 'yyyymmdd.hhnn';
  
    HSC_SUCCESS_OK = 200;
    HSC_SUCCESS_CREATED = 201;
  
    HSC_ERROR_BADREQUEST = 400;
    HSC_ERROR_UNAUTHORIZED = 401;
  
negative.code:             begin
                aBitmap.Canvas.Stroke.Color := TAlphaColorRec.Black or TAlphaColorRec.Alpha;
              end;
              aBitmap.Canvas.Stroke.Thickness := 2; // todo: default width?
              aBitmap.Canvas.DrawPath(path, 1);
            finally
  