Advertisement
Guest User

Untitled

a guest
May 28th, 2015
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.97 KB | None | 0 0
  1. var fc = require('fc');
  2. var center = require('ctx-translate-center');
  3. var poly = require('ctx-render-polyline');
  4. var points = require('ctx-render-points');
  5. var bounds2 = require('2d-bounds');
  6. var gridlines = require('ctx-render-grid-lines');
  7. var isect = require('robust-segment-intersect');
  8. var createSDF = require('sdf-polygon-2d');
  9. var area = require('2d-polygon-area');
  10. var segseg = require('segseg');
  11. var sign = require('signum');
  12.  
  13. var TAU = Math.PI*2;
  14. var min = Math.min;
  15. var max = Math.max;
  16. var abs = Math.abs;
  17. var polyline = [
  18. [-10, -100],
  19. [-100, -100],
  20. [-100, -10],
  21. [-100, 100],
  22. [0, 0],
  23.  
  24. [100, 0],
  25. ];
  26.  
  27.  
  28. window.dump = function() {
  29. console.log(JSON.stringify(polyline, null, ' '))
  30. }
  31.  
  32. function pointinbox(point, minx, miny, maxx, maxy) {
  33. var x = point[0];
  34. var y = point[1];
  35. return x >= minx && x <= maxx && y >= miny && y <= maxy;
  36. }
  37.  
  38. function line(ctx, x1, y1, x2, y2, color) {
  39. ctx.beginPath();
  40. ctx.moveTo(x1, y1);
  41. ctx.lineTo(x2, y2);
  42. ctx.strokeStyle = color || "grey"
  43. ctx.stroke();
  44. }
  45.  
  46. function midpoint(c, n) {
  47. return [(c[0] + n[0])/2, (c[1] + n[1])/2];
  48. }
  49.  
  50. function closest(p, c, target) {
  51.  
  52. var pd = Math.abs(p-target);
  53. var cd = Math.abs(c-target);
  54.  
  55. return pd < cd ? 1 : 0;
  56. }
  57.  
  58.  
  59.  
  60. // a crossing is a isosurface zero crossing on a gridline
  61. // it is stored in this array as 'x,y' : [start, end]
  62. var crossingMap = {}
  63.  
  64.  
  65.  
  66.  
  67.  
  68. function gridfill(ctx, r, minx, miny, maxx, maxy, results) {
  69. var lx = min(minx, maxx);
  70. var ly = min(miny, maxy);
  71. var ux = max(minx, maxx);
  72. var uy = max(miny, maxy);
  73.  
  74. var offset = 1;
  75. var offset2 = offset * 2
  76. var inside = 'hsla(114, 19%, 25%, 1)';
  77. var border = 'hsla(228, 19%, 25%, 1)';
  78. var outside = 'hsla(0, 19%, 25%, .7)';
  79. var sdf = createSDF([polyline])
  80. var block = [0, 0];
  81. var r2 = (r/2)|0;
  82.  
  83. var contour = [];
  84. // a map of x,y => [index]
  85. var map = {}
  86.  
  87. for (var x = lx; x < ux; x+=r) {
  88. for (var y = ly; y < uy; y+=r) {
  89. var oy = min(r - offset2, uy - y);
  90. var ox = min(r - offset2, ux - x);
  91. var dist = sdf(x + r2, y + r2);
  92.  
  93. // TODO: test all 4 corners and see if an edge
  94. // goes through this box. If so, split the edge (how?)
  95. // and continue on..
  96.  
  97. var res = [false, false, false, false];
  98.  
  99. /*
  100. test the corners of the box
  101.  
  102. 0-------1
  103. | |
  104. | |
  105. | |
  106. 3-------2
  107. */
  108.  
  109.  
  110. var tests = [[x, y], [x+r, y], [x+r, y+r], [x, y+r]];
  111. var potentialCrossings = [
  112. [0, 1],
  113. [1, 2],
  114. [2, 3],
  115. [3, 0]
  116. ];
  117.  
  118. var distances = tests.map(function(a) {
  119. return sdf(a[0], a[1]);
  120. });
  121.  
  122.  
  123. var crossings = potentialCrossings.map(function(t) {
  124. if (sign(distances[t[0]] - r) !== sign(distances[t[1]] - r)) {
  125. return true;
  126. } else {
  127. return false;
  128. }
  129. })
  130.  
  131. // console.log(crossings);
  132.  
  133.  
  134. crossings.map(function(c, i) {
  135. if (c) {
  136. var edge = [
  137.  
  138. [
  139. tests[potentialCrossings[i][0]][0],
  140. tests[potentialCrossings[i][0]][1],
  141. distances[potentialCrossings[i][0]]
  142. ],
  143. [
  144. tests[potentialCrossings[i][1]][0],
  145. tests[potentialCrossings[i][1]][1],
  146. distances[potentialCrossings[i][1]]
  147. ],
  148. // tests[potentialCrossings[i][1]].concat()
  149. ];
  150.  
  151. // line(ctx, edge[0][0], edge[0][1], edge[1][0], edge[1][1]);
  152. // ctx.strokeStyle = "rgba(255, 255, 255, .01)";
  153. // ctx.stroke();
  154.  
  155.  
  156. // follow the rabbit and bisect the weird interval we've setup
  157. var ssss = 100, d = c, updateIndex;
  158. var lastDistance = Infinity;
  159. var mid;
  160. while(ssss--) {
  161. // bisect the current edge
  162. mid = midpoint(edge[0], edge[1]);
  163. var midpointDistance = sdf(mid[0], mid[1]);
  164. if (Math.abs(midpointDistance - r) < .000001 || midpointDistance > lastDistance) {
  165. found = true;
  166. ctx.beginPath()
  167. ctx.arc(mid[0], mid[1], 5, 0, Math.PI*2, false);
  168. ctx.fillStyle = "green";
  169. ctx.fill();
  170.  
  171. contour.push(mid);
  172. break;
  173. }
  174.  
  175. updateIndex = closest(edge[0][2], edge[1][2], r);
  176. edge[updateIndex][0] = mid[0];
  177. edge[updateIndex][1] = mid[1];
  178. edge[updateIndex][2] = midpointDistance;
  179. }
  180. if (ssss <= 0) {
  181. ctx.beginPath()
  182. ctx.arc(mid[0], mid[1], 5, 0, Math.PI*2, false);
  183. ctx.fillStyle = "green";
  184. ctx.fill();
  185. }
  186. }
  187. })
  188. }
  189. }
  190.  
  191.  
  192. // TODO: join end to end these contours
  193.  
  194. poly(ctx, contour);
  195. ctx.strokeStyle="green"
  196. ctx.stroke();
  197. }
  198.  
  199.  
  200. var r = 60;
  201. var b = [0, 0, 0, 0];
  202. var ctx = fc(function() {
  203. ctx.clear();
  204. center(ctx);
  205.  
  206. bounds2(polyline, b);
  207.  
  208. b[0] = ((Math.floor(b[0]/r) * r) - r*2)|0;
  209. b[1] = ((Math.floor(b[1]/r) * r) - r*2)|0;
  210. b[2] = ((Math.ceil(b[2]/r) * r) + r*2)|0;
  211. b[3] = ((Math.ceil(b[3]/r) * r) + r*2)|0;
  212.  
  213.  
  214.  
  215. var gridspacing = r;
  216. ctx.beginPath();
  217. gridlines(ctx, gridspacing, b[0], b[1], b[2], b[3]);
  218. ctx.strokeStyle = "rgba(222, 228, 244, .1)";
  219. ctx.stroke();
  220.  
  221. ctx.strokeStyle = "grey";
  222. var pad = 3;
  223. ctx.strokeRect(b[0]-pad, b[1]-pad, Math.ceil(b[2] - b[0]) + pad*2, Math.ceil(b[3] - b[1]) + pad*2) ;
  224. var results = [];
  225. gridfill(ctx, gridspacing, b[0], b[1], b[2], b[3], results);
  226.  
  227. ctx.beginPath();
  228. poly(ctx, polyline);
  229. ctx.closePath();
  230. ctx.strokeStyle = "hsl(17, 80%, 56%)";
  231. ctx.stroke();
  232.  
  233. ctx.beginPath();
  234. points(ctx, 3, polyline)
  235. ctx.fillStyle = "hsl(49, 60%, 56%)";
  236. ctx.fill();
  237.  
  238. if (mouse.dragging || mouse.near) {
  239. ctx.beginPath();
  240. var p = mouse.dragging === false ? mouse.near : mouse.down;
  241. var sr = 10;
  242. ctx.moveTo(p[0] + sr, p[1])
  243. ctx.arc(p[0], p[1], sr, 0, TAU, false);
  244. ctx.strokeStyle = 'hsl(49, 60%, 56%)';
  245. ctx.stroke();
  246. }
  247. results.forEach(function(seg) {
  248. if(seg.length < 2) {
  249. ctx.fillStyle = "red";
  250. ctx.fillRect(seg[0][2] + r/4, seg[0][3] + r/4, r/2, r/2);
  251.  
  252.  
  253. return;
  254. }
  255. ctx.strokeStyle = "green"
  256. line(ctx, seg[0][0], seg[0][1], seg[1][0], seg[1][1], 'red');
  257.  
  258. // ctx.beginPath();
  259. // ctx.moveTo(seg[0][0] + r, seg[0][1]);
  260. // ctx.arc(seg[0][0], seg[0][1], r, 0, Math.PI*2, false)
  261. // ctx.strokeStyle = '#red';
  262. // ctx.stroke();
  263.  
  264. // ctx.beginPath();
  265. // ctx.moveTo(seg[1][0] + r, seg[1][1]);
  266. // ctx.arc(seg[1][0], seg[1][1], r, 0, Math.PI*2, false)
  267. // ctx.strokeStyle = 'green';
  268. // ctx.stroke();
  269.  
  270. // var mid = midpoint(seg[0], seg[1]);
  271. // ctx.beginPath();
  272. // ctx.moveTo(mid[0] + r, mid[1]);
  273. // ctx.arc(mid[0], mid[1], r, 0, Math.PI*2, false)
  274. // ctx.strokeStyle = 'orange';
  275. // ctx.stroke();
  276.  
  277.  
  278. });
  279.  
  280. // poly(ctx,);
  281. // ctx.lineWidth = 10;
  282. // ctx.strokeStyle = "red";
  283. // ctx.stroke();
  284. return;
  285. var chain = results.slice();
  286. console.log('chain', JSON.stringify(chain, null, ' '))
  287. chain.sort(function(a, b) {
  288. return a[0][0] - b[0][0];
  289. });
  290.  
  291. function next(a, b) {
  292. // TODO: there are some degenerate cases here, I think it's just a matter
  293. // of the path not being closed
  294.  
  295. // console.log('diffs', Math.abs(a[0][0] - b[0][0]), Math.abs(a[0][1] - b[0][1]), Math.abs(a[1][0] - b[1][0]), Math.abs(a[1][1] - b[1][1]))
  296.  
  297. return Math.abs(a[0][0] - b[0][0]) < r ||
  298. Math.abs(a[0][1] - b[0][1]) < r ||
  299. Math.abs(a[1][0] - b[1][0]) < r ||
  300. Math.abs(a[1][1] - b[1][1]) < r
  301. }
  302.  
  303. var last = chain.shift();
  304. var out = [last];
  305. var sentinal = results.length*2;
  306. while(chain.length && sentinal--) {
  307. var l = chain.length;
  308. var found = false;
  309. for (var i=0; i<l; i++) {
  310. if (next(last, chain[i])) {
  311. last = chain.splice(i, 1)[0];
  312. out.push(last);
  313. break;
  314. }
  315. }
  316. }
  317.  
  318. var p = (360/out.length)
  319. var h = 0;
  320. out.map(function(link) {
  321. line(ctx, link[0][0], link[0][1], link[1][0], link[1][1], 'hsla(' + (h+=p) + ', 80%, 50%, .9)');
  322. });
  323.  
  324. });
  325.  
  326. var mouse = {
  327. down: false,
  328. dragging: false,
  329. near: false,
  330. pos: [0, 0]
  331. };
  332.  
  333. function nearPolyline(mouse, polyline) {
  334. var m = mouse.pos;
  335. for (var i=0; i<polyline.length; i++) {
  336. var p = polyline[i];
  337. var dx = p[0]-m[0];
  338. var dy = p[1]-m[1];
  339. var d = Math.sqrt(dx*dx + dy*dy);
  340.  
  341. if (d < min(10, r)) {
  342. return p;
  343. }
  344. }
  345. return false;
  346. }
  347.  
  348. document.addEventListener('mousemove', function(ev) {
  349. mouse.pos[0] = ev.clientX - (ctx.canvas.width/2)|0;
  350. mouse.pos[1] = ev.clientY - (ctx.canvas.height/2)|0;
  351.  
  352. if (mouse.down !== false) {
  353. if (!mouse.dragging) {
  354. mouse.dragging = true;
  355. } else {
  356. var p = mouse.down;
  357. p[0] = mouse.pos[0];
  358. p[1] = mouse.pos[1];
  359. }
  360. } else {
  361. mouse.near = nearPolyline(mouse, polyline);
  362. }
  363. ctx.dirty();
  364. });
  365.  
  366. document.addEventListener('mouseup', function(ev) {
  367. mouse.down = false;
  368. mouse.dragging = false;
  369. ctx.dirty();
  370. });
  371.  
  372. document.addEventListener('mousedown', function(ev) {
  373. mouse.down = nearPolyline(mouse, polyline);
  374. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement