[LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

A forum dedicated to the Draft, Arch and BIM workbenches development.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

[LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by paullee »

realthunder wrote: Ping
Reading https://github.com/realthunder/FreeCAD_ ... /wiki/Link how App::LinkExtensionPython Extension is used.

Wondering -

Currently ArchWall is capable to make a simple rectalinear shape wall as well as a BlockWall. For latter case, the file size increase significantly as internally it create a number of 'cut' volume to cut a simple rectilinear volume into blocks. The attached file is about 1MB for 5 segment of walls with blocks. (In BlenderBIM, it seems to be created by an Array Modifier)

Testing the example MyLink, and trying to add to a Part::FeaturePython (not App::FeaturePython) the LinkExtensionPython Extension. I thought ArchWall (a Part::FeaturePython) could in ordinary case produce a simple rectilinear shape volume, but when supplied with a Linked Object (a brick or block), it could produce an Array to create a blockwall.

Seem it does not works that way. Any idea if Link Array feature could be used this way?

Thanks :)



FreeCAD ArchWall MakeBlock
Screenshot from 2021-10-17 02-15-23.png
Screenshot from 2021-10-17 02-15-23.png (205.82 KiB) Viewed 3951 times

OSArch - BlenderBIM
Image
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by paullee »

Test codes to further illustrate the idea - not working as 'imagined' :)

Imagination :
- When there is a Linked Object (supposedly a 'brick/block' in the concept), the Feature Python would do an array and calculate placement of every brick
(just 1 element in below test code)
- When there is no Linked Object (the 'brick/block'), the Feature Python just do a simple Box shape (whatever the actual usecase would needs)
The latter is not successful ( 'fp.Shape = b' below is not working as imagined)

Thanks.

Code: Select all

# refer to https://github.com/realthunder/FreeCAD_assembly3/wiki/Link
class TestLink:
  def __init__(self):
      pass

  def attach(self,obj):
        obj.addProperty("App::PropertyLink","MyLink"," Link",'')
        obj.addProperty("App::PropertyPlacement","Placement"," Link",'')
        obj.addProperty("App::PropertyBool","ShowElement"," Link",'')
        obj.addProperty("App::PropertyInteger","ElementCount"," Link",'')
        obj.addExtension('App::LinkExtensionPython', None)
        self.linkSetup(obj)

  def linkSetup(self,obj):
        assert getattr(obj,'Proxy',None)==self
        self.Object = obj
        obj.configLinkProperty('ShowElement','ElementCount','Placement', LinkedObject='MyLink')

  def onDocumentRestored(self, obj):
        self.linkSetup(obj)

  def execute(self, fp):
      if fp.MyLink:
        return

      elif not fp.MyLink:
        print (" no MyLink, create a default shape")
        b = Part.makeBox(10,10,100)
        fp.Shape = b
              

def makeMyLink(obj):
    # addObject() API is extended to accpet extra parameters in order to 
    link = obj.Document.addObject("Part::FeaturePython",'link',TestLink(),None,True)

    link.setLink(obj)
    return link
Test_ LinkExtensionPython_ 1.FCStd
(5.67 KiB) Downloaded 48 times
Screenshot from 2021-10-17 08-58-23.png
Screenshot from 2021-10-17 08-58-23.png (181.28 KiB) Viewed 3871 times
Screenshot from 2021-10-17 08-58-35.png
Screenshot from 2021-10-17 08-58-35.png (177.92 KiB) Viewed 3871 times
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by realthunder »

With current upstream, using link array for block wall property isn't a good idea. Because each block has a simple geometry. Using link array for rendering saves geometry but requires extra matrix operation for each block during rendering. It will be a good solution once the renderer taps into the power of modern graphics API.

As for the storage issue, there is a simple fix. I've notice this problem for a long time that in Draft/Arch, it tends to call Shape.copy() for whatever reason. Copying shape is not a cheap method, especially when array is involved. OCCT is actually excellent in storage efficiency with its implicit shape sharing. But explicit copy (using Shape.copy()) disables implicit sharing. You ends up with hundreds and thousands of unique brick shape in the file.

Here is a patch to reduce the brick wall storage size. Since you are a Arch/Draft developer, maybe you can raise this concern and try to find out all unnecessary Shape.copy() and replace it with implicit copy Part.Shape(shape).
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by paullee »

