Created
June 11, 2012 12:41
-
-
Save nat-n/2909907 to your computer and use it in GitHub Desktop.
largest circle fitting onto jax picking regions with debugging visualisation, also uses Raphael and https://github.com/gorhill/Javascript-Voronoi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Jax.getGlobal().ApplicationHelper = Jax.Helper.create | |
patch_world: -> | |
Jax.World.prototype.find_region_centers = () -> | |
context = this.context | |
w = context.canvas.width | |
h = context.canvas.height | |
f = 4 | |
wf = w*f | |
data = new Uint8Array(w*h*4) | |
pickBuffer = new Jax.Framebuffer | |
width: w | |
height: h | |
depth: true | |
pickBuffer.bind context, () -> | |
pickBuffer.viewport(context) | |
context.gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) | |
context.gl.disable(GL_BLEND) | |
context.world.render({material:"picking"}) | |
context.gl.readPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data) | |
data = data.data if data.data | |
# restore the visible viewport and blending | |
context.gl.viewport 0, 0, w, h | |
context.gl.enable GL_BLEND | |
# find visible border pixels by region (randomly select half of one side of each border to speed things up a little) | |
borders_sites = [] | |
for i in [0...data.length] by f | |
gi = i+1 | |
if data[gi] and data[gi-f] != data[gi] or data[gi] != data[gi+wf] && Math.random()<0.5 # is border | |
quater_i = Math.floor(i/4) | |
borders_sites.push {x:quater_i%w, y:Math.ceil(quater_i/w)} | |
V = new Voronoi() | |
bbox = {xl:0, xr:w, yt:0, yb:h} | |
diagram = V.compute(borders_sites, bbox) | |
debug_paper = Raphael(648,8,w,h) | |
console.log diagram | |
centers = {} | |
# extract intersection points keeping only the best one for each region | |
for edge in diagram.edges | |
x = edge.va.x | |
y = edge.va.y | |
# skip borders | |
continue if x == bbox.xl || x == bbox.xr || y == bbox.yt || y == bbox.yb || !edge.lSite | |
# determine site distance (all sites should be at the same distance) | |
d = Math.sqrt(Math.pow(x-edge.lSite.x,2)+Math.pow(y-edge.lSite.y,2)) | |
# determine region (green value) at this point | |
continue unless r = data[Math.floor(y)*w*f + Math.floor(x)*f + 1] | |
debug_paper.rect(edge.lSite.x-0.5,h-edge.lSite.y-0.5,1,1).attr(opacity: 0.2) # draw border pixel over debug canvas | |
continue unless d > 5 # skip tiny edges | |
#debug_paper.path([["M", edge.va.x, h-edge.va.y], ["L", edge.vb.x, h-edge.vb.y]]).attr(opacity: 0.1, fill: "red") | |
centers[r] = centers[r] || {x:x, y:h-y, d:d} | |
if d > centers[r].d | |
centers[r] = {x:x, y:h-y, d:d} | |
for r of centers | |
debug_paper.circle(centers[r].x,centers[r].y,centers[r].d) # draw largest circle over debug canvas | |
centers[r].region = this.getObject(r) | |
# show pickBuffer | |
debug_context = document.getElementById("debug").getContext('2d') | |
imagedata = debug_context.getImageData 0, 0, w, h | |
# data needs to be flipped vertically as it's loaded into imagedata | |
bytesPerLine = w*4 | |
dr = data.length | |
for r in [0...data.length] by bytesPerLine | |
dr -= bytesPerLine | |
for c in [0...w*4] by 4 | |
di = dr+c | |
i = r+c | |
imagedata.data[i] = data[di] | |
imagedata.data[i+1] = data[di+1] | |
imagedata.data[i+2] = data[di+2]*2 | |
imagedata.data[i+3] = data[di+3] | |
debug_context.putImageData imagedata, 0, 0 | |
return centers |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment