LazMapViewer: Remove drawing residues outside the map tiles. Patch by Yuliyan Ivanov.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9142 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2024-01-15 11:51:35 +00:00
parent 1025d9526f
commit c7b2a5efda
5 changed files with 54 additions and 29 deletions

View File

@ -39,9 +39,9 @@ object MainForm: TMainForm
Height = 640 Height = 640
Top = 0 Top = 0
Width = 275 Width = 275
ActivePage = PgConfig ActivePage = PgData
Align = alRight Align = alRight
TabIndex = 1 TabIndex = 0
TabOrder = 1 TabOrder = 1
object PgData: TTabSheet object PgData: TTabSheet
Caption = 'Data' Caption = 'Data'

View File

@ -473,8 +473,7 @@ var
OldWidth: Integer; OldWidth: Integer;
OldStyle: TPenStyle; OldStyle: TPenStyle;
begin begin
{$IF 0} {$IF FPC_FullVersion >= 30203}
// TFPPixelCanvas.DoPolygonFill doesn't fill
FCanvas.Polygon(Points); FCanvas.Polygon(Points);
{$ELSE} {$ELSE}
if BrushStyle <> bsClear then if BrushStyle <> bsClear then

View File

@ -166,6 +166,13 @@ function OrthoVec(X1, Y1, X2, Y2: Integer; out MX, MY: Double): Boolean;
var var
DX, DY: Integer; DX, DY: Integer;
B: Double; B: Double;
// Inverted vector magnitude
function InvMagn(X, Y: Double): Double; inline;
begin
Result := 1.0 / Sqrt(X * X + Y * Y);
end;
begin begin
if (Y1 = Y2) and (X1 = X2) then if (Y1 = Y2) and (X1 = X2) then
Exit(False); Exit(False);
@ -180,20 +187,10 @@ begin
else if DY = 0 then else if DY = 0 then
MX := 0.0 // <0.0, 1.0> MX := 0.0 // <0.0, 1.0>
else else
begin // Quick and dirty... begin
if CompareValue(Abs(DY/DX), 1.0, 0.5) = 0 B := InvMagn(DX, DY);
then B := 0.7 MX := DY * B;
else B := 1.0; MY := -DX * B;
MX := EnsureRange(-DY/DX, -B, B);
MY := EnsureRange(-DX/DY, -B, B);
if Sign(DX) = Sign(DY) then
MX := -MX;
{$IFDEF 0}
// The correct way
A := ArcTan2(-DX, DY);
MX := Cos(A);
MY := Sin(A);
{$IFEND}
end; end;
Result := True; Result := True;
end; end;

View File

@ -115,7 +115,7 @@ type
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; const paintOnly: Boolean = False); procedure Redraw(const aWin: TMapWindow; const paintOnly: Boolean = False);
function CalculateVisibleTiles(const aWin: TMapWindow) : TArea; function CalculateVisibleTiles(const aWin: TMapWindow; out Area: TArea): Boolean;
function IsCurrentWin(const aWin: TMapWindow) : boolean; function IsCurrentWin(const aWin: TMapWindow) : boolean;
protected protected
procedure AdjustZoomCenter(var AWin: TMapWindow); procedure AdjustZoomCenter(var AWin: TMapWindow);
@ -352,18 +352,36 @@ begin
CalculateWin(AWin); CalculateWin(AWin);
end; end;
function TMapViewerEngine.CalculateVisibleTiles(const aWin: TMapWindow): TArea; // Returns whether the view area is not covered fully with a tiles
function TMapViewerEngine.CalculateVisibleTiles(const aWin: TMapWindow; out
Area: TArea): Boolean;
var var
MaxX, MaxY, startX, startY: int64; MaxX, MaxY, startX, startY: int64;
WorldSize: Int64;
begin begin
MaxX := (Int64(aWin.Width) div TILE_SIZE) + 1; Area := Default(TArea);
MaxY := (Int64(aWin.Height) div TILE_SIZE) + 1; Result := True;
WorldSize := 1 shl AWin.Zoom;
MaxX := Int64(aWin.Width) div TILE_SIZE + 1;
MaxY := Int64(aWin.Height) div TILE_SIZE + 1;
if (MaxX > WorldSize) or (MaxY > WorldSize) then
begin
Result := False;
MaxX := Min(WorldSize - 1, MaxX);
MaxY := Min(WorldSize - 1, MaxY);
end;
startX := -aWin.X div TILE_SIZE; startX := -aWin.X div TILE_SIZE;
startY := -aWin.Y div TILE_SIZE; startY := -aWin.Y div TILE_SIZE;
Result.Left := startX;// - 1; if (startX < 0) or (startY < 0) then
Result.Right := startX + MaxX; begin
Result.Top := startY;// - 1; startX := Max(0, -aWin.X div TILE_SIZE);
Result.Bottom := startY + MaxY; startY := Max(0, -aWin.Y div TILE_SIZE);
Result := False;
end;
Area.Left := startX;
Area.Right := startX + MaxX;
Area.Top := startY;
Area.Bottom := startY + MaxY;
end; end;
procedure TMapViewerEngine.CalculateWin(var AWin: TMapWindow); procedure TMapViewerEngine.CalculateWin(var AWin: TMapWindow);
@ -1007,11 +1025,21 @@ var
end; end;
end; end;
procedure EraseBackground;
var
I, J: Integer;
begin
for J := 0 to (AWin.Height div TILE_SIZE) + 1 do
for I := 0 to (AWin.Width div TILE_SIZE) + 1 do
DrawTile(tile, I * TILE_SIZE, J * TILE_SIZE, Nil);
end;
begin begin
if not(Active) then if not(Active) then
Exit; Exit;
TilesVis := CalculateVisibleTiles(AWin); if not CalculateVisibleTiles(AWin, TilesVis) then
EraseBackground;
SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1)); SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1));
iTile := Low(Tiles); iTile := Low(Tiles);
numTiles := 1 shl AWin.Zoom; numTiles := 1 shl AWin.Zoom;

View File

@ -108,7 +108,7 @@ type
implementation implementation
const const
WAIT_TIME = 300; WAIT_TIME = 150;
TERMINATE_TIMEOUT = WAIT_TIME * 2; TERMINATE_TIMEOUT = WAIT_TIME * 2;
type type
@ -381,10 +381,11 @@ begin
begin begin
TerminateEvent := TEvent.Create(nil, false, false, ''); TerminateEvent := TEvent.Create(nil, false, false, '');
try try
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;
for i := 0 to Pred(Threads.Count) do
FEvent.SetEvent;
TerminateEvent.WaitFor(TERMINATE_TIMEOUT); TerminateEvent.WaitFor(TERMINATE_TIMEOUT);
for i := 0 to Pred(Threads.Count) do for i := 0 to Pred(Threads.Count) do
TQueueThread(Threads[i]).WaitFor; TQueueThread(Threads[i]).WaitFor;