get Y value given X value in AM Charts JS - javascript

I am using AMCharts for my project, what I want is to accomplish this:
given 1. data points:
const data = [{x: 23, y: 0},{x: 24, y: 0},{x: 25, y: 23},...,{x: 26, y: 24}]
I want to extract any Y value given X value from the series...
Partial code I am using to create chart:
this.chart = am4core.create(this.chartDiv, am4charts.XYChart);
this.title = this.chart.titles.create();
// chartData is just an array of x,y values
this.chart.data = this.props.chartData;
const X_AXIS = this.chart.xAxes.push(new am4charts.ValueAxis());
X_AXIS.title.text = "X VALUES";
const Y_AXIS = this.chart.yAxes.push(new am4charts.ValueAxis());
Y_AXIS.title.text = "Y VALUES";
this.series = this.chart.series.push(new am4charts.LineSeries());
this.series.dataFields.valueX = "xValue";
this.series.dataFields.valueY = "yValue";
// cursor
this.chart.cursor = new am4charts.XYCursor();
this.chart.cursor.xAxis = X_AXIS;
this.chart.cursor.yAxis = Y_AXIS;
this.chart.cursor.snapToSeries = this.series;
How can I accomplish this? Say Y value for X = 24 in JS (something like this.series.get(25))

Why not just search through the data using the Array.prototype.find method since you're generating your points based on the data array anyways.
const data = [{x: 23, y: 0},{x: 24, y: 0},{x: 25, y: 23},{x: 26, y: 24}];
console.log(data.find(item => item.x === 23).y);

Related

Sort Coordinates by Distance to Origin Point - JavaScript

I have random rectangles on canvas stored in an array like so:
var rectangles = [
{x: 10, y: 10},
{x: 40, y: 50},
{x: 1, y: 70},
{x: 80, y: 5},
{x: 30, y: 60}
];
I now want to label these rectangles based on their proximity to the origin point (0, 0).
My first thought was to loop through the x and y axis in different patterns, one example would be:
// 100 is the width and height of the canvas
for(var x = 0; x < 100; x++){
for(var y = 0; y < 100; y++){
// "intersects" loops through the array and returns the matching index or -1 if no match
if(intersects(rectangles, x, y) > -1){
console.log('Rectangle' + (intersects(rectangles, x, y) + 1));
}
}
}
The issue i am having, is that no matter the pattern of the loop the result is not as expected.
My second thought was to draw rectangles to the origin point (seen on the last image) and sort the by the size of the rectangle. However, this (and calculating the line distance for that matter) also did not produce the expected result. This can be seen with the green rectangle, that is very close to X0, but should be last.
For example this should return the same result:
Does anyone know how I can achieve the correct labeling result? Thanks!
Here's how to compare distances of coordinates against the origin and sort them (closest to furthest).
var rectangles = [
{x: 10, y: 10},
{x: 40, y: 50},
{x: 1, y: 70},
{x: 80, y: 5},
{x: 30, y: 60}
];
const sumOfSquares = (x, y) => {
return Math.pow(x, 2) + Math.pow(y, 2);
};
rectangles.sort((a, b) => {
const sumA = sumOfSquares(a.x, a.y);
const sumB = sumOfSquares(b.x, b.y);
return sumA - sumB;
});
console.log(rectangles);

How to create a random ground in matter.js

