在矩形的边缘上获取两个点

我有一个矩形,想:

  1. 在一侧(任意)上获得一个随机点。

  2. 在一侧(除了先前选择的)随机点。

我最初的方法是为每个可能的边创建数组。

var arr:Array = [[{x:0,y:0},           // Top

                  {x:width,y:0}],      //

                 [{x:width,y:0},       // Right

                  {x:width,y:height}], //

                 [{x:width,y:height},  // Bottom

                  {x:0,y:height}],     //

                 [{x:0,y:height},      // Left

                  {x:0,y:0}]];         //

然后,我得到了双方。 rand是一个实例Rand并具有以下方法: .next()它提供一个介于0和之间的随机数,1 .between(x,y)它返回一个介于x和之间的随机数y。


var firstSide:Array = arr[rand.next() * arr.length];

var secondSide:Array;

do {

    secondSide = arr[rand.next() * arr.length];

} while(secondSide.equals(firstSide));

最后,我计算我的分数。


var pointOnFirstSide:Object = {x:rand.between(firstSide[0].x, firstSide[1].x),

                               y:rand.between(firstSide[0].y, firstSide[1].y};

var pointOnSecondSide:Object = {x:rand.between(secondSide[0].x, secondSide[1].x),

                                y:rand.between(secondSide[0].y, secondSide[1].y};

我认为这不是解决此问题的最有效方法。


你会怎么做?


慕容森
浏览 159回答 2
2回答

慕慕森

jcalz 已经给出了很好的答案。这是我在评论中询问的变体的替代版本:当您希望在周长的两侧均匀选择您的点时,如果您的w : h比率为4 : 1,则第一个点位于水平边的可能性是 的四倍作为一个垂直的。(这意味着击中两个相反的长边的几率是 24/45;两个相反的短边的几率是 1/45;并且每个击中一个的几率是 20/45——通过一个简单但略显乏味的计算。)const rand = {&nbsp; next: () => Math. random (),&nbsp; between: (lo, hi) => lo + (hi - lo) * Math .random (),}const vertices = (w, h) => [ {x: 0, y: h}, {x: w, y: h}, {x: w, y: 0}, {x: 0, y: 0} ]const edges = ([v1, v2, v3, v4]) => [ [v1, v2], [v2, v3], [v3, v4], [v4, v1] ]const randomPoint = ([v1, v2], rand) => ({&nbsp; x: v1 .x + rand .next () * (v2 .x - v1 .x),&nbsp; y: v1 .y + rand .next () * (v2 .y - v1 .y),})const getIndex = (w, h, x) => x < w ? 0 : x < w + h ? 1 : x < w + h + w ? 2 : 3const twoPoints = (w, h, rand) => {&nbsp; const es = edges (vertices (w, h) )&nbsp; const perimeter = 2 * w + 2 * h&nbsp; const r1 = rand .between (0, perimeter)&nbsp; const idx1 = getIndex (w, h, r1)&nbsp; const r2 = (&nbsp; &nbsp; rand. between (0, perimeter - (idx1 % 2 == 0 ? w : h)) +&nbsp; &nbsp; &nbsp; Math .ceil ((idx1 + 1) / 2) * w + Math .floor ((idx1 + 1) / 2) * h&nbsp; ) % perimeter&nbsp; const idx2 = getIndex (w, h, r2)&nbsp; return {p1: randomPoint (es [idx1], rand), p2: randomPoint (es [idx2], rand)}}console .log (&nbsp; // Ten random pairs on rectangle with width 5 and height 2&nbsp; Array (10) .fill () .map (() => twoPoints (5, 2, rand)))唯一复杂的位是 的计算r2。我们通过将所有四个边加在一起并减去当前边的长度(width如果idx是偶数,height如果是奇数)来计算 0 和其余三个边的总长度之间的随机数。然后我们把它加到边的总长度上,直到并包括索引(其中ceil和floor调用简单地计算水平和垂直边的数量,这些值分别乘以宽度和高度,并加在一起),最后取结果与周长的浮点模数。这与 jcalz 的答案中的技术相同,但通过处理边长而不是简单的计数而变得更加复杂。我没有创建rand任何类或接口的实例,实际上这里也没有做任何 Typescript,但是你可以很容易地自己添加它。

小唯快跑啊

假设我们有以下接口和类型:interface Rand {&nbsp; next(): number;&nbsp; between(x: number, y: number): number;}interface Point {&nbsp; x: number;&nbsp; y: number;}type PointPair = readonly [Point, Point];并在评论中接受您的话,该程序是:首先随机选择两个边,然后在这些边上随机选择点......首先让我们看看随机选择两个边所涉及的内容:&nbsp; const s1 = Math.floor(rand.between(0, arr.length));&nbsp; const s2 = (Math.floor(rand.between(1, arr.length)) + s1) % arr.length;&nbsp;s1并s2代表arr我们正在选择的索引。第一个选择介于0和 小于数组长度之间的整数。我们通过0在数组的 和之间选择一个实数(好吧,浮点数,无论如何),然后取该实数的下限来做到这一点。由于长度是4,我们正在做的是在0和之间均匀地选择一个实数4。这些数字有四分之一之间0和1之间,另外四分之一1和2之间,一个季度2和3最后一个季度,并且之间3和4。这意味着你有 25% 的机会选择每一个0,1,2和3。(选择的机会4基本上为 0,或者如果rand以排除上限的正常方式实现,则可能恰好为 0 )。因为s2我们现在1在数组的长度和之间均匀地选择一个数字。在这种情况下,我们正在采摘1,2或3用33%的几率各。我们将这个数字加到s1然后除以的余数4。想想我们正在做的事情是从第一边开始s1,然后顺时针移动 1、2 或 3 边(比如)以选择下边。这完全消除了两次选择同一面的可能性。现在让我们看看在给定一个实例的情况下PointPair,在一条线段(可以定义为 a ,对应于线段的两端p1和p2)上随机选取一个点涉及什么Rand:function randomPointOnSide([p1, p2]: PointPair, rand: Rand): Point {&nbsp; const frac = rand.next(); // between 0 and 1&nbsp; return { x: (p2.x - p1.x) * frac + p1.x, y: (p2.y - p1.y) * frac + p1.y };}在这里,我们做的就是选择一个随机数frac,沿途有多远从代表p1到p2我们想去的地方。如果frac是0,我们选择p1。如果frac是1,我们选择p2。如果frac是0.5,我们选择介于p1和之间的中间位置p2。造成这种情况的通式是之间的线性插值p1和p2给出frac。希望在这两者之间,您可以实现您正在寻找的算法。祝你好运!
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript