Android Tutorial OSMDroid - MapView for B4A tutorial

warwound

Expert
Licensed User
How about this...

  • OSMDroid_CircleOverlay
    Fields:
    • RADIUS_UNITS_TYPE_METERS As RadiusUnitsType
    • RADIUS_UNITS_TYPE_PIXELS As RadiusUnitsType
    Methods:
    • AddCircleOverlayItem (Center As GeoPoint, Radius As Float, RadiusUnitsType1 As RadiusUnitsType, StrokeWidth As Float, StrokeColor As Int) As CircleOverlayItem
      Creates, adds and return a CircleOverlayItem object.
    • AddCircleOverlayItem2 (Latitude As Double, Longitude As Double, Radius As Float, RadiusUnitsType1 As RadiusUnitsType, StrokeWidth As Float, StrokeColor As Int) As CircleOverlayItem
    • ClearCircleOverlayItems
      Clear the CircleOverlay of all CircleOverlayItems.
    • GetBoundingBox As BoundingBox
      Returns a BoundingBox that represents the area covered by the centers of all CircleOverlayItems.
    • Initialize
    • IsInitialized As Boolean
    • RemoveCircleOverlayItem (CircleOverlayItem1 As CircleOverlayItem) As Boolean
      Remove CircleOverlayItem1 from the CircleOverlay.
      Return True on success otherwise False.
  • OSMDroid_CircleOverlayItem
    Fields:
    • FILL As Style
      Geometry and text drawn with this style will be filled, ignoring all stroke-related settings in the paint.
    • FILL_AND_STROKE As Style
      Geometry and text drawn with this style will be both filled and stroked at the same time, respecting the stroke-related fields on the paint.
    • STROKE As Style
      Geometry and text drawn with this style will be stroked, respecting the stroke-related fields on the paint.
      This is the CircleOverlayItem default.
    Properties:
    • Center As GeoPoint
    • Radius As Float
    • RadiusUnitsType As RadiusUnitsType
    • StrokeColor As Int
    • StrokeStyle As Style
    • StrokeWidth As Float
    • Tag As Object
The CircleOverlay displays CircleOverlayItems - a CircleOverlayItem has a center, radius, stroke width, stroke color, stroke type and Tag property.
The CircleOverlay methods AddCircleOverlayItem and AddCircleOverlayItem2 create, add and return a CircleOverlayItem.
That reference to the CircleOverlayItem can be used to remove it from the overlay using the method RemoveCircleOverlayItem.

All CircleOverlayItem properties can be modified at runtime though you'll need to call the MapView Invalidate method to see any modifications applied.

You can set a CircleOverlayItem radius in units of pixels (fixed size circle) or meters (circle size depends on zoom level).
You can choose the stroke style (same as PathOverlay) of FILL, FILL_AND_STROKE or STROKE.
And the CircleOverlay now has a GetBoundingBox method.

Updated library files and demo b4a project can be downloaded from here: http://b4a.martinpearman.co.uk/osmdroid/CircleOverlay-20140505.zip.

Martin.
 

Spectre

Active Member
Licensed User
How about this...

  • OSMDroid_CircleOverlay
    Fields:
    • RADIUS_UNITS_TYPE_METERS As RadiusUnitsType
    • RADIUS_UNITS_TYPE_PIXELS As RadiusUnitsType
    Methods:
    • AddCircleOverlayItem (Center As GeoPoint, Radius As Float, RadiusUnitsType1 As RadiusUnitsType, StrokeWidth As Float, StrokeColor As Int) As CircleOverlayItem
      Creates, adds and return a CircleOverlayItem object.
    • AddCircleOverlayItem2 (Latitude As Double, Longitude As Double, Radius As Float, RadiusUnitsType1 As RadiusUnitsType, StrokeWidth As Float, StrokeColor As Int) As CircleOverlayItem
    • ClearCircleOverlayItems
      Clear the CircleOverlay of all CircleOverlayItems.
    • GetBoundingBox As BoundingBox
      Returns a BoundingBox that represents the area covered by the centers of all CircleOverlayItems.
    • Initialize
    • IsInitialized As Boolean
    • RemoveCircleOverlayItem (CircleOverlayItem1 As CircleOverlayItem) As Boolean
      Remove CircleOverlayItem1 from the CircleOverlay.
      Return True on success otherwise False.
  • OSMDroid_CircleOverlayItem
    Fields:
    • FILL As Style
      Geometry and text drawn with this style will be filled, ignoring all stroke-related settings in the paint.
    • FILL_AND_STROKE As Style
      Geometry and text drawn with this style will be both filled and stroked at the same time, respecting the stroke-related fields on the paint.
    • STROKE As Style
      Geometry and text drawn with this style will be stroked, respecting the stroke-related fields on the paint.
      This is the CircleOverlayItem default.
    Properties:
    • Center As GeoPoint
    • Radius As Float
    • RadiusUnitsType As RadiusUnitsType
    • StrokeColor As Int
    • StrokeStyle As Style
    • StrokeWidth As Float
    • Tag As Object
