[PR Merged] Moving Windows/Doors

[Moderator : see post https://forum.freecad.org/viewtopic.php?p=660136#p660136 on PR Merged]

Can someone explain why sometimes when I Draft/Arch/Bim Move a Window or Door it becomes disconnected from the opening in its Host wall? The attached file DoorInsertion002.FCStd demonstrates my problem. The door is currently not in the Wall opening, and moving it further along the Wall makes the situation worse. Try it.

The file was extracted from a larger project by copy and paste and for another reason that I don’t understand the Line on which the Wall was built is now distant from the Wall. That is an aberration of the copy and paste as it is correctly positioned in the original. In any case it doesn’t seem to have had any effect on the failure of the Wall opening to move in unison with the Door.

Thanks
DoorInsertion002.FCStd (24.1 KB)

in my opinion it is just as quick to delete a door and create a new one

Ok, create always from scratch can do the job, but it’s a workaround, because as you know moving Doors and Windows should work properly in a BIM WB, and not a nightmare like it is now.

It seems there is a bug here … (the opening go in opposite direction with the Wall object is rotated around Z-axis by 180 deg). Anyone like to fix this ?


Maybe people can suggest workflow in the meantime :slight_smile:

Say, build ArchWall based on DraftLine at correct position, do not move the Wall afterward.

Screenshot from 2022-03-11 00-47-07.png
Screenshot from 2022-03-11 01-00-22.png
Screenshot from 2022-03-11 01-02-42.png
Screenshot from 2022-03-11 01-00-10.png
DoorInsertion002_ r.FCStd (32.1 KB)

The workaround would then be to rotate the wall:

  • Set the workingplane to “Top” with Draft_SelectPlane.
  • Switch on Draft_Snap_Center and Draft_Snap_WorkingPlane.
  • Change the “Move With Host” property of the door to false.
  • Select the wall.
  • Invoke Draft_Rotate.
  • For the center of rotation pick the center of the top face of the wall.
  • For the base angle pick a point with Shift held down to constrain to the X or Y axis.
  • Release Shift.
  • For the rotation angle pick a point on the opposite side of the center of rotation again with Shift held down.
  • Change the “Move With Host” property of the door back to true.

Thank you all for your replies.
I acknowledge that many versions back the whole building of which this wall is just one small part was rotated through 180 degrees, and it would seem that this is the cause of the problem.
From a user perspective I submit that rotation is a pretty fundamental operation that shouldn’t have unintended consequences.
Thank you Roy for your comprehensive step by step workaround. I have a whole building with many walls, some rotated (historically), some not and some containing many features. I hope that someone will take the necessary steps to fix this apparent bug as confused and frustrated users don’t help the aspirations of the developers.

yorik and all the arch programmers did a great job in my opinion. so as not to give the impression that freecad is half finished, i will say that freecad as it is now is very good for commercial use. you should be well trained and know freecad well, then “everything” is possible. easy and fast. I really enjoy working with it.

Trying to understand how the bug is created and digging through ArchWall.py, ArchComponent.py, ArchWindow.py.

Not understand in ArchComponent.py why the object’s attribute Placement seems would be changed by a method itself … :unamused:

                        if not self.isIdentity(placement):
                            obj.Placement = placement
                        else:
                            obj.Placement = p

starting from line 919 of ArchComponent.py

                        p = self.spread(obj,shape,placement).Placement.copy() # for some reason this gets zeroed in next line
                        obj.Shape = self.spread(obj,shape,placement)
                        if not self.isIdentity(placement):
                            obj.Placement = placement
                        else:
                            obj.Placement = p
                    else:
                        if allownosolid:
                            obj.Shape = self.spread(obj,shape,placement)
                            if not self.isIdentity(placement):
                                obj.Placement = placement
                        else:
                            FreeCAD.Console.PrintWarning(obj.Label + " " + translate("Arch","has no solid")+"\n")
                else:
                    if allowinvalid:
                        obj.Shape = self.spread(obj,shape,placement)
                        if not self.isIdentity(placement):
                            obj.Placement = placement

hmm that seems weird indeed :slight_smile: i’ll have a better look

I was experimenting with ArchComponent.py a month ago in relation to some other issues (structure, pipe, computeAreas). A project I have put on the side-burner for now (because it’s quite complex in general). But my experimental version of the code does solve the OP’s issue. I’ll try to dissect the relevant bits later.
ArchComponent.py (95.4 KB)

That’s inspiring :slight_smile:

Have no idea about shape.transformShape(), but it looks ‘similar’. Can you enlighten if this change fix the OP problem and what is the difference ?

Thanks.

                        if inv_matrix:
                            add.transformShape(inv_matrix)

As already mentioned: Yes.


In some cases a copied shape will have a Placement that is not the same as its original. Manipulations based on the Placement will then lead to faulty results. Using transformShape instead avoids this. But I have yet to check if this is the case here.

Thanks for the explanation :slight_smile:


This may be same / similar problem (2018) as previously reported ?

Arch Window create Wrong Opening Position Bug?

It seems the order of inversing placement needs to take in account of the Window’s placement, and below rectify the problem?

                            #subvolume.Placement = subvolume.Placement.multiply(placement)
                            subPl = FreeCAD.Placement()

                            print (" subvolume placement is ", subPl)
                            subPl = subPl.multiply(placement)  # inverse placement of Wall object

                            print (" subvolume placement is ", subPl)
                            subPl = subPl.multiply(subvolume.Placement) # placementof Window (Opening) object

                            print (" subvolume placement is ", subPl)
                            subvolume.Placement = subPl

ArchComponent.py (96.7 KB)
DoorInsertion002_ r2.FCStd (36.2 KB)
Screenshot from 2022-03-13 02-19-50.png

And seems it fix the problem 3 4 years ago (2018) ? :smiley:

Before
Screenshot from 2022-03-13 02-24-00.png
After
Screenshot from 2022-03-13 02-23-47.png

Just try to compare if there is any significant difference in time, seems both 5000 routine spend about somthing slightly more than 5s.

w=Gui.Selection.getSelection()[0] # window
wl=Gui.Selection.getSelection()[0] # wall

for i in range(0,5000):
  ws=w.Proxy.getSubVolume(w)
  wlpi=FreeCAD.Placement().multiply(wl.Placement.inverse()).multiply(w.Placement)
  ws.Placement=wlpi



for i in range(0,5000):
  ws=w.Proxy.getSubVolume(w)
  inv_matrix = wl.Placement.Matrix.inverse()
  ws.transformShape(inv_matrix)

Hmmm, for some reason, the inverse_matrix method is not working ?

ArchComponent.py (97.2 KB)
Test_ Arch Door Opening_ 3_ Sketch_ Wall Offseted.fcstd (14.6 KB)
Test_ ArchSketch_ 49_ Window-Placement_r.FCStd (35.6 KB)
Screenshot from 2022-03-14 01-56-59.png
Screenshot from 2022-03-14 01-57-17.png
Screenshot from 2022-03-14 02-19-01.png
Screenshot from 2022-03-14 02-18-48.png

On line 721 you have:

placement = placement.inverse()

On line 729 you have:

inv_matrix = placement.Matrix.inverse()

In other words you are applying the inversion twice.

This code works.

It can be reduced to this line:

                            subvolume.Placement = placement.multiply(subvolume.Placement)

If you compare it to the original code (line 786) there is only a subtle difference:

                            subvolume.Placement = subvolume.Placement.multiply(placement)

I have to admit that I do not understand this difference.

Note that the .Placement.multiply(placement) structure occurs elsewhere in the file. I suppose it would have to be changed there as well?

Thanks. I understand the multiplication of placement is not ‘commutative’ in mathematics sense - so multiplication needs to be in the particular order of successive placement manipulation.


And further examining other Additions / Subtraction cases, and the bug seems exist. It can be shown that only Window object (getSubVolume) works correctly.

Test_ ArchSketch_ 49_ Window-Placement_r2.FCStd (63.9 KB)
Screenshot from 2022-03-15 01-34-18.png
Screenshot from 2022-03-15 01-34-10.png
Screenshot from 2022-03-15 01-34-21.png