Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
3a3bb30
Merge branch `test` into `master`.
flatheadmill Apr 17, 2014
49b490e
Upgrade Proof to 0.0.47.
flatheadmill Sep 14, 2014
1adeaa8
Diary entry.
demarius Oct 20, 2014
0f1d8b9
Diary entry.
demarius Oct 22, 2014
08b785c
Function signatures.
demarius Oct 22, 2014
3b0dba1
Change export names.
demarius Oct 23, 2014
71d7405
Fix distance-to-point calculation.
demarius Oct 24, 2014
30753fe
Minimum height is 2.
demarius Oct 26, 2014
446a2ba
Update minimum height for p2d.
demarius Oct 27, 2014
177c79a
Fix rotation calculations.
demarius Oct 27, 2014
02c8ddc
Converting distance to point works.
demarius Oct 29, 2014
9a21b17
Merge branch `point` into `master`.
flatheadmill Oct 30, 2014
0fe6325
Test conversion to point.
demarius Oct 31, 2014
40ca0de
Test conversion to distance.
demarius Oct 31, 2014
195922d
Diary entry.
demarius Oct 29, 2014
d3101ab
Renaming.
demarius Nov 1, 2014
8f39a58
Working on 3D conversions.
demarius Nov 2, 2014
6fe52fe
Working on 3D.
demarius Nov 6, 2014
7f9312c
Fix rotate2d() calls.
demarius Nov 4, 2014
8d385ed
Implement rotate3d().
demarius Nov 5, 2014
5f5686d
Diary entry.
demarius Nov 7, 2014
3ce2d8c
Merge branch `3d` into `master`.
flatheadmill Nov 7, 2014
92a5783
Fix function params.
demarius Nov 8, 2014
4d6134b
Working on 3d->distance.
demarius Nov 9, 2014
d17bdea
Parity.
demarius Nov 9, 2014
3aa1668
Diary entry.
demarius Nov 10, 2014
ae78aa8
Diary entry.
demarius Nov 11, 2014
f7ab6e6
Function signatures.
demarius Nov 15, 2014
3dc0ced
Compiles.
demarius Nov 16, 2014
4b57ddf
Add point object.
demarius Nov 17, 2014
41a0fef
Expand point object.
demarius Nov 18, 2014
d1a13b8
'roatateLeft()'.
demarius Nov 20, 2014
04324f8
Point.n.
demarius Nov 22, 2014
47a1eb5
Diary entry.
demarius Nov 24, 2014
4ca1b67
'rotateRight()'.
demarius Nov 20, 2014
1b15bfc
Switching to point object.
demarius Nov 22, 2014
4981c2a
Cleanup.
demarius Nov 26, 2014
9192f71
Merge branch `3d` into `master`.
flatheadmill Nov 26, 2014
7b01fb9
Point.toArray().
demarius Nov 27, 2014
f5fc1d4
Point.n().
demarius Nov 27, 2014
b241d57
Point.rotateLeft().
demarius Nov 28, 2014
74faaca
Point.rotateRight().
demarius Nov 29, 2014
28c3c45
Merge branch `3d` into `master`.
flatheadmill Dec 2, 2014
efaa29c
Point.mod().
demarius Dec 1, 2014
c219a5c
Fix rotation names.
demarius Dec 2, 2014
307faf9
Working out rotations.
demarius Dec 3, 2014
959f672
Utilities for 3d.
demarius Dec 2, 2014
4fe150e
Merge branch `3d` into `master`.
flatheadmill Dec 4, 2014
5f3e672
Changing rotations.
demarius Dec 4, 2014
df418df
Remove 2d rotations.
demarius Dec 5, 2014
dc2eb46
Use general rotate2d().
demarius Dec 6, 2014
a056237
Change point parameters and make rotate2d() useful.
demarius Dec 8, 2014
3583978
Update convertDistanceTo2dPoint().
demarius Dec 8, 2014
fa44b80
Fix Point().
demarius Dec 10, 2014
7c7b7e1
Point.rotate3d().
demarius Dec 11, 2014
04c583a
Diary entry.
demarius Dec 11, 2014
04aad29
Just put rotations in a {}.
demarius Dec 12, 2014
6b0df8b
Diary entry.
demarius Dec 13, 2014
8a92930
Function signatures.
demarius Dec 14, 2014
cdb7411
Merge branch `3d` into `master`.
flatheadmill Dec 16, 2014
5a4d118
Change n to field, not function.
demarius Dec 15, 2014
60eeb53
Working on d->3d.
demarius Dec 16, 2014
e8f21f4
Fix rotateLeft() params.
demarius Dec 17, 2014
4a9dd04
Cleanup dist -> 3d.
demarius Dec 18, 2014
8a241a3
Comments.
demarius Dec 19, 2014
51111ea
Commenting 'unrotate'
demarius Dec 20, 2014
8b4a49e
Scoping 3d-> dist.
demarius Dec 21, 2014
a055ae9
Exports.
demarius Dec 22, 2014
5b30ff8
Add algorithm to diary.
demarius Dec 23, 2014
a23d4a1
Diary.
demarius Dec 25, 2014
02a04a4
Cleanup.
demarius Dec 27, 2014
bbc8649
Fix 'n'.
demarius Dec 29, 2014
db053a9
separate init for cleaner array handling.
demarius Dec 29, 2014
1b462b7
Fix 'z' in array inits.
demarius Dec 30, 2014
3dcfcf7
Diary.
demarius Dec 31, 2014
f14892b
Exports.
demarius Jan 2, 2015
fc3523e
Cleanup.
demarius Jan 2, 2015
66264b0
Move optional 'height' parameter.
demarius Jan 4, 2015
5578e6c
Cleanup.
demarius Jan 4, 2015
04fd8fb
Exports and convert to xyz2d to use Point.
demarius Jan 6, 2015
f2646b7
Merge branch `3d` into `master`.
flatheadmill Jan 6, 2015
f5b1072
Cleanup.
demarius Jan 7, 2015
31f2149
Don't return Points.
demarius Jan 12, 2015
413dd84
Remove old tests.
demarius Jan 12, 2015
2d77249
Update tests.
demarius Jan 13, 2015
31b2551
Update Proof.
demarius Jan 14, 2015
5f7a6c0
Remove old test.
demarius Jan 16, 2015
b2bec89
Test 1d -> 2D.
demarius Jan 16, 2015
2407f23
Test 1D <-> 3D.
demarius Jan 17, 2015
8f8bd12
Test 2D <-> 1D.
demarius Jan 18, 2015
2bccc31
Don't return Points.
demarius Jan 12, 2015
4035fe6
Remove old tests.
demarius Jan 12, 2015
84522e1
Update tests.
demarius Jan 13, 2015
f329182
Update Proof.
demarius Jan 14, 2015
707447f
Remove old test.
demarius Jan 16, 2015
0294cd7
Test 1d -> 2D.
demarius Jan 16, 2015
f6c6709
Test 1D <-> 3D.
demarius Jan 17, 2015
99567be
Test 2D <-> 1D.
demarius Jan 18, 2015
7513787
Cleanup.
demarius Jan 19, 2015
96d916f
Fix 1d<->2d test.
demarius Jan 21, 2015
72dc9b4
Fix height.
demarius Jan 21, 2015
0b98f49
Diary entry.
demarius Jan 22, 2015
6d58273
Merge branch `3d` into `master`.
flatheadmill Jan 23, 2015
8ca47cb
Merge branch `3d` into `master`.
flatheadmill Jan 23, 2015
61ab759
Implement `d2xy` function.
jgpelletier Jan 24, 2015
8f6532e
Exchange bit variables in 2dPoint to distance.
jgpelletier Jan 25, 2015
a76b15f
Fix rotate2d() calls.
demarius Jan 23, 2015
cbd3b73
Update test.
demarius Jan 24, 2015
3dac665
Merge remote-tracking branch 'josh/xyd2'
demarius Jan 25, 2015
a877e56
Add test for `xy2d`.
jgpelletier Jan 26, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions diary.md
Original file line number Diff line number Diff line change
@@ -1 +1,42 @@
the function convertPointToDistance requires 'height' to be a power of 2. Looking into ways to rewrite that, or determine if a rewrite is necessary.