The CircleOverlay displays CircleOverlayItems - a CircleOverlayItem has a center, radius, stroke width, stroke color, stroke type and Tag property.
The CircleOverlay methods AddCircleOverlayItem and AddCircleOverlayItem2 create, add and return a CircleOverlayItem.
That reference to the CircleOverlayItem can be used to remove it from the overlay using the method RemoveCircleOverlayItem.

All CircleOverlayItem properties can be modified at runtime though you'll need to call the MapView Invalidate method to see any modifications applied.

You can set a CircleOverlayItem radius in units of pixels (fixed size circle) or meters (circle size depends on zoom level).
You can choose the stroke style (same as PathOverlay) of FILL, FILL_AND_STROKE or STROKE.
And the CircleOverlay now has a GetBoundingBox method.

Updated library files and demo b4a project can be downloaded from here: http://b4a.martinpearman.co.uk/osmdroid/CircleOverlay-20140505.zip.

Martin.
fantastic. I try right away...
 

Spectre

Active Member
Licensed User
Hi Martin, great job...
All works very well ... I have some problems on the distances in meters of the circle ...

CircleOverlayItem1=CircleOverlay1.AddCircleOverlayItem(CurrentPosition, 300, CircleOverlay1.RADIUS_UNITS_TYPE_METERS, 2dip, Colors.red)

300=200 meter +/-
850=800 meter +/-
 

warwound

Expert
Licensed User
@Spectre

Look here: http://code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/src/main/java/org/osmdroid/views/MapView.java.
Lines around 1477:

B4X:
public float metersToEquatorPixels(final float meters) {
                        return meters / (float) TileSystem.GroundResolution(0, mZoomLevelProjection);
                }
This is the method used to convert pixels to meters for each zoom level.
So a circle with a radius of 300 meters will have the expected pixel size if it is centered on the equator.
Further north or south will introduce inaccuracies due to the nature of a spherical projection.

If you center your circles on the equator do you see a 'more correct' size?

Martin.
 

Spectre

Active Member
Licensed User
I have read ... I try to make sure, thanks for the suggestion and the link.

Riccardo.
 

eronquillo

Member
Licensed User
Hi, is there an example on how to utilize gps coordinates from a MySQL DB to be used to display the markers within the bounding box?
 

warwound

Expert
Licensed User
Hi, is there an example on how to utilize gps coordinates from a MySQL DB to be used to display the markers within the bounding box?
Can you give a bit more detail?

Are you wanting to only select rows from your table that are within the map bounds and then create a marker for each row?

Or are you wanting to select all rows from your table but only create a Marker if the row is within the map bounds?

When the map bounds changes do you then need to query the database again?

Martin.
 

eronquillo

Member
Licensed User
Can you give a bit more detail?

Are you wanting to only select rows from your table that are within the map bounds and then create a marker for each row?

Or are you wanting to select all rows from your table but only create a Marker if the row is within the map bounds?

When the map bounds changes do you then need to query the database again?

Martin.
Hi Martin! You're doing an awesome job with OSM Droid. I have incorporated your tutorials into a project where I can check in/out and then store the gps coordinates within an MySQL table. What I would like to do now is select the rows that have unique coordinates (lat and long) that reside within the bounding box and then display them. When the map moves, a re-query on the DB takes place and displays markers.


Edward
 

warwound

