从二维距离数组在浏览器中绘制地图
Draw Map in Browser out of 2 Dimensional Array of Distances
我正在接收二维坐标系中随机点之间的所有距离。
如何在我的浏览器中将其可视化为地图上的坐标?
如果有很多解决方案,我只想查看我的算法可以提出的第一个可能的解决方案。
所以这是一个非常简单的例子:
PointCount = 3
Distances:
0-1 = 2
0-2 = 4
1-2 = 2
有没有人知道一个简单的方法(可能 solution/framework 已经存在)来使用现有的任何东西来使它更容易实施?
我在想也许可以使用 html canvas 元素进行绘图,但我不知道如何创建一个算法来为这些点提供可能的坐标。
上面的例子是简化的-
实际距离值可能如下所示:
(0) (1) (2) (3)
(0) 0 2344 3333 10000
(1) 0 3566 10333
(2) 0 12520
最小工作示例。请记住,在 canvas 坐标中,y 值是倒置的,但您可以这样做:
y = canvasHeight - y
如果您也有负分,那么需要一些额外的工作。在这种情况下,绘制线条和刻度线以可视化轴也可能会有所帮助。
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let scale = 10;
let radius = 10;
function point(x, y) {
ctx.fillRect(x*scale, y*scale, radius, radius);
}
// test
point(10, 15);
point(20, 8);
<html>
<body>
<canvas id="canvas" width=1000 height=1000></canvas>
</body>
</html>
我不确定这是否与 SO 相关,但无论如何...
执行此操作的方法非常简单,使用数据将点一一放置:
为第一个点选择一个随机位置(假设它是 0,0)。
第二个点在以第一个点为圆心的半径为d(0,1)的圆上,所以可以在圆上任意取一点。让我们选择 (d(0,1),0).
第三个点在半径为d(0,2)圆心为1的圆和半径为d(1,2)圆心为2的圆的交点处。你将得到 0、1、2 或无穷多个解决方案。如果数据来自真实点,则不应出现 0。 1 和无穷大是边缘情况,但您仍应处理它们。选择任何解决方案。
第四个点在3个圆的交点处。除非你很倒霉(但你应该考虑到这一点),否则应该只有一种解决方案。
以此类推,直到所有点都被放置。
请注意,这并不意味着您将获得原始点的确切位置:您可以任意组合平移(选择第一个点)、旋转(选择第二个点)和对称性(第三点的选择)产生了差异。
一个快速而肮脏的实现(没有处理很多情况,并且测试得很少):
function distance(p1, p2) {
return Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
}
// adapted from
function intersection(x0, y0, r0, x1, y1, r1) {
var a, dx, dy, d, h, rx, ry;
var x2, y2;
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
dx = x1 - x0;
dy = y1 - y0;
/* Determine the straight-line distance between the centers. */
d = Math.sqrt((dy * dy) + (dx * dx));
/* Check for solvability. */
if (d > (r0 + r1)) {
/* no solution. circles do not intersect. */
return false;
}
if (d < Math.abs(r0 - r1)) {
/* no solution. one circle is contained in the other */
return false;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);
/* Determine the coordinates of point 2. */
x2 = x0 + (dx * a / d);
y2 = y0 + (dy * a / d);
/* Determine the distance from point 2 to either of the
* intersection points.
*/
h = Math.sqrt((r0 * r0) - (a * a));
/* Now determine the offsets of the intersection points from
* point 2.
*/
rx = -dy * (h / d);
ry = dx * (h / d);
/* Determine the absolute intersection points. */
var xi = x2 + rx;
var xi_prime = x2 - rx;
var yi = y2 + ry;
var yi_prime = y2 - ry;
return [
[xi, yi],
[xi_prime, yi_prime]
];
}
function generateData(nbPoints) {
var i, j, k;
var originalPoints = [];
for (i = 0; i < nbPoints; i++) {
originalPoints.push([Math.random() * 20000 - 10000, Math.random() * 20000 - 10000]);
}
var data = [];
var distances;
for (i = 0; i < nbPoints; i++) {
distances = [];
for (j = 0; j < i; j++) {
distances.push(distance(originalPoints[i], originalPoints[j]));
}
data.push(distances);
}
//console.log("original points", originalPoints);
//console.log("distance data", data);
return data;
}
function findPointsForDistances(data, threshold) {
var points = [];
var solutions;
var solutions1, solutions2;
var point;
var i, j, k;
if (!threshold)
threshold = 0.01;
// First point, arbitrarily set at 0,0
points.push([0, 0]);
// Second point, arbitrarily set at d(0,1),0
points.push([data[1][0], 0]);
// Third point, intersection of two circles, pick any solution
solutions = intersection(
points[0][0], points[0][1], data[2][0],
points[1][0], points[1][1], data[2][1]);
//console.log("possible solutions for point 3", solutions);
points.push(solutions[0]);
//console.log("solution for points 1, 2 and 3", points);
found = true;
// Subsequent points, intersections of n-1 circles, use first two to find 2 solutions,
// the 3rd to pick one of the two
// then use others to check it's valid
for (i = 3; i < data.length; i++) {
// distances to points 1 and 2 give two circles and two possible solutions
solutions = intersection(
points[0][0], points[0][1], data[i][0],
points[1][0], points[1][1], data[i][1]);
//console.log("possible solutions for point " + (i + 1), solutions);
// try to find which solution is compatible with distance to point 3
found = false;
for (j = 0; j < 2; j++) {
if (Math.abs(distance(solutions[j], points[2]) - data[i][2]) <= threshold) {
point = solutions[j];
found = true;
break;
}
}
if (!found) {
console.log("could not find solution for point " + (i + 1));
console.log("distance data", data);
console.log("solution for points 1, 2 and 3", points);
console.log("possible solutions for point " + (i + 1), solutions);
console.log("distances to point 3",
distance(solutions[0], points[2]),
distance(solutions[1], points[2]),
data[i][2]
);
break;
}
// We have found a solution, we need to check it's valid
for (j = 3; j < i; j++) {
if (Math.abs(distance(point, points[j]) - data[i][j]) > threshold) {
console.log("Could not verify solution", point, "for point " + (i + 1) + " against distance to point " + (j + 1));
found = false;
break;
}
}
if (!found) {
console.log("stopping");
break;
}
points.push(point);
}
if (found) {
//console.log("complete solution", points);
return points;
}
}
console.log(findPointsForDistances([
[],
[2344],
[3333, 3566],
[10000, 10333, 12520],
]));
console.log(findPointsForDistances([
[],
[2],
[4, 2],
]));
console.log(findPointsForDistances([
[],
[4000],
[5000, 3000],
[3000, 5000, 4000]
]));
console.log(findPointsForDistances([
[],
[2928],
[4938, 3437],
[10557, 10726, 13535]
]));
var nbPoints, i;
for (nbPoints = 4; nbPoints < 8; nbPoints++) {
for (i = 0; i < 10; i++) {
console.log(findPointsForDistances(generateData(nbPoints)));
}
}
那里有很多图书馆。
chartist.js 是易于使用且响应迅速的 JavaS 脚本库。在尝试了许多其他图表后,我去年将它用于基本图表,但它是唯一一个可以在不同屏幕尺寸下轻松缩放的图表。
chartJS 是另一个更好看的库。
您可以使用 html5 canvas 它既简单又有趣,但需要时间,尤其是在缩放方面。
要缩放和定位,您应该使用 x 和 y 的最小值和最大值。
祝你好运
我正在接收二维坐标系中随机点之间的所有距离。
如何在我的浏览器中将其可视化为地图上的坐标? 如果有很多解决方案,我只想查看我的算法可以提出的第一个可能的解决方案。
所以这是一个非常简单的例子:
PointCount = 3
Distances:
0-1 = 2
0-2 = 4
1-2 = 2
有没有人知道一个简单的方法(可能 solution/framework 已经存在)来使用现有的任何东西来使它更容易实施?
我在想也许可以使用 html canvas 元素进行绘图,但我不知道如何创建一个算法来为这些点提供可能的坐标。
上面的例子是简化的-
实际距离值可能如下所示:
(0) (1) (2) (3)
(0) 0 2344 3333 10000
(1) 0 3566 10333
(2) 0 12520
最小工作示例。请记住,在 canvas 坐标中,y 值是倒置的,但您可以这样做:
y = canvasHeight - y
如果您也有负分,那么需要一些额外的工作。在这种情况下,绘制线条和刻度线以可视化轴也可能会有所帮助。
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let scale = 10;
let radius = 10;
function point(x, y) {
ctx.fillRect(x*scale, y*scale, radius, radius);
}
// test
point(10, 15);
point(20, 8);
<html>
<body>
<canvas id="canvas" width=1000 height=1000></canvas>
</body>
</html>
我不确定这是否与 SO 相关,但无论如何...
执行此操作的方法非常简单,使用数据将点一一放置:
为第一个点选择一个随机位置(假设它是 0,0)。
第二个点在以第一个点为圆心的半径为d(0,1)的圆上,所以可以在圆上任意取一点。让我们选择 (d(0,1),0).
第三个点在半径为d(0,2)圆心为1的圆和半径为d(1,2)圆心为2的圆的交点处。你将得到 0、1、2 或无穷多个解决方案。如果数据来自真实点,则不应出现 0。 1 和无穷大是边缘情况,但您仍应处理它们。选择任何解决方案。
第四个点在3个圆的交点处。除非你很倒霉(但你应该考虑到这一点),否则应该只有一种解决方案。
以此类推,直到所有点都被放置。
请注意,这并不意味着您将获得原始点的确切位置:您可以任意组合平移(选择第一个点)、旋转(选择第二个点)和对称性(第三点的选择)产生了差异。
一个快速而肮脏的实现(没有处理很多情况,并且测试得很少):
function distance(p1, p2) {
return Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
}
// adapted from
function intersection(x0, y0, r0, x1, y1, r1) {
var a, dx, dy, d, h, rx, ry;
var x2, y2;
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
dx = x1 - x0;
dy = y1 - y0;
/* Determine the straight-line distance between the centers. */
d = Math.sqrt((dy * dy) + (dx * dx));
/* Check for solvability. */
if (d > (r0 + r1)) {
/* no solution. circles do not intersect. */
return false;
}
if (d < Math.abs(r0 - r1)) {
/* no solution. one circle is contained in the other */
return false;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);
/* Determine the coordinates of point 2. */
x2 = x0 + (dx * a / d);
y2 = y0 + (dy * a / d);
/* Determine the distance from point 2 to either of the
* intersection points.
*/
h = Math.sqrt((r0 * r0) - (a * a));
/* Now determine the offsets of the intersection points from
* point 2.
*/
rx = -dy * (h / d);
ry = dx * (h / d);
/* Determine the absolute intersection points. */
var xi = x2 + rx;
var xi_prime = x2 - rx;
var yi = y2 + ry;
var yi_prime = y2 - ry;
return [
[xi, yi],
[xi_prime, yi_prime]
];
}
function generateData(nbPoints) {
var i, j, k;
var originalPoints = [];
for (i = 0; i < nbPoints; i++) {
originalPoints.push([Math.random() * 20000 - 10000, Math.random() * 20000 - 10000]);
}
var data = [];
var distances;
for (i = 0; i < nbPoints; i++) {
distances = [];
for (j = 0; j < i; j++) {
distances.push(distance(originalPoints[i], originalPoints[j]));
}
data.push(distances);
}
//console.log("original points", originalPoints);
//console.log("distance data", data);
return data;
}
function findPointsForDistances(data, threshold) {
var points = [];
var solutions;
var solutions1, solutions2;
var point;
var i, j, k;
if (!threshold)
threshold = 0.01;
// First point, arbitrarily set at 0,0
points.push([0, 0]);
// Second point, arbitrarily set at d(0,1),0
points.push([data[1][0], 0]);
// Third point, intersection of two circles, pick any solution
solutions = intersection(
points[0][0], points[0][1], data[2][0],
points[1][0], points[1][1], data[2][1]);
//console.log("possible solutions for point 3", solutions);
points.push(solutions[0]);
//console.log("solution for points 1, 2 and 3", points);
found = true;
// Subsequent points, intersections of n-1 circles, use first two to find 2 solutions,
// the 3rd to pick one of the two
// then use others to check it's valid
for (i = 3; i < data.length; i++) {
// distances to points 1 and 2 give two circles and two possible solutions
solutions = intersection(
points[0][0], points[0][1], data[i][0],
points[1][0], points[1][1], data[i][1]);
//console.log("possible solutions for point " + (i + 1), solutions);
// try to find which solution is compatible with distance to point 3
found = false;
for (j = 0; j < 2; j++) {
if (Math.abs(distance(solutions[j], points[2]) - data[i][2]) <= threshold) {
point = solutions[j];
found = true;
break;
}
}
if (!found) {
console.log("could not find solution for point " + (i + 1));
console.log("distance data", data);
console.log("solution for points 1, 2 and 3", points);
console.log("possible solutions for point " + (i + 1), solutions);
console.log("distances to point 3",
distance(solutions[0], points[2]),
distance(solutions[1], points[2]),
data[i][2]
);
break;
}
// We have found a solution, we need to check it's valid
for (j = 3; j < i; j++) {
if (Math.abs(distance(point, points[j]) - data[i][j]) > threshold) {
console.log("Could not verify solution", point, "for point " + (i + 1) + " against distance to point " + (j + 1));
found = false;
break;
}
}
if (!found) {
console.log("stopping");
break;
}
points.push(point);
}
if (found) {
//console.log("complete solution", points);
return points;
}
}
console.log(findPointsForDistances([
[],
[2344],
[3333, 3566],
[10000, 10333, 12520],
]));
console.log(findPointsForDistances([
[],
[2],
[4, 2],
]));
console.log(findPointsForDistances([
[],
[4000],
[5000, 3000],
[3000, 5000, 4000]
]));
console.log(findPointsForDistances([
[],
[2928],
[4938, 3437],
[10557, 10726, 13535]
]));
var nbPoints, i;
for (nbPoints = 4; nbPoints < 8; nbPoints++) {
for (i = 0; i < 10; i++) {
console.log(findPointsForDistances(generateData(nbPoints)));
}
}
那里有很多图书馆。
chartist.js 是易于使用且响应迅速的 JavaS 脚本库。在尝试了许多其他图表后,我去年将它用于基本图表,但它是唯一一个可以在不同屏幕尺寸下轻松缩放的图表。
chartJS 是另一个更好看的库。
您可以使用 html5 canvas 它既简单又有趣,但需要时间,尤其是在缩放方面。
要缩放和定位,您应该使用 x 和 y 的最小值和最大值。
祝你好运