我想设计一个可以生成各种“地图”的功能。
例如:
位置 A 已创建,它位于某个位置 X
创建位置 B,它位于某个位置 Y,我们知道 X、Y 之间的距离
创建位置 C,我们知道从 C 到 B 的距离,我们如何计算 C 到 A?
使用三角形方法,我想我也可以分配一个随机角度并计算第三边,但是如果我随机添加一个位置 D、E、F 该怎么办?我会计算多个三角形,每次添加都会变得更糟吗?
我想设计一个可以生成各种“地图”的功能。
例如:
位置 A 已创建,它位于某个位置 X
创建位置 B,它位于某个位置 Y,我们知道 X、Y 之间的距离
创建位置 C,我们知道从 C 到 B 的距离,我们如何计算 C 到 A?
使用三角形方法,我想我也可以分配一个随机角度并计算第三边,但是如果我随机添加一个位置 D、E、F 该怎么办?我会计算多个三角形,每次添加都会变得更糟吗?
假设您要生成位置列表L[1..n]
,您只需随机选择下一个位置并扫描L
以确保距离超过阈值,否则,再次选择。
然后,将其推送到您的列表中L
。所以生成元素列表的总运行时间是 O(n^2)。当 n < 1000 时,这已经足够快了。下面的方法保证会终止,它是为相对较小的 read-to-pick 列表设计的,比如最多 1,000,000。
function generateList(orgList, numberToOutput) {
if (orgList.length < numberToOutput)
return false;
var orgListClone = orgList.slice(0);
var L = [];
while (L.length < numberToOutput && orgListClone.length > 0) {
var n = parseInt(Math.random() * orgListClone.length);
// Assume we pick n-th element in the list.
var ok = true;
for (var j = 0; j < L.length; j++)
if (distance(orgListClone[n], L[j]) < kThreshold) {
// n is not an option, swap orgListClone[n] with the last element and pop it out.
orgListClone[n] = orgListClone[orgListClone.length - 1];
orgListClone.pop();
ok = false;
break;
}
if (ok) {
// All tests passed
L.push(orgListClone[n]);
orgListClone[n] = orgListClone[orgListClone.length - 1];
orgListClone.pop();
}
}
if (L.length == numberToOutput)
return L;
// Failed to find the list
return null;
}
另一种解决方案是计算前方每个位置之间的距离,并为每个位置制作一个距离太近的位置列表。
因此,在每次选择之后,只需将太近的位置合并到当前集合,这需要 O(n)。然后选择另一个不包含在此集合中的位置。此方法仅在 read-to-pick 列表足够大时有效,因此1 - |too close list| / |read-to-pick list|
选择未包含在集合中的位置的概率 ( ) 很大。这总共需要 O(nm),其中 m 是平均 |too close list|。
function generateList(orgList, numberToOutput) {
if (orgList.length < numberToOutput)
return false;
var tooCloseSet = {};
var L = [];
var lastLengthOfL = 0;
var repickCount = 0;
for (L.length < numberToOutput) {
if (l.length == lastLengthOfL) {
if (++repickCount > 10)
return false;
} else {
lastLengthOfL = l.length;
repickCount = 0;
}
var n = parseInt(Math.random() * orgList.length);
if (n in tooCloseSet)
continue;
L.push(orgList[n]);
mergeSet(tooCloseSet, orgList[n].tooCloseList);
}
return L;
}
是的,您添加的每个点都会在几何上变得更加复杂。
问题是即使你知道三角形所有三个边的长度,你仍然不知道方向。为了说明您的示例:
您通过指定距离 dAB 和 dBC(它为您提供 dAC)来定义 ABC。但实际上你有两个可能的三角形,ABC 和 ABC'。这意味着如果你添加第四个点 D,通过指定它到 ABC 上的一个点的距离(例如 dCD),你就添加了第二个三角形,它也可以有两个方向之一,总共有四个可能的解决方案。如您所见,方向对于确定同一三角形上两点之间的距离无关紧要,但对于确定不同三角形上两点之间的距离,它确实如此。
你可以试试这样的东西,我还没有测试过,所以现在只是概念性的。
您可以只生成一个随机放置的点数组,每个点都可以保存自己的距离数组,使用基本三角法计算。
function Point(x, y) {
return {
x: x,
y:y,
addRelative: function(pt) {
this.realtivePoints[pt] = abs(sqrt(pow((this.x-pt.x),2) + pow((this.y-pt.y),2)));
},
relativePoints: {}
};
var randPoints = []; // Lets assume this has a collection of random Point objects
for(var i=0; i<randPoints.length; i++) {
for(var j=0; j<randPoints.length; j++) {
randPoint[i].addRelative(randPoints[j]);
}
}
randPoints[0].relativePoints[randPoints[1]]; // Dist from first to second point.