Performance textfield over scaleSlider - rascal

I'm trying to create something that looks like an interactive bar-chart. I'm using a method that creates a figure based on a list of boxes.
I'm using scaleSlider to interactively change the number of boxes shown in my figure. Using only one bar, the performance is OK but with 4 bars, the performance is drastically reduced.
I've tried to replace scaleSlider by textfield, to see if that improves the performance. However, i need some help to get things running.
The scaledbox example below is working and results in the screenshot below.
Figure scaledbox(){
int n = 10;
return vcat([ hcat([ scaleSlider(int() { return 0; },
int () { return 50; },
int () { return n; },
void (int s) { n = s; },
width(200)),
text(str () { return "n: <n>";})
], left(), top(), resizable(false)),
computeFigure(Figure (){ return visualizeAllUnitSizes(n); })
]);
}
How do I implement textfield to replace the scaleSlider with a textfield input field? I've tried the tfield() example from the Rascal tutor but I'm not sure how to create a small textbox that will hold an int and will run the method that generates the figure after pressing enter.
public Figure tfield(){
str entered = "";
return vcat([ box(textfield("", void(str s){ entered = s;}, fillColor("yellow")), size(20,30)),
text(str(){return "entered: <entered>";}, left())
]);
}

To answer my own question;
There was a big difference in performance between my 2015 iMac 5K model and my 2016 MacBook Pro. On my MBP the slider ran smoothly, on my iMac the slider was barely usable. So the performance issue is probably related to the high resolution of my iMac.

Related

How to use Indicator count and how to turn key event into code in MQL4

I'm just learning to code and have few questions. Can someone tell me please how to do this thing;
1- How to prevent my custom indicator being duplicated on the chart? If it's already on the chart and I will drop it on to the chart again, I want it to detect the first one and abort launching the second one.
something like this: but working :)
int OnInit()
{
int indicators_total = ChartIndicatorsTotal(0,0);
for(int i = 0; ndicators_total > i; i++)
{
if(ChartIndicatorName(0,0,i)==IndicatorName)
return(INIT_FAILED); (AND THEN EXIT)
}
}
2 - How do I detect if there is more than one indicator with the same name on the chart?
3 - How to write an "if" statement to do something if indicator "x" is not present (=0) on the chart?
Something like this: but working :)
if(IndicatorName==0)
{
Print("INDI ",IndicatorName, " NOT DETECTED");
}
4 - And is there a way to put keyboard event (F11 - full screen) into code? To make my custom indicator be able to detect when full screen is on just like with the "chart scale" ChartGetInteger(0,CHART_SCALEFIX); ?
Welcome to SOF. Look at counter below. The idea is to count number of indicators on the chart. The one you are adding will be in this list either once (this copy) or more (you are trying to add a new copy to an existing one). This example is for main chart (subwindow = 0).
int OnInit()
{
const string indName = WindowExpertName(); // name of your indicator
int counter=0;
for(int i=ChartIndicatorsTotal(0,0)-1;i>=0;i--)
{
//printf("%i %s: i=%d/%d, %s",__LINE__,__FILE__,i,ChartIndicatorsTotal(0,0),ChartIndicatorName(0,0,i));
if(ChartIndicatorName(0,0,i)==indName)
counter++;
}
if(counter>1)
{
Print("already exist!");
return INIT_FAILED;
}
//--- indicator buffers mapping
// do all other indicator preparation work here
//---
return(INIT_SUCCEEDED);
}

Change background of google slides shape to red

