This question already has answers here:
How to find the coordinate that is closest to the point of origin?
(2 answers)
Closed 4 years ago.
I am wondering how can I calculate my coordinates to an array of coordinates and find out which one is closest?
Lets say:
var player = {
x: 10,
y: 20
}
var box = [
{x: 17, y: 30},
{x: 41, y: 14},
{x: 20, y: 30}
];
So my player stays on 10, 20. And i have 3 different boxed, and i need to find out which one is closest. Is there any easy way to caluculate that?
You could calculate the distance and reduce the array by checking each distance and return the object with the shortest.
function getDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
}
var player = { x: 10, y: 20 },
box = [{ x: 17, y: 30 }, { x: 41, y: 14 }, { x: 20, y: 30 }];
console.log(box.reduce((a, b) => getDistance(a, player) < getDistance(b, player) ? a : b));
To find the least distance (the closest point) just find the least difference in the sum of the squares of their x and y offsets. You don't need to take the square root to find the actual distance as per Pythagorous's theorom. If you have trouble writing the code don't forget to include what you have tried.
You can use 2 points canvas formla and sort it based on distance
let positions = [
{x: 17, y: 30},
{x: 41, y: 14},
{x: 20, y: 30}
];
let x=10;
let y= 20;
let positions_close=positions.sort(p=>Math.hypot(p.x-x, p.y-y));
console.log(positions_close[0]);
//check the distance
let distances=positions.map(p=>Math.hypot(p.x-x, p.y-y));
console.log(distances);
Related
I have hero coordinates, target coordinate and range.
Let's say my hero is at x: 1, y: 1;
Target coordinates are: x: 4, y: 4;
I'm getting every coordinate from target within range. So if range is 1 then I create array of objects like this:
[
{x: 3, y: 3},
{x: 4, y: 3},
{x: 5, y: 3},
{x: 3, y: 4},
{x: 5, y: 4},
{x: 3, y: 5},
{x: 4, y: 5},
{x: 5, y: 5}
]
just 1 sqm - 8 coordinates around target. I'm getting that with simple algorithm
const hero = {x: 1, y: 1};
const closest = {x: 4, y: 4};
const range = 1;
const coordsAround = [];
for (let i = 0; i <= range * 2; i++) {
for (let j = 0; j <= range * 2; j++) {
let newCoord = { x: closest.x - range + j, y: closest.y - range + i };
//here note
if(!((newCoord.x === 3 && newCoord.y === 3) || (newCoord.x === 4 && newCoord.y === 3))) {
coordsAround.push(newCoord);
}
}
}
but additionally before push to coordsAround I'm executing some function which check collisions. Here in example I just added if statement to simplify it a bit. And with this if I excluded 3,3 and 4,3.
So now my dashboard is like this:
( I accidently made this dashboard so it's in y,x pattern instead of x,y srr)
where pink is hero (1,1) red are collisions, gold is the target (4,4) and greens are around the target (gained from above code snippet)
Now it's pretty simple to say which green is closest if it would be without red tiles (collisions):
const realClosest = {
x: hero.x > closest.x
? closest.x + 1
: closest.x - 1,
y: hero.y > closest.y
? closest.y + 1
: closest.y - 1
};
console.log('real closest is:', realClosest, 'but it is not within coordsAournd:', coordsAround,
'so next closest coord is 3,4 or 4,3 but 3,4 is not within coordsAournd as well' +
'so closest coord is 4,3');
but as far as I have this red tiles I don't know how to tell which is second best, third best and so on..
Sort the tiles with a custom function so that coordsAround[0] is the tile that is the closest to the hero, coordsAround[coordsAround.length - 1] is the tile that is thefarthest:
function dist2(a, b) {
let dx = a.x - b.x;
let dy = a.y - b.y;
return dx*dx + dy*dy;
}
coordsAround.sort(function (a, b) {
let da = dist2(a, hero);
let db = dist2(b, hero);
if (da < db) return -1;
if (da > db) return 1;
return 0;
})
The auxiliary function dist2 calculates the square of the distance. The sorting rder will be the same, because sqrt(x) < sqrt(y) when x < y (and both values are non--negative). Given that your range is reates a square, not a circly, you could also use dist = Math.max(Math.abs(dx), Math.abs(dy)).
I have one array of objects which have pair of numbers and i have one given pair
let points = [{x:20,y:30}, {x:34,y:40}, {x:45,y:30}, {x:55,y:30}]
let givenNumber= {x:19,y:25}
How i can find nearest pair from array which is near to my given pair number
Anyone can help?
You could get the distance and then reduce the array by taking the smaler distance of two points of the array.
const distance = (p1, p2) => Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
let points = [{ x: 20, y: 30 }, { x: 34, y: 40 }, { x: 45, y: 30 }, { x: 55, y: 30 }],
point = { x: 19, y: 25} ,
result = points.reduce((a, b) => distance(a, point) < distance(b, point) ? a : b);
console.log(result);
I have some javascript code that tries to place some objects above each other relative from a center point in this case 0,0
The thing is that the amount of objects, size of the objects, and spacing between the objects are all variable.
See this image below that explains my situation the best (hopefully ;)):
So in this case the center point is the green dot and the mesh center positions are the yellow dots.
The Mh stands for Mesh Height (variable)
The Sh stands for Spacing height (variable)
I tried to show the logic behind the calculation of the yellow dots. But when i try to implement this in javascript it works for 3 lines but it breaks on other amount of lines.
This is what i have tried so far:
var data = {
text : ["THE NEXT","POINT","OF VIEW"],
size : 5,
height : 2,
curveSegments : 12,
line_height : 2
};
function generateTextGeometry(mesh) {
var scaled_lineheight = map_r(data.size, 2, 75, 0.5, 20);
var y_start = (0 - data.text.length * data.size / 2 - data.size / 2 - (data.text.length - 1) * scaled_lineheight)/2;
var loader = new THREE.FontLoader();
loader.load( 'data/suisse_2.json', function ( font ) {
for (var i = data.text.length - 1; i >= 0; i--) {
var geometry = new THREE.TextGeometry( data.text[i], {
font: font,
size: data.size,
height: data.height,
curveSegments: data.curveSegments
});
geometry.center();
mesh.children[i].geometry = geometry;
mesh.children[i].position.y = y_start;
console.log(mesh.children[i].position);
if (i < data.text.length) {
y_start += (data.size + scaled_lineheight);
}else{
y_start += data.size;
}
}
console.log('-----------------------');
});
}
and When i console.log the position for 3 lines it is ok:
p {x: 0, y: -6.301369863013699, z: 0}
p {x: 0, y: 0, z: 0}
p {x: 0, y: 6.301369863013699, z: 0}
but for any other amount of lines it is wrong:
p {x: 0, y: -4.4006849315068495, z: 0}
p {x: 0, y: 1.9006849315068495, z: 0}
So my final question is how do i always get the yellow positions on the right location relative from the green center? What is wrong in my current logic?
If anything is unclear please let me know! So i can clarify.
So after reading my own question about 20 times. The light shined upon my brains haha.
So i just made a mistake when calculating the initial start Here is the updated line:
var y_start = 0 - (((data.text.length - 1) * data.size) + ((data.text.length - 1) * scaled_lineheight))/ 2;
I know there are many many questions about sorting javascript arrays by multiple values, but none of the answers solved my problem.
I have an array of coordinates like:
x | y
--------
10 20
12 18
20 30
5 40
100 2
How can I get the coordinate that is closest to the point of origin?
Calculate the distance of each point using
Math.sqrt( Math.pow(x, 2) + Math.pow(y, 2) );
Take the result that's the lowest
var points = [
{x: 10, y: 20},
{x: 12, y: 18},
{x: 20, y: 30},
{x: 5, y: 40},
{x: 100, y: 2}
];
function d(point) {
return Math.pow(point.x, 2) + Math.pow(point.y, 2);
}
var closest = points.slice(1).reduce(function(min, p) {
if (d(p) < min.d) min.point = p;
return min;
}, {point: points[0], d:d(points[0])}).point;
closest;
// {x: 12, y:18}
You'll notice that we're skipping the Math.sqrt step here. As Mark Setchell points out, calculating the square root is a sort of "lowest common denominator" operation; We can still determine the closest point by getting the smallest x^2 + y^2 value.
For each x,y pair, square x, square y and add together. Smallest number is nearest to the origin.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I am trying to make the following codes less ugly and not sure what to do. Are there any suggestions from you guys? Thanks
a lot.
if($element.is('builder') || $element.is('#options') ){
tooltipYPos=yPos + 35;
}
if($element.is('#button')){
tooltipXPos=xPos - 240;
}
if($element.is('#addn')){
tooltipXPos=xPos - 295;
tooltipYPos=yPos - 80;
}
if($element.is('#count')){
tooltipXPos=xPos + 180;
tooltipYPos=yPos - 90;
}
if($element.is('label')){
tooltipXPos=xPos + 80;
tooltipYPos=yPos - 90;
}
The general cure is to move the problem from code to data. One solution (demonstrated below) is to set up a JavaScript associative array keyed on the various ID tags and the values are value pairs X and Y offsets (in some cases one or the other is 0). At usage time, loop through the keys of the associative array, looking for matches. If so, add the X and Y offsets from the associative array onto toolTipXPos and toolTipYPos.
This will keep your offsets in one place, out of the way, and the code to manipulate them short and simple.
(untested, naturally)
// This can be stashed away anywhere.
var a = {
'#te_classbuilder': { X: 0, Y: 35 },
'#te_options': { X: 0, Y: 35 },
'#lesson-details-extend-button': { X: -240, Y: 0 },
'#asset-list-asset-add-button': { X: 295, Y: -80 },
'#asmnt_option_label_q_count': { X: 180, Y: -90 },
"label": { X: 80, Y: -90 }
}
// Put this where you need the actual evaluation to happen
jQuery.each(data, function(key, value) {
if ( $element.is(key) ) {
tooltipXPos = xPos + value.X;
tooltipYPos = yPos + value.Y;
}
});
Edit: changed to loop, so that label could be tested for, and not #label.
Another option would be to make use of jQuery's .data function to store the appropriate X and Y values on the elements themselves, like so:
$('label').data({ x: 80, y: -90 });
$('#te_classbuilder, #te_options').data({ x: 0, y: 35 });
$('#lesson-details-extend-button').data({ x: -240, y: 0 });
$('#asset-list-asset-add-button').data({ x: -295, y: -80 });
$('#asmnt_option_label_q_count').data({ x: 180, y: -90 });
Then, when it comes time to modify your tooltip position values, no conditional statements are required. Simply retrieve the x and y data attributes from $element.
tooltipXPos = xPos + $element.data('x');
tooltipYPos = yPos + $element.data('y');
This, of course, assumes that any element that may be assigned to $element will have previously had .data called on it with appropriate x and y values.
Can you work out the height/width of $element and then alter tooltipXPos/tooltipYPos accordingly, instead of hard-coding the deltas?
In first if you can combine conditions:
if ($element.is('#te_classbuilder, #te_options')) {
tooltipYPos = yPos + 35;
}
If we could not make some big changes then I would write it this way:
if ($element.is('#te_classbuilder, #te_options')) tooltip = { x: 0, y: yPos + 35 };
if ($element.is('#lesson-details-extend-button')) tooltip = { x: xPos - 240, y: 0 };
if ($element.is('#asset-list-asset-add-button')) tooltip = { x: xPos - 295, y: yPos - 80 };
if ($element.is('#asmnt_option_label_q_count')) tooltip = { x: xPos + 180, y: yPos - 90 };
if ($element.is('label')) tooltip = { x: xPos + 80; y: yPos - 90 };