Random point in a triangle

1.3k Views Asked by At

This subject has already been covered here, and my question is slightly different.

Preliminary warning: i'm quite a noob (and probably will continue to be unless i go back to school), but i do love some maths, the one i can't do with programming. Please excuse my lack of "academism". If the question is too informal, please let me know, i will ask my question elsewhere.

In an euclidean space I got a triangle ABC, quite special, i don't know how to name it :

  • A is (0, 0)
  • B is (width, 0)
  • C is (cx, cy)

So 3 numbers are enough to describe ABC.

I want to pick a random point inside ABC. How to do it ?

I tried the following: Get a random point in the parallelogram, then "squeeze" into ABC.

let randomPoint = (width, C) => {
    let r1 = Math.random()
    let y = C.y * r1
    let r2 = Math.random()
    let x = width * r2 * (1 - r1) + C.x * r1
    return new Point(x, y)
}

enter image description here Of course, there's to much points near C. So i believed i would be able to fix that by changing the distribution along y.

So i got better results:

let randomPoint = (width, C) => {
    let r1 = Math.random() * Math.random()
    let y = C.y * r1
    let r2 = Math.random()
    let x = width * r2 * (1 - r1) + C.x * r1
    return new Point(x, y)
}

enter image description here But this is very empiric, and obviously, this is not uniform.

Is there a way to change the computation of r1 the random number to have a distribution that will be uniform inside ABC ?

NB: i realize my self that it should be a simplier solution by mirroring point in the upper triangle (BCA') to the first triangle ABC. I will post the solution in an anwser. Still however any comment will be much appreciated since I feel myself like fumbling in the fog.

1

There are 1 best solutions below

3
On

Ok there is a simple solution which consist of...

i don't even know how to describe it properly...

to "remap the upper triangle to the lower over the diagonal".

So with a picture:

enter image description here

And by code (JS/pseudo-code):

let randomPoint1 = (width, C) => {

    let r1 = Math.random()
    let r2 = Math.random()

    // if over the diagonal, then flip r1 & r2
    if (r1 + r2 > 1) {
        r1 = (1 - r1)
        r2 = (1 - r2)
    }

    let x = width * r2 + C.x * r1
    let y = C.y * r1
    return new Point(x, y)
}

Once again, any mathematical words will be appreciated here. It's quite annoying to have problems and not being able to tell them because lacking vocabulary and mathematical rigor.