From 4443d0dcc0f1cbedab888286e6901f5877658fe0 Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:24:04 -0700
Subject: [PATCH 01/15] Delete Unnecessary Templates
---
addon/templates/components/e3-shape/path.hbs | 1 -
addon/templates/components/e3-shape/text.hbs | 1 -
2 files changed, 2 deletions(-)
delete mode 100644 addon/templates/components/e3-shape/path.hbs
delete mode 100644 addon/templates/components/e3-shape/text.hbs
diff --git a/addon/templates/components/e3-shape/path.hbs b/addon/templates/components/e3-shape/path.hbs
deleted file mode 100644
index 889d9ee..0000000
--- a/addon/templates/components/e3-shape/path.hbs
+++ /dev/null
@@ -1 +0,0 @@
-{{yield}}
diff --git a/addon/templates/components/e3-shape/text.hbs b/addon/templates/components/e3-shape/text.hbs
deleted file mode 100644
index 889d9ee..0000000
--- a/addon/templates/components/e3-shape/text.hbs
+++ /dev/null
@@ -1 +0,0 @@
-{{yield}}
From b9742280f683d9e5133d5aa04d98644cd6d2d6f4 Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:24:37 -0700
Subject: [PATCH 02/15] Support Sums in e3-extent
Is this becoming too much of a behemoth helper? :-|
---
addon/helpers/e3-extent.js | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/addon/helpers/e3-extent.js b/addon/helpers/e3-extent.js
index 75b4187..5fd0a93 100644
--- a/addon/helpers/e3-extent.js
+++ b/addon/helpers/e3-extent.js
@@ -9,6 +9,7 @@ const {get} = Ember;
Options {
key => the property key of where the value sits on each of the items in the array
padding => A percent (0-1) of the found extent to be "padded" to both ends of the extent
+ sum => A flag to determine wether we should take the sum of the values.
min-value => The minimum possible value (clips actual values lower than it)
max-value => The maximum possible value (clips values higher than it)
min-delta => Forces the different between the min and max to be at least a certain value.
@@ -24,6 +25,7 @@ export function e3Extent(params, hash) {
}
let key = hash.key;
+ let sum = hash['sum'];
let nestedKey = hash['nested-key'];
let nestedSum = hash['nested-sum'];
let length = arr.length;
@@ -57,12 +59,23 @@ export function e3Extent(params, hash) {
length = arr.length;
index = -1;
- // Iterate over the array and figure out min/max values.
- while(++index < length) {
- // If there's a key to map, get that value.
- let cur = key ? get(arr[index], key) : arr[index];
- result[0] = Math.min(result[0], cur);
- result[1] = Math.max(result[1], cur);
+ if(sum) {
+ let sumVal = 0;
+ while(++index < length) {
+ let cur = key ? get(arr[index], key) : arr[index];
+ sumVal += cur;
+ }
+
+ result[0] = 0;
+ result[1] = Math.max(result[1], sumVal);
+ } else {
+ // Iterate over the array and figure out min/max values.
+ while(++index < length) {
+ // If there's a key to map, get that value.
+ let cur = key ? get(arr[index], key) : arr[index];
+ result[0] = Math.min(result[0], cur);
+ result[1] = Math.max(result[1], cur);
+ }
}
// Apply the padding.
From 4eca22a227c0ddfbc23476c7576d59f8c7f2a015 Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:24:52 -0700
Subject: [PATCH 03/15] Support Domain Max only
---
addon/mixins/e3-scale.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/addon/mixins/e3-scale.js b/addon/mixins/e3-scale.js
index 610dd82..d44ae9c 100644
--- a/addon/mixins/e3-scale.js
+++ b/addon/mixins/e3-scale.js
@@ -62,7 +62,13 @@ export default Ember.Mixin.create({
do something to this.
*/
getDomain() {
- return this.getAttr('domain');
+ let domain = this.getAttr('domain');
+
+ if(!isArray(domain)) {
+ domain = [0, domain];
+ }
+
+ return domain;
},
/*
From 688382734d6bd9a40637a9671cbb8f411c5291ac Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:25:25 -0700
Subject: [PATCH 04/15] Add Arc Shape Shell
---
addon/components/e3-shape/arc.js | 14 ++++++++++++++
addon/utils/shadow/types/canvas.js | 19 +++++++++++++++++++
addon/utils/shadow/types/svg.js | 18 ++++++++++++++++++
app/components/e3-shape/arc.js | 1 +
4 files changed, 52 insertions(+)
create mode 100644 addon/components/e3-shape/arc.js
create mode 100644 app/components/e3-shape/arc.js
diff --git a/addon/components/e3-shape/arc.js b/addon/components/e3-shape/arc.js
new file mode 100644
index 0000000..d038b02
--- /dev/null
+++ b/addon/components/e3-shape/arc.js
@@ -0,0 +1,14 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ shadowType: 'path',
+ enterState: {},
+ activeState: {
+ x: 0,
+ y: 0,
+ 'start-angle': 0,
+ 'angle': 0,
+ 'inner-radius': 0,
+ 'outer-radius': null
+ }
+});
diff --git a/addon/utils/shadow/types/canvas.js b/addon/utils/shadow/types/canvas.js
index a13cfa2..cf42c49 100644
--- a/addon/utils/shadow/types/canvas.js
+++ b/addon/utils/shadow/types/canvas.js
@@ -49,6 +49,25 @@ export default {
return parentContext;
},
+ arc(parentContext, selfContext, attrs, matrix) {
+ preShape(parentContext, attrs, matrix);
+ /*
+ attrs = {
+ x: {X Center},
+ y: {Y Center},
+ 'start-angle': {In Radians},
+ 'angle': {In Radians},
+ 'inner-radius': {Defaults to 0},
+ 'outer-radius': {Number}
+ }
+
+ Should accept these as arguments to construct a path array (shared with SVG);
+ Path array converts into commands...maybe pathFromCommands should support Arc commands?
+ */
+ postShape(parentContext, attrs, matrix);
+ return parentContext;
+ },
+
stage(parentContext, selfContext, attrs) {
if(!selfContext) {
selfContext = parentContext.getContext('2d');
diff --git a/addon/utils/shadow/types/svg.js b/addon/utils/shadow/types/svg.js
index bf30489..cb5e682 100644
--- a/addon/utils/shadow/types/svg.js
+++ b/addon/utils/shadow/types/svg.js
@@ -55,6 +55,24 @@ export default {
return selfContext;
},
+ arc(parentContext, selfContext, attrs) {
+ selfContext = preRender(selfContext, parentContext, 'path');
+ /*
+ attrs = {
+ x: {X Center},
+ y: {Y Center},
+ 'start-angle': {In Radians},
+ 'angle': {In Radians},
+ 'inner-radius': {Defaults to 0},
+ 'outer-radius': {Number}
+ }
+
+ Should accept these as arguments to construct a path array (shared with SVG);
+ Path array converts into commands...maybe pathFromCommands should support Arc commands?
+ */
+ return selfContext;
+ },
+
stage(parentContext/*, selfContext, attrs*/) {
return parentContext;
},
diff --git a/app/components/e3-shape/arc.js b/app/components/e3-shape/arc.js
new file mode 100644
index 0000000..7069127
--- /dev/null
+++ b/app/components/e3-shape/arc.js
@@ -0,0 +1 @@
+export { default } from 'ember-e3/components/e3-shape/arc';
\ No newline at end of file
From 75fa07275b6e9d82545b3a1b075a78b4a47a303d Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:25:38 -0700
Subject: [PATCH 05/15] Add Tests for e3-extent sums
---
tests/unit/helpers/e3-extent-test.js | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tests/unit/helpers/e3-extent-test.js b/tests/unit/helpers/e3-extent-test.js
index ba5773b..e32f6b9 100644
--- a/tests/unit/helpers/e3-extent-test.js
+++ b/tests/unit/helpers/e3-extent-test.js
@@ -30,6 +30,14 @@ test('handle options', function(assert) {
assert.deepEqual(result, [-1.5,8.5]);
});
+test('get data extent of sum', function(assert) {
+ let result = e3Extent([[1,2,3,4,5]], {sum: true});
+ assert.deepEqual(result, [0, 15]);
+
+ result = e3Extent([[{val:1},{val:100},{val:20},{val:5}]], {key :'val', sum: true});
+ assert.deepEqual(result, [0,126]);
+});
+
test('nested data', function(assert) {
let result = e3Extent([[
{
From 8e7bb4ca744bb338ffcc6b0e68c2bb0c4264fd94 Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:26:10 -0700
Subject: [PATCH 06/15] Support Radian Ranges
Give it start/end percentages; converts to radian based range. Defaults to [0, 2*PI]
---
addon/helpers/e3-radian-range.js | 10 ++++++++++
app/helpers/e3-radian-range.js | 1 +
tests/unit/helpers/e3-radian-range-test.js | 20 ++++++++++++++++++++
3 files changed, 31 insertions(+)
create mode 100644 addon/helpers/e3-radian-range.js
create mode 100644 app/helpers/e3-radian-range.js
create mode 100644 tests/unit/helpers/e3-radian-range-test.js
diff --git a/addon/helpers/e3-radian-range.js b/addon/helpers/e3-radian-range.js
new file mode 100644
index 0000000..2ebc209
--- /dev/null
+++ b/addon/helpers/e3-radian-range.js
@@ -0,0 +1,10 @@
+import Ember from 'ember';
+let twoPI = 2 * Math.PI;
+
+export function e3RadianRange(params, hash = {}) {
+ let startPercent = 'start' in hash ? hash.start : 0;
+ let endPercent = 'end' in hash ? hash.end : 1;
+ return [startPercent * twoPI, endPercent * twoPI];
+}
+
+export default Ember.Helper.helper(e3RadianRange);
diff --git a/app/helpers/e3-radian-range.js b/app/helpers/e3-radian-range.js
new file mode 100644
index 0000000..87bb8ef
--- /dev/null
+++ b/app/helpers/e3-radian-range.js
@@ -0,0 +1 @@
+export { default, e3RadianRange } from 'ember-e3/helpers/e3-radian-range';
diff --git a/tests/unit/helpers/e3-radian-range-test.js b/tests/unit/helpers/e3-radian-range-test.js
new file mode 100644
index 0000000..66a0a81
--- /dev/null
+++ b/tests/unit/helpers/e3-radian-range-test.js
@@ -0,0 +1,20 @@
+import { e3RadianRange } from 'ember-e3/helpers/e3-radian-range';
+import { module, test } from 'qunit';
+
+module('Unit | Helper | e3 radian range');
+
+// Replace this with your real tests.
+test('it works', function(assert) {
+ let result;
+ result = e3RadianRange([], {});
+ assert.deepEqual(result, [0, 2 * Math.PI]);
+
+ result = e3RadianRange([], {start: 0.5});
+ assert.deepEqual(result, [Math.PI, 2 * Math.PI]);
+
+ result = e3RadianRange([], {end: 0.5});
+ assert.deepEqual(result, [0, Math.PI]);
+
+ result = e3RadianRange([], {end: 0.75, start: 0.25});
+ assert.deepEqual(result, [Math.PI / 2, Math.PI * 1.5]);
+});
From a0c05fc50c09a72e6c26fa061a0f3643b5a376bd Mon Sep 17 00:00:00 2001
From: Spencer
Date: Fri, 14 Aug 2015 10:26:37 -0700
Subject: [PATCH 07/15] Add Pie Chart Template to Dummy App
Should work once arc shape support is fully filled out.
---
tests/dummy/app/router.js | 1 +
tests/dummy/app/routes/pie-chart.js | 37 +++++++++++++++++++
tests/dummy/app/templates/application.hbs | 3 +-
tests/dummy/app/templates/pie-chart.hbs | 28 ++++++++++++++
.../components/e3-shape/arc-test.js | 27 ++++++++++++++
5 files changed, 95 insertions(+), 1 deletion(-)
create mode 100644 tests/dummy/app/routes/pie-chart.js
create mode 100644 tests/dummy/app/templates/pie-chart.hbs
create mode 100644 tests/integration/components/e3-shape/arc-test.js
diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js
index 593863c..4089b3a 100644
--- a/tests/dummy/app/router.js
+++ b/tests/dummy/app/router.js
@@ -16,6 +16,7 @@ Router.map(function() {
this.route('grouped-bars');
this.route('invert');
this.route('nytimes-strikeouts');
+ this.route('pie-chart');
});
export default Router;
diff --git a/tests/dummy/app/routes/pie-chart.js b/tests/dummy/app/routes/pie-chart.js
new file mode 100644
index 0000000..5f9b5fc
--- /dev/null
+++ b/tests/dummy/app/routes/pie-chart.js
@@ -0,0 +1,37 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ actions: {
+ addBar() {
+ let model = this.controller.get('model').slice(0);
+ model.unshift(o());
+ this.controller.set('model', model);
+ },
+ removeBar() {
+ let model = this.controller.get('model').slice(0);
+ model.pop();
+ this.controller.set('model', model);
+ }
+ },
+
+ model() {
+ return g(10);
+ }
+});
+
+function g(number) {
+ let res = [];
+ while(--number >= 0) {
+ res.push(o());
+ }
+ return res;
+}
+
+let ID = 0;
+function o() {
+ return {
+ id: ++ID,
+ value: Math.random() * 100,
+ temperature: Math.random() * 100
+ };
+}
\ No newline at end of file
diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs
index 4cf6f60..4e0fe76 100644
--- a/tests/dummy/app/templates/application.hbs
+++ b/tests/dummy/app/templates/application.hbs
@@ -12,8 +12,9 @@
+
- {{!-- Can't show this yet as it dependson the mock server. Blarg. --}}
+ {{!-- Can't show this yet as it depends on the mock server. Blarg. --}}
{{!-- --}}
diff --git a/tests/dummy/app/templates/pie-chart.hbs b/tests/dummy/app/templates/pie-chart.hbs
new file mode 100644
index 0000000..15da856
--- /dev/null
+++ b/tests/dummy/app/templates/pie-chart.hbs
@@ -0,0 +1,28 @@
+
+
+
+{{#e3-container type='svg' height=400 width=800 as |ctx meta|}}
+
+ {{e3-scale/linear ctx 'wedge'
+ domain=(e3-extent model key='temperature' sum=true)
+ range=(e3-radian-range)
+ }}
+
+
+ {{#e3-stacked-group ctx
+ data=model
+ x=400
+ y=200
+ sum-props='temperature'
+ as |groupContext groupMeta data cums|}}
+ {{log data cums}}
+ {{e3-shape/arc groupContext
+ data=data
+ outer-radius=150
+ inner-radius=50
+ start-angle=(e3-bind-scale meta.scales.wedge 'temperature' data=cums)
+ angle=(e3-bind-scale meta.scales.wedge 'temperature')
+ mouse-move='mouseMoved'
+ }}
+ {{/e3-stacked-group}}
+{{/e3-container}}
\ No newline at end of file
diff --git a/tests/integration/components/e3-shape/arc-test.js b/tests/integration/components/e3-shape/arc-test.js
new file mode 100644
index 0000000..4d20549
--- /dev/null
+++ b/tests/integration/components/e3-shape/arc-test.js
@@ -0,0 +1,27 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+
+moduleForComponent('e3-shape/arc', 'Integration | Component | e3 shape/arc', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ assert.expect(2);
+
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });
+
+ this.render(hbs`{{e3-shape/arc}}`);
+
+ assert.equal(this.$().text(), '');
+
+ // Template block usage:
+ this.render(hbs`
+ {{#e3-shape/arc}}
+ template block text
+ {{/e3-shape/arc}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
From e3763c98af58e4961bc7aa788bcb72934c0d35ac Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Mon, 17 Aug 2015 00:06:27 -0700
Subject: [PATCH 08/15] Create separate classes for path commands
Since two path commands may have the same number of arguments
---
addon/utils/shadow/types/commands.js | 51 +++++++++++++++++++
.../line-interpolation/monotone-test.js | 14 ++---
2 files changed, 59 insertions(+), 6 deletions(-)
create mode 100644 addon/utils/shadow/types/commands.js
diff --git a/addon/utils/shadow/types/commands.js b/addon/utils/shadow/types/commands.js
new file mode 100644
index 0000000..a3b1f9f
--- /dev/null
+++ b/addon/utils/shadow/types/commands.js
@@ -0,0 +1,51 @@
+// gets set to move for the first command and line for all others
+export function Point(x, y) {
+ this.type = 'point';
+ this.x = x;
+ this.y = y;
+}
+
+export function Move(x, y) {
+ this.type = 'move';
+ this.x = x;
+ this.y = y;
+}
+
+export function Line(x, y) {
+ this.type = 'line';
+ this.x = x;
+ this.y = y;
+}
+
+export function SmoothCurve(x2, y2, x, y) {
+ this.type = 'smooth-curve';
+ this.x2 = x2;
+ this.y2 = y2;
+ this.x = x;
+ this.y = y;
+}
+
+export function BezierCurve(x1, y1, x2, y2, x, y) {
+ this.type = 'bezier-curve';
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.x = x;
+ this.y = y;
+}
+
+export function Arc(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
+ this.type = 'arc';
+ this.x = x;
+ this.y = y;
+ this.xAxisRotation = xAxisRotation;
+ this.largeArcFlag = largeArcFlag;
+ this.sweepFlag = sweepFlag;
+ this.rx = rx;
+ this.ry = ry;
+}
+
+export function Close() {
+ this.type = 'close';
+}
diff --git a/tests/unit/utils/shadow/line-interpolation/monotone-test.js b/tests/unit/utils/shadow/line-interpolation/monotone-test.js
index 0b399e6..233e7de 100644
--- a/tests/unit/utils/shadow/line-interpolation/monotone-test.js
+++ b/tests/unit/utils/shadow/line-interpolation/monotone-test.js
@@ -1,4 +1,5 @@
import monotone from 'ember-e3/utils/shadow/line-interpolation/monotone';
+import { Point, SmoothCurve, BezierCurve } from 'ember-e3/utils/shadow/types/commands';
import { module, test } from 'qunit';
module('Unit | Utility | shadow/line interpolation/monotone');
@@ -7,12 +8,13 @@ test('it has a wide repetoire of commands', function(assert) {
var points = [[0, 0], [1, 1], [2, 1], [3, 0], [4, 0]];
// a + (a - b) = 2a - b where a is the position and b is the last control point
- assert.deepEqual(monotone(points), [
- [0, 0],
- [0.08333333333333333, 0.08333333333333333, 0.6666666666666667, 1, 1, 1],
- [1.3333333333333333, 1, 1.6666666666666667, 1, 2, 1],
- [2.3333333333333333, 1, 2.6666666666666665, 0, 3, 0],
- [3.3333333333333335, 0, 3.8333333333333335, 0, 4, 0]
+ var commands = monotone(points);
+ assert.deepEqual(commands, [
+ new Point(0, 0),
+ new BezierCurve(0.08333333333333333, 0.08333333333333333, 0.6666666666666667, 1, 1, 1),
+ new SmoothCurve(1.3333333333333333, 1, 1.6666666666666667, 1, 2, 1),
+ new SmoothCurve(2.3333333333333333, 1, 2.6666666666666665, 0, 3, 0),
+ new SmoothCurve(3.3333333333333335, 0, 3.8333333333333335, 0, 4, 0)
]);
});
From 880d1651c6ed22398044d7a852e83093de07216f Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Mon, 17 Aug 2015 00:07:35 -0700
Subject: [PATCH 09/15] :squirrel: Borrow svg code from d3
---
addon/utils/shadow/types/svg.js | 29 ++---
.../shadow/types/svg/arc-svg-commands.js | 112 ++++++++++++++++++
2 files changed, 127 insertions(+), 14 deletions(-)
create mode 100644 addon/utils/shadow/types/svg/arc-svg-commands.js
diff --git a/addon/utils/shadow/types/svg.js b/addon/utils/shadow/types/svg.js
index cb5e682..c8fb199 100644
--- a/addon/utils/shadow/types/svg.js
+++ b/addon/utils/shadow/types/svg.js
@@ -2,6 +2,7 @@ import Ember from 'ember';
import {toArray} from '../matrix-math';
import pathCommands from '../line-interpolation/path-commands';
import pathFromCommands from './svg/path-from-commands';
+import arcSvgCommands from './svg/arc-svg-commands';
import ATTRIBUTE_MAP from './svg-attribute-map';
const {keys} = Object;
const {copy} = Ember;
@@ -38,6 +39,8 @@ export default {
},
path(parentContext, selfContext, attrs) {
+ console.log('arcc');
+
selfContext = preRender(selfContext, parentContext, 'path');
// Create the 'd' string from the attrs x/y
attrs.d = pathFromCommands(pathCommands(attrs.x, attrs.y, attrs.interpolation));
@@ -56,20 +59,18 @@ export default {
},
arc(parentContext, selfContext, attrs) {
- selfContext = preRender(selfContext, parentContext, 'path');
- /*
- attrs = {
- x: {X Center},
- y: {Y Center},
- 'start-angle': {In Radians},
- 'angle': {In Radians},
- 'inner-radius': {Defaults to 0},
- 'outer-radius': {Number}
- }
-
- Should accept these as arguments to construct a path array (shared with SVG);
- Path array converts into commands...maybe pathFromCommands should support Arc commands?
- */
+ console.log('arcc');
+ selfContext = preRender(selfContext, parentContext, 'arc');
+ var commands = arcSvgCommands(
+ attrs.x,
+ attrs.y,
+ attrs['start-angle'],
+ attrs['angle'],
+ attrs['inner-radius'],
+ attrs['outer-radius']
+ );
+ attrs.d = pathFromCommands(commands);
+ renderAttributes('path', selfContext, attrs);
return selfContext;
},
diff --git a/addon/utils/shadow/types/svg/arc-svg-commands.js b/addon/utils/shadow/types/svg/arc-svg-commands.js
new file mode 100644
index 0000000..5ae4ee3
--- /dev/null
+++ b/addon/utils/shadow/types/svg/arc-svg-commands.js
@@ -0,0 +1,112 @@
+const {pi} = Math;
+import { Line, Move, Arc, Close } from '../commands';
+
+/*
+ * Lovingly plucked from d3.js
+ *
+ * https://github.com/mbostock/d3/blob/master/src/svg/arc.js
+ */
+export default function arcSvgCommands(x, y, startAngle, angle, innerRadius, outerRadius) {
+
+ var r0 = Math.max(0, +innerRadius),
+ r1 = Math.max(0, +outerRadius),
+ a0 = startAngle - pi / 2,
+ a1 = (startAngle + angle) - pi / 2,
+ da = Math.abs(a1 - a0),
+ cw = a0 > a1 ? 0 : 1,
+ commands = [];
+
+ // Ensure that the outer radius is always larger than the inner radius.
+ if (r1 < r0) {
+ let rc = r1;
+ r1 = r0;
+ r0 = rc;
+ }
+
+ // Special case for an arc that spans the full circle.
+ if (da >= 2 * pi - 0.000001) {
+ commands.push(circleSegment(r1, cw));
+ if (r0) {
+ commands.push(circleSegment(r0, 1 - cw));
+ }
+ commands.push(new Close());
+ return commands;
+ }
+
+ var p0 = 0,
+ p1 = 0,
+ x0,
+ y0,
+ x1,
+ y1,
+ x2,
+ y2,
+ x3,
+ y3,
+ l0,
+ l1;
+
+ // Compute the two outer corners.
+ if (r1) {
+ x0 = r1 * Math.cos(a0 + p1);
+ y0 = r1 * Math.sin(a0 + p1);
+ x1 = r1 * Math.cos(a1 - p1);
+ y1 = r1 * Math.sin(a1 - p1);
+
+ // Detect whether the outer corners are collapsed.
+ l1 = Math.abs(a1 - a0 - 2 * p1) <= pi ? 0 : 1;
+ if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) {
+ var h1 = (a0 + a1) / 2;
+ x0 = r1 * Math.cos(h1);
+ y0 = r1 * Math.sin(h1);
+ x1 = y1 = null;
+ }
+ } else {
+ x0 = y0 = 0;
+ }
+
+ // Compute the two inner corners.
+ if (r0) {
+ x2 = r0 * Math.cos(a1 - p0);
+ y2 = r0 * Math.sin(a1 - p0);
+ x3 = r0 * Math.cos(a0 + p0);
+ y3 = r0 * Math.sin(a0 + p0);
+
+ // Detect whether the inner corners are collapsed.
+ l0 = Math.abs(a0 - a1 + 2 * p0) <= pi ? 0 : 1;
+ if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === (1 - cw) ^ l0) {
+ var h0 = (a0 + a1) / 2;
+ x2 = r0 * Math.cos(h0);
+ y2 = r0 * Math.sin(h0);
+ x3 = y3 = null;
+ }
+ } else {
+ x2 = y2 = 0;
+ }
+
+ commands.push(new Move(x, y));
+ if (x1 != null) {
+ commands.push(new Arc(r1, r1, l1, cw, x1, y1));
+ }
+
+ commands.push(new Line(x2, y2));
+ if (x3 != null) {
+ commands.push(new Arc(r0, r0, l0, 1 - cw, x3, y3));
+ }
+
+ commands.push(new Close());
+ return commands;
+}
+
+function circleSegment(r1, cw) {
+ return [
+ new Move(0, r1),
+ new Arc(r1, r1, 0, 1, cw, 0, -r1),
+ new Arc(r1, r1, 0, 1, cw, 0, r1),
+ ];
+}
+
+// Note: similar to d3_cross2d, d3_geom_polygonInside
+function d3_svg_arcSweep(x0, y0, x1, y1) {
+ return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1;
+}
From e889c0199dcc687285c2bb3f9342b7855dc115a0 Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Mon, 17 Aug 2015 00:09:09 -0700
Subject: [PATCH 10/15] Linear interpolation produces a set of Points
---
addon/utils/shadow/line-interpolation/path-commands.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/addon/utils/shadow/line-interpolation/path-commands.js b/addon/utils/shadow/line-interpolation/path-commands.js
index 3157adf..c2dd621 100644
--- a/addon/utils/shadow/line-interpolation/path-commands.js
+++ b/addon/utils/shadow/line-interpolation/path-commands.js
@@ -1,4 +1,5 @@
import monotone from './monotone';
+import { Point } from './monotone';
export default function generatePath(xPoints, yPoints, interpolation = 'linear') {
@@ -6,7 +7,9 @@ export default function generatePath(xPoints, yPoints, interpolation = 'linear')
var commands;
switch(interpolation) {
case 'linear':
- commands = points;
+ commands = points.map(point => {
+ return new Point(point[0], point[1]);
+ });
break;
case 'monotone':
commands = monotone(points);
From bd4fa8118f3220f0329683d5a4ff59d018a1ccdb Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Mon, 17 Aug 2015 00:09:25 -0700
Subject: [PATCH 11/15] Arc shape uses the arc shadow type
---
addon/components/e3-shape/arc.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addon/components/e3-shape/arc.js b/addon/components/e3-shape/arc.js
index d038b02..d6e75c0 100644
--- a/addon/components/e3-shape/arc.js
+++ b/addon/components/e3-shape/arc.js
@@ -1,7 +1,7 @@
import Ember from 'ember';
export default Ember.Component.extend({
- shadowType: 'path',
+ shadowType: 'arc',
enterState: {},
activeState: {
x: 0,
From 146eed42d7d0e12b60c5d7f0a32d4024a06b17ef Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Mon, 17 Aug 2015 00:10:09 -0700
Subject: [PATCH 12/15] Attempt to migrate monotone to use new commands
---
.../shadow/line-interpolation/monotone.js | 70 +++++++++++--------
tests/dummy/app/templates/pie-chart.hbs | 4 +-
2 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/addon/utils/shadow/line-interpolation/monotone.js b/addon/utils/shadow/line-interpolation/monotone.js
index c7e59a9..c23a748 100644
--- a/addon/utils/shadow/line-interpolation/monotone.js
+++ b/addon/utils/shadow/line-interpolation/monotone.js
@@ -1,4 +1,5 @@
const {abs} = Math;
+import { Point, SmoothCurve, BezierCurve } from '../types/commands';
/**
* Returns an array of arguemnts for commands
@@ -11,7 +12,10 @@ export default function monotone(points) {
return points;
}
- return [points[0]].concat(d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)));
+ var commands = [];
+ commands.push(new Point(points[0][0], points[0][1]));
+ var hermite = d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+ return commands.concat(hermite);
}
/*
@@ -90,12 +94,14 @@ function d3_svg_lineHermite(points, tangents) {
pi = 1;
if (quad) {
- commands.push([
- p[0] - t0[0] * 2 / 3,
- p[1] - t0[1] * 2 / 3,
- p[0],
- p[1]
- ]);
+ commands.push(
+ new SmoothCurve(
+ p[0] - t0[0] * 2 / 3,
+ p[1] - t0[1] * 2 / 3,
+ p[0],
+ p[1]
+ )
+ );
p0 = points[1];
pi = 2;
}
@@ -104,14 +110,16 @@ function d3_svg_lineHermite(points, tangents) {
t = tangents[1];
p = points[pi];
pi++;
- commands.push([
- p0[0] + t0[0],
- p0[1] + t0[1],
- p[0] - t[0],
- p[1] - t[1],
- p[0],
- p[1]
- ]);
+ commands.push(
+ new BezierCurve(
+ p0[0] + t0[0],
+ p0[1] + t0[1],
+ p[0] - t[0],
+ p[1] - t[1],
+ p[0],
+ p[1]
+ )
+ );
for (var i = 2; i < tangents.length; i++, pi++) {
p = points[pi];
@@ -119,25 +127,29 @@ function d3_svg_lineHermite(points, tangents) {
let lt = tangents[i - 1];
let lp = points[i - 1];
- commands.push([
- lp[0] + lt[0], // Add the last tangent but reflected
- lp[1] + lt[1],
- p[0] - t[0],
- p[1] - t[1],
- p[0],
- p[1]
- ]);
+ commands.push(
+ new BezierCurve(
+ lp[0] + lt[0], // Add the last tangent but reflected
+ lp[1] + lt[1],
+ p[0] - t[0],
+ p[1] - t[1],
+ p[0],
+ p[1]
+ )
+ );
}
}
if (quad) {
var lp = points[pi];
- commands.push([
- p[0] + t[0] * 2 / 3,
- p[1] + t[1] * 2 / 3,
- lp[0],
- lp[1]
- ]);
+ commands.push(
+ new SmoothCurve(
+ p[0] + t[0] * 2 / 3,
+ p[1] + t[1] * 2 / 3,
+ lp[0],
+ lp[1]
+ )
+ );
}
return commands;
diff --git a/tests/dummy/app/templates/pie-chart.hbs b/tests/dummy/app/templates/pie-chart.hbs
index 15da856..04b44e7 100644
--- a/tests/dummy/app/templates/pie-chart.hbs
+++ b/tests/dummy/app/templates/pie-chart.hbs
@@ -8,14 +8,12 @@
range=(e3-radian-range)
}}
-
{{#e3-stacked-group ctx
data=model
x=400
y=200
sum-props='temperature'
as |groupContext groupMeta data cums|}}
- {{log data cums}}
{{e3-shape/arc groupContext
data=data
outer-radius=150
@@ -25,4 +23,4 @@
mouse-move='mouseMoved'
}}
{{/e3-stacked-group}}
-{{/e3-container}}
\ No newline at end of file
+{{/e3-container}}
From 1ae312c8348792897ac6a84cde5fd9668e8d3028 Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Wed, 2 Sep 2015 21:45:48 -0700
Subject: [PATCH 13/15] Add title to dummy page
---
tests/dummy/app/templates/pie-chart.hbs | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/dummy/app/templates/pie-chart.hbs b/tests/dummy/app/templates/pie-chart.hbs
index 04b44e7..4c4f98b 100644
--- a/tests/dummy/app/templates/pie-chart.hbs
+++ b/tests/dummy/app/templates/pie-chart.hbs
@@ -1,3 +1,4 @@
+Pie chart
From c36d2aadcdff7b1c1a97b040d587363c865af6ec Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Wed, 2 Sep 2015 23:07:22 -0700
Subject: [PATCH 14/15] Write SVG commands using the new syntax
---
addon/components/e3-shape/arc.js | 4 +--
.../shadow/types/svg/path-from-commands.js | 34 ++++++++++++++-----
2 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/addon/components/e3-shape/arc.js b/addon/components/e3-shape/arc.js
index d6e75c0..c946993 100644
--- a/addon/components/e3-shape/arc.js
+++ b/addon/components/e3-shape/arc.js
@@ -1,6 +1,6 @@
-import Ember from 'ember';
+import e3AnimatedChild from '../e3-animated-child';
-export default Ember.Component.extend({
+export default e3AnimatedChild.extend({
shadowType: 'arc',
enterState: {},
activeState: {
diff --git a/addon/utils/shadow/types/svg/path-from-commands.js b/addon/utils/shadow/types/svg/path-from-commands.js
index 9bfde4a..60c97fe 100644
--- a/addon/utils/shadow/types/svg/path-from-commands.js
+++ b/addon/utils/shadow/types/svg/path-from-commands.js
@@ -1,19 +1,37 @@
+import { Move, Line, Point, Arc, SmoothCurve, BezierCurve } from '../commands';
+
export default function pathFromCommands(commands) {
let svgCommands = commands.map((command, i) => {
- let name = '';
- if (command.length === 2) {
- name = i === 0 ? 'M' : 'L';
+
+ if (command instanceof Point) {
+ return (i === 0 ? 'M' : 'L') + command.x + command.y;
+ }
+
+ if (command instanceof Move) {
+ return 'M' + command.x + command.y;
}
- if (command.length === 4) {
- name = 'S';
+ if (command instanceof Line) {
+ return 'L' + command.x + command.y;
}
- if (command.length === 6) {
- name = 'C';
+ if (command instanceof SmoothCurve) {
+ return 'S' + command.x2 + command.y2 + command.x + command.y;
}
- return name + command.join(',');
+ if (command instanceof BezierCurve) {
+ return 'C' + command.x1 + command.y1 +
+ command.x2 + command.y2 +
+ command.x + command.y;
+ }
+
+ if (command instanceof Arc) {
+ return 'A' + command.rx + command.ry +
+ command.xAxisRotation +
+ command.largeArcFlag +
+ command.sweepFlag +
+ command.x + command.y;
+ }
});
return svgCommands.join(' ');
From 0b05c4f079987ba9d103b6f1b57ca5b526af62ad Mon Sep 17 00:00:00 2001
From: Ben Holmes
Date: Wed, 2 Sep 2015 23:43:55 -0700
Subject: [PATCH 15/15] This arc is going places!
---
addon/utils/shadow/types/svg.js | 5 +---
.../shadow/types/svg/arc-svg-commands.js | 9 ++++---
.../shadow/types/svg/path-from-commands.js | 25 ++++++++++---------
3 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/addon/utils/shadow/types/svg.js b/addon/utils/shadow/types/svg.js
index c8fb199..2647d3a 100644
--- a/addon/utils/shadow/types/svg.js
+++ b/addon/utils/shadow/types/svg.js
@@ -39,8 +39,6 @@ export default {
},
path(parentContext, selfContext, attrs) {
- console.log('arcc');
-
selfContext = preRender(selfContext, parentContext, 'path');
// Create the 'd' string from the attrs x/y
attrs.d = pathFromCommands(pathCommands(attrs.x, attrs.y, attrs.interpolation));
@@ -59,8 +57,7 @@ export default {
},
arc(parentContext, selfContext, attrs) {
- console.log('arcc');
- selfContext = preRender(selfContext, parentContext, 'arc');
+ selfContext = preRender(selfContext, parentContext, 'path');
var commands = arcSvgCommands(
attrs.x,
attrs.y,
diff --git a/addon/utils/shadow/types/svg/arc-svg-commands.js b/addon/utils/shadow/types/svg/arc-svg-commands.js
index 5ae4ee3..e5c1641 100644
--- a/addon/utils/shadow/types/svg/arc-svg-commands.js
+++ b/addon/utils/shadow/types/svg/arc-svg-commands.js
@@ -1,4 +1,4 @@
-const {pi} = Math;
+const {PI} = Math;
import { Line, Move, Arc, Close } from '../commands';
/*
@@ -8,7 +8,8 @@ import { Line, Move, Arc, Close } from '../commands';
*/
export default function arcSvgCommands(x, y, startAngle, angle, innerRadius, outerRadius) {
- var r0 = Math.max(0, +innerRadius),
+ var pi = PI,
+ r0 = Math.max(0, +innerRadius),
r1 = Math.max(0, +outerRadius),
a0 = startAngle - pi / 2,
a1 = (startAngle + angle) - pi / 2,
@@ -86,12 +87,12 @@ export default function arcSvgCommands(x, y, startAngle, angle, innerRadius, out
commands.push(new Move(x, y));
if (x1 != null) {
- commands.push(new Arc(r1, r1, l1, cw, x1, y1));
+ commands.push(new Arc(r1, r1, 0, l1, cw, x1, y1));
}
commands.push(new Line(x2, y2));
if (x3 != null) {
- commands.push(new Arc(r0, r0, l0, 1 - cw, x3, y3));
+ commands.push(new Arc(r0, r0, 0, l0, 1 - cw, x3, y3));
}
commands.push(new Close());
diff --git a/addon/utils/shadow/types/svg/path-from-commands.js b/addon/utils/shadow/types/svg/path-from-commands.js
index 60c97fe..04c6bd4 100644
--- a/addon/utils/shadow/types/svg/path-from-commands.js
+++ b/addon/utils/shadow/types/svg/path-from-commands.js
@@ -4,33 +4,34 @@ export default function pathFromCommands(commands) {
let svgCommands = commands.map((command, i) => {
if (command instanceof Point) {
- return (i === 0 ? 'M' : 'L') + command.x + command.y;
+ return (i === 0 ? 'M' : 'L') + command.x + ',' + command.y;
}
if (command instanceof Move) {
- return 'M' + command.x + command.y;
+ return 'M' + command.x + ',' + command.y;
}
if (command instanceof Line) {
- return 'L' + command.x + command.y;
+ return 'L' + command.x + ',' + command.y;
}
if (command instanceof SmoothCurve) {
- return 'S' + command.x2 + command.y2 + command.x + command.y;
+ return 'S' + command.x2 + ',' + command.y2 + ' ' +
+ command.x + ',' + command.y;
}
if (command instanceof BezierCurve) {
- return 'C' + command.x1 + command.y1 +
- command.x2 + command.y2 +
- command.x + command.y;
+ return 'C' + command.x1 + ',' + command.y1 + ' ' +
+ command.x2 + ',' + command.y2 + ' ' +
+ command.x + ',' + command.y;
}
if (command instanceof Arc) {
- return 'A' + command.rx + command.ry +
- command.xAxisRotation +
- command.largeArcFlag +
- command.sweepFlag +
- command.x + command.y;
+ return 'A' + command.rx + ',' + command.ry + ' ' +
+ command.xAxisRotation + ' ' +
+ command.largeArcFlag + ',' +
+ command.sweepFlag + ' ' +
+ command.x + ',' + command.y;
}
});