So I have something like this, a rotated “plane”. Let’s give Vector3s a (X, Z) notation. The relative top left point is coordinates (0, 0), the relative bottom right point is (2, 1). The arrow signifies the lookVector of the CFrame of the plane that’s given.
Pretend the Y rotation (0°)/position is static, (non-existent).
First you want to get all other corners of your rectangle.
Since you’re rotating around the top left corner you can get the “real” position of 0, 1 and 2, 0 first. Assuming rotation is clockwise (the rotation shown should be negative in that case) you’ll want to “travel” in the direction of rotation by width to get the real position of 2, 0.
First you’ll want the slope of your line. You can use some trigonometry for this. 2 (the width) should be your hypotenuse. Now you’ll want to find the Y offset from the origin of rotation’s y coordinate. You can use sin to do this: Y/width = sin(radiansOfRotation)
Now you multiply the sin value by with to get the Y offset from the origin’s Y coordinate.
You can then get the X offset using the Pythagorean formula like so: A^2 + Y^2 = width^2
So your X offset should be this: sqrt(A) = sqrt(width^2 - Y^2)
You can now repeat this process for 0, 1 by increasing the rotation value by 90 degrees (the angle of your corners).
Now you can use the offsets of the other two corners to know where the last corner is.
Once you have all of your corners you can find the midpoint and you’re done.
For this specific case, you can probably use some CFrame math. In order to do that, we will need to do one thing, split into three things:
turning the part on its corner
getting to the corner
turning by an angle modeled after a slope of 1/2
going back to center
Getting to a corner is as easy as getting the part’s size and dividing by two. We then translate by that from the part’s starting CFrame.
For turning by the slope of 1/2, math.atan returns an angle equivalent to Y/X, rise over run, same as slope, so math.atan(slope).
We would then clean it up by returning back to the center by translating by a negative of the corner CFrame.
code
-- returns a corner when multiplied by part size
-- negate x and/or z for other corners
local TransformV3 = Vector3.new(1,0,1) / 2
local rotatedPosition = (
-- start with part's CFrame
part.CFrame *
-- move to corner
CFrame.new(part.Size * TransformV3) *
-- turn by slope Y/X, might need to be negated
CFrame.Angles(0,math.atan(0.5),0) *
-- move back to center
CFrame.new(-part.Size * TransformV3)
-- return position
).Position
For other use-cases, I would essentially need to know what can change, and how the formula needs to be mutated.
Here’s some code for my earlier answer.
This assumes you have the angle of rotation and point of rotation(origin for new vector space)
Example Script
local origin = Vector3.new(3,2,-1)
local angle = 30
--because, truncation
local int = {
[1] = math.cos(math.rad(angle)),
[2] = -math.sin(math.rad(angle)),
[3] = math.cos(math.rad(angle-90)),
[4] = -math.sin(math.rad(angle-90)),
[5] = math.cos(math.rad(-angle)),
[6] = -math.sin(math.rad(-angle)),
[7] = math.cos(math.rad(-angle-90)),
[8] = -math.sin(math.rad(-angle-90)),
}
for i,v in pairs(int) do
v = v*1000
v = math.floor(v)
int[i] = v/1000
end
--axis units mapped to alternate vector space
local mUnitVec = Vector3.new(int[1],0,int[2])
local oUnitVec = Vector3.new(int[3],0,int[4])
local xUnitVec = Vector3.new(int[5],0,int[6])
local zUnitVec = Vector3.new(int[7],0,int[8])
--base grid is x,y,z y static
--new grid is m,n,o n static
function toMNO(XYZ)
local XYZNoOffset = XYZ-origin
local x = XYZNoOffset.X
local z = XYZNoOffset.Z
return (x*xUnitVec + z*zUnitVec)
end
function toXYZ(MNO)
local m = MNO.X
local o = MNO.Z
return ((m*mUnitVec+o*oUnitVec)+origin)
end
--setup info
print("Origin of MNO on XYZ: ", origin)
print("Angle in Degrees(CounterClockwise: "..angle)
--unit vectors
print("M axis unit in xyz:",mUnitVec)
print("O axis unit in xyz:",oUnitVec)
print("X axis unit in mno:",xUnitVec)
print("Z axis unit in mno:",zUnitVec)
--tests
print("(0,0,1) -> ",toMNO(toXYZ(Vector3.new(0,0,1))))
print("(3,0,1) -> ",toMNO(toXYZ(Vector3.new(3,0,1))))
print("(1,0,1) -> ",toMNO(toXYZ(Vector3.new(1,0,1))))
print("(2,0,1) -> ",toMNO(toXYZ(Vector3.new(2,0,1))))
print("(7,0,1) -> ",toMNO(toXYZ(Vector3.new(7,0,1))))
print("(4,0,4) -> ",toMNO(toXYZ(Vector3.new(4,0,4))))
print("(1,0,0.5) -> ",toMNO(toXYZ(Vector3.new(1,0,0.5))))
--rounding to 1/100 would be pretty accurate or you can just increase accuracy by changing the 1000 up there to 1000000 :P