Reposition tubes and boxes outwards

I have this combination of boxes and tubes that represent a room’s walls on a floor plan.

Example: Babylon.js Playground

Currently, the corners pivot point is in the center of the box, but I need it to be at the inner room corner of the box.

This means that the tube and boxes of the room need to be repositioned outwards like in the image below:

27-12_01_42

I think I figured a way to reposition the boxes, by calculating direction vectors from the center of the room and adding the difference.

In this case, how do I reposition the tubes also? Can I move the pivot for the starting and end points of the tubes to the corner of the tube also?

In general, this is the right strategy? Or should I redraw the room with different meshes at this point?

@JohnK your help is appreciated.

Not so easy - needs thinking about. What is main issue, positioning tubes and boxes so that the boxes do not to overlap tubes or setting pivots?

The issue is that for the next step, the user will be adding windows.

At the moment, if the user placed the window at the very left of wall 0, then it would look as if the window is “inside” wall 3.

Even though in terms of “coordinates” its correct, its visually wrong.

Does this make sense?

How is your user positioning the boxes, tubes and windows? I mean for example using drag and drop, providing numeric data etc.

For the walls, its based on clicks. First click sets the first corner, second click the second corner etc until you have a closed shape room. Center of the box is the click location.

The tubes are just connecting the corners.

I didnt implement the windows yet but I am thinking it will be drag n drop.

Will all walls meet at right angles?
Will all walls be vertical and horizontal?

No, I made it so you can draw any angle you want

So you could have something like this
27-14_24_32

Then I do not understand the role of the boxes in the corner!

This is how it looks without the boxes.
27-14_29_46

I added the boxes because it’s easy for the user to resize the walls and its a good visual cue for the user to know where the wall starts and ends.

But even if you forget the boxes, as you can see above, the tubes still need fixing. So I am not sure what is the right thing to do right now =/

Here is how the end result should look like:

See how on the green arrow, you cannot place a window on that black box. Its not a space available on the inside dimensions of the room.
And on the red arrow you can because its on the inside dimension of the room.

I hope I am explaining this correctly.

Does the thickness of the black lines represent the thickness of the walls to be built? If so you cannot place a window at the red arrow since it overlaps a wall!!?

Yes you are right about that! I made a mistake there. But the issue still persists because as it is the window would be positioned like the red arrow on all corners.

I think I am overcomplicating things also.

Should I just use buildFromPlan from here Using Build a House from a Floorplan - Babylon.js Documentation and then place the windows?

Because I though its better to let the user show me the windows position and then transform to 3D.

But instead, I should create the mesh in 3D now, keep the orthographic top view, then place the windows, and then transforms again with windows/doors?

Does this make sense?

Just a suggestion. Once the user has clicked on all the corners make an assumption that lines joining the corners form the inner walls of the room. Take any of the lines L joining two corners and when drawing the tubes of radius R for L add +R or -R to the points forming L. in the direction of the normal to L. Plus or minus depending of the relative position of the line to the center of the room.

A simple case let L define a wall of thickness T (radius R = T / 2) where L has length 200 with corners (0, -100) and (0, 100) and is a right hand wall. The the path line, P, for the tube is from (R, -100) to (R, 100).

Now take a window of length W with its center C (R, y) on the path line P, then the constraints for y are

y - W/2 > -100 and y + W/2 < 100

Bit more fiddly if line is an angle but just as doable.

How do I get the normal?

I found this How To Align Torus With Tube? - Questions & Answers - HTML5 Game Devs Forum but looks a bit complex. Is there an easier way?

Because I am having trouble understanding this:

each tube axis point holds a Path3D point

How do I get the normal facing in the correct direction? Because a tube must have many normals facing in different directions correct?

True in 3D but your house plan is 2D so only two normals one the negative of the other.

When p0 and p1 are two points (position vectors) on a line then t = p1 - p0 will give a vector along the line from p0 to p1 and the vector (-t.y, t.x) will be one of the normals. You then have to decide which is pointing to the outside. For a usual 2D axis system with p0, p1 in counter clockwise order and t = p1 - p0 the the normal needed is (ty, -tx)

Which is OK https://www.babylonjs-playground.com/#J0VTG5#1 unless you have an internal reflex angle https://www.babylonjs-playground.com/#J0VTG5#2 then it becomes much more tricky

A bit closer Babylon.js Playground but all for today.

This one works but a little code optimisation is needed https://www.babylonjs-playground.com/#80179F#1

EDIT Optimised to one loop https://www.babylonjs-playground.com/#80179F#3

@JohnK thank you for devoting the time on this!

Some questions to understand this:

angleDirectionStart/End:
Why take only the y value from the unit vector?
I see that the resulting values are 1, -1, or 0.9999999999999999. What does each value mean? Its a bit hard for me to visualize the direction of an angle.

I can see later that we use this to determine if the corner is reversed(internal reflex angle)?

outerPointStart/End:

outerPointStart = corners[p]
    .add(prevLineNormal.scale(width))
    .add(prevLine.scale(angleDirectionStart * width/Math.tan(angleStart / 2)));

The first add() will move the startPoint towards the normal of the previous line, but what does the next add() do?

This is used only if we have an internal reflex angle right?

The end of the blog arrow is the outerPointEnd, and the black arrow is the new outerPointStart?

29-12_24_22

I could never figure this out on my own. Thanks again.

1 Like

That is its purpose should be 1 or -1, 0.9999999999 is a lack of precision because floating-point needed, close enough.

On mobile so cannot draw a diagram and it is hard to explain without one. Basically for any size corner angle it adds the needed offset parallel to the line to position the outer corner point