0028079: Proofreading of updates section and possible documentation changes since 7.0
[occt.git] / dox / user_guides / ocaf / ocaf.md
CommitLineData
ba06f8bb 1OCAF {#occt_user_guides__ocaf}
72b7576f 2========================
3
e5bd0d98 4@tableofcontents
5
72b7576f 6@section occt_ocaf_1 Introduction
7
8This manual explains how to use the Open CASCADE Application Framework (OCAF).
9It provides basic documentation on using OCAF. For advanced information on OCAF
e2ba9cb1 10and its applications, see our <a href="http://www.opencascade.com/content/tutorial-learning">E-learning & Training</a> offerings.
72b7576f 11
27245ff9 12@subsection occt_ocaf_1_1 Purpose of OCAF
72b7576f 13
27245ff9 14OCAF (the Open CASCADE Application Framework) is an easy-to-use platform for rapidly developing
15 sophisticated domain-specific design applications.
16 A typical application developed using OCAF deals with two or three-dimensional (2D or 3D) geometric modeling
17 in trade-specific Computer Aided Design (CAD) systems, manufacturing or analysis applications,
18 simulation applications or illustration tools.
19
20 Developing a design application requires addressing many technical aspects.
21 In particular, given the functional specification of your application, you must at least:
3f812249 22
23 * Design the architecture of the application— definition of the software components and the way they cooperate;
27245ff9 24 * Define the data model able to support the functionality required — a design application operates on data maintained during the whole end-user working session;
25 * Structure the software in order to:
26 * synchronize the display with the data — commands modifying objects must update the views;
27 * support generalized undo-redo commands — this feature has to be taken into account very early in the design process;
28 * Implement the function for saving the data — if the application has a long life cycle, the compatibility of data between versions of the application has to be addressed;
29 * Build the application user interface.
30
31Architectural guidance and ready-to-use solutions provided by OCAF offer you the following benefits:
32 * You can concentrate on the functionality specific for your application;
33 * The underlying mechanisms required to support the application are already provided;
34 * The application can be rapidly be prototyped thanks to the coupling the other Open CASCADE Technology modules;
35 * The final application can be developed by industrializing the prototype — you don't need to restart the development from scratch.
36 * The Open Source nature of the platform guarantees the long-term usefulness of your development.
72b7576f 37
3f812249 38OCAF is much more than just one toolkit among many in the CAS.CADE Object Libraries. Since it can handle any data and algorithms in these libraries -- be it modeling algorithms, topology or geometry -- OCAF is their logical supplement.
72b7576f 39
40The table below contrasts the design of a modeling application using object libraries alone and using OCAF.
41
42**Table 1: Services provided by OCAF**
43
44|Development tasks |Comments | Without OCAF | With OCAF |
45|------------------:|---------:|---------------:|-----------:|
46|Creation of geometry| Algorithm Calling the modeling libraries | To be created by the user | To be created by the user|
47| Data organization | Including specific attributes and modeling process | To be created by the user | Simplified|
48| Saving data in a file | Notion of document | To be created by the user | Provided |
49| Document-view management | | To be created by the user | Provided |
50| Application infrastructure | New, Open, Close, Save and Save As File menus | To be created by the user | Provided |
51| Undo-Redo | Robust, multi-level | To be created by the user | Provided |
52| Application-specific dialog boxes | | To be created by the user | To be created by the user |
53
27245ff9 54OCAF uses other modules of Open CASCADE Technology — the Shape is implemented with the geometry supported by the <a href="#user_guides__modeling_data">Modeling Data</a> module and the viewer is the one provided with the <a href="#user_guides__visualization">Visualization</a> module. Modeling functions can be implemented using the <a href="#user_guides__modeling_algos">Modeling Algorithms</a> module.
72b7576f 55
56The relationship between OCAF and the Open CASCADE Technology (**OCCT**) Object Libraries can be seen in the image below.
57
27245ff9 58@figure{/user_guides/ocaf/images/ocaf_image003.svg, "OCCT Architecture"}
72b7576f 59
60In the image, the OCAF (Open CASCADE Application Framework) is shown with black rectangles and OCCT Object Libraries required by OCAF are shown with white rectangles.
27245ff9 61
72b7576f 62The subsequent chapters of this document explain the concepts and show how to use the services of OCAF.
63
27245ff9 64@subsection occt_ocaf_1_2 Architecture Overview
72b7576f 65
27245ff9 66OCAF provides you with an object-oriented Application-Document-Attribute model consisting of C++ class libraries.
72b7576f 67
67d7f07f 68@image html ocaf_wp_image003.png "The Application-Document-Attribute model"
69@image latex ocaf_wp_image003.png "The Application-Document-Attribute model"
72b7576f 70
27245ff9 71@subsubsection occt_ocaf_1_2_1 Application
72b7576f 72
27245ff9 73The *Application* is an abstract class in charge of handling documents during the working session, namely:
74 * Creating new documents;
75 * Saving documents and opening them;
76 * Initializing document views.
77
78@subsubsection occt_ocaf_1_2_2 Document
79
80 The document, implemented by the concrete class *Document*, is the container for the application data. Documents offer access to the data framework and serve the following purposes:
72b7576f 81
27245ff9 82 * Manage the notification of changes
83 * Update external links
84 * Manage the saving and restoring of data
85 * Store the names of software extensions.
86 * Manage command transactions
87 * Manage Undo and Redo options.
88
89 Each document is saved in a single flat ASCII file defined by its format and extension (a ready-to-use format is provided with OCAF).
72b7576f 90
27245ff9 91 Apart from their role as a container of application data, documents can refer to each other; Document A, for example, can refer to a specific label in Document B. This functionality is made possible by means of the reference key.
92
93@subsubsection occt_ocaf_1_2_3 Attribute
72b7576f 94
27245ff9 95 Application data is described by **Attributes**, which are instances of classes derived from the *Attribute* abstract class, organized according to the OCAF Data Framework.
96
67d7f07f 97 The @ref occt_ocaf_3 "OCAF Data Framework" references aggregations of attributes using persistent identifiers in a single hierarchy. A wide range of attributes come with OCAF, including:
27245ff9 98
67d7f07f 99 * @ref occt_ocaf_6 "Standard attributes" allow operating with simple common data in the data framework (for example: integer, real, string, array kinds of data), realize auxiliary functions (for example: tag sources attribute for the children of the label counter), create dependencies (for example: reference, tree node)....;
100 * @ref occt_ocaf_5 "Shape attributes" contain the geometry of the whole model or its elements including reference to the shapes and tracking of shape evolution;
27245ff9 101 * Other geometric attributes such as **Datums** (points, axis and plane) and **Constraints** (*tangent-to, at-a-given-distance, from-a-given-angle, concentric,* etc.)
102 * User attributes, that is, attributes typed by the application
67d7f07f 103 * @ref occt_ocaf_7 "Visualization attributes" allow placing viewer information to the data framework, visual representation of objects and other auxiliary visual information, which is needed for graphical data representation.
104 * @ref occt_ocaf_8 "Function services" — the purpose of these attributes is to rebuild objects after they have been modified (parameterization of models). While the document manages the notification of changes, a function manages propagation of these changes. The function mechanism provides links between functions and calls to various algorithms.
27245ff9 105
106In addition, application-specific data can be added by defining new attribute classes; naturally, this changes the standard file format. The only functions that have to be implemented are:
107 * Copying the attribute
d3013f55 108 * Converting it from and persistent data storage
27245ff9 109
110@subsection occt_ocaf_1_3 Reference-key model
111
112 In most existing geometric modeling systems, the data are topology driven.
113 They usually use a boundary representation (BRep), where geometric models
114 are defined by a collection of faces, edges and vertices,
115 to which application data are attached. Examples of data include:
116
117 * a color;
118 * a material;
119 * information that a particular edge is blended.
120
121 When the geometric model is parameterized, that is, when you can change
122 the value of parameters used to build the model (the radius of a blend, the thickness of a rib, etc.),
123 the geometry is highly subject to change.
124 In order to maintain the attachment of application data, the geometry must be distinguished from other data.
125
126 In OCAF, the data are reference-key driven. It is a uniform model in which reference-keys
127 are the persistent identification of data. All **accessible** data, including the geometry,
128 are implemented as attributes attached to reference-keys.
129 The geometry becomes the value of the Shape attribute, just as a number is the value
130 of the Integer and Real attributes and a string that of the Name attribute.
131
132 On a single reference-key, many attributes can be aggregated;
133 the application can ask at runtime which attributes are available.
134 For example, to associate a texture to a face in a geometric model,
135 both the face and the texture are attached to the same reference-key.
136
137@image html ocaf_image004.png "Topology driven versus reference-key driven approaches"
138@image latex ocaf_image004.png "Topology driven versus reference-key driven approaches"
72b7576f 139
27245ff9 140 Reference-keys can be created in two ways:
141
142 * At programming time, by the application
143 * At runtime, by the end-user of the application (providing that you include this capability in the application)
144
145 As an application developer, you generate reference-keys in order to give semantics to the data.
146 For example, a function building a prism may create three reference-keys:
147 one for the base of the prism, a second for the lateral faces and a third for the top face.
148 This makes up a semantic built-in the application's prism feature.
149 On the other hand, in a command allowing the end-user to set a texture to a face he/she selects,
150 you must create a reference-key to the selected face
151 if it has not previously been referenced in any feature
152 (as in the case of one of the lateral faces of the prism).
153
154 When you create a reference-key to selected topological elements (faces, edges or vertices),
155 OCAF attaches to the reference-key information defining the selected topology — the Naming attribute.
156 For example, it may be the faces to which a selected edge is common to.
157 This information, as well as information about the evolution of the topology at each modeling step
158 (the modified, updated and deleted faces), is used by the naming algorithm to maintain the topology
159 attached to the reference-key. As such, on a parametrized model,
160 after modifying the value of a parameter, the reference-keys still address the appropriate faces,
161 even if their geometry has changed.
67d7f07f 162 Consequently, you change the size of the cube shown in the figure above,
27245ff9 163 the user texture stay attached to the right face.
164
165 <b>Note</b> As Topological naming is based on the reference-key and attributes such as Naming
166 (selection information) and Shape (topology evolution information),
167 OCAF is not coupled to the underlying modeling libraries.
168 The only modeling services required by OCAF are the following:
169
170 * Each algorithm must provide information about the evolution of the topology
171 (the list of faces modified, updated and deleted by the algorithm)
172 * Exploration of the geometric model must be available
173 (a 3D model is made of faces bounded by close wires,
174 themselves composed by a sequence of edges connected by their vertices)
175
176 Currently, OCAF uses the Open CASCADE Technology modeling libraries.
177
178 To design an OCAF-based data model, the application developer is encouraged to aggregate
179 ready-to-use attributes instead of defining new attributes by inheriting from an abstract root class.
180 There are two major advantages in using aggregation rather than inheritance:
181
182 * As you don't implement data by defining new classes, the format of saved data
183 provided with OCAF doesn't change; so you don't have to write the Save and Open functions
184 * The application can query the data at runtime if a particular attribute is available
185
186**Summary**
187
188 * OCAF is based on a uniform reference-key model in which:
189 * Reference-keys provide persistent identification of data;
190 * Data, including geometry, are implemented as attributes attached to reference-keys;
191 * Topological naming maintains the selected geometry attached to reference-keys in parametrized models;
192 * In many applications, the data format provided with OCAF doesn't need to be extended;
193 * OCAF is not coupled to the underlying modeling libraries.
194
195
196@section occt_ocaf_3 The Data Framework
197
198@subsection occt_ocaf_3_1 Data Structure
199
200 The OCAF Data Framework is the Open CASCADE Technology realization
201 of the reference-key model in a tree structure. It offers a single environment where data from different application components can be handled. This allows exchanging and modifying data simply, consistently, with a maximum level of information and stable semantics.
202
72b7576f 203
27245ff9 204The building blocks of this approach are:
72b7576f 205
27245ff9 206 * The tag
207 * The label
208 * The attribute
72b7576f 209
27245ff9 210As it has been mentioned earlier, the first label in a framework is the root label of the tree. Each label has a tag expressed as an integer value, and a label is uniquely defined by an entry expressed as a list of tags from the root, 0:1:2:1, for example.
72b7576f 211
27245ff9 212Each label can have a list of attributes, which contain data, and several attributes can be attached to a label. Each attribute is identified by a GUID, and although a label may have several attributes attached to it, it must not have more than one attribute of a single GUID.
72b7576f 213
27245ff9 214The sub-labels of a label are called its children. Conversely, each label, which is not the root, has a father. Brother labels cannot share the same tag.
215
216The most important property is that a label’s entry is its persistent address in the data framework.
72b7576f 217
dba69de2 218@image html /user_guides/ocaf/images/ocaf_image005.png "A simple framework model"
219@image latex /user_guides/ocaf/images/ocaf_image005.png "A simple framework model"
72b7576f 220
27245ff9 221In this image the circles contain tags of the corresponding labels. The lists of tags are located under the circles. The root label always has a zero tag.
72b7576f 222
223The children of a root label are middle-level labels with tags 1 and 3. These labels are brothers.
224
dba69de2 225List of tags of the right-bottom label is "0:3:4": this label has tag 4, its father (with entry "0:3") has tag 3, father of father has tag 0 (the root label always has "0" entry).
72b7576f 226
27245ff9 227@subsection occt_ocaf_3_2 Examples of a Data Structure
228
229Let's have a look at the example:
230
231@image html ocaf_wp_image007.png "The coffee machine"
232@image latex ocaf_wp_image007.png "The coffee machine"
233
234 In the image the application for designing coffee machines first allocates
235 a label for the machine unit. It then adds sub-labels for the main features
236 (glass coffee pot, water receptacle and filter) which it refines as needed
237 (handle and reservoir of the coffee pot and spout of the reservoir).
238
239 You now attach technical data describing the handle — its geometry and color —
240 and the reservoir — its geometry and material.
241 Later on, you can modify the handle's geometry without changing its color —
242 both remain attached to the same label.
243
244@image html ocaf_wp_image005.png "The data structure of the coffee machine"
245@image latex ocaf_wp_image005.png "The data structure of the coffee machine"
246
247 The nesting of labels is key to OCAF. This allows a label to have its own structure
248 with its local addressing scheme which can be reused in a more complex structure.
249 Take, for example, the coffee machine. Given that the coffee pot's handle has a label of tag [1],
250 the entry for the handle in the context of the coffee pot only (without the machine unit) is [0:1:1].
251 If you now model a coffee machine with two coffee pots, one at the label [1],
252 the second at the label [4] in the machine unit,
253 the handle of the first pot would have the entry [0:1:1:1]
254 whereas the handle of the second pot would be [0:1:4:1].
255 This way, we avoid any confusion between coffee pot handles.
256
257Another example is the application for designing table lamps. The first label is allocated to the lamp unit.
258
259@image html /user_guides/ocaf/images/ocaf_image006.png
260@image latex /user_guides/ocaf/images/ocaf_image006.png
261
262The root label cannot have brother labels. Consequently, various lamps in the framework allocation correspond to the sub-labels of the root label. This allows avoiding any confusion between table lamps in the data framework. Different lamp parts have different material, color and other attributes, so a child label of the lamp with the specified tags is allocated for each sub-unit of the lamp:
72b7576f 263
264 * a lamp-shade label with tag 1
265 * a bulb label with tag 2
266 * a stem label with tag 3
267
3f812249 268Label tags are chosen at will. They are only identifiers of the lamp parts. Now you can refine all units: by setting geometry, color, material and other information about the lamp or its parts to the specified label. This information is placed into special attributes of the label: the pure label contains no data -- it is only a key to access data.
72b7576f 269
27245ff9 270Remember that tags are private addresses without any meaning outside the data framework. It would, for instance, be an error to use part names as tags. These might change or be removed from production in next versions of the application, whereas the exact form of that part might be reused in your design, the part name could be integrated into the framework as an attribute.
72b7576f 271
272So, after the user changes the lamp design, only corresponding attributes are changed, but the label structure is maintained. The lamp shape must be recreated by new attribute values and attributes of the lamp shape must refer to a new shape.
273
dba69de2 274@image html /user_guides/ocaf/images/ocaf_image007.png
275@image latex /user_guides/ocaf/images/ocaf_image007.png
72b7576f 276
277
278The previous figure shows the table-lamps document structure: each child of the root label contains a lamp shape attribute and refers to the sub-labels, which contain some design information about corresponding sub-units.
279
280The data framework structure allows to create more complex structures: each lamp label sub-label may have children labels with more detailed information about parts of the table lamp and its components.
281
282Note that the root label can have attributes too, usually global attributes: the name of the document, for example.
283
27245ff9 284@subsection occt_ocaf_3_3 Tag
72b7576f 285
286A tag is an integer, which identifies a label in two ways:
287
288 * Relative identification
289 * Absolute identification.
290
291In relative identification, a label’s tag has a meaning relative to the father label only. For a specific label, you might, for example, have four child labels identified by the tags 2, 7, 18, 100. In using relative identification, you ensure that you have a safe scope for setting attributes.
292
dba69de2 293In absolute identification, a label’s place in the data framework is specified unambiguously by a colon-separated list of tags of all the labels from the one in question to the root of the data framework. This list is called an entry. *TDF_Tool::TagList* allows retrieving the entry for a specific label.
72b7576f 294
3f812249 295In both relative and absolute identification, it is important to remember that the value of an integer has no intrinsic semantics whatsoever. In other words, the natural sequence that integers suggest, i.e. 0, 1, 2, 3, 4 ... -- has no importance here. The integer value of a tag is simply a key.
72b7576f 296
297The tag can be created in two ways:
298
299 * Random delivery
300 * User-defined delivery
301
302As the names suggest, in random delivery, the tag value is generated by the system in a random manner. In user-defined delivery, you assign it by passing the tag as an argument to a method.
303
27245ff9 304@subsubsection occt_ocaf_3_3_1 Creating child labels using random delivery of tags
72b7576f 305
dba69de2 306To append and return a new child label, you use *TDF_TagSource::NewChild*. In the example below, the argument *level2*, which is passed to *NewChild,* is a *TDF_Label*.
307
72b7576f 308
72b7576f 309~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
310TDF_Label child1 = TDF_TagSource::NewChild (level2);
311TDF_Label child2 = TDF_TagSource::NewChild (level2);
312~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
313
27245ff9 314@subsubsection occt_ocaf_3_3_2 Creation of a child label by user delivery from a tag
72b7576f 315
316The other way to create a child label from a tag is by user delivery. In other words, you specify the tag, which you want your child label to have.
317
dba69de2 318To retrieve a child label from a tag which you have specified yourself, you need to use *TDF_Label::FindChild* and *TDF_Label::Tag* as in the example below. Here, the integer 3 designates the tag of the label you are interested in, and the Boolean false is the value for the argument *create*. When this argument is set to *false*, no new child label is created.
319
72b7576f 320
72b7576f 321~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322TDF_Label achild = root.FindChild(3,Standard_False);
323if (!achild.IsNull()) {
324Standard_Integer tag = achild.Tag();
325}
326~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
327
27245ff9 328@subsection occt_ocaf_3_4 Label
72b7576f 329
3f812249 330The tag gives a persistent address to a label. The label -- the semantics of the tag -- is a place in the data framework where attributes, which contain data, are attached. The data framework is, in fact, a tree of labels with a root as the ultimate father label.
72b7576f 331
332Label can not be deleted from the data framework, so, the structure of the data framework that has been created can not be removed while the document is opened. Hence any kind of reference to an existing label will be actual while an application is working with the document.
333
27245ff9 334@subsubsection occt_ocaf_3_4_1 Label creation
72b7576f 335
dba69de2 336Labels can be created on any labels, compared with brother labels and retrieved. You can also find their depth in the data framework (depth of the root label is 0, depth of child labels of the root is 1 and so on), whether they have children or not, relative placement of labels, data framework of this label. The class *TDF_Label* offers the above services.
72b7576f 337
27245ff9 338@subsubsection occt_ocaf_3_4_2 Creating child labels
72b7576f 339
dba69de2 340To create a new child label in the data framework using explicit delivery of tags, use *TDF_Label::FindChild*.
341
72b7576f 342
72b7576f 343~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
344//creating a label with tag 10 at Root
345TDF_Label lab1 = aDF->Root().FindChild(10);
346
347//creating labels 7 and 2 on label 10
348TDF_Label lab2 = lab1.FindChild(7);
349
350TDF_Label lab3 = lab1.FindChild(2);
351~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 352You could also use the same syntax but add the Boolean *true* as a value of the argument **create**. This ensures that a new child label will be created if none is found. Note that in the previous syntax, this was also the case since **create** is *true* by default.
353
72b7576f 354
72b7576f 355~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
356TDF_Label level1 = root.FindChild(3,Standard_True);
357TDF_Label level2 = level1.FindChild(1,Standard_True);
358~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 359@subsubsection occt_ocaf_3_4_3 Retrieving child labels
72b7576f 360
361You can retrieve child labels of your current label by iteration on the first level in the scope of this label.
362
dba69de2 363
72b7576f 364~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
365TDF_Label current;
366//
367for (TDF_ChildIterator it1 (current,Standard_False); it1.More(); it1.Next()) {
368achild = it1.Value();
369//
370// do something on a child (level 1)
371//
372}
373~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374You can also retrieve all child labels in every descendant generation of your current label by iteration on all levels in the scope of this label.
375~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
376for (TDF_ChildIterator itall (current,Standard_True); itall.More(); itall.Next()) {
377achild = itall.Value();
378//
379// do something on a child (all levels)
380//
381}
382~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 383Using *TDF_Tool::Entry* with *TDF_ChildIterator* you can retrieve the entries of your current label’s child labels as well.
72b7576f 384
dba69de2 385
72b7576f 386~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
387void DumpChildren(const TDF_Label& aLabel)
388{
389 TDF_ChildIterator it;
390 TCollection_AsciiString es;
391 for (it.Initialize(aLabel,Standard_True); it.More(); it.Next()){
392 TDF_Tool::Entry(it.Value(),es);
4ee1bdf4 393 cout << as.ToCString() << endl;
72b7576f 394 }
395}
396~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 397@subsubsection occt_ocaf_3_4_4 Retrieving the father label
72b7576f 398
399Retrieving the father label of a current label.
400
dba69de2 401
72b7576f 402~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
403TDF_Label father = achild.Father();
404isroot = father.IsRoot();
405~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 406
407@subsection occt_ocaf_3_5 Attribute
72b7576f 408
3f812249 409The label itself contains no data. All data of any type whatsoever -- application or non-application -- is contained in attributes. These are attached to labels, and there are different types for different types of data. OCAF provides many ready-to-use standard attributes such as integer, real, constraint, axis and plane. There are also attributes for topological naming, functions and visualization. Each type of attribute is identified by a GUID.
72b7576f 410
dba69de2 411The advantage of OCAF is that all of the above attribute types are handled in the same way. Whatever the attribute type is, you can create new instances of them, retrieve them, attach them to and remove them from labels, "forget" and "remember" the attributes of a particular label.
72b7576f 412
27245ff9 413@subsubsection occt_ocaf_3_5_1 Retrieving an attribute from a label
72b7576f 414
dba69de2 415To retrieve an attribute from a label, you use *TDF_Label::FindAttribute*. In the example below, the GUID for integer attributes, and *INT*, a handle to an attribute are passed as arguments to *FindAttribute* for the current label.
416
72b7576f 417
72b7576f 418~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
419if(current.FindAttribute(TDataStd_Integer::GetID(),INT))
420{
421 // the attribute is found
422}
423else
424{
425 // the attribute is not found
426}
427~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 428@subsubsection occt_ocaf_3_5_2 Identifying an attribute using a GUID
72b7576f 429
dba69de2 430You can create a new instance of an attribute and retrieve its GUID. In the example below, a new integer attribute is created, and its GUID is passed to the variable *guid* by the method ID inherited from *TDF_Attribute*.
431
72b7576f 432
72b7576f 433~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
434Handle(TDataStd_Integer) INT = new TDataStd_Integer();
435Standard_GUID guid = INT->ID();
436~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 437
27245ff9 438@subsubsection occt_ocaf_3_5_3 Attaching an attribute to a label
72b7576f 439
dba69de2 440To attach an attribute to a label, you use *TDF_Label::Add*. Repetition of this syntax raises an error message because there is already an attribute with the same GUID attached to the current label.
441
442*TDF_Attribute::Label* for *INT* then returns the label *attach* to which *INT* is attached.
72b7576f 443
72b7576f 444
72b7576f 445~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
446current.Add (INT); // INT is now attached to current
447current.Add (INT); // causes failure
448TDF_Label attach = INT->Label();
449~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 450@subsubsection occt_ocaf_3_5_4 Testing the attachment to a label
72b7576f 451
dba69de2 452You can test whether an attribute is attached to a label or not by using *TDF_Attribute::IsA* with the GUID of the attribute as an argument. In the example below, you test whether the current label has an integer attribute, and then, if that is so, how many attributes are attached to it. *TDataStd_Integer::GetID* provides the GUID argument needed by the method IsAttribute.
453
454*TDF_Attribute::HasAttribute* tests whether there is an attached attribute, and *TDF_Tool::NbAttributes* returns the number of attributes attached to the label in question, e.g. *current*.
72b7576f 455
72b7576f 456
72b7576f 457~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
458// Testing of attribute attachment
459//
460if (current.IsA(TDataStd_Integer::GetID())) {
461// the label has an Integer attribute attached
462}
463if (current.HasAttribute()) {
464// the label has at least one attribute attached
465Standard_Integer nbatt = current.NbAttributes();
466// the label has nbatt attributes attached
467}
468~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 469@subsubsection occt_ocaf_3_5_5 Removing an attribute from a label
72b7576f 470
dba69de2 471To remove an attribute from a label, you use *TDF_Label::Forget* with the GUID of the deleted attribute. To remove all attributes of a label, *TDF_Label::ForgetAll*.
472
72b7576f 473
72b7576f 474~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
475current.Forget(TDataStd_Integer::GetID());
476// integer attribute is now not attached to current label
477current.ForgetAll();
478// current has now 0 attributes attached
479~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27245ff9 480@subsubsection occt_ocaf_3_5_6 Specific attribute creation
72b7576f 481
dba69de2 482If the set of existing and ready to use attributes implementing standard data types does not cover the needs of a specific data presentation task, the user can build his own data type and the corresponding new specific attribute implementing this new data type.
72b7576f 483
dba69de2 484There are two ways to implement a new data type: create a new attribute (standard approach), or use the notion of User Attribute by means of a combination of standard attributes (alternative way)
72b7576f 485
d3013f55 486In order to create a new attribute in the standard way, create a class inherited from *TDF_Attribute* and implement all purely virtual and necessary virtual methods:
487* **ID()** -- returns a unique GUID of a given attribute
488* **Restore(attribute)** -- sets fields of this attribute equal to the fields of a given attribute of the same type
489* **Paste(attribute, relocation_table)** -- sets fields of a given attribute equal to the field values of this attribute ; if the attribute has references to some objects of the data framework and relocation_table has this element, then the given attribute must also refer to this object .
490* **NewEmpty()** -- returns a new attribute of this class with empty fields
491* **Dump(stream)** -- outputs information about a given attribute to a given stream debug (usually outputs an attribute of type string only)
72b7576f 492
dba69de2 493Methods *NewEmpty, Restore* and *Paste* are used for the common transactions mechanism (Undo/Redo commands). If you don’t need this attribute to react to undo/redo commands, you can write only stubs of these methods, else you must call the Backup method of the *TDF_Attribute* class every time attribute fields are changed.
72b7576f 494
d3013f55 495To enable possibility to save / restore the new attribute in XML format, do the following:
dba69de2 496 1. Create a new package with the name Xml[package name] (for example *XmlMyAttributePackage*) containing class *XmlMyAttributePackage_MyAttributeDriver*. The new class inherits *XmlMDF_ADriver* class and contains the translation functionality: from transient to persistent and vice versa (see the realization of the standard attributes in the packages *XmlMDataStd*, for example). Add package method AddDrivers which adds your class to a driver table (see below).
497 2. Create a new package (or do it in the current one) with two package methods:
e2b55410 498 * *Factory*, which loads the document storage and retrieval drivers; and
499 * *AttributeDrivers*, which calls the methods AddDrivers for all packages responsible for persistence of the document.
dba69de2 500 3. Create a plug-in implemented as an executable (see example *XmlPlugin*). It calls a macro PLUGIN with the package name where you implemented the method Factory.
d3013f55 501
502To enable possibility to save / restore the new attribute in binary format, do the following:
e2b55410 503 1. Create a new package with name <i> Bin[package name] </i> (for example *BinMyAttributePackage*) containing a class *BinMyAttributePackage_MyAttributeDriver*. The new class inherits *BinMDF_ADriver* class and contains the translation functionality: from transient to persistent and vice versa (see the realization of the standard attributes in the packages *BinMDataStd*, for example). Add package method *AddDrivers*, which adds your class to a driver table.
dba69de2 504 2. Create a new package (or do it in the current one) with two package methods:
505 * Factory, which loads the document storage and retrieval drivers; and
506 * AttributeDrivers, which calls the methods AddDrivers for all packages responsible for persistence of the document.
507 3. Create a plug-in implemented as an executable (see example *BinPlugin*). It calls a macro PLUGIN with the package name where you implemented the method Factory.
67d7f07f 508See @ref occt_ocaf_4_3_3 "Saving the document" and @ref occt_ocaf_4_3_4 "Opening the document from a file" for the description of document save/open mechanisms.
72b7576f 509
dba69de2 510If you decided to use the alternative way (create a new attribute by means of *UAttribute* and a combination of other standard attributes), do the following:
511 1. Set a *TDataStd_UAttribute* with a unique GUID attached to a label. This attribute defines the semantics of the data type (identifies the data type).
512 2. Create child labels and allocate all necessary data through standard attributes at the child labels.
513 3. Define an interface class for access to the data of the child labels.
72b7576f 514
dba69de2 515Choosing the alternative way of implementation of new data types allows to forget about creating persistence classes for your new data type. Standard persistence classes will be used instead. Besides, this way allows separating the data and the methods for access to the data (interfaces). It can be used for rapid development in all cases when requirements to application performance are not very high.
72b7576f 516
dba69de2 517Let’s study the implementation of the same data type in both ways by the example of transformation represented by *gp_Trsf* class. The class *gp_Trsf* defines the transformation according to the type (*gp_TrsfForm*) and a set of parameters of the particular type of transformation (two points or a vector for translation, an axis and an angle for rotation, and so on).
72b7576f 518
67d7f07f 5191. The first way: creation of a new attribute. The implementation of the transformation by creation of a new attribute is represented in the @ref occt_ocaf_11 "Samples".
72b7576f 520
5212. The second way: creation of a new data type by means of combination of standard attributes. Depending on the type of transformation it may be kept in data framework by different standard attributes. For example, a translation is defined by two points. Therefore the data tree for translation looks like this:
e2b55410 522 * Type of transformation <i>(gp_Translation)</i> as *TDataStd_Integer*;
523 * First point as *TDataStd_RealArray* (three values: X1, Y1 and Z1);
524 * Second point as *TDataStd_RealArray* (three values: X2, Y2 and Z2).
72b7576f 525
dba69de2 526@image html /user_guides/ocaf/images/ocaf_image010.png "Data tree for translation"
527@image latex /user_guides/ocaf/images/ocaf_image010.png "Data tree for translation"
72b7576f 528
529If the type of transformation is changed to rotation, the data tree looks like this:
e2b55410 530 * Type of transformation <i>(gp_Rotation)</i> as *TDataStd_Integer*;
531 * Point of axis of rotation as *TDataStd_RealArray* (three values: X, Y and Z);
532 * Axis of rotation as *TDataStd_RealArray* (three values: DX, DY and DZ);
533 * Angle of rotation as *TDataStd_Real*.
72b7576f 534
dba69de2 535@image html /user_guides/ocaf/images/ocaf_image011.png "Data tree for rotation"
536@image latex /user_guides/ocaf/images/ocaf_image011.png "Data tree for rotation"
72b7576f 537
e2b55410 538The attribute *TDataStd_UAttribute* with the chosen unique GUID identifies the data type. The interface class initialized by the label of this attribute allows access to the data container (type of transformation and the data of transformation according to the type).
27245ff9 539
540@subsection occt_ocaf_3_6 Compound documents
541
542 As the identification of data is persistent, one document can reference data contained in another document,
543 the referencing and referenced documents being saved in two separate files.
544
545 Lets look at the coffee machine application again. The coffee pot can be placed in one document.
546 The coffee machine document then includes an *occurrence* — a positioned copy — of the coffee pot.
547 This occurrence is defined by an XLink attribute (the external Link)
548 which references the coffee pot of the first document
549 (the XLink contains the relative path of the coffee pot document and the entry of the coffee pot data [0:1] ).
550
551@image html ocaf_wp_image006.png "The coffee machine compound document"
552@image latex ocaf_wp_image006.png "The coffee machine compound document"
553
554 In this context, the end-user of the coffee machine application can open the coffee pot document,
555 modify the geometry of, for example, the reservoir, and overwrite the document without worrying
556 about the impact of the modification in the coffee machine document.
557 To deal with this situation, OCAF provides a service which allows the application to check
558 whether a document is up-to-date. This service is based on a modification counter included in each document:
559 when an external link is created, a copy of the referenced document counter is associated to the XLink
560 in the referencing document. Providing that each modification of the referenced document increments its own counter,
561 we can detect that the referencing document has to be updated by comparing the two counters
562 (an update function importing the data referenced by an XLink into the referencing document is also provided).
563
564 @subsection occt_ocaf_3_7 Transaction mechanism
565
566 The Data Framework also provides a transaction mechanism inspired from database management systems:
567 the data are modified within a transaction which is terminated either by a Commit
568 if the modifications are validated or by an Abort if the modifications are abandoned —
569 the data are then restored to the state it was in prior to the transaction.
570 This mechanism is extremely useful for:
571
572 * Securing editing operations (if an error occurs, the transaction is abandoned and the structure retains its integrity)
573 * Simplifying the implementation of the **Cancel** function (when the end-user begins a command,
574 the application may launch a transaction and operate directly in the data structure;
575 abandoning the action causes the transaction to Abort)
576 * Executing **Undo** (at commit time, the modifications are recorded in order to be able to restore the data to their previous state)
577
578 The transaction mechanism simply manages a backup copy of attributes.
579 During a transaction, attributes are copied before their first modification.
580 If the transaction is validated, the copy is destroyed.
581 If the transaction is abandoned, the attribute is restored to its initial value
582 (when attributes are added or deleted, the operation is simply reversed).
583
584 Transactions are document-centered, that is, the application starts a transaction on a document.
585 So, modifying a referenced document and updating one of its referencing documents requires
586 two transactions, even if both operations are done in the same working session.
72b7576f 587
588
589@section occt_ocaf_4_ Standard Document Services
590
591@subsection occt_ocaf_4_1 Overview
592
593Standard documents offer ready-to-use documents containing a TDF-based data framework. Each document can contain only one framework.
594
6fe96f84 595The documents themselves are contained in the instantiation of a class *TDocStd_Application* (or its descendant). This application manages the creation, storage and retrieval of documents.
72b7576f 596
597You can implement undo and redo in your document, and refer from the data framework of one document to that of another one. This is done by means of external link attributes, which store the path and the entry of external links.
598
599To sum up, standard documents alone provide access to the data framework. They also allow you to:
600
601 * Update external links
602 * Manage the saving and opening of data
603 * Manage the undo/redo functionality.
604
605
606@subsection occt_ocaf_4_2 The Application
607
6fe96f84 608As a container for your data framework, you need a document, and your document must be contained in your application. This application will be a class *TDocStd_Application* or a class inheriting from it.
72b7576f 609
610@subsubsection occt_ocaf_4_2_1 Creating an application
611
612To create an application, use the following syntax.
613
72b7576f 614~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
6fe96f84 615Handle(TDocStd_Application) app = new TDocStd_Application ();
72b7576f 616~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72b7576f 617
618@subsubsection occt_ocaf_4_2_2 Creating a new document
619
dba69de2 620To the application which you declared in the previous example (4.2.1), you must add the document *doc* as an argument of *TDocStd_Application::NewDocument*.
72b7576f 621
72b7576f 622~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
623Handle(TDocStd_Document) doc;
624app->NewDocument("NewDocumentFormat", doc);
625~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 626
6fe96f84 627Here "NewDocumentFormat" is identifier of the format of your document.
80223385 628OCCT defines several standard formats, distinguishing by a set of supported OCAF attributes, and method of encoding (e.g. binary data or XML), described below.
6fe96f84 629If your application defines specific OCAF attributes, you need to define your own format for it.
630
72b7576f 631@subsubsection occt_ocaf_4_2_3 Retrieving the application to which the document belongs
632
633To retrieve the application containing your document, you use the syntax below.
634
72b7576f 635~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
6fe96f84 636app = Handle(TDocStd_Application)::DownCast (doc->Application());
72b7576f 637~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
638@subsection occt_ocaf_4_3 The Document
639
640The document contains your data framework, and allows you to retrieve this framework, recover its main label, save it in a file, and open or close this file.
641
642@subsubsection occt_ocaf_4_3_1 Accessing the main label of the framework
643
dba69de2 644To access the main label in the data framework, you use *TDocStd_Document::Main* as in the example below. The main label is the first child of the root label in the data framework, and has the entry 0:1.
72b7576f 645
72b7576f 646~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
647TDF_Label label = doc->Main();
648~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
649@subsubsection occt_ocaf_4_3_2 Retrieving the document from a label in its framework
650
4ee1bdf4 651To retrieve the document from a label in its data framework, you use *TDocStd_Document::Get* as in the example below. The argument *label* passed to this method is an instantiation of *TDF_Label*.
72b7576f 652~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
653doc = TDocStd_Document::Get(label);
654~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 655
6fe96f84 656@subsubsection occt_ocaf_4_3_format Defining storage format
72b7576f 657
80223385 658OCAF uses a customizable mechanism for storage of the documents.
6fe96f84 659In order to use OCAF persistence to save and read your documents to / from the file, you need to define one or several formats in your application.
72b7576f 660
6fe96f84 661For that, use method TDocStd_Application::DefineFormat(), for instance:
662~~~~~
663app->DefineFormat ("NewDocumentFormat", "New format for OCAF documents", "ndf",
664 new NewDocumentFormat_RetrievalDriver(),
665 new NewDocumentFormat_StorageDriver());
666~~~~~
72b7576f 667
80223385 668This example defines format "NewDocumentFormat" with a default file extension "ndf", and instantiates drivers for reading and storing documents from and to that format.
669Either of the drivers can be null, in this case the corresponding action will not be supported for that format.
6fe96f84 670
671OCAF provides several standard formats, each covering some set of OCAF attributes:
672
673<table>
674<tr><th>Format</th><th>Persistent toolkit</th><th>OCAF attributes covered</th></tr>
675<tr><td colspan=3>Legacy formats (read only)</td></tr>
676<tr><td>OCC-StdLite </td><td> TKStdL </td><td> TKLCAF </td></tr>
677<tr><td>MDTV-Standard </td><td> TKStd </td><td> TKLCAF + TKCAF </td></tr>
678<tr><td colspan=3>Binary formats</td></tr>
679<tr><td>BinLOcaf </td><td> TKBinL </td><td> TKLCAF </td></tr>
680<tr><td>BinOcaf </td><td> TKBin </td><td> TKLCAF + TKCAF </td></tr>
681<tr><td>BinXCAF </td><td> TKBinXCAF </td><td> TKLCAF + TKCAF + TKXCAF </td></tr>
682<tr><td>TObjBin </td><td> TKBinTObj </td><td> TKLCAF + TKTObj </td></tr>
683<tr><td colspan=3>XML formats</td></tr>
684<tr><td>XmlLOcaf </td><td> TKXmlL </td><td> TKLCAF </td></tr>
685<tr><td>XmlOcaf </td><td> TKXml </td><td> TKLCAF + TKCAF </td></tr>
686<tr><td>XmlXCAF </td><td> TKXmlXCAF </td><td> TKLCAF + TKCAF + TKXCAF </td></tr>
687<tr><td>TObjXml </td><td> TKXmlTObj </td><td> TKLCAF + TKTObj </td></tr>
688</table>
689
80223385 690For convenience, these toolkits provide static methods *DefineFormat()* accepting handle to application.
6fe96f84 691These methods allow defining corresponding formats easily, e.g.:
692
693~~~~~
694BinDrivers::DefineFormat (app); // define format "BinOcaf"
72b7576f 695~~~~~
6fe96f84 696
80223385 697Use these toolkits as an example for implementation of persistence drivers for custom attributes, or new persistence formats.
6fe96f84 698
699The application can define several storage formats.
80223385 700On save, the format specified in the document (see *TDocStd_Document::StorageFormat()*) will be used (save will fail if that format is not defined in the application).
701On reading, the format identifier stored in the file is used and recorded in the document.
6fe96f84 702
703@subsubsection occt_ocaf_4_3_plugins Defining storage format by resource files
704
80223385 705The alternative method to define formats is via usage of resource files.
706This method was used in earlier versions of OCCT and is considered as deprecated since version 7.1.0.
6fe96f84 707This method allows loading persistence drivers on demand, using plugin mechanism.
708
80223385 709To use this method, create your own application class inheriting from *TDocStd_Application*, and override method *ResourcesName()*.
710That method should return a string with a name of resource file, e.g. "NewDocumentFormat", which will contain a description of the format.
6fe96f84 711
80223385 712Then create that resource file and define the parameters of your format:
6fe96f84 713
714~~~~~
715ndf.FileFormat: NewDocumentFormat
716NewDocumentFormat.Description: New Document Format Version 1.0
72b7576f 717NewDocumentFormat.FileExtension: ndf
6fe96f84 718NewDocumentFormat.StoragePlugin: bb5aa176-c65c-4c84-862e-6b7c1fe16921
719NewDocumentFormat.RetrievalPlugin: 76fb4c04-ea9a-46aa-88a2-25f6a228d902
72b7576f 720~~~~~
721
80223385 722The GUIDs should be unique and correspond to the GUIDs supported by relevant plugin.
723You can use an existing plugins (see the table above) or create your own.
72b7576f 724
80223385 725Finally, make a copy of the resource file "Plugin" from *$CASROOT/src/StdResource* and, if necessary, add the definition of your plugin in it, for instance:
6fe96f84 726
727~~~~~
728bb5aa176-c65c-4c84-862e-6b7c1fe16921.Location: TKNewFormat
72976fb4c04-ea9a-46aa-88a2-25f6a228d902.Location: TKNewFormat
730~~~~~
731
732In order to have these resource files loaded during the program execution, it is necessary to set two environment variables: *CSF_PluginDefaults* and *CSF_NewFormatDefaults*.
733For example, set the files in the directory *MyApplicationPath/MyResources*:
72b7576f 734
735~~~~~
736setenv CSF_PluginDefaults MyApplicationPath/MyResources
737setenv CSF_NewFormatDefaults MyApplicationPath/MyResources
738~~~~~
739
6fe96f84 740@subsubsection occt_ocaf_4_3_3 Saving a document
741
80223385 742To save the document, make sure that its parameter *StorageFormat()* corresponds to one of the formats defined in the application, and use method *TDocStd_Application::SaveAs*, for instance:
6fe96f84 743
744~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
745app->SaveAs(doc, "/tmp/example.caf");
746~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72b7576f 747
748@subsubsection occt_ocaf_4_3_4 Opening the document from a file
749
e2b55410 750To open the document from a file where it has been previously saved, you can use *TDocStd_Application::Open* as in the example below. The arguments are the path of the file and the document saved in this file.
72b7576f 751
72b7576f 752~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
753app->Open("/tmp/example.caf", doc);
754~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
755
e2b55410 756@subsubsection occt_ocaf_4_3_5 Cutting, copying and pasting inside a document
757
758To cut, copy and paste inside a document, use the class *TDF_CopyLabel*.
759
760In fact, you must define a *Label*, which contains the temporary value of a cut or
761copy operation (say, in <i> Lab_Clipboard</i>). You must also define two other labels:
762
763* The data container (e.g. <i> Lab_source</i>)
764* The destination of the copy (e.g. <i> Lab_ Target</i> )
765
766~~~~
767 Copy = copy (Lab_Source => Lab_Clipboard)
768 Cut = copy + Lab_Source.ForgetAll() // command clear the contents of LabelSource.
769 Paste = copy (Lab_Clipboard => Lab_target)
770~~~~
771
772So we need a tool to copy all (or a part) of the content of a label and its sub-label,
773to another place defined by a label.
774
775~~~~
776 TDF_CopyLabel aCopy;
777 TDF_IDFilter aFilter (Standard_False);
778
779 //Don't copy TDataStd_TreeNode attribute
780
781 aFilter.Ignore(TDataStd_TreeNode::GetDefaultTreeID());
782 aCopy.Load(aSource, aTarget); aCopy.UseFilter(aFilter); aCopy.Perform();
783
784 // copy the data structure to clipboard
785
786 return aCopy.IsDone(); }
787~~~~
788
789The filter is used to forbid copying a specified type of attribute.
790
791You can also have a look at the class *TDF_Closure*, which can be useful to determine the dependencies of the part you want to cut from the document.
792
72b7576f 793@subsection occt_ocaf_4_4 External Links
794
dba69de2 795External links refer from one document to another. They allow you to update the copy of data framework later on.
72b7576f 796
dba69de2 797@image html /user_guides/ocaf/images/ocaf_image012.png "External links between documents"
798@image latex /user_guides/ocaf/images/ocaf_image012.png "External links between documents"
72b7576f 799
800Note that documents can be copied with or without a possibility of updating an external link.
801
802@subsubsection occt_ocaf_4_4_1 Copying the document
803
dba69de2 804#### With the possibility of updating it later
72b7576f 805
e2b55410 806To copy a document with a possibility of updating it later, you use *TDocStd_XLinkTool::CopyWithLink*.
72b7576f 807
72b7576f 808~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
809Handle(TDocStd_Document) doc1;
810Handle(TDocStd_Document) doc2;
811
812TDF_Label source = doc1->GetData()->Root();
813TDF_Label target = doc2->GetData()->Root();
814TDocStd_XLinkTool XLinkTool;
815
816XLinkTool.CopyWithLink(target,source);
817~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
818
819Now the target document has a copy of the source document. The copy also has a link in order to update the content of the copy if the original changes.
820
e2b55410 821In the example below, something has changed in the source document. As a result, you need to update the copy in the target document. This copy is passed to *TDocStd_XLinkTool::UpdateLink* as the argument *target*.
72b7576f 822
72b7576f 823~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
824XLinkTool.UpdateLink(target);
825~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
826
dba69de2 827#### Without any link between the copy and the original
72b7576f 828
3f812249 829You can also create a copy of the document with no link between the original and the copy. The syntax to use this option is *TDocStd_XLinkTool::Copy*. The copied document is again represented by the argument *target*, and the original -- by *source.*
72b7576f 830
72b7576f 831~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
832XLinkTool.Copy(target, source);
833
834~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
835
836
27245ff9 837@section occt_ocaf_5 OCAF Shape Attributes
72b7576f 838@subsection occt_ocaf_5_1 Overview
839
e2b55410 840A topological attribute can be seen as a hook into the topological structure. It is possible to attach data to define references to it.
841
842OCAF shape attributes are used for topology objects and their evolution access. All topological objects are stored in one *TNaming_UsedShapes* attribute at the root label of the data framework. This attribute contains a map with all topological shapes used in a given document.
72b7576f 843
e2b55410 844The user can add the *TNaming_NamedShape* attribute to other labels. This attribute contains references (hooks) to shapes from the *TNaming_UsedShapes* attribute and an evolution of these shapes. The *TNaming_NamedShape* attribute contains a set of pairs of hooks: to the *Old* shape and to a *New* shape (see the following figure). It allows not only to get the topological shapes by the labels, but also to trace the evolution of the shapes and to correctly update dependent shapes by the changed one.
72b7576f 845
846If a shape is newly created, then the old shape of a corresponding named shape is an empty shape. If a shape is deleted, then the new shape in this named shape is empty.
847
dba69de2 848@image html /user_guides/ocaf/images/ocaf_image013.png
849@image latex /user_guides/ocaf/images/ocaf_image013.png
72b7576f 850
a7372ed5 851@subsection occt_ocaf_5_2 Shape attributes in data framework.
e2b55410 852
72b7576f 853Different algorithms may dispose sub-shapes of the result shape at the individual labels depending on whether it is necessary to do so:
854
855* If a sub-shape must have some extra attributes (material of each face or color of each edge). In this case a specific sub-shape is placed to a separate label (usually to a sub-label of the result shape label) with all attributes of this sub-shape.
856* If the topological naming algorithm is needed, a necessary and sufficient set of sub-shapes is placed to child labels of the result shape label. As usual, for a basic solid and closed shells, all faces of the shape are disposed.
857
e2b55410 858*TNaming_NamedShape* may contain a few pairs of hooks with the same evolution. In this case the topology shape, which belongs to the named shape is a compound of new shapes.
72b7576f 859
e2b55410 860Consider the following example. Two boxes (solids) are fused into one solid (the result one). Initially each box was placed to the result label as a named shape, which has evolution PRIMITIVE and refers to the corresponding shape of the *TNaming_UsedShapes* map. The box result label has a material attribute and six child labels containing named shapes of Box faces.
72b7576f 861
dba69de2 862@image html /user_guides/ocaf/images/ocaf_image014.png "Resulting box"
863@image latex /user_guides/ocaf/images/ocaf_image014.png "Resulting box"
72b7576f 864
3f812249 865After the fuse operation a modified result is placed to a separate label as a named shape, which refers to the old shape (one of the boxes) and to the new shape resulting from the fuse operation, and has evolution MODIFY (see the following figure).
72b7576f 866
3f812249 867Named shapes, which contain information about modified faces, belong to the fuse result sub-labels:
868* sub-label with tag 1 -- modified faces from box 1,
869* sub-label with tag 2 -- modified faces from box 2.
72b7576f 870
dba69de2 871@image html /user_guides/ocaf/images/ocaf_image015.png
872@image latex /user_guides/ocaf/images/ocaf_image015.png
72b7576f 873
874This is necessary and sufficient information for the functionality of the right naming mechanism: any sub-shape of the result can be identified unambiguously by name type and set of labels, which contain named shapes:
875
e2b55410 876 * face F1’ as a modification of face F11
877 * face F1’’ as generation of face F12
72b7576f 878 * edges as an intersection of two contiguous faces
879 * vertices as an intersection of three contiguous faces
880
881After any modification of source boxes the application must automatically rebuild the naming entities: recompute the named shapes of the boxes (solids and faces) and fuse the resulting named shapes (solids and faces) that reference to the new named shapes.
882
a7372ed5 883@subsection occt_ocaf_5_3 Registering shapes and their evolution
72b7576f 884
885When using TNaming_NamedShape to create attributes, the following fields of an attribute are filled:
886
dba69de2 887* A list of shapes called the "old" and the "new" shapes A new shape is recomputed as the value of the named shape. The meaning of this pair depends on the type of evolution.
e2b55410 888* The type of evolution, which is a term of the *TNaming_Evolution* enumeration used for the selected shapes that are placed to the separate label:
3f812249 889 * PRIMITIVE -- newly created topology, with no previous history;
890 * GENERATED -- as usual, this evolution of a named shape means, that the new shape is created from a low-level old shape ( a prism face from an edge, for example );
891 * MODIFY -- the new shape is a modified old shape;
892 * DELETE -- the new shape is empty; the named shape with this evolution just indicates that the old shape topology is deleted from the model;
893 * SELECTED -- a named shape with this evolution has no effect on the history of the topology.
72b7576f 894
895Only pairs of shapes with equal evolution can be stored in one named shape.
896
a7372ed5 897@subsection occt_ocaf_5_4 Using naming resources
72b7576f 898
a7372ed5 899The class *TNaming_Builder* allows creating a named shape attribute. It has a label of a future attribute as an argument of the constructor. Respective methods are used for the evolution and setting of shape pairs. If for the same TNaming_Builder object a lot of pairs of shapes with the same evolution are given, then these pairs would be placed in the resulting named shape. After the creation of a new object of the TNaming_Builder class, an empty named shape is created at the given label.
72b7576f 900
72b7576f 901~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
dba69de2 902// a new empty named shape is created at "label"
72b7576f 903TNaming_Builder builder(label);
904// set a pair of shapes with evolution GENERATED
905builder.Generated(oldshape1,newshape1);
906// set another pair of shapes with the same evolution
907builder.Generated(oldshape2,newshape2);
3f812249 908// get the result - TNaming_NamedShape attribute
72b7576f 909Handle(TNaming_NamedShape) ns = builder.NamedShape();
910~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a7372ed5 911
912@subsection occt_ocaf_5_5 Reading the contents of a named shape attribute
72b7576f 913
e2b55410 914You can use the method <i>TNaming_NamedShape::Evolution()</i> to get the evolution of this named shape and the method <i>TNaming_NamedShape::Get()</i> to get a compound of new shapes of all pairs of this named shape.
dba69de2 915
72b7576f 916More detailed information about the contents of the named shape or about the modification history of a topology can be obtained with the following:
e2b55410 917* *TNaming_Tool* provides a common high-level functionality for access to the named shapes contents:
918 * The method <i>GetShape(Handle(TNaming_NamedShape)) </i> returns a compound of new shapes of the given named shape;
919 * The method <i>CurrentShape(Handle(TNaming_NamedShape))</i> returns a compound of the shapes, which are latest versions of the shapes from the given named shape;
3f812249 920 * The method <i>NamedShape(TopoDS_Shape,TDF_Label) </i> returns a named shape, which contains a given shape as a new shape. A given label is any label from the data framework -- it just gives access to it.
e2b55410 921* *TNaming_Iterator* gives access to the named shape and hooks pairs.
72b7576f 922
72b7576f 923~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
924// create an iterator for a named shape
925TNaming_Iterator iter(namedshape);
926// iterate while some pairs are not iterated
927while(iter.More()) {
928// get the new shape from the current pair
929TopoDS_Shape newshape = iter.NewShape();
930// get the old shape from the current pair
931TopoDS_Shape oldshape = iter.OldShape();
932// do something...
933
934// go to the next pair
935iter.Next();
936}
937~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
938
939
a7372ed5 940@subsection occt_ocaf_5_6 Topological naming
941
942The Topological Naming mechanism is based on 3 components:
943* History of the used modeling operation algorithm;
944* Registering of the built result in Data Framework (i.e. loading the necessary elements of the extracted history in OCAF document);
945* Selection / Recomputation of a "selected" sub-shape of the algorithm result.
946
947To get the expected result the work of the three components should be synchronized and the rules of each component should be respected.
948
949@subsubsection occt_ocaf_5_6_1 Algorithm history
950
951The "correct" history of a used modeling operation serves the basis of naming mechanism. It should be provided by the algorithm supporting the operation. The history content depends on the type of the topological result. The purpose of the history is to provide all entities for consistent and correct work of the Selection / Recomputation mechanism. The table below presents expected types of entities depending on the result type.
952
953| Result type | Type of sub-shapes to be returned by history of algorithm | Comments |
954| :---------- | :-------------------------------------------------------- | :------- |
955| Solid or closed shell | Faces | All faces |
956| Open shell or single face | Faces and edges of opened boundaries only | All faces plus all edges of opened boundaries |
957| Closed wire | Edges | All edges |
958| Opened wire | Edges and ending vertexes | All edges plus ending vertexes of the wire |
959| Edge | Vertexes | Two vertexes are expected |
960| Compound or CompSolid | To be used consequentially the above declared rule applied to all sub-shapes of the first level | Compound/CompSolid to be explored level by level until any the mentioned above types will be met |
961
962The history should return (and track) only elementary types of sub-shapes, i.e. Faces, Edges and Vertexes, while other so-called aggregation types: Compounds, Shells, Wires, are calculated by Selection mechanism automatically.
72b7576f 963
3f812249 964There are some simple exceptions for several cases. For example, if the Result contains a seam edge -- in conical, cylindrical or spherical surfaces -- this seam edge should be tracked by the history and in addition should be defined before the types. All degenerated entities should be filtered and excluded from consideration.
72b7576f 965
a7372ed5 966@subsubsection occt_ocaf_5_6_2 Loading history in data framework
72b7576f 967
a7372ed5 968All elements returned by the used algorithm according to the aforementioned rules should be put in the Data Framework (or OCAF document in other words) consequently in linear order under the so-called **Result Label**.
72b7576f 969
a7372ed5 970The "Result Label" is *TDF_label* used to keep the algorithm result *Shape* from *TopoDS* in *NamedShape* attribute. During loading sub-shapes of the result in Data Framework should be used the rules of chapter @ref occt_ocaf_5_3. These rules are also applicable for loading the main shape, i.e. the resulting shape produced by the modeling algorithm.
72b7576f 971
a7372ed5 972@subsubsection occt_ocaf_5_6_3 Selection / re-computation mechanism
973
974When the Data Framework is filled with all impacted entities (including the data structures resulting from the current modeling operation and the data structures resulting from the previous modeling operations, on which the current operation depends) any sub-shape of the current result can be **selected**, i.e. the corresponding new naming data structures, which support this functionality, can be produced and kept in the Data Framework.
975
976One of the user interfaces for topological naming is the class *TNaming_Selector*. It implements the above mentioned sub-shape "selection" functionality as an additional one. I.e. it can be used for:
3f812249 977* Storing the selected shape on a label -- its **Selection**;
978* Accessing the named shape -- check the kept value of the shape
979* Update of this naming -- recomputation of an earlier selected shape.
a7372ed5 980
981The selector places a new named shape with evolution **SELECTED** to the given label. The selector creates a **name** of the selected shape, which is a unique description (data structure) of how to find the selected topology using as resources:
982* the given context shape, i.e. the main shape kept on **Result Label**, which contains a selected sub-shape,
983* its evolution and
984* naming structure.
985
986After any modification of a context shape and update of the corresponding naming structure, it is necessary to call method *TNaming_Selector::Solve*. If the naming structure, i.e. the above mentioned **name**, is correct, the selector automatically updates the selected sub-shape in the corresponding named shape, else it fails.
987
988@subsection occt_ocaf_5_7 Exploring shape evolution
72b7576f 989
e2b55410 990The class *TNaming_Tool* provides a toolkit to read current data contained in the attribute.
72b7576f 991
e2b55410 992If you need to create a topological attribute for existing data, use the method *NamedShape*.
72b7576f 993
72b7576f 994~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
995class MyPkg_MyClass
996{
997public: Standard_Boolean SameEdge (const Handle(CafTest_Line)& L1, const Handle(CafTest_Line)& L2);
998};
999
1000Standard_Boolean CafTest_MyClass::SameEdge (const Handle(CafTest_Line)& L1, const Handle(CafTest_Line)& L2)
1001{
1002 Handle(TNaming_NamedShape) NS1 = L1->NamedShape();
1003 Handle(TNaming_NamedShape) NS2 = L2->NamedShape();
1004 return BRepTools::Compare(NS1,NS2);
1005}
1006~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1007
a7372ed5 1008
1009@subsection occt_ocaf_5_8 Example of topological naming usage
1010
1011**Topological naming** is a mechanism of Open CASCADE aimed to keep reference to the selected shape. If, for example, we select a vertex of a solid shape and “ask” the topological naming to keep reference to this vertex, it will refer to the vertex whatever happens with the shape (translations, scaling, fusion with another shape, etc.).
1012
1013Let us consider an example: imagine a wooden plate. The job is to drive several nails in it:
1014
1015@figure{/user_guides/ocaf/images/ocaf_image020.png, "A nail driven in a wooden plate"}
1016
1017There may be several nails with different size and position. A **Hammer** should push each **Nail** exactly in the center point of the top surface. For this the user does the following:
1018* Makes several Nails of different height and diameter (according to the need),
1019* Chooses (selects) the upper surface of each Nail for the Hammer.
1020
3f812249 1021The job is done. The application should do the rest -- the Hammer calculates a center point for each selected surface of the Nail and “strikes” each Nail driving it into the wooden plate.
a7372ed5 1022
1023What happens if the user changes the position of some Nails? How will the Hammer know about it? It keeps reference to the surface of each Nail. However, if a Nail is relocated, the Hammer should know the new position of the selected surface. Otherwise, it will “strike” at the old position (keep the fingers away!)…
1024
1025Topological naming mechanism should help the Hammer to obtain the relocated surfaces. The Hammer “asks” the mechanism to “resolve” the selected shapes by calling method *TNaming_Selection::Solve()* and the mechanism “returns” the modified surfaces located at the new position by calling *TNaming_Selector::NamedShape()*.
1026
1027The topological naming is represented as a “black box” in the example above. Now it is time to make the box a little more “transparent”.
1028
1029The application contains 3 functions:
3f812249 1030* **Nail** -- produces a shape representing a nail,
1031* **Translator** -- translates a shape along the wooden plate,
1032* **Hammer** -- drives the nail in the wooden plate.
a7372ed5 1033
1034Each function gives the topological naming some hints how to “re-solve” the selected sub-shapes:
1035* The Nail constructs a solid shape and puts each face of the shape into sub-labels:
1036
1037@figure{/user_guides/ocaf/images/ocaf_image021.png, "Distribution of faces through sub-labels of the Nail"}
1038
3f812249 1039* The **Translator** moves a shape and registers modification for each face: it puts a pair: “old” shape -- “new” shape at a sub-label of each moving Nail. The “old” shape represents a face of the Nail at the initial position. The “new” shape -- is the same face, but at a new position:
a7372ed5 1040
1041@figure{/user_guides/ocaf/images/ocaf_image022.png, "Registration of relocation of faces of a Nail"}
1042
1043How does it work?
1044* The Hammer selects a face of a Nail calling *TNaming_Selector::Select()*. This call makes a unique name for the selected shape. In our example, it will be a direct reference to the label of the top face of the Nail (Face 1).
3f812249 1045* When the user moves a Nail along the wooden plate, the Translator registers this modification by putting the pairs: “old” face of the Nail -- new face of the Nail into its sub-labels.
a7372ed5 1046* When the Hammer calls *TNaming::Solve()*, the topological naming “looks” at the unique name of the selected shape and tries to re-solve it:
3f812249 1047 * It finds the 1st appearance of the selected shape in the data tree -- it is a label under the Nail function *Face 1*.
1048 * It follows the evolution of this face. In our case, there is only one evolution -- the translation: *Face 1* (top face) -- <i>Face 1’</i> (relocated top face). So, the last evolution is the relocated top face.
1049* Calling the method *TNaming_Selector::NamedShape()* the Hammer obtains the last evolution of the selected face -- the relocated top face.
a7372ed5 1050
1051The job is done.
1052
3f812249 1053P.S. Let us say a few words about a little more complicated case -- selection of a wire of the top face. Its topological name is an “intersection” of two faces. We remember that the **Nail** puts only faces under its label. So, the selected wire will represent an “intersection” of the top face and the conic face keeping the “head” of the nail. Another example is a selected vertex. Its unique name may be represented as an “intersection” of three or even more faces (depends on the shape).
a7372ed5 1054
1055
27245ff9 1056@section occt_ocaf_6 Standard Attributes
72b7576f 1057
1058@subsection occt_ocaf_6_1 Overview
1059
e2b55410 1060Standard attributes are ready-to-use attributes, which allow creating and modifying attributes for many basic data types. They are available in the packages *TDataStd, TDataXtd* and *TDF*. Each attribute belongs to one of four types:
72b7576f 1061
e2b55410 1062 * Geometric attributes;
1063 * General attributes;
1064 * Relationship attributes;
1065 * Auxiliary attributes.
27245ff9 1066
1067
72b7576f 1068
dba69de2 1069### Geometric attributes
1070
3f812249 1071 * **Axis** -- simply identifies, that the concerned *TNaming_NamedShape* attribute with an axis shape inside belongs to the same label;
1072 * **Constraint** -- contains information about a constraint between geometries: used geometry attributes, type, value (if exists), plane (if exists), "is reversed", "is inverted" and "is verified" flags;
1073 * **Geometry** -- simply identifies, that the concerned *TNaming_NamedShape* attribute with a specified-type geometry belongs to the same label;
1074 * **Plane** -- simply identifies, that the concerned *TNaming_NamedShape* attribute with a plane shape inside belongs to the same label;
1075 * **Point** -- simply identifies, that the concerned *TNaming_NamedShape* attribute with a point shape inside belongs to the same label;
1076 * **Shape** -- simply identifies, that the concerned *TNaming_NamedShape* attribute belongs to the same label;
1077 * **PatternStd** -- identifies one of five available pattern models (linear, circular, rectangular, circular rectangular and mirror);
1078 * **Position** -- identifies the position in 3d global space.
72b7576f 1079
dba69de2 1080### General attributes
1081
3f812249 1082 * **AsciiString** -- contains AsciiString value;
1083 * **BooleanArray** -- contains an array of Boolean;
1084 * **BooleanList** -- contains a list of Boolean;
1085 * **ByteArray** -- contains an array of Byte (unsigned char) values;
1086 * **Comment** -- contains a string -- the comment for a given label (or attribute);
1087 * **Expression** -- contains an expression string and a list of used variables attributes;
1088 * **ExtStringArray** -- contains an array of *ExtendedString* values;
1089 * **ExtStringList** -- contains a list of *ExtendedString* values;
1090 * **Integer** -- contains an integer value;
1091 * **IntegerArray** -- contains an array of integer values;
1092 * **IntegerList** -- contains a list of integer values;
1093 * **IntPackedMap** -- contains a packed map of integers;
1094 * **Name** -- contains a string -- the name of a given label (or attribute);
1095 * **NamedData** -- may contain up to 6 of the following named data sets (vocabularies): *DataMapOfStringInteger, DataMapOfStringReal, DataMapOfStringString, DataMapOfStringByte, DataMapOfStringHArray1OfInteger* or *DataMapOfStringHArray1OfReal*;
1096 * **NoteBook** -- contains a *NoteBook* object attribute;
1097 * **Real** -- contains a real value;
1098 * **RealArray** -- contains an array of real values;
1099 * **RealList** -- contains a list of real values;
1100 * **Relation** -- contains a relation string and a list of used variables attributes;
1101 * **Tick** -- defines a boolean attribute;
1102 * **Variable** -- simply identifies, that a variable belongs to this label; contains the flag *is constraint* and a string of used units ("mm", "m"...);
1103 * **UAttribute** -- attribute with a user-defined GUID. As a rule, this attribute is used as a marker, which is independent of attributes at the same label (note, that attributes with the same GUIDs can not belong to the same label).
72b7576f 1104
dba69de2 1105### Relationship attributes
1106
3f812249 1107 * **Reference** -- contains reference to the label of its own data framework;
1108 * **ReferenceArray** -- contains an array of references;
1109 * **ReferenceList** -- contains a list of references;
1110 * **TreeNode** -- this attribute allows to create an internal tree in the data framework; this tree consists of nodes with the specified tree ID; each node contains references to the father, previous brother, next brother, first child nodes and tree ID.
72b7576f 1111
dba69de2 1112### Auxiliary attributes
1113
3f812249 1114 * **Directory** -- high-level tool attribute for sub-labels management;
1115 * **TagSource** -- this attribute is used for creation of new children: it stores the tag of the last-created child of the label and gives access to the new child label creation functionality.
72b7576f 1116
e2b55410 1117All attributes inherit class *TDF_Attribute*, so, each attribute has its own GUID and standard methods for attribute creation, manipulation, getting access to the data framework.
72b7576f 1118
1119
1120@subsection occt_ocaf_6_2 Services common to all attributes
1121
1122@subsubsection occt_ocaf_6_2_1 Accessing GUIDs
1123
1124To access the GUID of an attribute, you can use two methods:
e2b55410 1125 * Method *GetID* is the static method of a class. It returns the GUID of any attribute, which is an object of a specified class (for example, *TDataStd_Integer* returns the GUID of an integer attribute). Only two classes from the list of standard attributes do not support these methods: *TDataStd_TreeNode* and *TDataStd_Uattribute*, because the GUIDs of these attributes are variable.
dba69de2 1126 * Method *ID* is the method of an object of an attribute class. It returns the GUID of this attribute. Absolutely all attributes have this method: only by this identifier you can discern the type of an attribute.
e2b55410 1127
1128To find an attribute attached to a specific label, you use the GUID of the attribute type you are looking for. This information can be found using the method <i> GetID</i> and the method <i> Find</i> for the label as follows:
1129
1130~~~~
1131 Standard_GUID anID = MyAttributeClass::GetID();
1132 Standard_Boolean HasAttribute = aLabel.Find(anID,anAttribute);
1133~~~~
72b7576f 1134
1135@subsubsection occt_ocaf_6_2_2 Conventional Interface of Standard Attributes
1136
1137It is usual to create standard named methods for the attributes:
1138
dba69de2 1139 * Method *Set(label, [value])* is the static method, which allows to add an attribute to a given label. If an attribute is characterized by one value this method may set it.
1140 * Method *Get()* returns the value of an attribute if it is characterized by one value.
1141 * Method *Dump(Standard_OStream)* outputs debug information about a given attribute to a given stream.
72b7576f 1142
27245ff9 1143@subsection occt_ocaf_6_3 The choice between standard and custom attributes
1144
1145When you start to design an application based on OCAF, usually it is necessary to choose, which attribute will be used for allocation of data in the OCAF document: standard or newly-created?
1146
1147It is possible to describe any model by means of standard OCAF attributes.
1148 However, it is still a question if this description will be efficient in terms of memory and speed, and, at the same time, convenient to use.
1149
1150 This depends on a particular model.
1151
1152 OCAF imposes the restriction that only one attribute type may be allocated to one label.
1153 It is necessary to take into account the design of the application data tree.
1154 For example, if a label should possess several double values,
1155 it is necessary to distribute them through several child sub-labels or use an array of double values.
1156
1157 Let us consider several boundary implementations of the same model in OCAF tree and analyze the advantages and disadvantages of each approach.
1158
1159
1160@subsubsection occt_ocaf_6_2_3 Comparison and analysis of approaches
1161
1162 Below are described two different model implementations:
1163 one is based on standard OCAF attributes and the other is based
1164 on the creation of a new attribute possessing all data of the model.
1165
1166 A load is distributed through the shape. The measurements are taken at particular points defined by (x, y and z) co-ordinates. The load is represented as a projection onto X, Y and Z axes of the local co-ordinate system at each point of measurement. A matrix of transformation is needed
1167 to convert the local co-ordinate system to the global one, but this is optional.
1168
1169 So, we have 15 double values at each point of measurement.
1170 If the number of such points is 100 000, for example, it means
1171 that we have to store 1 500 000 double values in the OCAF document.
1172
1173 The first approach consists in using standard OCAF attributes.
1174 Besides, there are several variants of how the standard attributes may be used:
1175 * Allocation of all 1 500 000 double values as one array of double values attached to one label;
1176 * Allocation of values of one measure of load (15 values) as one array of double values and attachment of one point of measure to one label;
1177 * Allocation of each point of measure as an array of 3 double values attached to one label, the projection of load onto the local co-ordinate system axes as another array of 3 double values attached to a sub-label, and the matrix of projection (9 values) as the third array also attached to a sub-label.
1178
1179 Certainly, other variants are also possible.
1180
1181@image html ocaf_tree_wp_image003.png "Allocation of all data as one array of double values"
1182@image latex ocaf_tree_wp_image003.png "Allocation of all data as one array of double values"
1183
1184 The first approach to allocation of all data represented as one array of double values
1185 saves initial memory and is easy to implement.
1186 But access to the data is difficult because the values are stored in a flat array.
1187 It will be necessary to implement a class with several methods giving access
1188 to particular fields like the measurement points, loads and so on.
1189
1190 If the values may be edited in the application,
1191 it means that the whole array will be backed-up on each edition.
1192 The memory usage will increase very fast!
1193 So, this approach may be considered only in case of non-editable data.
1194
1195 Let’s consider the allocation of data of each measurement point per label (the second case).
3f812249 1196 In this case we create 100 000 labels -- one label for each measurement point
27245ff9 1197 and attach an array of double values to these labels:
1198
1199@image html ocaf_tree_wp_image004.png "Allocation of data of each measurement point as arrays of double values"
1200@image latex ocaf_tree_wp_image004.png "Allocation of data of each measurement point as arrays of double values"
1201
1202 Now edition of data is safer as far as memory usage is concerned.
1203 Change of value for one measurement point (any value: point co-ordinates, load, and so on)
1204 backs-up only one small array of double values.
1205 But this structure (tree) requires more memory space (additional labels and attributes).
1206
1207 Besides, access to the values is still difficult and it is necessary
1208 to have a class with methods of access to the array fields.
1209
1210 The third case of allocation of data through OCAF tree is represented below:
1211
1212@image html ocaf_tree_wp_image005.png "Allocation of data into separate arrays of double values"
1213@image latex ocaf_tree_wp_image005.png "Allocation of data into separate arrays of double values"
1214
1215 In this case sub-labels are involved and we can easily access the values of each measurement point,
1216 load or matrix. We don’t need an interface class with methods of access to the data
1217 (if it exists, it would help to use the data structure, but this is optional).
1218
1219 On the one hand, this approach requires more memory for allocation of the attributes (arrays of double values).
1220 On the other hand, it saves memory during the edition of data
1221 by backing-up only the small array containing the modified data.
1222 So, if the data is fully modifiable, this approach is more preferable.
1223
1224 Before making a conclusion, let’s consider the same model implemented through a newly created OCAF attribute.
1225
1226 For example, we might allocate all data belonging to one measurement point as one OCAF attribute.
1227 In this case we implement the third variant of using the standard attributes (see picture 3),
1228 but we use less memory (because we use only one attribute instead of three):
1229
1230@image html ocaf_tree_wp_image006.png "Allocation of data into newly created OCAF attribute"
1231@image latex ocaf_tree_wp_image006.png "Allocation of data into newly created OCAF attribute"
1232
1233 The second variant of using standard OCAF attributes still has drawbacks:
1234 when data is edited, OCAF backs-up all values of the measurement point.
1235
1236 Let’s imagine that we have some non-editable data.
1237 It would be better for us to allocate this data separately from editable data.
1238 Back-up will not affect non-editable data and memory will not increase so much during data edition.
1239
1240 @subsubsection occt_ocaf_6_2_4 Conclusion
1241
1242 When deciding which variant of data model implementation to choose,
1243 it is necessary to take into account the application response time,
1244 memory allocation and memory usage in transactions.
1245
1246 Most of the models may be implemented using only standard OCAF attributes.
1247 Some other models need special treatment and require implementation of new OCAF attributes.
1248
1249
dba69de2 1250@section occt_ocaf_7 Visualization Attributes
72b7576f 1251
1252@subsection occt_ocaf_7_1 Overview
1253
e2b55410 1254Standard visualization attributes implement the Application Interactive Services (see @ref occt_user_guides__visualization "Visualization User's Guide"). in the context of Open CASCADE Technology Application Framework. Standard visualization attributes are AISViewer and Presentation and belong to the TPrsStd package.
72b7576f 1255
1256@subsection occt_ocaf_7_2 Services provided
1257
1258@subsubsection occt_ocaf_7_2_1 Defining an interactive viewer attribute
1259
e2b55410 1260The class *TPrsStd_AISViewer* allows you to define an interactive viewer attribute. There may be only one such attribute per one data framework and it is always placed to the root label. So, it could be set or found by any label ("access label") of the data framework. Nevertheless the default architecture can be easily extended and the user can manage several Viewers per one framework by himself.
72b7576f 1261
e2b55410 1262To initialize the AIS viewer as in the example below, use method *Find*.
72b7576f 1263
72b7576f 1264~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
dba69de2 1265// "access" is any label of the data framework
72b7576f 1266Handle(TPrsStd_AISViewer) viewer = TPrsStd_AISViewer::Find(access)
1267~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1268
1269@subsection occt_ocaf_7_2_2 Defining a presentation attribute
1270
e2b55410 1271The class *TPrsStd_AISPresentation* allows you to define the visual presentation of document labels contents. In addition to various visual fields (color, material, transparency, *isDisplayed*, etc.), this attribute contains its driver GUID. This GUID defines the functionality, which will update the presentation every time when needed.
72b7576f 1272
1273@subsubsection occt_ocaf_7_2_3 Creating your own driver
1274
1275The abstract class TPrsStd_Driver allows you to define your own driver classes. Simply redefine the Update method in your new class, which will rebuild the presentation.
1276
e2b55410 1277If your driver is placed to the driver table with the unique driver GUID, then every time the viewer updates presentations with a GUID identical to your driver’s GUID, the *Update* method of your driver for these presentations must be called:
dba69de2 1278@image html /user_guides/ocaf/images/ocaf_image016.png
1279@image latex /user_guides/ocaf/images/ocaf_image016.png
72b7576f 1280
1281As usual, the GUID of a driver and the GUID of a displayed attribute are the same.
1282
1283@subsubsection occt_ocaf_7_2_4 Using a container for drivers
1284
e2b55410 1285You frequently need a container for different presentation drivers. The class *TPrsStd_DriverTable* provides this service. You can add a driver to the table, see if one is successfully added, and fill it with standard drivers.
72b7576f 1286
e2b55410 1287To fill a driver table with standard drivers, first initialize the AIS viewer as in the example above, and then pass the return value of the method *InitStandardDrivers* to the driver table returned by the method *Get*. Then attach a *TNaming_NamedShape* to a label and set the named shape in the presentation attribute using the method *Set*. Then attach the presentation attribute to the named shape attribute, and the *AIS_InteractiveObject*, which the presentation attribute contains, will initialize its drivers for the named shape. This can be seen in the example below.
72b7576f 1288
1289**Example**
1290~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1291DriverTable::Get() -> InitStandardDrivers();
1292// next, attach your named shape to a label
1293TPrsStd_AISPresentation::Set(NS};
1294// here, attach the AISPresentation to NS.
1295~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1296
27245ff9 1297
dba69de2 1298@section occt_ocaf_8 Function Services
72b7576f 1299
3f812249 1300Function services aggregate data necessary for regeneration of a model. The function mechanism -- available in the package *TFunction* -- provides links between functions and any execution algorithms, which take their arguments from the data framework, and write their results inside the same framework.
72b7576f 1301
1302When you edit any application model, you have to regenerate the model by propagating the modifications. Each propagation step calls various algorithms. To make these algorithms independent of your application model, you need to use function services.
1303
27245ff9 1304@image html /user_guides/ocaf/images/ocaf_image008.png "Document structure"
1305@image latex /user_guides/ocaf/images/ocaf_image008.png "Document structure"
1306
72b7576f 1307Take, for example, the case of a modeling sequence made up of a box with the application of a fillet on one of its edges. If you change the height of the box, the fillet will need to be regenerated as well.
1308
dba69de2 1309@subsection occt_ocaf_8_1 Finding functions, their owners and roots
72b7576f 1310
e2b55410 1311The class *TFunction_Function* is an attribute, which stores a link to a function driver in the data framework. In the static table *TFunction_DriverTable* correspondence links between function attributes and drivers are stored.
72b7576f 1312
e2b55410 1313You can write your function attribute, a driver for such attribute, which updates the function result in accordance to a given map of changed labels, and set your driver with the GUID to the driver table.
72b7576f 1314
e2b55410 1315Then the solver algorithm of a data model can find the *Function* attribute on a corresponding label and call the *Execute* driver method to update the result of the function.
72b7576f 1316
dba69de2 1317@subsection occt_ocaf_8_2 Storing and accessing information about function status
72b7576f 1318
e2b55410 1319For updating algorithm optimization, each function driver has access to the *TFunction_Logbook* object that is a container for a set of touched, impacted and valid labels. Using this object a driver gets to know which arguments of the function were modified.
72b7576f 1320
dba69de2 1321@subsection occt_ocaf_8_3 Propagating modifications
72b7576f 1322
e2b55410 1323An application must implement its functions, function drivers and the common solver for parametric model creation. For example, check the following model:
72b7576f 1324
dba69de2 1325@image html /user_guides/ocaf/images/ocaf_image017.png
1326@image latex /user_guides/ocaf/images/ocaf_image017.png
72b7576f 1327
1328The procedure of its creation is as follows:
27245ff9 1329 * create a rectangular planar face *F* with height 100 and width 200;
1330 * create prism *P* using face *F* as a basis;
1331 * create fillet *L* at the edge of the prism;
1332 * change the width of *F* from 200 to 300;
1333 * the solver for the function of face *F* starts;
1334 * the solver detects that an argument of the face *F* function has been modified;
1335 * the solver calls the driver of the face *F* function for a regeneration of the face;
1336 * the driver rebuilds face *F* and adds the label of the face *width* argument to the logbook as touched and the label of the function of face *F* as impacted;
1337
3f812249 1338 * the solver detects the function of *P* -- it depends on the function of *F*;
27245ff9 1339 * the solver calls the driver of the prism *P* function;
1340 * the driver rebuilds prism *P* and adds the label of this prism to the logbook as impacted;
3f812249 1341 * the solver detects the function of *L* -- it depends on the function of *P*;
27245ff9 1342 * the solver calls the *L* function driver;
1343 * the driver rebuilds fillet *L* and adds the label of the fillet to the logbook as impacted.
1344
1345 @section occt_ocaf_8a Example of Function Mechanism Usage
1346
1347 @subsection occt_ocaf_8a_1 Introduction
1348
1349 Let us describe the usage of the Function Mechanism of Open CASCADE Application Framework on a simple example.
1350 This example represents a "nail" composed by a cone and two cylinders of different radius and height:
1351
1352@image html ocaf_functionmechanism_wp_image003.png "A nail"
1353@image latex ocaf_functionmechanism_wp_image003.png " A nail"
1354
1355 These three objects (a cone and two cylinders) are independent,
3f812249 1356 but the Function Mechanism makes them connected to each other and representing one object -- a nail.
27245ff9 1357 The object "nail" has the following parameters:
1358
1359 * The position of the nail is defined by the apex point of the cone.
1360 The cylinders are built on the cone and therefore they depend on the position of the cone.
1361 In this way we define a dependency of the cylinders on the cone.
1362 * The height of the nail is defined by the height of the cone.
1363 Let’s consider that the long cylinder has 3 heights of the cone
1364 and the header cylinder has a half of the height of the cone.
1365 * The radius of the nail is defined by the radius of the cone.
1366 The radius of the long cylinder coincides with this value.
1367 Let’s consider that the header cylinder has one and a half radiuses of the cone.
1368
1369 So, the cylinders depend on the cone and the cone parameters define the size of the nail.
1370
1371 It means that re-positioning the cone (changing its apex point) moves the nail,
1372 the change of the radius of the cone produces a thinner or thicker nail,
1373 and the change of the height of the cone shortens or prolongates the nail.
1374  It is suggested to examine the programming steps needed to create a 3D parametric model of the "nail".
1375
1376@subsection occt_ocaf_8a_2 Step 1: Data Tree
1377
1378 The first step consists in model data allocation in the OCAF tree.
1379 In other words, it is necessary to decide where to put the data.
1380
1381 In this case, the data can be organized into a simple tree
1382 using references for definition of dependent parameters:
1383
1384* Nail
1385 * Cone
1386 + Position (x,y,z)
1387 + Radius
1388 + Height
1389 * Cylinder (stem)
1390 + Position = "Cone" position translated for "Cone" height along Z;
1391 + Radius = "Cone" radius;
1392 + Height = "Cone" height multiplied by 3;
1393 * Cylinder (head)
1394 + Position = "Long cylinder" position translated for "Long cylinder" height along Z;
1395 + Radius = "Long cylinder" radius multiplied by 1.5;
1396 + Height = "Cone" height divided by 2.
1397
1398 The "nail" object has three sub-leaves in the tree: the cone and two cylinders.
1399
1400 The cone object is independent.
1401
1402 The long cylinder representing a "stem" of the nail refers to the corresponding parameters
1403 of the cone to define its own data (position, radius and height). It means that the long cylinder depends on the cone.
1404
1405 The parameters of the head cylinder may be expressed through the cone parameters
1406 only or through the cone and the long cylinder parameters.
1407 It is suggested to express the position and the radius of the head cylinder
1408 through the position and the radius of the long cylinder, and the height
1409 of the head cylinder through the height of the cone.
1410 It means that the head cylinder depends on the cone and the long cylinder.
1411
1412@subsection occt_ocaf_8a_3 Step 2: Interfaces
1413
1414 The interfaces of the data model are responsible for dynamic creation
1415 of the data tree of the represented at the previous step, data modification and deletion.
1416
1417 The interface called *INail* should contain the methods for creation
1418 of the data tree for the nail, setting and getting of its parameters, computation, visualization and removal.
1419
1420@subsubsection occt_ocaf_8a_3_1 Creation of the nail
1421
1422 This method of the interface creates a data tree for the nail at a given leaf of OCAF data tree.
1423
1424 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).
1425
1426 It sets the default values of position, radius and height of the nail.
1427
1428 The nail has the following user parameters:
3f812249 1429 * The position -- coincides with the position of the cone
1430 * The radius of the stem part of the nail -- coincides with the radius of the cone
1431 * The height of the nail -- a sum of heights of the cone and both cylinders
27245ff9 1432
1433 The values of the position and the radius of the nail are defined for the cone object data.
1434 The height of the cone is recomputed as 2 * heights of nail and divided by 9.
1435
1436@subsubsection occt_ocaf_8a_3_2 Computation
1437
1438 The Function Mechanism is responsible for re-computation of the nail.
1439 It will be described in detail later in this document.
1440
1441 A data leaf consists of the reference  to the location of the real data
1442 and a real value defining a coefficient of multiplication of the referenced data.
1443
1444 For example, the height of the long cylinder is defined as a reference to the height of the cone
1445 with coefficient 3. The data leaf of the height of the long cylinder
1446 should contain two attributes: a reference to the height of cone and a real value equal to 3.
1447
1448@subsubsection occt_ocaf_8a_3_3 Visualization
1449
1450 The shape resulting of the nail function can be displayed using the standard OCAF visualization mechanism.
1451
1452@subsubsection occt_ocaf_8a_3_4 Removal of the nail
1453
1454To automatically erase the nail from the viewer and the data tree it is enough to clean the nail leaf from attributes.
1455
1456@subsection occt_ocaf_8a_4 Step 3: Functions
1457
1458 The nail is defined by four functions: the cone, the two cylinders and the nail function.
1459 The function of the cone is independent. The functions of the cylinders depend on the cone function.
1460 The nail function depends on the results of all functions:
1461
1462@image html ocaf_functionmechanism_wp_image005.png "A graph of dependencies between functions"
1463@image latex ocaf_functionmechanism_wp_image005.png "A graph of dependencies between functions"
1464
1465 Computation of the model starts with the cone function, then the long cylinder,
1466 after that the header cylinder and, finally, the result is generated by the nail function at the end of function chain.
1467
1468 The Function Mechanism of Open CASCADE Technology creates this graph of dependencies
1469 and allows iterating it following the dependencies.
1470 The only thing the Function Mechanism requires from its user
1471 is the implementation of pure virtual methods of *TFunction_Driver*:
1472
3f812249 1473 * <i>\::Arguments()</i> -- returns a list of arguments for the function
1474 * <i>\::Results()</i> -- returns a list of results of the function
27245ff9 1475
1476 These methods give the Function Mechanism the information on the location of arguments
1477 and results of the function and allow building a graph of functions.
1478 The class *TFunction_Iterator* iterates the functions of the graph in the execution order.
1479
1480 The pure virtual method *TFunction_Driver::Execute()* calculating the function should be overridden.
1481
1482 The method <i>\::MustExecute()</i> calls the method <i>\::Arguments()</i> of the function driver
1483 and ideally this information (knowledge of modification of arguments of the function) is enough
1484 to make a decision whether the function should be executed or not. Therefore, this method usually shouldn’t be overridden.
1485
1486 The cone and cylinder functions differ only in geometrical construction algorithms.
1487 Other parameters are the same (position, radius and height).
1488
3f812249 1489 It means that it is possible to create a base class -- function driver for the three functions,
27245ff9 1490 and two descendant classes producing: a cone or a cylinder.
1491
1492 For the base function driver the methods <i>\::Arguments()</i> and <i>\::Results()</i> will be overridden.
1493 Two descendant function drivers responsible for creation of a cone and a cylinder will override only the method <i>\::Execute()</i>.
1494
3f812249 1495 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.
27245ff9 1496
1497 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.
1498
1499@subsection occt_ocaf_8a_5 Example 1: iteration and execution of functions.
1500
1501 This is an example of the code for iteration and execution of functions.
1502
1503~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1504
1505 // The scope of functions is defined.
1506 Handle(TFunction_Scope) scope = TFunction_Scope::Set( anyLabel );
1507
1508 // The information on modifications in the model is received.
1509 TFunction_Logbook&amp; log = scope-GetLogbook();
1510
1511 // The iterator is iInitialized by the scope of functions.
1512 TFunction_Iterator iterator( anyLabel );
1513 Iterator.SetUsageOfExecutionOrder( true );
1514
1515 // The function is iterated,  its dependency is checked on the modified data and  executed if necessary.
1516 for (; iterator.more(); iterator.Next())
1517 {
1518 // The function iterator may return a list of current functions for execution.
1519 // It might be useful for multi-threaded execution of functions.
1520 const TDF_LabelList&amp; currentFunctions = iterator.Current();
1521
1522 //The list of current functions is iterated.
1523 TDF_ListIteratorOfLabelList currentterator( currentFucntions );
1524 for (; currentIterator.More(); currentIterator.Next())
1525 {
1526 // An interface for the function is created.
1527 TFunction_IFunction interface( currentIterator.Value() );
1528
1529 // The function driver is retrieved.
1530 Handle(TFunction_Driver) driver = interface.GetDriver();
1531
1532 // The dependency of the function on the  modified data is checked.
1533 If (driver-MustExecute( log ))
1534 {
1535 // The function is executed.
1536 int ret = driver-Execute( log );
1537 if ( ret )
1538 return false;
1539 } // end if check on modification
1540 } // end of iteration of current functions
1541 } // end of iteration of functions.
1542
1543~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1544
1545@subsection occt_ocaf_8a_6 Example 2: Cylinder function driver
1546
1547 This is an example of the code for a cylinder function driver. To make the things clearer, the methods <i>\::Arguments()</i> and <i>\::Results()</i> from the base class are also mentioned.
1548
1549~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1550
1551 // A virtual method ::Arguments() returns a list of arguments of the function.
1552 CylinderDriver::Arguments( TDF_LabelList&amp; args )
1553 {
1554 // The direct arguments, located at sub-leaves of the fucntion, are collected (see picture 2).
1555 TDF_ChildIterator cIterator( Label(), false );
1556 for (; cIterator.More(); cIterator.Next() )
1557 {
1558 // Direct argument.
1559 TDF_Label sublabel = cIterator.Value();
1560 Args.Append( sublabel );
1561
1562 // The references to the external data are checked.
1563 Handle(TDF_Reference) ref;
1564 If ( sublabel.FindAttribute( TDF_Reference::GetID(), ref ) )
1565 {
1566 args.Append( ref-Get() );
1567 }
1568 }
1569
1570 // A virtual method ::Results() returns a list of result leaves.
1571 CylinderDriver::Results( TDF_LabelList&amp; res )
1572 {
1573 // The result is kept at the function label.
1574   Res.Append( Label() );
1575 }
1576
1577 // Execution of the function driver.
1578 Int CylinderDriver::Execute( TFunction_Logbook&amp; log )
1579 {
3f812249 1580 // Position of the cylinder - position of the first function (cone)
27245ff9 1581 //is  elevated along Z for height values of all previous functions.
1582 gp_Ax2 axes = …. // out of the scope of this guide.
1583 // The radius value is retrieved.
1584 // It is located at second child sub-leaf (see the picture 2).
1585 TDF_Label radiusLabel = Label().FindChild( 2 );
1586
1587 // The multiplicator of the radius ()is retrieved.
1588 Handle(TDataStd_Real) radiusValue;
1589 radiusLabel.FindAttribute( TDataStd_Real::GetID(), radiusValue);
1590
1591 // The reference to the radius is retrieved.
1592 Handle(TDF_Reference) refRadius;
1593 RadiusLabel.FindAttribute( TDF_Reference::GetID(), refRadius );
1594
1595 // The radius value is calculated.
1596 double radius = 0.0;
1597
1598 if ( refRadius.IsNull() )
1599 {
1600 radius = radiusValue-Get();
1601 }
1602 else
1603 {
1604 // The referenced radius value is retrieved.
1605 Handle(TDataStd_Real) referencedRadiusValue;
1606 RefRadius-Get().FindAttribute(TDataStd_Real::GetID() ,referencedRadiusValue );
1607 radius = referencedRadiusValue-Get() * radiusValue-Get();
1608 }
1609
1610 // The height value is retrieved.
1611 double height = … // similar code to taking the radius value.
1612
1613 // The cylinder is created.
1614 TopoDS_Shape cylinder = BRepPrimAPI_MakeCylinder(axes, radius, height);
1615
1616 // The result (cylinder) is set
1617 TNaming_Builder builder( Label() );
1618 Builder.Generated( cylinder );
1619
1620 // The modification of the result leaf is saved in the log.
1621 log.SetImpacted( Label() );
1622
1623 return 0;
1624 }
1625~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1626
1627
72b7576f 1628
1629@section occt_ocaf_9 XML Support
1630
1631Writing and reading XML files in OCCT is provided by LDOM package, which constitutes an integral part
1632of XML OCAF persistence, which is the optional component provided on top of Open CASCADE Technology.
1633
1634The Light DOM (LDOM) package contains classes maintaining a data structure whose main principles conform to W3C DOM Level 1 Recommendations. The purpose of these classes as required by XML OCAF persistence schema is to:
3f812249 1635* Maintain a tree structure of objects in memory representing the XML document. The root of the structure is an object of the *LDOM_Document* type. This object contains all the data corresponding to a given XML document and contains one object of the *LDOM_Element* type named "document element". The document element contains other *LDOM_Element* objects forming a tree. Other types of nodes: *LDOM_Attr, LDOM_Text, LDOM_Comment* and *LDOM_CDATASection* -- represent the corresponding XML types and serve as branches of the tree of elements.
e2b55410 1636* Provide class *LDOM_Parser* to read XML files and convert them to *LDOM_Document* objects.
1637* Provide class *LDOM_XmlWriter* to convert *LDOM_Document* to a character stream in XML format and store it in file.
72b7576f 1638
1639This package covers the functionality provided by numerous products known as "DOM parsers". Unlike most of them, LDOM was specifically developed to meet the following requirements:
1640* To minimize the virtual memory allocated by DOM data structures. In average, the amount of memory of LDOM is the same as the XML file size (UTF-8).
1641* To minimize the time required for parsing and formatting XML, as well as for access to DOM data structures.
1642
1643Both these requirements are important when XML files are processed by applications if these files are relatively large (occupying megabytes and even hundreds of megabytes). To meet the requirements, some limitations were imposed on the DOM Level 1 specification; these limitations are insignificant in applications like OCAF. Some of these limitations can be overridden in the course of future developments. The main limitations are:
e2b55410 1644* No Unicode support as well as various other encodings; only ASCII strings are used in DOM/XML. Note: There is a data type *TCollection_ExtendedString* for wide character data. This type is supported by *LDOM_String* as a sequence of numbers.
1645* Some superfluous methods are deleted: *getPreviousSibling, getParentNode,* etc.
72b7576f 1646* No resolution of XML Entities of any kind
1647* No support for DTD: the parser just checks for observance of general XML rules and never validates documents.
e2b55410 1648* Only 5 available types of DOM nodes: *LDOM_Element, LDOM_Attr, LDOM_Text, LDOM_Comment* and *LDOM_CDATASection*.
72b7576f 1649* No support of Namespaces; prefixed names are used instead of qualified names.
e2b55410 1650* No support of the interface *DOMException* (no exception when attempting to remove a non-existing node).
72b7576f 1651
1652LDOM is dependent on Kernel OCCT classes only. Therefore, it can be used outside OCAF persistence in various algorithms where DOM/XML support may be required.
1653
1654@subsection occt_ocaf_9_1 Document Drivers
1655
1656The drivers for document storage and retrieval manage conversion between a transient OCAF
e2b55410 1657Document in memory and its persistent reflection in a container (disk, memory, network). For XML Persistence, they are defined in the package XmlDrivers.
72b7576f 1658
1659The main methods (entry points) of these drivers are:
3f812249 1660* *Write()* -- for a storage driver;
1661* *Read()* -- for a retrieval driver.
72b7576f 1662
1663The most common case (which is implemented in XML Persistence) is writing/reading document to/from a regular OS file. Such conversion is performed in two steps:
1664
1665First it is necessary to convert the transient document into another form (called persistent), suitable for writing into a file, and vice versa.
1666In XML Persistence LDOM_Document is used as the persistent form of an OCAF Document and the DOM_Nodes are the persistent objects.
1667An OCAF Document is a tree of labels with attributes. Its transformation into a persistent form can be functionally divided into two parts:
1668* Conversion of the labels structure, which is performed by the method XmlMDF::FromTo()
1669* Conversion of the attributes and their underlying objects, which is performed by the corresponding attribute drivers (one driver per attribute type).
1670
1671The driver for each attribute is selected from a table of drivers, either by attribute
1672type (on storage) or by the name of the corresponding DOM_Element (on retrieval).
1673The table of drivers is created by by methods *XmlDrivers_DocumentStorageDriver::AttributeDrivers()*
1674and *XmlDrivers_DocumentRetrievalDriver::AttributeDrivers()*.
1675
1676Then the persistent document is written into a file (or read from a file).
4ee1bdf4 1677In standard persistence Storage and FSD packages contain classes for writing/reading the persistent document into a file. In XML persistence *LDOMParser* and *LDOM_XmlWriter* are used instead.
72b7576f 1678
4ee1bdf4 1679Usually, the library containing document storage and retrieval drivers is loaded at run time by a plugin mechanism. To support this in XML Persistence, there is a plugin *XmlPlugin* and a *Factory()* method in the *XmlDrivers* package. This method compares passed GUIDs with known GUIDs and returns the corresponding driver or generates an exception if the GUID is unknown.
72b7576f 1680
1681The application defines which GUID is needed for document storage or retrieval and in which library it should be found. This depends on document format and application resources. Resources for XML Persistence and also for standard persistence are found in the StdResource unit. They are written for the XmlOcaf document format.
1682
1683@subsection occt_ocaf_9_2 Attribute Drivers
1684
4ee1bdf4 1685There is one attribute driver for XML persistence for each transient attribute from a set of standard OCAF attributes, with the exception of attribute types, which are never stored (pure transient). Standard OCAF attributes are collected in six packages, and their drivers also follow this distribution. Driver for attribute <i>T*_*</i> is called <i>XmlM*_*</i>. Conversion between transient and persistent form of attribute is performed by two methods *Paste()* of attribute driver.
72b7576f 1686
1687*XmlMDF_ADriver* is the root class for all attribute drivers.
1688
4ee1bdf4 1689At the beginning of storage/retrieval process, one instance of each attribute driver is created and appended to driver table implemented as *XmlMDF_ADriverTable*. During OCAF Data storage, attribute drivers are retrieved from the driver table by the type of attribute. In the retrieval step, a data map is created linking names of *DOM_Elements* and attribute drivers, and then attribute drivers are sought in this map by *DOM_Element* qualified tag names.
72b7576f 1690
4ee1bdf4 1691Every transient attribute is saved as a *DOM_Element* (root element of OCAF attribute) with attributes and possibly sub-nodes. The name of the root element can be defined in the attribute driver as a string passed to the base class constructor. The default is the attribute type name. Similarly, namespace prefixes for each attribute can be set. There is no default value, but it is possible to pass NULL or an empty string to store attributes without namespace prefixes.
72b7576f 1692
4ee1bdf4 1693The basic class *XmlMDF_ADriver* supports errors reporting via the method *WriteMessage(const TCollection_ExtendedString&)*. It sends a message string to its message driver which is initialized in the constructor with a *Handle(CDM_MessageDriver)* passed from the application by Document Storage/Retrieval Driver.
72b7576f 1694
1695@subsection occt_ocaf_9_3 XML Document Structure
1696
ba06f8bb 1697Every XML Document has one root element, which may have attributes and contain other nodes. In OCAF XML Documents the root element is named "document" and has attribute "format" with the name of the OCAF Schema used to generate the file. The standard XML format is "XmlOcaf". The following elements are sub-elements of \<document\> and should be unique entries as its sub-elements, in a specific order. The order is:
3f812249 1698* **Element info** -- contains strings identifying the format version and other parameters of the OCAF XML document. Normally, data under the element is used by persistence algorithms to correctly retrieve and initialize an OCAF document. The data also includes a copyright string.
1699* **Element comments** -- consists of an unlimited number of \<comment\> sub-elements containing necessary comment strings.
1700* **Element label** -- the root label of the document data structure, with the XML attribute "tag" equal to 0. It contains all the OCAF data (labels, attributes) as tree of XML elements. Every sub-label is identified by a tag (positive integer) defining a unique key for all sub-labels of a label. Every label can contain any number of elements representing OCAF attributes (see OCAF Attributes Representation below).
1701* **Element shapes** -- contains geometrical and topological entities in BRep format. These entities being referenced by OCAF attributes written under the element \<label\>. This element is empty if there are no shapes in the document. It is only output if attribute driver *XmlMNaming_NamedShapeDriver* has been added to drivers table by the *DocumentStorageDriver*.
72b7576f 1702
dba69de2 1703### OCAF Attributes Representation
72b7576f 1704
1705In XML documents, OCAF attributes are elements whose name identifies the OCAF attribute type. These elements may have a simple (string or number) or complex (sub-elements) structure, depending on the architecture of OCAF attribute. Every XML type for OCAF attribute possesses a unique positive integer "id" XML attribute identifying the OCAF attribute throughout the document. To ensure "id" uniqueness, the attribute name "id" is reserved and is only used to indicate and identify elements which may be referenced from other parts of the OCAF XML document.
1706For every standard OCAF attribute, its XML name matches the name of a C++ class in Transient data model. Generally, the XML name of OCAF attribute can be specified in the corresponding attribute driver.
1707XML types for OCAF attributes are declared with XML W3C Schema in a few XSD files where OCAF attributes are grouped by the package where they are defined.
1708
dba69de2 1709### Example of resulting XML file
1710
3f812249 1711The following example is a sample text from an XML file obtained by storing an OCAF document with two labels (0: and 0:2) and two attributes -- *TDataStd_Name* (on label 0:) and *TNaming_NamedShape* (on label 0:2). The \<shapes\> section contents are replaced by an ellipsis.
72b7576f 1712
4ee1bdf4 1713~~~~
72b7576f 1714<?xml version="1.0" encoding="UTF-8"?>
1715<document format="XmlOcaf" xmlns="http://www.opencascade.org/OCAF/XML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1716xsi:schemaLocation="http://www.opencascade.org/OCAF/XML http://www.opencascade.org/OCAF/XML/XmlOcaf.xsd">
1717
1718<info date="2001-10-04" schemav="0" objnb="3">
1719<iitem>Copyright: Open Cascade, 2001</iitem>
1720<iitem>STORAGE_VERSION: PCDM_ReadWriter_1</iitem>
1721<iitem>REFERENCE_COUNTER: 0</iitem>
1722<iitem>MODIFICATION_COUNTER: 1</iitem>
1723</info>
1724<comments/>
1725<label tag="0">
1726<TDataStd_Name id="1">Document_1</TDataStd_Name>
1727<label tag="2">
1728<TNaming_NamedShape id="2" evolution="primitive">
1729<olds/>
1730<news>
1731<shape tshape="+34" index="1"/>
1732</news>
1733</TNaming_NamedShape>
1734</label>
1735</label>
ba06f8bb 1736\<shapes\>
72b7576f 1737...
1738</shapes>
1739</document>
1740
4ee1bdf4 1741~~~~
72b7576f 1742
1743@subsection occt_ocaf_9_4 XML Schema
1744
1745The XML Schema defines the class of a document.
1746
1747The full structure of OCAF XML documents is described as a set of XML W3C Schema files with definitions of all XML element types. The definitions provided cannot be overridden. If any application defines new persistence schemas, it can use all the definitions from the present XSD files but if it creates new or redefines existing types, the definition must be done under other namespace(s).
1748
1749There are other ways to declare XML data, different from W3C Schema, and it should be possible to use them to the extent of their capabilities of expressing the particular structure and constraints of our XML data model. However, it must be noted that the W3C Schema is the primary format for declarations and as such, it is the format supported for future improvements of Open CASCADE Technology, including the development of specific applications using OCAF XML persistence.
1750
1751The Schema files (XSD) are intended for two purposes:
1752* documenting the data format of files generated by OCAF;
1753* validation of documents when they are used by external (non-OCAF) applications, e.g., to generate reports.
1754
1755The Schema definitions are not used by OCAF XML Persistence algorithms when saving and restoring XML documents. There are internal checks to ensure validity when processing every type of data.
1756
dba69de2 1757### Management of Namespaces
1758
4ee1bdf4 1759Both the XML format and the XML OCAF persistence code are extensible in the sense that every new development can reuse everything that has been created in previous projects. For the XML format, this extensibility is supported by assigning names of XML objects (elements) to different XML Namespaces. Hence, XML elements defined in different projects (in different persistence libraries) can easily be combined into the same XML documents. An example is the XCAF XML persistence built as an extension to the Standard OCAF XML persistence <i>[File XmlXcaf.xsd]</i>. For the correct management of Namespaces it is necessary to:
dba69de2 1760* Define *targetNamespace* in the new XSD file describing the format.
4ee1bdf4 1761* Declare (in *XSD* files) all elements and types in the targetNamespace to appear without a namespace prefix; all other elements and types use the appropriate prefix (such as "ocaf:").
dba69de2 1762* Add (in the new *DocumentStorageDriver*) the *targetNamespace* accompanied with its prefix, using method *XmlDrivers_DocumentStorageDriver::AddNamespace*. The same is done for all namespaces objects which are used by the new persistence, with the exception of the "ocaf" namespace.
1763* Pass (in every OCAF attribute driver) the namespace prefix of the *targetNamespace* to the constructor of *XmlMDF_ADriver*.
27245ff9 1764
72b7576f 1765@section occt_ocaf_10 GLOSSARY
1766
3f812249 1767* **Application** -- a document container holding all documents containing all application data.
1768* **Application data** -- the data produced by an application, as opposed to data referring to it.
1769* **Associativity of data** -- the ability to propagate modifications made to one document to other documents, which refer to such document. Modification propagation is:
72b7576f 1770 * unidirectional, that is, from the referenced to the referencing document(s), or
1771 * bi-directional, from the referencing to the referenced document and vice-versa.
3f812249 1772* **Attribute** -- a container for application data. An attribute is attached to a label in the hierarchy of the data framework.
1773* **Child** -- a label created from another label, which by definition, is the father label.
1774* **Compound document** -- a set of interdependent documents, linked to each other by means of external references. These references provide the associativity of data.
1775* **Data framework** -- a tree-like data structure which in OCAF, is a tree of labels with data attached to them in the form of attributes. This tree of labels is accessible through the services of the *TDocStd_Document* class.
1776* **Document** -- a container for a data framework which grants access to the data, and is, in its turn, contained by an application. A document also allows you to:
dba69de2 1777 * Manage modifications, providing Undo and Redo functions
1778 * Manage command transactions
1779 * Update external links
1780 * Manage save and restore options
1781 * Store the names of software extensions.
3f812249 1782* **Driver** -- an abstract class, which defines the communications protocol with a system.
1783* **Entry** -- an ASCII character string containing the tag list of a label. For example:
72b7576f 1784~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
17850:3:24:7:2:7
1786~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1787
3f812249 1788* **External links** -- references from one data structure to another data structure in another document.
72b7576f 1789To store these references properly, a label must also contain an external link attribute.
3f812249 1790* **Father** -- a label, from which other labels have been created. The other labels are, by definition, the children of this label.
1791* **Framework** -- a group of co-operating classes which enable a design to be re-used for a given category of problem. The framework guides the architecture of the application by breaking it up into abstract classes, each of which has different responsibilities and collaborates in a predefined way. Application developer creates a specialized framework by:
72b7576f 1792 * defining new classes which inherit from these abstract classes
1793 * composing framework class instances
1794 * implementing the services required by the framework.
1795
1796In C++, the application behavior is implemented in virtual functions redefined in these derived classes. This is known as overriding.
1797
3f812249 1798* **GUID** -- Global Universal ID. A string of 37 characters intended to uniquely identify an object. For example:
72b7576f 1799~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
18002a96b602-ec8b-11d0-bee7-080009dc3333
1801~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1802
3f812249 1803* **Label** -- a point in the data framework, which allows data to be attached to it by means of attributes. It has a name in the form of an entry, which identifies its place in the data framework.
1804* **Modified label** -- containing attributes whose data has been modified.
1805* **Reference key** -- an invariant reference, which may refer to any type of data used in an application. In its transient form, it is a label in the data framework, and the data is attached to it in the form of attributes. In its persistent form, it is an entry of the label. It allows an application to recover any entity in the current session or in a previous session.
1806* **Resource file** -- a file containing a list of each document’s schema name and the storage and retrieval plug-ins for that document.
1807* **Root** -- the starting point of the data framework. This point is the top label in the framework. It is represented by the [0] entry and is created at the same time with the document you are working on.
1808* **Scope** -- the set of all the attributes and labels which depend on a given label.
1809* **Tag list** -- a list of integers, which identify the place of a label in the data framework. This list is displayed in an entry.
1810* **Topological naming** -- systematic referencing of topological entities so that these entities can still be identified after the models they belong to have gone through several steps in modeling. In other words, topological naming allows you to track entities through the steps in the modeling process. This referencing is needed when a model is edited and regenerated, and can be seen as a mapping of labels and name attributes of the entities in the old version of a model to those of the corresponding entities in its new version. Note that if the topology of a model changes during the modeling, this mapping may not fully coincide. A Boolean operation, for example, may split edges.
1811* **Topological tracking** -- following a topological entity in a model through the steps taken to edit and regenerate that model.
1812* **Valid label** -- in a data framework, this is a label, which is already recomputed in the scope of regeneration sequence and includes the label containing a feature which is to be recalculated. Consider the case of a box to which you first add a fillet, then a protrusion feature. For recalculation purposes, only valid labels of each construction stage are used. In recalculating a fillet, they are only those of the box and the fillet, not the protrusion feature which was added afterwards.
72b7576f 1813
dba69de2 1814@section occt_ocaf_11 Samples
27245ff9 1815
1816@subsection occt_ocaf_11_a Getting Started
1817
1818 At the beginning of your development, you first define an application class by inheriting from the Application abstract class.
1819 You only have to create and determine the resources of the application
1820 for specifying the format of your documents (you generally use the standard one) and their file extension.
1821
1822 Then, you design the application data model by organizing attributes you choose among those provided with OCAF.
1823 You can specialize these attributes using the User attribute. For example, if you need a reflection coefficient,
1824 you aggregate a User attribute identified as a reflection coefficient
1825 with a Real attribute containing the value of the coefficient (as such, you don't define a new class).
1826
1827 If you need application specific data not provided with OCAF, for example,
1828 to incorporate a finite element model in the data structure,
1829 you define a new attribute class containing the mesh,
1830 and you include its persistent homologue in a new file format.
1831
1832 Once you have implemented the commands which create and modify the data structure
1833 according to your specification, OCAF provides you, without any additional programming:
1834
1835 * Persistent reference to any data, including geometric elements — several documents can be linked with such reference;
1836 * Document-View association;
1837 * Ready-to-use functions such as :
1838 * Undo-redo;
1839 * Save and open application data.
1840
1841 Finally, you develop the application's graphical user interface using the toolkit of your choice, for example:
1842 * KDE Qt or GNOME GTK+ on Linux;
1843 * Microsoft Foundation Classes (MFC) on Windows Motif on Sun;
1844 * Other commercial products such as Ilog Views.
1845
1846 You can also implement the user interface in the Java language using
1847 the Swing-based Java Application Desktop component (JAD) provided with OCAF.
1848
d3013f55 1849@subsection occt_ocaf_11_1 Implementation of Attribute Transformation in a HXX file
72b7576f 1850
1851~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
6fe96f84 1852#include <TDF_Attribute.hxx>
72b7576f 1853
6fe96f84 1854#include <gp_Ax3.hxx>
1855#include <gp_Pnt.hxx>
1856#include <gp_Vec.hxx>
1857#include <gp_Trsf.hxx>
72b7576f 1858
6fe96f84 1859// This attribute implements a transformation data container
d3013f55 1860class MyPackage_Transformation : public TDF_Attribute
1861{
1862public:
6fe96f84 1863 //!@ name Static methods
72b7576f 1864
d3013f55 1865 //! The method returns a unique GUID of this attribute.
1866 //! By means of this GUID this attribute may be identified
1867 //! among other attributes attached to the same label.
1868 Standard_EXPORT static const Standard_GUID& GetID ();
72b7576f 1869
d3013f55 1870 //! Finds or creates the attribute attached to <theLabel>.
1871 //! The found or created attribute is returned.
1872 Standard_EXPORT static Handle(MyPackage_Transformation) Set (const TDF_Label theLabel);
72b7576f 1873
6fe96f84 1874 //!@ name Methods for access to the attribute data
d3013f55 1875
1876 //! The method returns the transformation.
1877 Standard_EXPORT gp_Trsf Get () const;
dba69de2 1878
6fe96f84 1879 //!@ name Methods for setting the data of transformation
dba69de2 1880
d3013f55 1881 //! The method defines a rotation type of transformation.
1882 Standard_EXPORT void SetRotation (const gp_Ax1& theAxis, Standard_Real theAngle);
dba69de2 1883
d3013f55 1884 //! The method defines a translation type of transformation.
1885 Standard_EXPORT void SetTranslation (const gp_Vec& theVector);
dba69de2 1886
d3013f55 1887 //! The method defines a point mirror type of transformation (point symmetry).
1888 Standard_EXPORT void SetMirror (const gp_Pnt& thePoint);
dba69de2 1889
d3013f55 1890 //! The method defines an axis mirror type of transformation (axial symmetry).
1891 Standard_EXPORT void SetMirror (const gp_Ax1& theAxis);
dba69de2 1892
d3013f55 1893 //! The method defines a point mirror type of transformation (planar symmetry).
1894 Standard_EXPORT void SetMirror (const gp_Ax2& thePlane);
dba69de2 1895
d3013f55 1896 //! The method defines a scale type of transformation.
1897 Standard_EXPORT void SetScale (const gp_Pnt& thePoint, Standard_Real theScale);
dba69de2 1898
d3013f55 1899 //! The method defines a complex type of transformation from one co-ordinate system to another.
1900 Standard_EXPORT void SetTransformation (const gp_Ax3& theCoordinateSystem1, const gp_Ax3& theCoordinateSystem2);
dba69de2 1901
6fe96f84 1902 //!@ name Overridden methods from TDF_Attribute
d3013f55 1903
1904 //! The method returns a unique GUID of the attribute.
1905 //! By means of this GUID this attribute may be identified among other attributes attached to the same label.
1906 Standard_EXPORT const Standard_GUID& ID () const;
dba69de2 1907
d3013f55 1908 //! The method is called on Undo / Redo.
1909 //! It copies the content of theAttribute into this attribute (copies the fields).
1910 Standard_EXPORT void Restore (const Handle(TDF_Attribute)& theAttribute);
dba69de2 1911
d3013f55 1912 //! It creates a new instance of this attribute.
1913 //! It is called on Copy / Paste, Undo / Redo.
1914 Standard_EXPORT Handle(TDF_Attribute) NewEmpty () const;
dba69de2 1915
d3013f55 1916 //! The method is called on Copy / Paste.
1917 //! It copies the content of this attribute into theAttribute (copies the fields).
1918 Standard_EXPORT void Paste (const Handle(TDF_Attribute)& theAttribute, const Handle(TDF_RelocationTable)& theRelocationTable);
dba69de2 1919
d3013f55 1920 //! Prints the content of this attribute into the stream.
1921 Standard_EXPORT Standard_OStream& Dump(Standard_OStream& theOS);
dba69de2 1922
6fe96f84 1923 //!@ name Constructor
dba69de2 1924
d3013f55 1925 //! The C++ constructor of this atribute class.
1926 //! Usually it is never called outside this class.
1927 Standard_EXPORT MyPackage_Transformation();
1928
1929private:
1930 gp_TrsfForm myType;
72b7576f 1931
d3013f55 1932 // Axes (Ax1, Ax2, Ax3)
1933 gp_Ax1 myAx1;
1934 gp_Ax2 myAx2;
1935 gp_Ax3 myFirstAx3;
1936 gp_Ax3 mySecondAx3;
72b7576f 1937
d3013f55 1938 // Scalar values
1939 Standard_Real myAngle;
1940 Standard_Real myScale;
1941
1942 // Points
1943 gp_Pnt myFirstPoint;
1944 gp_Pnt mySecondPoint;
1945};
72b7576f 1946~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1947
dba69de2 1948@subsection occt_ocaf_11_2 Implementation of Attribute Transformation in a CPP file
1949
72b7576f 1950~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
6fe96f84 1951#include <MyPackage_Transformation.hxx>
72b7576f 1952
1953//=======================================================================
1954//function : GetID
dba69de2 1955//purpose : The method returns a unique GUID of this attribute.
1956// By means of this GUID this attribute may be identified
1957// among other attributes attached to the same label.
72b7576f 1958//=======================================================================
1959const Standard_GUID& MyPackage_Transformation::GetID()
1960{
dba69de2 1961 static Standard_GUID ID("4443368E-C808-4468-984D-B26906BA8573");
1962 return ID;
72b7576f 1963}
1964
1965//=======================================================================
1966//function : Set
dba69de2 1967//purpose : Finds or creates the attribute attached to <theLabel>.
1968// The found or created attribute is returned.
72b7576f 1969//=======================================================================
1970Handle(MyPackage_Transformation) MyPackage_Transformation::Set(const TDF_Label& theLabel)
1971{
dba69de2 1972 Handle(MyPackage_Transformation) T;
1973 if (!theLabel.FindAttribute(MyPackage_Transformation::GetID(), T))
1974 {
1975 T = new MyPackage_Transformation();
1976 theLabel.AddAttribute(T);
1977 }
1978 return T;
72b7576f 1979}
1980
1981//=======================================================================
1982//function : Get
dba69de2 1983//purpose : The method returns the transformation.
72b7576f 1984//=======================================================================
1985gp_Trsf MyPackage_Transformation::Get() const
1986{
dba69de2 1987 gp_Trsf transformation;
1988 switch (myType)
1989 {
1990 case gp_Identity:
1991 {
1992 break;
1993 }
1994 case gp_Rotation:
1995 {
1996 transformation.SetRotation(myAx1, myAngle);
1997 break;
1998 }
1999 case gp_Translation:
2000 {
2001 transformation.SetTranslation(myFirstPoint, mySecondPoint);
2002 break;
2003 }
2004 case gp_PntMirror:
2005 {
2006 transformation.SetMirror(myFirstPoint);
2007 break;
2008 }
2009 case gp_Ax1Mirror:
2010 {
2011 transformation.SetMirror(myAx1);
2012 break;
2013 }
2014 case gp_Ax2Mirror:
2015 {
2016 transformation.SetMirror(myAx2);
2017 break;
2018 }
2019 case gp_Scale:
2020 {
2021 transformation.SetScale(myFirstPoint, myScale);
2022 break;
2023 }
2024 case gp_CompoundTrsf:
2025 {
2026 transformation.SetTransformation(myFirstAx3, mySecondAx3);
2027 break;
2028 }
2029 case gp_Other:
2030 {
2031 break;
2032 }
2033 }
2034 return transformation;
72b7576f 2035}
2036
2037//=======================================================================
2038//function : SetRotation
dba69de2 2039//purpose : The method defines a rotation type of transformation.
72b7576f 2040//=======================================================================
2041void MyPackage_Transformation::SetRotation(const gp_Ax1& theAxis, const Standard_Real theAngle)
2042{
dba69de2 2043 Backup();
2044 myType = gp_Rotation;
2045 myAx1 = theAxis;
2046 myAngle = theAngle;
72b7576f 2047}
2048
2049//=======================================================================
2050//function : SetTranslation
dba69de2 2051//purpose : The method defines a translation type of transformation.
72b7576f 2052//=======================================================================
2053void MyPackage_Transformation::SetTranslation(const gp_Vec& theVector)
2054{
dba69de2 2055 Backup();
2056 myType = gp_Translation;
2057 myFirstPoint.SetCoord(0, 0, 0);
2058 mySecondPoint.SetCoord(theVector.X(), theVector.Y(), theVector.Z());
72b7576f 2059}
2060
2061//=======================================================================
2062//function : SetMirror
dba69de2 2063//purpose : The method defines a point mirror type of transformation
2064// (point symmetry).
72b7576f 2065//=======================================================================
2066void MyPackage_Transformation::SetMirror(const gp_Pnt& thePoint)
2067{
dba69de2 2068 Backup();
2069 myType = gp_PntMirror;
2070 myFirstPoint = thePoint;
72b7576f 2071}
2072
2073//=======================================================================
2074//function : SetMirror
dba69de2 2075//purpose : The method defines an axis mirror type of transformation
2076// (axial symmetry).
72b7576f 2077//=======================================================================
2078void MyPackage_Transformation::SetMirror(const gp_Ax1& theAxis)
2079{
dba69de2 2080 Backup();
2081 myType = gp_Ax1Mirror;
2082 myAx1 = theAxis;
72b7576f 2083}
2084
2085//=======================================================================
2086//function : SetMirror
dba69de2 2087//purpose : The method defines a point mirror type of transformation
2088// (planar symmetry).
72b7576f 2089//=======================================================================
2090void MyPackage_Transformation::SetMirror(const gp_Ax2& thePlane)
2091{
dba69de2 2092 Backup();
2093 myType = gp_Ax2Mirror;
2094 myAx2 = thePlane;
72b7576f 2095}
2096
2097//=======================================================================
2098//function : SetScale
dba69de2 2099//purpose : The method defines a scale type of transformation.
72b7576f 2100//=======================================================================
2101void MyPackage_Transformation::SetScale(const gp_Pnt& thePoint, const Standard_Real theScale)
2102{
dba69de2 2103 Backup();
2104 myType = gp_Scale;
2105 myFirstPoint = thePoint;
2106 myScale = theScale;
72b7576f 2107}
2108
2109//=======================================================================
2110//function : SetTransformation
dba69de2 2111//purpose : The method defines a complex type of transformation
2112// from one co-ordinate system to another.
72b7576f 2113//=======================================================================
2114void MyPackage_Transformation::SetTransformation(const gp_Ax3& theCoordinateSystem1,
dba69de2 2115 const gp_Ax3& theCoordinateSystem2)
72b7576f 2116{
dba69de2 2117 Backup();
2118 myFirstAx3 = theCoordinateSystem1;
2119 mySecondAx3 = theCoordinateSystem2;
72b7576f 2120}
2121
2122//=======================================================================
2123//function : ID
dba69de2 2124//purpose : The method returns a unique GUID of the attribute.
2125// By means of this GUID this attribute may be identified
2126// among other attributes attached to the same label.
72b7576f 2127//=======================================================================
2128const Standard_GUID& MyPackage_Transformation::ID() const
2129{
dba69de2 2130 return GetID();
72b7576f 2131}
2132
2133//=======================================================================
2134//function : Restore
dba69de2 2135//purpose : The method is called on Undo / Redo.
2136// It copies the content of <theAttribute>
2137// into this attribute (copies the fields).
72b7576f 2138//=======================================================================
2139void MyPackage_Transformation::Restore(const Handle(TDF_Attribute)& theAttribute)
2140{
dba69de2 2141 Handle(MyPackage_Transformation) theTransformation = Handle(MyPackage_Transformation)::DownCast(theAttribute);
2142 myType = theTransformation->myType;
2143 myAx1 = theTransformation->myAx1;
2144 myAx2 = theTransformation->myAx2;
2145 myFirstAx3 = theTransformation->myFirstAx3;
2146 mySecondAx3 = theTransformation->mySecondAx3;
2147 myAngle = theTransformation->myAngle;
2148 myScale = theTransformation->myScale;
2149 myFirstPoint = theTransformation->myFirstPoint;
2150 mySecondPoint = theTransformation->mySecondPoint;
72b7576f 2151}
2152
2153//=======================================================================
2154//function : NewEmpty
dba69de2 2155//purpose : It creates a new instance of this attribute.
2156// It is called on Copy / Paste, Undo / Redo.
72b7576f 2157//=======================================================================
2158Handle(TDF_Attribute) MyPackage_Transformation::NewEmpty() const
dba69de2 2159{
2160 return new MyPackage_Transformation();
72b7576f 2161}
2162
2163//=======================================================================
2164//function : Paste
dba69de2 2165//purpose : The method is called on Copy / Paste.
2166// It copies the content of this attribute into
2167// <theAttribute> (copies the fields).
72b7576f 2168//=======================================================================
2169void MyPackage_Transformation::Paste(const Handle(TDF_Attribute)& theAttribute,
dba69de2 2170 const Handle(TDF_RelocationTable)& ) const
72b7576f 2171{
dba69de2 2172 Handle(MyPackage_Transformation) theTransformation = Handle(MyPackage_Transformation)::DownCast(theAttribute);
2173 theTransformation->myType = myType;
2174 theTransformation->myAx1 = myAx1;
2175 theTransformation->myAx2 = myAx2;
2176 theTransformation->myFirstAx3 = myFirstAx3;
2177 theTransformation->mySecondAx3 = mySecondAx3;
2178 theTransformation->myAngle = myAngle;
2179 theTransformation->myScale = myScale;
2180 theTransformation->myFirstPoint = myFirstPoint;
2181 theTransformation->mySecondPoint = mySecondPoint;
72b7576f 2182}
2183
2184//=======================================================================
2185//function : Dump
dba69de2 2186//purpose : Prints the content of this attribute into the stream.
72b7576f 2187//=======================================================================
2188Standard_OStream& MyPackage_Transformation::Dump(Standard_OStream& anOS) const
dba69de2 2189{
2190 anOS = "Transformation: ";
2191 switch (myType)
2192 {
2193 case gp_Identity:
2194 {
2195 anOS = "gp_Identity";
2196 break;
2197 }
2198 case gp_Rotation:
2199 {
2200 anOS = "gp_Rotation";
2201 break;
2202 }
2203 case gp_Translation:
2204 {
2205 anOS = "gp_Translation";
2206 break;
2207 }
2208 case gp_PntMirror:
2209 {
2210 anOS = "gp_PntMirror";
2211 break;
2212 }
2213 case gp_Ax1Mirror:
2214 {
2215 anOS = "gp_Ax1Mirror";
2216 break;
2217 }
2218 case gp_Ax2Mirror:
2219 {
2220 anOS = "gp_Ax2Mirror";
2221 break;
2222 }
2223 case gp_Scale:
2224 {
2225 anOS = "gp_Scale";
2226 break;
2227 }
2228 case gp_CompoundTrsf:
2229 {
2230 anOS = "gp_CompoundTrsf";
2231 break;
2232 }
2233 case gp_Other:
2234 {
2235 anOS = "gp_Other";
2236 break;
2237 }
2238 }
2239 return anOS;
72b7576f 2240}
2241
2242//=======================================================================
2243//function : MyPackage_Transformation
dba69de2 2244//purpose : A constructor.
72b7576f 2245//=======================================================================
2246MyPackage_Transformation::MyPackage_Transformation():myType(gp_Identity){
2247
2248}
dba69de2 2249~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2250
2251@subsection occt_ocaf_11_3 Implementation of typical actions with standard OCAF attributes.
2252
ba06f8bb 2253There are four sample files provided in the directory 'OpenCasCade/ros/samples/ocafsamples'. They present typical actions with OCAF services (mainly for newcomers).
dba69de2 2254The method *Sample()* of each file is not dedicated for execution 'as is', it is rather a set of logical actions using some OCAF services.
2255
2256### TDataStd_Sample.cxx
2257This sample contains templates for typical actions with the following standard OCAF attributes:
2258- Starting with data framework;
2259- TDataStd_Integer attribute management;
2260- TDataStd_RealArray attribute management;
2261- TDataStd_Comment attribute management;
2262- TDataStd_Name attribute management;
2263- TDataStd_UAttribute attribute management;
2264- TDF_Reference attribute management;
2265- TDataXtd_Point attribute management;
2266- TDataXtd_Plane attribute management;
2267- TDataXtd_Axis attribute management;
2268- TDataXtd_Geometry attribute management;
2269- TDataXtd_Constraint attribute management;
2270- TDataStd_Directory attribute management;
2271- TDataStd_TreeNode attribute management.
2272
2273### TDocStd_Sample.cxx
2274This sample contains template for the following typical actions:
2275- creating application;
2276- creating the new document (document contains a framework);
2277- retrieving the document from a label of its framework;
2278- filling a document with data;
2279- saving a document in the file;
2280- closing a document;
2281- opening the document stored in the file;
2282- copying content of a document to another document with possibility to update the copy in the future.
2283
2284### TPrsStd_Sample.cxx
2285This sample contains template for the following typical actions:
2286- starting with data framework;
2287- setting the TPrsStd_AISViewer in the framework;
2288- initialization of aViewer;
2289- finding TPrsStd_AISViewer attribute in the DataFramework;
2290- getting AIS_InteractiveContext from TPrsStd_AISViewer;
2291- adding driver to the map of drivers;
2292- getting driver from the map of drivers;
ba06f8bb 2293- setting TNaming_NamedShape to \<ShapeLabel\>;
2294- setting the new TPrsStd_AISPresentation to \<ShapeLabel\>;
dba69de2 2295- displaying;
2296- erasing;
2297- updating and displaying presentation of the attribute to be displayed;
2298- setting a color to the displayed attribute;
2299- getting transparency of the displayed attribute;
2300- modify attribute;
2301- updating presentation of the attribute in viewer.
2302
2303### TNaming_Sample.cxx
2304This sample contains template for typical actions with OCAF Topological Naming services.
2305The following scenario is used:
2306- data framework initialization;
2307- creating Box1 and pushing it as PRIMITIVE in DF;
2308- creating Box2 and pushing it as PRIMITIVE in DF;
2309- moving Box2 (applying a transformation);
2310- pushing the selected edges of the top face of Box1 in DF;
2311- creating a Fillet (using the selected edges) and pushing the result as a modification of Box1;
2312- creating a Cut (Box1, Box2) as a modification of Box1 and push it in DF;
2313- recovering the result from DF.
2314