Look forward to an enhanced renderer :)

Somehow in 'voxelisation' experiment, used an 'intermediate' object to Shape.copy() all the shapes in a Link to a Folder, then the Link Array to this 'intermediate' object have a much better graphic performance. Better still if a more advanced renderer with modern graphic power is available !


ArchWall BlockWall Model file size reduced from about ~890kB to ~61kB

And tried the ArchWall.py with the proposed change, the file size is reduced significantly to ~61kB! Amazing ! Good to learn to use Part.Shape() instead of Shape.copy() !!!

And checking the code again, it is currently not an array of each individual Block. But rather, each layer is a compound of faces of Block, then extruded individually. Wondering if there is more room to 'compress' if the code Part.Shape(each block), then translate to required placemen...

realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by realthunder »

Compound is OCCT's way to group shape instances, TopoDS_Shape to be precise, which contains a location (TopLoc_Location) and a reference to the actual shape data, which can be shared if there are multiple instances of the same shape at different location. This is as efficient as it can get to store shape array. FreeCAD Placement uses about the same memory space to store as TopLoc_Location. And Link will need a few more extra properties per instance.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by paullee »

Thanks, can do more experiment with the latest information :)
carlopav
Veteran
Posts: 2062
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by carlopav »

realthunder wrote: Mon Oct 18, 2021 2:00 am Compound is OCCT's way to group shape instances, TopoDS_Shape to be precise, which contains a location (TopLoc_Location) and a reference to the actual shape data, which can be shared if there are multiple instances of the same shape at different location. This is as efficient as it can get to store shape array. FreeCAD Placement uses about the same memory space to store as TopLoc_Location. And Link will need a few more extra properties per instance.
Very interesting indeed.
follow my experiments on BIM modelling for architecture design
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by paullee »

yorik wrote: Ping
See if you have a gap to have a look at below patch by @Realthunder, see all right to me with basic python knowledge, I have a simple test and the file reduction seems significant (see above post and model file attached) :D

realthunder wrote: Sun Oct 17, 2021 7:35 am As for the storage issue, there is a simple fix. I've notice this problem for a long time that in Draft/Arch, it tends to call Shape.copy() for whatever reason. Copying shape is not a cheap method, especially when array is involved. OCCT is actually excellent in storage efficiency with its implicit shape sharing. But explicit copy (using Shape.copy()) disables implicit sharing. You ends up with hundreds and thousands of unique brick shape in the file.

Here is a patch to reduce the brick wall storage size. Since you are a Arch/Draft developer, maybe you can raise this concern and try to find out all unnecessary Shape.copy() and replace it with implicit copy Part.Shape(shape).
User avatar
yorik
Founder
Posts: 13640
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by yorik »

Realthunder's fix is amazing! Let's propagate that through Arch & Draft.

As for using linkarrays for blocks, the problem is that many blocks need to be cut at different sizes/angles. So I guess that if we were using linkarrayed objects with the current algo, the overall gain would be small. Also, why? The blocks system of the wall object is just a convenience thing. It will only work well for pretty simple walls. For more complex things, you will likely switch to another workflow and model the blocks yourself, using other tools (arrays, etc), then convert the result to a wall. In that case, you can already use link tools...

What could be useful, though: A switch so if the base object is made of blocks, the wall's "block count" property would reflect the correct number..
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

Re: [LinkExtensionPython] - LinkArray of Blocks in ArchWall ?

Post by paullee »

yorik wrote: Tue Oct 19, 2021 9:25 am Realthunder's fix is amazing! Let's propagate that through Arch & Draft.

As for using linkarrays for blocks, the problem is that many blocks need to be cut at different sizes/angles. So I guess that if we were using linkarrayed objects with the current algo, the overall gain would be small. Also, why? The blocks system of the wall object is just a convenience thing. It will only work well for pretty simple walls. For more complex things, you will likely switch to another workflow and model the blocks yourself, using other tools (arrays, etc), then convert the result to a wall. In that case, you can already use link tools...

What could be useful, though: A switch so if the base object is made of blocks, the wall's "block count" property would reflect the correct number..
Thanks for checking!

@realhunder's approach really make the file much lighter. So, there is no need to experiment the concept of using LinkArray for blocks, other than me trying to learn how LinkExtensionPython works :D


Maybe 1st PR is to @realthunder's fix 8-)
Post Reply