Split models from intersection points

Without showing too much code and overcomplicating the question, basically, I am generating walls. Each wall has a start and end point (marked by the poles) Both the poles and walls are stored in tables.

I have code that checks for intersecting walls. This works, and detects where intersections are, and create a pole to mark the position.

The idea with splitting the wall is you go from the wall all being under 1 model as 1 wall, I check the intersection point and any wall that is beyond said point of the intersection gets put into its own separate wall.

local test = wall:GetPivot().LookVector:Cross(Vector3.new(0, 1, 0))
	
	-- Transfer wall parts from 'wall' to 'WallModel'
	for _, wallPart in pairs(wall:GetChildren()) do
		if test.Z ~= 0 then
			if wallPart.Position.Z < startPoint.Z then
				wallPart.Parent = WallModel
			end
		end
		
		if test.X ~= 0 then
			if wallPart.Position.X < startPoint.X then
				wallPart.Parent = WallModel
			end
		end
	end

The main problem is that when you have a wall that requires several splits at once, it only detects the original wall and splits from there.

So basically, the wall is created, there are several splits in it, it detects all those splits, and splits all those walls it’s intersecting. However, that new wall that was just added isnt checked with the original loop.

I’m sorry, it’s really hard to explain, and I don’t want to just paste 400 odd lines of code. Hopefully someone knows what I am trying to accomplish and have a better solution?

I believe the code I have above is the main issue though and that my method for getting the intersection point isn’t right. startPoint is the intersection points position

Video example


As you can see, most of the walls are cutting correctly. But it’s missing some spots. Unsure if this is maybe how I am storing the poles and walls, but they should be storing correctly, just that the code above isn’t cutting them correctly

More help (hopefully)
So the cream wall is generated last. When generated, it detects 2 intersections. And when I test this time, it did Intersection 1 first (it appears to be random each time, whether it goes to the intersection of the left, or right)


And so it then splits

So OG wall is the original wall model, new wall is the one created, and the code above goes through OG wall, finds all the parts to the left of intersection 1, and puts them in New wall.

However, since the loop doesn’t take into account newly created walls, new wall doesn’t detect that there’s an intersection there. Reason I don’t detect new walls added is cause it broke the intersection system, so I have to only loop through the existing walls

2 Likes

Hi, I’m aware that this is a necrobump, however no solution was ever posted so I’d like to share my solution. I encountered a similar issue with my wall builder and want to share my process achieving this. I have a function that allows placing walls, starting at point 1 and ending at point 2.

Video demo:

So my process is this:
1- get a table of all parts that may intersect with the main wall (the newly placed wall). For this I made this function, where ‘wall’ is a model that contains every part of the wall. A wall’s hierarchy looks like this for reference:
image
So, get all walls touching the main wall, ensure there are no duplicate walls, and ensure you are not adding the main wall to this array:

function module:GetWallsThatMayIntersect(wall: Wall)
	local parts: {Wall} = {}
	local part1 = wall:WaitForChild('Part1')
	for i,v in ipairs(workspace:GetPartsInPart(part1)) do
		if v.Parent ~= wall and (v.Name == 'Part1' or v.Name == 'Part2') then
			local wallParent = v.Parent
			if not table.find(parts, wallParent) then
				table.insert(parts, wallParent)
			end
		end
	end
	local part2 = wall:WaitForChild('Part2')
	for i,v in ipairs(workspace:GetPartsInPart(part2)) do
		if v.Parent ~= wall and (v.Name == 'Part1' or v.Name == 'Part2') then
			local wallParent = v.Parent
			if not table.find(parts, wallParent) then
				table.insert(parts, wallParent)
			end
		end
	end
	return parts
end

2- Now, for each wall, find the intersection point of the main wall and each of the touching walls. Determine if this intersection is an intersection where the wall can split (eg. is the intersection grid aligned?). If this intersection point is valid, add it to a table.
In a second table, add the point and the corresponding wall. You should have two tables, t1 is the table of intersection points, t2 is the table of intersection points with corresponding wall models:

t1 = { Vector3 };
t2 = {
    { WallModel = wallModel; IntersectionPoint = Vector3; }
}

3- Sort the table of intersection points. I did this by doing PointToObjectSpace with the wall’s origin CFrame (origin) on the intersection point, on the Z axis:

		table.sort(mainWallIntersections, function(a,b)
			local vectorALocal = origin:PointToObjectSpace(a)
			local vectorBLocal = origin:PointToObjectSpace(b)
			return vectorALocal.Z > vectorBLocal.Z
		end)

4- Now, from left to right, create the wall where point 1 is the wall’s first point and point 2 is the first intersection, next iteration point 1 is intersection point and point 2 is next intersection all the way until you get to the last iteration where the first point will be the last intersection point and the second point will be the original main wall’s second point. There are a lot of variables but this works for me:

		local pole1, pole2 = wallUtil:GetPoles(wallModel)
		height = wallUtil:GetWallHeight(wallModel)
		local last = plotBottomLeft:ToObjectSpace(pole1.CFrame).Position
		for i = 1,#mainWallIntersections + 1 do
			placeWall(plotModel, {
				Point1 = last;
				Point2 = mainWallIntersections[i] or plotBottomLeft:ToObjectSpace(pole2.CFrame).Position;
				WallHeight = height
			}, true)
			last = mainWallIntersections[i]
		end

For a visual, this is what it would look like, neon spheres are where walls are being placed:


5- Delete the main wall.
6- Now, remember that second table with walls intersecting the main wall? We’re going to do the same thing pretty much, but it’s much easier, we place point 1 where the intersecting wall’s point 1 is, point 2 where the intersection is, then another wall where point 1 is where the intersection is, and point 2 is where that wall’s original wall’s point 2 is. At the end, delete that intersecting wall:

	for i,v in ipairs(nonMainWallIntersections) do
		local pole1, pole2 = wallUtil:GetPoles(v.WallModel)
		local height = wallUtil:GetWallHeight(v.WallModel)
		placeWall(
			plotModel, {
				Point1 = plotBottomLeft:PointToObjectSpace(pole1.Position);
				Point2 = plotBottomLeft:PointToObjectSpace(v.Intersection);
				WallHeight = height;
			}, true
		)
		placeWall(
			plotModel, {
				Point1 = plotBottomLeft:PointToObjectSpace(v.Intersection);
				Point2 = plotBottomLeft:PointToObjectSpace(pole2.Position);
				WallHeight = height;
			}, true
		)
		deleteWall(v.WallModel)
	end

That’s it. Hope this helps if you haven’t found a solution already! And if you need any help interpreting my script or have any questions, let me know.