GWT OpenLayers set sum of values of underlying VectorFeatures on cluster point - gwt

I'm using gwt-openlayers-1.0, currently learning this example (Animated Cluster Strategy).
In my project each VectoreFeature has a numeric label and I want to display sums of label values of underlying points on each cluster point. Is there a way to do that?
upd:
According to this article (The “Most Important” Strategy part) in JS it would look like this:
// for each feature:
feature.attributes = { result_count: 10 };
...
var style = new OpenLayers.Style({
...
} , context: {
label: function(feature) {
if (feature.cluster) {
var result_count = 0;
for (var i = 0; i < feature.cluster.length; i++) {
result_count += feature.cluster[i].attributes.result_count;
}
features.attributes.label = result_count.toString();
} else {
features.attributes.label = features.attributes.result_count.toString();
}
}
}
But I can't find a way to implement this in gwt-openlayers:
org.gwtopenmaps.openlayers.client.Style style = new org.gwtopenmaps.openlayers.client.Style();
style.setLabel( ??? );

I don't think this is possible.
I also don't think this is possible in standard OpenLayers with the standard AnimatedCluster.
Your best guess is to first go to https://github.com/acanimal/AnimatedCluster and ask there if what you want is possible (in standard openlayers).
If they say it is possible, and say how come back here and I can look further into it.
If they say it is also not possible in standard openlayers, then it is also not possible in gwt openlayers.

I enhanced the Animated Cluster With Popup example to do what you ask.
Will take some time before this is online though.
Changes I made are :
First I added an attribute to each feature added to the map. This feature just is a random number that we want to display the sum of when clicking a clustered feature :
for (int i = 0; i < points.size(); i++)
{
features[i] = new VectorFeature(points.get(i));
Attributes attributes = new Attributes();
attributes.setAttribute("examplenumber", Random.nextInt(10));
features[i].setAttributes(attributes);
}
Second change is in the public void onFeatureSelected(FeatureSelectedEvent eventObject)
int totalNumber = 0;
VectorFeature[] clusters = eventObject.getVectorFeature().getCluster();
for (int i = 0; i < clusters.length; i++)
{
GWT.log("examplenumber = " + clusters[i].getAttributes().getAttributeAsInt("examplenumber"));
totalNumber += clusters[i].getAttributes().getAttributeAsInt("examplenumber");
}
Now totalnumber contains the sum of all examplenumber attribute values.
I believe this solves your problem ?

In method where I assign strategy to the VectorLayer:
{
org.gwtopenmaps.openlayers.client.Style style = new org.gwtopenmaps.openlayers.client.Style();
style.setJSObject(getOpenLayersStyle());
}
And where the magic is done:
private native JSObject getOpenLayersStyle() /*-{
var style = new $wnd.OpenLayers.Style({
fontColor: "#FFFFFF",
fontSize: "12px",
label: "${countLabel}"
}, { context: {
countLabel: function(feature) {
var countLabel;
if (feature.cluster) {
var result_count = 0;
for (var i = 0; i < feature.cluster.length; i++) {
result_count += feature.cluster[i].attributes.result_count;
}
countLabel = result_count.toString();
} else {
countLabel = feature.attributes.result_count.toString();
}
feature.attributes.label = countLabel;
return countLabel;
}
}
});
return style;
}-*/;

Related

Audioworklet loop

I'm trying to create an audioworklet that loops a single instance of a sound to create a sort of sustain effect. No matter how many sections of the input I loop, I keep hearing a blip type skipping sound. How many calls to the processor is one instance?
To give you an idea, this is what I have so far:
constructor() {
super();
this.sound = [];
this.count = 20;
this.step = [0, 0];
}
process(inputs, outputs, parameters) {
if (inputs && inputs.length) {
for (var i = 0; i < inputs[0].length; i++) {
var input = inputs[0][i];
var output = outputs[0][i];
if (!this.sound[i]) {
this.sound[i] = [];
}
if (this.sound[i].length < this.count) {
this.sound[i].push([]);
for (var j = 0; j < input.length; j++) {
this.sound[i][this.sound[i].length - 1][j] = input[j];
}
} else if (this.sound[i]) {
var s = this.sound[i][this.step[i] % this.sound[i].length];
for (var j = 0; j < s.length; j++) {
output[j] = s[j];
}
this.step[i]++;
}
}
}
return true;
}
So the idea is that I capture the incoming input in an array of N length for each channel(in my case there are 2 channels). Then once that array is full, I cycle through that array to fill the output until the node is disabled.
Thanks for the fiddle. Very helpful.
I didn't look to see what was causing the clicks, but I took your example and modified it very slightly like so:
// #channels 2
// #duration 1.0
// #sampleRate 44100
var bufferSize = 4096;
let ctx = context;
let osc = ctx.createOscillator();
osc.start();
let myPCMProcessingNode = ctx.createScriptProcessor(bufferSize, 2, 2);
let _count = 1;
var sound = [];
var count = _count++;
console.log(count)
var hesitate = 0;
var step = [0, 0];
//Logic to pay attention to
myPCMProcessingNode.onaudioprocess = function(e) {
for(var i = 0; i<2; i++){
var input = e.inputBuffer.getChannelData(i);
var output = e.outputBuffer.getChannelData(i);
if (!sound[i]) {
sound[i] = [];
}
if (sound[i].length < count) {
sound[i].push([]);
for (var j = 0; j < input.length; j++) {
sound[i][sound[i].length - 1][j] = input[j];
}
} else if (sound[i]) {
var s = sound[i][step[i] % sound[i].length];
for (var j = 0; j < s.length; j++) {
output[j] = s[j];
}
step[i]++;
}
}
}
//To hear
osc.connect(myPCMProcessingNode).connect(ctx.destination);
I pasted this in the code window at https://hoch.github.io/canopy. Press the top left button (arrow) to the left of the code window, and you can see the rendered audio. You can see that the output (frequency is 10 instead of 440 to make it easier to see) is discontinuous. This causes the clicks you hear. You can also change the frequency to 100 and find discontinuities in the output.
I hope this is enough to help you figure out what's wrong with your buffering.
An alternative is to create an AudioBufferSourceNode with an AudioBuffer of the basic sample. You can set the AudioBufferSourceNode to loop the whole buffer. This doesn't solve the clicking problem, but it is somewhat simpler.
But this is a general problem of looping any buffer. Unless you arrange the last sample to be close to the first sample, you will hear clicks when you wrap around. You either need to grab chunks where the first and last samples are nearly the same, or modified the chunks so they ramp up at the beginning in some way and ramp down at the end in some way.

How to add Filtered by in FilterBar?

I am trying to implement the FilterBar. When clicked on Hide Filter Bar, I want to display Filtered by(): Filter name1, Filter 2, Filter 3. Something like the below screenshot:
But I want to do it using FilterBar control.
Also, when I add some data to the Filters, I'm not getting the numbers of filters() used on the filter bar.
Example:
You have to use GetFiltersWithValue.
onInit(){
...
this.oFilterBar = this.byId("filterbarID);
this.oFilterBar.registerGetFiltersWithValues(this.fGetFiltersWithValues);
...
}
....
fGetFiltersWithValues: function() {
var i;
var oControl;
var aFilters = this.getFilterGroupItems();
var aFiltersWithValue = [];
for (i = 0; i < aFilters.length; i++) {
oControl = this.determineControlByFilterItem(aFilters[i]);
if (oControl && oControl.getValue && oControl.getValue()) {
aFiltersWithValue.push(aFilters[i]);
}
}
return aFiltersWithValue;
},

VS Code extension how to edit in context?

Her is the class I use automatically capitalize true, false, ...
export class StUpdater {
private _lines: number;
private _strings: Array<string>;
constructor() {
this._lines = 0;
this._strings = ['true', 'false', 'exit', 'continue', 'return'];
}
Update(Cntx: boolean = false) {
let editor = window.activeTextEditor;
if (!editor || (editor.document.languageId != 'st')) {
window.showErrorMessage('No editor!')
return;
}
let doc = editor.document;
if (Cntx == false) {
if (this._lines >= doc.lineCount) {
this._lines = doc.lineCount;
return;
}
this._lines = doc.lineCount;
let AutoFormat = workspace.getConfiguration('st').get('autoFormat');
if (!AutoFormat) {
return;
}
}
let edit = new WorkspaceEdit();
for (let line = 0; line < doc.lineCount; line++) {
const element = doc.lineAt(line);
for (let i = 0; i < this._strings.length; i++) {
let str = this._strings[i];
let last_char = 0;
while (element.text.indexOf(str, last_char) >= 0) {
let char = element.text.indexOf(str, last_char);
last_char = char + str.length;
edit.replace(
doc.uri,
new Range(
new Position(line, char),
new Position(line, last_char)
),
str.toUpperCase()
);
}
}
}
return workspace.applyEdit(edit);
}
public dispose() {
}
}
This code works fine, but I do not want to replace it inside the string or comment. How do I do that? I cannot find preg version of replace and even if I do, in one line I do not know if it is comment or not if it is multiple line comment.
If I understand you correctly you want capitalize only certain elements (identifiers probably), but not words in comments or strings, correct? That requires to identify lexical elements in the text, which is a mapping of a range of letters to a lexical type. This is usually done by a lexer. It's not difficult to write one by hand which walks over the characters on top of your current processing and find those ranges that can be manipulated.

css/javascript multiple card flip: reset other cards

So I'm currently using this one: http://jsfiddle.net/nawdpj5j/10/
Now what I need is that when I flip one card (doesn't matter which one) and then flip another one the first one resets/turnes back.
I think I need to add something in here:
var init = function() {
var flippers = document.getElementsByClassName("flip");
for(i = 0; i < flippers.length; i++){
flippers[i].addEventListener( 'click', function(){
var cardID = this.dataset.targetid;
var card = document.getElementById(cardID);
card.toggleClassName('flipped');
}, false);
}
};
Thank you in advance!
You can get an array of all flipped cards and flip them back whenever a card is flipped like so:
var init = function() {
var flippers = document.getElementsByClassName("flip");
for (i = 0; i < flippers.length; i++) {
flippers[i].addEventListener('click', function() {
var cardID = this.dataset.targetid;
var card = document.getElementById(cardID);
var flipped = document.getElementsByClassName('flipped');
for (i = 0; i < flipped.length; i++) {
if (card !== flipped[i]) {
flipped[i].toggleClassName('flipped');
}
}
card.toggleClassName('flipped');
}, false);
}
};
window.addEventListener('DOMContentLoaded', init, false);
Here is a link to a working demo JS FIDDLE

CreateJS swapping display list containers with the use of classes

This is a 2D Jenga game.
So I am currently making a Jenga game in createjs. When users take a block out from the Jenga building they can move it around, ultimately users are suppose to be able to take the piece and move it to the top like a typical Jenga game. The problem is you can take any piece out move it towards the bottom it appears to be in front of the Jenga building, but once you move a block towards the top it goes behind the building. I have a piece class which creates one block looks like this:
var GamepeiceComponent = (function() {
var assets = {};
var offset;
var gamePeice;
var currentX;
var currentY;
var newContainer;
this.makePiece = function(ingredient) {
gamePeice = new createjs.Container();
assets.peice = new createjs.Bitmap(queue.getResult(ingredient));
gamePeice.on('pressmove', handlePieceDrag);
gamePeice.on("pressup", handlePieceUp);
gamePeice.on("mousedown", handleMouseDown);
gamePeice.cursor = 'pointer';
gamePeice.addChild(assets.peice);
}
function handleMouseDown(e) {
// Game.block.swapChildren(e.currentTarget, Game.block);
for(var i = 0; i < Game.stage.children.length; i++){
console.log(Game.stage.children[i]);
//Game.stage.swapChildren(e.currentTarget, Game.stage.children[i])
}
//Game.stage.addChildAt(gamePeice,1);
offset = {x: e.target.x - e.stageX, y: e.target.y - e.stageY};
createjs.EventDispatcher.initialize(GamepeiceComponent.prototype);
gamePeice.dispatchEvent("pieceClicked");
}
function handlePieceDrag(e) {
e.target.x = e.stageX + offset.x;
e.target.y = e.stageY + offset.y;
}
function handlePieceUp(e) {
e.target.x = 0;
e.target.y = 0;
}
this.addPiece = function() {
return gamePeice;
}
return this;
});
I then have a block class which creates a block using the piece class because it creates 3 pieces per block (just like Jenga) heres what that is:
var GameblockComponent = (function() {
var gameBlock;
this.makeBlock = function(ingredient, yOffset, xOffset) {
gameBlock = new createjs.Container();
for(var i=0;i<3;i++) {
var gamePieces = new GamepeiceComponent();
var makePiece = gamePieces.makePiece(ingredient);
gamePieces.addPiece().y = yOffset * i;
gamePieces.addPiece().x = xOffset * i;
gamePieces.addPiece().on('pieceClicked', handleClick);
gameBlock.addChild(gamePieces.addPiece());
}
}
function handleClick(e) {
console.log('Game Piece Clicked');
}
this.addBlock = function() {
return gameBlock;
}
return this;
});
Lastly I have a building which organizes all the blocks in order:
var GamebuildingComponent = (function(game) {
var jengaContainer;
var left = ['burger_l', 'cheese_l', 'egg_l', 'ham_l', 'lettuce_l', 'onion_l', 'pickle_l', 'salmon_l', 'sausage_l', 'tomato_l'];
var right = ['burger_r', 'cheese_r', 'egg_r', 'ham_r', 'lettuce_r', 'onion_r', 'pickle_r', 'salmon_r', 'sausage_r', 'tomato_r'];
var bread = ['bread_l', 'bread_r'];
var seed = [];
var offsets = {
xOffsetLeft: 15,
yOffsetLeft: -33,
xPosLeft: 170,
xOffsetRight: 17,
yOffsetRight: 33,
yPosRight:100
};
function init() {
jengaContainer = new createjs.Container();
createBread(15);
createSubBlock(40);
createBread(160);
createSubBlock(185);
createBread(305);
}
function createBread(yOffset) {
var block = new GameblockComponent();
var breadLeft = block.makeBlock(bread[0], offsets.xOffsetLeft, offsets.yOffsetLeft);
block.addBlock().x = 170;
block.addBlock().y = yOffset;
jengaContainer.addChildAt(block.addBlock(), 0);
}
// LEFT: left side facing to left
// RIGHT: right side facing to right
function createSubBlock(yOffset) {
for(var i=0;i<5;i++) {
var block = new GameblockComponent();
var random = Math.floor(Math.random()*left.length);
// prevents duplicates
while(seed.indexOf(random) > -1) {
var random = Math.floor(Math.random()*left.length);
}
if(i%2 != 0) {
var ingredient = block.makeBlock(left[random], offsets.xOffsetLeft, offsets.yOffsetLeft);
block.addBlock().x = 170;
} else {
var ingredient = block.makeBlock(right[random], offsets.xOffsetRight, offsets.yOffsetRight);
block.addBlock().x = 105;
}
seed.push(random);
block.addBlock().y = 23 * i + yOffset;
jengaContainer.addChildAt(block.addBlock(), 0);
}
}
this.addBuilding = function() {
return jengaContainer;
}
init();
return this;
});
It all works fine except for when you move a lower piece towards the top the piece goes behind the jenga building, and of course its how the displaylist works, how would I be able to swap the piece correctly and where? I was listing all my child elements that are on the stage and it gave me one child (the jenga building). That child gave me 13 children (each block).
Then I just add the Jenga building to a view, and that view gets called from a controller.
You're probably looking for the setChildIndex method of the Container object.
function handleMouseDown(e) {
Game.block.setChildIndex(e.currentTarget, Game.block.children.length - 1);
}