I'm writing a program for visualizing crystals. As a part of the program, I have to generate all different basic points in a lattice structure. For those that aren't familiar with crystallography, you can find the most general cases of these structures here: https://en.wikipedia.org/wiki/Hermann%E2%80%93Mauguin_notation#Lattice_types
The problem was that I wanted to keep track of all these points. So I gave them a number. I was trying a bit with pen and paper, and found a nice algorithm to connect a coordinate (either in 2D or in 3D) with a number (and the other way around) by writing it out in binary form.
So if you want, for example, a simple cubic lattice in 2D, and you want to know the coordinates of point number 14. you can write this binary as 001110. You divide the number into 00|11|10, in which the most right part stands for (x,y)*1, the middle part part stands for (x,y)*2, the left part stands for (x,y)*4 (which is useless for number 14, just to make everything clear) and so on. So number 14 maps to the point (3, 2).
A simple C++ program to generate coordinates for the first 50 ints:
int x, y;
for (int n = 0; n < 50; n++)
{
x = 0;
y = 0;
bitset<16> nset(n);
for (int i = 0; i < 16/2; i++)
{
x+=(nset[2*i]*pow(2.,i));
y+=(nset[2*i+1]*pow(2.,i));
}
cout << n << "\t" << x << "\t" << y << endl;
}
I extended this algorithm to 3D by reserving an additional column for the z-value, and for the other Lattice types by reserving the first one or two columns with kind of x+1/2, y+1/2, z+1/2 properties, different for each Lattice type.
So here's my question: does this algorithm exists already? Has it a name? Or is this just an obvious application of binary math? I read some things about hashmaps, but this seems more efficient to me, at least if you are dealing with integer numbers.
This is my very first question at stackexchange, was doubting I had to post this here or at the physics forum. Or perhaps at the math forum, because this is kind of a R^2->R bijection. So please correct me if this question is not at the right place.
Sep 17 2018In-product view. Mapping coordinates specify how a map is placed, oriented, and scaled onto geometry. Mapping coordinates are often specified in terms of U, V, and W, where U is the horizontal dimension, V is the vertical dimension, and W is the optional third dimension, specifying depth.
Coordinates are a set of numbers or numbers and letters together that show you a position on a map. They can help you find a specific place or object that you are looking for.
So here's my question: does this algorithm exists already? Has it a name?
This mapping is called the Z-order curve or Morton code:
In mathematical analysis and computer science, Z-order, Morton order, or Morton code is a function which maps multidimensional data to one dimension while preserving locality of the data points. It was introduced in 1966 by G. M. Morton. The z-value of a point in multidimensions is simply calculated by interleaving the binary representations of its coordinate values. Once the data are sorted into this ordering, any one-dimensional data structure can be used such as binary search trees, B-trees, skip lists or (with low significant bits truncated) hash tables. The resulting ordering can equivalently be described as the order one would get from a depth-first traversal of a quadtree.
As shown in your example C++ code, the the x co-ordinate is stored in the even numbered bits and the y co-ordinate is stored in the odd numbered bits. The mapping can be easily extended to higher dimensions.
Some algorithms for fast interleaving of bits to encode these numbers using bit-manipulation operations can be found here.
I may be misinterpreting your code, but it seems like what you're doing is taking the even-numbered bits of the binary number, concatenating them together to form a new number, and using that number as your x coordinate. You seem to be doing the same thing for the y coordinate.
I don't think there's a name for this algorithm, though it seems like a pretty standard technique. For what it's worth, I think there's a much easier way to accomplish what you're doing here by using bitwise operators rather than bitset
and pow
:
for (int n = 0; n < kUpperBound; n++) {
int x = 0;
int y = 0;
for (int i = 0; i < 8; i++) {
if (n & (1 << (2*i)) != 0) {
x += 1 << i;
}
if (n & (1 << (2*i + 1)) != 0) {
y += 1 << i;
}
}
cout << n << " " << x << " " << y << endl;
}
The value 1 << k
is a number whose kth bit is 1 and which is 0 otherwise. Using the bitwise AND operator to AND this number with n
will give back 0 if the kth bit of n
is 0 and a nonzero number otherwise. Therefore, the test if (n & (1 << k) != 0)
checks whether the kth bit of n
is set or not. Then, instead of using pow
to evaluate 2n, we use the fact that 1 << k
has the numerical value 2k.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With