Add options to specify a custom major and minor interval in the scale(s).
This commit is contained in:
parent
5ce7ff4bce
commit
a6eed3a1ed
@ -152,6 +152,10 @@ TileGenerator::TileGenerator():
|
||||
m_scaleFactor(1),
|
||||
m_sqliteCacheWorldRow(false),
|
||||
m_chunkSize(0),
|
||||
m_sideScaleMajor(0),
|
||||
m_sideScaleMinor(0),
|
||||
m_heightScaleMajor(0),
|
||||
m_heightScaleMinor(0),
|
||||
m_image(0),
|
||||
m_xMin(INT_MAX/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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
m_drawAlpha = drawAlpha;
|
||||
@ -1649,40 +1665,82 @@ void TileGenerator::renderScale()
|
||||
{
|
||||
int color = m_scaleColor.to_libgd();
|
||||
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(), 2, 24, reinterpret_cast<unsigned char *>(const_cast<char *>("Z")), color);
|
||||
gdImageString(m_image, gdFontGetMediumBold(), borderLeft() - 26, 0, reinterpret_cast<unsigned char *>(const_cast<char *>("X")), 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;
|
||||
|
||||
if ((m_drawScale & DRAWSCALE_TOP)) {
|
||||
for (int i = (m_xMin / 4) * 4; i <= m_xMax; i += 4 * m_scaleFactor) {
|
||||
stringstream buf1, buf2;
|
||||
buf1 << i * 16;
|
||||
buf2 << "(" << i << ")";
|
||||
int xPos = worldX2ImageX(i * 16);
|
||||
int start;
|
||||
int extra_left = borderLeft() ? 0 : major;
|
||||
int extra_right = borderRight() ? 0 : major;
|
||||
if (m_xMin >= 0)
|
||||
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);
|
||||
scaleText = buf2.str();
|
||||
gdImageString(m_image, gdFontGetTiny(), xPos + 2, 16, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
|
||||
if ((major % 16) == 0) {
|
||||
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);
|
||||
}
|
||||
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)) {
|
||||
for (int i = (m_zMax / 4) * 4; i >= m_zMin; i -= 4 * m_scaleFactor) {
|
||||
stringstream buf1, buf2;
|
||||
buf1 << i * 16;
|
||||
buf2 << "(" << i << ")";
|
||||
int yPos = worldZ2ImageY(i * 16);
|
||||
int start;
|
||||
int extra_top = borderTop() ? 0 : major;
|
||||
int extra_bottom = borderBottom() ? 0 : major;
|
||||
if (m_zMax >= 0)
|
||||
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);
|
||||
scaleText = buf2.str();
|
||||
gdImageString(m_image, gdFontGetTiny(), 2, yPos-10, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
|
||||
if ((major % 16) == 0) {
|
||||
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);
|
||||
}
|
||||
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 (??)
|
||||
@ -1700,11 +1758,18 @@ void TileGenerator::renderHeightScale()
|
||||
if (height_step < 1.0 / 16) {
|
||||
height_step = 1.0 / 16;
|
||||
}
|
||||
double number_step = 64;
|
||||
while (number_step / height_step < 48)
|
||||
number_step *= 2;
|
||||
while (number_step / height_step > 96)
|
||||
number_step /= 2;
|
||||
double major;
|
||||
int minor = m_heightScaleMinor;
|
||||
if (m_heightScaleMajor) {
|
||||
major = m_heightScaleMajor;
|
||||
}
|
||||
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;
|
||||
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());
|
||||
|
||||
int iheight = int(height + (height > 0 ? 0.5 : -0.5));
|
||||
int iheight64 = int(iheight / number_step + (height > 0 ? 0.5 : -0.5)) * number_step;
|
||||
if (fabs(height - iheight64) <= height_step / 2 && (height - iheight64) > -height_step / 2) {
|
||||
if (iheight64 / int(number_step) % 2 == 1 && fabs(height) > 9999 && number_step / height_step < 56) {
|
||||
int iheightMaj = int(iheight / major + (height > 0 ? 0.5 : -0.5)) * major;
|
||||
if (fabs(height - iheightMaj) <= height_step / 2 && (height - iheightMaj) > -height_step / 2) {
|
||||
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
|
||||
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 16, scaleColor);
|
||||
}
|
||||
else {
|
||||
stringstream buf;
|
||||
buf << iheight64;
|
||||
buf << iheightMaj;
|
||||
string scaleText = buf.str();
|
||||
gdImageString(m_image, gdFontGetMediumBold(), xBorderOffset + x + 2, yBorderOffset + borderBottom() - 16,
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,8 @@ public:
|
||||
void setDrawPlayers(bool drawPlayers);
|
||||
void setDrawScale(int scale);
|
||||
void setDrawHeightScale(int scale);
|
||||
void setSideScaleInterval(int major, int minor);
|
||||
void setHeightScaleInterval(int major, int minor);
|
||||
void setDrawAlpha(bool drawAlpha);
|
||||
void setDrawAir(bool drawAir);
|
||||
void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); }
|
||||
@ -235,6 +237,10 @@ private:
|
||||
int m_scaleFactor;
|
||||
bool m_sqliteCacheWorldRow;
|
||||
int m_chunkSize;
|
||||
int m_sideScaleMajor;
|
||||
int m_sideScaleMinor;
|
||||
int m_heightScaleMajor;
|
||||
int m_heightScaleMinor;
|
||||
|
||||
DB *m_db;
|
||||
gdImagePtr m_image;
|
||||
|
59
mapper.cpp
59
mapper.cpp
@ -38,6 +38,7 @@ using namespace std;
|
||||
#define OPT_HEIGHTMAPCOLORSFILE 0x8c
|
||||
#define OPT_DRAWHEIGHTSCALE 0x8d
|
||||
#define OPT_SCALEFACTOR 0x8e
|
||||
#define OPT_SCALEINTERVAL 0x8f
|
||||
|
||||
// Will be replaced with the actual name and location of the executable (if found)
|
||||
string executableName = "minetestmapper";
|
||||
@ -87,7 +88,9 @@ void usage()
|
||||
" --origincolor <color>\n"
|
||||
" --tilebordercolor <color>\n"
|
||||
" --drawscale[=left,top]\n"
|
||||
" --sidescale-interval <major>[[,:]<minor>]\n"
|
||||
" --drawheightscale\n"
|
||||
" --heightscale-interval <major>[[,:]<minor>]\n"
|
||||
" --drawplayers\n"
|
||||
" --draworigin\n"
|
||||
" --drawalpha[=cumulative|cumulative-darken|average|none]\n"
|
||||
@ -555,7 +558,9 @@ int main(int argc, char *argv[])
|
||||
{"draworigin", no_argument, 0, 'R'},
|
||||
{"drawplayers", no_argument, 0, 'P'},
|
||||
{"drawscale", optional_argument, 0, 'S'},
|
||||
{"sidescale-interval", required_argument, 0, OPT_SCALEINTERVAL},
|
||||
{"drawheightscale", no_argument, 0, OPT_DRAWHEIGHTSCALE},
|
||||
{"heightscale-interval", required_argument, 0, OPT_SCALEINTERVAL},
|
||||
{"drawalpha", optional_argument, 0, 'e'},
|
||||
{"drawair", no_argument, 0, OPT_DRAWAIR},
|
||||
{"drawpoint", required_argument, 0, OPT_DRAW_OBJECT},
|
||||
@ -733,6 +738,60 @@ int main(int argc, char *argv[])
|
||||
case OPT_DRAWHEIGHTSCALE :
|
||||
generator.setDrawHeightScale(DRAWHEIGHTSCALE_BOTTOM);
|
||||
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':
|
||||
if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') {
|
||||
if (optarg[0] == '0')
|
||||
|
Loading…
x
Reference in New Issue
Block a user