Getting the outer positions of an area(circle)

Hey DevForum, currently I am looking for a way to get the various positions around an area like this:

Screenshot_2651
(Black dots represent the positions I’m trying to get in that 30x30 area, pretend they are perfectly placed)


I don’t really know where to start, I’ve only got this code down:

local function GetPositions(NumberOfPositions, Area, RootPosition)
   local Positions = {}
   --[[Get the positions]]
   return Positions
end

local Area = 30^2
local RootPosition = Vector3.new(0,2,0)

local Positions = GetPositions(8, Area, Position)

I tried researching and I couldn’t really find anything, if there are some resources out there that might help me; link them in the replies, any help is appreciated!

1 Like

Is the root position the centre of the circle? If so then the formula would be:

For N total positions, the nth position would be:

r = sqrt(Area/π)

pos(n) = rootPosition + r*Vector3.new( math.cos(2*π*n/N), 0, math.sin(2*π*n/N) )

This comes from looking at polar coordinates in 2D if you were wanting to learn more about the maths. You could also try searching for the unit circle.

1 Like

Alright, so it looks like you are trying to find the positions of the black dots which are all equidistant from each other and the center. Looking at your GetPositions function, it looks like the number of dots of a parameter, so we will have to use some geometric principles here.

Firstly, since this is a circle, we can take advantage of angles as a way to find the directions of each black dot. For example, if we want 8 spaces, and our circle is 360 degrees in total, then we can just divide 360 / 8 to get the angular distance between each space (the angle separation of each relative to the center.
image

Using the angle, and the radius of the circle (not the area), we can get all the positions easily by converting the polar coordinates of each of these angles to vector form with respect to the XZ plane, since this circle is on the vertical Y plane

local function GetPositions(NumberOfPositions, Radius, RootPosition)
   local Positions = {}
   local angularDisplacement = 360 / NumberOfPositions

   for i = 1, NumberOfPosition do
       local angleVector = Vector3.new(Radius * math.cos(math.rad(i * angularDisplacement)), 0, Radius * math.sin(math.rad(i * angularDisplacement)))
       Positions[#Positions + 1] = RootPosition + angleVector
   end

   return Positions
end

local Radius = 30
local RootPosition = Vector3.new(0,2,0)

local Positions = GetPositions(8, Radius, Position)

Now if you wanted it to work for all orientations of the circle, you would need some vector transformations relative to the CFrame.LookVector but I won’t get into that. Good luck

1 Like

If you hate math and want to cheat you can also rotate a stationary CFrame and then use the LookVector to find the distance away from the center.

local cf = CFrame.new(Vector3.new())
local segments = 10
local radius = 10
local Positions = {}
for i = 1, segments do
 local angle = 360/i
 local cheating = cf * CFrame.Angles(0,math.rad(angle),0)
 table.insert(Positions, cheating.Position + cheating.LookVector * radius)
end

Trigonometry lovers hate this one simple trick!

1 Like

Testing the code it came out like this:

The code:

local cf = CFrame.new(Vector3.new(0,2,0))
local segments = 10
local radius = 10
local Positions = {}
for i = 1, segments do
	local angle = 360/i
	local cheating = cf * CFrame.Angles(0,math.rad(angle),0)
	table.insert(Positions, cheating.Position + cheating.LookVector * radius)
end

for i,v in pairs(Positions) do
	local Part = Instance.new("Part", workspace)
	Part.Anchored = true
	Part.Size = Vector3.new(1,1,1)
	Part.Position = v
end

There is an error here:

What does #Position represent?

My mistake!

local cf = CFrame.new(Vector3.new(0,2,0))
local segments = 10
local radius = 10
local Positions = {}
local single = 360/segments

for i = 1, segments do
 local angle = single*i
 local cheating = cf * CFrame.Angles(0,math.rad(angle),0)
 table.insert(Positions, cheating.Position + cheating.LookVector * radius)
end

for i,v in pairs(Positions) do
 local Part = Instance.new("Part", workspace)
 Part.Anchored = true
 Part.Size = Vector3.new(1,1,1)
 Part.Position = v
end

Oh god the formatting. Define “single” and then do single*i for angle, those are the only changes

3 Likes

I’ll now proceed to understand how it works, thanks for the code :wink:

1 Like

Glad I could help! On a high level, all I’m really doing here is finding the angle between each segment (360/10), then rotating a cframe at the center position to match that angle. By doing that we can set the part position to the position of the cframe, plus the direction the rotated cframe is facing (times the radius to get the outside of the circle).

Is it the best method? No, and if you like math it makes you sad.
Does it work? Yup!

1 Like

it should be #Positions, sorry about that. It’s the length of the array

1 Like