import argparse import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation from itertools import islice parser = argparse.ArgumentParser() parser.add_argument('--revert', action='store_true') args = parser.parse_args() NUM_POINTS = 1000 LIMIT = 100 def part1_by1(x): x &= 0x0000ffff x = (x ^ (x << 8)) & 0x00ff00ff x = (x ^ (x << 4)) & 0x0f0f0f0f x = (x ^ (x << 2)) & 0x33333333 x = (x ^ (x << 1)) & 0x55555555 return x def part_even(x): x = x & 0x5555555555555555 x = (x | (x >> 1)) & 0x3333333333333333 x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F x = (x | (x >> 4)) & 0x00FF00FF00FF00FF x = (x | (x >> 8)) & 0x0000FFFF0000FFFF return x def encode_morton_2d(x, y): code = (part1_by1(y) << 1) + part1_by1(x) return code def decode_morton_2d(code): x = part_even(code) y = part_even(code >> 1) return x, y def revert_morton(code): code = ((code >> 1) & 0x55555555) | ((code & 0x55555555) << 1) code = ((code >> 2) & 0x33333333) | ((code & 0x33333333) << 2) code = ((code >> 4) & 0x0f0f0f0f) | ((code & 0x0f0f0f0f) << 4) code = ((code >> 8) & 0x00ff00ff) | ((code & 0x00ff00ff) << 8) code = ((code >> 16) & 0xffff) | ((code & 0xffff) << 16) return code def identity(code): return code a = np.random.randint(1, 100, size=(NUM_POINTS, 2)) func = revert_morton if args.revert else identity codes = ((p[0], p[1], func(encode_morton_2d(p[0], p[1]))) for p in a) codes_sorted = sorted(codes, key=lambda c: c[2]) b = np.array(list([c[0], c[1]] for c in islice(codes_sorted, LIMIT))) def update_line(num, data, line): line.set_data(data[:num, 0], data[:num, 1]) return line, fig = plt.figure() plt.plot(a[:, 0], a[:, 1], 'b.') plt.title('Revert Morton' if args.revert else 'Morton') l, = plt.plot([], [], 'ro') anim = animation.FuncAnimation(fig, update_line, LIMIT, fargs=(b, l), interval=50, blit=True, repeat=False) anim.save('{}morton.mp4'.format('revert' if args.revert else '')) plt.show()