Skip to content

Commit

Permalink
Fix rule mark to support arbitrary (possibly oblique) line segments
Browse files Browse the repository at this point in the history
Fix #3263
  • Loading branch information
kanitw authored and domoritz committed Jan 15, 2018
1 parent 59eb6da commit cebdffb
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 4 deletions.
8 changes: 7 additions & 1 deletion src/compile/mark/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ function orient(mark: Mark, encoding: Encoding<string>, specifiedOrient: Orient)

switch (mark) {
case RULE:
// return undefined for line segment rule
if (xIsRange && yIsRange) {
return undefined;
}
/* tslint:disable */
// intentional fall through
case BAR:
case AREA:
// If there are range for both x and y, y (vertical) has higher precedence.
Expand All @@ -80,7 +86,7 @@ function orient(mark: Mark, encoding: Encoding<string>, specifiedOrient: Orient)
}
}

/* tslint:disable */

case LINE: // intentional fall through
case TICK: // Tick is opposite to bar, line, area and never have ranged mark.

Expand Down
7 changes: 6 additions & 1 deletion src/compile/mark/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ export const rule: MarkCompiler = {
...mixins.markDefProperties(model.markDef, true),
...mixins.pointPosition('x', model, orient === 'horizontal' ? 'zeroOrMin' : ref.mid(width)),
...mixins.pointPosition('y', model, orient === 'vertical' ? 'zeroOrMin' : ref.mid(height)),
...mixins.pointPosition2(model, 'zeroOrMax'),

// include x2 for horizontal or line segment rule
...(orient !== 'vertical' ? mixins.pointPosition2(model, 'zeroOrMax', 'x2') : {}),

// include y2 for vertical or line segment rule
...(orient !== 'horizontal' ? mixins.pointPosition2(model, 'zeroOrMax', 'y2') : {}),

...mixins.color(model),
...mixins.text(model, 'tooltip'),
Expand Down
26 changes: 25 additions & 1 deletion test/compile/mark/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ describe('compile/mark/init', function() {
assert.equal(model.markDef.orient, 'vertical');
});

it('should return correct orient for horizontal rule', function() {
it('should return correct orient for horizontal rule', function () {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
"encoding": {
Expand All @@ -206,6 +206,30 @@ describe('compile/mark/init', function() {
assert.equal(model.markDef.orient, 'horizontal');
});

it('should return undefined for line segment rule', function () {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
"encoding": {
"y": {"value": 0},
"x": {"value": 0},
"y2": {"value": 100},
"x2": {"value": 100},
},
});
assert.equal(model.markDef.orient, undefined);
});

it('should return undefined for line segment rule with only x and y without x2, y2', function () {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
"encoding": {
"y": {"value": 0},
"x": {"value": 0}
},
});
assert.equal(model.markDef.orient, undefined);
});

it('should return correct orient for horizontal rules without x2 ', function() {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
Expand Down
40 changes: 39 additions & 1 deletion test/compile/mark/rule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,51 @@ describe('Mark: Rule', function() {

const props = rule.encodeEntry(model);

it('should create horizontal rules', function() {
it('should create horizontal rules', function () {
assert.deepEqual(props.x, {scale: X, field: 'a'});
assert.deepEqual(props.x2, {scale: X, field: 'a2'});
assert.deepEqual(props.y, {scale: Y, field: 'b'});
});
});

describe('with x, x2, y, and y2', () => {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
"encoding": {
"x": {"field": "a", "type": "quantitative"},
"x2": {"field": "a2", "type": "quantitative"},
"y": {"field": "b", "type": "quantitative"},
"y2": {"field": "b2", "type": "quantitative"}
}
});

const props = rule.encodeEntry(model);

it('should create oblique rules', function () {
assert.deepEqual(props.x, {scale: X, field: 'a'});
assert.deepEqual(props.x2, {scale: X, field: 'a2'});
assert.deepEqual(props.y, {scale: Y, field: 'b'});
assert.deepEqual(props.y2, {scale: Y, field: 'b2'});
});
});

describe('with x and y', () => {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
"encoding": {
"x": {"field": "a", "type": "quantitative"},
"y": {"field": "b", "type": "quantitative"}
}
});

const props = rule.encodeEntry(model);

it('should create oblique rules', function () {
assert.deepEqual(props.x, {scale: X, field: 'a'});
assert.deepEqual(props.y, {scale: Y, field: 'b'});
});
});

describe('with y, y2, and x', () => {
const model = parseUnitModelWithScaleAndLayoutSize({
"mark": "rule",
Expand Down

0 comments on commit cebdffb

Please sign in to comment.