Add options to specify a custom major and minor interval in the scale(s).

This commit is contained in:
Rogier 2015-02-14 21:25:40 +01:00
parent 5ce7ff4bce
commit a6eed3a1ed
3 changed files with 163 additions and 27 deletions

View File

@ -152,6 +152,10 @@ TileGenerator::TileGenerator():
m_scaleFactor(1), m_scaleFactor(1),
m_sqliteCacheWorldRow(false), m_sqliteCacheWorldRow(false),
m_chunkSize(0), m_chunkSize(0),
m_sideScaleMajor(0),
m_sideScaleMinor(0),
m_heightScaleMajor(0),
m_heightScaleMinor(0),
m_image(0), m_image(0),
m_xMin(INT_MAX/16-1), m_xMin(INT_MAX/16-1),
m_xMax(INT_MIN/16+1), m_xMax(INT_MIN/16+1),
@ -319,6 +323,18 @@ void TileGenerator::setDrawHeightScale(int scale)
m_drawScale = (scale & DRAWHEIGHTSCALE_MASK) | (m_drawScale & DRAWSCALE_MASK & ((~scale & DRAWHEIGHTSCALE_MASK) >> 4)); m_drawScale = (scale & DRAWHEIGHTSCALE_MASK) | (m_drawScale & DRAWSCALE_MASK & ((~scale & DRAWHEIGHTSCALE_MASK) >> 4));
} }
void TileGenerator::setSideScaleInterval(int major, int minor)
{
m_sideScaleMajor = major;
m_sideScaleMinor = minor;
}
void TileGenerator::setHeightScaleInterval(int major, int minor)
{
m_heightScaleMajor = major;
m_heightScaleMinor = minor;
}
void TileGenerator::setDrawAlpha(bool drawAlpha) void TileGenerator::setDrawAlpha(bool drawAlpha)
{ {
m_drawAlpha = drawAlpha; m_drawAlpha = drawAlpha;
@ -1649,40 +1665,82 @@ void TileGenerator::renderScale()
{ {
int color = m_scaleColor.to_libgd(); int color = m_scaleColor.to_libgd();
if ((m_drawScale & DRAWSCALE_LEFT) && (m_drawScale & DRAWSCALE_TOP)) { if ((m_drawScale & DRAWSCALE_LEFT) && (m_drawScale & DRAWSCALE_TOP)) {
gdImageString(m_image, gdFontGetMediumBold(), 24, 0, reinterpret_cast<unsigned char *>(const_cast<char *>("X")), color); gdImageString(m_image, gdFontGetMediumBold(), borderLeft() - 26, 0, reinterpret_cast<unsigned char *>(const_cast<char *>("X")), color);
gdImageString(m_image, gdFontGetMediumBold(), 2, 24, reinterpret_cast<unsigned char *>(const_cast<char *>("Z")), color); gdImageString(m_image, gdFontGetMediumBold(), 2, borderTop() - 26, reinterpret_cast<unsigned char *>(const_cast<char *>("Z")), color);
} }
int major = m_sideScaleMajor ? m_sideScaleMajor : 4 * 16 * m_scaleFactor;
int minor = m_sideScaleMinor;
string scaleText; string scaleText;
if ((m_drawScale & DRAWSCALE_TOP)) { if ((m_drawScale & DRAWSCALE_TOP)) {
for (int i = (m_xMin / 4) * 4; i <= m_xMax; i += 4 * m_scaleFactor) { int start;
stringstream buf1, buf2; int extra_left = borderLeft() ? 0 : major;
buf1 << i * 16; int extra_right = borderRight() ? 0 : major;
buf2 << "(" << i << ")"; if (m_xMin >= 0)
int xPos = worldX2ImageX(i * 16); start = (m_xMin * 16 + m_mapXStartNodeOffset - 1 + major - 1 - extra_left) / major * major;
else
start = (m_xMin * 16 + m_mapXStartNodeOffset - 1 - extra_left) / major * major;
for (int i = start; i <= (m_xMax + 1) * 16 + m_mapXEndNodeOffset + extra_right; i += major) {
stringstream buf;
buf << i;
int xPos = worldX2ImageX(i);
scaleText = buf1.str(); scaleText = buf.str();
gdImageString(m_image, gdFontGetMediumBold(), xPos + 2, 0, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color); gdImageString(m_image, gdFontGetMediumBold(), xPos + 2, 0, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
scaleText = buf2.str(); if ((major % 16) == 0) {
gdImageString(m_image, gdFontGetTiny(), xPos + 2, 16, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color); buf.str("");
buf << "(" << i / 16 << ")";
scaleText = buf.str();
gdImageString(m_image, gdFontGetTiny(), xPos + 2, 16, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
}
gdImageLine(m_image, xPos, 0, xPos, borderTop() - 1, color); gdImageLine(m_image, xPos, 0, xPos, borderTop() - 1, color);
} }
if (minor) {
if (m_xMin >= 0)
start = (m_xMin * 16 + m_mapXStartNodeOffset + minor - 2) / minor * minor;
else
start = (m_xMin * 16 + m_mapXStartNodeOffset - 1) / minor * minor;
for (int i = start; i <= (m_xMax + 1) * 16 + m_mapXEndNodeOffset; i += minor) {
int xPos = worldX2ImageX(i);
gdImageLine(m_image, xPos, borderTop() - 5, xPos, borderTop() - 1, color);
}
}
} }
if ((m_drawScale & DRAWSCALE_LEFT)) { if ((m_drawScale & DRAWSCALE_LEFT)) {
for (int i = (m_zMax / 4) * 4; i >= m_zMin; i -= 4 * m_scaleFactor) { int start;
stringstream buf1, buf2; int extra_top = borderTop() ? 0 : major;
buf1 << i * 16; int extra_bottom = borderBottom() ? 0 : major;
buf2 << "(" << i << ")"; if (m_zMax >= 0)
int yPos = worldZ2ImageY(i * 16); start = ((m_zMax + 1) * 16 - m_mapYStartNodeOffset + extra_top) / major * major;
else
start = ((m_zMax + 1) * 16 - m_mapYStartNodeOffset - major + 1 + extra_top) / major * major;
for (int i = start; i >= m_zMin * 16 - m_mapYEndNodeOffset - 1 - extra_bottom; i -= major) {
stringstream buf;
buf << i;
int yPos = worldZ2ImageY(i);
scaleText = buf1.str(); scaleText = buf.str();
gdImageString(m_image, gdFontGetMediumBold(), 2, yPos, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color); gdImageString(m_image, gdFontGetMediumBold(), 2, yPos, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
scaleText = buf2.str(); if ((major % 16) == 0) {
gdImageString(m_image, gdFontGetTiny(), 2, yPos-10, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color); buf.str("");
buf << "(" << i / 16 << ")";
scaleText = buf.str();
gdImageString(m_image, gdFontGetTiny(), 2, yPos-10, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
}
gdImageLine(m_image, 0, yPos, borderLeft() - 1, yPos, color); gdImageLine(m_image, 0, yPos, borderLeft() - 1, yPos, color);
} }
if (minor) {
if (m_zMax >= 0)
start = ((m_zMax + 1) * 16 - m_mapYStartNodeOffset) / minor * minor;
else
start = ((m_zMax + 1) * 16 - m_mapYStartNodeOffset - minor + 1) / minor * minor;
for (int i = start; i >= m_zMin * 16 - m_mapYEndNodeOffset - 1; i -= minor) {
int yPos = worldZ2ImageY(i);
gdImageLine(m_image, borderLeft() - 5, yPos, borderLeft() - 1, yPos, color);
}
}
} }
// DRAWSCALE_RIGHT and DRAWSCALE_BOTTOM not implemented - getting the text positioned right seems not trivial (??) // DRAWSCALE_RIGHT and DRAWSCALE_BOTTOM not implemented - getting the text positioned right seems not trivial (??)
@ -1700,11 +1758,18 @@ void TileGenerator::renderHeightScale()
if (height_step < 1.0 / 16) { if (height_step < 1.0 / 16) {
height_step = 1.0 / 16; height_step = 1.0 / 16;
} }
double number_step = 64; double major;
while (number_step / height_step < 48) int minor = m_heightScaleMinor;
number_step *= 2; if (m_heightScaleMajor) {
while (number_step / height_step > 96) major = m_heightScaleMajor;
number_step /= 2; }
else {
major = 64;
while (major / height_step / 64 < 0.75)
major *= 2;
while (major / height_step / 64 > 1.5)
major /= 2;
}
double height = height_min; double height = height_min;
for (int x = 0; height < height_limit; x++, height += height_step) { for (int x = 0; height < height_limit; x++, height += height_step) {
@ -1712,21 +1777,27 @@ void TileGenerator::renderHeightScale()
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + 8, xBorderOffset + x, yBorderOffset + borderBottom() - 20, color.to_libgd()); gdImageLine(m_image, xBorderOffset + x, yBorderOffset + 8, xBorderOffset + x, yBorderOffset + borderBottom() - 20, color.to_libgd());
int iheight = int(height + (height > 0 ? 0.5 : -0.5)); int iheight = int(height + (height > 0 ? 0.5 : -0.5));
int iheight64 = int(iheight / number_step + (height > 0 ? 0.5 : -0.5)) * number_step; int iheightMaj = int(iheight / major + (height > 0 ? 0.5 : -0.5)) * major;
if (fabs(height - iheight64) <= height_step / 2 && (height - iheight64) > -height_step / 2) { if (fabs(height - iheightMaj) <= height_step / 2 && (height - iheightMaj) > -height_step / 2) {
if (iheight64 / int(number_step) % 2 == 1 && fabs(height) > 9999 && number_step / height_step < 56) { if (iheightMaj / int(major) % 2 == 1 && fabs(height) > 9999 && major / height_step < 56) {
// Maybe not enough room for the number. Draw a tick mark instead // Maybe not enough room for the number. Draw a tick mark instead
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 16, scaleColor); gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 16, scaleColor);
} }
else { else {
stringstream buf; stringstream buf;
buf << iheight64; buf << iheightMaj;
string scaleText = buf.str(); string scaleText = buf.str();
gdImageString(m_image, gdFontGetMediumBold(), xBorderOffset + x + 2, yBorderOffset + borderBottom() - 16, gdImageString(m_image, gdFontGetMediumBold(), xBorderOffset + x + 2, yBorderOffset + borderBottom() - 16,
reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), scaleColor); reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), scaleColor);
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 1, scaleColor); gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 1, scaleColor);
} }
} }
if (minor) {
int iheightMin = int(iheight / minor + (height > 0 ? 0.5 : -0.5)) * minor;
if (fabs(height - iheightMin) <= height_step / 2 && (height - iheightMin) > -height_step / 2) {
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 16, scaleColor);
}
}
} }
} }

