Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devdoc #48

Merged
merged 15 commits into from
Aug 2, 2023
Prev Previous commit
Next Next commit
Revert "Delete ContMulti.js"
This reverts commit 949feac.
  • Loading branch information
zmalkmus committed Aug 2, 2023
commit 0b879b7d3f9b2551506c1e7aeb8ab8c45c72ce8a
283 changes: 283 additions & 0 deletions agvis/static/js/ContMulti.js
Original file line number Diff line number Diff line change
@@ -0,0 1,283 @@
/*
const contourVertexShader = `
precision mediump float;
attribute vec2 aPosition;
attribute float aValue;
uniform mat4 uProjection;
varying float vValue;

void main() {
gl_Position = uProjection * vec4(aPosition, 0, 1);
vValue = aValue;
}
`;

const contourFragmentShader = `
precision mediump float;
varying float vValue;
uniform sampler2D uColormapSampler;
uniform float uScaleMin;
uniform float uScaleMax;

void main() {
float value = (vValue - uScaleMin) / (uScaleMax - uScaleMin);
gl_FragColor = texture2D(uColormapSampler, vec2(value, 0.0));
}
`;
*/
//The mutilayer version of the contour layer
function renderMultiCont(canvas, { size, bounds, project, needsProjectionUpdate }) {
const context = this._context;
if (!context) return;
const SysParam = this._newlayer.data;
if (!SysParam) return;
const Bus = SysParam.Bus;
//const Idxvgs = this._newlayer.Idxvgs;
//if (!Idxvgs) return;
//const Varvgs = this._newlayer.Varvgs;
//if (!Varvgs) return;

const temparr = [];
let x;

//Select data based on where the timer for the animation is at
for (let j = 0; j < this._newlayer.data["history"]["t"].length; j ) {

let val = Number(this._newlayer.data["history"]["t"][j]);
if (val >= Number(this._newlayer.time)) {

x = j;
break;
}
}


temparr.push(this._newlayer.data["history"]["varvgs"][x].length);
const Varvgs = new dime.NDArray("F", temparr, this._newlayer.data["history"]["varvgs"][x]);

let paramCache = this._cache.get(SysParam);
if (!paramCache) {
paramCache = {};
this._cache.set(SysParam, paramCache);
}

//I don't entirely understand how it works, but it basically uses delauney triangles to create heat maps between nodes, then it uses a gradient function to smooth it over
const nelems = Bus.idx.length;

let { busLatLngCoords } = paramCache;
if (!busLatLngCoords) {
busLatLngCoords = paramCache.busLatLngCoords =
new NDArray('C', [nelems, 2]);

for (let i=0; i < nelems; i) {
const lat = Bus.ycoord[i];
const lng = Bus.xcoord[i];
busLatLngCoords.set(lat, i, 0);
busLatLngCoords.set(lng, i, 1);
}
}

let { busPixelCoords } = paramCache;
if (!busPixelCoords || needsProjectionUpdate) {
busPixelCoords = paramCache.busPixelCoords = new NDArray('C', [nelems, 2]);
for (let i=0; i < nelems; i) {
const lat = busLatLngCoords.get(i, 0);
const lng = busLatLngCoords.get(i, 1);
const point = project(L.latLng(lat, lng));
busPixelCoords.set(point.x, i, 0);
busPixelCoords.set(point.y, i, 1);
}
}

let { busTriangles } = paramCache;
if (!busTriangles || needsProjectionUpdate) {
const delaunay = new d3.Delaunay(busLatLngCoords.array);

busTriangles = paramCache.busTriangles =
new NDArray('C', [delaunay.triangles.length/3, 3], delaunay.triangles);
}
/*
let idxvgsCache = this._cache.get(Idxvgs);
if (!idxvgsCache) {
idxvgsCache = {};
this._cache.set(idxvgsCache);
}

let { variableSubIndices } = idxvgsCache;

if (!variableSubIndices) {
variableSubIndices = idxvgsCache.variableSubIndices =
Idxvgs.Bus.V.extents();

variableSubIndices.end -= variableSubIndices.begin - 1;
variableSubIndices.begin = 0;
}
*/
let gl = this._cache.get(canvas);
if (!gl) {
gl = canvas.getContext('webgl2');
this._cache.set(canvas, gl);
}

let glCache = this._cache.get(gl);
if (!glCache) {
glCache = {};
this._cache.set(gl, glCache);
}

let { programInfo } = glCache;
if (!programInfo) {
programInfo = glCache.programInfo =
twgl.createProgramInfo(gl, [contourVertexShader, contourFragmentShader]);
}

let { aPositionBufferInfo } = glCache;
if (!aPositionBufferInfo || needsProjectionUpdate) {
aPositionBufferInfo = glCache.aPositionBufferInfo = twgl.createBufferInfoFromArrays(gl, {
aPosition: {
data: busPixelCoords.array,
numComponents: 2,
},
});
}

let { aIndicesBufferInfo } = glCache;
if (!aIndicesBufferInfo) {
aIndicesBufferInfo = glCache.aIndicesBufferInfo = twgl.createBufferInfoFromArrays(gl, {
indices: {
data: busTriangles.array,
numComponents: 3,
},
});
}

let { uColormapSampler } = glCache;
if (!uColormapSampler) {
uColormapSampler = glCache.uColormapSampler = twgl.createTexture(gl, {
src: '/img/map256.png',
wrapS: gl.CLAMP_TO_EDGE,
wrapT: gl.CLAMP_TO_EDGE,
min: gl.LINEAR_MIPMAP_LINEAR,
});
}

const uProjection = [
2.0 / gl.canvas.width, 0, 0, 0,
0, -2.0 / gl.canvas.height, 0, 0,
0, 0, 0, 0,
-1, 1, 0, 1,
];

const vars = new dime.NDArray(Varvgs.order, Varvgs.shape, Float32Array.from(Varvgs.array));
const variableValue = vars.subarray(this._variableRange);

let maxVoltageDifference = Math.abs(variableValue.get(0, 0) - 1.0);
for (let i=1, l=variableValue.shape[1]; i<l; i) {
const v = Math.abs(variableValue.get(0, i) - 1.0);
maxVoltageDifference = Math.max(maxVoltageDifference, v);
}

const uScaleMin = this._uScaleMin;
const uScaleMax = this._uScaleMax;

const aValueBufferInfo = twgl.createBufferInfoFromArrays(gl, {
aValue: {
data: variableValue.array,
numComponents: 1,
},
});

if(this._render) {
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, aPositionBufferInfo);
twgl.setBuffersAndAttributes(gl, programInfo, aValueBufferInfo);
twgl.setBuffersAndAttributes(gl, programInfo, aIndicesBufferInfo);
twgl.setUniforms(programInfo, {
uScaleMin,
uScaleMax,
uProjection,
uColormapSampler,
});
twgl.drawBufferInfo(gl, aIndicesBufferInfo, gl.TRIANGLES);

}
else {
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
}
}