I am creating the ground of a game using a Perlin noise function. This gives me an array of vertices. I then add a vertex at the front that is {x:0 y: WORLD_HEIGHT} and another at the end of the array that is {x: WORLD_WIDTH y: WORLD_HEIGHT}. I am hoping that will give me a flat base with a random top.
How then do I add this into the matter.js world?
I am trying to create the ground using;
var terrain = Bodies.fromVertices(???, ???, vertexSets, {
isStatic: true
}, true);
but I don't know what to use for the ??? co-ordinates. I think they are supposed to represent the center of the object. However, I don't know what that is because it is noise. What I would like to do is specify the x & y of the first perlin noise vertex.
I am not even sure that given these vertices matter.js is creating a single body or multiple.
Is this the right way to approach it or there another way to do this? I am really struggling with the docs and the examples.
I use Matter.Body.setPosition(body, position) to override the center of mass and put the ground where I want it based on its bounds property.
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine: engine,
});
const w = 300;
const h = 300;
const vertices = [
...[...Array(16)].map((_, i) => ({
x: i * 20,
y: ~~(Math.random() * 40),
})),
{x: w, y: 100},
{x: 0, y: 100},
];
const ground = Matter.Bodies.fromVertices(
w - 10, h - 10, // offset by 10 pixels for illustration
vertices,
{isStatic: true},
/* flagInternal =*/ true,
);
Matter.Body.setPosition(ground, {
x: w - ground.bounds.min.x,
y: h - ground.bounds.max.y + 110,
});
const {min: {x}, max: {y}} = ground.bounds;
console.log(x, y); // 10 120
Matter.Composite.add(engine.world, [ground]);
Matter.Render.run(render);
Matter.Runner.run(engine);
<script src="https://cdn.jsdelivr.net/npm/poly-decomp#0.3.0/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
Without setPosition, you can see things jump around if you run this snippet a few times (just to reproduce OP's error with a concrete example):
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine: engine,
});
const vertices = [
...[...Array(16)].map((_, i) => ({
x: i * 20,
y: ~~(Math.random() * 40),
})),
{x: 300, y: 100},
{x: 0, y: 100},
];
const ground = Matter.Bodies.fromVertices(
200, 100, vertices,
{isStatic: true},
/* flagInternal =*/ true,
);
Matter.Composite.add(engine.world, [ground]);
Matter.Render.run(render);
Matter.Runner.run(engine);
<script src="https://cdn.jsdelivr.net/npm/poly-decomp#0.3.0/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
I'm not using Perlin noise and there are some internal vertices that aren't properly detected in the above examples, but the result should be the same either way.
should be integers, all width and height of the noise texture. values at those x, y integer places can be floats... no problem.
and same width and height should go to terrain and values at that places will be the height of the terrain.

How to set the max value in the heatmap properly setData?

I have some data saved and it is huge, 100.000 plus points saved in the database. In this format:
database_data = [
{ x: 100, y: 100, value: 1},
{ x: 200, y: 100, value: 1},
{ x: 120, y: 320, value: 1},
...
]
I am giving the value of 1 for each point as you can see above. I would like to use:
heatmap.setData({
max: max_value,
data: database_data
});
To plot the data on the screen. How can I calculate the max_value of the heatmap? Because I wanna have the information been displayed on the screen where the most red color is the points where we have more frequently in the database and the less red color would be the point where we have only once in the database. But as we know, (x:100, y:100) and x:120, y: 120) will have some intersection between them, and that would also need to be consider, just like the normal heat map.
In other words, I want to know how to automatically calculate the value for "max" in the heatmap using setData function!
Here below it is a function that is working fine, but it takes too much time:
var body = document.body;
var bodyStyle = getComputedStyle(body);
var hmEl = document.querySelector(".heatmap-wrapper");
hmEl.style.width = bodyStyle.width;
hmEl.style.height = bodyStyle.height;
hmEl.style.background = "#3e1852";
hmEl.style.zIndex = "1000";
var hm = document.querySelector(".heatmap");
var heatmap = h337.create({
container: hm,
radius: 40,
});
var dbh_x = <?php echo $dbh_x;?>; //LIKE THIS->["100", "200", "300","400", "420", "500", "600", "600"];
var dbh_y = <?php echo $dbh_y;?>;//LIKE THIS->["100", "200", "300","400", "420", "500", "600", "600"];
for ( var i =0; i< dbh_x.length; i++){
heatmap.addData({
x: dbh_x[i],
y: dbh_y[i],
});
};
Because of the loading time, I was trying to use setData instead:
var body = document.body;
var bodyStyle = getComputedStyle(body);
var hmEl = document.querySelector(".heatmap-wrapper");
hmEl.style.width = bodyStyle.width;
hmEl.style.height = bodyStyle.height;
hmEl.style.background = "#3e1852";
hmEl.style.zIndex = "1000";
var hm = document.querySelector(".heatmap");
var heatmap = h337.create({
container: hm,
radius: 40,
});
heatmap.setData({//This function will show the data kind a fast for 100000+points
max: 10, //This is the problem
data: [{ x: 891, y: 50, value: 1},{ x: 891, y: 50, value: 1},...]
});
Appreciate your guys time!

