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
Top = 0
Width = 275
ActivePage = PgConfig
ActivePage = PgData
Align = alRight
TabIndex = 1
TabIndex = 0
TabOrder = 1
object PgData: TTabSheet
Caption = 'Data'

View File

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

View File

@ -166,6 +166,13 @@ function OrthoVec(X1, Y1, X2, Y2: Integer; out MX, MY: Double): Boolean;
var
DX, DY: Integer;
B: Double;
// Inverted vector magnitude
function InvMagn(X, Y: Double): Double; inline;
begin
Result := 1.0 / Sqrt(X * X + Y * Y);
end;
begin
if (Y1 = Y2) and (X1 = X2) then
Exit(False);
@ -180,20 +187,10 @@ begin
else if DY = 0 then
MX := 0.0 // <0.0, 1.0>
else
begin // Quick and dirty...
if CompareValue(Abs(DY/DX), 1.0, 0.5) = 0
then B := 0.7
else B := 1.0;
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}
begin
B := InvMagn(DX, DY);
MX := DY * B;
MY := -DX * B;
end;
Result := True;
end;

View File

@ -115,7 +115,7 @@ type
function DegreesToPixelsEPSG3395(const AWin: TMapWindow; ALonLat: TRealPoint): TPoint;
function DegreesToPixelsEPSG3857(const AWin: TMapWindow; ALonLat: TRealPoint): TPoint;
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;
protected
procedure AdjustZoomCenter(var AWin: TMapWindow);
@ -352,18 +352,36 @@ begin
CalculateWin(AWin);
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
MaxX, MaxY, startX, startY: int64;
WorldSize: Int64;
begin
MaxX := (Int64(aWin.Width) div TILE_SIZE) + 1;
MaxY := (Int64(aWin.Height) div TILE_SIZE) + 1;
Area := Default(TArea);
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;
startY := -aWin.Y div TILE_SIZE;
Result.Left := startX;// - 1;
Result.Right := startX + MaxX;
Result.Top := startY;// - 1;
Result.Bottom := startY + MaxY;
if (startX < 0) or (startY < 0) then
begin
startX := Max(0, -aWin.X div TILE_SIZE);
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;
procedure TMapViewerEngine.CalculateWin(var AWin: TMapWindow);
@ -1007,11 +1025,21 @@ var
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
if not(Active) then
Exit;
TilesVis := CalculateVisibleTiles(AWin);
if not CalculateVisibleTiles(AWin, TilesVis) then
EraseBackground;
SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1));
iTile := Low(Tiles);
numTiles := 1 shl AWin.Zoom;

View File

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