I’m drawing a 3D cosine line given two points in space using parts. I created a transformation of the cosine function to travel between the two extrema on the interval [x_0, x_1], along with its derivative. It returns the worldspace height over an interval
Functions (On Desmos):
Currently the script will plot the cosine function without regards to the Z axis except for the XZ distance intended for pivoting, so no rotation or pivot from the starting point. The script creates a worldspace CFrame fom the function output and then composes that with an angle CFrame with the Z axis rotated over the atan of the derivative output.
2D Result:
I haven’t been able to figure out how to rotate or pivot these points with only CFrames and the worldspace positions. I tried welding all of the parts together but that was leading me to half-circles and other strange phenomena
Here’s my script:
function script.DrawCosineLine.OnInvoke(p0: Vector3, p1: Vector3, step: number)
local xzDist = math.sqrt((p1.X - p0.X)^2 + (p1.Z - p0.Z)^2)
-- (y_1 - y_0) * (1 - cos(pi * (x - x_0) / d_xz)) / 2 + y_0
local pathHeightFn = function(x) return (p1.Y - p0.Y) * (1 - math.cos(math.pi * (x - p0.X) / xzDist)) / 2 + p0.Y end
-- y' of above
-- pi * (y_1 - y_0) * sin(pi * (x - x_0) / d_xz) / (2 * d_xz)
local pathSlopeFn = function(x) return math.pi * (p1.Y - p0.Y) * math.sin(math.pi * (x - p0.X) / xzDist) / (2 * xzDist) end
for i = 0, xzDist, step do
local part = Instance.new("Part")
part.Name = "Cosine Step " .. i
part.Anchored = true
part.CanCollide = false
-- The darker a point is, the further it is from p_0
part.Color = Color3.fromRGB(171, 203, 255):Lerp(Color3.fromRGB(0, 98, 255), i / xzDist)
part.Size = Vector3.new(step, 0.5, 0.5)
part.Parent = workspace
local fnInfo2D = {}
fnInfo2D.X = p0.X + i -- p_0 with step applied to get height at step. Z axis is accounted for with xzDist as step stopping point
fnInfo2D.Y = pathHeightFn(fnInfo2D.X)
fnInfo2D.M = pathSlopeFn(fnInfo2D.X)
print("X: " .. fnInfo2D.X .. ", Y: " .. fnInfo2D.Y .. ", M: " .. fnInfo2D.M)
-- Set the CFrame of the part to be placed along the X and Y of pathFn with Y angle of pathFnDdx
part.CFrame = CFrame.new(fnInfo2D.X, fnInfo2D.Y, 0) * CFrame.Angles(0, 0, math.atan(fnInfo2D.M))
end
end
script.DrawCosineLine:Invoke(Vector3.new(-30, 5, 0), Vector3.new(30, 25, 0), 1.5)
Thanks