I am trying to find the answer in Google Slides API references for how to set the background color of a shape I have in my Google Slide. I have given it the title (using Alt Text feature) "rectangle1", so my intention is to write the code along the lines of "if shape's property "title" == "rectangle1", then set background color to red."
I can't see a single reference to "SetBackgroundFill" or SetBackgroundColor, or anything of that sort.
Is it possible?
This is another possible answer, using a so-called "container bound script", which is only accessible through the specific Slide's Tools/Script Editor menu (no other way, or else it won't work).
I found that this "container bound script" approach gives me more power over my slide, and it avoids these expensive calls to "batchUpdate", when using "stand alone" scripts as in my other "self-answer".
So, in a way, I recommend it to myself, but, perhaps, to someone else, my other approach would be a better choice.
For one thing, this approach has a much faster response time.
var hex_color = '#54BdeF';
function test1() {
var selection = SlidesApp.getActivePresentation().getSelection();
var currentPage = selection.getCurrentPage();
var selectionType = selection.getSelectionType();
var shapes = currentPage.getShapes();
for (i=0; i < shapes.length; i++) {
if (shapes[i].getTitle() == 'rectangle1') {
shape_fill = shapes[i].getFill();
shape_fill.setSolidFill(hex_color);
}
}
}
Again, as before, I would welcome any comments and suggestions.
To set background color, you need Element Operations.
The Slides API allows you to create and edit a variety of page
elements, including text boxes, images, tables, basic shapes, lines,
and embedded videos. The examples on this page show some common page
element operations that can be achieved with the API.
Following the steps specified here will do the changes in your specified shape or element. Check the example.
Well, here is my solution. If someone sees a way to improve it, I am all ears, but so far, it appears to work for me glitch-free.
First, I find the shape I am after using the following logic:
function ChangeColorMain()
{
ChangeShapeBackgroundColor('title', 'rectangle1', color_to_repl_r, color_to_repl_g, color_to_repl_b, alpha_value );
}
function ChangeShapeBackgroundColor(shape_property_name, shape_property_value, color_to_set_r, color_to_set_g, color_to_set_b) {
Logger.log( 'ChangeShapeBackgroundColor(shape_property_name=%s, shape_property_value=%s, color_to_set_r=%s, color_to_set_g=%s, color_to_set_b=%s) ',
shape_property_name, shape_property_value, color_to_set_r, color_to_set_g, color_to_set_b);
var presentation = Slides.Presentations.get(presentationId);
var slides = presentation.slides;
Logger.log('The presentation contains %s slides:', slides.length);
for (i = 0; i < slides.length; i++) {
for (j = 0; j < slides[i].pageElements.length; j++ ) {
if (shape_property_name == 'title' && shape_property_value == slides[i].pageElements[j].title) {
Logger.log('Found it');
//slides[i].pageElements[j].shape.shapeProperties.shapeBackgroundFill.solidFill.color.rgbColor.red = color_to_set_r;
SubmitRequest(slides[i].pageElements[j].objectId, color_to_set_r, color_to_set_g, color_to_set_b, alpha_value);
}
} //end of for that iterates through every element
}
}
So, you'll notice that I start my process by calling the function "ChangeColorMain" which also gets my global variables color_to_repl_r... which are defined in a different file of my google script project, but that's not important.
Once inside the ChangeShapeBackgroundColor(), I iterate through all "PageElements" on my slide (see the relevant for loops) and use if statements to check if I got to the shape I am looking for. Finally, once I have located it, I call the all important function SubmitRequest(), which is "expensive". You can't make too many calls in one day, or else Google blocks this function until the day ends. But not a problem if you are making less than 500 calls per day (this number might be wrong/might change).
Here are the details of "SubmitRequest()" which I was able to create by finally figuring out how to make sense of this reference page:
https://developers.google.com/slides/reference/rest/v1/presentations/request#UpdateShapePropertiesRequest
function SubmitRequest(shape_id, r, g, b, a) {
var rgb_color = {
red: r,
green: g,
blue: b
};
var opaque_color = {
rgbColor: rgb_color
};
var solid_fill = {
color: opaque_color,
alpha: a
};
var background_fill = {
solidFill: solid_fill
};
var shape_properties = {
shapeBackgroundFill: background_fill
};
var update_request = {
objectId: shape_id,
shapeProperties: shape_properties,
fields: "shapeBackgroundFill.solidFill.color"
};
var requests = [{
updateShapeProperties: update_request
}];
// Execute the request.
var batch_update_return = Slides.Presentations.batchUpdate({
requests: requests
}, presentationId);
Logger.log(
'This is what you get from Google after submitting batchUpdate request:\n%s', batch_update_return);
}

Stock High Charts with Custom points on X-axis

