Via Michelin maps - possible to add to Locus?

Started by 2012, October 24, 2012, 16:06:54

0 Members and 1 Guest are viewing this topic.

2012

UPDATE to this first post: As can be seen from the posts below, the URL system for accessing Via Michelin map tiles have been reverse-engineered and can easily be put into a simple algorithm. The question that remains is if it would be possible to incorporate support for this (and perhaps other "non-standard" tile server systems) into Locus. That would make Locus an even more formidable tool, IMHO. A secondary question is if, otherwise, any other tool, e.g. MOBAC, could be of help to get a cache of tiles from this type of server.

Hi, could anyone say if it is possible to add Via Michelin as a map source to Locus?

//http://www.viamichelin.com/

I've added other 'third-party' map sources by hand before, but they had other 'structure' than Via Michelin, so I'm not sure if it would work.

The Via Michelin maps are excellent especially for France, their Android app is not very good though. :(
  •  

2012

#1
URLs look like this:

http://m12.viamichelin.com/mapsgene/dm/mapdirect;ZnJhX2NfMDE4NWtfcjA2MQ==;MDAwMDAwMDEwMTAwMDAwMDAxMDQ=?
http://m10.viamichelin.com/mapsgene/dm/mapdirect;d29jXzYwMDBrX3IwMg==;MDAwMDAwMDA2MTAwMDAwMDAwMzQ=? (one zoom level out)
http://m11.viamichelin.com/mapsgene/dm/mapdirect;ZXVyX2NfMTAwMGtfcjA1;MDAwMDAwMDA1NTAwMDAwMDAwMjY=? (a further zoom level out)
(map center is not the exact same between the zoom outs)

They are 256x256 PNGs. The m10/m11/m12 hostname part seems to be only load-balancing, it doesn't matter for the result. Also, the ending question-mark is not used.

the URL parameters seem base64 encoded, decoding (//http://www.opinionatedgeek.com/dotnet/tools/base64decode/) gives:
ZnJhX2NfMDE4NWtfcjA2MQ== -> fra_c_0185k_r061
MDAwMDAwMDEwMTAwMDAwMDAxMDQ= -> 00000001010000000104
d29jXzYwMDBrX3IwMg== -> woc_6000k_r02
MDAwMDAwMDA2MTAwMDAwMDAwMzQ= -> 00000000610000000034
ZXVyX2NfMTAwMGtfcjA1 -> eur_c_1000k_r05
MDAwMDAwMDA1NTAwMDAwMDAwMjY= -> 00000000550000000026

My interpretation is that the first part of the URL parameter is the "map name", with the 'k'-number some indication of scale (indicating the real-world width of one tile?) and the 'r'-number probably being a revision number; the second part then being a 2D-coordinate reference to the tile within that map, with the 10-digit tile coordinates being put together into one 20-digit string.

I.e.
map              longitude? latitude?
fra_c_0185k_r061 0000000101 0000000104
woc_6000k_r02    0000000061 0000000034
eur_c_1000k_r05  0000000055 0000000026

Some testing at first seemed to confirm this. If I add 1 to the presumed latitude of the second url (MDAwMDAwMDA2MTAwMDAwMDAwMzQ= -> base64-decoded to 00000000610000000034 -> +1 latitude to 00000000610000000035 -> base64-encoded to MDAwMDAwMDA2MTAwMDAwMDAwMzU=) I get the map tile just south of the original. (Hereafter I refer to the coordinate string in the form 61/34.) However, if I subtract one from the 'latitude', to get 61/33, I get a tile 1 position south and two positions west of the original 61/34. I then try 60/34, and get the tile 1W (one west) of 61/34, all good there. But 62/34 gets me the tile 2S1W of 61/34. OK, so here's something a bit more complex at work. I start mapping out some tile URLs around the 61/34 position and get even more intriguing numbers, see below. I also try to find some pattern in their base 4 and binary equivalents. Perhaps someone is able to interpret them and understand the system.

In the tile patterns below "*" indicates the same 61/34 position tile.
decimal "tile referral" values:
              54/39  55/39  50/45
       61/32  60/34  61*34  56/40
60/33  61/33  60/35  61/35  56/41
62/33  63/32  62/34  63/34  58/40
              62/35  63/35  58/41

base 4 (looking for semi-QuadKey patterns):          
                    313/213  302/231
                    331*202  320/220
                    331/203  320/221
                    333/202  322/220
                    333/203  322/221

binary (looking for some 1d+1d "binarykey" pattern):
  110110/100111  110111/100111  110010/101101
  111100/100010  111101*100010  111000/101000
  111100/100011  111101/100011  111000/101001
                 111111/100010  111010/101000
                 111111/100011  111010/101001

Anyone doing better than this at me? It seems too simple and ordered to indicate some real effort at encrypting and making things difficult to reverse-engineer.

Any chance of Locus, now or in the future, handling such a map structure (if we understand the tile referral pattern)? The ability to base64 encode is obviously needed.

The custom online map sources I've added myself before have been of the "type 5"/QuadKey structure, much more simple (and elegant).
  •  

2012

#2
Some more URLs and decode values.

I will refer to "map ref" and "tile ref", e.g. "http://m10.viamichelin.com/mapsgene/dm/mapdirect;<map ref>;<tile ref>?". I will also divide the tile ref string in two 10-digit parts for clarity.

Refs of max zoomed out, "world", level:

map ref: wot_0180m_r02

tile refs:
0000000000 0000000000  0000000001 0000000000  0000000000 0000000002  0000000001 0000000002
0000000000 0000000001  0000000001 0000000001  0000000000 0000000003  0000000001 0000000003
0000000002 0000000000  0000000003 0000000000  0000000002 0000000002  0000000003 0000000002
0000000002 0000000001  0000000003 0000000001  0000000002 0000000003  0000000003 0000000003
This is the complete tileset of "world" map!

abbreviated:
0/0 1/0 0/2 1/2
0/1 1/1 0/3 1/3
2/0 3/0 2/2 3/2
2/1 3/1 2/3 3/3

Let us call the first part of tile ref (before our "/") TRa and the second part TRb.
We can deduce that knowing only TRa or only TRb is not enough to discern the exact tile position in either dimension. We need both TRa and TRb, then we get a unique identifier for the tile position (in both dimensions).

binary:
00/00 01/00 00/10 01/10
00/01 01/01 00/11 01/11
10/00 11/00 10/10 11/10
10/01 11/01 10/11 11/11

To denote the individual digit in a TRa or TRb (binary) number, let us count them backwards and denote them TRa1, TRa2, et cetera and vice versa.

Then we see that the tile column (longitude) is defined by TRa1 together with TRb2. In fact if we concatenate these digits and reverse their order, we get a proper 00-11 (0-3 decimal) column tile ref (in a system from left to right).
The row position (latitude) on the other hand, are defined by TRa2 together with TRb1. Concatenate these digits for a proper row tile ref (in a top to bottom system).

This makes for easy conversion between a "straight-forward" tile ref system and the "michelin" system. Could we find a conversion algorithm that holds up for all zoom levels?

Let's continue with some reference samples from the different zoom levels. I've tried to keep the same spot (Notre Dame in Paris) centered throughout the zooming.

zoom    map ref           tile ref (example)
 0      wot_0180m_r02     0000000000 0000000003
 1      woc_0090m_r02     0000000006 0000000000
 2      woc_0045m_r02     0000000000 0000000013
 3      woc_0024m_r02     0000000015 0000000010
 4      woc_0012m_r02     0000000020 0000000031
 5      woc_6000k_r02     0000000052 0000000039
 6      woc_3000k_r02     0000000069 0000000109
 7      woc_1500k_r02     0000000212 0000000133
 8      eur_c_1000k_r05   0000000051 0000000014
 9      fra_c_0275k_r061  0000000004 0000000062
10      fra_c_0185k_r061  0000000099 0000000002
11      eur_c_0060k_r08   0000000256 0000001492
12      eur_c_0024k_r08   0000002483 0000000692
13      eur_c_0012k_r08   0000001405 0000004940
14/max  eur_c_0006k_r08   0000003610 0000006830

Note some things here, numbers are generally increasing the further we zoom in, per "map type" (woc/eur_c/fra_c). Increasing numbers could indicate some per-map QuadKey reference system, which might be discernible when we really understand the tile ref numbers.

Side note: the 'fra_c' is the real gold of the michelin map data, so I would be happy to just have those zoom levels, but let us just keep hacking for now.

Next step, analyze tile refs of the zoom 1 level map, see if they in part can be produced from their "parent" zoom level 0 tile ref.
  •  

2012

#3
So...

I've now zoomed into level 1, and find that the 0/3 (michelin tile ref) tile of level 0 corresponds to a 2x2 square of level 1 tiles. Very nice so far. Let us see what their tile refs are then.

0000000006 0000000000  0000000007 0000000000
0000000006 0000000001  0000000007 0000000001

abbreviated:
6/0 7/0
6/1 7/1

binary:
110/000 111/000
110/001 111/001
Where the parent tile ref in binary was 00/11.

We can see that most digits are common to the whole 2x2 set of tile refs, i.e. TRa2-3 and TRb2-3. Within this 2x2 set, the individual tiles can be referenced by only TRa1 and TRb1.

Let us now look at the level 1 corresponding tiles of another level 0 tile, and see if we can find a pattern (hopefully à la QuadKey).

We will look at the level 0 tile 1/1, just left of the 0/3 tile we just looked at.

abbreviated tile refs:
2/2 3/2
2/3 3/3

binary:
010/010 011/010
010/011 011/011
Parent tile's binary ref: 01/01

Pattern emerging! Again, we see that TRa2-3 and TRb2-3 are common to the whole 2x2 set. Within the 2x2 set, the individual tiles can also this time be referenced by only TRa1 and TRb1.

Could it be that the tile refs for the child 2x2 tiles are constructed by just switching around TRa and TRb of the parent tile, and then adding a new digit to the end of them (in binary, pushing the leftmost zero off record)?

In that case, this seems to be how the new digit is added to TRa/TRb:
0/0 1/0
0/1 1/1

Let's see if it holds up at a whole different zoom level. Remember that "61/34" tile from before (a couple of posts up)?

decimal "tile referral" values:
              54/39  55/39  50/45
       61/32  60/34  61*34  56/40
60/33  61/33  60/35  61/35  56/41
62/33  63/32  62/34  63/34  58/40
              62/35  63/35  58/41

binary (looking for some 1d+1d "binarykey" pattern):
  110110/100111  110111/100111  110010/101101
  111100/100010  111101*100010  111000/101000
  111100/100011  111101/100011  111000/101001
                 111111/100010  111010/101000
                 111111/100011  111010/101001

Note the 2x2 square of tile refs that has "61*34" in the top right corner, it follows our rule about last digit distribution that we just presumed AND all the other digits are the same. Bingo?
If we reverse-engineer what should be the tile ref of the parent tile to that 2x2 square, we get 10001/11110 (remember we switch TRa/TRb around).
Let us see what the actual tile ref is...

http://m10.viamichelin.com/mapsgene/dm/mapdirect;d29jXzAwMTJtX3IwMg==;MDAwMDAwMDAyMjAwMDAwMDAwMzE=?
->
map ref: woc_0012m_r02
tile ref: 0000000022 0000000031

And 22/31 in binary is... 10110/11111. Damned.

There is something more going on when "inheriting" the parent tile ref than just TRa/TRb switching. But I believe we will find out soon.
  •  

2012

#4
So, let us slow down a bit and go back to tile 6/0 of zoom level 1 (the top left child tile of level 0 tile 0/3).

Remember, parent tile 00/11 gave us child tiles
110/000 111/000
110/001 111/001
(all binary here, obviously)

Now we will see what tile refs the child tiles of 110/000 have.
0/12 1/12
0/13 1/13

In binary:
0000/1100 0001/1100
0000/1101 0001/1101

So far, our originally hypothesized algorithm seems to hold up, hmm.

The tile refs for child tiles of 0/13 should then be:
11010/00000 11011/00000
11010/00001 11011/00001

In decimal:
26/0 27/0
26/1 27/1

But they are not. What we find is:
13/11 24/1
15/10 26/0

In binary:
01101/01011 11000/00001
01111/01010 11010/00000

Hmm, looking at the child tiles, I see that they do not map up 100% nice with the 'parent tile'. Perhaps it's just a matter of a 1-tile misalignment in both dimensions (26/0 is still there, and the TRa1/TRb1 digits of our 2x2 still match our pattern if we take the same misalignment into account).

I am rather sure that if we would look at the three 'missing' tiles just around 26/0 (to E, SW and S respectively) we would find our 2x2 square. But do the three 'unexpected' tiles here match what we would expect from a misalignment?

World map in binary was:
00/00 01/00 00/10 01/10
00/01 01/01 00/11 01/11
10/00 11/00 10/10 11/10
10/01 11/01 10/11 11/11

We dived into 01/01 00/11 and found:
010/010 011/010 110/000 111/000
010/011 011/011 110/001 111/001

Where 110/000, corresponding to our hypothesis, gave us:
0000/1100 0001/1100
0000/1101 0001/1101

We expected 0000/1101 to give:
11010/00000 11011/00000
11010/00001 11011/00001

But we found instead:
01101/01011 11000/00001
01111/01010 11010/00000

If this was because of misalignment (and if our hypothesis is correct), the parents of these tiles would be:
0101/0110 0000/1100
0101/0111 0000/1101
(The tile refs in the left column are calculated from our hypothesis and the fact that 011/010 is the left neighbor of 110/000 and that they should form the right column of their 2x2 square.)

And then the actual tile refs we found should have been:
01101/01011 11000/00001
01111/01010 11010/00000

Yes! That matches up perfectly against what we found. So it seems that it is just a case of misalignment.

Could that also be the case with the earlier letdown with 10110/11111 when we were expecting 10001/11110? Well, that tires my brain too much to test at this point, but what we do have here is some system of tile reference that is at least consistent per map level, even if it might not have perfect parent<->child consistency. Hooray!

We could now make a simple algorithm that converts back and forth between standard reference systems (x,y or QuadKey) and the "michelin" system.

But could Locus support this rather unusual tile reference system?
  •  

2012

#5
A quick note to add the observation that this algorithm also explains the arrangement of the zoom level 0 tile refs.

Take a zoom level "-1" base 2x2 square:
0/0 1/0
0/1 1/1

And apply our algorithm for creating "child tile" refs:
1. convert to binary, TRa and TRb separately
2. switch TRa/TRb
3. rotate one bit left, drop the carry
4. create child tile refs by quadrupling tile refs into 2x2 2x2 squares
5. replace the least significant bit of the child tile refs according to this matrix
0/0 1/0
0/1 1/1
6. convert back to decimal (keep padded with zeroes to 10 digits total) and reconcatenate TRa and TRb

Let us try the steps, one by one.

Start with the assumed "level -1" tile ref matrix:
00000000000000000000 00000000010000000000
00000000000000000001 00000000010000000001

1. Convert to binary (not that difficult with all numbers being either 0000000000 or 0000000001 to begin with), I've inserted a slash to make things more readable:
0000000000/0000000000 0000000001/0000000000
0000000000/0000000001 0000000001/0000000001
(Yes, it is the same, nothing changed, sic.)

2. Switch TRa/TRb:
0000000000/0000000000 0000000000/0000000001
0000000001/0000000000 0000000001/0000000001

3. Rotate one bit left, drop the carry, insert whatever (I use 0 here):
0000000000/0000000000 0000000000/0000000010
0000000010/0000000000 0000000010/0000000010

4. Create child tile refs by quadrupling into 2x2 2x2 squares:
0000000000/0000000000 0000000000/0000000000 0000000000/0000000010 0000000000/0000000010
0000000000/0000000000 0000000000/0000000000 0000000000/0000000010 0000000000/0000000010
0000000010/0000000000 0000000010/0000000000 0000000010/0000000010 0000000010/0000000010
0000000010/0000000000 0000000010/0000000000 0000000010/0000000010 0000000010/0000000010

5. Replace the least significant bits of child tile refs according our matrix
0000000000/0000000000 0000000001/0000000000 0000000000/0000000010 0000000001/0000000010
0000000000/0000000001 0000000001/0000000001 0000000000/0000000011 0000000001/0000000011
0000000010/0000000000 0000000011/0000000000 0000000010/0000000010 0000000011/0000000010
0000000010/0000000001 0000000011/0000000001 0000000010/0000000011 0000000011/0000000011

6. Convert back to decimal (keep padded with zeroes to  10 digits total) and reconcatenate TRa and TRb
00000000000000000000 00000000010000000000 00000000000000000002 00000000010000000002
00000000000000000001 00000000010000000001 00000000000000000003 00000000010000000003
00000000020000000000 00000000030000000000 00000000020000000002 00000000030000000002
00000000020000000001 00000000030000000001 00000000020000000003 00000000030000000003

And presto, we have the level 0 tile ref system.

To make an actual tile url out of it just base64-encode it and prepend with "http://m11.viamichelin.com/mapsgene/dm/mapdirect;d290XzAxODBtX3IwMg==;".

This method could be repeated ad infinitum to create further zoom levels in the same map system (with a corresponding change of the map ref part of the URL parameter of course).

I think that we will find that for every zoom level, the system chooses a tile ref system of 2^n*2^n size that is just large enough to fit the number of tiles needed. Therefore, when we zoom into the eur_c (Europe) map from the woc (world) map, the tile ref system can shrink a bit, because we are in fact having fewer tiles, even though we zoomed in (because a map of Europe is less than a quarter of the size of a map of the world). The same happens when we switch between eur_c and fra_c (France) maps.
  •  

gynta

#6
Quote from: "2012"The Via Michelin maps are excellent especially for France,...
...but not really up to date. isn't it?

2012

#7
Quote from: "gynta"
Quote from: "2012"The Via Michelin maps are excellent especially for France,...
...but not really up to date. isn't it?
Well, what is ever up to date in the world of maps? ;)
But from what I hear they are updated pretty regularly. I don't live in France, but I am there a couple of times every year. Their annotation of scenic routes is excellent IMHO. They are also good at having correct information about the RF ("routes forestières"), from my experience. I've not used them outside of France, no idea how usable they are there. (See the huge difference in revision number between the France map and others at my earlier post //http://forum.locusmap.eu/viewtopic.php?f=43&t=2477#p16655.)
I understand that they also sell their maps in file format, I do not know if it is the same data as the online. Some information available here: //http://wiki.navit-project.org/index.php/Map_driver#Raw_notes_about_ViaMichelin
  •  

jusc

#8
There exists a map tool called Topo Map. It´s able to convert maps into OruxMaps format, that can be used with Locus too. viewtopic.php?f=43&t=1954  ==> http://download.cnet.com/TopoMap/3000-1 ... 31395.html. There is a doc file inside, that describes how to use it. Maybe it similiar to your project?
Regards J.
  •  

2012

#9
Quote from: "jusc"There exists a map tool called Topo Map. It´s able to convert maps into OruxMaps format, that can be used with Locus too. viewtopic.php?f=43&t=1954  ==> http://download.cnet.com/TopoMap/3000-1 ... 31395.html. There is a doc file inside, that describes how to use it. Maybe it similiar to your project?

Interesting read in the documentation about how they access the IGN France map from Geoportail. However, it seems that Geoportail has since then switched to a more straight-forward system and it is now also possible to access via a quite simple XML with MOBAC. (In fact I could not get TopoMap to work anymore.)
The system is not the same as for Via Michelin however, but I guess it proves that if there is a will there is a way. Maybe the TopoMaps author would be interested in adapting a solution for Via Michelin downloads.

However, in  general I much prefer to be able to add a custom online source than prefetching large tile databases. It is much more convenient for the user AND it saves load on the map server.

My plan now is to sum up the system of access to Via Michelin tiles and post a proper request on Locus' Get Satisfaction place. If that is turned down I guess I will have to resort to either write a download app myself or see if MOBAC or TopoMap authors could be interested in supporting the format.

I also found quite thorough information about the APIs available with Via Michelin: //http://dev.viamichelin.com/
  •  

cftt

#10
Quote from: "2012"We could now make a simple algorithm that converts back and forth between standard reference systems (x,y or QuadKey) and the "michelin" system.


Hi 2012, good job!

But I can't get the good algorithm to transform x,y and zoom level to the michelin system.

Do you have a script for mobac?

Thx
  •  

2012

#11
Hi, happy to see some interest in this. I do not currently have the time to do more work on this, and I am not very familiar with the workings of MOBAC, but for someone who is, he/she could find all the reverse-engineering work done above. My next step would be either to write pseudo-code for the transformation algorithm (to make it even clearer to someone else) or to learn more about how MOBAC works and see if this work can actually be completed with MOBAC or if it is too complex and needs some custom-made third-party app support.
  •  

cftt

#12
Hi. Your reverse-engenering is clear. I understand the way the Michelin tiles are created....
But I am unable to write a good algorithm to get the right michelin tile from x, y and zoom level as input.
If you have time to develop it, I would be happy to read your pseudo code for transformation and so I could adapt it as an bsh addon for MOBAC.
Get in touch...
  •  

2012

#13
OK, I couldn't resist. :)

Here is ugly untested hack pseudo code, tell me if it works for you, I've probably messed up somewhere, just ask if it is unclear/faulty.

I think the algorithm could be done without recursion, but I couldn't think of a way right now, rusty programming/math skills.


urlstring(mapname,r,c) {
;
; mapname: fra_c_0185k_r061, ...
; r: row (1...n, positive integer, top to bottom)
; c: column (1...n, positive integer, left to right)
;
tile = rc2tile(r,c)
tileA = tile[0]
tileB = tile[1]
tilestring = tiles2string(tileA,tileB)
mapb64string = base64encode(mapname)
tileb64string = base64encode(tilestring)
return mapb64string + tileb64string
}

rc2tile(r,c) {
if (r=1 and c=1) {
A = 0
B = 0
}
else {
r2 = round(r/2)
c2 = round(c/2)
tile2 = rc2tile(r2,c2)
tile2A = tile2[0]
tile2B = tile2[1]
A = tile2B * 2 + ((c-1) mod 2))
B = tile2A * 2 + ((r-1) mod 2))
;
; note that the A/B switch above is intentional
;
}
return (A,B)
}

