- Home /

# Finding random position in torus?

Hello,

I am trying to finding a random position in torus.

Actually I found a method that finding torus iteratively. But it includes while loop and I don't want to use while loop in a method while it slows down update duration.

Are there any algorithm for my purpose.

Here is the code that I wrote

```
Vector3 GetARandomPositionInTorus(Vector3 center)
{
Vector3 dest = transform.position;
while (Vector3.Distance(dest, transform.position) < newCirclePositionMinDistance)
{
Vector3 randomPosition = Random.insideUnitSphere * newCirclePositionMaxDistance;
randomPosition = new Vector3(randomPosition.x, transform.position.y, randomPosition.z);
dest = randomPosition + center;
}
return dest;
```

}

**Answer** by AlucardJay
·
Oct 20, 2016 at 05:32 PM

*This is more of a math problem than a Unity problem.*

Imagine the torus as a necklace; a bunch of spheres connected with a string through their centers, and aligned in a ring.

Get a random angle around that ring.

Find the position of the string.

Imagine a sphere there.

Get a random point in that sphere.

Now you have a point that lies within the torus \o/

Here's some code to demonstrate. I have not factored in the position and orientation of the torus, this is just to show the above steps in practice. Attach to an empty gameObject in a new scene. Hit Play. Left-click in the scene view and change the inspector values while playing.

```
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class RandomPosInTorus : MonoBehaviour
{
public float innerRadius = 2f;
public float outerRadius = 5f;
[Space(20)]
public int iterations = 1000;
public GameObject markerObject;
private List< GameObject > markerList; // object pool. for testing purposes
void Start()
{
markerList = new List< GameObject >();
Generate();
}
void Update()
{
if ( Input.GetKeyDown( KeyCode.Mouse0 ) )
Generate();
}
void Generate()
{
// object pool. for testing purposes. remove old markers each time Generate is called
if ( markerList.Count > 0 )
foreach ( GameObject marker in markerList )
Destroy( marker );
markerList = new List< GameObject >();
float wallRadius = ( outerRadius - innerRadius ) * 0.5f;
float ringRadius = wallRadius + innerRadius; // ( ( max - min ) / 2 ) + min
for ( int i = 0; i < iterations; i ++ )
{
// create marker object
GameObject go;
if ( !markerObject )
{
go = GameObject.CreatePrimitive( PrimitiveType.Sphere );
go.transform.localScale = Vector3.one * 0.05f;
}
else
go = (GameObject)Instantiate( markerObject );
go.name = "Sphere_" + i.ToString();
markerList.Add( go );
// position marker object
Transform tx = go.transform;
tx.position = GetRandomPositionInTorus( ringRadius, wallRadius );
tx.parent = transform;
}
}
Vector3 GetRandomPositionInTorus( float ringRadius, float wallRadius )
{
// get a random angle around the ring
float rndAngle = Random.value * 6.28f; // use radians, saves converting degrees to radians
// determine position
float cX = Mathf.Sin( rndAngle );
float cZ = Mathf.Cos( rndAngle );
Vector3 ringPos = new Vector3( cX, 0, cZ );
ringPos *= ringRadius;
// At any point around the center of the ring
// a sphere of radius the same as the wallRadius will fit exactly into the torus.
// Simply get a random point in a sphere of radius wallRadius,
// then add that to the random center point
Vector3 sPos = Random.insideUnitSphere * wallRadius;
return ( ringPos + sPos );
}
}
```

this is a great solution. using a sphere around a point on the spine is much more efficient than figuring a random point on the circle around the skin at that point.

one minor note is that this will produce points that are not *evenly* distributed within the torus. that might not matter for the OP, not sure.

there are a couple aspects of non-evenness here:

points will be more dense near the skin of the torus than in the interior.

points will be more dense on the inside wall of the skin than on the outside.

offhand i'm not sure how to correct these. i think my approach would be to select a point evenly within a unit disk (this counteracts the first bullet-point above), and then to nudge the point towards the right-hand side (say) of the disk, and then translate the disk out to spine of the torus and rotate it a random amount around the center. this would counteract the second bullet.

but the "nudge" amount is non-trivial. with a torus of infinite radius the nudge amount should be zero, and with a torus where the center hole is zero it should be maximal.

Thanks. I went for a solution that was easy to understand, not factoring evenness of distribution.

*points will be more dense near the skin of the torus than in the interior.* : not sure I agree with this. I assume it would be a very rare case where the random sphere point would line up with the torus surface. (on the edge of the circle that is the same as the torus surface)

*points will be more dense on the inside wall of the skin than on the outside.* : agreed. A nudge factor could work, or use a lookup reference to evenly bias the random value (something like this solution with a gradient mask: https://forum.unity3d.com/threads/help-with-random-distribution-script.277194/#post-1831558 )

p.s. I really like your website :)

howdy.

i think i was mistaken because i read your post too fast and thought it was selecting points *on* the unit sphere rather than *inside* it. assuming that Random.insideUnitySphere yields a uniform distribution inside the sphere, then i think my first point goes away: "points will be more dense near the skin". I think the second point: "points will be more dense towards the inside hole of the donut" is still true, tho. again, really nice solution!

totally separately, i recently looked into distributing points randomly on the *surface* of an arbitrary triangle mesh. it turned out not to be too hard, but it was fun. here's a WebGL demo.

What makes this superior to getting an angle along the normal axis of the torus and selecting a random position at that angle through Random.insideUnitSphere?

howdy.
i think i may have been mistaken, because i read @alucardj's post too fast and thought it was selecting points *on* the unit sphere rather than *inside* it. assuming that Random.insideUnitySphere yields a uniform distribution inside the sphere, then i think my first point goes away: "points will be more dense near the skin". I think the second point: "points will be more dense towards the inside hole of the donut" is still true, tho.

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.