Implement printing POIs

closes #98
This commit is contained in:
Klaus Ethgen 2023-04-24 21:45:09 +01:00
parent 7af222dd9d
commit 1d2a7aaba3
8 changed files with 160 additions and 1 deletions

View File

@ -175,6 +175,7 @@ add_executable(minetestmapper
BlockDecoder.cpp
PixelAttributes.cpp
PlayerAttributes.cpp
POIAttributes.cpp
TileGenerator.cpp
ZlibDecompressor.cpp
ZstdDecompressor.cpp

View File

@ -87,7 +87,8 @@ void Image::drawLine(int x1, int y1, int x2, int y2, const Color &c)
void Image::drawText(int x, int y, const std::string &s, const Color &c)
{
SIZECHECK(x, y);
gdImageString(m_image, gdFontGetMediumBold(), x, y, (unsigned char*) s.c_str(), color2int(c));
int brect[8];
gdImageStringFT(m_image, &brect[0], color2int(c), "dejavu/DejaVuSans-Bold;freefont/FreeSansBold;msttcorefonts/Arial", 13., 0., x, y, s.c_str());
}
void Image::drawFilledRect(int x, int y, int w, int h, const Color &c)

87
POIAttributes.cpp Normal file
View File

@ -0,0 +1,87 @@
#include <cstdio>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <dirent.h>
#include <unistd.h> // for usleep
#include <sqlite3.h>
#include "config.h"
#include "POIAttributes.h"
#include "util.h"
POIAttributes::POIAttributes(const std::string &worldDir)
{
std::ifstream ifs(worldDir + "world.mt");
if (!ifs.good())
throw std::runtime_error("Failed to read world.mt");
std::string backend = read_setting_default("mod_storage_backend", ifs, "sqlite3");
ifs.close();
if (backend == "sqlite3")
readSqlite(worldDir + "mod_storage.sqlite");
else
throw std::runtime_error(std::string("Unknown poi backend: ") + backend);
}
/**********/
#define SQLRES(f, good) \
result = (sqlite3_##f); \
if (result != good) { \
throw std::runtime_error(sqlite3_errmsg(db));\
}
#define SQLOK(f) SQLRES(f, SQLITE_OK)
void POIAttributes::readSqlite(const std::string &db_name)
{
int result;
sqlite3 *db;
sqlite3_stmt *stmt_get_poi_pos;
SQLOK(open_v2(db_name.c_str(), &db, SQLITE_OPEN_READONLY |
SQLITE_OPEN_PRIVATECACHE, 0))
SQLOK(prepare_v2(db,
"SELECT key, value FROM entries WHERE modname = 'poi'",
-1, &stmt_get_poi_pos, NULL))
while ((result = sqlite3_step(stmt_get_poi_pos)) != SQLITE_DONE) {
if (result == SQLITE_BUSY) { // Wait some time and try again
usleep(10000);
} else if (result != SQLITE_ROW) {
throw std::runtime_error(sqlite3_errmsg(db));
}
POI poi;
const unsigned char *name_ = sqlite3_column_text(stmt_get_poi_pos, 0);
poi.name = reinterpret_cast<const char*>(name_);
const char *pos_ = reinterpret_cast<const char*>(sqlite3_column_text(stmt_get_poi_pos, 1));
float x, y, z;
int items = sscanf(pos_, "(%f,%f,%f)", &x, &y, &z);
if (items != 3) {
std::cerr << "Failed to parse POI position '" << pos_ << "'" << std::endl;
return;
}
poi.x = x;
poi.y = y;
poi.z = z;
m_pois.push_back(poi);
}
sqlite3_finalize(stmt_get_poi_pos);
sqlite3_close(db);
}
/**********/
POIAttributes::POIs::const_iterator POIAttributes::begin() const
{
return m_pois.cbegin();
}
POIAttributes::POIs::const_iterator POIAttributes::end() const
{
return m_pois.cend();
}

View File

@ -14,6 +14,7 @@
#include "TileGenerator.h"
#include "config.h"
#include "PlayerAttributes.h"
#include "POIAttributes.h"
#include "BlockDecoder.h"
#include "Image.h"
#include "util.h"
@ -118,6 +119,7 @@ TileGenerator::TileGenerator():
m_scaleColor(0, 0, 0),
m_originColor(255, 0, 0),
m_playerColor(255, 0, 0),
m_poiColor(0, 128, 255),
m_drawOrigin(false),
m_drawPlayers(false),
m_drawScale(false),
@ -195,6 +197,11 @@ void TileGenerator::setDrawPlayers(bool drawPlayers)
m_drawPlayers = drawPlayers;
}
void TileGenerator::setDrawPOIs(bool drawPOIs)
{
m_drawPOIs = drawPOIs;
}
void TileGenerator::setDrawScale(bool drawScale)
{
m_drawScale = drawScale;
@ -314,6 +321,9 @@ void TileGenerator::generate(const std::string &input_path, const std::string &o
if (m_drawPlayers) {
renderPlayers(input_path);
}
if (m_drawPOIs) {
renderPOIs(input_path);
}
writeImage(output);
printUnknown();
}
@ -848,6 +858,27 @@ void TileGenerator::renderPlayers(const std::string &input_path)
}
}
void TileGenerator::renderPOIs(const std::string &input_path)
{
std::string input = input_path;
if (input.back() != PATH_SEPARATOR)
input += PATH_SEPARATOR;
POIAttributes pois(input);
for (auto &poi : pois) {
if (poi.x < m_xMin * 16 || poi.x > m_xMax * 16 ||
poi.z < m_zMin * 16 || poi.z > m_zMax * 16)
continue;
if (poi.y < m_yMin || poi.y > m_yMax)
continue;
int imageX = getImageX(poi.x, true),
imageY = getImageY(poi.z, true);
m_image->drawCircle(imageX, imageY, 9, m_poiColor);
m_image->drawText(imageX + 7, imageY, poi.name, m_poiColor);
}
}
void TileGenerator::writeImage(const std::string &output)
{
m_image->save(output);

26
include/POIAttributes.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <list>
#include <string>
struct POI
{
std::string name;
float x, y, z;
};
class POIAttributes
{
public:
typedef std::list<POI> POIs;
POIAttributes(const std::string &worldDir);
POIs::const_iterator begin() const;
POIs::const_iterator end() const;
private:
void readFiles(const std::string &poisPath);
void readSqlite(const std::string &db_name);
POIs m_pois;
};

View File

@ -79,6 +79,7 @@ public:
void setDrawPlayers(bool drawPlayers);
void setDrawScale(bool drawScale);
void setDrawAlpha(bool drawAlpha);
void setDrawPOIs(bool drawPOIs);
void setShading(bool shading);
void setGeometry(int x, int y, int w, int h);
void setMinY(int y);
@ -109,6 +110,7 @@ private:
void renderScale();
void renderOrigin();
void renderPlayers(const std::string &inputPath);
void renderPOIs(const std::string &inputPath);
void writeImage(const std::string &output);
void printUnknown();
void reportProgress(size_t count);
@ -121,10 +123,12 @@ private:
Color m_scaleColor;
Color m_originColor;
Color m_playerColor;
Color m_poiColor;
bool m_drawOrigin;
bool m_drawPlayers;
bool m_drawScale;
bool m_drawAlpha;
bool m_drawPOIs;
bool m_shading;
bool m_dontWriteEmpty;
std::string m_backend;

View File

@ -24,6 +24,7 @@ static void usage()
{"--drawplayers", ""},
{"--draworigin", ""},
{"--drawalpha", ""},
{"--drawpois", ""},
{"--noshading", ""},
{"--noemptyimage", ""},
{"--min-y", "<y>"},
@ -108,6 +109,7 @@ int main(int argc, char *argv[])
{"drawplayers", no_argument, 0, 'P'},
{"drawscale", no_argument, 0, 'S'},
{"drawalpha", no_argument, 0, 'e'},
{"drawpois", no_argument, 0, 'I'},
{"noshading", no_argument, 0, 'H'},
{"backend", required_argument, 0, 'd'},
{"geometry", required_argument, 0, 'g'},
@ -170,6 +172,9 @@ int main(int argc, char *argv[])
case 'e':
generator.setDrawAlpha(true);
break;
case 'I':
generator.setDrawPOIs(true);
break;
case 'E':
onlyPrintExtent = true;
break;

View File

@ -52,6 +52,10 @@ Draw origin indicator
.BR \-\-drawalpha
Allow nodes to be drawn with transparency
.TP
.BR \-\-drawpois
Draw POIs
.TP
.BR \-\-noshading
Don't draw shading on nodes