Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 69 additions & 14 deletions axes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function Axes(gl) {
this.tickFont = [ 'sans-serif', 'sans-serif', 'sans-serif' ]
this.tickSize = [ 12, 12, 12 ]
this.tickAngle = [ 0, 0, 0 ]
this._tickAlign = [ 'auto', 'auto', 'auto' ]
this.tickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ]
this.tickPad = [ 10, 10, 10 ]

Expand All @@ -48,7 +49,8 @@ function Axes(gl) {
this.labelEnable = [ true, true, true ]
this.labelFont = 'sans-serif'
this.labelSize = [ 20, 20, 20 ]
this.labelAngle = [ 0, 0, 0 ]
this._labelAngle = [ 0, 0, 0 ]
this._labelAlign = [ 'auto', 'auto', 'auto' ]
this.labelColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ]
this.labelPad = [ 10, 10, 10 ]

Expand Down Expand Up @@ -457,13 +459,48 @@ proto.draw = function(params) {
projection,
this.pixelRatio)

var alignOpt = [0,0,1]
// Note: the 3rd member is the integer option
// from {-1, 0, 1, 2, 3, ..., n}
var alignOpt // options in shader are from this list {-1, 0, 1, 2, 3, ..., n}
// -1: backward compatible
// 0: raw data
// 1: auto align, free angles
// 2: auto align, horizontal or vertical
//3-n: auto align, round to n directions e.g. 12 -> round to angles with 30-degree steps

var upwardsTolerance
var hv_ratio = 0.5 // can have an effect on the ratio between horizontals and verticals when using option 2

var alignDir

function alignTo(i) {
alignDir = [0,0,0];
alignDir[i] = 1
}

function solveTickAlignments(i, minor, major) {

var i1 = (i + 1) % 3
var i2 = (i + 2) % 3

var A = minor[i1]
var B = minor[i2]
var C = major[i1]
var D = major[i2]

if ((A > 0) && (D > 0)) { alignTo(i1); return; }
else if ((A > 0) && (D < 0)) { alignTo(i1); return; }
else if ((A < 0) && (D > 0)) { alignTo(i1); return; }
else if ((A < 0) && (D < 0)) { alignTo(i1); return; }
else if ((B > 0) && (C > 0)) { alignTo(i2); return; }
else if ((B > 0) && (C < 0)) { alignTo(i2); return; }
else if ((B < 0) && (C > 0)) { alignTo(i2); return; }
else if ((B < 0) && (C < 0)) { alignTo(i2); return; }
}

