[solved] Sharply cropped map


I’m trying to generate a map that is sharply cropped to its bounding box. This is just a visual top layer (i. e. no routing…) sitting on top of another map which should seamlessly take over outside the top layers bounding box.

Using osmconvert without any of the three --complete-… options but with --drop-broken-refs and subsequently splitter (seemingly independent of but even with --keep-complete=false, --overlap=0 and --no-trim=false) results in splitter output like

Processing /home/....o5m
Bounding box 6.5 51.400000000000006 7.6000000000000005 52.1
10.000.000 nodes parsed... id=3463546112
Fill-densities-map pass took 1745 ms
Exact map coverage read from input file(s) is (51.40000820159912,6.500000953674316) to (52.10000038146973,7.600007057189941)
Rounded map coverage is (51.3720703125,6.4599609375) to (52.119140625,7.6025390625)

And this “Rounded map coverage” (pretty much matching the maximal extension of elements if using osmconvert with the --complete-… options) is exactly what mkgmap renders; filled with background polygone without any elements outside the specified bounding box. An unwanted “frame” of different width lon/lat.

From https://wiki.openstreetmap.org/wiki/Mkgmap/help/splitter

Am I missing an option to force splitter or mkgmap to exactly respect the bounding box or are there means to crop the map later on? Have not tried editing areas.list manually…



Splitter creates tiles which are aligned to multiples of Garmin units. In your special case splitter will probably not split into multiple tiles, so I wonder why you use the program?

Hey Gerd,

first off, this was a trial only for a biger area later on. And just the standard toolchain.
Then splitter shure did create 15 tiles for that area:

Solution is nice. Can't find a better solution with search-limit 200000: 15 tile(s). The smallest node count is 930019 (77 %), the worst aspect ratio is near 3.12
Final solution: 15 tile(s). The smallest node count is 930019 (77 %), the worst aspect ratio is near 3.12
This seems to be nice.
Area 54030001 covers (51.943359375,7.0751953125) to (52.119140625,7.6025390625) and contains 930019 nodes (77 %)
Area 54030002 covers (51.7236328125,7.0751953125) to (51.943359375,7.6025390625) and contains 1067181 nodes (88 %)
Area 54030003 covers (51.7236328125,6.4599609375) to (51.85546875,7.0751953125) and contains 1070928 nodes (89 %)
Area 54030004 covers (51.85546875,6.4599609375) to (52.119140625,7.0751953125) and contains 1082845 nodes (90 %)
Area 54030005 covers (51.50390625,6.4599609375) to (51.7236328125,6.8115234375) and contains 1125037 nodes (93 %)
Area 54030006 covers (51.3720703125,6.4599609375) to (51.50390625,6.8115234375) and contains 1170943 nodes (97 %)
Area 54030007 covers (51.5478515625,7.294921875) to (51.7236328125,7.6025390625) and contains 1145831 nodes (95 %)
Area 54030008 covers (51.5478515625,6.8115234375) to (51.7236328125,7.0751953125) and contains 1025498 nodes (85 %)
Area 54030009 covers (51.5478515625,7.0751953125) to (51.7236328125,7.294921875) and contains 1100016 nodes (91 %)
Area 54030010 covers (51.3720703125,6.8115234375) to (51.4599609375,7.1630859375) and contains 1030114 nodes (85 %)
Area 54030011 covers (51.3720703125,7.1630859375) to (51.4599609375,7.6025390625) and contains 1094286 nodes (91 %)
Area 54030012 covers (51.4599609375,7.4267578125) to (51.5478515625,7.6025390625) and contains 937265 nodes (78 %)
Area 54030013 covers (51.4599609375,7.20703125) to (51.5478515625,7.4267578125) and contains 1051710 nodes (87 %)
Area 54030014 covers (51.4599609375,6.8115234375) to (51.5478515625,6.9873046875) and contains 1018340 nodes (84 %)
Area 54030015 covers (51.4599609375,6.9873046875) to (51.5478515625,7.20703125) and contains 1025615 nodes (85 %)

But lastly, I don’t care for any exact bounding box. So doing one iteration and specifying the rounded result of a first splitter run as osmconverts bounding box for a second made some big improvement!

There still are some polygones and lines cropped a little early in while others pretty much aren’t, but the overall outcome is much better. I guess, this remainder is due to the relatively coarse old img format, as discussed recently?

Initially I was considering an alignment effect like this but got derailled by the “rounded” output line.



I don’t understand what you mean. The splitter produces rectangular tiles which should cover exactly the “Rounded map coverage” bbox.
If the data inside those tiles is complete there should be nothing missing. Maybe use osmconvert with the --complete option(s) or a much larger bbox and tell splitter the bounding box with the --polygon-file option.
Or maybe you describe the effect of trimming in splitter? Do you use --no-trim?

