Add --buildpyramid, to build a full zoom pyramid for leaflet.
This commit is contained in:
parent
f84828b0bf
commit
90e7228bb9
|
@ -103,6 +103,13 @@ tilesize:
|
||||||
a multiple of 16. The filenames will be created in the form <x>_<y>_<filename>, where <x> and <y>
|
a multiple of 16. The filenames will be created in the form <x>_<y>_<filename>, where <x> and <y>
|
||||||
are the tile numbers and <filename> is the name specified with -o. Skip empty tiles by also specifying --noemptyimage.
|
are the tile numbers and <filename> is the name specified with -o. Skip empty tiles by also specifying --noemptyimage.
|
||||||
|
|
||||||
|
leaflet:
|
||||||
|
Together with --tilesize, output tiles in a leaflet-compaitble numbering and also output a html file to display the map.
|
||||||
|
Copy the files in the Leaflet subfolder to the same folder as your map.
|
||||||
|
|
||||||
|
buildpyramid:
|
||||||
|
Together with --leaflet, build a zoom pyramid for faster zooming/loading of the generated map.
|
||||||
|
|
||||||
zoom:
|
zoom:
|
||||||
Apply zoom to drawn nodes by enlarging them to n*n squares, e.g. ``--zoom 4``
|
Apply zoom to drawn nodes by enlarging them to n*n squares, e.g. ``--zoom 4``
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "TileGenerator.h"
|
#include "TileGenerator.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -81,6 +82,7 @@ TileGenerator::TileGenerator():
|
||||||
m_shading(true),
|
m_shading(true),
|
||||||
m_leaflet(false),
|
m_leaflet(false),
|
||||||
m_dontWriteEmpty(false),
|
m_dontWriteEmpty(false),
|
||||||
|
m_buildPyramid(false),
|
||||||
m_backend(""),
|
m_backend(""),
|
||||||
m_xBorder(0),
|
m_xBorder(0),
|
||||||
m_yBorder(0),
|
m_yBorder(0),
|
||||||
|
@ -185,6 +187,11 @@ void TileGenerator::setLeaflet(bool leaflet)
|
||||||
m_leaflet = leaflet;
|
m_leaflet = leaflet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileGenerator::setBuildPyramid(bool pyramid)
|
||||||
|
{
|
||||||
|
m_buildPyramid = pyramid;
|
||||||
|
}
|
||||||
|
|
||||||
void TileGenerator::setBackend(std::string backend)
|
void TileGenerator::setBackend(std::string backend)
|
||||||
{
|
{
|
||||||
m_backend = backend;
|
m_backend = backend;
|
||||||
|
@ -251,10 +258,6 @@ void TileGenerator::setDontWriteEmpty(bool f)
|
||||||
|
|
||||||
void TileGenerator::generate(const std::string &input, const std::string &output)
|
void TileGenerator::generate(const std::string &input, const std::string &output)
|
||||||
{
|
{
|
||||||
if (m_leaflet)
|
|
||||||
{
|
|
||||||
outputLeafletCode(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
string input_path = input;
|
string input_path = input;
|
||||||
if (input_path[input.length() - 1] != PATH_SEPARATOR) {
|
if (input_path[input.length() - 1] != PATH_SEPARATOR) {
|
||||||
|
@ -294,6 +297,22 @@ void TileGenerator::generate(const std::string &input, const std::string &output
|
||||||
|
|
||||||
tilePositions();
|
tilePositions();
|
||||||
|
|
||||||
|
// round xMax/zMax tot integer number of tiles
|
||||||
|
m_xMax = m_xMin + m_numTilesX * m_tileW;
|
||||||
|
m_zMax = m_zMin + m_numTilesY * m_tileH;
|
||||||
|
|
||||||
|
int maxZoomLevel = 0;
|
||||||
|
if (m_buildPyramid)
|
||||||
|
{
|
||||||
|
int maxDimX = m_xMax > -m_xMin ? m_xMax : -m_xMin;
|
||||||
|
int maxDimY = m_zMax > -m_zMin ? m_zMax : -m_zMin;
|
||||||
|
int maxDim = maxDimX > maxDimY ? maxDimX : maxDimY;
|
||||||
|
|
||||||
|
maxZoomLevel = static_cast<int>(log2(maxDim / m_tileW)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int trueXMin = m_xMin;
|
int trueXMin = m_xMin;
|
||||||
int trueZMin = m_zMin;
|
int trueZMin = m_zMin;
|
||||||
|
|
||||||
|
@ -322,8 +341,16 @@ void TileGenerator::generate(const std::string &input, const std::string &output
|
||||||
renderPlayers(input_path);
|
renderPlayers(input_path);
|
||||||
}
|
}
|
||||||
ostringstream fn;
|
ostringstream fn;
|
||||||
|
if (m_leaflet)
|
||||||
|
{
|
||||||
|
fn << maxZoomLevel << "_";
|
||||||
|
}
|
||||||
fn << x + minTileX << '_' << (flipY * (y + minTileZ)) << '_' << output;
|
fn << x + minTileX << '_' << (flipY * (y + minTileZ)) << '_' << output;
|
||||||
writeImage(fn.str());
|
writeImage(fn.str());
|
||||||
|
if (m_buildPyramid)
|
||||||
|
{
|
||||||
|
m_availableTiles.insert(Coords(x + minTileX,(flipY * (y + minTileZ))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,6 +361,15 @@ void TileGenerator::generate(const std::string &input, const std::string &output
|
||||||
m_image->fill(m_bgColor);
|
m_image->fill(m_bgColor);
|
||||||
writeImage(fn.str());
|
writeImage(fn.str());
|
||||||
}
|
}
|
||||||
|
if (m_buildPyramid)
|
||||||
|
{
|
||||||
|
buildPyramid(output, maxZoomLevel);
|
||||||
|
}
|
||||||
|
if (m_leaflet)
|
||||||
|
{
|
||||||
|
outputLeafletCode(output, maxZoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -843,12 +879,12 @@ static char const *leafletMapHtml =
|
||||||
"<script>\n"
|
"<script>\n"
|
||||||
" var MineTestMap = L.map('mapid', {\n"
|
" var MineTestMap = L.map('mapid', {\n"
|
||||||
" crs: L.CRS.Simple,\n"
|
" crs: L.CRS.Simple,\n"
|
||||||
"// minZoom: -3,\n"
|
"// minZoom: 0,\n"
|
||||||
" });\n"
|
" });\n"
|
||||||
" MineTestMap.setView([0.0, 0.0], 0);\n"
|
" MineTestMap.setView([0.0, 0.0], %d);\n"
|
||||||
" L.tileLayer('{x}_{y}_%s', {\n"
|
" L.tileLayer('{z}_{x}_{y}_%s', {\n"
|
||||||
" minNativeZoom: 0,\n"
|
" minNativeZoom: 0,\n"
|
||||||
" maxNativeZoom: 0,\n"
|
" maxNativeZoom: %d,\n"
|
||||||
" attribution: 'Minetest World',\n"
|
" attribution: 'Minetest World',\n"
|
||||||
" tileSize: %d,\n"
|
" tileSize: %d,\n"
|
||||||
" errorTileUrl: \"empty_tile_%s\",\n"
|
" errorTileUrl: \"empty_tile_%s\",\n"
|
||||||
|
@ -866,7 +902,7 @@ static char const *leafletMapHtml =
|
||||||
"</html>\n";
|
"</html>\n";
|
||||||
|
|
||||||
|
|
||||||
void TileGenerator::outputLeafletCode(std::string const &output)
|
void TileGenerator::outputLeafletCode(std::string const &output, int maxLevel)
|
||||||
{
|
{
|
||||||
if (m_tileH != m_tileW)
|
if (m_tileH != m_tileW)
|
||||||
{
|
{
|
||||||
|
@ -874,6 +910,12 @@ void TileGenerator::outputLeafletCode(std::string const &output)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_tileH == INT_MAX)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Can only use --leaflet with --tilesize!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ostringstream fn;
|
ostringstream fn;
|
||||||
fn << output << ".html";
|
fn << output << ".html";
|
||||||
|
|
||||||
|
@ -888,9 +930,73 @@ void TileGenerator::outputLeafletCode(std::string const &output)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(out, leafletMapHtml, output.c_str(), m_tileW, output.c_str());
|
fprintf(out, leafletMapHtml, maxLevel, output.c_str(), maxLevel, m_tileW*16, output.c_str());
|
||||||
|
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileGenerator::buildPyramid(std::string const &fileName, int startLevel)
|
||||||
|
{
|
||||||
|
TileSet tilesToGenerate;
|
||||||
|
int level = startLevel;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
for (TileSet::iterator t = m_availableTiles.begin(); t != m_availableTiles.end(); t++)
|
||||||
|
{
|
||||||
|
int x = t->first;
|
||||||
|
int y = t->second;
|
||||||
|
if (x >=0)
|
||||||
|
x++;
|
||||||
|
if (y >=0)
|
||||||
|
y++;
|
||||||
|
x = round_multiple_nosign(x, 2) / 2;
|
||||||
|
y = round_multiple_nosign(y, 2) / 2;
|
||||||
|
if (x > 0)
|
||||||
|
x--;
|
||||||
|
if (y > 0)
|
||||||
|
y--;
|
||||||
|
|
||||||
|
tilesToGenerate.insert(Coords(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
int halfW = m_mapWidth/2;
|
||||||
|
int halfH = m_mapHeight/2;
|
||||||
|
for (TileSet::iterator g = tilesToGenerate.begin(); g != tilesToGenerate.end(); g++)
|
||||||
|
{
|
||||||
|
m_image->fill(m_bgColor);
|
||||||
|
int x = g->first;
|
||||||
|
int y = g->second;
|
||||||
|
for (int i = 0; i < 2 ; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
if (m_availableTiles.find(Coords(2*x+i, 2*y+j)) != m_availableTiles.end())
|
||||||
|
{
|
||||||
|
std::ostringstream f;
|
||||||
|
f << level << "_" << (2*x+i) << "_" << (2*y+j) << "_" << fileName;
|
||||||
|
Image src(f.str());
|
||||||
|
src.scaleBlit(m_image, i*halfW, j*halfH, halfW, halfH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::ostringstream f;
|
||||||
|
f << (level-1) << "_" << x << "_" << y << "_" << fileName;
|
||||||
|
m_image->save(f.str());
|
||||||
|
cout << "Wrote image " << f.str() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "generated pyramid level " << (level -1) << endl;
|
||||||
|
level--;
|
||||||
|
|
||||||
|
if (!level)
|
||||||
|
{
|
||||||
|
return; // we're done
|
||||||
|
}
|
||||||
|
|
||||||
|
m_availableTiles = tilesToGenerate;
|
||||||
|
tilesToGenerate.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,13 @@ struct BitmapThing { // 16x16 bitmap
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<std::pair<int, int> > PositionsList;
|
typedef std::list<std::pair<int, int> > PositionsList;
|
||||||
|
typedef std::pair<int16_t, int16_t> Coords;
|
||||||
|
|
||||||
|
struct Coords_hash {
|
||||||
|
inline std::size_t operator()(const Coords &v) const {
|
||||||
|
return std::hash<int>()((static_cast<int>(v.first) << 16) + static_cast<int>(v.second));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class TileGenerator
|
class TileGenerator
|
||||||
{
|
{
|
||||||
|
@ -65,10 +71,12 @@ private:
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
typedef std::unordered_map<std::string, ColorEntry> ColorMap;
|
typedef std::unordered_map<std::string, ColorEntry> ColorMap;
|
||||||
typedef std::unordered_set<std::string> NameSet;
|
typedef std::unordered_set<std::string> NameSet;
|
||||||
|
typedef std::unordered_set<Coords, Coords_hash> TileSet;
|
||||||
typedef std::unordered_map<int, PositionsList> TileMap;
|
typedef std::unordered_map<int, PositionsList> TileMap;
|
||||||
#else
|
#else
|
||||||
typedef std::map<std::string, ColorEntry> ColorMap;
|
typedef std::map<std::string, ColorEntry> ColorMap;
|
||||||
typedef std::set<std::string> NameSet;
|
typedef std::set<std::string> NameSet;
|
||||||
|
typedef std::set<Coords, Coords_hash> TileSet;
|
||||||
typedef std::map<int, PositionsList> TileMap;
|
typedef std::map<int, PositionsList> TileMap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -85,6 +93,7 @@ public:
|
||||||
void setDrawAlpha(bool drawAlpha);
|
void setDrawAlpha(bool drawAlpha);
|
||||||
void setShading(bool shading);
|
void setShading(bool shading);
|
||||||
void setLeaflet(bool leaflet);
|
void setLeaflet(bool leaflet);
|
||||||
|
void setBuildPyramid(bool pyramid);
|
||||||
void setGeometry(int x, int y, int w, int h);
|
void setGeometry(int x, int y, int w, int h);
|
||||||
void setTileSize(int w, int h);
|
void setTileSize(int w, int h);
|
||||||
void setMinY(int y);
|
void setMinY(int y);
|
||||||
|
@ -119,7 +128,8 @@ private:
|
||||||
void setZoomed(int x, int y, Color color);
|
void setZoomed(int x, int y, Color color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void outputLeafletCode(std::string const &output);
|
void outputLeafletCode(std::string const &output, int maxZoomLevel);
|
||||||
|
void buildPyramid(std::string const &baseName, int startLevel);
|
||||||
Color m_bgColor;
|
Color m_bgColor;
|
||||||
Color m_scaleColor;
|
Color m_scaleColor;
|
||||||
Color m_originColor;
|
Color m_originColor;
|
||||||
|
@ -131,6 +141,7 @@ private:
|
||||||
bool m_shading;
|
bool m_shading;
|
||||||
bool m_leaflet;
|
bool m_leaflet;
|
||||||
bool m_dontWriteEmpty;
|
bool m_dontWriteEmpty;
|
||||||
|
bool m_buildPyramid;
|
||||||
|
|
||||||
std::string m_backend;
|
std::string m_backend;
|
||||||
int m_xBorder, m_yBorder;
|
int m_xBorder, m_yBorder;
|
||||||
|
@ -167,6 +178,9 @@ private:
|
||||||
|
|
||||||
int m_zoom;
|
int m_zoom;
|
||||||
uint m_scales;
|
uint m_scales;
|
||||||
|
// stuff for pyramid building
|
||||||
|
TileSet m_availableTiles;
|
||||||
|
|
||||||
}; // class TileGenerator
|
}; // class TileGenerator
|
||||||
|
|
||||||
#endif // TILEGENERATOR_HEADER
|
#endif // TILEGENERATOR_HEADER
|
||||||
|
|
|
@ -31,6 +31,7 @@ void usage()
|
||||||
" --geometry x:y+w+h\n"
|
" --geometry x:y+w+h\n"
|
||||||
" --tilesize wxh\n"
|
" --tilesize wxh\n"
|
||||||
" --leaflet\n"
|
" --leaflet\n"
|
||||||
|
" --buildpyramid\n"
|
||||||
" --extent\n"
|
" --extent\n"
|
||||||
" --zoom <zoomlevel>\n"
|
" --zoom <zoomlevel>\n"
|
||||||
" --colors <colors.txt>\n"
|
" --colors <colors.txt>\n"
|
||||||
|
@ -93,6 +94,7 @@ int main(int argc, char *argv[])
|
||||||
{"scales", required_argument, 0, 'f'},
|
{"scales", required_argument, 0, 'f'},
|
||||||
{"noemptyimage", no_argument, 0, 'n'},
|
{"noemptyimage", no_argument, 0, 'n'},
|
||||||
{"leaflet", no_argument, 0, 'l'},
|
{"leaflet", no_argument, 0, 'l'},
|
||||||
|
{"buildpyramid", no_argument, 0, 'B'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,6 +154,9 @@ int main(int argc, char *argv[])
|
||||||
case 'l':
|
case 'l':
|
||||||
generator.setLeaflet(true);
|
generator.setLeaflet(true);
|
||||||
break;
|
break;
|
||||||
|
case 'B':
|
||||||
|
generator.setBuildPyramid(true);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
generator.setBackend(optarg);
|
generator.setBackend(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -82,6 +82,16 @@ Don't output one big image, but output tiles of the specified size, e.g. "--tile
|
||||||
a multiple of 16. The filenames will be created in the form <x>_<y>_<filename>, where <x> and <y>
|
a multiple of 16. The filenames will be created in the form <x>_<y>_<filename>, where <x> and <y>
|
||||||
are the tile numbers and <filename> is the name specified with -o. Skip empty tiles by also specifying --noemptyimage.
|
are the tile numbers and <filename> is the name specified with -o. Skip empty tiles by also specifying --noemptyimage.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR \-\-leaflet " " \fIleaflet\fR
|
||||||
|
Together with --tilesize, output tiles in a leaflet-compaitble numbering and also output a html file to display the map.
|
||||||
|
Copy the files in the Leaflet subfolder to the same folder as your map.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR \-\-buildpyramid " " \fIbuildpyramid\fR
|
||||||
|
Together with --leaflet, build a zoom pyramid for faster zooming/loading of the generated map.
|
||||||
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR \-\-extent " " \fIextent\fR
|
.BR \-\-extent " " \fIextent\fR
|
||||||
Dont render the image, just print the extent of the map that would be generated, in the same format as the geometry above.
|
Dont render the image, just print the extent of the map that would be generated, in the same format as the geometry above.
|
||||||
|
|
Loading…
Reference in New Issue