编程语言
首页 > 编程语言> > javascript-在浏览器中绘制二维距离阵列中的地图

javascript-在浏览器中绘制二维距离阵列中的地图

作者:互联网

我正在接收二维坐标系中任意数量点之间的所有距离.

如何在浏览器中将其可视化为地图上的坐标?
如果有很多解决方案,我只想看看我的算法可以提出的第一个可能的解决方案.

因此,这是一个非常简单的示例:

PointCount = 3  
Distances:  
0-1 = 2  
0-2 = 4  
1-2 = 2  

enter image description here

有谁知道一种简单的方法(可能是现有的解决方案/框架)使用现有的方法来简化实现?
我当时在考虑使用html canvas元素进行绘制,但是我不知道如何创建一种算法,可以得出这些点的可能坐标.

上面的示例已简化-
实际距离值可能如下所示:

       (0)  (1)     (2)     (3)
   (0)  0   2344    3333    10000   
   (1)      0       3566    10333   
   (2)              0       12520   

解决方法:

我不确定这是否与SO有关,但是无论如何…

做到这一点的方法非常简单,就是使用数据一一放置点:

>为第一个点选择一个随机位置(假设它是0,0).
>第二个点在半径为d(0,1)的圆上,第一个点为中心,因此您可以选择圆上的任何点.让我们选择(d(0,1),0).
>第三个点位于半径为d(0,2)和中心点1的圆与半径为d(1,2)和中心点2的圆的交点处.您将得到0、1、2或无限的解决方案.如果数据来自真实点,则不应发生0. 1和infinity是边缘情况,但是您仍然应该处理它们.选择任何解决方案.
>第四个点是3个圆的交点.除非您非常不幸(但您应该考虑一下),否则应该只有一个解决方案.
>像这样继续直到所有点都放好.

请注意,这并不意味着您将获得原始点的确切位置:可以将平移(选择第一个点),旋转(选择第二个点)和对称(选择第三点)有所作为.

一个快速而肮脏的实现(不处理很多情况,并且很少测试):

function distance(p1, p2) {
  return Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
}

// adapted from https://stackoverflow.com/a/12221389/3527940
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)));
  }
}

在这里提琴:https://jsfiddle.net/jacquesc/82aqmpnb/15/

标签:graph-drawing,html,javascript
来源: https://codeday.me/bug/20191025/1928827.html