I have a requirement where i have to show custom points on x-axis instead of dates values. Also same custom data points needs to be shown on navigator as well. In the below Js fiddle, i am converting data (Per13/2016 etc) into equivalent date values and then binding the chart using converted date values.
Below is the link of the JS fiddle:- Fiddle link
In the Js fiddle, i am showing Per1,Per2 etc.on x-axis and same has to be shown on navigator as well.
Now i am facing problem with the navigator,when i changes the range using slider ,the x-axis labels changes but not according to the range selected.Also tool-tip formatting is getting changed.
Can you please let me know how to handle this scenario and best way to do the same.
//few code lines to post fiddle link
xAxis: {
labels: {
formatter: function () {
if(fiscal13){
var perDate = new Date(this.value);
return 'Per' + (perDate.getMonth() + 1);
}
}
}
}
I am not sure if I am right, but I think you are overdoing this.
Let's keep original data, so remove fiscal13Data.Data.forEach(function(item) { .. }); function. And When creating data, use simply index of the point as x-value:
var cost = [],
usage = [],
dataLength = fiscal13Data.Data.length
i = 0;
for (i; i < dataLength; i += 1) {
// need to sum costs
cost.push([
i, // the index
fiscal13Data.Data[i]['Cost'] // cost
]);
usage.push([
i, // the index
fiscal13Data.Data[i]['Usage'] // Usage
]);
}
Now you can get to the "Per13/2016" strings in a simple way in xAxis labels' formatters:
var str = fiscal13Data.Data[this.value].Date;
In tooltip formatter, it is almost exactly the same:
var str = fiscal13Data.Data[this.x].Date;
And here is working demo: http://jsfiddle.net/qneuh4Ld/3/
Note: You data looks a bit strange - don't you want to sort it first? Also, you have twice every date (e.g. "Per13/2016" - once for "water" and once for "electric").

Very slow hover interactions in OpenLayers 3 with any browser except Chrome

I have two styles of interactions, one highlights the feature, the second places a tooltop with the feature name. Commenting both out, they're very fast, leave either in, the map application slows in IE and Firefox (but not Chrome).
map.addInteraction(new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
layers: [stationLayer],
style: null // this is actually a style function but even as null it slows
}));
$(map.getViewport()).on('mousemove', function(evt) {
if(!dragging) {
var pixel = map.getEventPixel(evt.originalEvent);
var feature = null;
// this block directly below is the offending function, comment it out and it works fine
map.forEachFeatureAtPixel(pixel, function(f, l) {
if(f.get("type") === "station") {
feature = f;
}
});
// commenting out just below (getting the feature but doing nothing with it, still slow
if(feature) {
target.css("cursor", "pointer");
$("#FeatureTooltip").html(feature.get("name"))
.css({
top: pixel[1]-10,
left: pixel[0]+15
}).show();
} else {
target.css("cursor", "");
$("#FeatureTooltip").hide();
}
}
});
I mean this seems like an issue with OpenLayers-3 but I just wanted to be sure I wasn't overlooking something else here.
Oh yeah, there's roughly 600+ points. Which is a lot, but not unreasonably so I would think. Zooming-in to limit the features in view definitely helps. So I guess this is a # of features issue.
This is a known bug and needs more investigation. You can track progress here: https://github.com/openlayers/ol3/issues/4232.
However, there is one thing you can do to make things faster: return a truthy value from map.forEachFeatureAtPixel to stop checking for features once one was found:
var feature = map.forEachFeatureAtPixel(pixel, function(f) {
if (f.get('type') == 'station') {
return feature;
}
});
i had same issue, solved a problem by setInterval, about this later
1) every mouse move to 1 pixel fires event, and you will have a quee of event till you stop moving, and the quee will run in calback function, and freezes
2) if you have an objects with difficult styles, all element shown in canvas will take time to calculate for if they hit the cursor
resolve:
1. use setInterval
2. check for pixels moved size from preview, if less than N, return
3. for layers where multiple styles, try to simplify them by dividing into multiple ones, and let only one layer by interactive for cursor move
function mouseMove(evt) {
clearTimeout(mm.sheduled);
function squareDist(coord1, coord2) {
var dx = coord1[0] - coord2[0];
var dy = coord1[1] - coord2[1];
return dx * dx + dy * dy;
}
if (mm.isActive === false) {
map.unByKey(mm.listener);
return;
}
//shedules FIFO, last pixel processed after 200msec last process
const elapsed = (performance.now() - mm.finishTime);
const pixel = evt.pixel;
const distance = squareDist(mm.lastP, pixel);
if (distance > 0) {
mm.lastP = pixel;
mm.finishTime = performance.now();
mm.sheduled = setTimeout(function () {
mouseMove(evt);
}, MIN_ELAPSE_MSEC);
return;
} else if (elapsed < MIN_ELAPSE_MSEC || mm.working === true) {
// console.log(`distance = ${distance} and elapsed = ${elapsed} mesc , it never should happen`);
mm.sheduled = setTimeout(function () {
mouseMove(evt);
}, MIN_ELAPSE_MSEC);
return;
}
//while multithreading is not working on browsers, this flag is unusable
mm.working = true;
let t = performance.now();
//region drag map
const vStyle = map.getViewport().style;
vStyle.cursor = 'default';
if (evt.dragging) {
vStyle.cursor = 'grabbing';
}//endregion
else {
//todo replace calback with cursor=wait,cursor=busy
UtGeo.doInCallback(function () {
checkPixel(pixel);
});
}
mm.finishTime = performance.now();
mm.working = false;
console.log('mm finished', performance.now() - t);
}
In addition to #ahocevar's answer, a possible optimization for you is to utilize the select interaction's select event.
It appears that both the select interaction and your mousemove listener are both checking for hits on the same layers, doing double work. The select interaction will trigger select events whenever the set of selected features changes. You could listen to it, and show the popup whenever some feature is selected and hide it when not.
This should reduce the work by half, assuming that forEachFeatureAtPixel is what's hogging the system.