tiles2string(a,b) {
p=length(a)
q=length(b)
return repeat("0",10-p) + a + repeat("0",10-q) + b
}

;
; example use
;
geturl(http://m10.viamichelin.com/mapsgene/dm/mapdirect; + urlstring(fra_c_0185k_r061,14,58))

;
; if you don't have mod/%/modulo available, use this:
;
mod(a,n) {
return a - (n * int(a/n)).
}
;
; and "X mod Y" above has to be rewritten as "mod(X,Y)"
;

Also note, here is some much simpler explanations of the matrix definition - still recursive, but without the totally unnecessary dec<->bin conversions I've used above:

In the "cell quading" way of above:
original cell:
A:B
->
child cells:
2B:2A   2B+1:2A
2B:2A+1 2B+1:2A+1

In quarter-the-matrix approach:
(made an error in this, might add later)

Or, reversely/recursively defined...

Every matrix cell has data in the form of x:y, the cells are referred to with M[r,c] where r=row and c=column.

for r=c=1:
M[1,1] = 0:0

for all other cases with r and c positive integers:
M[r,c](x) = M[round(r/2),round(c/2)](y)*2+((c-1) mod 2)
M[r,c](y) = M[round(r/2),round(c/2)](x)*2+((r-1) mod 2)

(recurses until first case reached)

NOTHING OF THIS IS THOUROUGHLY TESTED!

edit
Zoom levels with correpsonding "map names" would of course have to be set up by hand.
And then there is some work of aligning the tiles to the right geoposition, but the above pseudeocode should, barring mistakes, be enough to know how to call any specified tile in a map.

edit again
Corrected an obvious mistake in tiles2string pseudo code.
  •  

cftt

#14
Here a bsh script from your pseudo code.

It need some adjustments with the definition of origins at each zoom level....
static import java.lang.Math.*;

name = "Michelin2012";
tileType = "png";
tileSize = 256;
minZoom = 2;
maxZoom = 16;
tileUpdate = TileUpdate.IfModifiedSince;
backgroundColor = "#ffffff";
ignoreError = "True";

String urlstring(int zm,int r,int c) {
int[] tile;
int new_zoom=zm-2;
String zs;
switch (new_zoom)    {
case 0  : zs="wot_0180m_r02"   ; break;
case 1  : zs="woc_0090m_r02"   ; break;
case 2  : zs="woc_0045m_r02"   ; break;
case 3  : zs="woc_0024m_r02"   ; break;
case 4  : zs="woc_0012m_r02"   ; break;
case 5  : zs="woc_6000k_r02"   ; break;
case 6  : zs="woc_3000k_r02"   ; break;
case 7  : zs="woc_1500k_r02"   ; break;
case 8  : zs="eur_c_1000k_r05" ; break;
case 9  : zs="fra_c_0275k_r061"; break;
case 10 : zs="fra_c_0185k_r061"; break;
case 11 : zs="eur_c_0060k_r08" ; break;
case 12 : zs="eur_c_0024k_r08" ; break;
case 13 : zs="eur_c_0012k_r08" ; break;
case 14 : zs="eur_c_0006k_r08" ; break;
}
   tile = rc2tile(r,c);
   int tileA = tile[0];
   int tileB = tile[1];
   String tilestring = tiles2string(String.valueOf(tileA),String.valueOf(tileB));
   String mapb64string = Tools.encodeBase64(zs.getBytes( "UTF-8" ));
   String tileb64string = Tools.encodeBase64(tilestring.getBytes( "UTF-8" ));
   return mapb64string + ";"+tileb64string;
}

int[] rc2tile(int r,int c) {
int[] tile2;
int A;
int B;
//javax.swing.JOptionPane.showMessageDialog(null,r+" "+c);
   if ((r==1)&&(c==1)) {
      A = 0;
      B = 0;
   }
   else {
Double r0=(Double)r;
Double c0=(Double)c;
      int r2 = round(r0/2);
      int c2 = round(c0/2);
      tile2 = rc2tile(r2,c2);
      int tile2A = tile2[0];
      int tile2B = tile2[1];
      A = tile2B * 2 + ((r-1) % 2);
      B = tile2A * 2 + ((c-1) % 2);
            // note that the A/B switch above is intentional
   }
   return new int[] {A,B};
}

String tiles2string(String a,String b) {
   String ps="";
   String qs="";
   int p=a.length();
   int q=b.length();
   for(i=0;i<(10-p);p++)
ps=ps+"0";
   for(i=0;i<(10-q);q++)
qs=qs+"0";
   return ps + a + qs + b;
}

String getTileUrl( int zoom, int x, int y ) {
return "http://m10.viamichelin.com/mapsgene/dm/mapdirect;" + urlstring(zoom,x+1,y+1);
}

Try this with MOBAC and MapEvaluator for tweeking...
  •