Part1 of the idea. Recompute system revolution
* make recompute system nested.
Here's how the new recompute system would work.
1. Document::recompute:
1.1 gathers list of top level objects (typical situation: a spreadsheet, a master sketch, and a few Part containers).
1.2 topological sorts only these objects. Consider all objects, but treat links between objects as dependencies of top-level-object on top-level object
1.3 recompute these objects. As Part::Execute is called, it behaves as a subdocument, and takes care of recomputing all objects it contains. For example, a recompute routine of Body may look like:
Code: Select all
class Body(...):
...
def execute(self, selfobj):
self.recomputeExpressionsionsInSelf() #epsecially, in selfobj.Placement. These expressions should not use any objects contained by Body!, otherwise throw an error
execute_order = TopologicalSort(self.Group, context= self)
removeUntouchedObjects(execute_order)
for obj in execute_order:
obj.recompute()
selfobj.Shape = copy_shape_get_rid_of_placement(selfobj.Tip.Shape)
Code: Select all
class AssemblyConainer(...):
...
def execute(self, selfobj):
self.recomputeExpressionsionsInSelf() #epsecially, in selfobj.Placement. These expressions should not use any objects contained by Assembly!, otherwise throw an error
# it is important that constraint objects don't put up their geometric links as dependencies
# it recomputes contained Parts, instances, ..., and evaluates expressions in assembly constraints. But does not solve the assembly.
execute_order = TopologicalSort(self.Group, context= self)
removeUntouchedObjects(execute_order)
for obj in execute_order:
obj.recompute()
self.solveAssembly()
* scoped recompute becomes easy
(scoped recompute means that when a Part is active, only the objects contained by Part are recomputed, not the whole project.
* tolerance to dependency loops.
(if there is a dependency loop in some Part, the rest of the project will still recompute just fine)
* solves problems with dependencies on assembled pieces
* solves dependency-delated problem of accounting for Part.Placement from within Part itself.
* makes it possible to create brand new kinds of objects.
For example, a container that supports non-DAGness inside, for using it as an iterative process. Or support for a container that would optimize a Part's strength-to-weight ratio by recomputing the internals multiple times.
* possibility to do the Part2 of the idea!
And of course, drawbacks.
* certain cross-dependencies between containers are more restricted.
For example: Body2.Sketch2 links to Body1.Sketch1, and Body1.Sketch3 dependent on Body2.Sketch2. As of now, it will work just fine. With the nested recompute, this is a circular dependency between the bodies.
Part2 of the idea. Coordinate systems
Reimplement PropertyPartShape to account for coordinate system within getShape()/getValue(). PropertyPartShape finds out the transformation by querying Document.getActiveCS, and applies the transform to returned shape implicitly. The getActiveCS is to return the active CS container depending on situation:
* when recomputing, getActiveCS should always retuen the container of the object being recomputed right now.
* in other cases, getActiveCS should return activeContainer's CS.
So, execute of Body needs to be extended a bit:
Code: Select all
class Body(...):
...
def execute(self, selfobj):
selfobj.Document.setRecomputingActiveCS(selfobj) #but it can be done automatically by FreeCAD, implicitly
self.recomputeExpressionsionsInSelf() #epsecially, in selfobj.Placement. These expressions should not use any objects contained by Body!, otherwise throw an error
execute_order = TopologicalSort(self.Group, context= self)
removeUntouchedObjects(execute_order)
for obj in execute_order:
obj.recompute()
selfobj.Shape = copy_shape_get_rid_of_placement(selfobj.Tip.Shape)
selfobj.Document.resetRecomputingActiveCS(selfobj)
Benefits:
* eliminates the need to have separate link class for cross-cs linkage
* gives cross-cs link support for all existing features without needing to modify them
Problems:
* the implementation of getActiveCS requires global variables, which creates obstacles for bringing recompute system into a separate thread.
* does not solve cross-cs links through Instances, does not give immediate support for using instances to all existing features.
As a consequence, Placement property of an object will appear to change, as different containers are activated. Which IMO is quite cool .
I feel like this idea came way too late