for(var i=0; i<3; ++i) {

var minor = lineOffset[i].primalMinor
var major = lineOffset[i].mirrorMinor

var offset = copyVec3(PRIMAL_OFFSET, lineOffset[i].primalOffset)

for(var j=0; j<3; ++j) {
Expand All @@ -475,12 +512,25 @@ proto.draw = function(params) {
var axis = [0,0,0]
axis[i] = 1

var alignDir = [0,0,0]
alignDir[i] = 1

//Draw tick text
if(this.tickEnable[i]) {

upwardsTolerance = 0.0 // using a value e.g. 0.25 * Math.PI could allow downwards ticks (45 degrees)

if(this.tickAngle[i] === -3600) {
this.tickAngle[i] = 0
this._tickAlign[i] = 'auto'
} else {
this._tickAlign[i] = -1
}

alignOpt = [this._tickAlign[i], upwardsTolerance, hv_ratio]
if(alignOpt[0] === 'auto') alignOpt[0] = 1
else alignOpt[0] = parseInt('' + alignOpt[0])

alignDir = [0,0,0]
solveTickAlignments(i, minor, major)

//Add tick padding
for(var j=0; j<3; ++j) {
offset[j] += pixelScaleF * minor[j] * this.tickPad[j] / model[5*j]
Expand All @@ -490,7 +540,7 @@ proto.draw = function(params) {
this._text.drawTicks(
i,
this.tickSize[i],
this.tickAngle[i] + 0.5 * Math.PI,
this.tickAngle[i],
offset,
this.tickColor[i],
axis,
Expand All @@ -501,22 +551,27 @@ proto.draw = function(params) {
//Draw labels
if(this.labelEnable[i]) {

upwardsTolerance = 0 // no tolerance for titles
alignOpt = [this._labelAlign[i], upwardsTolerance, hv_ratio]
if(alignOpt[0] === 'auto') alignOpt[0] = 1
else alignOpt[0] = parseInt('' + alignOpt[0])

var alignDir = [0,0,0]
if(this.labels[i].length > 4) { // for large label axis enable alignDir to axis
alignTo(i)
}

//Add label padding
for(var j=0; j<3; ++j) {
offset[j] += pixelScaleF * minor[j] * this.labelPad[j] / model[5*j]
}
offset[i] += 0.5 * (bounds[0][i] + bounds[1][i])

var alignDir = [0,0,0]
if(this.labels[i].length > 4) { // for large label axis enable alignDir to axis
alignDir[i] = 1
}

//Draw axis
this._text.drawLabel(
i,
this.labelSize[i],
this.labelAngle[i],
this._labelAngle[i],
offset,
this.labelColor[i],
[0,0,0],
Expand Down
34 changes: 17 additions & 17 deletions lib/shaders/textVert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ const float TWO_PI = 2.0 * PI;
const float HALF_PI = 0.5 * PI;
const float ONE_AND_HALF_PI = 1.5 * PI;

int option = int(floor(alignOpt.x + 0.001));
float up_tolerance = alignOpt.y;
float hv_ratio = alignOpt.z;

float positive_angle(float a) {
if (a < 0.0) return a + TWO_PI;
return a;
}

float look_upwards(float a) {
float look_upwards(float a, float tolerance) {
float b = positive_angle(a);
if ((b > HALF_PI) && (b < ONE_AND_HALF_PI)) return b - PI;
if ((b > HALF_PI + tolerance) && (b <= ONE_AND_HALF_PI + tolerance)) return b - PI;
return b;
}

Expand All @@ -48,11 +52,9 @@ float look_round_n_directions(float a, int n) {
float b = positive_angle(a);
float div = TWO_PI / float(n);
float c = roundTo(b, div);
return look_upwards(c);
return look_upwards(c, up_tolerance);
}

int option = int(floor(alignOpt.z + 0.001));

float applyAlignOption(float rawAngle) {

if (option == -1) {
Expand All @@ -63,35 +65,33 @@ float applyAlignOption(float rawAngle) {
return rawAngle;
} else if (option == 1) {
// option 1: use free angle, but flip when reversed
return look_upwards(rawAngle);
return look_upwards(rawAngle, up_tolerance);
} else if (option == 2) {
// option 2: horizontal or vertical
return look_horizontal_or_vertical(rawAngle, 0.8); // 0.8 here means: increase the chance of getting horizontal labels
return look_horizontal_or_vertical(rawAngle, hv_ratio);
}

// option 3-n: round to n directions
return look_round_n_directions(rawAngle, option);
}

bool enableAlign = (alignDir.x != 0.0) || (alignDir.y != 0.0) || (alignDir.z != 0.0);

void main() {

//Compute world offset
float axisDistance = position.z;
vec3 dataPosition = axisDistance * axis + offset;

float clipAngle = 0.0;

if ((alignDir.x != 0.0) ||
(alignDir.y != 0.0) ||
(alignDir.z != 0.0)) {
float clipAngle = angle; // i.e. user defined attributes for each tick

vec3 REF = dataPosition;
if (enableAlign) {
vec3 startPoint = project(dataPosition);
vec3 endPoint = project(dataPosition + alignDir);

vec3 startPoint = project(REF);
vec3 endPoint = project(REF + alignDir);
if (endPoint.z < 0.0) endPoint = project(dataPosition - alignDir);

clipAngle = applyAlignOption(
angle + // i.e. user defined attributes for each tick
clipAngle += applyAlignOption(
atan(
(endPoint.y - startPoint.y) * resolution.y,
(endPoint.x - startPoint.x) * resolution.x
Expand Down