You've already forked lazarus-ccr
LazMapViewer: Fixes issues with painting/multithreading. Issue #39063, patch by Yuliyan Ivanov.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9092 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -60,8 +60,12 @@ Type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
FPimage, GraphType, FPReadJPEG;
|
FPimage, GraphType, FPReadJPEG, DateUtils;
|
||||||
|
|
||||||
|
const
|
||||||
|
MEMCACHE_MAX = 64; // Tiles kept in memory
|
||||||
|
MEMCACHE_SWEEP_CNT = 10; // Max tiles to be swept at once
|
||||||
|
DISKCACHE_MAXAGE = 10 * 86400; // 10 days
|
||||||
|
|
||||||
{ TPictureCache }
|
{ TPictureCache }
|
||||||
|
|
||||||
@ -104,7 +108,7 @@ end;
|
|||||||
constructor TPictureCache.Create(aOwner: TComponent);
|
constructor TPictureCache.Create(aOwner: TComponent);
|
||||||
begin
|
begin
|
||||||
inherited Create(aOwner);
|
inherited Create(aOwner);
|
||||||
FMemMaxElem := 2048 div 256;
|
FMemMaxElem := MEMCACHE_MAX;
|
||||||
Cache := TStringList.create;
|
Cache := TStringList.create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -200,11 +204,13 @@ end;
|
|||||||
function TPictureCache.DiskCached(const aFileNAme: String): Boolean;
|
function TPictureCache.DiskCached(const aFileNAme: String): Boolean;
|
||||||
var
|
var
|
||||||
FullFileName: string;
|
FullFileName: string;
|
||||||
|
Age: LongInt;
|
||||||
begin
|
begin
|
||||||
if UseDisk then
|
if UseDisk then
|
||||||
begin
|
begin
|
||||||
FullFileName := BasePath + aFileName;
|
FullFileName := BasePath + aFileName;
|
||||||
Result := FileExists(FullFileName);
|
Age := FileAge(fullFileName);
|
||||||
|
Result := Age > (DateTimeToUnix(Now, False) - DISKCACHE_MAXAGE);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Result := False;
|
Result := False;
|
||||||
@ -217,9 +223,9 @@ var
|
|||||||
lStream: TFileStream;
|
lStream: TFileStream;
|
||||||
begin
|
begin
|
||||||
img := nil;
|
img := nil;
|
||||||
FullFileName := BasePath + aFileName;
|
if DiskCached(aFileName) then
|
||||||
if FileExists(fullFileName) then
|
|
||||||
begin
|
begin
|
||||||
|
FullFileName := BasePath + aFileName;
|
||||||
lStream := TFileStream.Create(FullFileName, fmOpenRead);
|
lStream := TFileStream.Create(FullFileName, fmOpenRead);
|
||||||
try
|
try
|
||||||
try
|
try
|
||||||
@ -258,7 +264,7 @@ begin
|
|||||||
try
|
try
|
||||||
if Cache.Count > FMemMaxElem then
|
if Cache.Count > FMemMaxElem then
|
||||||
begin
|
begin
|
||||||
for i:=1 to 10 do
|
for i := 1 to MEMCACHE_SWEEP_CNT do
|
||||||
begin
|
begin
|
||||||
idx := pred(Cache.Count);
|
idx := pred(Cache.Count);
|
||||||
if idx > 1 then
|
if idx > 1 then
|
||||||
@ -311,9 +317,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not FUseThreads then
|
|
||||||
CheckCacheSize(self);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPictureCache.GetFromCache(MapProvider: TMapProvider;
|
procedure TPictureCache.GetFromCache(MapProvider: TMapProvider;
|
||||||
|
@ -36,6 +36,8 @@ type
|
|||||||
TDrawStretchedTileEvent = procedure (const TileId: TTileId; X,Y: Integer;
|
TDrawStretchedTileEvent = procedure (const TileId: TTileId; X,Y: Integer;
|
||||||
TileImg: TLazIntfImage; const R: TRect) of object;
|
TileImg: TLazIntfImage; const R: TRect) of object;
|
||||||
|
|
||||||
|
TTileDownloadedEvent = procedure (const TileId: TTileId) of object;
|
||||||
|
|
||||||
TTileIdArray = Array of TTileId;
|
TTileIdArray = Array of TTileId;
|
||||||
|
|
||||||
TDistanceUnits = (duMeters, duKilometers, duMiles);
|
TDistanceUnits = (duMeters, duKilometers, duMiles);
|
||||||
@ -71,6 +73,7 @@ type
|
|||||||
FOnChange: TNotifyEvent;
|
FOnChange: TNotifyEvent;
|
||||||
FOnDrawTile: TDrawTileEvent;
|
FOnDrawTile: TDrawTileEvent;
|
||||||
FOnDrawStretchedTile: TDrawStretchedTileEvent;
|
FOnDrawStretchedTile: TDrawStretchedTileEvent;
|
||||||
|
FOnTileDownloaded: TTileDownloadedEvent;
|
||||||
FOnZoomChange: TNotifyEvent;
|
FOnZoomChange: TNotifyEvent;
|
||||||
lstProvider : TStringList;
|
lstProvider : TStringList;
|
||||||
Queue : TJobQueue;
|
Queue : TJobQueue;
|
||||||
@ -106,7 +109,7 @@ type
|
|||||||
procedure CalculateWin(var AWin: TMapWindow);
|
procedure CalculateWin(var AWin: TMapWindow);
|
||||||
function DegreesToPixelsEPSG3395(const AWin: TMapWindow; ALonLat: TRealPoint): TPoint;
|
function DegreesToPixelsEPSG3395(const AWin: TMapWindow; ALonLat: TRealPoint): TPoint;
|
||||||
function DegreesToPixelsEPSG3857(const AWin: TMapWindow; ALonLat: TRealPoint): TPoint;
|
function DegreesToPixelsEPSG3857(const AWin: TMapWindow; ALonLat: TRealPoint): TPoint;
|
||||||
procedure Redraw(const aWin: TMapWindow);
|
procedure Redraw(const aWin: TMapWindow; const paintOnly: Boolean = False);
|
||||||
function CalculateVisibleTiles(const aWin: TMapWindow) : TArea;
|
function CalculateVisibleTiles(const aWin: TMapWindow) : TArea;
|
||||||
function IsCurrentWin(const aWin: TMapWindow) : boolean;
|
function IsCurrentWin(const aWin: TMapWindow) : boolean;
|
||||||
protected
|
protected
|
||||||
@ -115,6 +118,7 @@ type
|
|||||||
function GetTileName(const Id: TTileId): String;
|
function GetTileName(const Id: TTileId): String;
|
||||||
procedure evDownload(Data: TObject; Job: TJob);
|
procedure evDownload(Data: TObject; Job: TJob);
|
||||||
procedure TileDownloaded(Data: PtrInt);
|
procedure TileDownloaded(Data: PtrInt);
|
||||||
|
procedure DrawTileFromCache(constref ATile: TTileId; constref AWin: TMapWindow);
|
||||||
procedure DrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TLazIntfImage; const R: TRect);
|
procedure DrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TLazIntfImage; const R: TRect);
|
||||||
Procedure DrawTile(const TileId: TTileId; X,Y: integer; TileImg: TLazIntfImage);
|
Procedure DrawTile(const TileId: TTileId; X,Y: integer; TileImg: TLazIntfImage);
|
||||||
Procedure DoDrag(Sender: TDragObj);
|
Procedure DoDrag(Sender: TDragObj);
|
||||||
@ -176,6 +180,7 @@ type
|
|||||||
property OnChange: TNotifyEvent Read FOnChange write FOnchange; //called when visiable area change
|
property OnChange: TNotifyEvent Read FOnChange write FOnchange; //called when visiable area change
|
||||||
property OnDrawStretchedTile: TDrawStretchedTileEvent read FOnDrawStretchedTile write FOnDrawStretchedTile;
|
property OnDrawStretchedTile: TDrawStretchedTileEvent read FOnDrawStretchedTile write FOnDrawStretchedTile;
|
||||||
property OnDrawTile: TDrawTileEvent read FOnDrawTile write FOnDrawTile;
|
property OnDrawTile: TDrawTileEvent read FOnDrawTile write FOnDrawTile;
|
||||||
|
property OnTileDownloaded: TTileDownloadedEvent read FOnTileDownloaded write FOnTileDownloaded;
|
||||||
property OnZoomChange: TNotifyEvent read FOnZoomChange write FOnZoomChange;
|
property OnZoomChange: TNotifyEvent read FOnZoomChange write FOnZoomChange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -233,32 +238,8 @@ begin
|
|||||||
Result := round(IntPower(2, AZoomLevel));
|
Result := round(IntPower(2, AZoomLevel));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
{ TLaunchDownloadJob }
|
|
||||||
|
|
||||||
TLaunchDownloadJob = class(TJob)
|
|
||||||
private
|
|
||||||
AllRun: boolean;
|
|
||||||
Win: TMapWindow;
|
|
||||||
Engine: TMapViewerEngine;
|
|
||||||
FRunning: boolean;
|
|
||||||
FTiles: TTileIdArray;
|
|
||||||
FStates: Array of integer;
|
|
||||||
protected
|
|
||||||
function pGetTask: integer; override;
|
|
||||||
procedure pTaskStarted(aTask: integer); override;
|
|
||||||
procedure pTaskEnded(aTask: integer; aExcept: Exception); override;
|
|
||||||
public
|
|
||||||
procedure ExecuteTask(aTask: integer; FromWaiting: boolean); override;
|
|
||||||
function Running: boolean; override;
|
|
||||||
public
|
|
||||||
constructor Create(Eng: TMapViewerEngine; const Tiles: TTileIdArray;
|
|
||||||
const aWin: TMapWindow);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{ TEnvTile }
|
{ TEnvTile }
|
||||||
|
|
||||||
TEnvTile = Class(TBaseTile)
|
TEnvTile = Class(TBaseTile)
|
||||||
@ -285,90 +266,6 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TLaunchDownloadJob }
|
|
||||||
|
|
||||||
function TLaunchDownloadJob.pGetTask: integer;
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
begin
|
|
||||||
if not AllRun and not Cancelled then
|
|
||||||
begin
|
|
||||||
for i:=Low(FStates) to High(FStates) do
|
|
||||||
if FStates[i] = 0 then
|
|
||||||
begin
|
|
||||||
Result := i + 1;
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
AllRun := True;
|
|
||||||
end;
|
|
||||||
Result := ALL_TASK_COMPLETED;
|
|
||||||
for i := Low(FStates) to High(FStates) do
|
|
||||||
if FStates[i] = 1 then
|
|
||||||
begin
|
|
||||||
Result := NO_MORE_TASK;
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TLaunchDownloadJob.pTaskStarted(aTask: integer);
|
|
||||||
begin
|
|
||||||
FRunning := True;
|
|
||||||
FStates[aTask-1] := 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TLaunchDownloadJob.pTaskEnded(aTask: integer; aExcept: Exception);
|
|
||||||
begin
|
|
||||||
if Assigned(aExcept) then
|
|
||||||
FStates[aTask - 1] := 3
|
|
||||||
Else
|
|
||||||
FStates[aTask - 1] := 2;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TLaunchDownloadJob.ExecuteTask(aTask: integer; FromWaiting: boolean);
|
|
||||||
var
|
|
||||||
iTile: integer;
|
|
||||||
lJob: TEventJob;
|
|
||||||
lTile: TEnvTile;
|
|
||||||
begin
|
|
||||||
iTile := aTask - 1;
|
|
||||||
lTile:=TEnvTile.Create(FTiles[iTile], Win);
|
|
||||||
lJob := TEventJob.Create
|
|
||||||
(
|
|
||||||
@Engine.evDownload,
|
|
||||||
lTile,
|
|
||||||
false, // owns data
|
|
||||||
Engine.GetTileName(FTiles[iTile])
|
|
||||||
);
|
|
||||||
if not Queue.AddUniqueJob(lJob ,
|
|
||||||
Launcher
|
|
||||||
) then
|
|
||||||
begin
|
|
||||||
FreeAndNil(lJob);
|
|
||||||
FreeAndNil(lTile);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TLaunchDownloadJob.Running: boolean;
|
|
||||||
begin
|
|
||||||
Result := FRunning;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TLaunchDownloadJob.Create(Eng: TMapViewerEngine;
|
|
||||||
const Tiles: TTileIdArray; const aWin: TMapWindow);
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
begin
|
|
||||||
Engine := Eng;
|
|
||||||
SetLength(FTiles, Length(Tiles));
|
|
||||||
For i:=Low(FTiles) to High(FTiles) do
|
|
||||||
FTiles[i] := Tiles[i];
|
|
||||||
SetLength(FStates, Length(Tiles));
|
|
||||||
AllRun := false;
|
|
||||||
Name := 'LaunchDownload';
|
|
||||||
Win := aWin;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{ TEnvTile }
|
{ TEnvTile }
|
||||||
|
|
||||||
constructor TEnvTile.Create(const aTile: TTileId; const aWin: TMapWindow);
|
constructor TEnvTile.Create(const aTile: TTileId; const aWin: TMapWindow);
|
||||||
@ -392,7 +289,6 @@ begin
|
|||||||
FBkColor := colWhite;
|
FBkColor := colWhite;
|
||||||
RegisterProviders;
|
RegisterProviders;
|
||||||
Queue := TJobQueue.Create(8);
|
Queue := TJobQueue.Create(8);
|
||||||
Queue.OnIdle := @Cache.CheckCacheSize;
|
|
||||||
|
|
||||||
inherited Create(aOwner);
|
inherited Create(aOwner);
|
||||||
|
|
||||||
@ -531,8 +427,8 @@ begin
|
|||||||
MoveMapCenter(Sender);
|
MoveMapCenter(Sender);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapViewerEngine.DrawStretchedTile(const TileID: TTileID; X, Y: Integer;
|
procedure TMapViewerEngine.DrawStretchedTile(const TileId: TTileID; X,
|
||||||
TileImg: TLazIntfImage; const R: TRect);
|
Y: Integer; TileImg: TLazIntfImage; const R: TRect);
|
||||||
begin
|
begin
|
||||||
if Assigned(FOnDrawStretchedTile) then
|
if Assigned(FOnDrawStretchedTile) then
|
||||||
FOnDrawStretchedTile(TileId, X, Y, TileImg, R);
|
FOnDrawStretchedTile(TileId, X, Y, TileImg, R);
|
||||||
@ -652,7 +548,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TMapViewerEngine.IsValidTile(const aWin: TMapWindow;
|
function TMapViewerEngine.IsValidTile(const aWin: TMapWindow;
|
||||||
const aTile: TTileId): boolean;
|
const aTile: TTIleId): boolean;
|
||||||
var
|
var
|
||||||
tiles: int64;
|
tiles: int64;
|
||||||
begin
|
begin
|
||||||
@ -806,7 +702,8 @@ begin
|
|||||||
Result.Lon := Math.EnsureRange(Result.Lon, MIN_LONGITUDE, MAX_LONGITUDE);
|
Result.Lon := Math.EnsureRange(Result.Lon, MIN_LONGITUDE, MAX_LONGITUDE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Function TMapViewerEngine.PixelsToDegreesEPSG3395(APoint: TPoint; Zoom: Integer): TRealPoint;
|
function TMapViewerEngine.PixelsToDegreesEPSG3395(APoint: TPoint; Zoom: Integer
|
||||||
|
): TRealPoint;
|
||||||
|
|
||||||
function PhiIteration(y, phi: Extended): Extended;
|
function PhiIteration(y, phi: Extended): Extended;
|
||||||
var
|
var
|
||||||
@ -1048,18 +945,33 @@ begin
|
|||||||
Redraw(MapWin);
|
Redraw(MapWin);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapViewerEngine.Redraw(const AWin: TMapWindow);
|
procedure TMapViewerEngine.Redraw(const aWin: TMapWindow;
|
||||||
|
const paintOnly: Boolean);
|
||||||
var
|
var
|
||||||
TilesVis: TArea;
|
TilesVis: TArea;
|
||||||
x, y : Integer; //int64;
|
x, y, px, py: Integer;
|
||||||
|
iTile, numTiles: Integer;
|
||||||
Tiles: TTileIdArray = nil;
|
Tiles: TTileIdArray = nil;
|
||||||
iTile: Integer;
|
|
||||||
tile: TTileID;
|
tile: TTileID;
|
||||||
numTiles: Integer;
|
|
||||||
px, py: Integer;
|
|
||||||
previewDrawn: Boolean;
|
previewDrawn: Boolean;
|
||||||
previewImg: TLazIntfImage;
|
previewImg: TLazIntfImage;
|
||||||
R: TRect;
|
R: TRect;
|
||||||
|
|
||||||
|
procedure AddJob;
|
||||||
|
var
|
||||||
|
lTile: TEnvTile;
|
||||||
|
lJob: TEventJob;
|
||||||
|
begin
|
||||||
|
lTile:=TEnvTile.Create(Tiles[iTile], aWin);
|
||||||
|
lJob := TEventJob.Create(@evDownload, lTile, False, // owns data
|
||||||
|
GetTileName(Tiles[iTile]));
|
||||||
|
if not Queue.AddUniqueJob(lJob, Self) then
|
||||||
|
begin
|
||||||
|
FreeAndNil(lJob);
|
||||||
|
FreeAndNil(lTile);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if not(Active) then
|
if not(Active) then
|
||||||
Exit;
|
Exit;
|
||||||
@ -1082,9 +994,11 @@ begin
|
|||||||
Tiles[iTile].Y := Y;
|
Tiles[iTile].Y := Y;
|
||||||
Tiles[iTile].Z := AWin.Zoom;
|
Tiles[iTile].Z := AWin.Zoom;
|
||||||
|
|
||||||
|
if Cache.InCache(AWin.MapProvider, Tiles[iTile]) then
|
||||||
|
DrawTileFromCache(Tiles[iTile], AWin)
|
||||||
|
else
|
||||||
// Avoid tiling artefacts when a tile does not exist (lowest zoom) or
|
// Avoid tiling artefacts when a tile does not exist (lowest zoom) or
|
||||||
// is not valid
|
// is not valid
|
||||||
if not Cache.InCache(AWin.MapProvider, Tiles[iTile]) then
|
|
||||||
begin
|
begin
|
||||||
previewdrawn := False;
|
previewdrawn := False;
|
||||||
py := AWin.Y + Y * TILE_SIZE;
|
py := AWin.Y + Y * TILE_SIZE;
|
||||||
@ -1104,14 +1018,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
if not previewDrawn then
|
if not previewDrawn then
|
||||||
DrawTile(Tiles[iTile], px, py, nil); // Draw blank tile if preview cannot be generated
|
DrawTile(Tiles[iTile], px, py, nil); // Draw blank tile if preview cannot be generated
|
||||||
end;
|
|
||||||
|
|
||||||
if IsValidTile(AWin, Tiles[iTile]) then
|
if IsValidTile(AWin, Tiles[iTile]) then
|
||||||
|
begin
|
||||||
|
AddJob;
|
||||||
inc(iTile);
|
inc(iTile);
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
SetLength(Tiles, iTile);
|
SetLength(Tiles, iTile);
|
||||||
if Length(Tiles) > 0 then
|
if Length(Tiles) < 1 then
|
||||||
Queue.AddJob(TLaunchDownloadJob.Create(self, Tiles, AWin), self);
|
Cache.CheckCacheSize(Nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapViewerEngine.RegisterProviders;
|
procedure TMapViewerEngine.RegisterProviders;
|
||||||
@ -1270,48 +1187,57 @@ end;
|
|||||||
procedure TMapViewerEngine.TileDownloaded(Data: PtrInt);
|
procedure TMapViewerEngine.TileDownloaded(Data: PtrInt);
|
||||||
var
|
var
|
||||||
EnvTile: TEnvTile;
|
EnvTile: TEnvTile;
|
||||||
|
begin
|
||||||
|
EnvTile := TEnvTile(Data);
|
||||||
|
try
|
||||||
|
if Assigned(FOnTileDownloaded) then
|
||||||
|
FOnTileDownloaded(EnvTile.Tile);
|
||||||
|
finally
|
||||||
|
FreeAndNil(EnvTile);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMapViewerEngine.DrawTileFromCache(constref ATile: TTileId; constref
|
||||||
|
AWin: TMapWindow);
|
||||||
|
var
|
||||||
img: TLazIntfImage;
|
img: TLazIntfImage;
|
||||||
X, Y: integer;
|
X, Y: integer;
|
||||||
worldWidth : Integer;
|
worldWidth : Integer;
|
||||||
numTiles : Integer;
|
numTiles : Integer;
|
||||||
baseX : Integer;
|
baseX : Integer;
|
||||||
begin
|
begin
|
||||||
EnvTile := TEnvTile(Data);
|
if IsCurrentWin(AWin)then
|
||||||
try
|
|
||||||
if IsCurrentWin(EnvTile.Win)then
|
|
||||||
begin
|
begin
|
||||||
Cache.GetFromCache(EnvTile.Win.MapProvider, EnvTile.Tile, img);
|
Cache.GetFromCache(AWin.MapProvider, ATile, img);
|
||||||
Y := EnvTile.Win.Y + EnvTile.Tile.Y * TILE_SIZE; // begin of Y
|
Y := AWin.Y + ATile.Y * TILE_SIZE; // begin of Y
|
||||||
if Cyclic then
|
if Cyclic then
|
||||||
begin
|
begin
|
||||||
baseX := EnvTile.Win.X + EnvTile.Tile.X * TILE_SIZE; // begin of X
|
baseX := AWin.X + ATile.X * TILE_SIZE; // begin of X
|
||||||
numTiles := 1 shl EnvTile.Win.Zoom;
|
numTiles := 1 shl AWin.Zoom;
|
||||||
worldWidth := numTiles * TILE_SIZE;
|
worldWidth := numTiles * TILE_SIZE;
|
||||||
// From the center to the left (western) hemisphere
|
// From the center to the left (western) hemisphere
|
||||||
X := baseX;
|
X := baseX;
|
||||||
while (X+TILE_SIZE >= 0) do
|
while (X+TILE_SIZE >= 0) do
|
||||||
begin
|
begin
|
||||||
DrawTile(EnvTile.Tile, X, Y, img);
|
DrawTile(ATile, X, Y, img);
|
||||||
X := X - worldWidth;
|
X := X - worldWidth;
|
||||||
end;
|
end;
|
||||||
// From the center to the right (eastern) hemisphere
|
// From the center to the right (eastern) hemisphere
|
||||||
X := baseX + worldWidth;
|
X := baseX + worldWidth;
|
||||||
while ((X-TILE_SIZE) <= EnvTile.Win.Width) do
|
while ((X-TILE_SIZE) <= AWin.Width) do
|
||||||
begin
|
begin
|
||||||
DrawTile(EnvTile.Tile, X, Y, img);
|
DrawTile(ATile, X, Y, img);
|
||||||
X := X + worldWidth;
|
X := X + worldWidth;
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
X := EnvTile.Win.X + EnvTile.Tile.X * TILE_SIZE; // begin of X
|
X := AWin.X + ATile.X * TILE_SIZE; // begin of X
|
||||||
DrawTile(EnvTile.Tile, X, Y, img);
|
DrawTile(ATile, X, Y, img);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
finally
|
|
||||||
FreeAndNil(EnvTile);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TMapViewerEngine.WorldScreenToLonLat(aPt: TPoint): TRealPoint;
|
function TMapViewerEngine.WorldScreenToLonLat(aPt: TPoint): TRealPoint;
|
||||||
begin
|
begin
|
||||||
aPt.X := aPt.X - MapWin.X;
|
aPt.X := aPt.X - MapWin.X;
|
||||||
|
@ -30,21 +30,20 @@ type
|
|||||||
TGPSObj = class
|
TGPSObj = class
|
||||||
private
|
private
|
||||||
BBoxSet: Boolean;
|
BBoxSet: Boolean;
|
||||||
FBoundingBox: TRealArea;
|
|
||||||
FExtraData: TObject;
|
FExtraData: TObject;
|
||||||
FName: String;
|
FName: String;
|
||||||
FIdOwner: integer;
|
FIdOwner: integer;
|
||||||
function GetBoundingBox: TRealArea;
|
function GetBoundingBox: TRealArea;
|
||||||
procedure SetBoundingBox(AValue: TRealArea);
|
|
||||||
procedure SetExtraData(AValue: TObject);
|
procedure SetExtraData(AValue: TObject);
|
||||||
public
|
public
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Assign(AObj: TGPSObj); virtual;
|
procedure Assign(AObj: TGPSObj); virtual;
|
||||||
procedure GetArea(out Area: TRealArea); virtual; abstract;
|
procedure GetArea(out Area: TRealArea); virtual; abstract;
|
||||||
|
procedure Draw(AView: TObject; Area: TRealArea); virtual; abstract;
|
||||||
property Name: String read FName write FName;
|
property Name: String read FName write FName;
|
||||||
property ExtraData: TObject read FExtraData write SetExtraData;
|
property ExtraData: TObject read FExtraData write SetExtraData;
|
||||||
property IdOwner: Integer read FIdOwner;
|
property IdOwner: Integer read FIdOwner;
|
||||||
property BoundingBox: TRealArea read GetBoundingBox write SetBoundingBox;
|
property BoundingBox: TRealArea read GetBoundingBox;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TGPSObjarray = Array of TGPSObj;
|
TGPSObjarray = Array of TGPSObj;
|
||||||
@ -66,6 +65,7 @@ type
|
|||||||
|
|
||||||
procedure Assign(AObj: TGPSObj); override;
|
procedure Assign(AObj: TGPSObj); override;
|
||||||
procedure GetArea(out Area: TRealArea);override;
|
procedure GetArea(out Area: TRealArea);override;
|
||||||
|
procedure Draw({%H-}AView: TObject; {%H-}Area: TRealArea); override;
|
||||||
function HasElevation: boolean;
|
function HasElevation: boolean;
|
||||||
function HasDateTime: Boolean;
|
function HasDateTime: Boolean;
|
||||||
function DistanceInKmFrom(OtherPt: TGPSPoint; UseElevation: boolean=true): double;
|
function DistanceInKmFrom(OtherPt: TGPSPoint; UseElevation: boolean=true): double;
|
||||||
@ -89,6 +89,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(ALon, ALat: Double; AElevation: Double = NO_ELE;
|
constructor Create(ALon, ALat: Double; AElevation: Double = NO_ELE;
|
||||||
ADateTime: TDateTime = NO_DATE);
|
ADateTime: TDateTime = NO_DATE);
|
||||||
|
procedure Draw({%H-}AView: TObject; {%H-}Area: TRealArea); override;
|
||||||
property ImageIndex: Integer read FImageIndex write FImageIndex default -1;
|
property ImageIndex: Integer read FImageIndex write FImageIndex default -1;
|
||||||
end;
|
end;
|
||||||
{ TGPSTrack }
|
{ TGPSTrack }
|
||||||
@ -106,6 +107,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
procedure GetArea(out Area: TRealArea); override;
|
procedure GetArea(out Area: TRealArea); override;
|
||||||
|
procedure Draw({%H-}AView: TObject; {%H-}Area: TRealArea); override;
|
||||||
function TrackLengthInKm(UseEle: Boolean=true): double;
|
function TrackLengthInKm(UseEle: Boolean=true): double;
|
||||||
|
|
||||||
property Points: TGPSPointList read FPoints;
|
property Points: TGPSPointList read FPoints;
|
||||||
@ -155,6 +157,7 @@ type
|
|||||||
procedure ClearExcept(OwnedBy: integer; const ExceptLst: TIdArray;
|
procedure ClearExcept(OwnedBy: integer; const ExceptLst: TIdArray;
|
||||||
out Notfound: TIdArray);
|
out Notfound: TIdArray);
|
||||||
procedure GetArea(out Area: TRealArea); override;
|
procedure GetArea(out Area: TRealArea); override;
|
||||||
|
procedure Draw({%H-}AView: TObject; {%H-}Area: TRealArea); override;
|
||||||
function GetObjectsInArea(const Area: TRealArea): TGPSObjList;
|
function GetObjectsInArea(const Area: TRealArea): TGPSObjList;
|
||||||
function GetIdsArea(const Ids: TIdArray; AIdOwner: integer): TRealArea;
|
function GetIdsArea(const Ids: TIdArray; AIdOwner: integer): TRealArea;
|
||||||
|
|
||||||
@ -184,7 +187,7 @@ function GetAreaOf(objs: TGPSObjList): TRealArea;
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
mvExtraData;
|
mvExtraData, mvMapViewer;
|
||||||
|
|
||||||
function hasIntersectArea(const Area1: TRealArea; const Area2: TRealArea): boolean;
|
function hasIntersectArea(const Area1: TRealArea; const Area2: TRealArea): boolean;
|
||||||
begin
|
begin
|
||||||
@ -249,19 +252,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TGPSObj.GetBoundingBox: TRealArea;
|
function TGPSObj.GetBoundingBox: TRealArea;
|
||||||
|
var
|
||||||
|
A: TRealArea;
|
||||||
begin
|
begin
|
||||||
if not(BBoxSet) then
|
GetArea(A);
|
||||||
begin
|
Result := A;
|
||||||
GetArea(FBoundingBox);
|
|
||||||
BBoxSet := true;
|
|
||||||
end;
|
|
||||||
Result := FBoundingBox;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGPSObj.SetBoundingBox(AValue: TRealArea);
|
|
||||||
begin
|
|
||||||
FBoundingBox := AValue;
|
|
||||||
BBoxSet := true;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TGPSObj.Destroy;
|
destructor TGPSObj.Destroy;
|
||||||
@ -408,6 +403,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGPSObjectList.Draw(AView: TObject; Area: TRealArea);
|
||||||
|
begin
|
||||||
|
//;
|
||||||
|
end;
|
||||||
|
|
||||||
function TGPSObjectList.GetObjectsInArea(const Area: TRealArea): TGPSObjList;
|
function TGPSObjectList.GetObjectsInArea(const Area: TRealArea): TGPSObjList;
|
||||||
var
|
var
|
||||||
i: integer;
|
i: integer;
|
||||||
@ -628,7 +628,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGPSObjectList.FindTrackByID(const ID: Integer): TGpsTrack;
|
function TGPSObjectList.FindTrackByID(const id: Integer): TGpsTrack;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
@ -686,6 +686,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGPSTrack.Draw(AView: TObject; Area: TRealArea);
|
||||||
|
begin
|
||||||
|
TMapView(AView).DrawTrack(Area, Self);
|
||||||
|
end;
|
||||||
|
|
||||||
function TGPSTrack.TrackLengthInKm(UseEle: Boolean): double;
|
function TGPSTrack.TrackLengthInKm(UseEle: Boolean): double;
|
||||||
var
|
var
|
||||||
i: integer;
|
i: integer;
|
||||||
@ -698,7 +703,7 @@ end;
|
|||||||
|
|
||||||
{ TGPSPoint }
|
{ TGPSPoint }
|
||||||
|
|
||||||
procedure TGPSPoint.Assign(AObj: TGpsObj);
|
procedure TGPSPoint.Assign(AObj: TGPSObj);
|
||||||
begin
|
begin
|
||||||
if (AObj is TGPSPoint) then
|
if (AObj is TGPSPoint) then
|
||||||
begin
|
begin
|
||||||
@ -725,6 +730,11 @@ begin
|
|||||||
Area.BottomRight := FRealPt;
|
Area.BottomRight := FRealPt;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGPSPoint.Draw(AView: TObject; Area: TRealArea);
|
||||||
|
begin
|
||||||
|
TMapView(AView).DrawPt(Area, Self);
|
||||||
|
end;
|
||||||
|
|
||||||
function TGPSPoint.HasElevation: boolean;
|
function TGPSPoint.HasElevation: boolean;
|
||||||
begin
|
begin
|
||||||
Result := FElevation <> NO_ELE;
|
Result := FElevation <> NO_ELE;
|
||||||
@ -796,6 +806,11 @@ begin
|
|||||||
FImageIndex := -1;
|
FImageIndex := -1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGPSPointOfInterest.Draw(AView: TObject; Area: TRealArea);
|
||||||
|
begin
|
||||||
|
TMapView(AView).DrawPointOfInterest(Area, Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -107,8 +107,8 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
const
|
const
|
||||||
WAIT_TIME = 3000;
|
WAIT_TIME = 300;
|
||||||
TERMINATE_TIMEOUT = 1000;
|
TERMINATE_TIMEOUT = WAIT_TIME * 2;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -297,7 +297,6 @@ begin
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
MyQueue.FEvent.ResetEvent;
|
|
||||||
if not(RestartTask) then
|
if not(RestartTask) then
|
||||||
MyQueue.pTaskStarted(aJob, TaskId);
|
MyQueue.pTaskStarted(aJob, TaskId);
|
||||||
end;
|
end;
|
||||||
@ -366,7 +365,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Jobs := TObjectList.Create(true);
|
Jobs := TObjectList.Create(true);
|
||||||
Threads := TObjectList.Create(true);
|
Threads := TObjectList.Create(true);
|
||||||
FEvent := TEvent.Create(nil,true,false,'');
|
FEvent := TEvent.Create(Nil, False, False,'');
|
||||||
FSect := TCriticalSection.Create;
|
FSect := TCriticalSection.Create;
|
||||||
TerminatedThread := 0;
|
TerminatedThread := 0;
|
||||||
for i:=1 to FNbThread do
|
for i:=1 to FNbThread do
|
||||||
@ -383,9 +382,11 @@ begin
|
|||||||
try
|
try
|
||||||
FEvent.SetEvent;
|
FEvent.SetEvent;
|
||||||
TerminatedThread := 0;
|
TerminatedThread := 0;
|
||||||
for i:=0 to pred(Threads.Count) do
|
for i := 0 to Pred(Threads.Count) do
|
||||||
TQueueThread(Threads[i]).Terminate;
|
TQueueThread(Threads[i]).Terminate;
|
||||||
TerminateEvent.WaitFor(TERMINATE_TIMEOUT);
|
TerminateEvent.WaitFor(TERMINATE_TIMEOUT);
|
||||||
|
for i := 0 to Pred(Threads.Count) do
|
||||||
|
TQueueThread(Threads[i]).WaitFor;
|
||||||
FreeAndNil(FSect);
|
FreeAndNil(FSect);
|
||||||
FreeAndNil(FEvent);
|
FreeAndNil(FEvent);
|
||||||
FreeAndNil(Threads);
|
FreeAndNil(Threads);
|
||||||
|
@ -23,7 +23,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Controls, Graphics, FPImage, IntfGraphics, Forms, ImgList, LCLVersion,
|
Classes, SysUtils, Controls, Graphics, FPImage, IntfGraphics, Forms, ImgList, LCLVersion,
|
||||||
MvTypes, MvGPSObj, MvEngine, MvMapProvider, MvDownloadEngine, MvDrawingEngine;
|
MvTypes, MvGPSObj, MvEngine, MvMapProvider, MvDownloadEngine, MvDrawingEngine, mvCache;
|
||||||
|
|
||||||
Type
|
Type
|
||||||
|
|
||||||
@ -54,9 +54,7 @@ Type
|
|||||||
procedure CallAsyncInvalidate;
|
procedure CallAsyncInvalidate;
|
||||||
procedure DoAsyncInvalidate({%H-}Data: PtrInt);
|
procedure DoAsyncInvalidate({%H-}Data: PtrInt);
|
||||||
procedure DrawObjects(const {%H-}TileId: TTileId; aLeft, aTop, aRight,aBottom: integer);
|
procedure DrawObjects(const {%H-}TileId: TTileId; aLeft, aTop, aRight,aBottom: integer);
|
||||||
procedure DrawPointOfInterest(const {%H-}Area: TRealArea; APt: TGPSPointOfInterest);
|
procedure DrawGpsObj(const {%H-}Area: TRealArea; AObj: TGPSObj);
|
||||||
procedure DrawPt(const {%H-}Area: TRealArea; APt: TGPSPoint);
|
|
||||||
procedure DrawTrack(const Area: TRealArea; trk: TGPSTrack);
|
|
||||||
function GetCacheOnDisk: boolean;
|
function GetCacheOnDisk: boolean;
|
||||||
function GetCachePath: String;
|
function GetCachePath: String;
|
||||||
function GetCenter: TRealPoint;
|
function GetCenter: TRealPoint;
|
||||||
@ -108,6 +106,7 @@ Type
|
|||||||
procedure DoDrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TLazIntfImage; const R: TRect);
|
procedure DoDrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TLazIntfImage; const R: TRect);
|
||||||
procedure DoDrawTile(const TileId: TTileId; X,Y: integer; TileImg: TLazIntfImage);
|
procedure DoDrawTile(const TileId: TTileId; X,Y: integer; TileImg: TLazIntfImage);
|
||||||
procedure DoDrawTileInfo(const {%H-}TileID: TTileID; X,Y: Integer);
|
procedure DoDrawTileInfo(const {%H-}TileID: TTileID; X,Y: Integer);
|
||||||
|
procedure DoTileDownloaded(const TileId: TTileId);
|
||||||
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
||||||
MousePos: TPoint): Boolean; override;
|
MousePos: TPoint): Boolean; override;
|
||||||
procedure DoOnResize; override;
|
procedure DoOnResize; override;
|
||||||
@ -124,6 +123,9 @@ Type
|
|||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
procedure DrawPointOfInterest(const {%H-}Area: TRealArea; APt: TGPSPointOfInterest);
|
||||||
|
procedure DrawPt(const {%H-}Area: TRealArea; APt: TGPSPoint);
|
||||||
|
procedure DrawTrack(const Area: TRealArea; trk: TGPSTrack);
|
||||||
procedure ClearBuffer;
|
procedure ClearBuffer;
|
||||||
procedure GetMapProviders(lstProviders: TStrings);
|
procedure GetMapProviders(lstProviders: TStrings);
|
||||||
function GetVisibleArea: TRealArea;
|
function GetVisibleArea: TRealArea;
|
||||||
@ -266,13 +268,7 @@ var
|
|||||||
begin
|
begin
|
||||||
iObj := aTask-1;
|
iObj := aTask-1;
|
||||||
Obj := FLst[iObj];
|
Obj := FLst[iObj];
|
||||||
if Obj.InheritsFrom(TGPSTrack) then
|
Viewer.DrawGpsObj(FArea, Obj);
|
||||||
Viewer.DrawTrack(FArea, TGPSTrack(Obj));
|
|
||||||
if Obj.InheritsFrom(TGPSPointOfInterest) then
|
|
||||||
Viewer.DrawPointOfInterest(FArea, TGPSPointOfInterest(Obj))
|
|
||||||
else
|
|
||||||
if Obj.InheritsFrom(TGPSPoint) then
|
|
||||||
Viewer.DrawPt(FArea, TGPSPoint(Obj));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDrawObjJob.Running: boolean;
|
function TDrawObjJob.Running: boolean;
|
||||||
@ -295,8 +291,6 @@ destructor TDrawObjJob.Destroy;
|
|||||||
begin
|
begin
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
FreeAndNil(FLst);
|
FreeAndNil(FLst);
|
||||||
if not(Cancelled) then
|
|
||||||
Viewer.CallAsyncInvalidate;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -557,6 +551,7 @@ begin
|
|||||||
Result:=inherited DoMouseWheel(Shift, WheelDelta, MousePos);
|
Result:=inherited DoMouseWheel(Shift, WheelDelta, MousePos);
|
||||||
if IsActive then
|
if IsActive then
|
||||||
Engine.MouseWheel(self,Shift,WheelDelta,MousePos,Result);
|
Engine.MouseWheel(self,Shift,WheelDelta,MousePos,Result);
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
procedure TMapView.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
||||||
@ -565,6 +560,7 @@ begin
|
|||||||
inherited MouseDown(Button, Shift, X, Y);
|
inherited MouseDown(Button, Shift, X, Y);
|
||||||
if IsActive then
|
if IsActive then
|
||||||
Engine.MouseDown(self,Button,Shift,X,Y);
|
Engine.MouseDown(self,Button,Shift,X,Y);
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
procedure TMapView.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
||||||
@ -573,6 +569,7 @@ begin
|
|||||||
inherited MouseUp(Button, Shift, X, Y);
|
inherited MouseUp(Button, Shift, X, Y);
|
||||||
if IsActive then
|
if IsActive then
|
||||||
Engine.MouseUp(self,Button,Shift,X,Y);
|
Engine.MouseUp(self,Button,Shift,X,Y);
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.MouseMove(Shift: TShiftState; X, Y: Integer);
|
procedure TMapView.MouseMove(Shift: TShiftState; X, Y: Integer);
|
||||||
@ -580,6 +577,7 @@ begin
|
|||||||
inherited MouseMove(Shift, X, Y);
|
inherited MouseMove(Shift, X, Y);
|
||||||
if IsActive then
|
if IsActive then
|
||||||
Engine.MouseMove(self,Shift,X,Y);
|
Engine.MouseMove(self,Shift,X,Y);
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.Notification(AComponent: TComponent; Operation: TOperation);
|
procedure TMapView.Notification(AComponent: TComponent; Operation: TOperation);
|
||||||
@ -594,6 +592,7 @@ begin
|
|||||||
inherited DblClick;
|
inherited DblClick;
|
||||||
if IsActive then
|
if IsActive then
|
||||||
Engine.DblClick(self);
|
Engine.DblClick(self);
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DoOnResize;
|
procedure TMapView.DoOnResize;
|
||||||
@ -604,13 +603,18 @@ begin
|
|||||||
DrawingEngine.CreateBuffer(ClientWidth, ClientHeight);
|
DrawingEngine.CreateBuffer(ClientWidth, ClientHeight);
|
||||||
if IsActive then
|
if IsActive then
|
||||||
Engine.SetSize(ClientWidth, ClientHeight);
|
Engine.SetSize(ClientWidth, ClientHeight);
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.Paint;
|
procedure TMapView.Paint;
|
||||||
begin
|
begin
|
||||||
inherited Paint;
|
inherited Paint;
|
||||||
if IsActive then
|
if IsActive then
|
||||||
DrawingEngine.PaintToCanvas(Canvas)
|
begin
|
||||||
|
Engine.Redraw;
|
||||||
|
DrawObjects(Default(TTileId), 0, 0, Canvas.Width, Canvas.Height);
|
||||||
|
DrawingEngine.PaintToCanvas(Canvas);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Canvas.Brush.Color := InactiveColor;
|
Canvas.Brush.Color := InactiveColor;
|
||||||
@ -631,7 +635,7 @@ begin
|
|||||||
if hasIntersectArea(objArea, visArea) then
|
if hasIntersectArea(objArea, visArea) then
|
||||||
begin
|
begin
|
||||||
Area := IntersectArea(objArea, visArea);
|
Area := IntersectArea(objArea, visArea);
|
||||||
Engine.Jobqueue.AddJob(TDrawObjJob.Create(self, Objs, Area), Engine);
|
Invalidate;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
objs.Free;
|
objs.Free;
|
||||||
@ -654,8 +658,6 @@ begin
|
|||||||
if not trk.Visible or (trk.Points.Count = 0) then
|
if not trk.Visible or (trk.Points.Count = 0) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
GPSItems.Lock;
|
|
||||||
try
|
|
||||||
// Determine track color
|
// Determine track color
|
||||||
if trk.LineColor = clDefault then
|
if trk.LineColor = clDefault then
|
||||||
begin
|
begin
|
||||||
@ -687,9 +689,6 @@ begin
|
|||||||
pt1 := pt2;
|
pt1 := pt2;
|
||||||
iPt1 := iPt2;
|
iPt1 := iPt2;
|
||||||
end;
|
end;
|
||||||
finally
|
|
||||||
GPSItems.Unlock;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DrawPointOfInterest(const Area: TRealArea; APt: TGPSPointOfInterest);
|
procedure TMapView.DrawPointOfInterest(const Area: TRealArea; APt: TGPSPointOfInterest);
|
||||||
@ -701,8 +700,6 @@ var
|
|||||||
bmp: TBitmap;
|
bmp: TBitmap;
|
||||||
w, h: Integer;
|
w, h: Integer;
|
||||||
begin
|
begin
|
||||||
GPSItems.Lock;
|
|
||||||
try
|
|
||||||
pt := Engine.LonLatToScreen(APt.RealPoint);
|
pt := Engine.LonLatToScreen(APt.RealPoint);
|
||||||
|
|
||||||
// Draw point as symbol from image list ...
|
// Draw point as symbol from image list ...
|
||||||
@ -746,9 +743,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
extent := DrawingEngine.TextExtent(s);
|
extent := DrawingEngine.TextExtent(s);
|
||||||
DrawingEngine.TextOut(pt.X - extent.CX div 2, pt.Y + 5, s);
|
DrawingEngine.TextOut(pt.X - extent.CX div 2, pt.Y + 5, s);
|
||||||
finally
|
|
||||||
GPSItems.Unlock;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DrawPt(const Area: TRealArea; APt: TGPSPoint);
|
procedure TMapView.DrawPt(const Area: TRealArea; APt: TGPSPoint);
|
||||||
@ -758,8 +752,6 @@ var
|
|||||||
extent: TSize;
|
extent: TSize;
|
||||||
s: String;
|
s: String;
|
||||||
begin
|
begin
|
||||||
GPSItems.Lock;
|
|
||||||
try
|
|
||||||
if Assigned(FOnDrawGpsPoint) then begin
|
if Assigned(FOnDrawGpsPoint) then begin
|
||||||
FOnDrawGpsPoint(Self, DrawingEngine, APt);
|
FOnDrawGpsPoint(Self, DrawingEngine, APt);
|
||||||
exit;
|
exit;
|
||||||
@ -796,6 +788,13 @@ begin
|
|||||||
extent := DrawingEngine.TextExtent(s);
|
extent := DrawingEngine.TextExtent(s);
|
||||||
DrawingEngine.Textout(Pt.X - extent.CX div 2, Pt.Y + 5, s);
|
DrawingEngine.Textout(Pt.X - extent.CX div 2, Pt.Y + 5, s);
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMapView.DrawGpsObj(const Area: TRealArea; AObj: TGPSObj);
|
||||||
|
begin
|
||||||
|
GPSItems.Lock;
|
||||||
|
try
|
||||||
|
AObj.Draw(Self, Area);
|
||||||
finally
|
finally
|
||||||
GPSItems.Unlock;
|
GPSItems.Unlock;
|
||||||
end;
|
end;
|
||||||
@ -815,22 +814,25 @@ procedure TMapView.DrawObjects(const TileId: TTileId;
|
|||||||
var
|
var
|
||||||
Area: TRealArea;
|
Area: TRealArea;
|
||||||
lst: TGPSObjList;
|
lst: TGPSObjList;
|
||||||
|
I: Integer;
|
||||||
begin
|
begin
|
||||||
Area.TopLeft := Engine.ScreenToLonLat(Point(aLeft, aTop));
|
Area.TopLeft := Engine.ScreenToLonLat(Point(aLeft, aTop));
|
||||||
Area.BottomRight := Engine.ScreenToLonLat(Point(aRight, aBottom));
|
Area.BottomRight := Engine.ScreenToLonLat(Point(aRight, aBottom));
|
||||||
if GPSItems.Count > 0 then
|
if GPSItems.Count > 0 then
|
||||||
begin
|
begin
|
||||||
lst := GPSItems.GetObjectsInArea(Area);
|
lst := GPSItems.GetObjectsInArea(Area);
|
||||||
|
try
|
||||||
if lst.Count > 0 then
|
if lst.Count > 0 then
|
||||||
Engine.Jobqueue.AddJob(TDrawObjJob.Create(self, lst, Area), Engine)
|
|
||||||
else
|
|
||||||
begin
|
begin
|
||||||
|
for I := 0 to Pred(lst.Count) do
|
||||||
|
DrawGpsObj(Area, lst[I]);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
FreeAndNil(Lst);
|
FreeAndNil(Lst);
|
||||||
CallAsyncInvalidate;
|
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
CallAsyncInvalidate;
|
;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DoAsyncInvalidate(Data: PtrInt);
|
procedure TMapView.DoAsyncInvalidate(Data: PtrInt);
|
||||||
@ -839,7 +841,7 @@ Begin
|
|||||||
AsyncInvalidate := false;
|
AsyncInvalidate := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DoDrawStretchedTile(const TileId: TTileId; X, Y: Integer;
|
procedure TMapView.DoDrawStretchedTile(const TileId: TTileID; X, Y: Integer;
|
||||||
TileImg: TLazIntfImage; const R: TRect);
|
TileImg: TLazIntfImage; const R: TRect);
|
||||||
begin
|
begin
|
||||||
if Assigned(TileImg) then
|
if Assigned(TileImg) then
|
||||||
@ -850,7 +852,6 @@ begin
|
|||||||
if FDebugTiles then
|
if FDebugTiles then
|
||||||
DoDrawTileInfo(TileID, X, Y);
|
DoDrawTileInfo(TileID, X, Y);
|
||||||
|
|
||||||
DrawObjects(TileId, X, Y, X + TILE_SIZE, Y + TILE_SIZE);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DoDrawTile(const TileId: TTileId; X, Y: integer;
|
procedure TMapView.DoDrawTile(const TileId: TTileId; X, Y: integer;
|
||||||
@ -864,7 +865,6 @@ begin
|
|||||||
if FDebugTiles then
|
if FDebugTiles then
|
||||||
DoDrawTileInfo(TileID, X, Y);
|
DoDrawTileInfo(TileID, X, Y);
|
||||||
|
|
||||||
DrawObjects(TileId, X, Y, X + TILE_SIZE, Y + TILE_SIZE);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapView.DoDrawTileInfo(const TileID: TTileID; X, Y: Integer);
|
procedure TMapView.DoDrawTileInfo(const TileID: TTileID; X, Y: Integer);
|
||||||
@ -877,6 +877,12 @@ begin
|
|||||||
DrawingEngine.Line(X, Y + TILE_SIZE, X + TILE_SIZE, Y + TILE_SIZE);
|
DrawingEngine.Line(X, Y + TILE_SIZE, X + TILE_SIZE, Y + TILE_SIZE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMapView.DoTileDownloaded(const TileId: TTileId);
|
||||||
|
begin
|
||||||
|
// TODO: Include tile information to optimize redraw.
|
||||||
|
CallAsyncInvalidate;
|
||||||
|
end;
|
||||||
|
|
||||||
function TMapView.IsActive: Boolean;
|
function TMapView.IsActive: Boolean;
|
||||||
begin
|
begin
|
||||||
if not(csDesigning in ComponentState) then
|
if not(csDesigning in ComponentState) then
|
||||||
@ -911,6 +917,7 @@ begin
|
|||||||
FEngine.CacheOnDisk := true;
|
FEngine.CacheOnDisk := true;
|
||||||
FEngine.OnDrawTile := @DoDrawTile;
|
FEngine.OnDrawTile := @DoDrawTile;
|
||||||
FEngine.OnDrawStretchedTile := @DoDrawStretchedTile;
|
FEngine.OnDrawStretchedTile := @DoDrawStretchedTile;
|
||||||
|
FEngine.OnTileDownloaded := @DoTileDownloaded;
|
||||||
FEngine.DrawPreviewTiles := True;
|
FEngine.DrawPreviewTiles := True;
|
||||||
FEngine.DrawTitleInGuiThread := false;
|
FEngine.DrawTitleInGuiThread := false;
|
||||||
FEngine.DownloadEngine := FBuiltinDownloadEngine;
|
FEngine.DownloadEngine := FBuiltinDownloadEngine;
|
||||||
@ -1054,7 +1061,7 @@ end;
|
|||||||
|
|
||||||
procedure TMapView.Redraw;
|
procedure TMapView.Redraw;
|
||||||
begin
|
begin
|
||||||
Engine.Redraw;
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMapView.GetVisibleArea: TRealArea;
|
function TMapView.GetVisibleArea: TRealArea;
|
||||||
|
Reference in New Issue
Block a user