Implement an iterator for BlockPos
This commit is contained in:
parent
a3f01d5a1e
commit
46c070070a
134
BlockPos.cpp
Normal file
134
BlockPos.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
#include <BlockPos.h>
|
||||||
|
|
||||||
|
void BlockPos::operator=(const std::string &s)
|
||||||
|
{
|
||||||
|
m_id = INT64_MIN;
|
||||||
|
std::istringstream is(s);
|
||||||
|
if (isdigit(is.peek()) || is.peek() == '-' || is.peek() == '+') {
|
||||||
|
int64_t ipos;
|
||||||
|
is >> ipos;
|
||||||
|
if (is.bad() || !is.eof()) {
|
||||||
|
throw std::runtime_error(std::string("Failed to decode i64 (minetest) coordinate string from database (") + s + ")" );
|
||||||
|
}
|
||||||
|
operator=(ipos);
|
||||||
|
m_strFormat = I64;
|
||||||
|
}
|
||||||
|
else if (is.peek() == 'a') {
|
||||||
|
// Freeminer new format (a<x>,<y>,<z>)
|
||||||
|
char c1, c2;
|
||||||
|
is >> c1;
|
||||||
|
is >> x();
|
||||||
|
is >> c1;
|
||||||
|
is >> y();
|
||||||
|
is >> c2;
|
||||||
|
is >> z();
|
||||||
|
if (is.bad() || !is.eof() || c1 != ',' || c2 != ',') {
|
||||||
|
throw std::runtime_error(std::string("Failed to decode axyz (freeminer) coordinate string from database (") + s + ")" );
|
||||||
|
}
|
||||||
|
m_strFormat = AXYZ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error(std::string("Failed to detect format of coordinate string from database (") + s + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BlockPos::databasePosStrFmt(StrFormat format) const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
switch(format) {
|
||||||
|
case Unknown:
|
||||||
|
throw std::runtime_error(std::string("Internal error: Converting BlockPos to unknown string type"));
|
||||||
|
break;
|
||||||
|
case I64:
|
||||||
|
os << databasePosI64();
|
||||||
|
break;
|
||||||
|
case XYZ:
|
||||||
|
os << x() << ',' << y() << ',' << z();
|
||||||
|
break;
|
||||||
|
case AXYZ:
|
||||||
|
os << 'a' << x() << ',' << y() << ',' << z();
|
||||||
|
break;
|
||||||
|
case STRFORMAT_MAX:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockPosIterator::printState(const char *message, FILE *file)
|
||||||
|
{
|
||||||
|
fprintf(file, "[%s] Value: %d,%d,%d; Range: %d,%d,%d .. %d,%d,%d; State: %d\n",
|
||||||
|
message,
|
||||||
|
m_value.x(), m_value.y(), m_value.z(),
|
||||||
|
m_start.x(), m_start.y(), m_start.z(),
|
||||||
|
m_end.x(), m_end.y(), m_end.z(),
|
||||||
|
m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockPosIterator::breakDim(int i, int step)
|
||||||
|
{
|
||||||
|
if (!step) return;
|
||||||
|
if (i == 0) {
|
||||||
|
m_value.dimension[1] = step < 0 ? m_start.dimension[1] : m_end.dimension[1];
|
||||||
|
m_value.dimension[0] = step < 0 ? m_start.dimension[0] : m_end.dimension[0];
|
||||||
|
}
|
||||||
|
else if (i == 1) {
|
||||||
|
m_value.dimension[1] = step < 0 ? m_start.dimension[1] : m_end.dimension[1];
|
||||||
|
}
|
||||||
|
else if (i == 2) {
|
||||||
|
m_value.dimension[1] = step < 0 ? m_start.dimension[1] : m_end.dimension[1];
|
||||||
|
m_value.dimension[0] = step < 0 ? m_start.dimension[0] : m_end.dimension[0];
|
||||||
|
m_value.dimension[2] = step < 2 ? m_start.dimension[2] : m_end.dimension[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockPosIterator::stepForward(void)
|
||||||
|
{
|
||||||
|
switch (m_state) {
|
||||||
|
case Start:
|
||||||
|
m_state = Middle;
|
||||||
|
m_value = m_start;
|
||||||
|
break;
|
||||||
|
case End:
|
||||||
|
break;
|
||||||
|
case Middle:
|
||||||
|
stepDim(1, 1)
|
||||||
|
|| stepDim(0, 1)
|
||||||
|
|| stepDim(2, 1)
|
||||||
|
|| (m_state = End);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Internal error: BlockPosIterator: unexpected state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BlockPosIterator::stepReverse(void)
|
||||||
|
{
|
||||||
|
switch (m_state) {
|
||||||
|
case Start:
|
||||||
|
break;
|
||||||
|
case End:
|
||||||
|
m_state = Middle;
|
||||||
|
m_value = m_end;
|
||||||
|
break;
|
||||||
|
case Middle:
|
||||||
|
stepDim(1, -1)
|
||||||
|
|| stepDim(0, -1)
|
||||||
|
|| stepDim(2, -1)
|
||||||
|
|| (m_state = Start);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Internal error: BlockPosIterator: unexpected state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t NodeCoord::hash(void) const
|
||||||
|
{
|
||||||
|
size_t hash = 0xd3adb33f;
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
// Nothing too fancy...
|
||||||
|
hash = ((hash << 8) | (hash >> 24)) ^ (dimension[i] ^ (isBlock[i] ? 0x50000000 : 0));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
142
BlockPos.h
142
BlockPos.h
@ -10,6 +10,9 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
class BlockPosIterator;
|
||||||
|
|
||||||
struct BlockPos {
|
struct BlockPos {
|
||||||
// m_strFormat is used to record the original format that was obtained
|
// m_strFormat is used to record the original format that was obtained
|
||||||
@ -21,6 +24,7 @@ struct BlockPos {
|
|||||||
I64, // Minetest & Freeminer
|
I64, // Minetest & Freeminer
|
||||||
XYZ,
|
XYZ,
|
||||||
AXYZ, // Freeminer
|
AXYZ, // Freeminer
|
||||||
|
STRFORMAT_MAX
|
||||||
};
|
};
|
||||||
int dimension[3];
|
int dimension[3];
|
||||||
int &x(void) { return dimension[0]; }
|
int &x(void) { return dimension[0]; }
|
||||||
@ -35,12 +39,13 @@ struct BlockPos {
|
|||||||
// std::size_t hash(void) const { return databasePosI64() % SIZE_MAX; }
|
// std::size_t hash(void) const { return databasePosI64() % SIZE_MAX; }
|
||||||
//#endif
|
//#endif
|
||||||
BlockPos() : dimension{0, 0, 0}, m_strFormat(Unknown), m_id(INT64_MIN) {}
|
BlockPos() : dimension{0, 0, 0}, m_strFormat(Unknown), m_id(INT64_MIN) {}
|
||||||
BlockPos(int _x, int _y, int _z) : dimension{_x, _y, _z}, m_strFormat(Unknown), m_id(INT64_MIN) {}
|
BlockPos(int _x, int _y, int _z, StrFormat format = Unknown) : dimension{_x, _y, _z}, m_strFormat(format), m_id(INT64_MIN) {}
|
||||||
BlockPos(int _x, int _y, int _z, int64_t id) : dimension{_x, _y, _z}, m_strFormat(Unknown), m_id(id) {}
|
BlockPos(int _x, int _y, int _z, int64_t id) : dimension{_x, _y, _z}, m_strFormat(Unknown), m_id(id) {}
|
||||||
BlockPos(const BlockPos &pos) : dimension{pos.x(), pos.y(), pos.z()}, m_strFormat(pos.m_strFormat), m_id(pos.m_id) {}
|
BlockPos(const BlockPos &pos) : dimension{pos.x(), pos.y(), pos.z()}, m_strFormat(pos.m_strFormat), m_id(pos.m_id) {}
|
||||||
BlockPos(int64_t i) { operator=(i); }
|
BlockPos(int64_t i) { operator=(i); }
|
||||||
BlockPos(int64_t i, int64_t id) { operator=(i); m_id = id; }
|
BlockPos(int64_t i, int64_t id) { operator=(i); m_id = id; }
|
||||||
BlockPos(const std::string &s) { operator=(s); }
|
BlockPos(const std::string &s) { operator=(s); }
|
||||||
|
StrFormat databaseFormat(void) const { return m_strFormat; }
|
||||||
int64_t databasePosI64(void) const { return getDBPos(); }
|
int64_t databasePosI64(void) const { return getDBPos(); }
|
||||||
int64_t databasePosId(void) const { return m_id; }
|
int64_t databasePosId(void) const { return m_id; }
|
||||||
bool databasePosIdIsValid(void) const { return m_id != INT64_MIN; }
|
bool databasePosIdIsValid(void) const { return m_id != INT64_MIN; }
|
||||||
@ -67,6 +72,41 @@ private:
|
|||||||
// WARNING: see comment about m_strFormat above !!
|
// WARNING: see comment about m_strFormat above !!
|
||||||
StrFormat m_strFormat;
|
StrFormat m_strFormat;
|
||||||
int64_t m_id;
|
int64_t m_id;
|
||||||
|
friend class BlockPosIterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This could be a random access iterator, but it is not needed, and it
|
||||||
|
// is more complex to implement
|
||||||
|
//class BlockPosIterator : public std::iterator<std::bidirectional_iterator_tag, BlockPos, long long>
|
||||||
|
class BlockPosIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum State { Start = -1, Middle = 0, End = 1 };
|
||||||
|
// NOTE: if m_state is initialized to Middle, the value of the iterator will be undefined
|
||||||
|
BlockPosIterator(void) : m_value(0,0,0), m_start(0,0,0), m_end(0,0,0), m_state(Start) {}
|
||||||
|
BlockPosIterator(BlockPos start, BlockPos end, State state = Middle) : m_value(start), m_start(start), m_end(end), m_state(state) {}
|
||||||
|
BlockPosIterator(const BlockPosIterator &i) : m_value(i.m_value), m_start(i.m_start), m_end(i.m_end), m_state(i.m_state) {}
|
||||||
|
BlockPosIterator &operator=(const BlockPosIterator &i);
|
||||||
|
bool operator==(const BlockPosIterator &i) const;
|
||||||
|
bool operator!=(const BlockPosIterator &i) const { return !operator==(i); }
|
||||||
|
|
||||||
|
BlockPos &operator*(void) { return m_value; }
|
||||||
|
BlockPos *operator->(void) { return &m_value; }
|
||||||
|
BlockPosIterator &operator++(void) { stepForward(); return *this; }
|
||||||
|
BlockPosIterator operator++(int) { BlockPosIterator rv(*this); stepForward(); return rv; }
|
||||||
|
BlockPosIterator &operator--(void) { stepReverse(); return *this; }
|
||||||
|
BlockPosIterator operator--(int) { BlockPosIterator rv(*this); stepReverse(); return rv; }
|
||||||
|
|
||||||
|
void breakDim(int i, int step = 1);
|
||||||
|
private:
|
||||||
|
BlockPos m_value;
|
||||||
|
BlockPos m_start;
|
||||||
|
BlockPos m_end;
|
||||||
|
State m_state;
|
||||||
|
void printState(const char *message, FILE *file);
|
||||||
|
void stepForward(void);
|
||||||
|
void stepReverse(void);
|
||||||
|
bool stepDim(int i, int step);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NodeCoord : BlockPos
|
struct NodeCoord : BlockPos
|
||||||
@ -119,38 +159,6 @@ namespace std {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BlockPos::operator=(const std::string &s)
|
|
||||||
{
|
|
||||||
m_id = INT64_MIN;
|
|
||||||
std::istringstream is(s);
|
|
||||||
if (isdigit(is.peek()) || is.peek() == '-' || is.peek() == '+') {
|
|
||||||
int64_t ipos;
|
|
||||||
is >> ipos;
|
|
||||||
if (is.bad() || !is.eof()) {
|
|
||||||
throw std::runtime_error(std::string("Failed to decode i64 (minetest) coordinate string from database (") + s + ")" );
|
|
||||||
}
|
|
||||||
operator=(ipos);
|
|
||||||
m_strFormat = I64;
|
|
||||||
}
|
|
||||||
else if (is.peek() == 'a') {
|
|
||||||
// Freeminer new format (a<x>,<y>,<z>)
|
|
||||||
char c1, c2;
|
|
||||||
is >> c1;
|
|
||||||
is >> x();
|
|
||||||
is >> c1;
|
|
||||||
is >> y();
|
|
||||||
is >> c2;
|
|
||||||
is >> z();
|
|
||||||
if (is.bad() || !is.eof() || c1 != ',' || c2 != ',') {
|
|
||||||
throw std::runtime_error(std::string("Failed to decode axyz (freeminer) coordinate string from database (") + s + ")" );
|
|
||||||
}
|
|
||||||
m_strFormat = AXYZ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::runtime_error(std::string("Failed to detect format of coordinate string from database (") + s + ")" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string BlockPos::databasePosStr(StrFormat defaultFormat) const
|
inline std::string BlockPos::databasePosStr(StrFormat defaultFormat) const
|
||||||
{
|
{
|
||||||
StrFormat format = m_strFormat;
|
StrFormat format = m_strFormat;
|
||||||
@ -159,27 +167,6 @@ inline std::string BlockPos::databasePosStr(StrFormat defaultFormat) const
|
|||||||
return databasePosStrFmt(format);
|
return databasePosStrFmt(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline std::string BlockPos::databasePosStrFmt(StrFormat format) const
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
switch(format) {
|
|
||||||
case Unknown:
|
|
||||||
throw std::runtime_error(std::string("Internal error: Converting BlockPos to unknown string type"));
|
|
||||||
break;
|
|
||||||
case I64:
|
|
||||||
os << databasePosI64();
|
|
||||||
break;
|
|
||||||
case XYZ:
|
|
||||||
os << x() << ',' << y() << ',' << z();
|
|
||||||
break;
|
|
||||||
case AXYZ:
|
|
||||||
os << 'a' << x() << ',' << y() << ',' << z();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// operator< should order the positions in the
|
// operator< should order the positions in the
|
||||||
// order the corresponding pixels are generated:
|
// order the corresponding pixels are generated:
|
||||||
// First (most significant): z coordinate, descending (i.e. reversed)
|
// First (most significant): z coordinate, descending (i.e. reversed)
|
||||||
@ -213,13 +200,48 @@ inline bool BlockPos::operator==(const BlockPos &p) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t NodeCoord::hash(void) const
|
inline BlockPosIterator &BlockPosIterator::operator=(const BlockPosIterator &i)
|
||||||
{
|
{
|
||||||
size_t hash = 0xd3adb33f;
|
m_value = i.m_value;
|
||||||
for (int i=0; i<3; i++)
|
m_start = i.m_start;
|
||||||
// Nothing too fancy...
|
m_end = i.m_end;
|
||||||
hash = ((hash << 8) | (hash >> 24)) ^ (dimension[i] ^ (isBlock[i] ? 0x50000000 : 0));
|
m_state = i.m_state;
|
||||||
return hash;
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool BlockPosIterator::operator==(const BlockPosIterator &i) const
|
||||||
|
{
|
||||||
|
if (m_state != i.m_state)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return m_value == i.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool BlockPosIterator::stepDim(int i, int step)
|
||||||
|
{
|
||||||
|
bool forward = true;
|
||||||
|
if (step < 0)
|
||||||
|
forward = false;
|
||||||
|
if (m_start.dimension[i] <= m_end.dimension[i] || !forward) {
|
||||||
|
if (m_value.dimension[i] < m_end.dimension[i]) {
|
||||||
|
m_value.dimension[i]++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_value.dimension[i] = m_start.dimension[i];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_value.dimension[i] > m_end.dimension[i]) {
|
||||||
|
m_value.dimension[i]--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_value.dimension[i] = m_start.dimension[i];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool NodeCoord::operator==(const NodeCoord &coord) const
|
inline bool NodeCoord::operator==(const NodeCoord &coord) const
|
||||||
|
@ -232,6 +232,7 @@ set(mapper_SRCS
|
|||||||
TileGenerator.cpp
|
TileGenerator.cpp
|
||||||
ZlibDecompressor.cpp
|
ZlibDecompressor.cpp
|
||||||
Color.cpp
|
Color.cpp
|
||||||
|
BlockPos.cpp
|
||||||
mapper.cpp
|
mapper.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user