I believe this is the direct method you were looking for, but it’s a lot harder than just projecting vectors. Here it is anyway. Consider this:

- Point A is the first point.
- Point B is the second point
- Vector ℓ is the tangent vector of the sphere at point A.
- The red vector is the normal vector of the sphere at the tangent point.
- The green point is the midpoint between A and B.
- The green vector is the vector pointing from the tangent line to the midpoint of A and B and extending to the center of the circle.
- The black point at the center is the center of the sphere.

In order to get the center of the sphere, you need to **find the intersection between the red vector (normal vector) and the green vector (midpoint vector)**. In code, this looks like this:

```
local function GetCenter(p1, p2, t)
local m = (p2 + p1) * 0.5; -- midpoint between p1 and p2
local d = (p2 - p1).Magnitude -- distance between p1 and p2
local s = (p2 - p1).Unit; -- the vector going from p1 to p2
local v = t:Cross(s).Unit; -- a vector used to get the normal vector at the tangent point
local n = t:Cross(v).Unit; -- normal vector at the tangent point
local a = s:Cross(n).Unit; -- a vector orthogonal to the normal vector and midvector used to get the vector perpendicular to the mid vector
local b = s:Cross(a).Unit; -- the vector perpendicular to the midvector
local center = GetIntersection(p1, -n, m, b); -- the center of the sphere is at the intersection of these two vectors
local radius = (center - p1).Magnitude; -- the radius of the sphere
return center, radius;
end
```

If you’re interested in the intersection function I used, I’ll add it here as well.

```
local Huge = 10000000000000000000;
--[[ an intersection function i found here in the dev forum that i editted to give
a y coordinate, props to @PlaasBoer]]
local function GetIntersection(startPoint1, dir1, startPoint2, dir2)
local endPoint1 = startPoint1 + dir1 * Huge;
local endPoint2 = startPoint2 + dir2 * Huge;
local point_1_x1 = startPoint1.X;
local point_1_y1 = startPoint1.Z;
local point_1_x2 = endPoint1.X;
local point_1_y2 = endPoint1.Z;
local point_2_x1 = startPoint2.X;
local point_2_y1 = startPoint2.Z;
local point_2_x2 = endPoint2.X;
local point_2_y2 = endPoint2.Z;
-- m = (y1 - y2) / (x1 - x2)
local line_1_m = 0;
local line_2_m = 0;
-- b = -(mx1) + y1
local line_1_b = 0;
local line_2_b = 0;
local intersect_x = 0;
local intersect_z = 0;
local isLineOneVertical = ((point_1_x1 / point_1_x2) % 2) == 1;
local isLineTwoVertical = ((point_2_x1 / point_2_x2) % 2) == 1;
if isLineOneVertical and isLineTwoVertical then
error("There is no cross point, both vertical");
end
-- Line 1
if isLineOneVertical then
line_2_m = (point_2_y1 - point_2_y2) / (point_2_x1 - point_2_x2);
line_2_b = -(line_2_m * point_2_x1) + point_2_y1;
intersect_x = point_1_x1;
intersect_z = (line_2_m * intersect_x) + line_2_b;
-- Line 2
elseif isLineTwoVertical then
line_1_m = (point_1_y1 - point_1_y2) / (point_1_x1 - point_1_x2);
line_1_b = -(line_1_m * point_1_x1) + point_1_y1;
intersect_x = point_2_x1;
intersect_z = (line_1_m * intersect_x) + line_1_b;
else
line_1_m = (point_1_y1 - point_1_y2) / (point_1_x1 - point_1_x2);
line_2_m = (point_2_y1 - point_2_y2) / (point_2_x1 - point_2_x2);
if line_1_m == line_2_m then
error("There is no cross point, both same slope")
end
line_1_b = -(line_1_m * point_1_x1) + point_1_y1;
line_2_b = -(line_2_m * point_2_x1) + point_2_y1;
intersect_x = (line_2_b - line_1_b) / (line_1_m - line_2_m);
intersect_z = (line_1_m * intersect_x) + line_1_b;
end
local u = (intersect_x - point_1_x1) / dir1.X
return Vector3.new(intersect_x, startPoint1.Y + dir1.Y * u, intersect_z);
end
```

Testing this in game results in a very nice looking sphere manipulation show. I added the multiple vectors that are created by the code.

Watch the sphere manipulation show here

I know this thread is old, but I couldn’t help but offer this solution!