http://www.win.tue.nl/~hermanh/stack/dagstuhl08-talk.pdf

pseudo-code: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html

http://arxiv.org/abs/1109.2323

Axis rotation: http://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/3drota.htm#X-Axis%20Rotation

parity: http://en.wikipedia.org/wiki/Parity_%28mathematics%29 http://en.wikipedia.org/wiki/Parity_bit

Want to express axis rotations internally without creating a point object.
or perhaps use one internally but return an array.

move Point to own module for reuse in Voronoi diagram calculator and r-tree

http://en.wikipedia.org/wiki/Rotation_matrix

figure out how to keep track of rotations so we can unrotate.

interesting hilbert implementation. https://github.com/ryan-williams/hilbert-js

2D encoding algorithm:
Outline of the Method

To encode from index to coordinates:
"Unpack" the index into a list of h D-bit ints (called "index chunks").
h will be the number of levels of recursion (in our case the number of times to loop); from this calculate the orientation of the overall cube.
Then, for each index chunk, starting at the most- significant,
Use a modified Gray code to convert the index chunk into a D-bit "coordinate chunk" with one bit destined for each of the D coordinates;
Calculate the start and end corners for the child cube to which the indexed point belongs;
Loop to do the child cube.
Finally,
"Pack" the output coordinates by redistributing the D bits from each of h coordinate chunks into D ints, each with h bits.
Decoding is very similar, except that at each stage we Gray- decode D index bits from coordinate bits. At that point the decoder has the same information the encoder uses to calculate the orientation of the child cube for the next stage.