View File

@ -123,6 +123,8 @@ public:
void setDrawPlayers(bool drawPlayers); void setDrawPlayers(bool drawPlayers);
void setDrawScale(int scale); void setDrawScale(int scale);
void setDrawHeightScale(int scale); void setDrawHeightScale(int scale);
void setSideScaleInterval(int major, int minor);
void setHeightScaleInterval(int major, int minor);
void setDrawAlpha(bool drawAlpha); void setDrawAlpha(bool drawAlpha);
void setDrawAir(bool drawAir); void setDrawAir(bool drawAir);
void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); } void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); }
@ -235,6 +237,10 @@ private:
int m_scaleFactor; int m_scaleFactor;
bool m_sqliteCacheWorldRow; bool m_sqliteCacheWorldRow;
int m_chunkSize; int m_chunkSize;
int m_sideScaleMajor;
int m_sideScaleMinor;
int m_heightScaleMajor;
int m_heightScaleMinor;
DB *m_db; DB *m_db;
gdImagePtr m_image; gdImagePtr m_image;

View File

@ -38,6 +38,7 @@ using namespace std;
#define OPT_HEIGHTMAPCOLORSFILE 0x8c #define OPT_HEIGHTMAPCOLORSFILE 0x8c
#define OPT_DRAWHEIGHTSCALE 0x8d #define OPT_DRAWHEIGHTSCALE 0x8d
#define OPT_SCALEFACTOR 0x8e #define OPT_SCALEFACTOR 0x8e
#define OPT_SCALEINTERVAL 0x8f
// Will be replaced with the actual name and location of the executable (if found) // Will be replaced with the actual name and location of the executable (if found)
string executableName = "minetestmapper"; string executableName = "minetestmapper";
@ -87,7 +88,9 @@ void usage()
" --origincolor <color>\n" " --origincolor <color>\n"
" --tilebordercolor <color>\n" " --tilebordercolor <color>\n"
" --drawscale[=left,top]\n" " --drawscale[=left,top]\n"
" --sidescale-interval <major>[[,:]<minor>]\n"
" --drawheightscale\n" " --drawheightscale\n"
" --heightscale-interval <major>[[,:]<minor>]\n"
" --drawplayers\n" " --drawplayers\n"
" --draworigin\n" " --draworigin\n"
" --drawalpha[=cumulative|cumulative-darken|average|none]\n" " --drawalpha[=cumulative|cumulative-darken|average|none]\n"
@ -555,7 +558,9 @@ int main(int argc, char *argv[])
{"draworigin", no_argument, 0, 'R'}, {"draworigin", no_argument, 0, 'R'},
{"drawplayers", no_argument, 0, 'P'}, {"drawplayers", no_argument, 0, 'P'},
{"drawscale", optional_argument, 0, 'S'}, {"drawscale", optional_argument, 0, 'S'},
{"sidescale-interval", required_argument, 0, OPT_SCALEINTERVAL},
{"drawheightscale", no_argument, 0, OPT_DRAWHEIGHTSCALE}, {"drawheightscale", no_argument, 0, OPT_DRAWHEIGHTSCALE},
{"heightscale-interval", required_argument, 0, OPT_SCALEINTERVAL},
{"drawalpha", optional_argument, 0, 'e'}, {"drawalpha", optional_argument, 0, 'e'},
{"drawair", no_argument, 0, OPT_DRAWAIR}, {"drawair", no_argument, 0, OPT_DRAWAIR},
{"drawpoint", required_argument, 0, OPT_DRAW_OBJECT}, {"drawpoint", required_argument, 0, OPT_DRAW_OBJECT},
@ -733,6 +738,60 @@ int main(int argc, char *argv[])
case OPT_DRAWHEIGHTSCALE : case OPT_DRAWHEIGHTSCALE :
generator.setDrawHeightScale(DRAWHEIGHTSCALE_BOTTOM); generator.setDrawHeightScale(DRAWHEIGHTSCALE_BOTTOM);
break; break;
case OPT_SCALEINTERVAL: {
istringstream arg;
arg.str(optarg);
int major;
int minor;
char sep;
arg >> major;
if (major < 0 || !isdigit(*optarg) || arg.fail()) {
std::cerr << "Invalid parameter to '" << long_options[option_index].name
<< "': '" << optarg << "' (expected: <major>[,<minor>]" << std::endl;
usage();
exit(1);
}
arg >> std::ws >> sep >> std::ws;
if (!arg.fail()) {
if ((sep != ',' && sep != ':') || !isdigit(arg.peek())) {
std::cerr << "Invalid parameter to '" << long_options[option_index].name
<< "': '" << optarg << "' (expected: <major>[,<minor>]" << std::endl;
usage();
exit(1);
}
arg >> minor;
if (minor < 0) {
std::cerr << "Invalid parameter to '" << long_options[option_index].name
<< "': '" << optarg << "' (expected: <major>[,<minor>]" << std::endl;
usage();
exit(1);
}
}
else {
minor = 0;
}
if (minor && sep == ':') {
if (major % minor) {
std::cerr << long_options[option_index].name << ": Cannot divide major interval in "
<< minor << " subintervals (not divisible)" << std::endl;
exit(1);
}
minor = major / minor;
}
if ((minor % major) == 0)
minor = 0;
if (long_options[option_index].name[0] == 's') {
generator.setSideScaleInterval(major, minor);
}
else if (long_options[option_index].name[0] == 'h') {
generator.setHeightScaleInterval(major, minor);
}
else {
std::cerr << "Internal error: option " << long_options[option_index].name << " not handled" << std::endl;
exit(1);
}
}
break;
case 'v': case 'v':
if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') { if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') {
if (optarg[0] == '0') if (optarg[0] == '0')