Expert
Licensed User
@eronquillo

I don't think you'll find a specific example that'll do as you require.

You say an MySQL database so presumably you're storing the coordinates online and not locally on the device?
Take a look at this Google search https://www.google.co.uk/search?q=mysql+spatial+extensions&ie=UTF-8&oe=UTF-8.
You'd make things easier to do if you use MySQL spatial extensions to store the coordinate data.
It'll take a bit more time to set up table columns using a spatial data type instead of a float or double data type but once set up you'll be able to make much more efficient queries.

Next, if each time the map is panned or zoomed you query your database for coordinates within the map bounds then you'll probably find you're making too many queries - if the user slowly pans the map bit by bit for example you don't want to query the database repeatedly.
I'm not sure what best to suggest here, ideally you want to have the database locally on the device so you don't have to wait for network requests to complete.

Have you seen the Spatialite library?
Spatialite is basically SQLite with spatial extensions.
A local (device based) spatialite database would enable you to make queries much faster and more efficiently than a remote MySQL database.

I think what i'd try to do is:
  • Fetch all coordinates from the database in a single query.
  • Create a b4a Type with properties to contain the coordinate data, use a GeoPoint type for the coordinate property.
  • Iterate through the database query result creating a List of these b4a Type objects - an object for each row in the results.
So you now have a List of objects, each object has a GeoPoint type property.
When you want to update the Markers, get the map bounds as a BoundingBox and iterate through the List of objects:
  • If the object's GeoPoint is within the BoundingBox and the object hasn't yet been added to the map as a Marker then create and add a Marker to the map.
    If a Marker has already been created for the object and added to the map then do nothing.
  • If the object's GeoPoint is not within the BoundingBox and the object has a corresponding Marker on the map then remove the Marker.
    If the object has no corresponding Marker then do nothing.

Martin.
 

IslamQabel

Active Member
Licensed User
Dear Warwound......
I would like to save the current location in map view as image (take screen shot ), is there a way to do that???
Thanks
 

warwound

Expert
Licensed User
Dear Warwound......
I would like to save the current location in map view as image (take screen shot ), is there a way to do that???
Thanks
This has been asked before and there is still no option in OSMDroid to create a Bitmap from the MapView.
There are various generic techniques to convert a View to a Bitmap but i'm not sure if these technqiues would work with the OSMDroid MapView.

I can only suggest that you search the forum, here's a starting point: http://www.basic4ppc.com/android/forum/threads/get-bitmap-of-a-view.28236/

Martin.
 

Spectre

Active Member
Licensed User
Hi Martin!
to the problem of being able to always see the name of the point on the map next to the symbol, you can do something?

Riccardo...
 

warwound

Expert
Licensed User
to the problem of being able to always see the name of the point on the map next to the symbol, you can do something?
Didn't you manage to use the new ViewHostOverlay and ViewHost objects to add Labels to the map next to each point?

Martin.
 

Spectre

Active Member
Licensed User
Didn't you manage to use the new ViewHostOverlay and ViewHost objects to add Labels to the map next to each point?

Martin.
Hi!
you gave me an example, but the labels were visible only when you did click!, I was waiting for developments.
 

warwound

Expert
Licensed User
On a zoom change as the map redraws, the Labels will be redrawn after the map, so there'll be a brief period where the Labels appear to not be anchored to the map.
Is that what you're seeing?

If you're not zooming the map then you should see the Labels anchored to the map and they should smoothly pan as you pan the map.

Does my example in post #375 work as you require but the code you've added to your project not work as required?
 

warwound

Expert
Licensed User
Hmmm...
That's odd.

I would ask you to post your project so i can take a look but bet it's not something you want to post and also it's probably a big project too?
How can i help you debug the problem?

Can you post just the code that creates the ViewHost and ViewHostOverlay?

Martin.
 

Spectre

Active Member
Licensed User
Hmmm...
That's odd.

I would ask you to post your project so i can take a look but bet it's not something you want to post and also it's probably a big project too?
How can i help you debug the problem?

Can you post just the code that creates the ViewHost and ViewHostOverlay?

Martin.
Hi Martin.