My understanding is this: You want to produce two rectangular mapsets with exactly the same outer bounds but possibly different number of tiles, one will be transparent, the other not. Is that correct? Maybe look at the scripts from Thomas Kukuk, I think he does that for his maps:


Figured it out; seems to work quite well now.

From the “rounded” comment I had gotten the assumption, that osmconvert somehow considered and communicated the extend of elements extending the bbox, hence tried to avoid that omitting the --complete-… options and even using --drop-broken-refs. Unfortunately this was still in place on the first quick trial following your pointers last night.

With the --complete-… osmconvert options all elements end exactly at the Garmin unit compatible bbox atm. Will still try to osmconvert a larger patch and have splitter crop that using the --polygon-file options later this week, since I‘m somewhat pressed on time atm. Could be the easyier approach. BTW: Would you have a source detailling the relation of these Garmin units and lon/lat?

I played with --no-trim but that did neither remove my border sections nor cause the problems. Im not shure, what it‘s supposed to accomplish anyway. Trim the (blank) areas between a bounding polygone and by default rectangular generated tiles?

No, although using a somewhat similar layered approach to Torsten, the intention here is pretty different.
I‘m rendering maps for fast road biking, hence simplified and decluttered for easy readability and focussed on suitable roads only. Garmin headunits nowadays come pre-equipped with full EU-coverage of OSM-based maps, dem, index, time-zone and bike-adapted routing in separate files/layers. I very seldom use routing on the device at all and tend to think, that Garmins routing probably outmatches my own approaches anyway. Same for dem and search (see below). Hence I leave all Garmin Layers enabled and only cover up the rendering with my own. Generated w/o routing and index; using Garmins POI types or own types in ranges way off well known types, not to confuse POI search. Which from Garmins underlaying maps is much better than from my decluttered maps anyway. On top of that I optionally use a transparent layer for cycling networks (from relations) by surface, another with own corrections/extensions to that and quite rarely contour lines.
On the one hand I like to quickly regenerate relatively small areas of coverage in optimizing style and typ. One the other hand race-biking including participating in events easily extends over quite some area. Hence I‘ve driven “out of my map” more than once lately. No problem as everything continues to function, only the suboptimal Garmin rendering becomes visible where my layer ends. Except for the quite relevant border sections with incomplete or missing elements we dealt with here.
Note to myself/finger exercise: Can that be avoided? Have the own map end sharply and seamlessly “hand over” to the underlaying rendering, where it ends? Solved. :slight_smile:

Thanks again


This is the code used in splitter:

	public static int toMapUnit(double l) {
		double delta = 360.0D / (1 << 24) / 2; // Correct rounding
		if (l > 0)
			return (int) ((l + delta) * (1 << 24) / 360);
		return (int) ((l - delta) * (1 << 24) / 360);

In words: lat/lon values from -180.0 to 180.0 are converted to integers from -16777216 to 16777216
The reverse function:

	public static double toDegrees(int val) {
		return 360.0d * val / (1 << 24) ;

24-bit resolution integer? Simple as that?
I’m no coder, but I see, I need to think like one, to avoid dumb questions.

Not a dumb question. The words “Garmin unit” are used in the help but I found no explanation for it anywhere except for the source.

Hey Gerd,

sorry for revisiting this topic once more although my immediate problem is solved. But something still seems quite odd to me:

If my math is correct, 24 bit quantization should give an increment of a little more than 2 m or 2.15E(-5) degrees, hence an alignment offset half of that at max. I think, we wouldn’t have talked about such at all.

My offsets due to aligning the bbox to Garmins quantization (rounded) were up to around 3 km, or 0.028 degrees (see the sample output in the first post). That’s something in the ballpark of 3 decades off the above!

Am I right assuming that D/d in your code snippets is converting from/to degrees HMS vs. decimal?


Splitter calculates a density grid and counts the nodes for each grid element. The --resolution gives the dimension of a grid element and thus also the alignment. The default resolution is 13, not 24. So, I think it is something like 4km.

So THAT’s the dominant effect for the bbox modification! I guess, it will always enlarge it in all dimensions to the next multiple.

Missed that so far (RTFM, but you’ve got to get the picture too…), but got it now. My bad, but I find it quite a steep learning curve to understand some of the inner works and not only make it function somehow.

But what’s the tradeoff here? Splitter may take longer for higher resolutions (more, smaller tiles). Who/what would benefit (except for heritage devices very tight on storage) or suffer either way? Plot performance? Search?

Thanks for your patience


I know only one good reason to increase the resolution in splitter: When I want to test the split algorithm with a rather small input file like maybe 20MB pbf file.
There can be a good reason to decrese the resolution when you want to split planet into e.g. 10 tiles. But that’s also a rare use case.
In short: For normal use cases there is never a reason to think about the resolution.