StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
5.0 KiB
219 lines
5.0 KiB
4 years ago
|
"use strict"
|
||
|
|
||
|
module.exports = createTextSprites
|
||
|
|
||
|
var createBuffer = require('gl-buffer')
|
||
|
var createVAO = require('gl-vao')
|
||
|
var vectorizeText = require('vectorize-text')
|
||
|
var createShader = require('./shaders').text
|
||
|
|
||
|
var globals = window || process.global || {}
|
||
|
var __TEXT_CACHE = globals.__TEXT_CACHE || {}
|
||
|
globals.__TEXT_CACHE = {}
|
||
|
|
||
|
//Vertex buffer format for text is:
|
||
|
//
|
||
|
/// [x,y,z] = Spatial coordinate
|
||
|
//
|
||
|
|
||
|
var VERTEX_SIZE = 3
|
||
|
|
||
|
function TextSprites(
|
||
|
gl,
|
||
|
shader,
|
||
|
buffer,
|
||
|
vao) {
|
||
|
this.gl = gl
|
||
|
this.shader = shader
|
||
|
this.buffer = buffer
|
||
|
this.vao = vao
|
||
|
this.tickOffset =
|
||
|
this.tickCount =
|
||
|
this.labelOffset =
|
||
|
this.labelCount = null
|
||
|
}
|
||
|
|
||
|
var proto = TextSprites.prototype
|
||
|
|
||
|
//Bind textures for rendering
|
||
|
var SHAPE = [0,0]
|
||
|
proto.bind = function(model, view, projection, pixelScale) {
|
||
|
this.vao.bind()
|
||
|
this.shader.bind()
|
||
|
var uniforms = this.shader.uniforms
|
||
|
uniforms.model = model
|
||
|
uniforms.view = view
|
||
|
uniforms.projection = projection
|
||
|
uniforms.pixelScale = pixelScale
|
||
|
SHAPE[0] = this.gl.drawingBufferWidth
|
||
|
SHAPE[1] = this.gl.drawingBufferHeight
|
||
|
this.shader.uniforms.resolution = SHAPE
|
||
|
}
|
||
|
|
||
|
proto.unbind = function() {
|
||
|
this.vao.unbind()
|
||
|
}
|
||
|
|
||
|
proto.update = function(bounds, labels, labelFont, ticks, tickFont) {
|
||
|
var data = []
|
||
|
|
||
|
function addItem(t, text, font, size, lineSpacing, styletags) {
|
||
|
var fontcache = __TEXT_CACHE[font]
|
||
|
if(!fontcache) {
|
||
|
fontcache = __TEXT_CACHE[font] = {}
|
||
|
}
|
||
|
var mesh = fontcache[text]
|
||
|
if(!mesh) {
|
||
|
mesh = fontcache[text] = tryVectorizeText(text, {
|
||
|
triangles: true,
|
||
|
font: font,
|
||
|
textAlign: 'center',
|
||
|
textBaseline: 'middle',
|
||
|
lineSpacing: lineSpacing,
|
||
|
styletags: styletags
|
||
|
})
|
||
|
}
|
||
|
var scale = (size || 12) / 12
|
||
|
var positions = mesh.positions
|
||
|
var cells = mesh.cells
|
||
|
for(var i=0, nc=cells.length; i<nc; ++i) {
|
||
|
var c = cells[i]
|
||
|
for(var j=2; j>=0; --j) {
|
||
|
var p = positions[c[j]]
|
||
|
data.push(scale*p[0], -scale*p[1], t)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Generate sprites for all 3 axes, store data in texture atlases
|
||
|
var tickOffset = [0,0,0]
|
||
|
var tickCount = [0,0,0]
|
||
|
var labelOffset = [0,0,0]
|
||
|
var labelCount = [0,0,0]
|
||
|
var lineSpacing = 1.25
|
||
|
var styletags = {
|
||
|
breaklines:true,
|
||
|
bolds: true,
|
||
|
italics: true,
|
||
|
subscripts:true,
|
||
|
superscripts:true
|
||
|
}
|
||
|
for(var d=0; d<3; ++d) {
|
||
|
|
||
|
//Generate label
|
||
|
labelOffset[d] = (data.length/VERTEX_SIZE)|0
|
||
|
addItem(
|
||
|
0.5*(bounds[0][d]+bounds[1][d]),
|
||
|
labels[d],
|
||
|
labelFont[d],
|
||
|
12, // labelFontSize
|
||
|
lineSpacing,
|
||
|
styletags
|
||
|
)
|
||
|
labelCount[d] = ((data.length/VERTEX_SIZE)|0) - labelOffset[d]
|
||
|
|
||
|
//Generate sprites for tick marks
|
||
|
tickOffset[d] = (data.length/VERTEX_SIZE)|0
|
||
|
for(var i=0; i<ticks[d].length; ++i) {
|
||
|
if(!ticks[d][i].text) {
|
||
|
continue
|
||
|
}
|
||
|
addItem(
|
||
|
ticks[d][i].x,
|
||
|
ticks[d][i].text,
|
||
|
ticks[d][i].font || tickFont,
|
||
|
ticks[d][i].fontSize || 12,
|
||
|
lineSpacing,
|
||
|
styletags
|
||
|
)
|
||
|
}
|
||
|
tickCount[d] = ((data.length/VERTEX_SIZE)|0) - tickOffset[d]
|
||
|
}
|
||
|
|
||
|
this.buffer.update(data)
|
||
|
this.tickOffset = tickOffset
|
||
|
this.tickCount = tickCount
|
||
|
this.labelOffset = labelOffset
|
||
|
this.labelCount = labelCount
|
||
|
}
|
||
|
|
||
|
//Draws the tick marks for an axis
|
||
|
proto.drawTicks = function(d, scale, angle, offset, color, axis, alignDir, alignOpt) {
|
||
|
if(!this.tickCount[d]) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
this.shader.uniforms.axis = axis
|
||
|
this.shader.uniforms.color = color
|
||
|
this.shader.uniforms.angle = angle
|
||
|
this.shader.uniforms.scale = scale
|
||
|
this.shader.uniforms.offset = offset
|
||
|
this.shader.uniforms.alignDir = alignDir
|
||
|
this.shader.uniforms.alignOpt = alignOpt
|
||
|
this.vao.draw(this.gl.TRIANGLES, this.tickCount[d], this.tickOffset[d])
|
||
|
}
|
||
|
|
||
|
//Draws the text label for an axis
|
||
|
proto.drawLabel = function(d, scale, angle, offset, color, axis, alignDir, alignOpt) {
|
||
|
if(!this.labelCount[d]) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
this.shader.uniforms.axis = axis
|
||
|
this.shader.uniforms.color = color
|
||
|
this.shader.uniforms.angle = angle
|
||
|
this.shader.uniforms.scale = scale
|
||
|
this.shader.uniforms.offset = offset
|
||
|
this.shader.uniforms.alignDir = alignDir
|
||
|
this.shader.uniforms.alignOpt = alignOpt
|
||
|
this.vao.draw(this.gl.TRIANGLES, this.labelCount[d], this.labelOffset[d])
|
||
|
}
|
||
|
|
||
|
//Releases all resources attached to this object
|
||
|
proto.dispose = function() {
|
||
|
this.shader.dispose()
|
||
|
this.vao.dispose()
|
||
|
this.buffer.dispose()
|
||
|
}
|
||
|
|
||
|
function tryVectorizeText(text, options) {
|
||
|
try {
|
||
|
return vectorizeText(text, options)
|
||
|
} catch(e) {
|
||
|
console.warn('error vectorizing text:"' + text + '" error:', e)
|
||
|
return {
|
||
|
cells: [],
|
||
|
positions: []
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createTextSprites(
|
||
|
gl,
|
||
|
bounds,
|
||
|
labels,
|
||
|
labelFont,
|
||
|
ticks,
|
||
|
tickFont) {
|
||
|
|
||
|
var buffer = createBuffer(gl)
|
||
|
var vao = createVAO(gl, [
|
||
|
{ "buffer": buffer,
|
||
|
"size": 3
|
||
|
}
|
||
|
])
|
||
|
|
||
|
var shader = createShader(gl)
|
||
|
shader.attributes.position.location = 0
|
||
|
|
||
|
var result = new TextSprites(
|
||
|
gl,
|
||
|
shader,
|
||
|
buffer,
|
||
|
vao)
|
||
|
|
||
|
result.update(bounds, labels, labelFont, ticks, tickFont)
|
||
|
|
||
|
return result
|
||
|
}
|