aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/cd.htm
diff options
context:
space:
mode:
authorGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-02-22 21:50:07 +0000
committerGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-02-22 21:50:07 +0000
commitc83c70e911a38aea03db4af8dd9841d0d77bd129 (patch)
treec957cfecc8e073f178dc13aae8a16d9bd3653e8c /experimental/Intersection/cd.htm
parentf8d7d2731318cdf510ab68e6b3f5ec68ab22c8e2 (diff)
shape ops work in progress
git-svn-id: http://skia.googlecode.com/svn/trunk@7836 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental/Intersection/cd.htm')
-rw-r--r--experimental/Intersection/cd.htm517
1 files changed, 517 insertions, 0 deletions
diff --git a/experimental/Intersection/cd.htm b/experimental/Intersection/cd.htm
new file mode 100644
index 0000000000..2e43022d7e
--- /dev/null
+++ b/experimental/Intersection/cd.htm
@@ -0,0 +1,517 @@
+<html>
+<head>
+<div style="height:0">
+
+<div id="test1">
+computeDelta c1=(0,1 1,6 1,0 2,0) t1=0.0166500365 scale1=1 c2=(0,1 0,2 1,0 6,1) t2=0.126935168 scale2=1
+cubicTangent t=0.0166500365 tangent=(-2.85263545,-12.6745554 2.95089079,15.1559166) pt=(0.0491276698 1.24068063) dxy=(2.90176312 13.915236)
+cubicTangent t=0.126935168 tangent=(-0.852150487,0.242871519 0.961097194,2.2532568) pt=(0.0544733534 1.24806416) dxy=(0.90662384 1.00519264)
+cubicDelta tangent=(-0.00039510851,-0.00189471984 0.0495227783,1.24257535) intersectLen=0.00193547772 tangentLen=14.2145708 scale=0.00390625 result=0.00404241153
+cubicDelta tangent=(0.00495057512,0.00548880522 0.0495227783,1.24257535) intersectLen=0.00739156118 tangentLen=1.35365395 scale=0.00390625 result=0.00936670107
+</div>
+
+<div id="test2">
+computeDelta c1=(0,1 0,2 1,0 6,1) t1=0.121215914 scale1=0.0187334021 c2=(0,1 1,6 1,0 2,0) t2=0.0167515231 scale2=0.00808482306
+cubicTangent t=0.121215914 tangent=(-0.810112087,0.159501524 0.908958243,2.32468734) pt=(0.0494230781 1.24209443) dxy=(0.859535165 1.08259291)
+cubicTangent t=0.0167515231 tangent=(-2.85175241,-12.6666182 2.95059667,15.1508033) pt=(0.0494221303 1.24209251) dxy=(2.90117454 13.9087108)
+cubicDelta tangent=(7.4284882e-07,9.35625319e-07 0.0494223352,1.2420935) intersectLen=1.19466276e-06 tangentLen=1.38231983 scale=7.31773521e-05 result=7.40415969e-05
+cubicDelta tangent=(-2.04951629e-07,-9.82572016e-07 0.0494223352,1.2420935) intersectLen=1.00371955e-06 tangentLen=14.2080628 scale=3.15813401e-05 result=3.16519844e-05
+</div>
+
+<div id="test3">
+computeDelta c1=(0,1 1,6 1,0 2,0) t1=0.0167458976 scale1=6.33039689e-05 c2=(0,1 0,2 1,0 6,1) t2=0.121141872 scale2=0.000148083194
+cubicTangent t=0.0167458976 tangent=(-2.85180136,-12.6670582 2.95061297,15.1510867) pt=(0.0494058095 1.24201427) dxy=(2.90120716 13.9090724)
+cubicTangent t=0.121141872 tangent=(-0.809569955,0.158411583 0.908288874,2.32561689) pt=(0.0493594591 1.24201424) dxy=(0.858929414 1.08360265)
+cubicDelta tangent=(-1.65436799e-05,-7.93143093e-05 0.0494223532,1.24209358) intersectLen=8.1021312e-05 tangentLen=14.2084235 scale=2.47281129e-07 result=5.94962466e-06
+cubicDelta tangent=(-6.28940702e-05,-7.93454971e-05 0.0494223532,1.24209358) intersectLen=0.000101249059 tangentLen=1.38273441 scale=5.78449976e-07 result=7.38022436e-05
+</div>
+
+</div>
+
+<script type="text/javascript">
+
+var testDivs = [
+ test3,
+ test2,
+ test1,
+];
+
+var scale, columns, rows, xStart, yStart;
+
+var ticks = 10;
+var at_x = 13 + 0.5;
+var at_y = 23 + 0.5;
+var decimal_places = 3;
+var tests = [];
+var testTitles = [];
+var testIndex = 0;
+var ctx;
+var minScale = 1;
+var subscale = 1;
+var curveT = -1;
+var drawCubics = true;
+var drawQuads = true;
+var drawControlLines = true;
+var drawT = true;
+
+var xmin, xmax, ymin, ymax;
+
+function strs_to_nums(strs) {
+ var result = [];
+ for (var idx in strs) {
+ var str = strs[idx];
+ var num = parseFloat(str);
+ if (isNaN(num)) {
+ result.push(str);
+ } else {
+ result.push(num);
+ }
+ }
+ return result;
+}
+
+function construct_regexp(pattern) {
+ var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
+ escape = escape.replace(/PT_VAL/g, "(-?\\d+\\.?\\d*e?-?\\d*),(-?\\d+\\.?\\d*e?-?\\d*)");
+ escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*e?-?\\d*)");
+ escape = escape.replace(/IDX/g, "(\\d+)");
+ escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
+ return new RegExp(escape, 'i');
+}
+
+var COMPUTE_DELTA = 1;
+var CUBIC_TANGENT = 2;
+var CUBIC_DATA = 3;
+
+var DELTA_C1_X1 = 1;
+var DELTA_C1_Y1 = 2;
+var DELTA_C1_X2 = 3;
+var DELTA_C1_Y2 = 4;
+var DELTA_C1_X3 = 5;
+var DELTA_C1_Y3 = 6;
+var DELTA_C1_X4 = 7;
+var DELTA_C1_Y4 = 8;
+var DELTA_T1 = 9;
+var DELTA_SCALE1 = 10;
+var DELTA_C2_X1 = 11;
+var DELTA_C2_Y1 = 12;
+var DELTA_C2_X2 = 13;
+var DELTA_C2_Y2 = 14;
+var DELTA_C2_X3 = 15;
+var DELTA_C2_Y3 = 16;
+var DELTA_C2_X4 = 17;
+var DELTA_C2_Y4 = 18;
+var DELTA_T2 = 19;
+var DELTA_SCALE2 = 20;
+
+var TANGENT_T = 1;
+var TANGENT_TANGENT_X1 = 2;
+var TANGENT_TANGENT_Y1 = 3;
+var TANGENT_TANGENT_X2 = 4;
+var TANGENT_TANGENT_Y2 = 5;
+var TANGENT_PT_X = 6;
+var TANGENT_PT_Y = 7;
+var TANGENT_DXY_X = 8;
+var TANGENT_DXY_Y = 9;
+
+var CUBIC_TANGENT_X1 = 1;
+var CUBIC_TANGENT_Y1 = 2;
+var CUBIC_TANGENT_X2 = 3;
+var CUBIC_TANGENT_Y2 = 4;
+var CUBIC_INTERSECTION_LEN = 5;
+var CUBIC_TANGENT_LEN = 6;
+var CUBIC_SCALE = 7;
+var CUBIC_RESULT = 8;
+
+function parse(test, title) {
+ var compute_delta = construct_regexp(" c1=(PT_VAL PT_VAL PT_VAL PT_VAL)"
+ + " t1=T_VAL scale1=T_VAL c2=(PT_VAL PT_VAL PT_VAL PT_VAL) t2=T_VAL scale2=T_VAL");
+ var cubic_tangent = construct_regexp(" t=T_VAL tangent=(PT_VAL PT_VAL)"
+ + " pt=(T_VAL T_VAL) dxy=(T_VAL T_VAL)");
+ var cubic_data = construct_regexp(" tangent=(PT_VAL PT_VAL)"
+ + " intersectLen=T_VAL tangentLen=T_VAL scale=T_VAL result=T_VAL");
+
+ var cStrs = test.split("computeDelta");
+ var data = [];
+ for (var cs in cStrs) {
+ var str = cStrs[cs];
+ if (str == "\n") {
+ continue;
+ }
+ var tStrs = str.split("cubicTangent");
+ for (var ts in tStrs) {
+ str = tStrs[ts];
+ if (str == "\n") {
+ continue;
+ }
+ var dStrs = str.split("cubicDelta");
+ var dataStrs;
+ for (var ds in dStrs) {
+ str = dStrs[ds];
+ if (str == "\n") {
+ continue;
+ }
+ var lineMatch, lineStrs;
+ if (compute_delta.test(str)) {
+ lineMatch = COMPUTE_DELTA;
+ lineStrs = compute_delta.exec(str);
+ } else if (cubic_tangent.test(str)) {
+ lineMatch = CUBIC_TANGENT;
+ lineStrs = cubic_tangent.exec(str);
+ } else if (cubic_data.test(str)) {
+ lineMatch = CUBIC_DATA;
+ lineStrs = cubic_data.exec(str);
+ } else {
+ continue;
+ }
+ var line = strs_to_nums(lineStrs);
+ data.push(lineMatch);
+ data.push(line);
+ }
+ }
+ }
+ if (data.length >= 1) {
+ tests.push(data);
+ testTitles.push(title);
+ }
+}
+
+function init(test) {
+ var canvas = document.getElementById('canvas');
+ if (!canvas.getContext) return;
+ canvas.width = window.innerWidth - at_x;
+ canvas.height = window.innerHeight - at_y;
+ ctx = canvas.getContext('2d');
+ xmin = Infinity;
+ xmax = -Infinity;
+ ymin = Infinity;
+ ymax = -Infinity;
+ var scanType = -1;
+ for (var scansStr in test) {
+ var scans = parseInt(scansStr);
+ var scan = test[scans];
+ if (scanType == -1) {
+ scanType = scan;
+ continue;
+ }
+ if (scanType == CUBIC_TANGENT) {
+ for (var idx = TANGENT_TANGENT_X1; idx < TANGENT_PT_X; idx += 2) {
+ xmin = Math.min(xmin, scan[idx]);
+ xmax = Math.max(xmax, scan[idx]);
+ ymin = Math.min(ymin, scan[idx + 1]);
+ ymax = Math.max(ymax, scan[idx + 1]);
+ }
+ }
+ scanType = -1;
+ }
+ var testW = xmax - xmin;
+ var testH = ymax - ymin;
+ subscale = 1;
+ if (testW > 1e10 || testH > 1e10) {
+ return;
+ }
+ while (testW * subscale < 0.1 && testH * subscale < 0.1) {
+ subscale *= 10;
+ }
+ while (testW * subscale > 10 && testH * subscale > 10) {
+ subscale /= 10;
+ }
+ calcFromScale();
+}
+
+function calcFromScale() {
+ xStart = Math.floor(xmin * subscale) / subscale;
+ yStart = Math.floor(ymin * subscale) / subscale;
+ var xEnd = Math.ceil(xmin * subscale) / subscale;
+ var yEnd = Math.ceil(ymin * subscale) / subscale;
+ var cCelsW = Math.floor(ctx.canvas.width / 10);
+ var cCelsH = Math.floor(ctx.canvas.height / 10);
+ var testW = xEnd - xStart;
+ var testH = yEnd - yStart;
+ var scaleWH = 1;
+ while (cCelsW > testW * scaleWH * 10 && cCelsH > testH * scaleWH * 10) {
+ scaleWH *= 10;
+ }
+ while (cCelsW * 10 < testW * scaleWH && cCelsH * 10 < testH * scaleWH) {
+ scaleWH /= 10;
+ }
+
+ columns = Math.ceil(xmax * subscale) - Math.floor(xmin * subscale) + 1;
+ rows = Math.ceil(ymax * subscale) - Math.floor(ymin * subscale) + 1;
+
+ var hscale = ctx.canvas.width / columns / ticks;
+ var vscale = ctx.canvas.height / rows / ticks;
+ minScale = Math.floor(Math.min(hscale, vscale));
+ scale = minScale * subscale;
+}
+
+function drawPoint(px, py, xoffset, yoffset, unit) {
+ var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
+ var _px = px * unit + xoffset;
+ var _py = py * unit + yoffset;
+ ctx.beginPath();
+ ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
+ ctx.closePath();
+ ctx.fill();
+ ctx.fillText(label, _px + 5, _py);
+}
+
+function drawTPt(scan, cIdx, tIdx, xoffset, yoffset, unit) {
+ var t = scan[tIdx];
+ var one_t = 1 - t;
+ var one_t2 = one_t * one_t;
+ var a = one_t2 * one_t;
+ var b = 3 * one_t2 * t;
+ var t2 = t * t;
+ var c = 3 * one_t * t2;
+ var d = t2 * t;
+ var x = a * scan[cIdx + 0] + b * scan[cIdx + 2] + c * scan[cIdx + 4] + d * scan[cIdx + 6];
+ var y = a * scan[cIdx + 1] + b * scan[cIdx + 3] + c * scan[cIdx + 5] + d * scan[cIdx + 7];
+ drawPoint(x, y, xoffset, yoffset, unit);
+}
+
+function draw(test, title, scale) {
+ ctx.fillStyle = "rgba(0,0,0, 0.1)";
+ ctx.font = "normal 50px Arial";
+ ctx.fillText(title, 50, 50);
+ ctx.font = "normal 10px Arial";
+
+ var unit = scale * ticks;
+ ctx.lineWidth = 1;
+ var i;
+ for (i = 0; i <= rows * ticks; ++i) {
+ ctx.strokeStyle = (i % ticks) != 0 ? "rgb(200,200,200)" : "black";
+ ctx.beginPath();
+ ctx.moveTo(at_x + 0, at_y + i * minScale);
+ ctx.lineTo(at_x + ticks * columns * minScale, at_y + i * minScale);
+ ctx.stroke();
+ }
+ for (i = 0; i <= columns * ticks; ++i) {
+ ctx.strokeStyle = (i % ticks) != 0 ? "rgb(200,200,200)" : "black";
+ ctx.beginPath();
+ ctx.moveTo(at_x + i * minScale, at_y + 0);
+ ctx.lineTo(at_x + i * minScale, at_y + ticks * rows * minScale);
+ ctx.stroke();
+ }
+
+ var xoffset = xStart * -unit + at_x;
+ var yoffset = yStart * -unit + at_y;
+
+ ctx.fillStyle = "rgb(40,80,60)"
+ for (i = 0; i <= columns; i += 1)
+ {
+ num = xStart + i / subscale;
+ ctx.fillText(num.toFixed(decimal_places), xoffset + num * unit - 5, 10);
+ }
+ for (i = 0; i <= rows; i += 1)
+ {
+ num = yStart + i / subscale;
+ ctx.fillText(num.toFixed(decimal_places), 0, yoffset + num * unit + 0);
+ }
+ var scanType = -1;
+ var partIndex = 0;
+ for (var scans in test) {
+ var scan = test[scans];
+ if (scanType == -1) {
+ scanType = scan;
+ continue;
+ }
+ partIndex++;
+ if (scanType == COMPUTE_DELTA) {
+ ctx.beginPath();
+ ctx.moveTo(xoffset + scan[DELTA_C1_X1] * unit, yoffset + scan[DELTA_C1_Y1] * unit);
+ ctx.bezierCurveTo(
+ xoffset + scan[DELTA_C1_X2] * unit, yoffset + scan[DELTA_C1_Y2] * unit,
+ xoffset + scan[DELTA_C1_X3] * unit, yoffset + scan[DELTA_C1_Y3] * unit,
+ xoffset + scan[DELTA_C1_X4] * unit, yoffset + scan[DELTA_C1_Y4] * unit);
+ ctx.strokeStyle = "red"; // "rgba(0,0,0, 1.0)";
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.moveTo(xoffset + scan[DELTA_C2_X1] * unit, yoffset + scan[DELTA_C2_Y1] * unit);
+ ctx.bezierCurveTo(
+ xoffset + scan[DELTA_C2_X2] * unit, yoffset + scan[DELTA_C2_Y2] * unit,
+ xoffset + scan[DELTA_C2_X3] * unit, yoffset + scan[DELTA_C2_Y3] * unit,
+ xoffset + scan[DELTA_C2_X4] * unit, yoffset + scan[DELTA_C2_Y4] * unit);
+ ctx.strokeStyle = "blue"; // "rgba(0,0,0, 1.0)";
+ ctx.stroke();
+ }
+ if (scanType == COMPUTE_DELTA && drawControlLines) {
+ ctx.beginPath();
+ ctx.moveTo(xoffset + scan[DELTA_C1_X1] * unit, yoffset + scan[DELTA_C1_Y1] * unit);
+ ctx.lineTo(xoffset + scan[DELTA_C1_X2] * unit, yoffset + scan[DELTA_C1_Y2] * unit);
+ ctx.lineTo(xoffset + scan[DELTA_C1_X3] * unit, yoffset + scan[DELTA_C1_Y3] * unit);
+ ctx.lineTo(xoffset + scan[DELTA_C1_X4] * unit, yoffset + scan[DELTA_C1_Y4] * unit);
+ ctx.strokeStyle = "rgba(0,0,0, 0.3)";
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.moveTo(xoffset + scan[DELTA_C2_X1] * unit, yoffset + scan[DELTA_C2_Y1] * unit);
+ ctx.lineTo(xoffset + scan[DELTA_C2_X2] * unit, yoffset + scan[DELTA_C2_Y2] * unit);
+ ctx.lineTo(xoffset + scan[DELTA_C2_X3] * unit, yoffset + scan[DELTA_C2_Y3] * unit);
+ ctx.lineTo(xoffset + scan[DELTA_C2_X4] * unit, yoffset + scan[DELTA_C2_Y4] * unit);
+ ctx.strokeStyle = "rgba(0,0,0, 0.3)";
+ ctx.stroke();
+ }
+ if (scanType == COMPUTE_DELTA && drawT) {
+ drawTPt(scan, DELTA_C1_X1, DELTA_T1, xoffset, yoffset, unit);
+ drawTPt(scan, DELTA_C2_X1, DELTA_T2, xoffset, yoffset, unit);
+ var num = "c1=" + scan[DELTA_T1].toFixed(decimal_places)
+ + " c2=" + scan[DELTA_T2].toFixed(decimal_places);
+ ctx.beginPath();
+ ctx.rect(200,10,200,10);
+ ctx.fillStyle="white";
+ ctx.fill();
+ ctx.fillStyle="black";
+ ctx.fillText(num, 230, 18);
+ }
+ if (scanType == CUBIC_TANGENT) {
+ ctx.beginPath();
+ ctx.moveTo(xoffset + scan[TANGENT_TANGENT_X1] * unit, yoffset + scan[TANGENT_TANGENT_Y1] * unit);
+ ctx.lineTo(xoffset + scan[TANGENT_TANGENT_X2] * unit, yoffset + scan[TANGENT_TANGENT_Y2] * unit);
+ ctx.strokeStyle = partIndex > 2 ? "rgba(0,0,255, 0.7)" : "rgba(255,0,0, 0.7)";
+ ctx.stroke();
+ }
+ scanType = -1;
+ }
+}
+
+function drawTop() {
+ init(tests[testIndex]);
+ redraw();
+}
+
+function redraw() {
+ ctx.beginPath();
+ ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
+ ctx.fillStyle="white";
+ ctx.fill();
+ draw(tests[testIndex], testTitles[testIndex], scale);
+}
+
+function doKeyPress(evt) {
+ var char = String.fromCharCode(evt.charCode);
+ switch (char) {
+ case 'c':
+ drawCubics ^= true;
+ redraw();
+ break;
+ case 'd':
+ decimal_places++;
+ redraw();
+ break;
+ case 'D':
+ decimal_places--;
+ if (decimal_places < 1) {
+ decimal_places = 1;
+ }
+ redraw();
+ break;
+ case 'l':
+ drawControlLines ^= true;
+ redraw();
+ break;
+ case 'N':
+ testIndex += 9;
+ case 'n':
+ if (++testIndex >= tests.length)
+ testIndex = 0;
+ mouseX = Infinity;
+ drawTop();
+ break;
+ case 'P':
+ testIndex -= 9;
+ case 'p':
+ if (--testIndex < 0)
+ testIndex = tests.length - 1;
+ mouseX = Infinity;
+ drawTop();
+ break;
+ case 'q':
+ drawQuads ^= true;
+ redraw();
+ break;
+ case 't':
+ drawT ^= true;
+ redraw();
+ break;
+ case 'x':
+ drawCubics ^= true;
+ drawQuads ^= true;
+ redraw();
+ break;
+ case '-':
+ case '_':
+ subscale /= 2;
+ calcFromScale();
+ redraw();
+ break;
+ case '+':
+ case '=':
+ subscale *= 2;
+ calcFromScale();
+ redraw();
+ break;
+ }
+}
+
+/*
+ var e = window.event;
+ var tgt = e.target || e.srcElement;
+ var min = tgt.offsetTop + Math.ceil(at_y);
+ var max = min + ticks * rows * minScale;
+ curveT = (e.clientY - min) / (max - min);
+ redraw();
+}
+*/
+
+function calcXY() {
+ var e = window.event;
+ var tgt = e.target || e.srcElement;
+ var left = tgt.offsetLeft;
+ var top = tgt.offsetTop;
+ var unit = scale * ticks;
+ mouseX = (e.clientX - left - Math.ceil(at_x) + 1) / unit + xStart;
+ mouseY = (e.clientY - top - Math.ceil(at_y)) / unit + yStart;
+}
+
+function handleMouseOver() {
+ /* calcXY();
+ var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
+ ctx.beginPath();
+ ctx.rect(30,10,200,10);
+ ctx.fillStyle="white";
+ ctx.fill();
+ ctx.fillStyle="black";
+ ctx.fillText(num, 30, 18);
+*/
+}
+
+function start() {
+ for (i = 0; i < testDivs.length; ++i) {
+ var title = testDivs[i].id.toString();
+ var str = testDivs[i].firstChild.data;
+ parse(str, title);
+ }
+ drawTop();
+ window.addEventListener('keypress', doKeyPress, true);
+ window.onresize = function() {
+ drawTop();
+ }
+}
+
+function handleMouseClick() {
+ start();
+}
+
+function startx() {
+}
+
+</script>
+</head>
+
+<body onLoad="startx();">
+<canvas id="canvas" width="750" height="500"
+ onmousemove="handleMouseOver()"
+ onclick="handleMouseClick()"
+ ></canvas >
+</body>
+</html>