Sign in Join
Wiki copytemporary

LazMapViewer: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: LazMapViewer

OldNewLine
1+<figure>
2+<img src="lazmapviewer.png" title="lazmapviewer.png" />
3+<figcaption>lazmapviewer.png</figcaption>
4+</figure>
5+
6+## About
7+
8+**LazMapViewer** is a component for embedding maps obtained from the internet, such as Google maps or OpenStreetView, into a Lazarus form.
9+
10+The initial version of the package was written by Maciej Kaczkowski and later improved by members of the Lazarus forum. The package is currently maintained by Werner Pamler (wp_xxyyzzz-at-gmx-dot-net).
11+
12+License: Modified LGPL (with linking exception, like Lazarus LCL).
13+
14+## Download and Installation
15+
16+**Development version**
17+
18+Use an SVN client to download the current trunk version from <svn://svn.code.sf.net/p/lazarus-ccr/svn/components/lazmapviewer>. Alternatively download the zipped snapshot from <https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/lazmapviewer/> and unzip it to some folder.
19+
20+**Release version**
21+
22+Occasionally, release versions are made available via the [[Online Package Manager]] for easy one-click-installation directly from Lazarus.
23+
24+**Installation**
25+
26+In Lazarus, go to "Package" \> "Open Package File .lpk". Navigate to the folder with the LazMapViewer sources, and select `lazmapviewerpkg.lkp`. Click "Compile", then "Use" \> "Install". This will rebuild the IDE (it may take some time). When the process is finished the IDE will restart, and you'll find the MapViewer in the palette **Misc**.
27+
28+There are optional, supporting packages to extend the basic functionality. They must be installed in the same way, after `lazmapviewerpkg.lpk`.
29+
30+| Package file name | Contained components | Purpose |
31+|----|----|----|
32+| lazmapviewerpkg.lpk | TMapView | Main component to display maps |
33+| | TMvGeoNames | Access to geo coordinates of cities |
34+| | TMvDEFpc | Default download engine using the internal fpc routines |
35+| lazmapviewer_synapse.lpk | TMvDESynapse | Alternative download engine based on the Synapse library |
36+| lazmapviewer_rgbgraphics.lpk | TMvRGBGraphicsDrawingEngine | Alternative drawing engine based on the RGBGraphics package |
37+| lazmapviewer_bgra.lpk | TMvBGRADrawingEngine | Alternative drawing engine based on the BGRABitmap package |
38+
39+**Requirements**
40+
41+Release v0.2.6 was tested successfully with the following tool combinations: Laz/main + FPC/main, Laz/main + FPC/fixes, Laz 3.0 + FPC 3.2.2, Laz 2.0.8 + FPC 3.0.4, Laz 1.6.4 + FPC 3.0.2 on Windows, with Laz 3.0 + FPC 3.2.2 on Linux Mint gtk2/gtk3/qt5, and with Laz/main + FPC 3.2.2 on MacOS cocoa.
42+
43+## The Main Map Viewer: TMapView
44+
45+### Getting Started
46+
47+Here is a short tutorial to create your first map.
48+
49+#### Preparation
50+
51+- Drop a `TMapView` component on the form and size it as needed. The component is on the *Misc* tab of the Lazarus component palette.
52+- Add this handler for the form's `OnShow` or `OnActivate` event and set the `Active` property of the `MapView` component to `true`; in principle, this should be possible also in the object inspector, however, does not work at the time of this writing.
53+
54+``` Pascal
55+procedure TForm1.FormActivate(Sender: TObject);
56+begin
57+ MapView1.Active := true;
58+end;
59+```
60+
61+- That's all. Compile, run and see your fist map!
62+- In the background the `MapView` component has established an internet connection to the default map provider and downloaded the default map. The maps are delivered as a series of **tiled images** at given size, usually 256x256 pixels, and usually in png format. They are stored in a cache directory (property `CachePath`) and used primarily to reduce internet traffic; only when an image is not found another download from the internet is triggered again.
63+
64+#### Magnification
65+
66+- The map images are provided in different magnifications depending on the `Zoom` level of the `MapView`. Each step in `Zoom` level corresponds to doubling the magnification. The maximum `Zoom` level for most map providers is 18 -- this means that the most detailed maps cover a fraction of `1/2^18` of the earth circumference, about 150 m.
67+- So, if you want to see **more details** you must increase the `Zoom` value of the `MapView`. You can enter the requested value in the Object Inspector, or add a `TScrollbar` or `TTrackbar` to the form to change the magnfication interactively by using the following simple `OnChange` event handler (set the `Max` of the bar to, say, 18:
68+
69+``` Pascal
70+procedure TForm1.TrackBar1Change(Sender: TObject);
71+begin
72+ MapView1.Zoom := TrackBar1.Position;
73+end;
74+```
75+
76+- Alternatively, zooming can also be achieved by rotating the **mouse wheel**.
77+
78+#### Location
79+
80+- By default the **center of the map** is the intersection of the 0-degree meridian with the equator - which is a bit off of the coast of western Africa. In order to focus onto a different location you must specify its longitude and latitude in the `Center` property of the `MapView`. This is a `TRealPoint` record having the longitude and latitude in the `Lon` and `Lat` record elements.
81+- Suppose we want to zoom into Manhattan. Use your favorite search engine to determine the geo coordinates of Manhattan: Longitude = -73.985130°, Latitude = 40.758896°. Alternatively you can also use the TGeoNames component which comes with the LazMapViewer package and provides access to a database of the geo coordinates of a huge number of locations via internet.
82+
83+``` Pascal
84+procedure TForm1.FormActivate(Sender: TObject);
85+var
86+ P: TRealPoint;
87+begin
88+ MapView1.Active := true;
89+ P.Lon := -73.985130;
90+ P.Lat := 40.758896;
91+ MapView1.Center := P;
92+end;
93+```
94+
95+- In addition to specifying the location numerically the you can also change location by **dragging the map with the mouse**. Just press the left mouse button and slowly move the mouse in the direction where you want to see more - the map will follow. But you should be aware that usually neighboring maps will have to be loaded from the internet, and this makes the entire action a bit sluggish.
96+
97+### Basic Documentation
98+
99+<figure>
100+<img src="tmapview_200.png" title="tmapview_200.png" />
101+<figcaption>tmapview_200.png</figcaption>
102+</figure>
103+
104+#### Properties
105+
106+These are the main properties of the `TMapView` component:
107+
108+- `Active (boolean)`: must be set to `true` before the `MapView` component can display maps.
109+- `CacheOnDisk (boolean)`: when set to `true` (default) dowloaded map tiles are stored in a directory to reduce internet traffic and for faster access. It is not recommended to turn this property off. The cache is not deleted automatically.
110+- `CachePath (string)`: name of the directory in which downloaded map images are buffered.
111+- `DownloadEngine (TMvCustomDownloadEngine)`: By default, the `TFPHttpClient` is employed to download the images from the map servers. If a different download engine is required the corresponding component can be hooked to this property. The standard installation of the *LazMapViewer* package contains the default `TMvDEFPC` downloader (based on FPC's `TFPHttpClient`) and the `TMvDESynapse` based on the *Synapse* library).
112+- `DrawingEngine (TMvCustomDrawingEngine)`: Painting of the tiled images is a speed-critical task. By default, this is done using routines from the *IntfGraphics* unit; the corresponding drawing engine is in the `TMvInfGraphicsDrawingEngine` class. However, it is possible to provide a different drawing engine here. The standard installation of *LazMapViewer* comes with the alternative `TMvRGBGraphicsDrawingEngine` which is based on the *RGBGraphics* package, and with the `TMvBGRADrawingEngine` utilizing the *BGRABitmap* package.
113+- `MapProvider (string)`: This string identifies the provider from which the maps are downloaded. Built-in providers allow to choose between *OpenStreetMaps*, *GoogleMaps*, *Virtual Earth*, *Yandex* etc. Details are given in section Map Providers.
114+- `Options = [mvoMouseDragging, mvoMouseZooming]`: Allows to disable dragging of the map with the mouse and zooming with the mouse wheel when the corresponding option is removed from the set (in v0.2.7 and newer). Default: both options active.
115+- `UseThreads (boolean)`: When set to `true` downloading and drawing of maps is delegated to several threads in order to achieve a smoother response. It is not recommended to turn this property off.
116+- `Zoom (integer)`: Magnfication of the map: 0 = coarsest magnification, earth view, 17 or 18 = highest magnification. Each zoom step results in doubling of the magnfication factor.
117+- `ZoomToCursor (boolean)`: When this is `true` zooming occurs relative to the mouse position, otherwise to the center of the map. This feature is interesting for zooming with the mouse wheel.
118+
119+Here are properties related to overlayed GPS objects (points of interest, tracks):
120+
121+- `GPSItems: TGPSObjectList`: list of GPS objects assigned to the MapView See below for details.
122+- `DefaultTrackColor: TColor`, `DefaultTrackWidth: Integer`: the default color and line width, respectively, of overlayed tracks. See below for details.
123+- `POIImage: TBitmap`: bitmap which will be overlayed to identify a "point of interest" (POI).
124+- `POITextBgColor: TColor`: background color of the overlayed text describing a point of interest. Turn off the text background by selecting `clNone`.
125+
126+#### Events
127+
128+- `OnCenterMove`: fires whenever the `Center` of the `MapView` have been changed.
129+- `OnChange`: fires whenever the `Center`, size or `Zoom` factor of the `MapView` change.
130+- `OnDrawGpsPoint`: see below
131+- `OnZoomChange`: fires whenever the `Zoom` factor of the `MapView` changes.
132+- `OnMouseDown, OnMouseEnter, OnMouseLeave, OnMouseMove, OnMouseUp`: standard mouse events.
133+
134+#### Main methods
135+
136+- `procedure GetMapProviders(lstProviders: TStrings)`: Returns in `lstProviders` the names of all registered map providers. When one of these strings is assigned to the `MapProvider` property of the `MapVieew` the servers of the corresponding provider will become the source of the displayed maps.
137+- `function GetVisibleArea: TRealArea`: returns the top/left and bottom/right corner points of the displayed rectangle in geo coordinates. `TRealArea` is a record consisting of the `TRealPoint` records `TopLeft` and `BottomRight`.
138+- `function LonLatToScreen(aPt: TRealPoint): TPoint`: maps a geo point (longitude, latitude) to screen pixels (relative to the `TMapView` instance).
139+- `function ScreenToLonLat(aPt: TPoint): TRealPoint`: maps a the coordinates of a screen pixel (relative to the `MapView` instance) to geo coordinates (longitude, latitude). Here is an example how the geo coordinates of the mouse cursor can be displayed in two labels by means of the `OnMouseMove` event of the `MapView`:
140+
141+``` Pascal
142+uses
143+ mvTypes, // for TRealPoint
144+ mvEngine; // for LonToStr() and LatToStr() funtions
145+
146+procedure TForm1.MapView1MouseMove(Sender: TObject; Shift: TShiftState;
147+ X, Y: Integer);
148+var
149+ P: TRealPoint;
150+begin
151+ P := MapView1.ScreenToLonLat(Point(X, Y));
152+ Label1.Caption := 'Longitude: ' + LonToStr(P.Lon, true);
153+ Label2.Caption := 'Latitude: ' + LatToStr(P.Lat, true);
154+end;
155+```
156+
157+- `procedure SaveToFile(AClass: TRasterImageClass; const AFileName: String)`: Save the currently displayed map as bitmap of the given class to a file. Example for saving to a jpg image:
158+
159+``` Pascal
160+procedure TForm1.Button1Click(Sender: TObject);
161+begin
162+ MapView1.SaveToFile(TJpegImage, 'mapview.jpg');
163+end;
164+```
165+
166+- `procedure SaveToStream(AClass: TRasterImageClass; AStream: TStream)`: Similar to `SaveToFile`, but output is not in a file, but in the stream provided.
167+- `function SaveToImage(AClass: TRasterImageClass): TRasterImage`: creates an instance of the given image class and writes the currently visible view port image to it.
168+- `procedure CenterOnObj(obj: TGPSObj)`: Centers the map on the provided GPS object. More on GPS objects below.
169+- `procedure ZoomOnArea(const aArea: TRealArea)`: Adjusts the `Zoom` level such that the given area is completely shown and fills the component bounds as much as possible.
170+- `procedure ZoomOnObj(obj: TGPSObj)`: Adjusts the `Zoom` level such that the given GPS object is completely seen at highest magnification. More about GPS objects below.
171+
172+### Map Providers
173+
174+The `MapView` component can display maps from various providers. To activate a given provider its name must be specified in the `MapProvider` property of the component.
175+
176+Here is a list of the names of the built-in map providers:
177+
178+- OpenStreetMap Mapnik
179+- OpenStreetMap Wikipedia
180+- OpenStreetMap Sputnik
181+- OpenStreetMap.fr Hot
182+- OpenStreetMap.fr Cycle Map
183+- Open Topo Map
184+- Google Maps
185+- Google Satellite
186+- Yandex.Maps
187+- Yandex.Maps Satellite
188+- Virtual Earth Bing
189+- Virtual Earth Aerial
190+- Virtual Earth Hybrid
191+
192+The following providers require an API key to access their service. The API key can be obtained by registering at the provider sites. Usually the API keys are free, however, a charge may be required for commercial usage - please see the details on the provider sites. The strings received as API keys must be stored in global variables of your application.
193+
194+- Registration at <https://www.thunderforest.com/docs/apikeys/>, store API key in the variable `ThunderForest_ApiKey`:
195+ - Open Cycle Map
196+ - OpenStreetMap Transport
197+- Registration at <https://developer.here.com/?create=Freemium-Basic&keepState=true&step=account>, store the received APP ID and APP CODE in the variables `HERE_AppID` and `HERE_AppCode`, respectively:
198+ - Here WeGo Map
199+ - Here WeGo Grey Map
200+ - Here WeGo Reduced Map
201+ - Here WeGo Transit Map
202+ - Here WeGo POI Map
203+ - Here WeGo Pedestrian Map
204+ - Here WeGo DreamWorks Map
205+- Registration at <https://home.openweathermap.org/users/sign_up>, store the API Key in variable `OpenWeatherMap_ApiKey`:
206+ - OpenWeatherMap Clouds
207+ - OpenWeatherMap Precipitation
208+ - OpenWeatherMap Pressure
209+ - OpenWeatherMap Temperature
210+ - OpenWeatherMap Wind
211+
212+Please respect the license requirements of the map providers.
213+
214+### GPS Objects
215+
216+The public `TMapView` property `GPSItems` collects data on points of interest and tracks to be overlayed on the map. The common data type of these overlay items is
217+
218+``` Pascal
219+type
220+ TGPSObj = class
221+ ...
222+ public
223+ destructor Destroy; override;
224+ property Name: String read FName write FName;
225+ property ExtraData: TObject read FExtraData write SetExtraData;
226+ property IdOwner: Integer read FIdOwner;
227+ property BoundingBox: TRealArea read GetBoundingBox write SetBoundingBox;
228+ end;
229+```
230+
231+The `Name` can be displayed near the item in the map.
232+
233+`ExtraData` can be used freely, for example to define the color of a track. An example how this could be done is found in unit `mvExtraData`, classes `TDrawingExtraData` and `TTrackExtraData`.
234+
235+`IdOwner` is the ID of the owner TGPSObj instance to which the current item belongs. `BoundingBox` gives the geo coordinates of the top/left and bottom/right corner points of the rectangle containing all points of the item.
236+
237+#### Points
238+
239+A special `TGPSObj` item is a `TGPSPoint`, for example a scenic "Point-of-Interest" (POI), a way point along a hiking path etc.
240+
241+``` Pascal
242+ TGPSPoint = class(TGPSObj)
243+ public
244+ constructor Create(ALon,ALat: double; AEle: double=NO_ELE; ADateTime: TDateTime=NO_DATE);
245+ class function CreateFrom(aPt: TRealPoint): TGPSPoint;
246+
247+ function HasEle: boolean;
248+ function HasDateTime: Boolean;
249+ function DistanceInKmFrom(OtherPt: TGPSPoint; UseEle: boolean=true): double;
250+
251+ property Lon: Double read GetLon;
252+ property Lat: Double read GetLat;
253+ property Ele: double read FEle;
254+ property DateTime: TDateTime read FDateTime;
255+ property RealPoint: TRealPoint read FRealPt;
256+ end;
257+```
258+
259+In its constructor, the geo coordinate longitude and latitude must be specified. They are also available as read-only properties `Lon` and `Lat`. Optional parameters are the elevation of the point (property `Ele` as well as some date/time information (property `DateTime`), for example the date when this point was visited. A special function, `DistanceInKmFrom`, is available to calculate the on-earth distance from another GPS point.
260+
261+#### Tracks
262+
263+The second important `TGPSObj` descendant is `TGPSTrack` which stores the points along a path, for example points visited on a trip or a hike. Each point is a instance of the `TGPSPoint` class, and the individual points are collected by the list `Points`. Again, there is a `DataTime` property usable for example to hold the date of the hike. Function `TrackLengthInKm` calculates the length of the entire path with the points being connected by straight line segments.
264+
265+``` Pascal
266+type
267+ TGPSTrack = class(TGPSObj)
268+ private
269+ FDateTime: TDateTime;
270+ FPoints: TGPSPointList;
271+ function GetDateTime: TDateTime;
272+ public
273+ constructor Create;
274+ destructor Destroy; override;
275+
276+ procedure GetArea(out Area: TRealArea); override;
277+ function TrackLengthInKm(UseEle: Boolean=true): double;
278+
279+ property Points: TGPSPointList read FPoints;
280+ property DateTime: TDateTime read GetDateTime write FDateTime;
281+ end;
282+```
283+
284+#### List of GPS Objects
285+
286+The property `GpsItems` of the `TMapView` component is the main class collecting all the GPS objects. It is an instance of the `TGPSObjectList`:
287+
288+``` Pascal
289+type
290+ TGPSObjectList = class(TGPSObj)
291+ ...
292+ constructor Create;
293+ destructor Destroy; override;
294+
295+ Procedure Clear(OwnedBy: integer);
296+ procedure ClearExcept(OwnedBy: integer; const ExceptLst: TIdArray; out Notfound: TIdArray);
297+ procedure GetArea(out Area: TRealArea); override;
298+ function GetObjectsInArea(const Area: TRealArea): TGPSObjList;
299+ function GetIdsArea(const Ids: TIdArray; AIdOwner: integer): TRealArea;
300+
301+ function Add(aItem: TGpsObj; AIdOwner: integer): integer;
302+ procedure DeleteById(const Ids: Array of integer);
303+
304+ procedure BeginUpdate;
305+ procedure EndUpdate;
306+
307+ property Count: integer read GetCount;
308+ property Items[AIndex: Integer]: TGpsObj read GetItem; default;
309+
310+ property OnModified: TModifiedEvent read FOnModified write FOnModified;
311+ end;
312+```
313+
314+Objects can be added to the list by calling the `Add` method. Since each addition is accompanied by a repaint of the `MapView` you should call `BeginUpdate` before and `EndUpdate` after adding the objects. Every added object must be assigned to an arbitrary ID which is used to group the objects.
315+
316+Method `DeleteByID` deletes all objects sharing the same IDE. `Clear`, on the other hand, clears all the objects which are owned by object having the specified ID. An extension is `ClearExcept` which does the same but skips IDs listed in the `ExceptLst` array.
317+
318+`GetObjectsInArea` creates a TFPObjectlist (of type `TGpsObjList` here) with all the objects enclosed by the given rectangle (`Area`). `GetIDsArea`, conversely, returns the rectangle enclosing all the objects with the IDs listed in parameter `IDs` (which is a simple array here).
319+
320+#### Example: Adding a Point of Interest
321+
322+Suppose you want to mark a special point in the map by a mouse click and identify it with some descriptive text. Write a handler for the OnMouseUp event in which you query the description and then take the pixel coordinates of the clicked point, convert it to geo coordinates and create a `TGpsPoint` from it which you add to the `GpsItems` of the `MapView`:
323+
324+``` Pascal
325+uses
326+ mvTypes, mvGPSObj;
327+
328+const
329+ _POI_ = 10;
330+
331+procedure TForm1.MapView1MouseUp(Sender: TObject; Button: TMouseButton;
332+ Shift: TShiftState; X, Y: Integer);
333+var
334+ pt: TRealPoint;
335+ gpsPt: TGpsPoint;
336+ ptName: String;
337+begin
338+ ptName := '';
339+ if InputQuery('Point of Interest', 'Enter name:', ptName) then
340+ begin
341+ pt := MapView1.ScreenToLonLat(Point(X, Y));
342+ gpsPt := TGpsPoint.CreateFrom(pt, NO_ELE, Now() );
343+ gpsPt.Name := ptName;
344+ Mapview1.GPSItems.Add(gpsPt, _POI_);
345+ end;
346+end;
347+```
348+
349+In this example the constant `_POI_` is used as ID of the added point. By default, the point is drawn as a red cross, the name is drawn underneath it. You can highlight the text by changing its background color in property `POITextBgColor` of the `MapView`. You can also replace the red cross by an arbitrary bitmap which must be loaded into the `POIImage` property (the folder *example* of the LazMapViewer installation contains a ready-to-use pin-cushion icon).
350+
351+There is also an event, `OnDrawGpsPoint`, which can be used to replace the entire labeling process by custom routines. The event has the `GpsPoint` as parameter. Drawing style can be defined based on the data stored in the `GpsPoint`. The other event parameter is the `DrawingEngine` which provides methods for drawing; it will be explained below. Here is an example in which the added Point-of-Interest is drawn by a blue circle and labeled by a large bold font:
352+
353+``` Pascal
354+procedure TForm1.MapView1DrawGpsPoint(Sender: TObject;
355+ ADrawer: TMvCustomDrawingEngine; APoint: TGpsPoint);
356+const
357+ R = 8;
358+var
359+ p: TPoint;
360+begin
361+ // Screen coordinates of the GPS point
362+ p := MapView1.LonLatToScreen(APoint.RealPoint);
363+
364+ // Draw a blue circle
365+ ADrawer.PenColor := clBlack;
366+ ADrawer.BrushColor := clBlue;
367+ ADrawer.BrushStyle := bsSolid;
368+ ADrawer.Ellipse(p.X-R, p.Y-R, P.X+R, p.Y+R);
369+
370+ // Draw the point label
371+ ADrawer.BrushStyle := bsClear;
372+ ADrawer.FontName := 'SegoeUI';
373+ ADrawer.FontSize := 16;
374+ ADrawer.FontStyle := [fsBold];
375+ ADrawer.TextOut(
376+ p.X - ADrawer.TextWidth(APoint.Name) div 2,
377+ p.Y + R + 4,
378+ APoint.Name
379+ );
380+end;
381+```
382+
383+## Finding Geo Locations: TMvGeoNames
384+
385+`TMvGeoNames` is a component which searches the geo coordinates (longitude, latitude) of many cities or other locations in the world. Using the download engine of the `MapView` component it sends a query to the site <http://geonames.org/search.html> and analyzes the returned html string.
386+
387+<figure>
388+<img src="tmvgeonames_200.png" title="tmvgeonames_200.png" />
389+<figcaption>tmvgeonames_200.png</figcaption>
390+</figure>
391+
392+### Getting Started
393+
394+- Assuming that you already have set up an application for the `TMapView` component as described above, you simply drop a `TMvGeoNames` component on the form; it is located next to the `TMapView` icon in the *Misc* component palette.
395+- Add a button which is supposed to trigger the search.
396+- Write an `OnClick` handler for the button which calls the `TMvGeoNames` method `Search`. Enter the search destination as first parameter, and the download engine to be used as second parameter. The function returns the found longitude and latitude as a `TRealPoint` record which can be passed immediately to the `Center` property of the `MapView` component. This way, the viewer can immediately jump to the found location:
397+
398+``` pascal
399+procedure TForm1.Button1Click(Sender: TObject);
400+begin
401+ MapView1.Center := MvGeoNames1.Search('Grand Canyon National Park', MapView1.DownloadEngine);
402+end;
403+```
404+
405+### Documentation
406+
407+#### Methods
408+
409+- `function Search(ALocationName: String; ADownloadEngine: TMvCustomDownloadEngine): TRealPoint`: searches the requested location using the specified download engine. Return value are the geo coordinates of the location given as a `TRealPoint`. The search returns also locations with similar names, however, they must be extracted by handling the `OnNameFound` event.
410+
411+#### Properties
412+
413+- `LocationName: string`: Is the name of the (first) found location as listed by the *geonames* site.
414+
415+#### Events
416+
417+- `OnNameFound`: This event is triggered while the received response of the *geonames* server is being analyzed. The html string usually contains a variety of locations. Whenver a location has been extracted from the received string the event is fired and tells the name, a description, and the longitude/latitude `TRealPoint` record for this location. Handling this event makes it possible to list all the found locations for example in a combobox or listbox to give the user the opportunity to select any one of them:
418+
419+``` pascal
420+type
421+ TGeoLocation = class
422+ Name: String;
423+ Descr: String;
424+ Coords: TRealPoint;
425+ end;
426+
427+procedure TForm1.MVGeoNames1NameFound(const AName: string;
428+ const ADescr: String; const ALoc: TRealPoint);
429+var
430+ loc: TGeoLocation;
431+begin
432+ loc := TGeoLocation.Create;
433+ loc.Name := AName;
434+ loc.Descr := ADescr;
435+ loc.Coords := ALoc;
436+ ComboBox1.Items.AddObject(AName, loc);
437+end;
438+```
439+
440+---
441+*From the Free Pascal wiki, page "LazMapViewer", as it stood on 2024-01-29 after a change by Wp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history