Is there a way to create a HTML element using an array of coordinates?

Say I have an array of 4 x/y co-ordinates
[{x: 10, y: 5}, {x:10, y:15}, {x:20, y:10}, {x:20, y:20}]
Is there a way to construct a HTML element, so that each of the four corners math the co-ordinates in the array?
I know this is possible using canvas, but I'm stuggling to work out how to go about doing this with HTML elements.
The array will always contain 4 sets of coordinates.
The final shape may be rotated or skewed, but will always be a "valid" shape which can be acheived using CSS transformations.
Assuming you got it in form of [topLeft, bottomLeft, topRight, BottomRight] of the original rectangle, you can try recreate it like this:
const obj1 = [{x: 10, y: 5}, {x:10, y:15}, {x:20, y:10}, {x:20, y:20}];
const obj2 = [{x: 40, y: 80}, {x: 10, y: 160}, {x: 120, y: 80}, {x: 90, y: 160}];
const obj3 = [{x: 200, y: 30}, {x: 150, y: 80}, {x: 250, y: 80}, {x: 200, y: 130}];
function render(obj) {
const skewX = obj[1].x - obj[0].x;
const skewY = obj[2].y - obj[0].y;
let translateX = Math.min(...obj.map(t => t.x));
let translateY = Math.min(...obj.map(t => t.y));
if(skewX<0) translateX -= skewX;
if(skewY<0) translateY -= skewY;
const scaleX = Math.abs(obj[0].x - obj[2].x);
const scaleY = Math.abs(obj[0].y - obj[1].y);
const el = document.createElement('div');
el.style.width = '1px';
el.style.height = '1px';
el.style.backgroundColor = 'blue';
el.style.transformOrigin = 'top left';
el.style.transform = `matrix(${scaleX}, ${skewY}, ${skewX}, ${scaleY}, ${translateX}, ${translateY})`;
document.body.appendChild(el);
}
render(obj1);
render(obj2);
render(obj3);
However, I will recommend you to not store the shapes as its vertices but as it's transformation matrix. (if it's possible, of course)
If you're simply trying to draw shapes without the use of canvas, you could maybe draw SVG shapes by translating the coordinates in your object.
If you want to deform a div, best I can think off top of my head is to make use of CSS transform:matrix, but you'd need to figure out how to translate your x/y for each corner coordinates to scale/skew/translate parameters.
If you're not deforming a div, and simply creating a regular rectangular one, then you should be able to translate your x/y coordinates into top; left; width; height; CSS properties.
Well, no. HTML is a tree-like structured DOM. Although, you can have a DOM with position: absolute (absolute to html) and top: y; left: x, but it does not have any advantage doing it this way, from my perspective.

Raphael.js how to store the name in each element?

I have rendered several rectangulars in Raphael.js. I would like to give each of the rectangular a name, and store the name to each of them. How to do in Raphael?
For example:
var r1 = paper.rect(10, 10, 50, 50); //name it 'car'
var r2 = paper.rect(10, 10, 50, 50); //name it 'plane'
var r3 = paper.rect(10, 10, 50, 50); //name it 'bike'
then, in future, I can distinguish them by check the name, like r1.attr('name')=='car'
How to add new attribute to store the names then?
Why not just add an ID to the DOM object using .node?
var r1,r2,r3;
r1 = paper.rect(10, 10, 50, 50);
r1.node.id = 'car'
r2 = paper.rect(10, 10, 50, 50);
r2.node.id = 'plane'
r3 = paper.rect(10, 10, 50, 50);
r3.node.id = 'bike'

Categories

Resources