N-dimensional mapping. http://www.dcs.bbk.ac.uk/~jkl/pubs/JL1_00a.pdf

more spatial indexing info. http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves

hilbert curve scheduling. http://en.wikipedia.org/wiki/Hilbert_curve_scheduling
189 changes: 166 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,172 @@
// Use Hilbert curve point generation to map 2D data to 1D space and vice-versa.
// Will later expand to allow `n` dimensions.

function Point(x, y, z) {
this.rotations = {
x: 0,
y: 0,
z: 0
}

this.init = function (x, y, z) {
this.x = Math.round(x) || 0
this.y = Math.round(y) || 0
if (z != null) {
this.z = Math.round(z) || 0
this.d = 3
this.n = 4 * this.z + 2 * this.y + this.x
} else {
this.z = null
this.d = 2
}
}
if (x instanceof Array) {
this.init(x[0], x[1], x[2])
} else {
this.init(x, y, z)
}
}

Point.prototype.rotate = function (p, n) { // :: Point -> Int -> Point
// record rotations
if (p.n == 0) return new Point(this.z, this.x, this.y)
if (p.n == 1 || p.n == 3) return new Point(this.y, this.z, this.x)
if (p.n == 2 || p.n == 6) return new Point(n - this.x, n - this.y, this.z)
return new Point(n - this.z, this.x, n - this.y)
}

Point.prototype.rotate2d = function (n, xbit, ybit) { // : Int -> Int -> Int -> Point
return new Point(rotate2d(n, this.x, this.y, xbit, ybit))
}

Point.prototype.rotate3d = function (level) { // :: Int -> Point
return new Point(rotate3d(level, this.x, this.y, this.z))
}

// Accepts the height or width of a square, and the coordinates to
Point.prototype.rotateLeft = function (n) { // :: Int -> Point
if (n % 3 == 0) return this
if (n % 3 == 1) return new Point(this.y, this.z, this.x)
return new Point(this.z, this.x, this.y)
}

Point.prototype.rotateRight = function (n) { // :: Int -> Point
if (n % 3 == 0) return this
if (n % 3 == 1) return new Point(this.z, this.x, this.y)
return new Point(this.y, this.z, this.x)
}

Point.prototype.toArray = function () { // :: -> [Int, Int]
if (this.d == 3) { return [this.x, this.y, this.z] }
return [this.x, this.y]
}

Point.prototype.mod = function (n) { // :: Int -> Point
return new Point(this.x % n, this.y % n, this.z % n)
}

Point.prototype.unrotate = function (n) {
// read this.rotations and undo
}