L.MultiContLayer = L.CanvasLayer.extend({
options: {
render: renderMultiCont,
},

initialize(newlayer, options) {
this._context = null;
this._variableRange = null;
this._variableRelIndices = null;
this._uScaleMin = 0.8;
this._uScaleMax = 1.2;
this._cache = new WeakMap();
this._render = false;
this._newlayer = newlayer;

this.variableName = null;
L.CanvasLayer.prototype.initialize.call(this, options);
},

update(context) {
this._context = context;
//console.log("stuff");
this.redraw();
},

onAdd(map) {
L.CanvasLayer.prototype.onAdd.call(this, map);
this.getPane().classList.add("multicont-pane" this._newlayer.num);
},

storeRelativeIndices(idx) {
this._variableRelIndices = idx;
},

showVariable(name) {
// updates the name of variables for the contour map
this.variableName = name;

this._variableRange = this._variableRelIndices[name];
this.redraw();
},

//Update range for the current shown variable
updateRange(lower, upper){
this._uScaleMax = upper;
this._uScaleMin = lower;
},

toggleRender() {
this._render = !this._render;
console.log("MultiContour rendering: ", this._render);
},

//Used for prioritize button, just copies over everything
stealVals(oldlayer) {

this._context = oldlayer._context;
this._variableRange = oldlayer._variableRange;
this._variableRelIndices = oldlayer._variableRelIndices;
this._uScaleMin = oldlayer._uScaleMin;
this._uScaleMax = oldlayer._uScaleMax;
this._cache = oldlayer._cache;
this.variableName = oldlayer.variableName;
this._render = oldlayer._render;

}
});

L.multicontLayer = function(newlayer, options) {
console.log("New multicont");
return new L.MultiContLayer(newlayer, options);
};