OLD | NEW |
| (Empty) |
1 <!-- bezier clip visualizer --> | |
2 <html> | |
3 <head> | |
4 <div style="height:0"> | |
5 | |
6 <div id="clip1"> | |
7 (gdb) p smaller | |
8 $2 = {{ | |
9 x = 0.91292418204644155, | |
10 y = 0.41931201426549197 | |
11 }, { | |
12 x = 0.70491388044579517, | |
13 y = 0.64754305977710236 | |
14 }, { | |
15 x = 0, | |
16 y = 1 | |
17 }} | |
18 (gdb) p larger | |
19 $3 = {{ | |
20 x = 0.21875, | |
21 y = 0.765625 | |
22 }, { | |
23 x = 0.125, | |
24 y = 0.875 | |
25 }, { | |
26 x = 0, | |
27 y = 1 | |
28 }} | |
29 (gdb) p distance2y | |
30 $1 = {{ | |
31 x = 0, | |
32 y = 0.080355482722450078 | |
33 }, { | |
34 x = 0.5, | |
35 y = 0.038383741101172597 | |
36 }, { | |
37 x = 1, | |
38 y = 0 | |
39 }} | |
40 </div> | |
41 | |
42 <div id="quad21a"> | |
43 bezier_clip q1=(0,0 1,0 0,2) q2=(0.5,0.25 0.5,0.5 0,1) minT=0 maxT=1 | |
44 </div> | |
45 <div id="quad21b"> | |
46 bezier_clip q1=(0.5,0.25 0.5,0.375 0.375,0.5625) q2=(0,0 1,0 0,2) minT=0.3 maxT=
0.78125 | |
47 </div> | |
48 <div id="quad21c"> | |
49 bezier_clip q1=(0.42,0.18 0.6125,0.46875 0.341796875,1.22070312) q2=(0.5,0.25 0.
5,0.375 0.375,0.5625) minT=0 maxT=0.926710098 | |
50 </div> | |
51 <div id="quad21d"> | |
52 bezier_clip q1=(0.5,0.25 0.5,0.307919381 0.473162762,0.379257381) q2=(0.42,0.18
0.6125,0.46875 0.341796875,1.22070312) minT=0.187231244 maxT=0.729263299 | |
53 </div> | |
54 <div id="quad21e"> | |
55 bezier_clip q1=(0.475846194,0.304363878 0.53317904,0.507883959 0.454423387,0.847
492538) q2=(0.5,0.25 0.5,0.307919381 0.473162762,0.379257381) minT=0 maxT=1 | |
56 </div> | |
57 <div id="quad21f"> | |
58 bezier_clip q1=(0.493290691,0.311274036 0.486581381,0.343588381 0.473162762,0.37
9257381) q2=(0.475846194,0.304363878 0.53317904,0.507883959 0.454423387,0.847492
538) minT=0.0828748517 maxT=0.150086861 | |
59 </div> | |
60 | |
61 <div id="quad21g"> | |
62 (gdb) p smaller | |
63 $1 = {{ | |
64 x = 0.48441440743366754, | |
65 y = 0.33903196011243797 | |
66 }, { | |
67 x = 0.48750982503868118, | |
68 y = 0.35346899178071778 | |
69 }, { | |
70 x = 0.48999046908865357, | |
71 y = 0.368520797004039 | |
72 }} | |
73 (gdb) p larger | |
74 $2 = {{ | |
75 x = 0.49329069058425024, | |
76 y = 0.31127403581536672 | |
77 }, { | |
78 x = 0.48658138116850047, | |
79 y = 0.34358838107698753 | |
80 }, { | |
81 x = 0.47316276233700094, | |
82 y = 0.37925738104648321 | |
83 }} | |
84 </div> | |
85 | |
86 <div id="quad36"> | |
87 (gdb) p fQ | |
88 $2 = {{ | |
89 x = 1.8883839294261275, | |
90 y = 2.1108590606904345 | |
91 }, { | |
92 x = 1.888463903363252, | |
93 y = 2.1111576060205435 | |
94 }, { | |
95 x = 1.8885438199983176, | |
96 y = 2.1114561800016824 | |
97 }} | |
98 (gdb) p rh.fQ | |
99 $3 = {{ | |
100 x = 1.8883839294260976, | |
101 y = 2.1108590606903377 | |
102 }, { | |
103 x = 1.8886366953645748, | |
104 y = 2.1109850143489544 | |
105 }, { | |
106 x = 1.8888888888888888, | |
107 y = 2.1111111111111112 | |
108 }} | |
109 (gdb) | |
110 </div> | |
111 | |
112 <div id="quad37"> | |
113 {{x = 360.048828125, y = 229.2578125}, {x = 360.048828125, y = 224.4140625}, {x
= 362.607421875, y = 221.3671875}} | |
114 {{x = 362.607421875, y = 221.3671875}, {x = 365.166015625, y = 218.3203125}, {x
= 369.228515625, y = 218.3203125}} | |
115 </div> | |
116 | |
117 <div id="quad38"> | |
118 $2 = {{fX = 369.969421, fY = 137.94809}, {fX = 383.982849, fY = 121.260353}, {fX
= 406.233154, fY = 121.260353}} | |
119 $4 = {{fX = 406.232788, fY = 121.260353}, {fX = 409.441956, fY = 121.260353}, {f
X = 412.972046, fY = 121.795212}} | |
120 </div> | |
121 | |
122 <div id="quad39"> | |
123 {{x = 406.233154296875, y = 121.26035308837891}, {x = 406.23153587045397, y = 12
1.26035308837891}, {x = 406.22991748761177, y = 121.26035317666889}}, | |
124 {{x = 406.23295158013377, y = 121.26035308872596}, {x = 406.2328698329315, y = 1
21.26035308837889}, {x = 406.2327880859375, y = 121.26035308837891}}, | |
125 </div> | |
126 | |
127 </div> | |
128 | |
129 <script type="text/javascript"> | |
130 | |
131 var testDivs = [ | |
132 quad56, | |
133 quad39, | |
134 quad38, | |
135 quad37, | |
136 quad36, | |
137 quad21g, | |
138 quad21a, | |
139 quad21b, | |
140 quad21c, | |
141 quad21d, | |
142 quad21e, | |
143 quad21f, | |
144 clip1, | |
145 ]; | |
146 | |
147 var scale, columns, rows, xStart, yStart; | |
148 | |
149 var ticks = 10; | |
150 var at_x = 13 + 0.5; | |
151 var at_y = 13 + 0.5; | |
152 var init_decimal_places = 1; // make this 3 to show more precision | |
153 var decimal_places; | |
154 var tests = []; | |
155 var testTitles = []; | |
156 var testIndex = 0; | |
157 var ctx; | |
158 var fat1 = true; | |
159 var fat2 = false; | |
160 var ctl1 = true; | |
161 var ctl2 = false; | |
162 var ctlPts1 = true; | |
163 var ctlPts2 = false; | |
164 var minScale = 1; | |
165 var subscale = 1; | |
166 | |
167 function parse(test, title) { | |
168 var curveStrs = test.split("{{"); | |
169 if (curveStrs.length == 1) | |
170 curveStrs = test.split("=("); | |
171 var pattern = /[a-z$=]?-?\d+\.*\d*/g; | |
172 var curves = []; | |
173 for (var c in curveStrs) { | |
174 var curveStr = curveStrs[c]; | |
175 var points = curveStr.match(pattern); | |
176 var pts = []; | |
177 for (var wd in points) { | |
178 var num = parseFloat(points[wd]); | |
179 if (isNaN(num)) continue; | |
180 pts.push(num); | |
181 } | |
182 if (pts.length > 0) | |
183 curves.push(pts); | |
184 } | |
185 if (curves.length >= 2) { | |
186 tests.push(curves); | |
187 testTitles.push(title); | |
188 } | |
189 } | |
190 | |
191 function init(test) { | |
192 var canvas = document.getElementById('canvas'); | |
193 if (!canvas.getContext) return; | |
194 canvas.width = window.innerWidth - at_x; | |
195 canvas.height = window.innerHeight - at_y; | |
196 ctx = canvas.getContext('2d'); | |
197 var xmin = Infinity; | |
198 var xmax = -Infinity; | |
199 var ymin = Infinity; | |
200 var ymax = -Infinity; | |
201 for (var curves in test) { | |
202 var curve = test[curves]; | |
203 var last = curve.length; | |
204 for (var idx = 0; idx < last; idx += 2) { | |
205 xmin = Math.min(xmin, curve[idx]); | |
206 xmax = Math.max(xmax, curve[idx]); | |
207 ymin = Math.min(ymin, curve[idx + 1]); | |
208 ymax = Math.max(ymax, curve[idx + 1]); | |
209 } | |
210 } | |
211 subscale = 1; | |
212 decimal_places = init_decimal_places; | |
213 if (xmax != xmin && ymax != ymin) { | |
214 while ((xmax - xmin) * subscale < 0.1 && (ymax - ymin) * subscale < 0.1)
{ | |
215 subscale *= 10; | |
216 decimal_places += 1; | |
217 // if (subscale > 100000) { | |
218 // break; | |
219 // } | |
220 } | |
221 } | |
222 columns = Math.ceil(xmax * subscale) - Math.floor(xmin * subscale) + 1; | |
223 rows = Math.ceil(ymax * subscale) - Math.floor(ymin * subscale) + 1; | |
224 | |
225 xStart = Math.floor(xmin * subscale) / subscale; | |
226 yStart = Math.floor(ymin * subscale) / subscale; | |
227 var hscale = ctx.canvas.width / columns / ticks; | |
228 var vscale = ctx.canvas.height / rows / ticks; | |
229 minScale = Math.floor(Math.min(hscale, vscale)); | |
230 scale = minScale * subscale; | |
231 // while (columns < 1000 && rows < 1000) { | |
232 // columns *= 2; | |
233 // rows *= 2; | |
234 // } | |
235 } | |
236 | |
237 function drawPoint(px, py, xoffset, yoffset, unit) { | |
238 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places); | |
239 var _px = px * unit + xoffset; | |
240 var _py = py * unit + yoffset; | |
241 ctx.beginPath(); | |
242 ctx.arc(_px, _py, 3, 0, Math.PI*2, true); | |
243 ctx.closePath(); | |
244 ctx.fill(); | |
245 ctx.fillText(label, _px + 5, _py); | |
246 } | |
247 | |
248 function draw(test, title, _at_x, _at_y, scale) { | |
249 ctx.fillStyle = "rgba(0,0,0, 0.1)"; | |
250 ctx.font = "normal 50px Arial"; | |
251 ctx.fillText(title, 50, 50); | |
252 ctx.font = "normal 10px Arial"; | |
253 | |
254 var unit = scale * ticks; | |
255 ctx.lineWidth = 1; | |
256 var i; | |
257 for (i = 0; i <= rows * ticks; ++i) { | |
258 ctx.strokeStyle = (i % ticks) != 0 ? "rgb(160,160,160)" : "black"; | |
259 ctx.beginPath(); | |
260 ctx.moveTo(_at_x + 0, _at_y + i * minScale); | |
261 ctx.lineTo(_at_x + unit * columns, _at_y + i * minScale); | |
262 ctx.stroke(); | |
263 } | |
264 for (i = 0; i <= columns * ticks; ++i) { | |
265 ctx.strokeStyle = (i % ticks) != 0 ? "rgb(160,160,160)" : "black"; | |
266 ctx.beginPath(); | |
267 ctx.moveTo(_at_x + i * minScale, _at_y + 0); | |
268 ctx.lineTo(_at_x + i * minScale, _at_y + unit * rows); | |
269 ctx.stroke(); | |
270 } | |
271 | |
272 var xoffset = xStart * -unit + _at_x; | |
273 var yoffset = yStart * -unit + _at_y; | |
274 | |
275 ctx.fillStyle = "rgb(40,80,60)" | |
276 for (i = 0; i <= columns; i += (1 / ticks)) | |
277 { | |
278 num = xStart + i / subscale; | |
279 ctx.fillText(num.toFixed(decimal_places), xoffset + num * unit - 5, 10); | |
280 } | |
281 for (i = 0; i <= rows; i += (1 / ticks)) | |
282 { | |
283 num = yStart + i / subscale; | |
284 ctx.fillText(num.toFixed(decimal_places), 0, yoffset + num * unit + 0); | |
285 } | |
286 | |
287 // draw curve 1 and 2 | |
288 var curves, pts; | |
289 for (curves in test) { | |
290 var curve = test[curves]; | |
291 ctx.beginPath(); | |
292 ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit); | |
293 switch (curve.length) { | |
294 case 6: | |
295 ctx.quadraticCurveTo( | |
296 xoffset + curve[2] * unit, yoffset + curve[3] * unit, | |
297 xoffset + curve[4] * unit, yoffset + curve[5] * unit); | |
298 break; | |
299 case 8: | |
300 ctx.bezierCurveTo( | |
301 xoffset + curve[2] * unit, yoffset + curve[3] * unit, | |
302 xoffset + curve[4] * unit, yoffset + curve[5] * unit, | |
303 xoffset + curve[6] * unit, yoffset + curve[7] * unit); | |
304 break; | |
305 } | |
306 if (curves == 2) ctx.strokeStyle = curves ? "red" : "blue"; | |
307 ctx.stroke(); | |
308 ctx.strokeStyle = "rgba(0,0,0, 0.3)"; | |
309 ctx.beginPath(); | |
310 ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit); | |
311 ctx.lineTo(xoffset + curve[2] * unit, yoffset + curve[3] * unit); | |
312 ctx.lineTo(xoffset + curve[4] * unit, yoffset + curve[5] * unit); | |
313 if (curve.length == 8) | |
314 ctx.lineTo(xoffset + curve[6] * unit, yoffset + curve[7] * unit); | |
315 ctx.stroke(); | |
316 } | |
317 // optionally draw fat lines for curve | |
318 if (fat1) | |
319 drawFat(test[0], xoffset, yoffset, unit); | |
320 if (fat2) | |
321 drawFat(test[1], xoffset, yoffset, unit); | |
322 if (ctl1) | |
323 drawCtl(test[0], xoffset, yoffset, unit); | |
324 if (ctl2) | |
325 drawCtl(test[1], xoffset, yoffset, unit); | |
326 if (ctlPts1) | |
327 drawCtlPts(test[0], xoffset, yoffset, unit); | |
328 if (ctlPts2) | |
329 drawCtlPts(test[1], xoffset, yoffset, unit); | |
330 } | |
331 | |
332 function drawCtl(curve, xoffset, yoffset, unit) { | |
333 var last = curve.length - 2; | |
334 ctx.strokeStyle = "rgba(0,0,0, 0.5)"; | |
335 ctx.beginPath(); | |
336 ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit); | |
337 ctx.lineTo(xoffset + curve[2] * unit, yoffset + curve[3] * unit); | |
338 ctx.lineTo(xoffset + curve[4] * unit, yoffset + curve[5] * unit); | |
339 ctx.stroke(); | |
340 } | |
341 | |
342 function drawCtlPts(curve, xoffset, yoffset, unit) { | |
343 drawPoint(curve[0], curve[1], xoffset, yoffset, unit); | |
344 drawPoint(curve[2], curve[3], xoffset, yoffset, unit); | |
345 drawPoint(curve[4], curve[5], xoffset, yoffset, unit); | |
346 } | |
347 | |
348 function drawFat(curve, xoffset, yoffset, unit) { | |
349 var last = curve.length - 2; | |
350 ctx.strokeStyle = "rgba(0,0,0, 0.5)"; | |
351 ctx.beginPath(); | |
352 ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit); | |
353 ctx.lineTo(xoffset + curve[last] * unit, yoffset + curve[last + 1] * unit); | |
354 ctx.stroke(); | |
355 // draw line parallel to end points through control points | |
356 var dx = curve[last] - curve[0]; | |
357 var dy = curve[last + 1] - curve[1]; | |
358 drawParallelLine(curve[2], curve[3], dx, dy, xoffset, yoffset, unit); | |
359 if (curve.length == 8) | |
360 drawParallelLine(curve[4], curve[5], dx, dy, xoffset, yoffset, unit); | |
361 } | |
362 | |
363 function drawParallelLine(x, y, dx, dy, xoffset, yoffset, unit) { | |
364 var x1 = x - dx; | |
365 var y1 = y - dy; | |
366 var x2 = x + dx; | |
367 var y2 = y + dy; | |
368 ctx.beginPath(); | |
369 ctx.moveTo(xoffset + x1 * unit, yoffset + y1 * unit); | |
370 ctx.lineTo(xoffset + x2 * unit, yoffset + y2 * unit); | |
371 ctx.stroke(); | |
372 } | |
373 | |
374 function drawTop() { | |
375 init(tests[testIndex]); | |
376 redraw(); | |
377 } | |
378 | |
379 function redraw() { | |
380 ctx.beginPath(); | |
381 ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height); | |
382 ctx.fillStyle="white"; | |
383 ctx.fill(); | |
384 draw(tests[testIndex], testTitles[testIndex], at_x, at_y, scale); | |
385 } | |
386 | |
387 function doKeyPress(evt) { | |
388 var char = String.fromCharCode(evt.charCode); | |
389 switch (char) { | |
390 case 'c': | |
391 ctl2 ^= true; | |
392 if (ctl2 == false) | |
393 ctl1 ^= true; | |
394 drawTop(); | |
395 break; | |
396 case 'd': | |
397 ctlPts2 ^= true; | |
398 if (ctlPts2 == false) | |
399 ctlPts1 ^= true; | |
400 drawTop(); | |
401 break; | |
402 case 'f': | |
403 fat2 ^= true; | |
404 if (fat2 == false) | |
405 fat1 ^= true; | |
406 drawTop(); | |
407 break; | |
408 case 'N': | |
409 testIndex += 9; | |
410 case 'n': | |
411 if (++testIndex >= tests.length) | |
412 testIndex = 0; | |
413 mouseX = Infinity; | |
414 drawTop(); | |
415 break; | |
416 case 'P': | |
417 testIndex -= 9; | |
418 case 'p': | |
419 if (--testIndex < 0) | |
420 testIndex = tests.length - 1; | |
421 mouseX = Infinity; | |
422 drawTop(); | |
423 break; | |
424 } | |
425 } | |
426 | |
427 function handleMouseClick() { | |
428 } | |
429 | |
430 function handleMouseOver() { | |
431 } | |
432 | |
433 function start() { | |
434 for (i = 0; i < testDivs.length; ++i) { | |
435 var title = testDivs[i].id.toString(); | |
436 var str = testDivs[i].firstChild.data; | |
437 parse(str, title); | |
438 } | |
439 drawTop(); | |
440 window.addEventListener('keypress', doKeyPress, true); | |
441 window.onresize = function() { | |
442 drawTop(); | |
443 } | |
444 } | |
445 | |
446 </script> | |
447 </head> | |
448 | |
449 <body onLoad="start();"> | |
450 <canvas id="canvas" width="750" height="500" | |
451 onmousemove="handleMouseOver()" | |
452 onclick="handleMouseClick()" | |
453 ></canvas > | |
454 </body> | |
455 </html> | |
OLD | NEW |