Three JS select geometry by id

Background: I'm a dev that knows JS, but is relatively new to Three JS. I've done a few small projects that involve static scenes with basic repeating animation.
I'm currently working on a modified version of Google's Globe project http://workshop.chromeexperiments.com/globe/. Looking back, I probably should have just started from scratch, but it was a good tool to see the approach their dev took. I just wish I could now update ThreeJS w/o the whole thing falling apart (too many unsupported methods and some bugs I never could fix, at least not in the hour I attempted it).
In the original, they are merging all of the geometric points into one object to speed up FPS. For my purposes, I'm updating the points on the globe using JSON, and there will never be more than 100 (probably no more than 60 actually), so they need to remain individual. I've removed the "combine" phase so I can now individually assign data to the points and then TWEEN the height change animation.
My question is, how do I manually select a single point (which is a Cube Geometry) so that I can modify the height value? I've looked through Stack Overflow and Three JS on GitHub and I'm not sure I understand the process. I'm assigning an ID to make it directly relate to the data that is being passed into it (I know WebGL adds an individual name/ID for particles, but I need something that is more directly related to what I'm doing for the sake of simplicity). That seems to work fine. But again, as a JS dev I've tried .getElementById(id) and $('#'+id) in jQuery, and neither works. I realize that Geometry objects don't behave the same way as HTML DOM objects, so I guess that's where I'm having struggles.
Code to add a point of data to the globe:
function addPoint(lat, lng, size, color, server) {
geometry = new THREE.Cube(0.75, 0.75, 1, 1, 1, 1, null, false, { px: true,
nx: true, py: true, ny: true, pz: false, nz: true});
for (var i = 0; i < geometry.vertices.length; i++) {
var vertex = geometry.vertices[i];
vertex.position.z += 0.5;
}
var point = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial ({
vertexColors: THREE.FaceColors
}));
var phi = (90 - lat) * Math.PI / 180;
var theta = (180 - lng) * Math.PI / 180;
point.position.x = 200 * Math.sin(phi) * Math.cos(theta);
point.position.y = 200 * Math.cos(phi);
point.position.z = 200 * Math.sin(phi) * Math.sin(theta);
if($('#'+server).length > 0) {
server = server+'b';
}
point.id = server;
point.lookAt(mesh.position);
point.scale.z = -size;
point.updateMatrix();
for (var i = 0; i < point.geometry.faces.length; i++) {
point.geometry.faces[i].color = color;
}
console.log(point.id);
scene.addObject(point);
}
So now to go back, I know I can't use point.id because obviously that will only reference inside the function. But I've tried 'Globe.id', 'Globe.object.id', 'object.id', and nothing seems to work. I know it is possible, I just can't seem to find a method that works.
Okay, I found a method that works for this by playing with the structure.
Essentially, the scene is labeled "globe" and all objects are its children. So treating the scene as an array, we can successfully pass an object into a var using the following structure:
Globe > Scene > Children > [Object]
Using a matching function, we loop through each item and find the desired geometric object and assign it to a temporary var for animation/adjustment:
function updatePoints(server){
var p, lineObject;
$.getJSON('/JSON/'+server+'.json', function(serverdata) {
/* script that sets p to either 0 or 1 depending on dataset */
var pointId = server+p;
//Cycle through all of the child objects and find a patch in
for(var t = 3; t < globe.scene.children.length; t++) {
if(globe.scene.children[t].name === pointId) {
//set temp var "lineObject" to the matched object
lineObject = globe.scene.children[t];
}
}
/* Manipulation based on data here, using lineObject */
});
}
I don't know if this is something that anyone else has had questions on, but I hope it helps someone else! :)
EDIT: Just realized this isn't a keyed array so I can use .length to get total # of objects

Resources