Forum > Packages and Libraries

LazMapView - adding a scale

(1/2) > >>

wschulte:
I am playing around with the LazMapViewer (0.2.7) and it works as a charm. I want to use it in a project, but first want to play around a bit.
Most is pretty straightforward, except one thing: how to implement a ruler line (indicating a distance) ?
Just writing to th canvas doesn't work of course. But adding a track as such a line is quite tedious: it has to be updated with every move and or zoom.
Is there a way to tie such a line to a fixed position in the view (eg. bottom right) ?

alpine:
You can put a TPanel on top of the map view, anchor it at the bottom right corner with some offset. Then, assuming the name of the map view is MapView and the panel is Ruler, put at Ruler.OnPaint something like this:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TMainForm.RulerPaint(Sender: TObject);var  LPt, RPt: TRealPoint;  Dist, V: Double;  Digits: Integer;  Km: Boolean = False;begin  LPt := MapView.ScreenToLatLon(Ruler.ClientToParent(Point(0, Ruler.Width - 250)));  RPt := MapView.ScreenToLatLon(Ruler.ClientToParent(Point(0, Ruler.Width)));  Dist := mvGeoMath.CalcGeoDistance(LPt.Lat, LPt.Lon, RPt.Lat, RPt.Lon, duMeters);  Km := Dist >= 1000;  if Km then    Dist := Dist * 0.001;  Digits := Trunc(Math.Log10(Dist));  V := Power(10, Digits);  if V + V < Dist then    V := V + V;  Ruler.Width := Round(250 * (V / Dist));  Ruler.Caption := Round(V).ToString + IfThen(Km, ' Km', ' m');  with Ruler do  begin    Canvas.Pen.Color := clBlack;    Canvas.Pen.EndCap := pecFlat;    Canvas.Pen.Width := 3;    Canvas.Polyline([Point(0, 10), Point(0, 1), Point(Width - 1, 1),      Point(Width - 1, 10)]);  end;end;Here the MapView and the Ruler have same parent and MapView is at (0, 0). Otherwise, MapView.ScreenToClient(Ruler.ClientToScreen(x)) shall be used instead of  Ruler.ClientToParent(x).

Also, call Ruler.Invalidate into MapView.OnZoomChange and MapView.OnCenterMove.

EDIT: You must be aware that there is an issues with that code when the zoom level is too small (<8 ).

wp:
I think a magnification scale is a key requirement for displaying maps and should be provided by the TMapView itself. I opened a bug report for it (https://gitlab.com/freepascal.org/lazarus/ccr/-/issues/39081)

wschulte:

--- Quote from: alpine on December 01, 2024, 12:51:22 pm ---You can put a TPanel on top of the map view, anchor it at the bottom right corner with some offset. Then, assuming the name of the map view is MapView and the panel is Ruler, put at Ruler.OnPaint something like this:

Here the MapView and the Ruler have same parent and MapView is at (0, 0). Otherwise, MapView.ScreenToClient(Ruler.ClientToScreen(x)) shall be used instead of  Ruler.ClientToParent(x).

Also, call Ruler.Invalidate into MapView.OnZoomChange and MapView.OnCenterMove.

EDIT: You must be aware that there is an issues with that code when the zoom level is too small (<8 ).

--- End quote ---

That came to my mind also, but I prefer the scale to overlay the map, like a track (which i did, but then you lack the text).

Btw. .. what issue are you referring to regarding the zoom level? That the map becomes smaller then the control size .. ?

wschulte:

--- Quote from: wp on December 01, 2024, 06:32:03 pm ---I think a magnification scale is a key requirement for displaying maps and should be provided by the TMapView itself. I opened a bug report for it (https://gitlab.com/freepascal.org/lazarus/ccr/-/issues/39081)

--- End quote ---

Thats a very good idea. I look into it.

Navigation

[0] Message Index

[#] Next page

Go to full version