// Accepts the height or width of a square/graph, and the coordinates to
// convert.
function convertPointToDistance (height, x, y) {
function convert2dPointToDistance (p, height) { // :: Int -> Int -> Int -> Int
var xbit, ybit, level, d = 0
var forHeight = p.x > p.y ? p.x : p.y

// needs some tests to make sure height is compatible
// What keeps the user from putting 54 down as the height
while (forHeight >= height) {
height *=2
}
// For each Hilbert level, we want to add an amount to
// `d` based on which region we are in
for (level = height / 2; level > 0; level /= 2) {
for (level = height / 2; level > 0; level = Math.floor(level / 2)) {
// Determine what region we're in
xbit = (x & level) > 0
ybit = (y & level) > 0
xbit = (p.x & level) > 0
ybit = (p.y & level) > 0
// increase distance based on region
d += level * level * ((3 * xbit) ^ ybit)
// rotate so that we'll be in sync with the next
// region.
var temp = rotate (height, x, y, xbit, ybit)
x = temp[0]
y = temp[1]
p = p.rotate2d(level, xbit, ybit)
// HEAD
// p = p.rotate2d(height, xbit, ybit)
}

return d
}

function convertDistanceToPoint (height, distance) {
var xbit, ybit, level, distance
var x = 0, y = 0
// height and coordinates.
function convert3dPointToDistance (p, height) { // :: Int -> Int -> Int -> Int -> Int
var s = 1, level = 0
var max = Math.max.apply(Math, p.toArray())
for (; 2 * s <= max; s *= 2) {
level = (level + 1) % 3
}

// shuffle axes
// rotate based on parity
}

// Accepts height or width of a square/graph and distance
function convertDistanceTo2dPoint (distance, height) { // :: Int -> Int -> [Int, Int]
distance = Math.floor(distance)
var xbit, ybit, level, p = new Point(0, 0)

if (height <= Math.sqrt(distance)) {
height = 2
while (height <= Math.sqrt(distance)) {
height *=2
}
}

for (level = 1; level < height; level *= 2) {
xbit = 1 & (distance / 2)
ybit = 1 & (distance ^ xbit)

var temp = rotate(height, x, y, xbit, ybit)
x = temp[0]
y = temp[1]
x += level * xbit
y += level * xbit
distance /= 4
p = p.rotate2d(level, xbit, ybit)
p.x += level * xbit
p.y += level * ybit
distance = Math.floor(distance / 4)
}

return [x, y]
return p.toArray()
}

// height/width of a square/graph and distance
function convertDistanceTo3dPoint (distance, height) { // Int -> Int -> [Int, Int, Int]
distance = Math.floor(distance)
var xbit, ybit, zbit, level, parity
var iter = 2, log = 0, p = new Point(x, y, z)

height = height || 2

for (parity = 1; parity < height; parity *= 2, log++) {}
parity = log % 3;

for (level = 1; level < height || distance > 0; level *=2) {
xbit = distance & 1;
ybit = (ditance / 2) & 1;
zbit = (distance / 4) & 1;

var temp = rotate3d(level - 1, xbit ^ ybit, ybit ^ zbit, zbit)
p.x = temp[0] * level + level - 1
p.y = temp[1] * level + level - 1
p.z = temp[2] * level + level - 1

distance = Math.floor(distance / 8)
level *= 2;
iter++;
}

return p.rotateLeft(iter - parity + 1).toArray();
}

// Rotate the coordinate plane and (x,y)
function rotate (n, x, y, xbit, ybit) {
if (ybit === 0 ) {
if (xbit === 1) {
function rotate2d (n, x, y, xbit, ybit) { // :: Int -> Int -> Int -> Int -> Int -> [Int, Int]
if (ybit == 0 ) {
if (xbit == 1) {
x = n - 1 - x
y = n - 1 - y
}
Expand All @@ -60,5 +179,29 @@ function rotate (n, x, y, xbit, ybit) {
return [x, y]
}

exports.convertPointToDistance = convertPointToDistance
exports.convertDistanceToPoint = convertDistanceToPoint
// Rotate the coordinate plane and (x,y, z)
function rotate3d(level, x, y, z) { // :: Int -> Int -> Int -> Int -> [Int, Int, Int]
index = 4 * z + 2 * y + x
if (index == 0) {
return [z, x, y]
} else if (index == 1 || index == 3) {
return [y, z, x]
} else if (index == 2 || index == 6) {
return [level - x, level - y, z]
} else if (index == 5 || index == 7) {
return [y, level - z, level - x]
} else {
return [level - z, x, level - y]
}
}

exports.xy2d = function (x, y, height) {
height = height || 2
return convert2dPointToDistance(new Point(x, y), height)
}
exports.xyz2d = function(x, y, z, height) {
height = height || 2
return convert3dPointToDistance(new Point(x, y, z), height)
}
exports.d2xy = convertDistanceTo2dPoint
exports.d2xyz = convertDistanceTo3dPoint
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
}],
"devDependencies":
{
"proof": "0.0.44"
"proof": "*"
},
"licenses":
[{
Expand Down
1 change: 1 addition & 0 deletions release.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Issue by Issue

* Upgrade Proof to 0.0.47. #16.
* Upgrade Proof to 0.0.44. #10.
* Remove "url" from `package.json`. #9.
* Update `LICENSE` for 2014. #8.
7 changes: 0 additions & 7 deletions t/xy/1dto2d.js

This file was deleted.

44 changes: 44 additions & 0 deletions t/xy/1dto2d.t.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env node

require('proof')(9, function (equal) {
var hilbert = require('../..')
equal(hilbert.d2xy(0, 2), [0, 0])
equal(hilbert.d2xy(0, 3), [0, 1])
equal(hilbert.d2xy(4, 2), [2, 0])
equal(hilbert.d2xy(15, 2), [3, 0])
equal(hilbert.d2xy(16, 2), [0, 4])
equal(hilbert.d2xy(63, 2), [7, 0])
equal(hilbert.d2xy(64, 2), [0, 8])
equal(hilbert.d2xy(1023, 2), [31, 0])
equal(hilbert.d2xy(1024, 2), [0, 32])
console.log("0 " , hilbert.d2xy(0, 2))
console.log("1 " , hilbert.d2xy(1, 2))
console.log("2 " , hilbert.d2xy(2, 2))
console.log("3 " , hilbert.d2xy(3, 2))
console.log("4 " , hilbert.d2xy(4, 2))
console.log("5 " , hilbert.d2xy(5, 2))
console.log("6 " , hilbert.d2xy(6, 2))
console.log("7 " , hilbert.d2xy(7, 2))
console.log("8 " , hilbert.d2xy(8, 2))
console.log("9 " , hilbert.d2xy(9, 2))
console.log("10 " , hilbert.d2xy(10, 2))
console.log("11 " , hilbert.d2xy(11, 2))
console.log("12 " ,hilbert.d2xy(12, 2))
console.log("13 " ,hilbert.d2xy(13, 2))
console.log("14 " ,hilbert.d2xy(14, 2))
console.log("15 " ,hilbert.d2xy(15, 2))
console.log("16 " ,hilbert.d2xy(16, 2))
console.log("17 " ,hilbert.d2xy(17, 2))
console.log("18 " ,hilbert.d2xy(18, 2))
console.log("19 " ,hilbert.d2xy(19, 2))
console.log("20 " ,hilbert.d2xy(20, 2))
console.log("21 " ,hilbert.d2xy(21, 2))
console.log("22 " ,hilbert.d2xy(22, 2))
console.log("23 " ,hilbert.d2xy(23, 2))
console.log("24 " ,hilbert.d2xy(24, 2))
console.log("25 " ,hilbert.d2xy(25, 2))
console.log("26 " ,hilbert.d2xy(26, 2))
console.log("27 " ,hilbert.d2xy(27, 2))
console.log("28 " ,hilbert.d2xy(28, 2))
console.log("29 " ,hilbert.d2xy(29, 2))
})
4 changes: 2 additions & 2 deletions t/xy/2dto1d.js → t/xy/1dto3d.t.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
require('proof')(1, function (equal) {
var hilbert = require('../..')

equal(hilbert.convertPointToDistance(16, 2, 2,), 8)
}
equal(hilbert.convertPointToDistance(16, 2, 2), 8)
})
26 changes: 26 additions & 0 deletions t/xy/2dto1d.t.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env node

require('proof')(3, function (equal) {

var hilbert = require('../..')
equal(hilbert.xy2d(1, 0, 2), 3)
equal(hilbert.xy2d(2, 0, 4), 4)
equal(hilbert.xy2d(9, 9, 4), 10)
//equal(5, 8)
//hilbert.xy2d(0, 4, 2)
console.log("x: 0, y: 1, length: ", hilbert.xy2d(0, 1, 2)) // 1
console.log("x: 1, y: 1, length: ", hilbert.xy2d(1, 1, 2)) // 2
console.log("x: 1, y: 0, length: ", hilbert.xy2d(1, 0, 2)) // 3
console.log("x: 0, y: 2, length: ", hilbert.xy2d(0, 2, 2)) // 4
console.log("x: 0, y: 3, length: ", hilbert.xy2d(0, 3, 2)) // 5
console.log("x: 1, y: 3, length: ", hilbert.xy2d(1, 3, 2)) // 6
console.log("x: 1, y: 2, length: ", hilbert.xy2d(1, 2, 2)) // 7
console.log("x: 2, y: 2, length: ", hilbert.xy2d(2, 2, 2)) // 8
console.log("x: 2, y: 3, length: ", hilbert.xy2d(2, 3, 2)) // 9
console.log("x: 3, y: 3, length: ", hilbert.xy2d(3, 3, 2)) // 10
console.log("x: 3, y: 2, length: ", hilbert.xy2d(3, 2, 2)) // 11
console.log("x: 3, y: 1, length: ", hilbert.xy2d(3, 1, 2)) // 12
console.log("x: 2, y: 1, length: ", hilbert.xy2d(2, 1, 2)) // 13
console.log("x: 2, y: 0, length: ", hilbert.xy2d(2, 0, 2)) // 14
console.log("x: 3, y: 0, length: ", hilbert.xy2d(3, 0, 2)) // 15
})