I’ve tried looking this up, however I’ve found nothing so I’m creating this topic in hopes of finally finding out about Part/Mesh boundary detection. The soul purpose of this would be the limitation of part placement system outside of the boundary. I’ve tried using region3 , but that turned out to be a bit messy and unreliable. Here’s the code for that bit:

```
--//Plot is a transparent part
Grid = 2
function snap(pos, modelSize)
local X = math.floor(pos.X/Grid+0.5)*Grid
local Y = math.floor(pos.Y/Grid+0.5) * Grid + modelSize.Y/2
local Z = math.floor(pos.Z/Grid+0.5)*Grid
return Vector3.new(X,Y,Z)
end
function checkBoundaries (Object, Offset, Plot)
if Object and Plot then
local pos = Object.PrimaryPart.CFrame
local min = Vector3.new(pos.X + Offset,pos.Y + Offset, pos.Z + Offset)
local max = Vector3.new(pos.X - Offset,pos.Y - Offset, pos.Z - Offset)
local region = Region3.new(max, min)
region = region:ExpandToGrid(4)
for _,Part in pairs(game.Workspace:FindPartsInRegion3(region,nil,math.huge)) do
if Part == Plot then
return true
else return false
end
end
end
function RenderStepped()
local IgnoreTable = {}
Switch = checkBoundaries(SampleBlock, Grid, Plot)
if GhostBlock and Switch then
local UnitRay = Mouse.UnitRay
local ray = Ray.new(UnitRay.Origin,UnitRay.Direction*100)
local modelSize = helperFunctionsDictionary.checkModelSize(GhostBlock , rotationY)
local target,pos,normal = workspace:FindPartOnRayWithIgnoreList(ray,IgnoreTable)
GhostBlock:SetPrimaryPartCFrame(CFrame.new(snap(pos, modelSize))*CFrame.Angles(0,math.rad(rotationY),0))
GhostBlock:SetPrimaryPartCFrame(CF)
end
end
```

Specific issue with that code(Bits of parts going through the boundary)

I’ve figured that the method that’s used by @EgoMoose in his post Creating A Furniture Placement System (**Specific code of his which I’m talking about is written below**) is more effective. However it’s limited to a 2D plane. Is there a way to expand/detect the boundaries?

```
function Placement:CalcCanvas()
local canvasSize = self.CanvasPart.Size
-- want to create CFrame such that cf.lookVector == self.CanvasPart.CFrame.upVector
-- do this by using object space and build the CFrame
local back = Vector3.new(0, -1, 0)
local top = Vector3.new(0, 0, -1)
local right = Vector3.new(-1, 0, 0)
-- convert to world space
local cf = self.CanvasPart.CFrame * CFrame.fromMatrix(-back*canvasSize/2, right, top, back)
-- use object space vectors to find the width and height
local size = Vector2.new((canvasSize * right).magnitude, (canvasSize * top).magnitude)
return cf, size
end
function Placement:CalcPlacementCFrame(model, position, rotation)
-- use other method to get info about the surface
local cf, size = self:CalcCanvas()
-- rotate the size so that we can properly constrain to the surface
local modelSize = CFrame.fromEulerAnglesYXZ(0, rotation, 0) * model.PrimaryPart.Size
modelSize = Vector3.new(math.abs(modelSize.x), math.abs(modelSize.y), math.abs(modelSize.z))
-- get the position relative to the surface's CFrame
local lpos = cf:pointToObjectSpace(position);
-- the max bounds the model can be from the surface's center
local size2 = (size - Vector2.new(modelSize.x, modelSize.z))/2
-- constrain the position using size2
local x = math.clamp(lpos.x, -size2.x, size2.x);
local y = math.clamp(lpos.y, -size2.y, size2.y);
-- create and return the CFrame
return cf * CFrame.new(x, y, -modelSize.y/2) * CFrame.Angles(-math.pi/2, rotation, 0)
end
```