0026478: There is a lack of documentation on OCAF / Topological naming
[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
10and its applications, see our offerings on our web site at
11<a href="http://www.opencascade.org/support/training/">www.opencascade.org/support/training/</a>
12
13OCAF (the Open CASCADE Application Framework) is a RAD (Rapid Application Development) framework used for
14specifying and organizing application data. To do this, OCAF provides:
15
16 * Ready-to-use data common to most CAD/CAM applications,
17 * A scalable extension protocol for implementing new application specific data,
18 * An infrastructure
19 * To attach any data to any topological element
20 * To link data produced by different applications (*associativity of data*)
21 * To register the modeling process - the creation history, or parametrics, used to carry out the modifications.
22
23Using OCAF, the application designer concentrates on the functionality and its specific algorithms. In this way, he avoids architectural problems notably implementing Undo-redo and saving application data.
24
25In OCAF, all of the above are already handled for the application designer, allowing him to reach a significant increase in productivity.
26
27In this respect, OCAF 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 a logical supplement to these libraries.
28
29The table below contrasts the design of a modeling application using object libraries alone and using OCAF.
30
31**Table 1: Services provided by OCAF**
32
33|Development tasks |Comments | Without OCAF | With OCAF |
34|------------------:|---------:|---------------:|-----------:|
35|Creation of geometry| Algorithm Calling the modeling libraries | To be created by the user | To be created by the user|
36| Data organization | Including specific attributes and modeling process | To be created by the user | Simplified|
37| Saving data in a file | Notion of document | To be created by the user | Provided |
38| Document-view management | | To be created by the user | Provided |
39| Application infrastructure | New, Open, Close, Save and Save As File menus | To be created by the user | Provided |
40| Undo-Redo | Robust, multi-level | To be created by the user | Provided |
41| Application-specific dialog boxes | | To be created by the user | To be created by the user |
42
43
44
45The relationship between OCAF and the Open CASCADE Technology (**OCCT**) Object Libraries can be seen in the image below.
46
3d68eaf5 47@figure{/user_guides/ocaf/images/ocaf_image003.svg, "OCAF Architecture"}
72b7576f 48
49In 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.
50
51The subsequent chapters of this document explain the concepts and show how to use the services of OCAF.
52
53@section occt_ocaf_2 Basic Concepts
54
55@subsection occt_ocaf_2_1 Overview
56
57In most existing geometric modeling systems, the data structure is shape driven. They usually use a brep model, where solids and surfaces are defined by a collection of entities such as faces, edges etc., and by attributes such as application data. These attributes are attached to the entities. Examples of application data include:
58
59 * color,
60 * material,
61 * information that a particular edge is blended.
62
63A shape, however, is inevitably tied to its underlying geometry. And geometry is highly subject to change in applications such as parametric modeling or product development. In this sort of application, using a brep (boundary representation) data structure proves to be a not very effective solution. A solution other than the shape must be found, i.e. a solution where attributes are attached to a deeper invariant structure of the model. Here, the topology itself will be one attribute among many.
64
65In OCAF, data structure is reference key-driven. The reference key is implemented in the form of labels. Application data is attached to these labels as attributes. By means of these labels and a tree structure they are organized in, the reference key aggregates all user data, not just shapes and their geometry. These attributes have similar importance; no attribute is master in respect of the others.
66
67The reference keys of a model - in the form of labels - have to be kept together in a single container. This container is called a document.
68
dba69de2 69@image html /user_guides/ocaf/images/ocaf_image004.png "Topology-driven vs. reference key-driven approaches"
70@image latex /user_guides/ocaf/images/ocaf_image004.png "Topology-driven vs. reference key-driven approaches"
72b7576f 71
72@subsection occt_ocaf_2_2 Applications and documents
73
74OCAF documents are in turn managed by an OCAF application, which is in charge of:
75
76 * Creating new documents
77 * Saving documents and opening them
78 * Initializing document views.
79
80Apart 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.
81
3d68eaf5 82@subsection occt_ocaf_2_3 The document and the data framework
72b7576f 83
84Inside a document, there is a data framework, a model, for example. This is a set of labels organized in a tree structure characterized by the following features:
85 * The first label in a framework is the root of the tree;
86 * Each label has a tag expressed as an integer value;
87 * Sub-labels of a label are called its children;
88 * Each label which is not the root has one father – label from an upper level of the framework;
89 * Labels which have the same father are called brothers;
90 * Brothers cannot share the same tag;
91 * A label is uniquely defined by an entry expressed as a list of tags (entry) of fathers from the root: this list of tags is written from right to left: tag of label, tag of its father, tag of father of its father,..., 0 (tag of the root label).
92
dba69de2 93@image html /user_guides/ocaf/images/ocaf_image005.png "A simple framework model"
94@image latex /user_guides/ocaf/images/ocaf_image005.png "A simple framework model"
72b7576f 95
96In the above figure inside the circles are the tags of corresponding labels. Under the circles are the lists of tags. The root label always has a zero tag.
97
98The children of a root label are middle-level labels with tags 1 and 3. These labels are brothers.
99
dba69de2 100List 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 101
102For example, an application for designing table lamps will first allocate a label for the lamp unit (the lamp is illustrated below). The root label never has brother labels, so, for a lot of lamps in the framework allocation, one of the root label sub-labels for the lamp unit is used. By doing so, you would avoid any confusion between table lamps in the data framework. Parts of the lamp have different material, color and other attributes, so, for each sub-unit of the lamp a child label of the lamp label with specified tags is allocated:
103
104 * a lamp-shade label with tag 1
105 * a bulb label with tag 2
106 * a stem label with tag 3
107
108Label tags are chosen at will. They are just identifiers of the lamp parts. Now you can refine all units: set to the specified label geometry, color, material and other information about the lamp or it’s parts. This information is placed into special attributes of the label: the pure label contains no data – it is only a key to access data.
109
110The thing to remember is 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 what you wanted to use in your design, the part name could be integrated into the framework as an attribute.
111
dba69de2 112@image html /user_guides/ocaf/images/ocaf_image006.png
113@image latex /user_guides/ocaf/images/ocaf_image006.png
72b7576f 114
115So, 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.
116
dba69de2 117@image html /user_guides/ocaf/images/ocaf_image007.png
118@image latex /user_guides/ocaf/images/ocaf_image007.png
72b7576f 119
120
121The 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.
122
123The 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.
124
125Note that the root label can have attributes too, usually global attributes: the name of the document, for example.
126
dba69de2 127As in the case of the table lamp example above, OCAF documents aggregate a battery of ready-to-use attributes, which represent typical data used in CAD. This data includes not only the Shape attribute, but a wide range of Standard attributes corresponding to the following types:
72b7576f 128
129 * Geometric attributes
130 * General attributes
131 * Relationship attributes
132 * Auxiliary attributes
133
134@subsubsection occt_ocaf_2_3_1 Documents
135
136Documents offer access to the data framework and manage the following items:
137
138 * Manage the notification of changes
139 * Update external links
140 * Manage the saving and restoring of data
141 * Store the names of software extensions.
142 * Manage command transactions
143 * Manage Undo and Redo options.
144
145@subsubsection occt_ocaf_2_3_2 Shape attribute
146
147The shape attribute implements the functionality of the OCCT topology manipulation:
72b7576f 148 * reference to the shapes
149 * tracking of shape evolution
150
151@subsubsection occt_ocaf_2_3_3 Standard attributes
152
153Several ready-to-use base attributes already exist. These 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)....
154
155@subsubsection occt_ocaf_2_3_4 Visualization attributes
156
157These 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.
158
159@subsubsection occt_ocaf_2_3_5 Function services
160
161Where 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.
162
dba69de2 163@image html /user_guides/ocaf/images/ocaf_image008.png "Document structure"
164@image latex /user_guides/ocaf/images/ocaf_image008.png "Document structure"
72b7576f 165
e2b55410 166
dba69de2 167@section occt_ocaf_3 Data Framework Services
72b7576f 168
169@subsection occt_ocaf_3_1 Overview
170
171The data framework offers a single environment in which data from different application components can be handled.
172
173This allows you to exchange and modify data simply, consistently, with a maximum level of information, and with stable semantics.
174
175The building blocks of this approach are:
176
177 * The tag
178 * The label
179 * The attribute
180
181As 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.
182
183Each 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.
184
185The 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.
186
187The most important property is that a label’s entry is its persistent address in the data framework.
188
dba69de2 189@image html /user_guides/ocaf/images/ocaf_image009.png "Contents of a document"
190@image latex /user_guides/ocaf/images/ocaf_image009.png "Contents of a document"
72b7576f 191
192@subsection occt_ocaf_3_2 The Tag
193
194A tag is an integer, which identifies a label in two ways:
195
196 * Relative identification
197 * Absolute identification.
198
199In 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.
200
dba69de2 201In 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 202
203In 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.
204
205The tag can be created in two ways:
206
207 * Random delivery
208 * User-defined delivery
209
210As 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.
211
212@subsubsection occt_ocaf_3_2_1 Creating child labels using random delivery of tags
213
dba69de2 214To 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*.
215
72b7576f 216
72b7576f 217~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
218TDF_Label child1 = TDF_TagSource::NewChild (level2);
219TDF_Label child2 = TDF_TagSource::NewChild (level2);
220~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221
222@subsubsection occt_ocaf_3_2_2 Creation of a child label by user delivery from a tag
223
224The 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.
225
dba69de2 226To 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.
227
72b7576f 228
72b7576f 229~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230TDF_Label achild = root.FindChild(3,Standard_False);
231if (!achild.IsNull()) {
232Standard_Integer tag = achild.Tag();
233}
234~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235
236@subsection occt_ocaf_3_3 The Label
237
238The 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 (refer to the following figure):
239
dba69de2 240@image html /user_guides/ocaf/images/ocaf_image007.png
241@image latex /user_guides/ocaf/images/ocaf_image007.png
72b7576f 242
243
244Label 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.
245
246@subsubsection occt_ocaf_3_3_1 Label creation
247
dba69de2 248Labels 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 249
250@subsubsection occt_ocaf_3_3_2 Creating child labels
251
dba69de2 252To create a new child label in the data framework using explicit delivery of tags, use *TDF_Label::FindChild*.
253
72b7576f 254
72b7576f 255~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
256//creating a label with tag 10 at Root
257TDF_Label lab1 = aDF->Root().FindChild(10);
258
259//creating labels 7 and 2 on label 10
260TDF_Label lab2 = lab1.FindChild(7);
261
262TDF_Label lab3 = lab1.FindChild(2);
263~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 264You 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.
265
72b7576f 266
72b7576f 267~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
268TDF_Label level1 = root.FindChild(3,Standard_True);
269TDF_Label level2 = level1.FindChild(1,Standard_True);
270~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
271@subsubsection occt_ocaf_3_3_3 Retrieving child labels
272
273You can retrieve child labels of your current label by iteration on the first level in the scope of this label.
274
dba69de2 275
72b7576f 276~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
277TDF_Label current;
278//
279for (TDF_ChildIterator it1 (current,Standard_False); it1.More(); it1.Next()) {
280achild = it1.Value();
281//
282// do something on a child (level 1)
283//
284}
285~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
286You 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.
287~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
288for (TDF_ChildIterator itall (current,Standard_True); itall.More(); itall.Next()) {
289achild = itall.Value();
290//
291// do something on a child (all levels)
292//
293}
294~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 295Using *TDF_Tool::Entry* with *TDF_ChildIterator* you can retrieve the entries of your current label’s child labels as well.
72b7576f 296
dba69de2 297
72b7576f 298~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
299void DumpChildren(const TDF_Label& aLabel)
300{
301 TDF_ChildIterator it;
302 TCollection_AsciiString es;
303 for (it.Initialize(aLabel,Standard_True); it.More(); it.Next()){
304 TDF_Tool::Entry(it.Value(),es);
4ee1bdf4 305 cout << as.ToCString() << endl;
72b7576f 306 }
307}
308~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
309@subsubsection occt_ocaf_3_3_4 Retrieving the father label
310
311Retrieving the father label of a current label.
312
dba69de2 313
72b7576f 314~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
315TDF_Label father = achild.Father();
316isroot = father.IsRoot();
317~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
318@subsection occt_ocaf_3_4 The Attribute
319
320The 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.
321
dba69de2 322The 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 323
324@subsubsection occt_ocaf_3_4_1 Retrieving an attribute from a label
325
dba69de2 326To 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.
327
72b7576f 328
72b7576f 329~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
330if(current.FindAttribute(TDataStd_Integer::GetID(),INT))
331{
332 // the attribute is found
333}
334else
335{
336 // the attribute is not found
337}
338~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
339@subsubsection occt_ocaf_3_4_2 Identifying an attribute using a GUID
340
dba69de2 341You 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*.
342
72b7576f 343
72b7576f 344~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
345Handle(TDataStd_Integer) INT = new TDataStd_Integer();
346Standard_GUID guid = INT->ID();
347~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 348
72b7576f 349@subsubsection occt_ocaf_3_4_3 Attaching an attribute to a label
350
dba69de2 351To 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.
352
353*TDF_Attribute::Label* for *INT* then returns the label *attach* to which *INT* is attached.
72b7576f 354
72b7576f 355
72b7576f 356~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
357current.Add (INT); // INT is now attached to current
358current.Add (INT); // causes failure
359TDF_Label attach = INT->Label();
360~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
361@subsubsection occt_ocaf_3_4_4 Testing the attachment to a label
362
dba69de2 363You 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.
364
365*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 366
72b7576f 367
72b7576f 368~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
369// Testing of attribute attachment
370//
371if (current.IsA(TDataStd_Integer::GetID())) {
372// the label has an Integer attribute attached
373}
374if (current.HasAttribute()) {
375// the label has at least one attribute attached
376Standard_Integer nbatt = current.NbAttributes();
377// the label has nbatt attributes attached
378}
379~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
380@subsubsection occt_ocaf_3_4_5 Removing an attribute from a label
381
dba69de2 382To 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*.
383
72b7576f 384
72b7576f 385~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
386current.Forget(TDataStd_Integer::GetID());
387// integer attribute is now not attached to current label
388current.ForgetAll();
389// current has now 0 attributes attached
390~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
391@subsubsection occt_ocaf_3_4_6 Specific attribute creation
392
dba69de2 393If 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 394
dba69de2 395There 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 396
397In order to create a new attribute in the standard way do the following:
dba69de2 398* Create a class inherited from *TDF_Attribute* and implement all purely virtual and necessary virtual methods:
399 + **ID()** – returns a unique GUID of a given attribute
400 + **Restore(attribute)** – sets fields of this attribute equal to the fields of a given attribute of the same type
401 + **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 .
402 + **NewEmpty()** - returns a new attribute of this class with empty fields
403 + **Dump(stream)** - outputs information about a given attribute to a given stream debug (usually outputs an attribute of type string only)
72b7576f 404* Create the persistence classes for this attribute according to the file format chosen for the document (see below).
405
dba69de2 406Methods *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 407
408If you use a standard file format and you want your new attributes to be stored during document saving and retrieved to the data framework whenever a document is opened, you must do the following:
409
dba69de2 410 1. If you place an attribute to a new package, it is desirable (although not mandatory) if your package name starts with letter "T" (transient), for example: attribute *TMyAttributePackage_MyAttribute* in the package *TMyAttributePackage*.
411 2. Create a new package with name "P[package name]" (for example *PMyAttributePackage*) with class *PMyAttributePackage_MyAttribute* inside. The new class inherits the *PDF_Attribute* class and contains fields of attributes, which must be saved or retrieved ("P" - persistent).
412 3. Create a new package with name "M[package name]" (for example *MMyAttributePackage*) with classes *MMyAttributePackage_MyAttributeRetrievalDriver* and *MMyAttributePackage_MyAttributeStorageDriver* inside. The new classes inherit *MDF_ARDriver* and *MDF_ASDriver* classes respectively and contain the translation functionality: from T... attribute to P... and vice versa (M - middle) (see the realization of the standard attributes).
4ee1bdf4 413 4. M... package must contain *AddStorageDrivers(aDriverSeq : ASDriverHSequence* from MDF) and *AddRetrievalDrivers(aDriverSeq : ASDriverHSequence* from MDF) methods, which append to the given sequence of drivers *aDriverSeq*, which is a sequence of all new attribute drivers (see the previous point) used for the storage/retrieval of attributes.
dba69de2 414 5 Use the standard schema (*StdSchema* unit) or create a new one to add your P-package and compile it.
72b7576f 415
416If you use the XML format, do the following:
dba69de2 417 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).
418 2. Create a new package (or do it in the current one) with two package methods:
e2b55410 419 * *Factory*, which loads the document storage and retrieval drivers; and
420 * *AttributeDrivers*, which calls the methods AddDrivers for all packages responsible for persistence of the document.
dba69de2 421 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.
72b7576f 422If you use the binary format, do the following:
e2b55410 423 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 424 2. Create a new package (or do it in the current one) with two package methods:
425 * Factory, which loads the document storage and retrieval drivers; and
426 * AttributeDrivers, which calls the methods AddDrivers for all packages responsible for persistence of the document.
427 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.
428See <a href="#occt_ocaf_4_3_3">Saving the document</a> and <a href="#occt_ocaf_4_3_4">Opening the document from a file</a> for the description of document save/open mechanisms.
72b7576f 429
dba69de2 430If 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:
431 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).
432 2. Create child labels and allocate all necessary data through standard attributes at the child labels.
433 3. Define an interface class for access to the data of the child labels.
72b7576f 434
dba69de2 435Choosing 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 436
dba69de2 437Let’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 438
dba69de2 4391. The first way: creation of a new attribute. The implementation of the transformation by creation of a new attribute is represented in the <a href="#occt_ocaf_11">Samples</a>.
72b7576f 440
4412. 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 442 * Type of transformation <i>(gp_Translation)</i> as *TDataStd_Integer*;
443 * First point as *TDataStd_RealArray* (three values: X1, Y1 and Z1);
444 * Second point as *TDataStd_RealArray* (three values: X2, Y2 and Z2).
72b7576f 445
dba69de2 446@image html /user_guides/ocaf/images/ocaf_image010.png "Data tree for translation"
447@image latex /user_guides/ocaf/images/ocaf_image010.png "Data tree for translation"
72b7576f 448
449If the type of transformation is changed to rotation, the data tree looks like this:
e2b55410 450 * Type of transformation <i>(gp_Rotation)</i> as *TDataStd_Integer*;
451 * Point of axis of rotation as *TDataStd_RealArray* (three values: X, Y and Z);
452 * Axis of rotation as *TDataStd_RealArray* (three values: DX, DY and DZ);
453 * Angle of rotation as *TDataStd_Real*.
72b7576f 454
dba69de2 455@image html /user_guides/ocaf/images/ocaf_image011.png "Data tree for rotation"
456@image latex /user_guides/ocaf/images/ocaf_image011.png "Data tree for rotation"
72b7576f 457
e2b55410 458The 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).
72b7576f 459
460
461@section occt_ocaf_4_ Standard Document Services
462
463@subsection occt_ocaf_4_1 Overview
464
465Standard documents offer ready-to-use documents containing a TDF-based data framework. Each document can contain only one framework.
466
e2b55410 467The documents themselves are contained in the instantiation of a class inheriting from *TDocStd_Application*. This application manages the creation, storage and retrieval of documents.
72b7576f 468
469You 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.
470
471To sum up, standard documents alone provide access to the data framework. They also allow you to:
472
473 * Update external links
474 * Manage the saving and opening of data
475 * Manage the undo/redo functionality.
476
477
478@subsection occt_ocaf_4_2 The Application
479
dba69de2 480As 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 inheriting from *TDocStd_Application*.
72b7576f 481
482@subsubsection occt_ocaf_4_2_1 Creating an application
483
484To create an application, use the following syntax.
485
72b7576f 486~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
487Handle(TDocStd_Application) app
488= new MyApplication_Application ();
489~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 490Note that *MyApplication_Application* is a class, which you have to create and which will inherit from *TDocStd_Application*.
72b7576f 491
492@subsubsection occt_ocaf_4_2_2 Creating a new document
493
dba69de2 494To 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 495
72b7576f 496~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
497Handle(TDocStd_Document) doc;
498app->NewDocument("NewDocumentFormat", doc);
499~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 500
72b7576f 501@subsubsection occt_ocaf_4_2_3 Retrieving the application to which the document belongs
502
503To retrieve the application containing your document, you use the syntax below.
504
72b7576f 505~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
506app = Handle(TDocStd_Application)::DownCast
507(doc->Application());
508~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
509@subsection occt_ocaf_4_3 The Document
510
511The 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.
512
513@subsubsection occt_ocaf_4_3_1 Accessing the main label of the framework
514
dba69de2 515To 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 516
72b7576f 517~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
518TDF_Label label = doc->Main();
519~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
520@subsubsection occt_ocaf_4_3_2 Retrieving the document from a label in its framework
521
4ee1bdf4 522To 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 523~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
524doc = TDocStd_Document::Get(label);
525~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dba69de2 526
72b7576f 527@subsubsection occt_ocaf_4_3_3 Saving the document
528
4ee1bdf4 529If in your document you use only standard attributes (from the packages *TDF, TDataStd, TNaming, TFunction, TPrsStd* and *TDocStd*), you just do the following steps:
72b7576f 530
dba69de2 531* In your application class (which inherits class *TDocStd_Application*) implement two methods:
4ee1bdf4 532 + Formats (TColStd_SequenceOfExtendedString& theFormats), which append to a given sequence <i>\<theFormats\></i> your document format string, for example, "NewDocumentFormat" – this string is also set in the document creation command
dba69de2 533 + ResourcesName(), which returns a string with a name of resources file (this file contains a description about the extension of the document, storage/retrieval drivers GUIDs...), for example, "NewFormat"
534* Create the resource file (with name, for example, "NewFormat") with the following strings:
72b7576f 535
536~~~~~
537formatlist:NewDocumentFormat
538NewDocumentFormat: New Document Format Version 1.0
539NewDocumentFormat.FileExtension: ndf
540NewDocumentFormat.StoragePlugin: bd696000-5b34-11d1-b5ba-00a0c9064368
541NewDocumentFormat.RetrievalPlugin: bd696001-5b34-11d1-b5ba-00a0c9064368
542NewDocumentFormatSchema: bd696002-5b34-11d1-b5ba-00a0c9064368
543NewDocumentFormat.AttributeStoragePlugin:57b0b826-d931-11d1-b5da-00a0c9064368
544NewDocumentFormat.AttributeRetrievalPlugin:57b0b827-d931-11d1-b5da-00a0c9064368
545~~~~~
546
dba69de2 547* Create the resource file "Plugin" with GUIDs and corresponding plugin libraries, which looks like this:
72b7576f 548
549**Example**
550~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
551! Description of available plugins
552! ************
553
554b148e300-5740-11d1-a904-080036aaa103.Location: libFWOSPlugin.so
555!
556! standard document drivers plugin
557!
558bd696000-5b34-11d1-b5ba-00a0c9064368.Location: libPAppStdPlugin.so
559bd696001-5b34-11d1-b5ba-00a0c9064368.Location: libPAppStdPlugin.so
560!
561! standard schema plugin
562!
563bd696002-5b34-11d1-b5ba-00a0c9064368.Location: libPAppStdPlugin.so
564!
565! standard attribute drivers plugin
566!
56757b0b826-d931-11d1-b5da-00a0c9064368.Location: libPAppStdPlugin.so
56857b0b827-d931-11d1-b5da-00a0c9064368.Location: libPAppStdPlugin.so
569~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
570
dba69de2 571In order to set the paths for these files it is necessary to set the environments: *CSF_PluginDefaults* and *CSF_NewFormatDefaults*. For example, set the files in the directory *MyApplicationPath/MyResources*:
72b7576f 572
573~~~~~
574setenv CSF_PluginDefaults MyApplicationPath/MyResources
575setenv CSF_NewFormatDefaults MyApplicationPath/MyResources
576~~~~~
577
dba69de2 578Once these steps are taken you may run your application, create documents and Save/Open them. These resource files already exist in the OCAF (format "Standard").
72b7576f 579
e2b55410 580If you use your specific attributes from packages, for example, <i>P-, M-</i> and *TMyAttributePackage* (see @ref occt_ocaf_3_4_6 "Specific attribute creation") you must take some additional steps for the new plugin implementation:
72b7576f 581
e2b55410 5821. Add our *P* package to the standard schema. You can get an already existing (in Open CASCADE Technology sources) schema from *StdSchema* unit and add your package string to the cdl-file: package *PMyAttributePackage*.
5832. The next step consists in the implementation of an executable, which will connect our documents to our application and open/save them. Copy the package *PAppStdPlugin* and change its name to *MyTheBestApplicationPlugin*. In the *PLUGIN* macros type the name of your factory, which will be defined at the next step.
5843. *Factory* is a method, which returns drivers (standard drivers and our defined drivers from the *M* package) by a GUID. Copy the package to the location, where the standard factory is defined (it is PAppStd in the OCAF sources). Change its name to *MyTheBestSchemaLocation*. The *Factory()* method of the *PappStd* package checks the GUID set as its argument and returns the corresponding table of drivers. Set two new GUIDs for your determined storage and retrieval drivers. Append two *if* declarations inside the *Factory()* method, which should check whether the set GUID coincides with GUIDs defined by the *Factory()* method as far as our storage and retrieval drivers are concerned. If the GUID coincides with one of them, the method should return a table of storage or retrieval drivers respectively.
5854. Recompile all and add the strings with GUIDs to the *Plugin* file in accordance with your plugin library GUID.
72b7576f 586
587@subsubsection occt_ocaf_4_3_4 Opening the document from a file
588
e2b55410 589To 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 590
72b7576f 591~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
592app->Open("/tmp/example.caf", doc);
593~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
594
e2b55410 595@subsubsection occt_ocaf_4_3_5 Cutting, copying and pasting inside a document
596
597To cut, copy and paste inside a document, use the class *TDF_CopyLabel*.
598
599In fact, you must define a *Label*, which contains the temporary value of a cut or
600copy operation (say, in <i> Lab_Clipboard</i>). You must also define two other labels:
601
602* The data container (e.g. <i> Lab_source</i>)
603* The destination of the copy (e.g. <i> Lab_ Target</i> )
604
605~~~~
606 Copy = copy (Lab_Source => Lab_Clipboard)
607 Cut = copy + Lab_Source.ForgetAll() // command clear the contents of LabelSource.
608 Paste = copy (Lab_Clipboard => Lab_target)
609~~~~
610
611So we need a tool to copy all (or a part) of the content of a label and its sub-label,
612to another place defined by a label.
613
614~~~~
615 TDF_CopyLabel aCopy;
616 TDF_IDFilter aFilter (Standard_False);
617
618 //Don't copy TDataStd_TreeNode attribute
619
620 aFilter.Ignore(TDataStd_TreeNode::GetDefaultTreeID());
621 aCopy.Load(aSource, aTarget); aCopy.UseFilter(aFilter); aCopy.Perform();
622
623 // copy the data structure to clipboard
624
625 return aCopy.IsDone(); }
626~~~~
627
628The filter is used to forbid copying a specified type of attribute.
629
630You 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.
631
72b7576f 632@subsection occt_ocaf_4_4 External Links
633
dba69de2 634External links refer from one document to another. They allow you to update the copy of data framework later on.
72b7576f 635
dba69de2 636@image html /user_guides/ocaf/images/ocaf_image012.png "External links between documents"
637@image latex /user_guides/ocaf/images/ocaf_image012.png "External links between documents"
72b7576f 638
639Note that documents can be copied with or without a possibility of updating an external link.
640
641@subsubsection occt_ocaf_4_4_1 Copying the document
642
dba69de2 643#### With the possibility of updating it later
72b7576f 644
e2b55410 645To copy a document with a possibility of updating it later, you use *TDocStd_XLinkTool::CopyWithLink*.
72b7576f 646
72b7576f 647~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
648Handle(TDocStd_Document) doc1;
649Handle(TDocStd_Document) doc2;
650
651TDF_Label source = doc1->GetData()->Root();
652TDF_Label target = doc2->GetData()->Root();
653TDocStd_XLinkTool XLinkTool;
654
655XLinkTool.CopyWithLink(target,source);
656~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
657
658Now 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.
659
e2b55410 660In 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 661
72b7576f 662~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
663XLinkTool.UpdateLink(target);
664~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
665
dba69de2 666#### Without any link between the copy and the original
72b7576f 667
e2b55410 668You 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 669
72b7576f 670~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
671XLinkTool.Copy(target, source);
672
673~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
674
675
676@section occt_ocaf_5_ OCAF Shape Attributes
677@subsection occt_ocaf_5_1 Overview
678
e2b55410 679A topological attribute can be seen as a hook into the topological structure. It is possible to attach data to define references to it.
680
681OCAF 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 682
e2b55410 683The 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 684
685If 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.
686
dba69de2 687@image html /user_guides/ocaf/images/ocaf_image013.png
688@image latex /user_guides/ocaf/images/ocaf_image013.png
72b7576f 689
a7372ed5 690@subsection occt_ocaf_5_2 Shape attributes in data framework.
e2b55410 691
72b7576f 692Different algorithms may dispose sub-shapes of the result shape at the individual labels depending on whether it is necessary to do so:
693
694* 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.
695* 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.
696
e2b55410 697*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 698
e2b55410 699Consider 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 700
dba69de2 701@image html /user_guides/ocaf/images/ocaf_image014.png "Resulting box"
702@image latex /user_guides/ocaf/images/ocaf_image014.png "Resulting box"
72b7576f 703
704After 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, as well as to the new shape – the shape resulting from the fuse operation – and has evolution MODIFY (see the following figure).
705
8d44b0a0 706Named shapes, which contain information about modified faces, belong to the fuse result sub-labels: sub-label with tag 1 – modified faces from box 1, sub-label with tag 2 – modified faces from box 2.
72b7576f 707
dba69de2 708@image html /user_guides/ocaf/images/ocaf_image015.png
709@image latex /user_guides/ocaf/images/ocaf_image015.png
72b7576f 710
711This 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:
712
e2b55410 713 * face F1’ as a modification of face F11
714 * face F1’’ as generation of face F12
72b7576f 715 * edges as an intersection of two contiguous faces
716 * vertices as an intersection of three contiguous faces
717
718After 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.
719
a7372ed5 720@subsection occt_ocaf_5_3 Registering shapes and their evolution
72b7576f 721
722When using TNaming_NamedShape to create attributes, the following fields of an attribute are filled:
723
dba69de2 724* 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 725* 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:
726 * PRIMITIVE – newly created topology, with no previous history;
727 * 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 );
728 * MODIFY – the new shape is a modified old shape;
729 * DELETE – the new shape is empty; the named shape with this evolution just indicates that the old shape topology is deleted from the model;
730 * SELECTED – a named shape with this evolution has no effect on the history of the topology.
72b7576f 731
732Only pairs of shapes with equal evolution can be stored in one named shape.
733
a7372ed5 734@subsection occt_ocaf_5_4 Using naming resources
72b7576f 735
a7372ed5 736The 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 737
72b7576f 738~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
dba69de2 739// a new empty named shape is created at "label"
72b7576f 740TNaming_Builder builder(label);
741// set a pair of shapes with evolution GENERATED
742builder.Generated(oldshape1,newshape1);
743// set another pair of shapes with the same evolution
744builder.Generated(oldshape2,newshape2);
745// get the result – TNaming_NamedShape attribute
746Handle(TNaming_NamedShape) ns = builder.NamedShape();
747~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a7372ed5 748
749@subsection occt_ocaf_5_5 Reading the contents of a named shape attribute
72b7576f 750
e2b55410 751You 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 752
72b7576f 753More detailed information about the contents of the named shape or about the modification history of a topology can be obtained with the following:
e2b55410 754* *TNaming_Tool* provides a common high-level functionality for access to the named shapes contents:
755 * The method <i>GetShape(Handle(TNaming_NamedShape)) </i> returns a compound of new shapes of the given named shape;
756 * 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;
757 * 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.
758* *TNaming_Iterator* gives access to the named shape and hooks pairs.
72b7576f 759
72b7576f 760~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
761// create an iterator for a named shape
762TNaming_Iterator iter(namedshape);
763// iterate while some pairs are not iterated
764while(iter.More()) {
765// get the new shape from the current pair
766TopoDS_Shape newshape = iter.NewShape();
767// get the old shape from the current pair
768TopoDS_Shape oldshape = iter.OldShape();
769// do something...
770
771// go to the next pair
772iter.Next();
773}
774~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
775
776
a7372ed5 777@subsection occt_ocaf_5_6 Topological naming
778
779The Topological Naming mechanism is based on 3 components:
780* History of the used modeling operation algorithm;
781* Registering of the built result in Data Framework (i.e. loading the necessary elements of the extracted history in OCAF document);
782* Selection / Recomputation of a "selected" sub-shape of the algorithm result.
783
784To get the expected result the work of the three components should be synchronized and the rules of each component should be respected.
785
786@subsubsection occt_ocaf_5_6_1 Algorithm history
787
788The "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.
789
790| Result type | Type of sub-shapes to be returned by history of algorithm | Comments |
791| :---------- | :-------------------------------------------------------- | :------- |
792| Solid or closed shell | Faces | All faces |
793| Open shell or single face | Faces and edges of opened boundaries only | All faces plus all edges of opened boundaries |
794| Closed wire | Edges | All edges |
795| Opened wire | Edges and ending vertexes | All edges plus ending vertexes of the wire |
796| Edge | Vertexes | Two vertexes are expected |
797| 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 |
798
799The 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 800
a7372ed5 801There 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 802
a7372ed5 803@subsubsection occt_ocaf_5_6_2 Loading history in data framework
72b7576f 804
a7372ed5 805All 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 806
a7372ed5 807The "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 808
a7372ed5 809@subsubsection occt_ocaf_5_6_3 Selection / re-computation mechanism
810
811When 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.
812
813One 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:
814* Storing the selected shape on a label - its **Selection**;
815* Accessing the named shape – check the kept value of the shape
816* Update of this naming – recomputation of an earlier selected shape.
817
818The 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:
819* the given context shape, i.e. the main shape kept on **Result Label**, which contains a selected sub-shape,
820* its evolution and
821* naming structure.
822
823After 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.
824
825@subsection occt_ocaf_5_7 Exploring shape evolution
72b7576f 826
e2b55410 827The class *TNaming_Tool* provides a toolkit to read current data contained in the attribute.
72b7576f 828
e2b55410 829If you need to create a topological attribute for existing data, use the method *NamedShape*.
72b7576f 830
72b7576f 831~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
832class MyPkg_MyClass
833{
834public: Standard_Boolean SameEdge (const Handle(CafTest_Line)& L1, const Handle(CafTest_Line)& L2);
835};
836
837Standard_Boolean CafTest_MyClass::SameEdge (const Handle(CafTest_Line)& L1, const Handle(CafTest_Line)& L2)
838{
839 Handle(TNaming_NamedShape) NS1 = L1->NamedShape();
840 Handle(TNaming_NamedShape) NS2 = L2->NamedShape();
841 return BRepTools::Compare(NS1,NS2);
842}
843~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
844
a7372ed5 845
846@subsection occt_ocaf_5_8 Example of topological naming usage
847
848**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.).
849
850Let us consider an example: imagine a wooden plate. The job is to drive several nails in it:
851
852@figure{/user_guides/ocaf/images/ocaf_image020.png, "A nail driven in a wooden plate"}
853
854There 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:
855* Makes several Nails of different height and diameter (according to the need),
856* Chooses (selects) the upper surface of each Nail for the Hammer.
857
858The 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.
859
860What 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!)…
861
862Topological 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()*.
863
864The topological naming is represented as a “black box” in the example above. Now it is time to make the box a little more “transparent”.
865
866The application contains 3 functions:
867* **Nail** - produces a shape representing a nail,
868* **Translator** - translates a shape along the wooden plate,
869* **Hammer** - drives the nail in the wooden plate.
870
871Each function gives the topological naming some hints how to “re-solve” the selected sub-shapes:
872* The Nail constructs a solid shape and puts each face of the shape into sub-labels:
873
874@figure{/user_guides/ocaf/images/ocaf_image021.png, "Distribution of faces through sub-labels of the Nail"}
875
876* 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:
877
878@figure{/user_guides/ocaf/images/ocaf_image022.png, "Registration of relocation of faces of a Nail"}
879
880How does it work?
881* 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).
882* 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.
883* When the Hammer calls *TNaming::Solve()*, the topological naming “looks” at the unique name of the selected shape and tries to re-solve it:
884 * It finds the 1st appearance of the selected shape in the data tree – it is a label under the Nail function *Face 1*.
885 * 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.
886* Calling the method *TNaming_Selector::NamedShape()* the Hammer obtains the last evolution of the selected face – the relocated top face.
887
888The job is done.
889
890P.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).
891
892
72b7576f 893@section occt_ocaf_6_ Standard Attributes
894
895@subsection occt_ocaf_6_1 Overview
896
e2b55410 897Standard 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 898
e2b55410 899 * Geometric attributes;
900 * General attributes;
901 * Relationship attributes;
902 * Auxiliary attributes.
72b7576f 903
dba69de2 904### Geometric attributes
905
e2b55410 906 * **Axis** – simply identifies, that the concerned *TNaming_NamedShape* attribute with an axis shape inside belongs to the same label;
907 * **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;
908 * **Geometry** – simply identifies, that the concerned *TNaming_NamedShape* attribute with a specified-type geometry belongs to the same label;
909 * **Plane** – simply identifies, that the concerned *TNaming_NamedShape* attribute with a plane shape inside belongs to the same label;
910 * **Point** – simply identifies, that the concerned *TNaming_NamedShape* attribute with a point shape inside belongs to the same label;
911 * **Shape** – simply identifies, that the concerned *TNaming_NamedShape* attribute belongs to the same label;
912 * **PatternStd** – identifies one of five available pattern models (linear, circular, rectangular, circular rectangular and mirror);
913 * **Position** – identifies the position in 3d global space.
72b7576f 914
dba69de2 915### General attributes
916
e2b55410 917 * **AsciiString** – contains AsciiString value;
918 * **BooleanArray** – contains an array of Boolean;
919 * **BooleanList** – contains a list of Boolean;
920 * **ByteArray** – contains an array of Byte (unsigned char) values;
921 * **Comment** – contains a string – some comment for a given label (or attribute);
922 * **Expression** – contains an expression string and a list of used variables attributes;
923 * **ExtStringArray** – contains an array of *ExtendedString* values;
924 * **ExtStringList** – contains a list of *ExtendedString* values;
925 * **Integer** – contains an integer value;
926 * **IntegerArray** – contains an array of integer values;
927 * **IntegerList** – contains a list of integer values;
928 * **IntPackedMap** – contains a packed map of integers;
929 * **Name** – contains a string – some name of a given label (or attribute);
930 * **NamedData** – may contain up to 6 of the following named data sets (vocabularies): *DataMapOfStringInteger, DataMapOfStringReal, DataMapOfStringString, DataMapOfStringByte, DataMapOfStringHArray1OfInteger* or *DataMapOfStringHArray1OfReal*;
931 * **NoteBook** – contains a *NoteBook* object attribute;
932 * **Real** – contains a real value;
933 * **RealArray** – contains an array of real values;
934 * **RealList** – contains a list of real values;
935 * **Relation** – contains a relation string and a list of used variables attributes;
936 * **Tick** – defines a boolean attribute;
937 * **Variable** – simply identifies, that a variable belongs to this label; contains the flag *is constraint* and a string of used units ("mm", "m"...);
938 * **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 939
dba69de2 940### Relationship attributes
941
e2b55410 942 * **Reference** – contains reference to the label of its own data framework;
943 * **ReferenceArray** – contains an array of references;
944 * **ReferenceList** – contains a list of references;
945 * **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 946
dba69de2 947### Auxiliary attributes
948
e2b55410 949 * **Directory** – high-level tool attribute for sub-labels management;
950 * **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 951
e2b55410 952All 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 953
954
955@subsection occt_ocaf_6_2 Services common to all attributes
956
957@subsubsection occt_ocaf_6_2_1 Accessing GUIDs
958
959To access the GUID of an attribute, you can use two methods:
e2b55410 960 * 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 961 * 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 962
963To 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:
964
965~~~~
966 Standard_GUID anID = MyAttributeClass::GetID();
967 Standard_Boolean HasAttribute = aLabel.Find(anID,anAttribute);
968~~~~
72b7576f 969
970@subsubsection occt_ocaf_6_2_2 Conventional Interface of Standard Attributes
971
972It is usual to create standard named methods for the attributes:
973
dba69de2 974 * 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.
975 * Method *Get()* returns the value of an attribute if it is characterized by one value.
976 * Method *Dump(Standard_OStream)* outputs debug information about a given attribute to a given stream.
72b7576f 977
dba69de2 978@section occt_ocaf_7 Visualization Attributes
72b7576f 979
980@subsection occt_ocaf_7_1 Overview
981
e2b55410 982Standard 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 983
984@subsection occt_ocaf_7_2 Services provided
985
986@subsubsection occt_ocaf_7_2_1 Defining an interactive viewer attribute
987
e2b55410 988The 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 989
e2b55410 990To initialize the AIS viewer as in the example below, use method *Find*.
72b7576f 991
72b7576f 992~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
dba69de2 993// "access" is any label of the data framework
72b7576f 994Handle(TPrsStd_AISViewer) viewer = TPrsStd_AISViewer::Find(access)
995~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
996
997@subsection occt_ocaf_7_2_2 Defining a presentation attribute
998
e2b55410 999The 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 1000
1001@subsubsection occt_ocaf_7_2_3 Creating your own driver
1002
1003The 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.
1004
e2b55410 1005If 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 1006@image html /user_guides/ocaf/images/ocaf_image016.png
1007@image latex /user_guides/ocaf/images/ocaf_image016.png
72b7576f 1008
1009As usual, the GUID of a driver and the GUID of a displayed attribute are the same.
1010
1011@subsubsection occt_ocaf_7_2_4 Using a container for drivers
1012
e2b55410 1013You 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 1014
e2b55410 1015To 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 1016
1017**Example**
1018~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1019DriverTable::Get() -> InitStandardDrivers();
1020// next, attach your named shape to a label
1021TPrsStd_AISPresentation::Set(NS};
1022// here, attach the AISPresentation to NS.
1023~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1024
dba69de2 1025@section occt_ocaf_8 Function Services
72b7576f 1026
1027Function 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.
1028
1029When 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.
1030
1031Take, 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.
1032
e2b55410 1033See the white paper @ref occt_user_guides__ocaf_functionmechanism_wp "Application Framework Function Mechanism" for more information.
1034
dba69de2 1035@subsection occt_ocaf_8_1 Finding functions, their owners and roots
72b7576f 1036
e2b55410 1037The 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 1038
e2b55410 1039You 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 1040
e2b55410 1041Then 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 1042
dba69de2 1043@subsection occt_ocaf_8_2 Storing and accessing information about function status
72b7576f 1044
e2b55410 1045For 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 1046
dba69de2 1047@subsection occt_ocaf_8_3 Propagating modifications
72b7576f 1048
e2b55410 1049An application must implement its functions, function drivers and the common solver for parametric model creation. For example, check the following model:
72b7576f 1050
dba69de2 1051@image html /user_guides/ocaf/images/ocaf_image017.png
1052@image latex /user_guides/ocaf/images/ocaf_image017.png
72b7576f 1053
1054The procedure of its creation is as follows:
1055 * create a rectangular planar face F with height 100 and width 200
1056 * create prism P using face F as a basis
1057 * create fillet L at the edge of the prism
1058 * change the width of F from 200 to 300:
1059 * the solver for the function of face F starts
1060 * the solver detects that an argument of the face *F* function has been modified
dba69de2 1061 * the solver calls the driver of the face F function for a regeneration of the face
72b7576f 1062 * 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
1063
1064 * the solver detects the function of P – it depends on the function of F
1065 * the solver calls the driver of the prism P function
dba69de2 1066 * the driver rebuilds prism P and adds the label of this prism to the logbook as impacted
1067 * the solver detects the function of L – it depends on the function of P
72b7576f 1068 * the solver calls the L function driver
1069 * the driver rebuilds fillet L and adds the label of the fillet to the logbook as impacted
1070
1071@section occt_ocaf_9 XML Support
1072
1073Writing and reading XML files in OCCT is provided by LDOM package, which constitutes an integral part
1074of XML OCAF persistence, which is the optional component provided on top of Open CASCADE Technology.
1075
1076The 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:
e2b55410 1077* 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.
1078* Provide class *LDOM_Parser* to read XML files and convert them to *LDOM_Document* objects.
1079* Provide class *LDOM_XmlWriter* to convert *LDOM_Document* to a character stream in XML format and store it in file.
72b7576f 1080
1081This 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:
1082* 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).
1083* To minimize the time required for parsing and formatting XML, as well as for access to DOM data structures.
1084
1085Both 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 1086* 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.
1087* Some superfluous methods are deleted: *getPreviousSibling, getParentNode,* etc.
72b7576f 1088* No resolution of XML Entities of any kind
1089* No support for DTD: the parser just checks for observance of general XML rules and never validates documents.
e2b55410 1090* Only 5 available types of DOM nodes: *LDOM_Element, LDOM_Attr, LDOM_Text, LDOM_Comment* and *LDOM_CDATASection*.
72b7576f 1091* No support of Namespaces; prefixed names are used instead of qualified names.
e2b55410 1092* No support of the interface *DOMException* (no exception when attempting to remove a non-existing node).
72b7576f 1093
1094LDOM 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.
1095
1096@subsection occt_ocaf_9_1 Document Drivers
1097
1098The drivers for document storage and retrieval manage conversion between a transient OCAF
e2b55410 1099Document in memory and its persistent reflection in a container (disk, memory, network). For XML Persistence, they are defined in the package XmlDrivers.
72b7576f 1100
1101The main methods (entry points) of these drivers are:
1102* *Write()* - for a storage driver;
1103* *Read()* - for a retrieval driver.
1104
1105The 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:
1106
1107First it is necessary to convert the transient document into another form (called persistent), suitable for writing into a file, and vice versa.
1108In XML Persistence LDOM_Document is used as the persistent form of an OCAF Document and the DOM_Nodes are the persistent objects.
1109An OCAF Document is a tree of labels with attributes. Its transformation into a persistent form can be functionally divided into two parts:
1110* Conversion of the labels structure, which is performed by the method XmlMDF::FromTo()
1111* Conversion of the attributes and their underlying objects, which is performed by the corresponding attribute drivers (one driver per attribute type).
1112
1113The driver for each attribute is selected from a table of drivers, either by attribute
1114type (on storage) or by the name of the corresponding DOM_Element (on retrieval).
1115The table of drivers is created by by methods *XmlDrivers_DocumentStorageDriver::AttributeDrivers()*
1116and *XmlDrivers_DocumentRetrievalDriver::AttributeDrivers()*.
1117
1118Then the persistent document is written into a file (or read from a file).
4ee1bdf4 1119In 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 1120
4ee1bdf4 1121Usually, 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 1122
1123The 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.
1124
1125@subsection occt_ocaf_9_2 Attribute Drivers
1126
4ee1bdf4 1127There 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 1128
1129*XmlMDF_ADriver* is the root class for all attribute drivers.
1130
4ee1bdf4 1131At 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 1132
4ee1bdf4 1133Every 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 1134
4ee1bdf4 1135The 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 1136
1137@subsection occt_ocaf_9_3 XML Document Structure
1138
ba06f8bb 1139Every 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:
72b7576f 1140* **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.
ba06f8bb 1141* **Element comments** - consists of an unlimited number of \<comment\> sub-elements containing necessary comment strings.
72b7576f 1142* **Element label** is 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).
4ee1bdf4 1143* **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 1144
dba69de2 1145### OCAF Attributes Representation
72b7576f 1146
1147In 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.
1148For 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.
1149XML 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.
1150
dba69de2 1151### Example of resulting XML file
1152
4ee1bdf4 1153The 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 1154
4ee1bdf4 1155~~~~
72b7576f 1156<?xml version="1.0" encoding="UTF-8"?>
1157<document format="XmlOcaf" xmlns="http://www.opencascade.org/OCAF/XML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1158xsi:schemaLocation="http://www.opencascade.org/OCAF/XML http://www.opencascade.org/OCAF/XML/XmlOcaf.xsd">
1159
1160<info date="2001-10-04" schemav="0" objnb="3">
1161<iitem>Copyright: Open Cascade, 2001</iitem>
1162<iitem>STORAGE_VERSION: PCDM_ReadWriter_1</iitem>
1163<iitem>REFERENCE_COUNTER: 0</iitem>
1164<iitem>MODIFICATION_COUNTER: 1</iitem>
1165</info>
1166<comments/>
1167<label tag="0">
1168<TDataStd_Name id="1">Document_1</TDataStd_Name>
1169<label tag="2">
1170<TNaming_NamedShape id="2" evolution="primitive">
1171<olds/>
1172<news>
1173<shape tshape="+34" index="1"/>
1174</news>
1175</TNaming_NamedShape>
1176</label>
1177</label>
ba06f8bb 1178\<shapes\>
72b7576f 1179...
1180</shapes>
1181</document>
1182
4ee1bdf4 1183~~~~
72b7576f 1184
1185@subsection occt_ocaf_9_4 XML Schema
1186
1187The XML Schema defines the class of a document.
1188
1189The 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).
1190
1191There 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.
1192
1193The Schema files (XSD) are intended for two purposes:
1194* documenting the data format of files generated by OCAF;
1195* validation of documents when they are used by external (non-OCAF) applications, e.g., to generate reports.
1196
1197The 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.
1198
dba69de2 1199### Management of Namespaces
1200
4ee1bdf4 1201Both 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 1202* Define *targetNamespace* in the new XSD file describing the format.
4ee1bdf4 1203* 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 1204* 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.
1205* Pass (in every OCAF attribute driver) the namespace prefix of the *targetNamespace* to the constructor of *XmlMDF_ADriver*.
72b7576f 1206
1207@section occt_ocaf_10 GLOSSARY
1208
dba69de2 1209* **Application** - a document container holding all documents containing all application data.
1210* **Application data** - the data produced by an application, as opposed to data referring to it.
1211* **Associativity of data** - the ability to propagate modifications made to one document to other documents, which refer to such document. Modification propagation is:
72b7576f 1212 * unidirectional, that is, from the referenced to the referencing document(s), or
1213 * bi-directional, from the referencing to the referenced document and vice-versa.
dba69de2 1214* **Attribute** - a container for application data. An attribute is attached to a label in the hierarchy of the data framework.
1215* **Child** - a label created from another label, which by definition, is the father label.
1216* **Compound document** - a set of interdependent documents, linked to each other by means of external references. These references provide the associativity of data.
1217* **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.
e2b55410 1218* **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 1219 * Manage modifications, providing Undo and Redo functions
1220 * Manage command transactions
1221 * Update external links
1222 * Manage save and restore options
1223 * Store the names of software extensions.
1224* **Driver** - an abstract class, which defines the communications protocol with a system.
e2b55410 1225* **Entry** - an ASCII character string containing the tag list of a label. For example:
72b7576f 1226
72b7576f 1227~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
12280:3:24:7:2:7
1229~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1230
dba69de2 1231* **External links** - references from one data structure to another data structure in another document.
72b7576f 1232To store these references properly, a label must also contain an external link attribute.
dba69de2 1233* **Father** - a label, from which other labels have been created. The other labels are, by definition, the children of this label.
1234* **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 1235 * defining new classes which inherit from these abstract classes
1236 * composing framework class instances
1237 * implementing the services required by the framework.
1238
1239In C++, the application behavior is implemented in virtual functions redefined in these derived classes. This is known as overriding.
1240
e2b55410 1241* **GUID** - Global Universal ID. A string of 37 characters intended to uniquely identify an object. For example:
72b7576f 1242
72b7576f 1243~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
12442a96b602-ec8b-11d0-bee7-080009dc3333
1245~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1246
dba69de2 1247* **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.
1248* **Modified label** - containing attributes whose data has been modified.
1249* **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.
1250* **Resource file** - a file containing a list of each document’s schema name and the storage and retrieval plug-ins for that document.
1251* **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.
1252* **Scope** - the set of all the attributes and labels which depend on a given label.
1253* **Tag list** - a list of integers, which identify the place of a label in the data framework. This list is displayed in an entry.
1254* **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.
1255* **Topological tracking** - following a topological entity in a model through the steps taken to edit and regenerate that model.
1256* **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 1257
dba69de2 1258@section occt_ocaf_11 Samples
1259@subsection occt_ocaf_11_1 Implementation of Attribute Transformation in a CDL file
72b7576f 1260
1261~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1262class Transformation from MyPackage inherits Attribute from TDF
1263
dba69de2 1264 ---Purpose: This attribute implements a transformation data container.
72b7576f 1265
1266uses
1267
dba69de2 1268 Attribute from TDF,
1269 Label from TDF,
1270 GUID from Standard,
1271 RelocationTable from TDF,
1272 Pnt from gp,
1273 Ax1 from gp,
1274 Ax2 from gp,
1275 Ax3 from gp,
1276 Vec from gp,
1277 Trsf from gp,
1278 TrsfForm from gp
72b7576f 1279
1280is
1281
dba69de2 1282 ---Category: Static methods
1283 -- ===============
1284
1285 GetID (myclass)
1286 ---C++: return const &
1287 ---Purpose: The method returns a unique GUID of this attribute.
1288 -- By means of this GUID this attribute may be identified
1289 -- among other attributes attached to the same label.
1290 returns GUID from Standard;
1291
1292 Set (myclass; theLabel : Label from TDF)
1293 ---Purpose: Finds or creates the attribute attached to <theLabel>.
1294 -- The found or created attribute is returned.
1295 returns Transformation from MyPackage;
1296
1297
1298 ---Category: Methods for access to the attribute data
1299 -- ========================================
1300
1301 Get (me)
1302 ---Purpose: The method returns the transformation.
1303 returns Trsf from gp;
1304
1305
1306 ---Category: Methods for setting the data of transformation
1307 -- ==============================================
1308
1309 SetRotation (me : mutable;
1310 theAxis : Ax1 from gp;
1311 theAngle : Real from Standard);
1312 ---Purpose: The method defines a rotation type of transformation.
1313
1314 SetTranslation (me : mutable;
1315 theVector : Vec from gp);
1316 ---Purpose: The method defines a translation type of transformation.
1317
1318 SetMirror (me : mutable;
1319 thePoint : Pnt from gp);
1320 ---Purpose: The method defines a point mirror type of transformation
1321 -- (point symmetry).
1322
1323 SetMirror (me : mutable;
1324 theAxis : Ax1 from gp);
1325 ---Purpose: The method defines an axis mirror type of transformation
1326 -- (axial symmetry).
1327
1328 SetMirror (me : mutable;
1329 thePlane : Ax2 from gp);
1330 ---Purpose: The method defines a point mirror type of transformation
1331 -- (planar symmetry).
1332
1333 SetScale (me : mutable;
1334 thePoint : Pnt from gp;
1335 theScale : Real from Standard);
1336 ---Purpose: The method defines a scale type of transformation.
1337
1338 SetTransformation (me : mutable;
1339 theCoordinateSystem1 : Ax3 from gp;
1340 theCoordinateSystem2 : Ax3 from gp);
1341 ---Purpose: The method defines a complex type of transformation
1342 -- from one co-ordinate system to another.
1343
1344
1345 ---Category: Overridden methods from TDF_Attribute
1346 -- =====================================
1347
1348 ID (me)
1349 ---C++: return const &
1350 ---Purpose: The method returns a unique GUID of the attribute.
1351 -- By means of this GUID this attribute may be identified
1352 -- among other attributes attached to the same label.
1353 returns GUID from Standard;
1354
1355 Restore (me: mutable;
1356 theAttribute : Attribute from TDF);
1357 ---Purpose: The method is called on Undo / Redo.
1358 -- It copies the content of <theAttribute>
1359 -- into this attribute (copies the fields).
1360
1361 NewEmpty (me)
1362 ---Purpose: It creates a new instance of this attribute.
1363 -- It is called on Copy / Paste, Undo / Redo.
1364 returns mutable Attribute from TDF;
1365
1366 Paste (me;
1367 theAttribute : mutable Attribute from TDF;
1368 theRelocationTable : mutable RelocationTable from TDF);
1369 ---Purpose:: The method is called on Copy / Paste.
1370 -- It copies the content of this attribute into
1371 -- <theAttribute> (copies the fields).
1372
1373 Dump(me; anOS : in out OStream from Standard)
1374 ---C++: return;
1375 ---Purpose: Prints the content of this attribute into the stream.
1376 returns OStream from Standard is redefined;
1377
1378
1379 ---Category: Constructor
1380 -- ===========
1381
1382 Create
1383 ---Purpose: The C++ constructor of this atribute class.
1384 -- Usually it is never called outside this class.
1385 returns mutable Transformation from MyPackage;
72b7576f 1386
1387
1388fields
1389
dba69de2 1390 -- Type of transformation
1391 myType : TrsfForm from gp;
72b7576f 1392
dba69de2 1393 -- Axes (Ax1, Ax2, Ax3)
1394 myAx1 : Ax1 from gp;
1395 myAx2 : Ax2 from gp;
1396 myFirstAx3 : Ax3 from gp;
1397 mySecondAx3 : Ax3 from gp;
1398
1399 -- Scalar values
1400 myAngle : Real from Standard;
1401 myScale : Real from Standard;
1402
1403 -- Points
1404 myFirstPoint : Pnt from gp;
1405 mySecondPoint : Pnt from gp;
72b7576f 1406
1407
1408end Transformation;
1409~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1410
dba69de2 1411@subsection occt_ocaf_11_2 Implementation of Attribute Transformation in a CPP file
1412
72b7576f 1413~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1414#include MyPackage_Transformation.ixx;
1415
1416//=======================================================================
1417//function : GetID
dba69de2 1418//purpose : The method returns a unique GUID of this attribute.
1419// By means of this GUID this attribute may be identified
1420// among other attributes attached to the same label.
72b7576f 1421//=======================================================================
1422const Standard_GUID& MyPackage_Transformation::GetID()
1423{
dba69de2 1424 static Standard_GUID ID("4443368E-C808-4468-984D-B26906BA8573");
1425 return ID;
72b7576f 1426}
1427
1428//=======================================================================
1429//function : Set
dba69de2 1430//purpose : Finds or creates the attribute attached to <theLabel>.
1431// The found or created attribute is returned.
72b7576f 1432//=======================================================================
1433Handle(MyPackage_Transformation) MyPackage_Transformation::Set(const TDF_Label& theLabel)
1434{
dba69de2 1435 Handle(MyPackage_Transformation) T;
1436 if (!theLabel.FindAttribute(MyPackage_Transformation::GetID(), T))
1437 {
1438 T = new MyPackage_Transformation();
1439 theLabel.AddAttribute(T);
1440 }
1441 return T;
72b7576f 1442}
1443
1444//=======================================================================
1445//function : Get
dba69de2 1446//purpose : The method returns the transformation.
72b7576f 1447//=======================================================================
1448gp_Trsf MyPackage_Transformation::Get() const
1449{
dba69de2 1450 gp_Trsf transformation;
1451 switch (myType)
1452 {
1453 case gp_Identity:
1454 {
1455 break;
1456 }
1457 case gp_Rotation:
1458 {
1459 transformation.SetRotation(myAx1, myAngle);
1460 break;
1461 }
1462 case gp_Translation:
1463 {
1464 transformation.SetTranslation(myFirstPoint, mySecondPoint);
1465 break;
1466 }
1467 case gp_PntMirror:
1468 {
1469 transformation.SetMirror(myFirstPoint);
1470 break;
1471 }
1472 case gp_Ax1Mirror:
1473 {
1474 transformation.SetMirror(myAx1);
1475 break;
1476 }
1477 case gp_Ax2Mirror:
1478 {
1479 transformation.SetMirror(myAx2);
1480 break;
1481 }
1482 case gp_Scale:
1483 {
1484 transformation.SetScale(myFirstPoint, myScale);
1485 break;
1486 }
1487 case gp_CompoundTrsf:
1488 {
1489 transformation.SetTransformation(myFirstAx3, mySecondAx3);
1490 break;
1491 }
1492 case gp_Other:
1493 {
1494 break;
1495 }
1496 }
1497 return transformation;
72b7576f 1498}
1499
1500//=======================================================================
1501//function : SetRotation
dba69de2 1502//purpose : The method defines a rotation type of transformation.
72b7576f 1503//=======================================================================
1504void MyPackage_Transformation::SetRotation(const gp_Ax1& theAxis, const Standard_Real theAngle)
1505{
dba69de2 1506 Backup();
1507 myType = gp_Rotation;
1508 myAx1 = theAxis;
1509 myAngle = theAngle;
72b7576f 1510}
1511
1512//=======================================================================
1513//function : SetTranslation
dba69de2 1514//purpose : The method defines a translation type of transformation.
72b7576f 1515//=======================================================================
1516void MyPackage_Transformation::SetTranslation(const gp_Vec& theVector)
1517{
dba69de2 1518 Backup();
1519 myType = gp_Translation;
1520 myFirstPoint.SetCoord(0, 0, 0);
1521 mySecondPoint.SetCoord(theVector.X(), theVector.Y(), theVector.Z());
72b7576f 1522}
1523
1524//=======================================================================
1525//function : SetMirror
dba69de2 1526//purpose : The method defines a point mirror type of transformation
1527// (point symmetry).
72b7576f 1528//=======================================================================
1529void MyPackage_Transformation::SetMirror(const gp_Pnt& thePoint)
1530{
dba69de2 1531 Backup();
1532 myType = gp_PntMirror;
1533 myFirstPoint = thePoint;
72b7576f 1534}
1535
1536//=======================================================================
1537//function : SetMirror
dba69de2 1538//purpose : The method defines an axis mirror type of transformation
1539// (axial symmetry).
72b7576f 1540//=======================================================================
1541void MyPackage_Transformation::SetMirror(const gp_Ax1& theAxis)
1542{
dba69de2 1543 Backup();
1544 myType = gp_Ax1Mirror;
1545 myAx1 = theAxis;
72b7576f 1546}
1547
1548//=======================================================================
1549//function : SetMirror
dba69de2 1550//purpose : The method defines a point mirror type of transformation
1551// (planar symmetry).
72b7576f 1552//=======================================================================
1553void MyPackage_Transformation::SetMirror(const gp_Ax2& thePlane)
1554{
dba69de2 1555 Backup();
1556 myType = gp_Ax2Mirror;
1557 myAx2 = thePlane;
72b7576f 1558}
1559
1560//=======================================================================
1561//function : SetScale
dba69de2 1562//purpose : The method defines a scale type of transformation.
72b7576f 1563//=======================================================================
1564void MyPackage_Transformation::SetScale(const gp_Pnt& thePoint, const Standard_Real theScale)
1565{
dba69de2 1566 Backup();
1567 myType = gp_Scale;
1568 myFirstPoint = thePoint;
1569 myScale = theScale;
72b7576f 1570}
1571
1572//=======================================================================
1573//function : SetTransformation
dba69de2 1574//purpose : The method defines a complex type of transformation
1575// from one co-ordinate system to another.
72b7576f 1576//=======================================================================
1577void MyPackage_Transformation::SetTransformation(const gp_Ax3& theCoordinateSystem1,
dba69de2 1578 const gp_Ax3& theCoordinateSystem2)
72b7576f 1579{
dba69de2 1580 Backup();
1581 myFirstAx3 = theCoordinateSystem1;
1582 mySecondAx3 = theCoordinateSystem2;
72b7576f 1583}
1584
1585//=======================================================================
1586//function : ID
dba69de2 1587//purpose : The method returns a unique GUID of the attribute.
1588// By means of this GUID this attribute may be identified
1589// among other attributes attached to the same label.
72b7576f 1590//=======================================================================
1591const Standard_GUID& MyPackage_Transformation::ID() const
1592{
dba69de2 1593 return GetID();
72b7576f 1594}
1595
1596//=======================================================================
1597//function : Restore
dba69de2 1598//purpose : The method is called on Undo / Redo.
1599// It copies the content of <theAttribute>
1600// into this attribute (copies the fields).
72b7576f 1601//=======================================================================
1602void MyPackage_Transformation::Restore(const Handle(TDF_Attribute)& theAttribute)
1603{
dba69de2 1604 Handle(MyPackage_Transformation) theTransformation = Handle(MyPackage_Transformation)::DownCast(theAttribute);
1605 myType = theTransformation->myType;
1606 myAx1 = theTransformation->myAx1;
1607 myAx2 = theTransformation->myAx2;
1608 myFirstAx3 = theTransformation->myFirstAx3;
1609 mySecondAx3 = theTransformation->mySecondAx3;
1610 myAngle = theTransformation->myAngle;
1611 myScale = theTransformation->myScale;
1612 myFirstPoint = theTransformation->myFirstPoint;
1613 mySecondPoint = theTransformation->mySecondPoint;
72b7576f 1614}
1615
1616//=======================================================================
1617//function : NewEmpty
dba69de2 1618//purpose : It creates a new instance of this attribute.
1619// It is called on Copy / Paste, Undo / Redo.
72b7576f 1620//=======================================================================
1621Handle(TDF_Attribute) MyPackage_Transformation::NewEmpty() const
dba69de2 1622{
1623 return new MyPackage_Transformation();
72b7576f 1624}
1625
1626//=======================================================================
1627//function : Paste
dba69de2 1628//purpose : The method is called on Copy / Paste.
1629// It copies the content of this attribute into
1630// <theAttribute> (copies the fields).
72b7576f 1631//=======================================================================
1632void MyPackage_Transformation::Paste(const Handle(TDF_Attribute)& theAttribute,
dba69de2 1633 const Handle(TDF_RelocationTable)& ) const
72b7576f 1634{
dba69de2 1635 Handle(MyPackage_Transformation) theTransformation = Handle(MyPackage_Transformation)::DownCast(theAttribute);
1636 theTransformation->myType = myType;
1637 theTransformation->myAx1 = myAx1;
1638 theTransformation->myAx2 = myAx2;
1639 theTransformation->myFirstAx3 = myFirstAx3;
1640 theTransformation->mySecondAx3 = mySecondAx3;
1641 theTransformation->myAngle = myAngle;
1642 theTransformation->myScale = myScale;
1643 theTransformation->myFirstPoint = myFirstPoint;
1644 theTransformation->mySecondPoint = mySecondPoint;
72b7576f 1645}
1646
1647//=======================================================================
1648//function : Dump
dba69de2 1649//purpose : Prints the content of this attribute into the stream.
72b7576f 1650//=======================================================================
1651Standard_OStream& MyPackage_Transformation::Dump(Standard_OStream& anOS) const
dba69de2 1652{
1653 anOS = "Transformation: ";
1654 switch (myType)
1655 {
1656 case gp_Identity:
1657 {
1658 anOS = "gp_Identity";
1659 break;
1660 }
1661 case gp_Rotation:
1662 {
1663 anOS = "gp_Rotation";
1664 break;
1665 }
1666 case gp_Translation:
1667 {
1668 anOS = "gp_Translation";
1669 break;
1670 }
1671 case gp_PntMirror:
1672 {
1673 anOS = "gp_PntMirror";
1674 break;
1675 }
1676 case gp_Ax1Mirror:
1677 {
1678 anOS = "gp_Ax1Mirror";
1679 break;
1680 }
1681 case gp_Ax2Mirror:
1682 {
1683 anOS = "gp_Ax2Mirror";
1684 break;
1685 }
1686 case gp_Scale:
1687 {
1688 anOS = "gp_Scale";
1689 break;
1690 }
1691 case gp_CompoundTrsf:
1692 {
1693 anOS = "gp_CompoundTrsf";
1694 break;
1695 }
1696 case gp_Other:
1697 {
1698 anOS = "gp_Other";
1699 break;
1700 }
1701 }
1702 return anOS;
72b7576f 1703}
1704
1705//=======================================================================
1706//function : MyPackage_Transformation
dba69de2 1707//purpose : A constructor.
72b7576f 1708//=======================================================================
1709MyPackage_Transformation::MyPackage_Transformation():myType(gp_Identity){
1710
1711}
dba69de2 1712~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1713
1714@subsection occt_ocaf_11_3 Implementation of typical actions with standard OCAF attributes.
1715
ba06f8bb 1716There are four sample files provided in the directory 'OpenCasCade/ros/samples/ocafsamples'. They present typical actions with OCAF services (mainly for newcomers).
dba69de2 1717The method *Sample()* of each file is not dedicated for execution 'as is', it is rather a set of logical actions using some OCAF services.
1718
1719### TDataStd_Sample.cxx
1720This sample contains templates for typical actions with the following standard OCAF attributes:
1721- Starting with data framework;
1722- TDataStd_Integer attribute management;
1723- TDataStd_RealArray attribute management;
1724- TDataStd_Comment attribute management;
1725- TDataStd_Name attribute management;
1726- TDataStd_UAttribute attribute management;
1727- TDF_Reference attribute management;
1728- TDataXtd_Point attribute management;
1729- TDataXtd_Plane attribute management;
1730- TDataXtd_Axis attribute management;
1731- TDataXtd_Geometry attribute management;
1732- TDataXtd_Constraint attribute management;
1733- TDataStd_Directory attribute management;
1734- TDataStd_TreeNode attribute management.
1735
1736### TDocStd_Sample.cxx
1737This sample contains template for the following typical actions:
1738- creating application;
1739- creating the new document (document contains a framework);
1740- retrieving the document from a label of its framework;
1741- filling a document with data;
1742- saving a document in the file;
1743- closing a document;
1744- opening the document stored in the file;
1745- copying content of a document to another document with possibility to update the copy in the future.
1746
1747### TPrsStd_Sample.cxx
1748This sample contains template for the following typical actions:
1749- starting with data framework;
1750- setting the TPrsStd_AISViewer in the framework;
1751- initialization of aViewer;
1752- finding TPrsStd_AISViewer attribute in the DataFramework;
1753- getting AIS_InteractiveContext from TPrsStd_AISViewer;
1754- adding driver to the map of drivers;
1755- getting driver from the map of drivers;
ba06f8bb 1756- setting TNaming_NamedShape to \<ShapeLabel\>;
1757- setting the new TPrsStd_AISPresentation to \<ShapeLabel\>;
dba69de2 1758- displaying;
1759- erasing;
1760- updating and displaying presentation of the attribute to be displayed;
1761- setting a color to the displayed attribute;
1762- getting transparency of the displayed attribute;
1763- modify attribute;
1764- updating presentation of the attribute in viewer.
1765
1766### TNaming_Sample.cxx
1767This sample contains template for typical actions with OCAF Topological Naming services.
1768The following scenario is used:
1769- data framework initialization;
1770- creating Box1 and pushing it as PRIMITIVE in DF;
1771- creating Box2 and pushing it as PRIMITIVE in DF;
1772- moving Box2 (applying a transformation);
1773- pushing the selected edges of the top face of Box1 in DF;
1774- creating a Fillet (using the selected edges) and pushing the result as a modification of Box1;
1775- creating a Cut (Box1, Box2) as a modification of Box1 and push it in DF;
1776- recovering the result from DF.
1777