0024722: Move functionality of WOK command wgendoc to OCCT tool gendoc
[occt.git] / dox / user_guides / ocaf_functionmechanism_wp / ocaf_functionmechanism_wp.md
1 OCAF Function Mechanism  {#occt_user_guides__ocaf_functionmechanism_wp}
2 ========================
3
4 @tableofcontents
5
6 @section occt_ocaf_functionmechanism_wp_1 Introduction
7
8   This guide describes the usage of the Function Mechanism of Open CASCADE Application Framework on a simple example.  
9   This example represents a "nail" composed by a cone and two cylinders of different radius and height:  
10
11 @image html ocaf_functionmechanism_wp_image003.png "A nail"
12 @image latex ocaf_functionmechanism_wp_image003.png " A nail"
13
14   These three objects (a cone and two cylinders) are  independent, 
15   but the Function Mechanism makes them connected to each other and representing one object – a nail.  
16   The object "nail" has the following parameters:  
17   
18   * The position of the nail is defined by the apex point of the  cone. 
19    The cylinders are built on the cone and therefore they depend on the position  of the cone. 
20    In this way we define a dependency of the cylinders on the cone.  
21   * The height of the nail is defined by the height of the cone.  
22    Let’s consider that the long cylinder has 3 heights of the cone 
23    and the header cylinder has a half of the height of the cone.  
24   * The radius of the nail is defined by the radius of the cone. 
25   The radius of the long cylinder coincides with this value. 
26   Let’s consider that the  header cylinder has one and a half radiuses of the cone.  
27   
28   So, the cylinders depend on the cone and the cone  parameters define the size of the nail.  
29   
30   It means that re-positioning the cone (changing its  apex point) moves the nail, 
31   the change of the radius of the cone produces a thinner or thicker nail, 
32   and the change of the height of the cone shortens or  prolongates the nail.  
33    It is suggested to examine the programming steps needed to create a 3D parametric model of the "nail".  
34   This guide describes in detail usage of the Function  Mechanism. 
35   Other aspects, such as the data model and the interfaces are mentioned  in brief.  
36
37 @section occt_ocaf_functionmechanism_wp_2 Step 1: Data Tree
38
39   The first step consists in model data allocation in the OCAF tree. 
40   In other words, it is necessary to decide where to put the data.  
41   
42   In this case, the data can be organized into a simple tree 
43   using references for definition of dependent parameters:  
44
45 * Nail
46         * Cone
47                 + Position (x,y,z)
48                 + Radius 
49                 + Height
50         * Cylinder (stem)
51                 + Position = "Cone" position translated for "Cone" height along Z;
52                 + Radius = "Cone" radius;
53                 + Height = "Cone" height multiplied by 3;
54         * Cylinder (head)  
55                 + Position = "Long cylinder" position translated for "Long cylinder" height along Z;
56                 + Radius = "Long cylinder" radius multiplied by 1.5;
57                 + Height = "Cone" height divided by 2. 
58
59   The "nail" object has three sub-leaves in the tree:  the cone and two cylinders.   
60   
61   The cone object is independent.  
62   
63   The long cylinder representing a "stem" of the nail  refers to the corresponding parameters 
64   of the cone to define its own data  (position, radius and height). It means that the long cylinder depends on the  cone.  
65   
66   The parameters of the head cylinder may be expressed  through the cone parameters 
67   only or through the cone and the long cylinder  parameters. 
68   It is suggested to express the position and the radius of the head cylinder 
69   through the position and the radius of the long cylinder, and the height 
70   of the head cylinder through the height of the cone. 
71   It means that the head cylinder depends on the cone and the long cylinder.  
72
73 @section occt_ocaf_functionmechanism_wp_3 Step 2: Interfaces
74
75   The interfaces of the data model are responsible for dynamic creation 
76   of the data tree of the represented at the previous step, data  modification and deletion.  
77   
78   The interface called *INail*  should contain the methods for creation 
79   of the data tree for the nail, setting  and getting of its parameters, computation, visualization and removal.  
80
81 @subsection occt_ocaf_functionmechanism_wp_3_1 Creation of the nail
82
83   This method of the interface creates a data tree for the nail  at a given leaf of OCAF data tree.  
84   
85   It creates three sub-leaves for the cone and two cylinders  and allocates the necessary data (references at the sub-leaves of the long and the  head cylinders).  
86   
87   It sets the default values of position, radius and height of  the nail.  
88   
89   The nail has the following user parameters:  
90   * The position – coincides with the position of the cone  
91   * The radius of the stem part of the nail – coincides with the radius  of the cone  
92   * The height of the nail – a sum of heights of the cone and both  cylinders  
93   
94   The values of the position and the radius of the  nail are defined for the cone object data. 
95   The height of the cone is recomputed  as 2 * heights of nail and divided by 9.  
96
97 @subsection occt_ocaf_functionmechanism_wp_3_2 Computation
98
99   The Function Mechanism is responsible for re-computation of  the nail. 
100   It will be described in detail later in this document.  
101   
102   A data leaf consists of the reference  to the location of the  real data 
103   and a real value defining a coefficient of multiplication of the  referenced data.  
104   
105   For example, the height of the long cylinder is defined as a  reference to the height of the cone 
106   with coefficient 3. The data  leaf of the height of the long cylinder 
107   should contain two attributes: a  reference to the height of cone and a real value equal to 3.  
108
109 @subsection occt_ocaf_functionmechanism_wp_3_3 Visualization
110
111  The shape resulting of the nail function can be displayed using the standard OCAF visualization mechanism.  
112
113 @subsection occt_ocaf_functionmechanism_wp_3_4 Removal of the nail
114
115 To automatically erase the nail from the viewer and the data  tree it is enough to clean the nail leaf from attributes.  
116
117 @section occt_ocaf_functionmechanism_wp_4 Step 3: Functions
118
119   The nail is defined by four functions: the cone, the two cylinders  and the nail function.  
120   The function of the cone is independent. The functions of the cylinders depend on the cone function. 
121   The nail function depends on the  results of all functions:  
122
123 @image html ocaf_functionmechanism_wp_image005.png "Picture 3. A graph of dependencies between functions"
124 @image latex ocaf_functionmechanism_wp_image005.png "Picture 3. A graph of dependencies between functions"
125
126   Computation of the model starts with the cone function, then the long cylinder, 
127   after that the header cylinder and, finally, the result is generated  by the nail function at the end of function chain.  
128
129   The Function Mechanism of Open CASCADE Technology creates this  graph of dependencies 
130   and allows iterating it following the dependencies. 
131   The  only thing the Function Mechanism requires from its user 
132   is the implementation  of pure virtual methods of *TFunction_Driver*:  
133   
134   * <i>\::Arguments()</i> – returns a list of arguments for the  function  
135   * <i>\::Results()</i> – returns a list of results of the function  
136   
137   These methods give the Function Mechanism the information on the location of arguments 
138   and results of the function and allow building a  graph of functions. 
139   The class *TFunction_Iterator* iterates the functions of the graph in the execution order.  
140   
141   The pure virtual method *TFunction_Driver::Execute()* calculating the function should be overridden.  
142   
143   The method <i>\::MustExecute()</i> calls the method <i>\::Arguments()</i>  of the function driver 
144   and ideally this information (knowledge of modification  of arguments of the function) is enough
145   to make a decision whether the function  should be executed or not. Therefore, this method usually shouldn’t be  overridden.  
146
147   The cone and cylinder functions differ only in geometrical construction algorithms. 
148   Other parameters are the same (position, radius and height).  
149   
150   It means that it is possible to create a base class – function driver for the three functions, 
151   and two descendent classes producing:  a cone or a cylinder.  
152   
153   For the base function driver the methods <i>\::Arguments()</i>  and <i>\::Results()</i> will be overridden. 
154   Two descendent function drivers responsible for creation of a cone and a cylinder will override only the method  <i>\::Execute()</i>. 
155   
156   The method <i>\::Arguments()</i> of the function driver of the nail returns the results of the functions located under it in the tree of  leaves.   The method <i>\::Execute()</i> just collects the  results of the functions and makes one shape – a nail. 
157   
158   This way the data model using the Function Mechanism is  ready for usage.   Do not forget to introduce the function drivers for a function  driver table with the help of *TFunction_DriverTable* class.
159
160 @section occt_ocaf_functionmechanism_wp_5 Appendix 1
161
162   This appendix gives an example of the code for iteration and execution of functions.  
163
164 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
165
166     // The scope of functions is  defined.  
167     Handle(TFunction_Scope) scope = TFunction_Scope::Set( anyLabel );  
168      
169     // The information on  modifications in the model is received.  
170     TFunction_Logbook&amp; log = scope-GetLogbook();  
171      
172     // The iterator is iInitialized by  the scope of functions.  
173     TFunction_Iterator iterator( anyLabel );  
174     Iterator.SetUsageOfExecutionOrder( true );  
175      
176     // The function is iterated,  its  dependency is checked on the modified data and  executed if necessary.  
177     for (; iterator.more(); iterator.Next())  
178     {  
179       // The function iterator may return a list of  current functions for execution.  
180       // It might be useful for multi-threaded execution  of functions.  
181       const  TDF_LabelList&amp; currentFunctions = iterator.Current();  
182        
183       //The list of current functions is iterated.  
184       TDF_ListIteratorOfLabelList  currentterator( currentFucntions );  
185       for (;  currentIterator.More(); currentIterator.Next())  
186       {  
187         //  An interface for the function is created.  
188         TFunction_IFunction  interface( currentIterator.Value() );  
189      
190         //  The function driver is retrieved.  
191         Handle(TFunction_Driver)  driver = interface.GetDriver();  
192      
193         //  The dependency of the function on the  modified data is checked.  
194         If  (driver-MustExecute( log ))  
195         {  
196           // The function is executed.  
197           int  ret = driver-Execute( log );  
198           if ( ret ) 
199             return  false;  
200         } // end if check on modification  
201       } // end of iteration of current functions  
202     } // end of iteration of  functions.
203
204 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
205
206 @section occt_ocaf_functionmechanism_wp_6 Appendix 2
207
208   This appendix gives an example of the code for a cylinder function driver.   In order to make the things clearer, the methods <i>\::Arguments()</i>  and <i>\::Results()</i>  from the base class are also mentioned.   
209
210 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
211
212     // A virtual method  ::Arguments() returns a list of arguments of the function.  
213     CylinderDriver::Arguments( TDF_LabelList&amp; args )  
214     {  
215       // The direct arguments, located at sub-leaves of  the fucntion, are collected (see picture 2).  
216       TDF_ChildIterator  cIterator( Label(), false );  
217       for (;  cIterator.More(); cIterator.Next() )  
218       {  
219         // Direct argument.  
220         TDF_Label  sublabel = cIterator.Value();  
221         Args.Append(  sublabel );  
222
223         // The references to the external data are  checked.  
224         Handle(TDF_Reference)  ref;  
225         If (  sublabel.FindAttribute( TDF_Reference::GetID(), ref ) )  
226         {  
227           args.Append(  ref-Get() );  
228         }
229     }
230      
231     // A virtual method ::Results()  returns a list of result leaves.  
232     CylinderDriver::Results( TDF_LabelList&amp; res )  
233     {  
234       // The result is kept at the function  label.  
235       Res.Append(  Label() );  
236     }
237      
238     // Execution of the function  driver.  
239     Int CylinderDriver::Execute( TFunction_Logbook&amp; log )  
240     {  
241       // Position of the cylinder – position of the first  function (cone)   
242       //is  elevated along Z for height values of all  previous functions.  
243       gp_Ax2 axes = …. // out of the scope of this guide.  
244       // The radius value is retrieved.  
245       // It is located at second child sub-leaf (see the  picture 2).  
246       TDF_Label radiusLabel  = Label().FindChild( 2 );  
247        
248       // The multiplicator of the radius ()is retrieved.  
249       Handle(TDataStd_Real)  radiusValue;  
250       radiusLabel.FindAttribute(  TDataStd_Real::GetID(), radiusValue);  
251        
252       // The reference to the radius is retrieved.  
253       Handle(TDF_Reference)  refRadius;  
254       RadiusLabel.FindAttribute(  TDF_Reference::GetID(), refRadius );  
255        
256       // The radius value is calculated.  
257       double radius = 0.0;
258       
259       if (  refRadius.IsNull() )
260       {
261         radius  = radiusValue-Get();  
262       }
263       else  
264       {  
265         // The referenced radius value is  retrieved.   
266         Handle(TDataStd_Real)  referencedRadiusValue;  
267         RefRadius-Get().FindAttribute(TDataStd_Real::GetID()  ,referencedRadiusValue );  
268         radius  = referencedRadiusValue-Get() * radiusValue-Get();  
269       }  
270        
271       // The height value is retrieved.  
272       double height = … // similar code to taking the radius value.  
273        
274       // The cylinder is created.  
275       TopoDS_Shape cylinder  = BRepPrimAPI_MakeCylinder(axes, radius, height);  
276        
277       // The result (cylinder) is set  
278       TNaming_Builder  builder( Label() );  
279       Builder.Generated(  cylinder );  
280        
281       // The modification of the result leaf is saved in  the log.  
282       log.SetImpacted(  Label() );  
283        
284       return 0;
285     }
286 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~