I work on for quite some time, even though I was working in VB.net I would like to avoid if possible to publish for now. I have also tried to copy the code of your project, but the result is the same.
B4X:
Sub load_WP ' load wp on map e fit to box+******************************************************************************************
Dim i,kkk As Int
Dim May_LatLng As LatLon
Dim MarkersList As List

MarkersList.Initialize
    Try

    If  Global.ListWPtoNavigate.Get(0) <> "" Then   
        May_LatLng.Initialize       
        Dim WPLoadOnMap As List
        WPLoadOnMap.Initialize
        spinWpSel.Clear
        For i=0 To Global.ListWPtoNavigate.Size -1       
            spinWpSel.Add(Global.ListWPtoNavigate.Get(i))'ad wp on spin to track   
            Dim Marker1 As OSMDroid_Marker
            ModWpAfterMArk(Global.ListWPtoNavigate.Get(i))           
            Dim g As Geodesic' conevert UTM To Lat lon
            g.Initialize
            Dim u As UTM
              u.UtmXZone = CurrentWPFuse
              u.X =CurrentWP_X
              u.Y = CurrentWP_Y
          'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
            If Global.Glob_FUSE_N=True Then
                u.NorthHemisphere=True
            Else
                u.NorthHemisphere=False
            End If
            'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
              Dim ll As LatLon
              ll = g.WGS84UTMTOLatLon(u) 
              May_LatLng.Lat=ll.Lat 'coordinate lat lon on active WP
              May_LatLng.Lon=ll.Lon   
           
            Marker1.Initialize(NomeCurrentWPLong,CurrentWPZone &" " & CurrentWPFuse &" " & CurrentWP_X  &"-" & CurrentWP_Y ,May_LatLng.Lat, May_LatLng.Lon)
            Dim MarkerIcon As BitmapDrawable
           
            Dim AA1,AA2 As Int
            Dim DummyIcon As String
            Dim IconSrch As String
               
            For kkk=0 To Global.ListIconWPMap.Size -1
                IconSrch=Global.ListIconWPMap.Get(kkk)
                AA1=IconSrch.IndexOf("|")
                IconSrch=IconSrch.SubString2(AA1+1,IconSrch.Length)           
                If NomeCurrentWPLong.Contains(IconSrch) = True Then           
                    DummyIcon=Global.ListIconWPMap.Get(kkk)
                    DummyIcon=DummyIcon.SubString2(0,AA1)
                End If
            Next       
           
            Try       
                Dim Bitmap2 As Bitmap=LoadBitmap(Global.GPSDir & "/NatoIcon",DummyIcon)
            Catch
                Dim Bitmap2 As Bitmap=LoadBitmap(Global.GPSDir & "/NatoIcon", "Wp.png")       
            End Try
           
            MarkerIcon.Initialize(Bitmap2)
            Marker1.SetMarkerIcon(MarkerIcon)
            MarkersList.Add(Marker1)
           
            Dim MarkerLabel As Label
            MarkerLabel.Initialize("")
            MarkerLabel.Color=Colors.Yellow
            MarkerLabel.TextColor=Colors.Black
            MarkerLabel.Gravity=Gravity.CENTER           
            MarkerLabel.TextSize=10
            MarkerLabel.Text=Marker1.GetTitle.ToUpperCase
           
            Dim ViewHost1 As OSMDroid_ViewHost
            ViewHost1.Initialize(MarkerLabel, Marker1.GetPoint, 0, 0, Constants1.LayoutParams.ALIGN_CENTER, True)       
            ViewHostOverlay1.AddItem(ViewHost1)               
        Next       
       
        If LastMarker.IsInitialized = False Then
            LastMarker.Initialize(May_LatLng.Lat,May_LatLng.Lon)   
        Else
            LastMarker.Initialize(May_LatLng.Lat,May_LatLng.Lon)
        End If
       
        If MarkerOverlay1.IsInitialized Then
            MapView1.GetOverlays.Remove(MarkerOverlay1)
        End If
       
        MarkerOverlay1.Initialize2("MarkerOverlay1", MapView1, Null)
        MarkerOverlay1.AddItems(MarkersList)
        MapView1.GetOverlays.Add(MarkerOverlay1)
       
    End If
Catch
    Return
End Try
End Sub
 
Top