Skip to content

Problem indexing maps in from Local Directory source #64

Open
@PeterQFR

Description

Describe the bug
The in built MapSource.get_y() does not produce the correct value for y for the southern hemisphere ie, latitudes that are negative.
And when it is fixed, the images are then indexed in the wrong order for surrounding images (indicating a negative increment).

N.B. I did not have this issue with the online sources for some reason they output the correct indexing. So I may be introducing a bug with my LocalMapSource class.

To Reproduce
Code example showing the issue:
I am using a new source that loads the map images from a local directory (could be part of the bug):

LocalSource.py:

# coding=utf-8
"""
Local tiles provider for MapView
============================
"""

__all__ = ["LocalMapSource"]


import io
import threading
import math
import os

from kivy.core.image import Image as CoreImage
from kivy.core.image import ImageLoader

from kivy_garden.mapview.downloader import Downloader
from kivy_garden.mapview.source import MapSource
from math import atan, ceil, cos, exp, log, pi, tan
from kivy_garden.mapview.utils import clamp
from kivy_garden.mapview.constants import (
    CACHE_DIR,
    MAX_LATITUDE,
    MAX_LONGITUDE,
    MIN_LATITUDE,
    MIN_LONGITUDE,
)
from kivy.metrics import dp

class LocalMapSource(MapSource):
    '''
        Similar to the Source except references a local directory 
        {dir}/{z}/{x}/{y}.png
        where {dir} is a local directory
    '''
    def __init__(self, directory, **kwargs):
        super().__init__(**kwargs)
        self.directory = directory
        self.attribution = ""
        self.projection = ''
        self.is_xy = self.projection == "xy"

    def fill_tile(self, tile):
        if tile.state == "done":
            return
        Downloader.instance(self.cache_dir).submit(self._load_tile, tile)

    def _load_tile(self, tile):
        # global db context cannot be shared across threads.
        
        filepath = os.path.abspath('{}/{}/{}/{}.png'.format(self.directory, 
                     tile.zoom, tile.tile_x, tile.tile_y))

        if os.path.exists(filepath):
    
            im = CoreImage(filepath)
            
            if im is None:
                tile.state = "done"
                return

            return self._load_tile_done, (tile, im,)
        else:
            
            tile.state="done"
            return

    def _load_tile_done(self, tile, im):
        tile.texture = im.texture
        tile.state = "need-animation"

    def get_x(self, zoom, lon):
        if self.is_xy:
            return lon
        x = super().get_x(zoom, lon)
        return x
#This is an alternate implementation from openstreetmap.
#        n = 2.** zoom
#        lon = clamp(lon, MIN_LONGITUDE, MAX_LONGITUDE)
#        x =  int(((lon +180.)/360.)*n)
#        print('z {} lon {} x {}'.format(zoom, lon, x))
#        return x

    def get_y(self, zoom, lat):
        if self.is_xy:
            return lat
        y= super().get_y(zoom, lat)
        print("getY {} {} {}".format(lat, zoom, y))
        return y
#This is an alternate implementation from openstreetmap.
#        n = 2.**zoom
#        lat = clamp(lat, MIN_LATITUDE, MAX_LATITUDE)
#        lat_rad = math.radians(lat)
#        y= int(n*(1.-math.asinh(tan(lat_rad))/pi)/2.0)
#        print('z {} lat {} y {}'.format(zoom, lat, y))
#        return y

    def get_lon(self, zoom, x):
        if self.is_xy:
            return x
        return super().get_lon(zoom, x)

    def get_lat(self, zoom, y):
        if self.is_xy:
            return y
        return super().get_lat(zoom, y)

main.py:


from kivy.app import App
from kivy_garden.mapview import MapView, MapSource
from local_source import LocalMapSource
from kivy.uix.widget import Widget
from kivy.properties import (
        NumericProperty, ReferenceListProperty, ObjectProperty
        )



class MapViewApp(App):
    def build(self):
        mapview = MapView(
                zoom=11, lat=-27.5399, lon=152.8045)
      
        mapview.map_source=LocalMapSource('local_dir')
              
        return mapview

if __name__ == "__main__":
    MapViewApp().run()       

Expected behavior
A clear and concise description of what you expected to happen.
I expect the system to display the map correctly. To produce the correct y index for the relevant image. And to order neighbours in the vertical direction correctly.

I found a fix for the y value of the center image by removing the negation in this clamp

lat = clamp(-lat, MIN_LATITUDE, MAX_LATITUDE)

That fixes the indexing issue. However the images are still in reverse order in the N-S direction. see image below:

Logs/output
If applicable, add screenshots to help explain your problem.

Platform (please complete the following information):
Linux, python 3.8

Screenshot from 2023-02-12 11-32-17
anch/commit

Additional context
Add any other context about the problem here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions