How to get the distance between peak and trough of a part?

How would you retrieve the distance from top-to-bottom (represented by the red lines) of the following part with different orientations?

part.Size.Y does not work in this scenarios as it returns the Y value relative to the part itself.

1 Like
``````local AbsoluteYSize = math.abs(workspace.Part.Size.Y)
print(AbsoluteYSize)``````
2 Likes

Absolute in-terms of orientation, not the number itself.

2 Likes

Ever tried raycasting from above and from below? Acquire both points and do the math.

Woops, alright. I have realized that you want the absolute Y-size from the peak of the part to the bottom of it.

Do you mean how much it has turned or how to get the Absolute Y Axis Size thanks to the Absolute Orientation

Iâ€™m asking it this way because I donâ€™t understand the problem very well. If you turn the part then the Absolute Y Size is the same, because you donâ€™t change the Part.Size.Y, you only change the Part.Orientation.Y. (In other words, the Absolute Y Size remains the same, or am I wrong?

If you rotate a part, itâ€™s relative Y-size will remain the same, however itâ€™s absolute Y-size relative to the workspace will change. Itâ€™s this size (the distance between the top and bottom of the part relative to the workspace, represented by the red lines in the picture) Iâ€™m trying to find using the simplest method.

Iâ€™m not smart, but have you tried that?

``````local Top = Vector3.fromNormalId(Part.TopSurface)
local Back = Vector3.fromNormalId(Part.BackSurface)
local AbsoluteY = math.abs(Top - Back)``````

That doesnâ€™t apply to all orientations. The goal is to acquire the bottom Y point from global Y-axis and also the top Y point, to calculate the height.

Also the code doesnâ€™t work, because the argument accepts enums.

But the Vector3.FromNormalId() transforms the enum into a vector, why shouldnâ€™t it?
Edit: I have understood it.

Hey! This is a really good question; what I ended up doing is found each corner of your part, then I took the highest point and the lowest point & subtracted to two to get the distance.

I took some math from Stravants Gap Fill to grab the vertices.

Heres what I came up with!

``````local function getCorners(part)
local size, cframe, pos = part.Size, part.CFrame, part.CFrame.p
local x, y, z = size.X/2, size.Y/2, size.Z/2
local r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12 = cframe:components()
local xV, yV, zV = Vector3.new(r4, r7, r10), Vector3.new(r5, r8, r11), Vector3.new(r6, r9, r12)
local xVX, yVY = xV * x, yV * y
local Corners = {
pos + xVX + yVY + zV * z, pos + xVX + yVY - zV * z,
pos - xVX + yVY + zV * z, pos - xVX + yVY - zV * z,
pos + xVX - yVY + zV * z, pos + xVX - yVY - zV * z,
pos - xVX - yVY + zV * z, pos - xVX - yVY - zV * z
}
return Corners
end

while wait() do
local Corners = getCorners(game:GetService("Workspace"):WaitForChild("Selection"))
if Corners then
local y1, y2 = -math.huge, math.huge
for _,pos in pairs(Corners) do
local Y = pos.Y
if Y > y1 then
y1 = Y
end
if Y < y2 then
y2 = Y
end
end
local diff = y1 - y2
print("Difference : "..diff)
end
end
``````

Keep in mind that this will work on every axis as well; https://i.imgur.com/XmaYUZO.png

4 Likes

The above solution is very clever. The way I would have done it is using RayCasting. First I would define the â€śaxisâ€ť to measure the height of, then I would use Model:GetBoundingBox to get the â€śmaximum sizeâ€ť using the pythagorean theorem. Next I would RayCast from this position (offset by a tiny amount) to the center of the part which would give me the position of the edge of the part. I would repeat this for the opposite side of the part giving me two positions. Next Iâ€™d just get the distance between the two points.

2 Likes

I donâ€™t get it.

Is it possible to get the position of the corners of the part? If so, could you explain it better?

That function will return a table full of each cornerâ€™s position!

1 Like

Why this? Is it very important?

We use that in order to compared it to all of the other Y values and see if its the highest or lowest one, if it is then we store it.

1 Like

``````cf = part.CFrame
sz = part.Size
a = cf.TopVector * sz.Y
b = cf.LookVector * sz.Z
c = cf.RightVector * sz.X
yTop = math.max(math.max(a.y, b.y), c.y)
YBottom = math.min(math.min(a.y, b.y), c.y)
``````

Same idea could be used for the x and z extents too. Wait, this actually needs a bit more detailâ€¦ I need a sum somewhere in there.

1 Like

Iâ€™ve probably posted about this trick before â€“ multiply the |second row of the rotation matrix| by size, then sum.

``````local function worldHeight(part)
local w = part.Size*part.CFrame:inverse().upVector
return math.abs(w.x) + math.abs(w.y) + math.abs(w.z)
end
``````

Hereâ€™s a ghetto visualization:

The inversion is a quick way to isolate the second row of the matrix, since inversion is equivalent to transposition when youâ€™re working with rotations.

10 Likes