Skip to content

Instantly share code, notes, and snippets.

@ppKrauss
Last active September 28, 2019 18:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ppKrauss/03d10beaaa5ad4663cd63e2195ca7404 to your computer and use it in GitHub Desktop.
Save ppKrauss/03d10beaaa5ad4663cd63e2195ca7404 to your computer and use it in GitHub Desktop.
OLD TEST on sp-fill curves
license: mit
function hilbertDemo() {
var refWidth = parseInt( document.getElementById('reftab').getBoundingClientRect().width/2.0 );
var svg = d3.select('svg#hilbert-chart'),
canvasWidth = Math.min(window.innerWidth, refWidth), //changed
hilbert;
function d3Digest() {
var hilbertData = {
start: 0,
length: Math.pow(4, globOrder)
};
hilbert.order(globOrder).layout(hilbertData);
svg.selectAll('path')
.datum(hilbertData)
.attr('d', function(d) { return getHilbertPath(d.pathVertices); })
.attr('transform', function(d) {
return 'scale('+ d.cellWidth + ') '
+ 'translate(' + (d.startCell[0] +.5) + ',' + (d.startCell[1] +.5) + ')';
});
svg.select('path:not(.skeleton)')
.transition().duration(globOrder * 1000).ease(d3.easePoly)
.attrTween('stroke-dasharray', tweenDash);
function getHilbertPath(vertices) {
var path = 'M0 0L0 0';
vertices.forEach(function(vert) {
switch(vert) {
case 'U': path += 'v-1'; break;
case 'D': path += 'v1'; break;
case 'L': path += 'h-1'; break;
case 'R': path += 'h1'; break;
}
});
return path;
}
function tweenDash() {
var l = this.getTotalLength(),
i = d3.interpolateString("0," + l, l + "," + l);
return function(t) { return i(t); };
}
}
hilbertDemo.d3Digest = d3Digest; // globalize reference
function init() {
hilbert = d3.hilbert()
.order(globOrder)
.canvasWidth(canvasWidth)
.simplifyCurves(false);
svg.attr("width", canvasWidth).attr("height", canvasWidth);
var canvas = svg.append('g');
canvas.append('path').attr('class', 'skeleton');
canvas.append('path');
// Canvas zoom/pan
svg.call(d3.zoom()
.translateExtent([[0, 0], [canvasWidth, canvasWidth]])
.scaleExtent([1, Infinity])
.on("zoom", function() {
if (xzoomNode.value==1) canvas.attr("transform", d3.event.transform);
})
);
// Value Tooltip
var valTooltip = d3.select('#val-tooltip2');
svg.on('mouseover', function() { valTooltip.style("display", "inline"); })
.on('mouseout', function() { valTooltip.style("display", "none"); })
.on('mousemove', function () {
var coords = d3.mouse(canvas.node());
var halfdigits = Math.ceil(globOrder/2);
var vv = hilbert.getValAtXY(coords[0], coords[1]);
var vv4 = parseInt(vv).toString(4).padStart(globOrder,'0');
var vv32 = parseInt(vv).toString(32).padStart(halfdigits,'0');
if (globOrder%2) vv32="-";
valTooltip.html( "decimal: <code>"+vv +"</code><br/>quaternary: <code>"+vv4 +"</code><br/>base32: <code>"+vv32+"</code>" )
//valTooltip.text(hilbert.getValAtXY(coords[0], coords[1]))
.style('left', d3.event.pageX+'px')
.style('top', d3.event.pageY+'px');
});
// Order slider
d3Digest();
}
init();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=1000"/>
<title>Sp-filling curves, compare</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script>
<script src="https://unpkg.com/d3-simple-slider"></script>
<script src="https://unpkg.com/d3-morton"></script>
<script src="morton-demo.js"></script>
<script src="https://unpkg.com/d3-hilbert"></script>
<script src="hilbert-demo.js"></script>
<style>
body {
text-align: center;
}
table {
padding:10px;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
svg {
margin: 10px;
}
svg path {
fill: none;
stroke: #3A5894;
stroke-width: 0.25;
stroke-linecap: square;
}
svg path.skeleton {
stroke: #EEE;
stroke-width: 0.1;
}
#val-tooltip1, #val-tooltip2 {
display: none;
position: absolute;
margin-top: 22px;
margin-left: -1px;
padding: 5px;
border-radius: 3px;
font: 11px sans-serif;
color: #eee;
background: rgba(0,0,140,0.9);
text-align: center;
pointer-events: none;
}
</style>
</head>
<body>
<a href="https://en.wikipedia.org/wiki/Space-filling_curve">Space-filling curve</a> <b>order</b>:
<!-- span id="xxvalue"></span -->
<select id="xvalue" onchange="changeOrder(this.value)">
<option>1<option selected>2<option>3<option>4
<option>5<option>6<option>8
</select>
&nbsp; &nbsp; &nbsp; Zoom/pan:
<select id="xzoom">
<option value="1" selected>Enable
<option value="0">Disable
</select> &nbsp;&nbsp;<small>(hover over the picture)</small>
<br/>&nbsp;<br/>
<h3>Quadrilateral (base4 codes)</h3>
<table id="reftab" border="0" width="60%" align="center">
<tr>
<td><a href="https://en.wikipedia.org/wiki/Z-order_curve">MORTON</a><br/>
<svg id="morton-chart"></svg>
<div id="val-tooltip1"></div>
</td>
<td><a href="https://en.wikipedia.org/wiki/Hilbert_curve">HILBERT CURVE</a><br/>
<svg id="hilbert-chart"></svg>
<div id="val-tooltip2"></div>
</td>
</tr>
</table>
<script>
var globOrder = 2; // need also to change selected option
var xzoomNode = document.getElementById('xzoom');
mortonDemo(); // morton-demo.js
hilbertDemo(); // hilbert-demo.js
function changeOrder(v) {
globOrder = v; // order change to new value
mortonDemo.d3Digest();
hilbertDemo.d3Digest();
}
</script>
<p>The curve with the <b>best code prefix preservation</b>? Less average distance? <br/>&nbsp; Seems Hilbert... Check base32 codes on Order-6. But we need to proff: the next gist will be it.
<br/>... And about hexagon, how to compare? Please help us to do it! </p>
<br/><h3>Hexagonal (base7 codes)</h3>
<img src="http://osm.codes/_foundations/hexagonalCell-geocode3c.png" width="90%"/>
</body>
</html>
function mortonDemo() {
var refWidth = parseInt( document.getElementById('reftab').getBoundingClientRect().width/2.0 );
var svg = d3.select('svg#morton-chart'),
canvasWidth = Math.min(refWidth, window.innerWidth ), //old Math.min(window.innerWidth, window.innerHeight - 100),
zOrder;
function d3Digest() {
var zOrderData = {
start: 0,
length: Math.pow(4, globOrder)
};
zOrder.order(globOrder).layout(zOrderData);
svg.selectAll('path')
.datum(zOrderData)
.attr('d', function(d) { return getZOrderPath(d.pathVertices); })
.attr('transform', function(d) {
return 'scale('+ d.cellWidth + ') '
+ 'translate(' + (d.pathVertices[0][0] +.5) + ',' + (d.pathVertices[0][1] +.5) + ')';
});
svg.select('path:not(.skeleton)')
.transition().duration(globOrder * 1000).ease(d3.easePoly)
.attrTween('stroke-dasharray', tweenDash);
function getZOrderPath(vertices) {
var path = 'M0 0L0 0';
vertices.forEach(function(vert) {
path += 'L' + vert.join(',');
});
return path;
}
function tweenDash() {
var l = this.getTotalLength(),
i = d3.interpolateString("0," + l, l + "," + l);
return function(t) { return i(t); };
}
}
mortonDemo.d3Digest = d3Digest; // globalize reference
function init() {
zOrder = d3.zOrder()
.order(globOrder)
.canvasWidth(canvasWidth)
.simplifyCurves(false);
svg.attr("width", canvasWidth).attr("height", canvasWidth);
var canvas = svg.append('g');
canvas.append('path').attr('class', 'skeleton');
canvas.append('path');
// Canvas zoom/pan
svg.call(d3.zoom()
.translateExtent([[0, 0], [canvasWidth, canvasWidth]])
.scaleExtent([1, Infinity])
.on("zoom", function() {
if (xzoomNode.value==1) canvas.attr("transform", d3.event.transform);
})
);
// Value Tooltip
var valTooltip = d3.select('#val-tooltip1');
svg.on('mouseover', function() { valTooltip.style("display", "inline"); })
.on('mouseout', function() { valTooltip.style("display", "none"); })
.on('mousemove', function () {
var coords = d3.mouse(canvas.node());
var halfdigits = Math.ceil(globOrder/2);
var vv = zOrder.getValAtXY(coords[0], coords[1]);
var vv4 = parseInt(vv).toString(4).padStart(globOrder,'0');
var vv32 = parseInt(vv).toString(32).padStart(halfdigits,'0');
if (globOrder%2) vv32="-";
valTooltip.html( "decimal: "+vv +"<br/>quaternary: "+vv4 +"<br/>base32: "+vv32 )
.style('left', d3.event.pageX+"px")
.style('top', d3.event.pageY+"px");
});
d3Digest();
}
init();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment