0029311: Implementation of the Oriented Bounding Boxes (OBB) functionality
authornbv <nbv@opencascade.com>
Wed, 8 Nov 2017 12:47:09 +0000 (15:47 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 8 Dec 2017 13:39:11 +0000 (16:39 +0300)
1. The class Bnd_OBB has been created to describe the Oriented Bounding Box.

2. Several key methods have been implemented: Bnd_OBB::IsOut(...), Bnd_OBB::Add(...) and Bnd_OBB::Enlarge(...).

3. Interface of Bnd_Box class has changed. New methods have been created. See Bnd_Box.hxx for detailed information.

4. BRepBndLib and Draw_Box classes have been amended in order to provide correct work with Bnd_OBB class.

5. Interface of "bounding" DRAW-command has been changed. Please see help for detailed information.

6. New DRAW-command "isbbinterf" has been created. Please see help for detailed information.

7. "boundingstr" and "optbounding" DRAW-commands have been eliminated because their function can be made by "bounding" DRAW-command (e.g. see tests/bugs/vis/buc60857 or samples/tcl/snowflake.tcl test cases).

8. Documentation has been updated.

83 files changed:
dox/user_guides/draw_test_harness/draw_test_harness.md
dox/user_guides/modeling_data/images/modeling_data_image015.png [new file with mode: 0644]
dox/user_guides/modeling_data/modeling_data.md
samples/tcl/Penrose.tcl
samples/tcl/snowflake.tcl
src/BRepBndLib/BRepBndLib.hxx
src/BRepBndLib/BRepBndLib_1.cxx [new file with mode: 0644]
src/BRepBndLib/FILES
src/BRepTest/BRepTest_BasicCommands.cxx
src/Bnd/Bnd_OBB.cxx [new file with mode: 0644]
src/Bnd/Bnd_OBB.hxx [new file with mode: 0644]
src/Bnd/FILES
src/Draw/Draw_Box.cxx
src/Draw/Draw_Box.hxx
tests/bugs/modalg_1/buc60849
tests/bugs/modalg_1/bug108
tests/bugs/modalg_1/bug12661
tests/bugs/modalg_4/bug6334
tests/bugs/modalg_6/bug27537
tests/bugs/modalg_7/bug29311_1 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_10 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_11 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_12 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_13 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_14 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_15 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_16 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_17 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_2 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_3 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_4 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_5 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_6 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_7 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_8 [new file with mode: 0644]
tests/bugs/modalg_7/bug29311_9 [new file with mode: 0644]
tests/bugs/moddata_1/bug15570
tests/bugs/moddata_2/bug23165
tests/bugs/moddata_2/bug2442
tests/bugs/moddata_2/bug257
tests/bugs/moddata_2/bug566
tests/bugs/moddata_2/bug6503
tests/bugs/moddata_3/bug23575
tests/bugs/moddata_3/bug25631
tests/bugs/moddata_3/bug26560
tests/bugs/moddata_3/bug27261_1
tests/bugs/moddata_3/bug27261_2
tests/bugs/step/bug24595
tests/bugs/stlvrml/bug26338
tests/bugs/vis/buc60857
tests/bugs/vis/bug27796
tests/bugs/xde/bug659
tests/caf/basic/K1
tests/caf/basic/K2
tests/caf/basic/K3
tests/caf/bugs/B3
tests/caf/bugs/B5
tests/caf/bugs/B7
tests/caf/bugs/D2
tests/caf/named_shape/A1
tests/caf/named_shape/B1
tests/caf/named_shape/C1
tests/caf/named_shape/D1
tests/caf/named_shape/D2
tests/caf/named_shape/D3
tests/caf/xlink/A1
tests/caf/xlink/A2
tests/caf/xlink/B1
tests/caf/xlink/B2
tests/caf/xlink/B3
tests/caf/xlink/B4
tests/caf/xlink/B5
tests/caf/xlink/C1
tests/caf/xlink/D1
tests/caf/xlink/D2
tests/chamfer/begin
tests/demo/draw/binpersist_1
tests/demo/draw/binpersist_2
tests/demo/draw/binpersist_3
tests/perf/modalg/bug29311 [new file with mode: 0644]
tests/xml/data/ocaf/B3
tests/xml/data/ocaf/B5
tests/xml/data/ocaf/B7

index d49c821..dc31956 100644 (file)
@@ -7324,8 +7324,9 @@ buildevol
 Analysis of shapes includes commands to compute length, area, volumes and inertial properties, as well as to compute some aspects impacting shape validity.
 
   * Use **lprops**, **sprops**, **vprops** to compute integral properties.
-  * Use **bounding** to display the bounding box of a shape.
+  * Use **bounding** to compute and to display the bounding box of a shape.
   * Use **distmini** to calculate the minimum distance between two shapes.
+  * Use **isbbinterf** to check if the two shapes are interfered by their bounding boxes. 
   * Use **xdistef**, **xdistcs**, **xdistcc**, **xdistc2dc2dss**, **xdistcc2ds** to check the distance between two objects on even grid.
   * Use **checkshape** to check validity of the shape.
   * Use **tolsphere** to see the tolerance spheres of all vertices in the shape.
@@ -7378,20 +7379,135 @@ I.Z = 314159.265357595
 
 Syntax:      
 ~~~~~
-bounding shape 
+bounding {-s shape | -c xmin ymin zmin xmax ymax zmax} [-obb] [-shape name] [-dump] [-notriangulation] [-perfmeter name NbIters] [-save xmin ymin zmin xmax ymax zmax] [-nodraw] [-optimal] [-exttoler]
 ~~~~~
 
-Displays the bounding box of a shape. The bounding box is a cuboid created with faces parallel to the x, y, and z planes. The command returns the dimension values of the the box, *xmin ymin zmin xmax ymax zmax.* 
+Computes and displays the bounding box (BndBox) of a shape. The bounding box is a cuboid circumscribes the source shape.
+Generaly, bounding boxes can be divided on two main types:
+  - axis-aligned BndBox (AABB). I.e. the box whose edges are parallel to the some axis of World Coordinate System (WCS);
+  - oriented BndBox (OBB). I.e. not AABB.
 
-**Example:** 
+Detailed information about this command is availabe in DRAW help-system (enter "help bounding" in DRAW-application).
+  
+**Example 1: Creation of AABB with given corners** 
+~~~~~
+bounding -c 50 100 30 180 200 100 -shape result
+# look at the box
+vdisplay result
+vfit
+vsetdispmode 1
 ~~~~~
-# bounding box of a torus 
+
+**Example 2: Compare AABB and OBB** 
+~~~~~
+# Create a torus and rotate it
 ptorus t 20 5 
-bounding t 
-==-27.059805107309852              -27.059805107309852 - 
-5.0000001000000003 
-==27.059805107309852               27.059805107309852 
-5.0000001000000003 
+trotate t 5 10 15 1 1 1 28
+
+# Create AABB from the torus
+bounding -s t -shape ra -dump -save x1 y1 z1 x2 y2 z2
+==Axes-aligned bounding box
+==X-range: -26.888704600189307 23.007685197265488
+==Y-range: -22.237699567214314 27.658690230240481
+==Z-range: -13.813966507560762 12.273995247458407
+
+# Obtain the boundaries
+dump x1 y1 z1 x2 y2 z2
+==*********** Dump of x1 *************
+==-26.8887046001893
+
+==*********** Dump of y1 *************
+==-22.2376995672143
+
+==*********** Dump of z1 *************
+==-13.8139665075608
+
+==*********** Dump of x2 *************
+==23.0076851972655
+
+==*********** Dump of y2 *************
+==27.6586902302405
+
+==*********** Dump of z2 *************
+==12.2739952474584
+
+# Compute the volume of AABB
+vprops ra 1.0e-12
+==Mass :         64949.9
+
+# Let us check this value
+dval (x2-x1)*(y2-y1)*(z2-z1)
+==64949.886543606823
+~~~~~
+
+The same result is obtained.
+
+~~~~~
+# Create OBB from the torus
+bounding -s t -shape ro -dump -obb
+==Oriented bounding box
+==Center: -1.9405097014619073 2.7104953315130857 -0.76998563005117782
+==X-axis: 0.31006700219833244 -0.23203206410428409 0.9219650619059514
+==Y-axis: 0.098302309139513336 -0.95673739537318336 -0.27384340837854165
+==Z-axis: 0.94561890324040099 0.17554109923901748 -0.27384340837854493
+==Half X: 5.0000002000000077
+==Half Y: 26.783728747002169
+==Half Z: 26.783728747002165
+
+# Compute the volume of OBB
+vprops ro 1.0e-12
+==Mass :         28694.7
+~~~~~
+
+As we can see, the volume of OBB is significantly less than the volume of AABB.
+
+@subsubsection occt_draw_7_9_2a   isbbinterf
+
+Syntax:      
+~~~~~
+isbbinterf shape1 shape2 [-o]
+~~~~~
+
+Checks whether the bounding-boxes created from the given shapes are interfered. If "-o"-option is switched on then the oriented boxes will be checked. Otherwise, axes-aligned boxes will be checked.
+
+**Example 1: Not interfered AABB** 
+~~~~~
+box b1 100 60 140 20 10 80
+box b2 210 200 80 120 60 90
+isbbinterf b1 b2
+==The shapes are NOT interfered by AABB.
+~~~~~
+
+**Example 2: Interfered AABB** 
+~~~~~
+box b1 300 300 300
+box b2 100 100 100 50 50 50
+isbbinterf b1 b2
+==The shapes are interfered by AABB.
+~~~~~
+
+**Example 3: Not interfered OBB** 
+~~~~~
+box b1 100 150 200
+copy b1 b2
+trotate b1 -150 -150 -150 1 2 3 -40
+trotate b2 -150 -150 -150 1 5 2 60
+
+# Check of interference
+isbbinterf b1 b2 -o
+==The shapes are NOT interfered by OBB.
+~~~~~
+
+**Example 4: Interfered OBB** 
+~~~~~
+box b1 100 150 200
+copy b1 b2
+trotate b1 -50 -50 -50 1 1 1 -40
+trotate b2 -50 -50 -50 1 1 1 60
+
+# Check of interference
+isbbinterf b1 b2 -o
+==The shapes are interfered by OBB.
 ~~~~~
 
 @subsubsection occt_draw_7_9_3  distmini
diff --git a/dox/user_guides/modeling_data/images/modeling_data_image015.png b/dox/user_guides/modeling_data/images/modeling_data_image015.png
new file mode 100644 (file)
index 0000000..a2e1e51
Binary files /dev/null and b/dox/user_guides/modeling_data/images/modeling_data_image015.png differ
index 5e3d8de..914260f 100644 (file)
@@ -1294,3 +1294,99 @@ The following sample code reads a shape from ASCII file and writes it to a binar
   }
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+@section occt_modat_6 Bounding boxes
+
+*Bounding box(es) (BndBox(es))* is used in many OCCT algorithms. In general, it is some filter to avoid check of excess interferences between pairs of shapes (check of interferences between BndBoxes is much simpler then between shapes and if BndBoxes do not interfere then there is no point in searching interferences between the corresponding shapes).
+Generally, BndBoxes can be divided on two main types: 
+  - axis-aligned BndBox (AABB). I.e. the box whose edges are parallel to the axes of World Coordinate System (WCS);
+  - oriented BndBox (OBB). I.e. not AABB.
+In fact, every AABB is a specific case of OBB.<br>
+
+The image below illustrates the example, when using OBB is better than AABB. 
+
+@figure{/user_guides/modeling_data/images/modeling_data_image015.png,"Illustrating the problem with AABB.",320}
+
+AABBs in this picture are interfered. Therefore, many OCCT-algorithms will spend much time to interfere the shapes. However, if we check OBBs, which are not interfered, then searching of interferences between the shapes will not be necessary. At that, creation and analysis of OBBs takes significantly more time than the analogical operations with AABB.
+
+Later in this section, the BndBox having the smallest surface area will be called as <b> optimal </b>.
+
+In OCCT, BndBox(es) are described in Bnd package. In general, Bnd_Box class describes AABB, Bnd_OBB class describes OBB. These classes contain the following common methods (this list is not complete; please see the documentation about corresponding class for detailed information):
+
+  - SetVoid() and IsVoid(). SetVoid method clears the existing BndBox. IsVoid method indicates whether the BndBox is initialized.
+  - Enlarge(...). Extends the current BndBox.
+  - Add(...). Rebuilds the current BndBox in order to cover all previous objects (which it was created from) and the argument of the method.
+  - IsOut(...). Checks whether the argument is inside/outside of the current BndBox.
+  
+Also, BRepBndLib class contains methods to provide creation of BndBox (both AABB and OBB) from the complex shape. 
+
+@subsection occt_modat_6_1 Brief description of some algorithms working with OBB
+
+@subsubsection occt_modat_6_1_1 Creation of OBB from set of points
+
+The algorithm is described in <a href="http://www.idt.mdh.se/~tla/publ/FastOBBs.pdf">"Fast Computation of Tight Fitting Oriented Bounding Boxes" by Thomas Larsson and Linus Källberg</a>. It includes the following steps:
+
+<span>1.</span> Choose \f$ N_{a} (N_{a} \geq 3) \f$ initial axes.<br>
+<span>2.</span> Project every given point to the every chosen (in item 1) axis. At that, "minimal" and "maximal" points of every axis (i.e. point having minimal and maximal parameter (correspondingly) of the projection to this axis) are chosen. I.e. \f$ 2*N_{a} \f$ points will be held and this set can contain equal points. Later (unless otherwise specified) in this algorithm we will work with these \f$ 2*N_{a} \f$ points only.<br>
+<span>3.</span> Choose one pair of points among all pairs of "minimal" and "maximal" points of every axis (from item 1), with two furthest points. Let \f$ p_{0} \f$  and \f$ p_{1} \f$  be the "minimal" and "maximal" point of this pair.<br>
+<span>4.</span> Create an axis \f$ \mathbf{e_{0}}\left \{ \overrightarrow{p_{0}p_{1}} \right \} \f$ (i.e. having direction \f$ \overrightarrow{p_{0}p_{1}} \f$ ).<br>
+<span>5.</span> Choose the point \f$ p_{2} \f$ (from the set defined in item 2) which is in the maximal distance from the infinite line directed along \f$ \mathbf{e_{0}} \f$ axis.<br>
+
+Further, let us consider the triangle \f$ T_{0}\left \langle p_{0}, p_{1}, p_{2} \right \rangle \f$ (i.e. having vertices \f$ p_{0}, p_{1} \f$ and \f$ p_{2} \f$). Namely:
+
+<span>6.</span> Create new axes: \f$ \mathbf{e_{1}}\left \{ \overrightarrow{p_{1}p_{2}} \right \} \f$, \f$ \mathbf{e_{2}}\left \{ \overrightarrow{p_{2}p_{0}} \right \} \f$, \f$ \mathbf{n}\left \{ \overrightarrow{\mathbf{e_{0}}} \times \overrightarrow{\mathbf{e_{1}}}  \right \} \f$, \f$ \mathbf{m_{0}}\left \{ \overrightarrow{\mathbf{e_{0}}} \times \overrightarrow{\mathbf{n}}  \right \} \f$, \f$ \mathbf{m_{1}}\left \{ \overrightarrow{\mathbf{e_{1}}} \times \overrightarrow{\mathbf{n}}  \right \} \f$, \f$ \mathbf{m_{2}}\left \{ \overrightarrow{\mathbf{e_{2}}} \times \overrightarrow{\mathbf{n}}  \right \} \f$.<br>
+<span>7.</span> Create OBBs based on the following axis: \f$ \left \{ \mathbf{e_{0}} \vdots \mathbf{m_{0}} \vdots \mathbf{n} \right \} \f$, \f$ \left \{ \mathbf{e_{1}} \vdots \mathbf{m_{1}} \vdots \mathbf{n} \right \} \f$ and \f$ \left \{ \mathbf{e_{2}} \vdots \mathbf{m_{2}} \vdots \mathbf{n} \right \} \f$ . Choose optimal OBB.<br>
+<span>8.</span> Choose the points \f$ q_{0} \f$ and \f$ q_{1} \f$ (from the set defined in item 2), which are in maximal distance from the plane of the triangle \f$ T_{0} \f$ (from both sides of this plane). At that, \f$ q_{0} \f$ has minimal coordinate along the axis \f$ \mathbf{n} \f$, \f$ q_{1} \f$ has a maximal coordinate.<br>
+<span>9.</span> Repeat the step 6...7 for the triangles \f$ T_{1}\left \langle p_{0}, p_{1}, q_{0} \right \rangle \f$, \f$ T_{2}\left \langle p_{1}, p_{2}, q_{0} \right \rangle \f$, \f$ T_{3}\left \langle p_{0}, p_{2}, q_{0} \right \rangle \f$, \f$ T_{4}\left \langle p_{0}, p_{1}, q_{1} \right \rangle \f$, \f$ T_{5}\left \langle p_{1}, p_{2}, q_{1} \right \rangle \f$, \f$ T_{6}\left \langle p_{0}, p_{2}, q_{1} \right \rangle \f$.<br>
+<span>10.</span> Compute the center of OBB and its half dimensions.<br>
+<span>11.</span> Create OBB using the center, axes and half dimensions.<br>
+
+This algorithm is realized in Bnd_OBB::ReBuild(...) method.
+
+@subsubsection occt_modat_6_1_2 Creation of OBB based on Axes of inertia
+
+The algorithm contains the following steps:
+1. Calculate three inertia axes, which will be the axes of the OBB.
+2. Transform the source object (TopoDS_Shape) into the local coordinate system based on the axes from item 1.
+3. Create an AABB for the shape obtained in the item 2.
+4. Compute the center of AABB and its half dimensions
+5. Transform the center into the WCS
+6. Create OBB using the center, axes and half dimensions.
+
+@subsubsection occt_modat_6_1_3 Method IsOut for a point
+
+1. Project the point to each axis.
+2. Check, whether the absolute value of the projection parameter greater than the correspond half-dimension. In this case, IsOut method will return TRUE.
+
+@subsubsection occt_modat_6_1_4 Method IsOut for another OBB
+
+According to the <a href="http://www.jkh.me/files/tutorials/Separating%20Axis%20Theorem%20for%20Oriented%20Bounding%20Boxes.pdf">"Separating Axis Theorem for Oriented Bounding Boxes"</a>, it is necessary to check the 15 separating axes: 6 axes of the boxes and 9 are their cross products.<br>
+The algorithm of analyzing axis \f$ \mathbf{l} \f$ is following:
+1. Compute the "length" according to the formula: \f$ L_{j}=\sum_{i=0}^{2}{H_{i}\cdot \left | \overrightarrow{\mathbf{a_{i}}} \cdot \overrightarrow{\mathbf{l}} \right |} \f$. Here, \f$ \mathbf{a_{i}} \f$ is an i-th axis (X-axis, Y-axis, Z-axis) of j-th BndBox (j=1...2). \f$ H_{i} \f$ is a half-dimension along i-th axis.
+2. If \f$ \left |\overrightarrow{C_{1}C_{2}} \cdot \overrightarrow{\mathbf{l}}  \right | > L_{1}+L_{2} \f$ (where \f$ C_{j} \f$ is the center of j-th OBB) then the considered OBBs are not interfered in terms of the axis \f$ \mathbf{l} \f$.
+
+If OBBs are not interfered in terms of at least one axis (of 15) then they are not interfered at all.
+
+@subsubsection occt_modat_6_1_5 Method Add for point or another BndBox
+
+Create new OBB (see the section @ref occt_modat_6_1_1) based on the source point and all vertices of the given BndBoxes.
+
+@subsection occt_modat_6_2 Add a shape
+
+Method BRepBndLib::AddOBB(...) allows creating BndBox from the complex object (TopoDS_Shape). This method uses both algorithms described in the sections @ref occt_modat_6_1_1 and sections @ref occt_modat_6_1_2.
+
+The first algorithm is used if the shape outer shell can be represented by a set of points contained in the shape. Namely, only the following elements are the source of set of points:
+
+  - Nodes of triangulation;
+  - Nodes of Poly_Polygon3D;
+  - Vertices of edges with linear 3D-curve lying in the planar face;
+  - Vertices of edges with linear 3D-curve if the source shape does not contain more complex topological structure (e.g. the source shape is a compound of edges);
+  - Vertices if the source shape does not contain more complex topological structure (e.g. the source shape is a compound of vertices).
+
+If required set of points cannot be extracted then the algorithm from section @ref occt_modat_6_1_2 is used for OBB creation.
+
+The package BRepBndLib contains the methods BRepBndLib::Add(...), BRepBndLib::AddClose(...) and BRepBndLib::AddOptimal(...) for creation of AABB of a shape. Please see reference manual for detailed information.
+
+@subsection occt_modat_6_3 Limitations of algorithm for OBB creation.
+
+1. The algorithm described in the section @ref occt_modat_6_1_1 works significantly better (finds resulting OBB with less surface area) and faster than the algorithm from the section @ref occt_modat_6_1_2. Nevertheless, (in general) the result returned by both algorithms is not always optimal (i.e. sometimes another OBB exists having less surface area). Moreover, the first method does not allow computing OBB of shapes with complex geometry.
+2. Currently, the algorithm of OBB creation is implemented for objects in 3D-space only.
index 64b79b6..3df642d 100644 (file)
@@ -41,11 +41,11 @@ tcopy bxx b10
 
 # make some boxes hollow
 for {set i 1} {$i <= 1} {incr i} {
-  set dim [boundingstr b$i]
-  set dx [expr [lindex $dim 3] - [lindex $dim 0]]
-  set x1 [expr [lindex $dim 0] + 0.1 * $dx]
-  set x2 [expr [lindex $dim 1] + 0.1 * $dx]
-  set x3 [expr [lindex $dim 2] + 0.1 * $dx]
+  set dim [bounding -s b$i -save xmin ymin zmin xmax ymax zmax]
+  set dx [dval xmax-xmin]
+  set x1 [dval xmin+0.1*$dx]
+  set x2 [dval ymin+0.1*$dx]
+  set x3 [dval zmin+0.1*$dx]
   box bc $x1 $x2 $x3 0.8*$dx 0.8*$dx $dx
   bcut bb b$i bc
   tcopy bb b$i
index 47dbe29..94fef6a 100644 (file)
@@ -135,7 +135,7 @@ vfit
 
 # add dimension:
 # detect vertices extremal in X direction
-boundingstr snowflake x1 y1 z1 x2 y2 z2
+bounding -s snowflake -save x1 y1 z1 x2 y2 z2
 plane f1 x1 0 0 1 0 0
 plane f2 x2 0 0 1 0 0
 mkface f1 f1
index 1c0f8ed..6f34387 100644 (file)
@@ -24,6 +24,7 @@
 #include <Standard_Boolean.hxx>
 class TopoDS_Shape;
 class Bnd_Box;
+class Bnd_OBB;
 
 
 //! This package provides the bounding boxes for curves
@@ -82,6 +83,25 @@ public:
                                           const Standard_Boolean useShapeTolerance = Standard_False);
 
 
+  //! Computes the Oriented Bounding box for the shape <theS>.
+  //! Two independent methods of computation are implemented:
+  //! first method based on set of points (so, it demands the
+  //! triangulated shape or shape with planar faces and linear edges).
+  //! The second method is based on use of inertia axes and is called
+  //! if use of the first method is impossible.
+  //! If theIsTriangulationUsed == FALSE then the triangulation will
+  //! be ignored at all. 
+  //! If theIsShapeToleranceUsed == TRUE then resulting box will be
+  //! extended on the tolerance of the shape.
+  //! theIsOptimal flag defines the algorithm for construction of initial
+  //! Bnd_Box for the second method (if theIsOptimal == TRUE then
+  //! this box will be created by AddOptimal(...) method).
+  Standard_EXPORT static 
+    void AddOBB(const TopoDS_Shape& theS,
+                Bnd_OBB& theOBB,
+                const Standard_Boolean theIsTriangulationUsed = Standard_True,
+                const Standard_Boolean theIsOptimal = Standard_False,
+                const Standard_Boolean theIsShapeToleranceUsed = Standard_True);
 
 protected:
 
diff --git a/src/BRepBndLib/BRepBndLib_1.cxx b/src/BRepBndLib/BRepBndLib_1.cxx
new file mode 100644 (file)
index 0000000..4eea3f2
--- /dev/null
@@ -0,0 +1,494 @@
+// Copyright (c) 1999-2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Adaptor3d_HCurve.hxx>
+#include <Adaptor3d_HSurface.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <BRepBndLib.hxx>
+#include <GProp_GProps.hxx>
+#include <TopoDS_Shape.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <Bnd_OBB.hxx>
+#include <BRepGProp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <GProp_PrincipalProps.hxx>
+#include <gp_Ax3.hxx>
+#include <BRepBuilderAPI_Transform.hxx>
+#include <Bnd_Box.hxx>
+#include <NCollection_List.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Line.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+
+#include <Geom_OffsetCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_BezierCurve.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_BezierSurface.hxx>
+
+//=======================================================================
+// Function : IsLinear
+// purpose : Returns TRUE if theC is line-like.
+//=======================================================================
+static Standard_Boolean IsLinear(const Adaptor3d_Curve& theC)
+{
+  const GeomAbs_CurveType aCT = theC.GetType();
+  if(aCT == GeomAbs_OffsetCurve)
+  {
+    return IsLinear(GeomAdaptor_Curve(theC.OffsetCurve()->BasisCurve()));
+  }
+
+  if((aCT == GeomAbs_BSplineCurve) || (aCT == GeomAbs_BezierCurve))
+  {
+    // Indeed, curves with C0-continuity and degree==1, may be 
+    // represented with set of points. It will be possible made
+    // in the future.
+
+    return ((theC.Degree() == 1) &&
+            (theC.Continuity() != GeomAbs_C0));
+  }
+
+  if(aCT == GeomAbs_Line)
+  {
+    return Standard_True;
+  }
+
+  return Standard_False;
+}
+
+//=======================================================================
+// Function : IsPlanar
+// purpose : Returns TRUE if theS is plane-like.
+//=======================================================================
+static Standard_Boolean IsPlanar(const Adaptor3d_Surface& theS)
+{
+  const GeomAbs_SurfaceType aST = theS.GetType();
+  if(aST == GeomAbs_OffsetSurface)
+  {
+    return IsPlanar(theS.BasisSurface()->Surface());
+  }
+
+  if(aST == GeomAbs_SurfaceOfExtrusion)
+  {
+    return IsLinear(theS.BasisCurve()->Curve());
+  }
+
+  if((aST == GeomAbs_BSplineSurface) || (aST == GeomAbs_BezierSurface))
+  {
+    if((theS.UDegree() != 1) || (theS.VDegree() != 1))
+      return Standard_False;
+
+    // Indeed, surfaces with C0-continuity and degree==1, may be 
+    // represented with set of points. It will be possible made
+    // in the future.
+
+    return ((theS.UContinuity() != GeomAbs_C0) && (theS.VContinuity() != GeomAbs_C0));
+  }
+
+  if(aST == GeomAbs_Plane)
+  {
+    return Standard_True;
+  }
+
+  return Standard_False;
+}
+
+//=======================================================================
+// Function : PointsForOBB
+// purpose : Returns number of points for array.
+//
+// Attention!!! 
+//  1. Start index for thePts must be 0 strictly.
+//  2. Currently, infinite edges/faces (e.g. half-space) are not
+//      processed correctly because computation of UV-bounds is a costly operation.
+//=======================================================================
+static Standard_Integer PointsForOBB(const TopoDS_Shape& theS,
+                                     const Standard_Boolean theIsTriangulationUsed,
+                                     TColgp_Array1OfPnt* thePts = 0,
+                                     TColStd_Array1OfReal* theArrOfToler = 0)
+{
+  Standard_Integer aRetVal = 0;
+  TopExp_Explorer anExpF, anExpE;
+
+  // get all vertices from the shape
+  for(anExpF.Init(theS, TopAbs_VERTEX); anExpF.More(); anExpF.Next())
+  {
+    const TopoDS_Vertex &aVert = TopoDS::Vertex(anExpF.Current());
+    if(thePts)
+    {
+      const gp_Pnt aP = BRep_Tool::Pnt(aVert);
+      (*thePts)(aRetVal) = aP;
+    }
+
+    if(theArrOfToler)
+    {
+      (*theArrOfToler) (aRetVal) = BRep_Tool::Tolerance(aVert);
+    }
+
+    ++aRetVal;
+  }
+
+  if(aRetVal == 0)
+    return 0;
+
+  // analyze the faces of the shape on planarity and existence of triangulation
+  TopLoc_Location aLoc;
+  for(anExpF.Init(theS, TopAbs_FACE); anExpF.More(); anExpF.Next())
+  {
+    const TopoDS_Face &aF = TopoDS::Face(anExpF.Current());
+    const BRepAdaptor_Surface anAS(aF, Standard_False);
+
+    if (!IsPlanar(anAS.Surface()))
+    {
+      if (!theIsTriangulationUsed)
+        // not planar and triangulation usage disabled
+        return 0;
+    }
+    else
+    {
+      // planar face
+      for(anExpE.Init(aF, TopAbs_EDGE); anExpE.More(); anExpE.Next())
+      {
+        const TopoDS_Edge &anE = TopoDS::Edge(anExpE.Current());
+        const BRepAdaptor_Curve anAC(anE);
+        if (!IsLinear(anAC))
+        {
+          if (!theIsTriangulationUsed)
+            // not linear and triangulation usage disabled
+            return 0;
+
+          break;
+        }
+      }
+
+      if (!anExpE.More())
+        // skip planar face with linear edges as its vertices have already been added
+        continue;
+    }
+
+    // Use triangulation of the face
+    const Handle(Poly_Triangulation) &aTrng = BRep_Tool::Triangulation(aF, aLoc);
+    if (aTrng.IsNull())
+      // no triangulation on the face
+      return 0;
+
+    const Standard_Integer aCNode = aTrng->NbNodes();
+    const TColgp_Array1OfPnt& aNodesArr = aTrng->Nodes();
+    for (Standard_Integer i = 1; i <= aCNode; i++)
+    {
+      if (thePts)
+      {
+        const gp_Pnt aP = aLoc.IsIdentity() ? aNodesArr(i) :
+          aNodesArr(i).Transformed(aLoc);
+        (*thePts)(aRetVal) = aP;
+      }
+
+      if (theArrOfToler)
+      {
+        (*theArrOfToler) (aRetVal) = aTrng->Deflection();
+      }
+
+      ++aRetVal;
+    }
+  }
+
+  // Consider edges without faces
+
+  for(anExpE.Init(theS, TopAbs_EDGE, TopAbs_FACE); anExpE.More(); anExpE.Next())
+  {
+    const TopoDS_Edge &anE = TopoDS::Edge(anExpE.Current());
+    const BRepAdaptor_Curve anAC(anE);
+
+    if (IsLinear(anAC))
+      // skip linear edge as its vertices have already been added
+      continue;
+
+    if (!theIsTriangulationUsed)
+      // not linear and triangulation usage disabled
+      return 0;
+
+    const Handle(Poly_Polygon3D) &aPolygon = BRep_Tool::Polygon3D(anE, aLoc);
+    if (aPolygon.IsNull())
+      return 0;
+
+    const Standard_Integer aCNode = aPolygon->NbNodes();
+    const TColgp_Array1OfPnt& aNodesArr = aPolygon->Nodes();
+    for (Standard_Integer i = 1; i <= aCNode; i++)
+    {
+      if (thePts)
+      {
+        const gp_Pnt aP = aLoc.IsIdentity() ? aNodesArr(i) :
+          aNodesArr(i).Transformed(aLoc);
+        (*thePts)(aRetVal) = aP;
+      }
+
+      if (theArrOfToler)
+      {
+        (*theArrOfToler) (aRetVal) = aPolygon->Deflection();
+      }
+
+      ++aRetVal;
+    }
+  }
+
+  return aRetVal;
+}
+
+//=======================================================================
+// Function : IsWCS
+// purpose : Returns 0 if the theDir does not match any axis of WCS.
+//            Otherwise, returns the index of correspond axis.
+//=======================================================================
+static Standard_Integer IsWCS(const gp_Dir& theDir)
+{
+  const Standard_Real aToler = Precision::Angular()*Precision::Angular();
+
+  const Standard_Real aX = theDir.X(),
+                      aY = theDir.Y(),
+                      aZ = theDir.Z();
+
+  const Standard_Real aVx = aY*aY + aZ*aZ,
+                      aVy = aX*aX + aZ*aZ,
+                      aVz = aX*aX + aY*aY;
+
+  if(aVz < aToler)
+    return 3; // Z-axis
+
+  if(aVy < aToler)
+    return 2; // Y-axis
+
+  if(aVx < aToler)
+    return 1; // X-axis
+
+  return 0;
+}
+
+//=======================================================================
+// Function : CheckPoints
+// purpose : Collects points for DiTO algorithm for OBB construction on
+//            linear/planar shapes and shapes having triangulation
+//            (http://www.idt.mdh.se/~tla/publ/FastOBBs.pdf).
+//=======================================================================
+static Standard_Boolean CheckPoints(const TopoDS_Shape& theS,
+                                    const Standard_Boolean theIsTriangulationUsed,
+                                    const Standard_Boolean theIsShapeToleranceUsed,
+                                    Bnd_OBB& theOBB)
+{
+  const Standard_Integer aNbPnts = PointsForOBB(theS, theIsTriangulationUsed);
+
+  if(aNbPnts < 1)
+    return Standard_False;
+
+  TColgp_Array1OfPnt anArrPnts(0, theOBB.IsVoid() ? aNbPnts - 1 : aNbPnts + 7);
+  TColStd_Array1OfReal anArrOfTolerances;
+  if(theIsShapeToleranceUsed)
+  {
+    anArrOfTolerances.Resize(anArrPnts.Lower(), anArrPnts.Upper(), Standard_False);
+    anArrOfTolerances.Init(0.0);
+  }
+
+  TColStd_Array1OfReal *aPtrArrTol = theIsShapeToleranceUsed ? &anArrOfTolerances : 0;
+
+  PointsForOBB(theS, theIsTriangulationUsed, &anArrPnts, aPtrArrTol);
+
+  if(!theOBB.IsVoid())
+  {
+    // All points of old OBB have zero-tolerance
+    theOBB.GetVertex(&anArrPnts(aNbPnts));
+  }
+
+#if 0
+  for(Standard_Integer i = anArrPnts.Lower(); i <= anArrPnts.Upper(); i++)
+  {
+    const gp_Pnt &aP = anArrPnts(i);
+    std::cout << "point p" << i << " " << aP.X() << ", " << 
+                                          aP.Y() << ", " << 
+                                          aP.Z() << ", "<< std::endl;
+  }
+#endif
+
+  theOBB.ReBuild(anArrPnts, aPtrArrTol);
+
+  return (!theOBB.IsVoid());
+}
+
+//=======================================================================
+// Function : ComputeProperties
+// purpose : Computes properties of theS.
+//=======================================================================
+static void ComputeProperties(const TopoDS_Shape& theS,
+                              GProp_GProps& theGCommon)
+{
+  TopExp_Explorer anExp;
+  for(anExp.Init(theS, TopAbs_SOLID); anExp.More(); anExp.Next())
+  {
+    GProp_GProps aG;
+    BRepGProp::VolumeProperties(anExp.Current(), aG, Standard_True);
+    theGCommon.Add(aG);
+  }
+
+  for(anExp.Init(theS, TopAbs_FACE, TopAbs_SOLID); anExp.More(); anExp.Next())
+  {
+    GProp_GProps aG;
+    BRepGProp::SurfaceProperties(anExp.Current(), aG, Standard_True);
+    theGCommon.Add(aG);
+  }
+
+  for(anExp.Init(theS, TopAbs_EDGE, TopAbs_FACE); anExp.More(); anExp.Next())
+  {
+    GProp_GProps aG;
+    BRepGProp::LinearProperties(anExp.Current(), aG, Standard_True);
+    theGCommon.Add(aG);
+  }
+
+  for(anExp.Init(theS, TopAbs_VERTEX, TopAbs_EDGE); anExp.More(); anExp.Next())
+  {
+    GProp_GProps aG(BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current())));
+    theGCommon.Add(aG);
+  }
+}
+
+//=======================================================================
+// Function : ComputePCA
+// purpose : Creates OBB with axes of inertia.
+//=======================================================================
+static void ComputePCA(const TopoDS_Shape& theS,
+                       Bnd_OBB& theOBB,
+                       const Standard_Boolean theIsTriangulationUsed,
+                       const Standard_Boolean theIsOptimal,
+                       const Standard_Boolean theIsShapeToleranceUsed)
+{
+  // Compute the transformation matrix to obtain more tight bounding box
+  GProp_GProps aGCommon;
+  ComputeProperties(theS, aGCommon);
+
+  // Transform the shape to the local coordinate system
+  gp_Trsf aTrsf;
+
+  const Standard_Integer anIdx1 =
+                  IsWCS(aGCommon.PrincipalProperties().FirstAxisOfInertia());
+  const Standard_Integer anIdx2 =
+                  IsWCS(aGCommon.PrincipalProperties().SecondAxisOfInertia());
+
+  if((anIdx1 == 0) || (anIdx2 == 0))
+  {
+    // Coordinate system in which the shape will have the optimal bounding box
+    gp_Ax3 aLocCoordSys(aGCommon.CentreOfMass(),
+                        aGCommon.PrincipalProperties().ThirdAxisOfInertia(),
+                        aGCommon.PrincipalProperties().FirstAxisOfInertia());
+    aTrsf.SetTransformation(aLocCoordSys);
+  }
+
+  const TopoDS_Shape aST = (aTrsf.Form() == gp_Identity) ? theS :
+                                              theS.Moved(TopLoc_Location(aTrsf));
+
+  // Initial axis-aligned BndBox
+  Bnd_Box aShapeBox;
+  if(theIsOptimal)
+  {
+    BRepBndLib::AddOptimal(aST, aShapeBox, theIsTriangulationUsed, theIsShapeToleranceUsed);
+  }
+  else
+  {
+    BRepBndLib::Add(aST, aShapeBox);
+  }
+
+  gp_Pnt aPMin = aShapeBox.CornerMin();
+  gp_Pnt aPMax = aShapeBox.CornerMax();
+
+  gp_XYZ aXDir(1, 0, 0);
+  gp_XYZ aYDir(0, 1, 0);
+  gp_XYZ aZDir(0, 0, 1);
+
+  // Compute the center of the box
+  gp_XYZ aCenter = (aPMin.XYZ() + aPMax.XYZ()) / 2.;
+
+  // Compute the half diagonal size of the box.
+  // It takes into account the gap.
+  gp_XYZ anOBBHSize = (aPMax.XYZ() - aPMin.XYZ()) / 2.;
+
+  // Apply transformation if necessary
+  if(aTrsf.Form() != gp_Identity)
+  {
+    aTrsf.Invert();
+    aTrsf.Transforms(aCenter);
+
+    // Make transformation
+    const Standard_Real * aMat = &aTrsf.HVectorialPart().Value(1, 1);
+    // Compute axes directions of the box
+    aXDir = gp_XYZ(aMat[0], aMat[3], aMat[6]);
+    aYDir = gp_XYZ(aMat[1], aMat[4], aMat[7]);
+    aZDir = gp_XYZ(aMat[2], aMat[5], aMat[8]);
+  }
+
+  if(theOBB.IsVoid())
+  {
+    // Create the OBB box
+
+    // Set parameters to the OBB
+    theOBB.SetCenter(aCenter);
+
+    theOBB.SetXComponent(aXDir, anOBBHSize.X());
+    theOBB.SetYComponent(aYDir, anOBBHSize.Y());
+    theOBB.SetZComponent(aZDir, anOBBHSize.Z());
+    theOBB.SetAABox(aTrsf.Form() == gp_Identity);
+  }
+  else
+  {
+    // Recreate the OBB box
+
+    TColgp_Array1OfPnt aListOfPnts(0, 15);
+    theOBB.GetVertex(&aListOfPnts(0));
+
+    const Standard_Real aX = anOBBHSize.X();
+    const Standard_Real aY = anOBBHSize.Y();
+    const Standard_Real aZ = anOBBHSize.Z();
+
+    const gp_XYZ aXext = aX*aXDir,
+                 aYext = aY*aYDir,
+                 aZext = aZ*aZDir;
+
+    Standard_Integer aPntIdx = 8;
+    aListOfPnts(aPntIdx++) = aCenter - aXext - aYext - aZext;
+    aListOfPnts(aPntIdx++) = aCenter + aXext - aYext - aZext;
+    aListOfPnts(aPntIdx++) = aCenter - aXext + aYext - aZext;
+    aListOfPnts(aPntIdx++) = aCenter + aXext + aYext - aZext;
+    aListOfPnts(aPntIdx++) = aCenter - aXext - aYext + aZext;
+    aListOfPnts(aPntIdx++) = aCenter + aXext - aYext + aZext;
+    aListOfPnts(aPntIdx++) = aCenter - aXext + aYext + aZext;
+    aListOfPnts(aPntIdx++) = aCenter + aXext + aYext + aZext;
+
+    theOBB.ReBuild(aListOfPnts);
+  }
+}
+
+//=======================================================================
+// Function : AddOBB
+// purpose : 
+//=======================================================================
+void BRepBndLib::AddOBB(const TopoDS_Shape& theS,
+                        Bnd_OBB& theOBB,
+                        const Standard_Boolean theIsTriangulationUsed,
+                        const Standard_Boolean theIsOptimal,
+                        const Standard_Boolean theIsShapeToleranceUsed)
+{
+  if(CheckPoints(theS, theIsTriangulationUsed, theIsShapeToleranceUsed, theOBB))
+    return;
+
+  ComputePCA(theS, theOBB, theIsTriangulationUsed, theIsOptimal, theIsShapeToleranceUsed);
+}
index 0f4ba8b..d05bed4 100644 (file)
@@ -1,2 +1,3 @@
 BRepBndLib.cxx
 BRepBndLib.hxx
+BRepBndLib_1.cxx
\ No newline at end of file
index b520085..19e93bb 100644 (file)
 #include <DrawTrSurf.hxx>
 #include <Geom_Plane.hxx>
 
+#include <OSD_Timer.hxx>
 #include <Draw_Segment3D.hxx>
 #include <Draw_Marker3D.hxx>
 #include <Draw_MarkerShape.hxx>
-
+#include <BRepPrimAPI_MakeBox.hxx>
 #include <stdio.h>
 
 Standard_IMPORT Draw_Viewer dout;
 
-
+//=======================================================================
+//function : ConvertBndToShape
+//purpose  : Creates TopoDS_Solid from theBox
+//=======================================================================
+static void ConvertBndToShape(const Bnd_OBB& theBox,
+                              const char* const theName)
+{
+  const gp_Pnt &aBaryCenter = theBox.Center();
+  const gp_XYZ &aXDir = theBox.XDirection(),
+               &aYDir = theBox.YDirection(),
+               &aZDir = theBox.ZDirection();
+  Standard_Real aHalfX = theBox.XHSize(),
+                aHalfY = theBox.YHSize(),
+                aHalfZ = theBox.ZHSize();
+
+  gp_Ax2 anAxes(aBaryCenter, aZDir, aXDir);
+  anAxes.SetLocation(aBaryCenter.XYZ() - aHalfX*aXDir - aHalfY*aYDir - aHalfZ*aZDir);
+  TopoDS_Solid aBox = BRepPrimAPI_MakeBox(anAxes, 2.0*aHalfX, 2.0*aHalfY, 2.0*aHalfZ);
+  DBRep::Set(theName, aBox);
+}
 
 //=======================================================================
 // addpcurve
@@ -400,31 +420,6 @@ static Standard_Integer orientsolid(Draw_Interpretor& ,Standard_Integer n,const
 
 }
 
-//=======================================================================
-//function : boundingstr
-//purpose  : 
-//=======================================================================
-static Standard_Integer boundingstr(Draw_Interpretor& di,Standard_Integer n,const char** a)
-{
-  if (n < 2) return 1;
-  TopoDS_Shape S = DBRep::Get(a[1]);
-  if (S.IsNull()) return 1;
-  Bnd_Box B;
-  BRepBndLib::Add(S,B);
-  Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
-  B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
-  di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
-  if (n >= 8) {
-    Draw::Set(a[2],axmin) ;
-    Draw::Set(a[3],aymin) ;
-    Draw::Set(a[4],azmin) ;
-    Draw::Set(a[5],axmax) ;
-    Draw::Set(a[6],aymax) ;
-    Draw::Set(a[7],azmax) ;
-  }
-  return 0;
-}
-
 //=======================================================================
 //function : getcoords
 //purpose  : 
@@ -454,76 +449,380 @@ static Standard_Integer getcoords(Draw_Interpretor& di,Standard_Integer n,const
 }
 
 //=======================================================================
-//function : bounding
+//function : BoundBox
 //purpose  : 
 //=======================================================================
-static Standard_Integer bounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
+static Standard_Integer BoundBox(Draw_Interpretor& theDI,
+                                 Standard_Integer theNArg,
+                                 const char** theArgVal)
 {
-  if (n < 2) return 1;
-  Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
-  Bnd_Box B; Handle(Draw_Box) DB;
+  if(theNArg < 2)
+  {
+    theDI << "Use: " << theArgVal[0] << " {-s shape | -c xmin ymin zmin xmax ymax zmax} "
+             "[-obb]\n\t\t[-shape name] [-dump] [-notriangulation]\n\t\t"
+             "[-perfmeter name NbIters] [-nodraw] [-optimal] [-exttoler]\n\t\t"
+             "[-save xmin ymin zmin xmax ymax zmax]\n\n\n";
+
+    theDI << "Computes a bounding box (BndBox). Two types of the source data are supported:\n";
+    theDI << "  * \"-s\"-option sets the shape, which will be circumscribed by the BndBox;\n";
+    theDI << "  * \"-c\"-option sets two opposite corners (having (xmin, ymin, zmin) and\n\t"
+             "(xmax, ymax, zmax) coordinates) of the resulting\n\taxis-aligned BndBox (AABB).\n";
+    theDI << "\nThe following options are supported:\n";
+    theDI << "  * \"-obb\". If it is switched on then the oriented BndBox (OBB) will "
+             "be\n\tcreated. Otherwise, AABB will be created.\n";
+    theDI << "  * \"-shape\". If it is switched on then the resulting BndBox will be "
+             "stored\n\tas a shape (solid) with specified name.\n";
+    theDI << "  * \"-nodraw\". If it is switched on then the resulting BndBox will not be\n\t"
+             "drawn as DRAW-object.\n";
+    theDI << "  * \"-dump\". Prints the information about the created BndBox.\n";
+    theDI << "  * \"-notriangulation\". By default, AABB is built from existing mesh.\n\t"
+             "This option allows ignoring triangulation.\n";
+    theDI << "  * \"-save\". Stores the information about created AABB in "
+             "specified variables.\n";
+    theDI << "  * \"-optimal\". If it is switched on then the AABB will be optimal.\n\t"
+             "This option is useful for OBB, too. It allows constructing\n\toptimal "
+             "initial AABB.\n";
+    theDI << "  * \"-exttoler\". If it is switched on then the resulting box will be "
+             "extended\n\ton the tolerance of the source shape.\n";
+    theDI << "  * \"-perfmeter\" - Auxiliary option. It provides compatibility "
+             "with\n\tOCCT-test system. \"name\" is the counter name for "
+             "\"chrono\"-TCL-command.\n\tNbIters is the number of iterations.\n";
+    return 1;
+  }
+
+  TopoDS_Shape aShape;
   
-  if (n == 2) { 
-    TopoDS_Shape S = DBRep::Get(a[1]);
-    if (S.IsNull()) return 1;
-    BRepBndLib::Add(S,B);
-    B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
-    DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_orange);
-    dout<<DB;
-    di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
+  Standard_Boolean isOBB = Standard_False;
+  Standard_Boolean hasToPrint = Standard_False,
+                   isTriangulationReq = Standard_True,
+                   isOptimal = Standard_False,
+                   isTolerUsed = Standard_False,
+                   hasToDraw = Standard_True;
+  Standard_Integer aNbIters = 1;
+  Standard_Integer aStartIdxToSave = -1,
+                   aStartIdxToCreate = -1,
+                   aNameToShape = -1,
+                   anIdxCounterName = -1;
+
+  for(Standard_Integer anAIdx = 1; anAIdx < theNArg; anAIdx++)
+  {
+    if(theArgVal[anAIdx][0] != '-')
+    {
+      theDI << "Error: Wrong option \"" << theArgVal[anAIdx] << 
+               "\". Please use \'-\' symbol\n";
+      return 1;
+    }
+
+    if(!strcmp(theArgVal[anAIdx], "-s"))
+    {
+      aShape = DBRep::Get(theArgVal[++anAIdx]);
+      if(aShape.IsNull())
+      {
+        theDI << "Error: Argument " << theArgVal[anAIdx] << " is not a shape.\n";
+        return 1;
+      }
+    }
+    else if(!strcmp(theArgVal[anAIdx], "-c"))
+    {
+      aStartIdxToCreate = anAIdx + 1;
+      anAIdx += 6;
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-obb", 4))
+    {
+      isOBB = Standard_True;
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-shape", 4))
+    {
+      aNameToShape = ++anAIdx;
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-dump", 4))
+    {
+      hasToPrint = Standard_True;
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-save", 4))
+    {
+      aStartIdxToSave = anAIdx+1;
+      anAIdx += 6;
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-notriangulation", 9))
+    {
+      isTriangulationReq = Standard_False;
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-perfmeter", 8))
+    {
+      anIdxCounterName = ++anAIdx;
+      aNbIters = Draw::Atoi(theArgVal[++anAIdx]);
+    }
+    else if(!strncmp(theArgVal[anAIdx], "-optimal", 4))
+    {
+      isOptimal = Standard_True;
+    }
+    else if(!strcmp(theArgVal[anAIdx], "-exttoler"))
+    {
+      isTolerUsed = Standard_True;
+    }
+    else if(!strcmp(theArgVal[anAIdx], "-nodraw"))
+    {
+      hasToDraw = Standard_False;
+    }
+    else
+    {
+      theDI << "Error: Unknown option  \"" << theArgVal[anAIdx] << "\".\n";
+      return 1;
+    }
   }
-  else if (n == 7) {
-    axmin=Draw::Atof(a[1]);
-    aymin=Draw::Atof(a[2]);
-    azmin=Draw::Atof(a[3]);
-    axmax=Draw::Atof(a[4]);
-    aymax=Draw::Atof(a[5]);
-    azmax=Draw::Atof(a[6]);
-    DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_orange);
-    dout<<DB;
+
+  if(aShape.IsNull() && (aStartIdxToCreate < 0))
+  {
+    theDI << "Error: One of the options \'-s\' or \'-c\' must be set necessarily.\n";
+    return 1;
   }
+
+  if(aStartIdxToCreate > 0)
+  {
+    if(!aShape.IsNull())
+    {
+      theDI << "Error: Options \'-s\' and \'-c\' are fail for using simultaneously.\n";
+      return 1;
+    }
+    else if(isOBB)
+    {
+      theDI << "Error: Options \'-c\' and \"-obb\" are fail for using simultaneously.\n";
+      return 1;
+    }
+  }
+
+  if(isOptimal)
+  {
+    if(aShape.IsNull())
+    {
+      theDI << "Error: Options \"-optimal\" is used without any shape. "
+               "Use \'-s\'-option.\n";
+      return 1;
+    }
+  }
+
+  if(isTolerUsed)
+  {
+    if(aShape.IsNull())
+    {
+      theDI << "Error: Option \"-exttoler\" is used without any shape. "
+        "Use \'-s\'-option.\n";
+      return 1;
+    }
+  }
+
+  Handle(Draw_Box) aDB;
+  OSD_Timer aTimer;
+
+  if(isOBB)
+  {
+    if(aStartIdxToSave > 0)
+    {
+      theDI << "Error: Option \"-save\" work only with axes-aligned boxes.\n";
+      return 1;
+    }
+
+    Bnd_OBB anOBB;
+    Standard_Integer aN = aNbIters;
+
+    aTimer.Start();
+    while(aN-- > 0)
+    {
+      anOBB.SetVoid();
+      BRepBndLib::AddOBB(aShape, anOBB, isTriangulationReq, isOptimal, isTolerUsed);
+    }
+    aTimer.Stop();
+
+    if(anOBB.IsVoid())
+    {
+      theDI << "Void box.\n";
+      hasToPrint = Standard_False;
+    }
+
+    const gp_Pnt &aBaryCenter= anOBB.Center();
+    const gp_XYZ &aXDir = anOBB.XDirection(),
+                 &aYDir = anOBB.YDirection(),
+                 &aZDir = anOBB.ZDirection();
+    Standard_Real aHalfX = anOBB.XHSize(), 
+                  aHalfY = anOBB.YHSize(),
+                  aHalfZ = anOBB.ZHSize();
+
+    if(hasToPrint)
+    {
+      theDI << "Oriented bounding box\n";
+      theDI << "Center: " << aBaryCenter.X() << " " << 
+                             aBaryCenter.Y() << " " <<
+                             aBaryCenter.Z() << "\n";
+      theDI << "X-axis: " << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
+      theDI << "Y-axis: " << aYDir.X() << " " << aYDir.Y() << " " << aYDir.Z() << "\n";
+      theDI << "Z-axis: " << aZDir.X() << " " << aZDir.Y() << " " << aZDir.Z() << "\n";
+      theDI << "Half X: " << aHalfX << "\n" << 
+               "Half Y: " << aHalfY << "\n" << "Half Z: " << aHalfZ << "\n";
+    }
+    
+    if(hasToDraw)
+      aDB = new Draw_Box(anOBB, Draw_orange);
+
+    if(aNameToShape > 0)
+    {
+      ConvertBndToShape(anOBB, theArgVal[aNameToShape]);
+    }
+  }
+  else // if(!isOBB)
+  {
+    Standard_Real aXmin = RealFirst(), aYmin = RealFirst(), aZmin = RealFirst(),
+                  aXMax = RealLast(), aYMax = RealLast(), aZMax = RealLast();
+
+    Bnd_Box anAABB;
+
+    if(aStartIdxToCreate < 0)
+    {
+      Standard_Integer aN = aNbIters;
+      if(isOptimal)
+      {
+        aTimer.Start();
+        while(aN-- > 0)
+        {
+          anAABB.SetVoid();
+          BRepBndLib::AddOptimal(aShape, anAABB, isTriangulationReq, isTolerUsed);
+        }
+        aTimer.Stop();
+      }
+      else
+      {
+        aTimer.Start();
+        while(aN-- > 0)
+        {
+          anAABB.SetVoid();
+          BRepBndLib::Add(aShape, anAABB, isTriangulationReq);
+        }
+        aTimer.Stop();
+      }
+    }
+    else
+    {
+      if(anIdxCounterName > 0)
+      {
+        theDI << "Error: Option \"-perfmeter\"does not work if the option \'-c\' "
+                 "is switched on.\n";
+        return 1;
+      }
+
+      Standard_Integer anIdx = aStartIdxToCreate;
+      aXmin = Draw::Atof(theArgVal[anIdx++]);
+      aYmin = Draw::Atof(theArgVal[anIdx++]);
+      aZmin = Draw::Atof(theArgVal[anIdx++]);
+      aXMax = Draw::Atof(theArgVal[anIdx++]);
+      aYMax = Draw::Atof(theArgVal[anIdx++]);
+      aZMax = Draw::Atof(theArgVal[anIdx++]);
+
+      anAABB.Add(gp_Pnt(aXmin, aYmin, aZmin));
+      anAABB.Add(gp_Pnt(aXMax, aYMax, aZMax));
+    }
+
+    if(anAABB.IsVoid())
+    {
+      theDI << "Void box.\n";
+      hasToPrint = Standard_False;
+    }
+
+    if(hasToPrint || (aStartIdxToSave>0))
+    {
+      anAABB.Get(aXmin, aYmin, aZmin, aXMax, aYMax, aZMax);
+
+      if(hasToPrint)
+      {
+        theDI << "Axes-aligned bounding box\n";
+        theDI << "X-range: " << aXmin << " " << aXMax << "\n" <<
+                 "Y-range: " << aYmin << " " << aYMax << "\n" <<
+                 "Z-range: " << aZmin << " " << aZMax << "\n";
+      }
+
+      if(aStartIdxToSave > 0)
+      {
+        Draw::Set(theArgVal[aStartIdxToSave++], aXmin);
+        Draw::Set(theArgVal[aStartIdxToSave++], aYmin);
+        Draw::Set(theArgVal[aStartIdxToSave++], aZmin);
+        Draw::Set(theArgVal[aStartIdxToSave++], aXMax);
+        Draw::Set(theArgVal[aStartIdxToSave++], aYMax);
+        Draw::Set(theArgVal[aStartIdxToSave++], aZMax);
+      }
+    }
+
+    if(hasToDraw)
+      aDB = new Draw_Box(anAABB, Draw_orange);
+
+    if(aNameToShape > 0)
+    {
+      ConvertBndToShape(anAABB, theArgVal[aNameToShape]);
+    }
+  }
+
+  if(hasToDraw)
+    dout << aDB;
+
+  if(anIdxCounterName > 0)
+  {
+    theDI << "COUNTER " << theArgVal[anIdxCounterName] << ": " << aTimer.ElapsedTime() << "\n";
+  }
+
   return 0;
 }
+
 //=======================================================================
-//function : optbounding
+//function : IsBoxesInterfered
 //purpose  : 
 //=======================================================================
-static Standard_Integer optbounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
+static Standard_Integer IsBoxesInterfered(Draw_Interpretor& theDI,
+                                          Standard_Integer theNArg,
+                                          const char** theArgVal)
 {
-  if (n < 2)
-  {
-    di << "Usage: optbounding shape [usetri [usetol]]\n";
-    di << "usetri and usetol can be 0 or 1, by default usetri = 1, usetol = 0\n";
-    return 1;
-  }
-  Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
-  Bnd_Box B; Handle(Draw_Box) DB;
-  
-  TopoDS_Shape S = DBRep::Get(a[1]);
-  if (S.IsNull()) 
+  if(theNArg < 2)
   {
-    di << "Null shape\n";
+    theDI << "Use: isbbinterf shape1 shape2 [-o].\n";
     return 1;
   }
-  Standard_Boolean useTri = Standard_True;
-  Standard_Boolean useTol = Standard_False;
-  if(n > 2 )
+
+  const TopoDS_Shape aShape1 = DBRep::Get(theArgVal[1]);
+  const TopoDS_Shape aShape2 = DBRep::Get(theArgVal[2]);
+
+  Standard_Boolean isOBB = (theNArg > 3) && (!strcmp(theArgVal[3], "-o"));
+
+  if(isOBB)
   {
-    Standard_Integer ii = atoi(a[2]);
-    useTri = ii > 0;
+    Bnd_OBB anOBB1, anOBB2;
+    BRepBndLib::AddOBB(aShape1, anOBB1);
+    BRepBndLib::AddOBB(aShape2, anOBB2);
+
+    if(anOBB1.IsOut(anOBB2))
+    {
+      theDI << "The shapes are NOT interfered by OBB.\n";
+    }
+    else
+    {
+      theDI << "The shapes are interfered by OBB.\n";
+    }
   }
-  if(n > 3 )
+  else
   {
-    Standard_Integer ii = atoi(a[3]);
-    useTol = ii > 0;
+    Bnd_Box anAABB1, anAABB2;
+    BRepBndLib::Add(aShape1, anAABB1);
+    BRepBndLib::Add(aShape2, anAABB2);
+
+    if(anAABB1.IsOut(anAABB2))
+    {
+      theDI << "The shapes are NOT interfered by AABB.\n";
+    }
+    else
+    {
+      theDI << "The shapes are interfered by AABB.\n";
+    }
   }
-  BRepBndLib::AddOptimal(S, B, useTri, useTol);
-  B.Get(axmin, aymin, azmin, axmax, aymax, azmax);
-  DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_vert);
-  dout<<DB;
-  di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
+
   return 0;
 }
+
 //=======================================================================
 //function : gbounding
 //purpose  : 
@@ -600,7 +899,7 @@ static Standard_Integer gbounding(Draw_Interpretor& di,Standard_Integer n,const
     if (Is3d)
     {
       B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
-      DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_vert);
+      DB = new Draw_Box(B, Draw_vert);
       dout<<DB;
       di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
     }
@@ -1208,25 +1507,21 @@ void  BRepTest::BasicCommands(Draw_Interpretor& theCommands)
     __FILE__,
     getcoords,g);
   
-  theCommands.Add("bounding",
-                 "bounding shape [ xmin ymin zmin xmax ymax zmax] ; draw bounds",
-                 __FILE__,
-                 bounding,g);
+  theCommands.Add("bounding", "enter the comand w/o any arguments to obtain the help.",
+                  __FILE__, BoundBox, g);
 
-  theCommands.Add("optbounding",
-                 "optbounding shape [usetri (0/1) [usetol (0/1)]] ; ",
-                 __FILE__,
-                 optbounding,g);
  //
   theCommands.Add("gbounding",
                  "gbounding surf/curve/curve2d [-o] ",
                  __FILE__,
                  gbounding,g);
 
-  theCommands.Add("boundingstr",
-                 "boundingstr shape [ xmin ymin zmin xmax ymax zmax] ; print bounding box",
-                 __FILE__,
-                 boundingstr,g);
+  theCommands.Add("isbbinterf", "isbbinterf shape1 shape2 [-o]\n"
+                  "Checks whether the bounding-boxes created from "
+                  "the given shapes are interfered. If \"-o\"-option "
+                  "is switched on then the oriented boxes will be checked. "
+                  "Otherwise, axes-aligned boxes will be checked.",
+                  __FILE__, IsBoxesInterfered, g);
 
   theCommands.Add("nurbsconvert",
                  "nurbsconvert result name [result name]",
diff --git a/src/Bnd/Bnd_OBB.cxx b/src/Bnd/Bnd_OBB.cxx
new file mode 100644 (file)
index 0000000..e9b7f36
--- /dev/null
@@ -0,0 +1,679 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Bnd_OBB.hxx>
+
+#include <Bnd_B3d.hxx>
+#include <NCollection_Array1.hxx>
+#include <Precision.hxx>
+#include <TColStd_Array1OfReal.hxx>
+
+class OBBTool
+{
+public:
+  //! Constructor. theL - list of points.
+  //! theLT is a pointer to the list of tolerances
+  //! (i-th element of this array is a tolerance
+  //! of i-th point in theL). If theLT is empty
+  //! then the tolerance of every point is equal to 0.
+  //! Attention! The objects, which theL and theLT links on,
+  //! must be available during all time of OBB creation
+  //! (i.e. while the object of OBBTool exists).
+  OBBTool(const TColgp_Array1OfPnt& theL,
+          const TColStd_Array1OfReal *theLT = 0);
+
+  //! DiTO algorithm for OBB construction
+  //! (http://www.idt.mdh.se/~tla/publ/FastOBBs.pdf)
+  void ProcessDiTetrahedron();
+
+  //! Creates OBB with already computed parameters
+  void BuildBox(Bnd_OBB& theBox);
+
+protected:
+  //! Works with the triangle set by the points in myTriIdx.
+  //! If theIsBuiltTrg == TRUE, new set of triangles will be
+  //! recomputed.
+  void ProcessTriangle(const Standard_Integer theIdx1,
+                       const Standard_Integer theIdx2,
+                       const Standard_Integer theIdx3,
+                       const Standard_Boolean theIsBuiltTrg);
+
+  //! Computes myTriIdx[2]
+  void FillToTriangle3();
+
+  //! Computes myTriIdx[3] and myTriIdx[4]
+  void FillToTriangle5(const gp_XYZ& theNormal,
+                       const gp_XYZ& theBarryCenter);
+
+  //! Returns half of the Surface area of the box
+  static Standard_Real ComputeQuality(const Standard_Real* const thePrmArr)
+  {
+    const Standard_Real aDX = thePrmArr[1] - thePrmArr[0],
+                        aDY = thePrmArr[3] - thePrmArr[2],
+                        aDZ = thePrmArr[5] - thePrmArr[4];
+
+    return (aDX*aDY + aDY*aDZ + aDX*aDZ);
+  }
+
+protected:
+  //! Assignment operator is forbidden
+  OBBTool& operator=(const OBBTool&);
+
+private:
+  //! Number of the initial axes.
+  static const Standard_Integer myNbInitAxes = 7;
+
+  //! Number of extremal points
+  static const Standard_Integer myNbExtremalPoints = 2 * myNbInitAxes;
+
+  //! The source list of points
+  const TColgp_Array1OfPnt& myPntsList;
+
+  //! Pointer to the array of tolerances
+  const TColStd_Array1OfReal *myListOfTolers;
+
+  //! Points of ditetrahedron
+  //! given by their indices in myLExtremalPoints.
+  Standard_Integer myTriIdx[5];
+
+  //! List of extremal points
+  gp_XYZ myLExtremalPoints[myNbExtremalPoints];
+
+  //! The axes of the box (always normalized or
+  //! can be null-vector)
+  gp_XYZ myAxes[3];
+
+  //! The surface area of the OBB
+  Standard_Real myQualityCriterion;
+};
+
+//=======================================================================
+// Function : SetMinMax
+// purpose : 
+//    ATTENTION!!! thePrmArr must be initialized before this method calling.
+//=======================================================================
+static inline void SetMinMax(Standard_Real* const thePrmArr,
+                             const Standard_Real theNewParam)
+{
+  if(theNewParam < thePrmArr[0])
+  {
+    thePrmArr[0] = theNewParam;
+  }
+  else if(theNewParam > thePrmArr[1])
+  {
+    thePrmArr[1] = theNewParam;
+  }
+}
+
+//=======================================================================
+// Function : Constructor
+// purpose : 
+//=======================================================================
+OBBTool::
+    OBBTool(const TColgp_Array1OfPnt& theL,
+            const TColStd_Array1OfReal *theLT) :myPntsList(theL),
+                                                myListOfTolers(theLT),
+                                                myQualityCriterion(RealLast())
+{
+  const Standard_Real aSqrt3 = Sqrt(3);
+  // Origin of all initial axis is (0,0,0).
+  // All axes must be normalized.
+  const gp_XYZ anInitialAxesArray[myNbInitAxes] = {gp_XYZ(1.0, 0.0, 0.0),
+                                                   gp_XYZ(0.0, 1.0, 0.0),
+                                                   gp_XYZ(0.0, 0.0, 1.0),
+                                                   gp_XYZ(1.0, 1.0, 1.0) / aSqrt3,
+                                                   gp_XYZ(1.0, 1.0, -1.0) / aSqrt3,
+                                                   gp_XYZ(1.0, -1.0, 1.0) / aSqrt3,
+                                                   gp_XYZ(1.0, -1.0, -1.0) / aSqrt3};
+
+  // Minimal and maximal point on every axis
+  const Standard_Integer aNbPoints = 2 * myNbInitAxes;
+
+  for(Standard_Integer i = 0; i < 5; i++)
+  {
+    myTriIdx[i] = INT_MAX;
+  }
+  
+  // Min and Max parameter
+  Standard_Real aParams[aNbPoints];
+  for(Standard_Integer i = 0; i < aNbPoints; i += 2)
+  {
+    aParams[i] = RealLast();
+    aParams[i + 1] = RealFirst();
+  }
+
+  // Look for the extremal points (myLExtremalPoints)
+  for(Standard_Integer i = myPntsList.Lower() ; i <= myPntsList.Upper(); i++)
+  {
+    const gp_XYZ &aCurrPoint = myPntsList(i).XYZ();
+    for(Standard_Integer anAxeInd = 0, aPrmInd = 0; anAxeInd < myNbInitAxes; anAxeInd++, aPrmInd++)
+    {
+      const Standard_Real aParam = aCurrPoint.Dot(anInitialAxesArray[anAxeInd]);
+      if(aParam < aParams[aPrmInd])
+      {
+        myLExtremalPoints[aPrmInd] = aCurrPoint;
+        aParams[aPrmInd] = aParam;
+      }
+      aPrmInd++;
+
+      if(aParam > aParams[aPrmInd])
+      {
+        myLExtremalPoints[aPrmInd] = aCurrPoint;
+        aParams[aPrmInd] = aParam;
+      }
+    }
+  }
+
+  // Compute myTriIdx[0] and myTriIdx[1].
+
+  Standard_Real aMaxSqDist = -1.0;
+  for(Standard_Integer aPrmInd = 0; aPrmInd < aNbPoints; aPrmInd += 2)
+  {
+    const gp_Pnt &aP1 = myLExtremalPoints[aPrmInd],
+                 &aP2 = myLExtremalPoints[aPrmInd + 1];
+    const Standard_Real aSqDist = aP1.SquareDistance(aP2);
+    if(aSqDist > aMaxSqDist)
+    {
+      aMaxSqDist = aSqDist;
+      myTriIdx[0] = aPrmInd;
+      myTriIdx[1] = aPrmInd + 1;
+    }
+  }
+
+  FillToTriangle3();
+}
+
+//=======================================================================
+// Function : FillToTriangle3
+// purpose : Two value of myTriIdx array is known. Let us find myTriIdx[2].
+//            It must be in maximal distance from the infinite axis going
+//            through the points with indexes myTriIdx[0] and myTriIdx[1].
+//=======================================================================
+void OBBTool::FillToTriangle3()
+{
+  const gp_XYZ &aP0 = myLExtremalPoints[myTriIdx[0]];
+  const gp_XYZ anAxis = myLExtremalPoints[myTriIdx[1]] - aP0;
+  Standard_Real aMaxSqDist = -1.0;
+  for(Standard_Integer i = 0; i < myNbExtremalPoints; i++)
+  {
+    if((i == myTriIdx[0]) || (i == myTriIdx[1]))
+      continue;
+
+    const gp_XYZ &aP = myLExtremalPoints[i];
+    const Standard_Real aDistToAxe = anAxis.CrossSquareMagnitude(aP - aP0);
+    if(aDistToAxe > aMaxSqDist)
+    {
+      myTriIdx[2] = i;
+      aMaxSqDist = aDistToAxe;
+    }
+  }
+}
+
+//=======================================================================
+// Function : FillToTriangle5
+// purpose : Three value of myTriIdx array is known.
+//            Let us find myTriIdx[3] and myTriIdx[4].
+//           They must be in the different sides of the plane of
+//            triangle set by points myTriIdx[0], myTriIdx[1] and
+//            myTriIdx[2]. Moreover, the distance from these points
+//            to the triangle plane must be maximal.
+//=======================================================================
+void OBBTool::FillToTriangle5(const gp_XYZ& theNormal,
+                              const gp_XYZ& theBarryCenter)
+{
+  Standard_Real aParams[2] = {0.0, 0.0};
+
+  for(Standard_Integer aPtIdx = 0; aPtIdx < myNbExtremalPoints; aPtIdx++)
+  {
+    if((aPtIdx == myTriIdx[0]) || (aPtIdx == myTriIdx[1]) || (aPtIdx == myTriIdx[2]))
+      continue;
+
+    const gp_XYZ &aCurrPoint = myLExtremalPoints[aPtIdx];
+    const Standard_Real aParam = theNormal.Dot(aCurrPoint - theBarryCenter);
+
+    if(aParam < aParams[0])
+    {
+      myTriIdx[3] = aPtIdx;
+      aParams[0] = aParam;
+    }
+    else if(aParam > aParams[1])
+    {
+      myTriIdx[4] = aPtIdx;
+      aParams[1] = aParam;
+    }
+  }
+
+  // The points must be in the different sides of the triangle plane.
+  if(aParams[0] > -Precision::Confusion())
+  {
+    myTriIdx[3] = INT_MAX;
+  }
+
+  if(aParams[1] < Precision::Confusion())
+  {
+    myTriIdx[4] = INT_MAX;
+  }
+}
+
+//=======================================================================
+// Function : ProcessTriangle
+// purpose : Choose the optimal box with triple axes containing normal
+//            to the triangle and some edge of the triangle (3rd axis is
+//            computed from these two ones).
+//=======================================================================
+void OBBTool::ProcessTriangle(const Standard_Integer theIdx1,
+                              const Standard_Integer theIdx2,
+                              const Standard_Integer theIdx3,
+                              const Standard_Boolean theIsBuiltTrg)
+{
+  const Standard_Integer aNbAxes = 3;
+
+  //Some vertex of the triangle
+  const gp_XYZ aP0 = myLExtremalPoints[theIdx1];
+
+  // All axes must be normalized in order to provide correct area computation
+  // (see ComputeQuality(...) method).
+  gp_XYZ aYAxis[aNbAxes] = {(myLExtremalPoints[theIdx2] - myLExtremalPoints[theIdx1]),
+                            (myLExtremalPoints[theIdx3] - myLExtremalPoints[theIdx2]),
+                            (myLExtremalPoints[theIdx1] - myLExtremalPoints[theIdx3])};
+
+  // Normal to the triangle plane
+  gp_XYZ aZAxis = aYAxis[0].Crossed(aYAxis[1]);
+
+  Standard_Real aSqMod = aZAxis.SquareModulus();
+
+  if(aSqMod < Precision::SquareConfusion())
+    return;
+
+  aZAxis /= Sqrt(aSqMod);
+
+  gp_XYZ aXAxis[aNbAxes];
+  for(Standard_Integer i = 0; i < aNbAxes; i++)
+  {
+    aXAxis[i] = aYAxis[i].Crossed(aZAxis).Normalized();
+    aYAxis[i].Normalize();
+  }
+
+  if(theIsBuiltTrg)
+    FillToTriangle5(aZAxis, aP0);
+
+  // Min and Max parameter
+  const Standard_Integer aNbPoints = 2 * aNbAxes;
+  
+  Standard_Integer aMinIdx = -1;
+  for(Standard_Integer anAxeInd = 0; anAxeInd < aNbAxes; anAxeInd++)
+  {
+    const gp_XYZ &aAX = aXAxis[anAxeInd],
+                 &aAY = aYAxis[anAxeInd];
+
+    Standard_Real aParams[aNbPoints] = {0.0, 0.0, 0.0,
+                                        0.0, 0.0, 0.0};
+
+    for(Standard_Integer aPtIdx = 0; aPtIdx < myNbExtremalPoints; aPtIdx++)
+    {
+      if(aPtIdx == theIdx1)
+        continue;
+
+      const gp_XYZ aCurrPoint = myLExtremalPoints[aPtIdx] - aP0;
+      SetMinMax(&aParams[0], aAX.Dot(aCurrPoint));
+      SetMinMax(&aParams[2], aAY.Dot(aCurrPoint));
+      SetMinMax(&aParams[4], aZAxis.Dot(aCurrPoint));
+    }
+
+    const Standard_Real anArea = ComputeQuality(aParams);
+    if(anArea < myQualityCriterion)
+    {
+      myQualityCriterion = anArea;
+      aMinIdx = anAxeInd;
+    }
+  }
+
+  if(aMinIdx < 0)
+    return;
+
+  myAxes[0] = aXAxis[aMinIdx];
+  myAxes[1] = aYAxis[aMinIdx];
+  myAxes[2] = aZAxis;
+}
+//=======================================================================
+// Function : ProcessDiTetrahedron
+// purpose : DiTo-algorithm (http://www.idt.mdh.se/~tla/publ/FastOBBs.pdf)
+//=======================================================================
+void OBBTool::ProcessDiTetrahedron()
+{
+  ProcessTriangle(myTriIdx[0], myTriIdx[1], myTriIdx[2], Standard_True);
+
+  if(myTriIdx[3] <= myNbExtremalPoints)
+  {
+    ProcessTriangle(myTriIdx[0], myTriIdx[1], myTriIdx[3], Standard_False);
+    ProcessTriangle(myTriIdx[1], myTriIdx[2], myTriIdx[3], Standard_False);
+    ProcessTriangle(myTriIdx[0], myTriIdx[2], myTriIdx[3], Standard_False);
+  }
+
+  if(myTriIdx[4] <= myNbExtremalPoints)
+  {
+    ProcessTriangle(myTriIdx[0], myTriIdx[1], myTriIdx[4], Standard_False);
+    ProcessTriangle(myTriIdx[1], myTriIdx[2], myTriIdx[4], Standard_False);
+    ProcessTriangle(myTriIdx[0], myTriIdx[2], myTriIdx[4], Standard_False);
+  }
+}
+
+//=======================================================================
+// Function : BuildBox
+// purpose : 
+//=======================================================================
+void OBBTool::BuildBox(Bnd_OBB& theBox)
+{
+  theBox.SetVoid();
+
+  // In fact, use Precision::SquareConfusion().
+  const Standard_Boolean isOBB = myAxes[0].SquareModulus()*
+                                 myAxes[1].SquareModulus()*
+                                 myAxes[2].SquareModulus() > 1.0e-14;
+
+  const gp_Dir aXDir = isOBB ? myAxes[0] : gp_Dir(1, 0, 0);
+  const gp_Dir aYDir = isOBB ? myAxes[1] : gp_Dir(0, 1, 0);
+  const gp_Dir aZDir = isOBB ? myAxes[2] : gp_Dir(0, 0, 1);
+
+  const Standard_Integer aNbPoints = 6;
+  Standard_Real aParams[aNbPoints];
+
+  gp_XYZ aFCurrPoint = myPntsList.First().XYZ();
+  
+  aParams[0] = aParams[1] = aFCurrPoint.Dot(aXDir.XYZ());
+  aParams[2] = aParams[3] = aFCurrPoint.Dot(aYDir.XYZ());
+  aParams[4] = aParams[5] = aFCurrPoint.Dot(aZDir.XYZ());
+
+  if(myListOfTolers != 0)
+  {
+    const Standard_Real aTol = myListOfTolers->First();
+    aParams[0] -= aTol;
+    aParams[1] += aTol;
+    aParams[2] -= aTol;
+    aParams[3] += aTol;
+    aParams[4] -= aTol;
+    aParams[5] += aTol;
+  }
+
+  for(Standard_Integer i = myPntsList.Lower() + 1; i <= myPntsList.Upper(); i++)
+  {
+    const gp_XYZ &aCurrPoint = myPntsList(i).XYZ();
+    const Standard_Real aDx = aCurrPoint.Dot(aXDir.XYZ()),
+                        aDy = aCurrPoint.Dot(aYDir.XYZ()),
+                        aDz = aCurrPoint.Dot(aZDir.XYZ());
+        
+    if(myListOfTolers == 0)
+    {
+      SetMinMax(&aParams[0], aDx);
+      SetMinMax(&aParams[2], aDy);
+      SetMinMax(&aParams[4], aDz);
+    }
+    else
+    {
+      const Standard_Real aTol = myListOfTolers->Value(i);
+      aParams[0] = Min(aParams[0], aDx - aTol);
+      aParams[1] = Max(aParams[1], aDx + aTol);
+      aParams[2] = Min(aParams[2], aDy - aTol);
+      aParams[3] = Max(aParams[3], aDy + aTol);
+      aParams[4] = Min(aParams[4], aDz - aTol);
+      aParams[5] = Max(aParams[5], aDz + aTol);
+    }
+  }
+
+  //Half-sizes
+  const Standard_Real aHX = 0.5*(aParams[1] - aParams[0]);
+  const Standard_Real aHY = 0.5*(aParams[3] - aParams[2]);
+  const Standard_Real aHZ = 0.5*(aParams[5] - aParams[4]);
+
+  const gp_XYZ aCenter = 0.5*((aParams[1] + aParams[0])*aXDir.XYZ() +
+                              (aParams[3] + aParams[2])*aYDir.XYZ() +
+                              (aParams[5] + aParams[4])*aZDir.XYZ());
+
+  theBox.SetCenter(aCenter);
+  theBox.SetXComponent(aXDir, aHX);
+  theBox.SetYComponent(aYDir, aHY);
+  theBox.SetZComponent(aZDir, aHZ);
+  theBox.SetAABox(!isOBB);
+}
+
+// =======================================================================
+// function : ReBuild
+// purpose  : http://www.idt.mdh.se/~tla/publ/
+// =======================================================================
+void Bnd_OBB::ReBuild(const TColgp_Array1OfPnt& theListOfPoints,
+                      const TColStd_Array1OfReal *theListOfTolerances)
+{
+  switch(theListOfPoints.Length())
+  {
+    case 1:
+      ProcessOnePoint(theListOfPoints.First());
+      if(theListOfTolerances)
+        Enlarge(theListOfTolerances->First());
+      return;
+    case 2:
+    {
+      const Standard_Real aTol1 = (theListOfTolerances == 0) ? 0.0 :
+                                      theListOfTolerances->First();
+
+      const Standard_Real aTol2 = (theListOfTolerances == 0) ? 0.0 :
+                                      theListOfTolerances->Last();
+      
+      const gp_XYZ &aP1 = theListOfPoints.First().XYZ(),
+                   &aP2 = theListOfPoints.Last().XYZ();
+      const gp_XYZ aDP = aP2 - aP1;
+      const Standard_Real aDPm = aDP.Modulus();
+      myIsAABox = Standard_False;
+      myHDims[1] = myHDims[2] = Max(aTol1, aTol2);
+
+      if(aDPm < Precision::Confusion())
+      {
+        ProcessOnePoint(aP1);
+        Enlarge(myHDims[1] + Precision::Confusion());
+        return;
+      }
+
+      myHDims[0] = 0.5*(aDPm+aTol1+aTol2);
+      myAxes[0] = aDP/aDPm;
+      if(Abs(myAxes[0].X()) > Abs(myAxes[0].Y()))
+      {
+        // Z-coord. is maximal or X-coord. is maximal
+        myAxes[1].SetCoord(-myAxes[0].Z(), 0.0, myAxes[0].X());
+      }
+      else
+      {
+        // Z-coord. is maximal or Y-coord. is maximal
+        myAxes[1].SetCoord(0.0, -myAxes[0].Z(), myAxes[0].Y());
+      }
+
+      myAxes[2] = myAxes[0].Crossed(myAxes[1]).Normalized();
+      myCenter = aP1 + 0.5*(aDPm - aTol1 + aTol2)*myAxes[0];
+    }
+    return;
+    default:
+      break;
+  }
+
+  OBBTool aTool(theListOfPoints, theListOfTolerances);
+  aTool.ProcessDiTetrahedron();
+  aTool.BuildBox(*this);
+}
+
+// =======================================================================
+// function : IsOut
+// purpose  : 
+// =======================================================================
+Standard_Boolean Bnd_OBB::IsOut(const Bnd_OBB& theOther) const
+{
+  if (IsVoid() || theOther.IsVoid())
+    return Standard_True;
+
+  if (myIsAABox && theOther.myIsAABox)
+  {
+    return ((Abs(theOther.myCenter.X() - myCenter.X()) > theOther.myHDims[0] + myHDims[0]) ||
+            (Abs(theOther.myCenter.Y() - myCenter.Y()) > theOther.myHDims[1] + myHDims[1]) ||
+            (Abs(theOther.myCenter.Z() - myCenter.Z()) > theOther.myHDims[2] + myHDims[2]));
+  }
+
+  // According to the Separating Axis Theorem for Oriented Bounding Boxes
+  // it is necessary to check the 15 separating axes (Ls):
+  // - 6 axes of the boxes;
+  // - 9 cross products of the axes of the boxes.
+  // If any of these axes is valid, the boxes do not interfere.
+
+  // The algorithm is following:
+  // 1. Compute the "length" for j-th BndBox (j=1...2) according to the formula:
+  //    L(j)=Sum(myHDims[i]*Abs(myAxes[i].Dot(Ls)))
+  // 2. If (theCenter2 - theCenter1).Dot(Ls) > (L(1) + L(2))
+  //    then the considered OBBs are not interfered in terms of the axis Ls.
+  //
+  // If OBBs are not interfered in terms of at least one axis (of 15) then
+  // they are not interfered at all.
+
+  // Precomputed difference between centers
+  gp_XYZ D = theOther.myCenter - myCenter;
+
+  // Check the axes of the this box, i.e. L is one of myAxes
+  // Since the Dot product of two of these directions is null, it could be skipped:
+  // myXDirection.Dot(myYDirection) = 0
+
+  for(Standard_Integer i = 0; i < 3; ++i)
+  {
+    // Length of the second segment
+    Standard_Real aLSegm2 = 0;
+    for(Standard_Integer j = 0; j < 3; ++j)
+      aLSegm2 += theOther.myHDims[j] * Abs(theOther.myAxes[j].Dot(myAxes[i]));
+
+    // Distance between projected centers
+    Standard_Real aDistCC = Abs(D.Dot(myAxes[i]));
+
+    if(aDistCC > myHDims[i] + aLSegm2)
+      return Standard_True;
+  }
+
+  // Check the axes of the Other box, i.e. L is one of theOther.myAxes
+
+  for(Standard_Integer i = 0; i < 3; ++i)
+  {
+    // Length of the first segment
+    Standard_Real aLSegm1 = 0.;
+    for(Standard_Integer j = 0; j < 3; ++j)
+      aLSegm1 += myHDims[j] * Abs(myAxes[j].Dot(theOther.myAxes[i]));
+
+    // Distance between projected centers
+    Standard_Real aDistCC = Abs(D.Dot(theOther.myAxes[i]));
+
+    if(aDistCC > aLSegm1 + theOther.myHDims[i])
+      return Standard_True;
+  }
+
+  const Standard_Real aTolNull = Epsilon(1.0);
+
+  // Check the axes produced by the cross products
+  for(Standard_Integer i = 0; i < 3; ++i)
+  {
+    for(Standard_Integer j = 0; j < 3; ++j)
+    {
+      // Separating axis
+      gp_XYZ aLAxe = myAxes[i].Crossed(theOther.myAxes[j]);
+
+      const Standard_Real aNorm = aLAxe.Modulus();
+      if(aNorm < aTolNull)
+        continue;
+
+      aLAxe /= aNorm;
+
+      // Length of the first segment
+      Standard_Real aLSegm1 = 0.;
+      for(Standard_Integer k = 0; k < 3; ++k)
+        aLSegm1 += myHDims[k] * Abs(myAxes[k].Dot(aLAxe));
+
+      // Length of the second segment
+      Standard_Real aLSegm2 = 0.;
+      for(Standard_Integer k = 0; k < 3; ++k)
+        aLSegm2 += theOther.myHDims[k] * Abs(theOther.myAxes[k].Dot(aLAxe));
+
+      // Distance between projected centers
+      Standard_Real aDistCC = Abs(D.Dot(aLAxe));
+
+      if(aDistCC > aLSegm1 + aLSegm2)
+        return Standard_True;
+    }
+  }
+
+  return Standard_False;
+}
+
+// =======================================================================
+// function : IsOut
+// purpose  : 
+// =======================================================================
+Standard_Boolean Bnd_OBB::IsOut(const gp_Pnt& theP) const
+{
+  // 1. Project the point to myAxes[i] (i=0...2).
+  // 2. Check, whether the absolute value of the correspond
+  //    projection parameter is greater than myHDims[i].
+  //    In this case, IsOut method will return TRUE.
+
+  const gp_XYZ aRV = theP.XYZ() - myCenter;
+
+  return ((Abs(myAxes[0].Dot(aRV)) > myHDims[0]) || 
+          (Abs(myAxes[1].Dot(aRV)) > myHDims[1]) ||
+          (Abs(myAxes[2].Dot(aRV)) > myHDims[2]));
+}
+
+// =======================================================================
+// function : IsCompletelyInside
+// purpose  : Checks if every vertex of theOther is completely inside *this
+// =======================================================================
+Standard_Boolean Bnd_OBB::IsCompletelyInside(const Bnd_OBB& theOther) const
+{
+  if(IsVoid() || theOther.IsVoid())
+    return Standard_False;
+
+  gp_Pnt aVert[8];
+  theOther.GetVertex(aVert);
+  for(Standard_Integer i = 0; i < 8; i++)
+  {
+    if(IsOut(aVert[i]))
+      return Standard_False;
+  }
+
+  return Standard_True;
+}
+
+// =======================================================================
+// function : Add
+// purpose  : 
+// =======================================================================
+void Bnd_OBB::Add(const gp_Pnt& theP)
+{
+  gp_Pnt aList[9];
+  GetVertex(aList);
+  aList[8] = theP;
+
+  ReBuild(TColgp_Array1OfPnt(aList[0], 0, 8));
+}
+
+// =======================================================================
+// function : Add
+// purpose  : 
+// =======================================================================
+void Bnd_OBB::Add(const Bnd_OBB& theOther)
+{
+  gp_Pnt aList[16];
+  GetVertex(&aList[0]);
+  theOther.GetVertex(&aList[8]);
+  ReBuild(TColgp_Array1OfPnt(aList[0], 0, 15));
+}
+
diff --git a/src/Bnd/Bnd_OBB.hxx b/src/Bnd/Bnd_OBB.hxx
new file mode 100644 (file)
index 0000000..e5f43ad
--- /dev/null
@@ -0,0 +1,290 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Bnd_OBB_HeaderFile
+#define _Bnd_OBB_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+#include <Standard_Real.hxx>
+#include <Standard_Boolean.hxx>
+
+#include <Bnd_Box.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_XYZ.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+
+//! The class describes the Oriented Bounding Box (OBB),
+//! much tighter enclosing volume for the shape than the
+//! Axis Aligned Bounding Box (AABB).
+//! The OBB is defined by a center of the box, the axes and the halves
+//! of its three dimensions.
+//! The OBB can be used more effectively than AABB as a rejection mechanism
+//! for non-interfering objects.
+class Bnd_OBB
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  //! Empty constructor
+  Bnd_OBB() :myIsAABox(Standard_False)
+  {
+    myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
+  }
+
+  //! Constructor taking all defining parameters
+  Bnd_OBB(const gp_Pnt& theCenter,
+          const gp_Dir& theXDirection,
+          const gp_Dir& theYDirection,
+          const gp_Dir& theZDirection,
+          const Standard_Real theHXSize,
+          const Standard_Real theHYSize,
+          const Standard_Real theHZSize) :myCenter (theCenter.XYZ()),
+                                          myIsAABox(Standard_False)
+  {
+    myAxes[0] = theXDirection.XYZ();
+    myAxes[1] = theYDirection.XYZ();
+    myAxes[2] = theZDirection.XYZ();
+
+    Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
+    Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
+    Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
+    
+    myHDims[0] = theHXSize;
+    myHDims[1] = theHYSize;
+    myHDims[2] = theHZSize;
+  }
+
+  //! Constructor to create OBB from AABB.
+  Bnd_OBB(const Bnd_Box& theBox) : myIsAABox(Standard_True)
+  {
+    Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2;
+    theBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);
+
+    myAxes[0].SetCoord(1.0, 0.0, 0.0);
+    myAxes[1].SetCoord(0.0, 1.0, 0.0);
+    myAxes[2].SetCoord(0.0, 0.0, 1.0);
+
+    myHDims[0] = 0.5*(aX2 - aX1);
+    myHDims[1] = 0.5*(aY2 - aY1);
+    myHDims[2] = 0.5*(aZ2 - aZ1);
+
+    myCenter.SetCoord(0.5*(aX2 + aX1), 0.5*(aY2 + aY1), 0.5*(aZ2 + aZ1));
+  }
+
+  //! Created new OBB covering every point in theListOfPoints.
+  //! Tolerance of every such point is set by *theListOfTolerances array.
+  //! If this array is not void (not null-pointer) then the resulted Bnd_OBB
+  //! will be enlarged using tolerances of points lying on the box surface.
+  Standard_EXPORT void ReBuild(const TColgp_Array1OfPnt& theListOfPoints,
+                               const TColStd_Array1OfReal *theListOfTolerances = 0);
+
+  //! Sets the center of OBB
+  void SetCenter(const gp_Pnt& theCenter)
+  {
+    myCenter = theCenter.XYZ();
+  }
+
+    //! Sets the X component of OBB - direction and size
+  void SetXComponent(const gp_Dir& theXDirection,
+                     const Standard_Real theHXSize)
+  {
+    Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
+
+    myAxes[0] = theXDirection.XYZ();
+    myHDims[0] = theHXSize;
+  }
+
+  //! Sets the Y component of OBB - direction and size
+  void SetYComponent(const gp_Dir& theYDirection,
+                     const Standard_Real theHYSize)
+  {
+    Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
+
+    myAxes[1] = theYDirection.XYZ();
+    myHDims[1] = theHYSize;
+  }
+
+  //! Sets the Z component of OBB - direction and size
+  void SetZComponent(const gp_Dir& theZDirection,
+                     const Standard_Real theHZSize)
+  {
+    Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
+
+    myAxes[2] = theZDirection.XYZ();
+    myHDims[2] = theHZSize;
+  }
+  
+  //! Returns the center of OBB
+  const gp_XYZ& Center() const
+  {
+    return myCenter;
+  }
+
+  //! Returns the X Direction of OBB
+  const gp_XYZ& XDirection() const
+  {
+    return myAxes[0];
+  }
+
+  //! Returns the Y Direction of OBB
+  const gp_XYZ& YDirection() const
+  {
+    return myAxes[1];
+  }
+
+  //! Returns the Z Direction of OBB
+  const gp_XYZ& ZDirection() const
+  {
+    return myAxes[2];
+  }
+
+  //! Returns the X Dimension of OBB
+  Standard_Real XHSize() const
+  {
+    return myHDims[0];
+  }
+
+  //! Returns the Y Dimension of OBB
+  Standard_Real YHSize() const
+  {
+    return myHDims[1];
+  }
+
+  //! Returns the Z Dimension of OBB
+  Standard_Real ZHSize() const
+  {
+    return myHDims[2];
+  }
+
+  //! Checks if the box is empty.
+  Standard_Boolean IsVoid() const
+  {
+    return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0));
+  }
+
+  //! Clears this box
+  void SetVoid()
+  {
+    myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
+    myCenter = myAxes[0] = myAxes[1] = myAxes[2] = gp_XYZ();
+    myIsAABox = Standard_False;
+  }
+
+  //! Sets the flag for axes aligned box
+  void SetAABox(const Standard_Boolean& theFlag)
+  {
+    myIsAABox = theFlag;
+  }
+
+  //! Returns TRUE if the box is axes aligned
+  Standard_Boolean IsAABox() const
+  {
+    return myIsAABox;
+  }
+
+  //! Enlarges the box with the given value
+  void Enlarge(const Standard_Real theGapAdd)
+  {
+    const Standard_Real aGap = Abs(theGapAdd);
+    myHDims[0] += aGap;
+    myHDims[1] += aGap;
+    myHDims[2] += aGap;
+  }
+
+  //! Returns the array of vertices in <this>.
+  //! The local coordinate of the vertex depending on the
+  //! index of the array are follow:
+  //! Index == 0: (-XHSize(), -YHSize(), -ZHSize())
+  //! Index == 1: ( XHSize(), -YHSize(), -ZHSize())
+  //! Index == 2: (-XHSize(),  YHSize(), -ZHSize())
+  //! Index == 3: ( XHSize(),  YHSize(), -ZHSize())
+  //! Index == 4: (-XHSize(), -YHSize(),  ZHSize())
+  //! Index == 5: ( XHSize(), -YHSize(),  ZHSize())
+  //! Index == 6: (-XHSize(),  YHSize(),  ZHSize())
+  //! Index == 7: ( XHSize(),  YHSize(),  ZHSize()).
+  Standard_Boolean GetVertex(gp_Pnt theP[8]) const
+  {
+    if(IsVoid())
+      return Standard_False;
+
+    theP[0].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
+    theP[1].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
+    theP[2].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
+    theP[3].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
+    theP[4].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
+    theP[5].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
+    theP[6].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
+    theP[7].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
+
+    return Standard_True;
+  }
+
+  //! Returns square diagonal of this box
+  Standard_Real SquareExtent() const
+  {
+    return (4.0*myHDims[0] * myHDims[0] + 
+            myHDims[1] * myHDims[1] +
+            myHDims[1] * myHDims[1]);
+  }
+
+  //! Check if the box do not interfere the other box.
+  Standard_EXPORT Standard_Boolean IsOut(const Bnd_OBB& theOther) const;
+
+  //! Check if the point is inside of <this>.
+  Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& theP) const;
+
+  //! Check if the theOther is completely inside *this.
+  Standard_EXPORT Standard_Boolean IsCompletelyInside(const Bnd_OBB& theOther) const;
+
+  //! Rebuilds this in order to include all previous objects
+  //! (which it was created from) and theOther.
+  Standard_EXPORT void Add(const Bnd_OBB& theOther);
+
+  //! Rebuilds this in order to include all previous objects
+  //! (which it was created from) and theP.
+  Standard_EXPORT void Add(const gp_Pnt& theP);
+
+  protected:
+    void ProcessOnePoint(const gp_Pnt& theP)
+    {
+      myIsAABox = Standard_True;
+      myHDims[0] = myHDims[1] = myHDims[2] = 0.0;
+      myAxes[0].SetCoord(1.0, 0.0, 0.0);
+      myAxes[1].SetCoord(0.0, 1.0, 0.0);
+      myAxes[2].SetCoord(0.0, 0.0, 1.0);
+      myCenter = theP.XYZ();
+    }
+
+private:
+
+  //! Center of the OBB
+  gp_XYZ myCenter;
+
+  //! Directions of the box's axes
+  //! (all vectors are already normalized)
+  gp_XYZ myAxes[3];
+
+  //! Half-size dimensions of the OBB
+  Standard_Real myHDims[3];
+
+  //! To be set if the OBB is axis aligned box;
+  Standard_Boolean myIsAABox;
+};
+
+#endif
index 845b525..1e88fce 100644 (file)
@@ -24,6 +24,8 @@ Bnd_Box2d.hxx
 Bnd_HArray1OfBox.hxx
 Bnd_HArray1OfBox2d.hxx
 Bnd_HArray1OfSphere.hxx
+Bnd_OBB.cxx
+Bnd_OBB.hxx
 Bnd_Range.cxx
 Bnd_Range.hxx
 Bnd_SeqOfBox.hxx
index 2504925..e8bb92e 100644 (file)
 IMPLEMENT_STANDARD_RTTIEXT(Draw_Box,Draw_Drawable3D)
 
 //=======================================================================
-//function : Draw_Box
+//function : Constructor
 //purpose  : 
 //=======================================================================
-Draw_Box::Draw_Box(const gp_Pnt& p1, const gp_Pnt& p2, const Draw_Color& col) :
-   myFirst(p1), myLast(p2),myColor(col)
+Draw_Box::Draw_Box(const Bnd_OBB& theOBB,
+                   const Draw_Color& theColor) :myOBB(theOBB), myColor(theColor)
 {
-  Standard_Real t;
-  if (myLast.X() < myFirst.X()) {
-    t = myFirst.X();
-    myFirst.SetX(myLast.X());
-    myLast.SetX(t);
-  }
-  if (myLast.Y() < myFirst.Y()) {
-    t = myFirst.Y();
-    myFirst.SetY(myLast.Y());
-    myLast.SetY(t);
-  }
-  if (myLast.Z() < myFirst.Z()) {
-    t = myFirst.Z();
-    myFirst.SetZ(myLast.Z());
-    myLast.SetZ(t);
-  }
 }
 
 //=======================================================================
-//function : DrawOn
+//function : ToWCS
 //purpose  : 
 //=======================================================================
-
-void Draw_Box::DrawOn(Draw_Display& dis) const 
+void Draw_Box::ToWCS(const Standard_Real theX,
+                     const Standard_Real theY,
+                     const Standard_Real theZ,
+                     gp_Pnt& theP) const
 {
-  dis.SetColor(myColor);
-  gp_Pnt P = myFirst;
-
-  dis.MoveTo(P);
-  P.SetX(myLast.X());
-  dis.DrawTo(P);
-  P.SetY(myLast.Y());
-  dis.DrawTo(P);
-  P.SetZ(myLast.Z());
-  dis.DrawTo(P);
-  P.SetX(myFirst.X());
-  dis.DrawTo(P);
-  P.SetY(myFirst.Y());
-  dis.DrawTo(P);
-  P.SetZ(myFirst.Z());
-  dis.DrawTo(P);
-
-  P.SetX(myLast.X());
-  dis.MoveTo(P);
-  P.SetZ(myLast.Z());
-  dis.DrawTo(P);
-  P.SetX(myFirst.X());
-  dis.DrawTo(P);
-  
-  P.SetX(myLast.X());
-  dis.MoveTo(P);
-  P.SetY(myLast.Y());
-  dis.DrawTo(P);
-  
-  P.SetX(myFirst.X());
-  dis.MoveTo(P);
-  P.SetZ(myFirst.Z());
-  dis.DrawTo(P);
-  P.SetY(myFirst.Y());
-  dis.DrawTo(P);
-  
-  P.SetY(myLast.Y());
-  dis.MoveTo(P);
-  P.SetX(myLast.X());
-  dis.DrawTo(P);
+  const gp_XYZ & aC = myOBB.Center();
+  const gp_XYZ aXDir = myOBB.XDirection(),
+               aYDir = myOBB.YDirection(),
+               aZDir = myOBB.ZDirection();
+
+  theP.SetXYZ(aC + theX*aXDir + theY*aYDir + theZ*aZDir);
 }
 
 //=======================================================================
-//function : First
+//function : MoveX
 //purpose  : 
 //=======================================================================
-
-const gp_Pnt& Draw_Box::First() const 
+void Draw_Box::MoveX(const Standard_Real theShift, gp_Pnt& thePt) const
 {
-  return myFirst;
+  const gp_XYZ aXDir = myOBB.XDirection();
+  thePt.SetXYZ(thePt.XYZ() + theShift*aXDir);
 }
 
 //=======================================================================
-//function : First
+//function : MoveY
 //purpose  : 
 //=======================================================================
-
-void Draw_Box::First(const gp_Pnt& P)
+void Draw_Box::MoveY(const Standard_Real theShift, gp_Pnt& thePt) const
 {
-  myFirst = P;
+  const gp_XYZ aYDir = myOBB.YDirection();
+  thePt.SetXYZ(thePt.XYZ() + theShift*aYDir);
 }
 
 //=======================================================================
-//function : Last
+//function : MoveZ
 //purpose  : 
 //=======================================================================
-
-const gp_Pnt& Draw_Box::Last() const 
+void Draw_Box::MoveZ(const Standard_Real theShift, gp_Pnt& thePt) const
 {
-  return myLast;
+  const gp_XYZ aZDir = myOBB.ZDirection();
+  thePt.SetXYZ(thePt.XYZ() + theShift*aZDir);
 }
 
 //=======================================================================
-//function : Last
+//function : DrawOn
 //purpose  : 
 //=======================================================================
-
-void Draw_Box::Last(const gp_Pnt& P)
+void Draw_Box::DrawOn(Draw_Display& theDIS) const 
 {
-  myLast = P;
+  if(myOBB.IsVoid())
+  {
+    return;
+  }
+
+  theDIS.SetColor(myColor);
+  
+  const Standard_Real aHx = myOBB.XHSize(),
+                      aHy = myOBB.YHSize(),
+                      aHz = myOBB.ZHSize();
+
+  gp_Pnt aP;
+  ToWCS(-aHx, -aHy, -aHz, aP);
+  theDIS.MoveTo(aP);
+
+  for(Standard_Integer i = 0; i<2; i++)
+  {
+    MoveX(2.0*aHx, aP);
+    theDIS.DrawTo(aP);
+    MoveY(2.0*aHy, aP);
+    theDIS.DrawTo(aP);
+    MoveX(-2.0*aHx, aP);
+    theDIS.DrawTo(aP);
+    MoveY(-2.0*aHy, aP);
+    theDIS.DrawTo(aP);
+
+    ToWCS(-aHx, -aHy, aHz, aP);
+    theDIS.MoveTo(aP);
+  }
+  
+  for(Standard_Integer i = 0; i < 4; i++)
+  {
+    switch(i)
+    {
+      case 0: ToWCS(-aHx, -aHy, -aHz, aP); break;
+      case 1: ToWCS(aHx, -aHy, -aHz, aP); break;
+      case 2: ToWCS(aHx, aHy, -aHz, aP); break;
+      case 3: ToWCS(-aHx, aHy, -aHz, aP); break;
+      default: break;
+    }
+
+    theDIS.MoveTo(aP);
+    MoveZ(2.0*aHz, aP);
+    theDIS.DrawTo(aP);
+  }
 }
 
index 0b37c82..25656fa 100644 (file)
 #include <Standard.hxx>
 #include <Standard_Type.hxx>
 
-#include <gp_Pnt.hxx>
+#include <Bnd_OBB.hxx>
 #include <Draw_Color.hxx>
 #include <Draw_Drawable3D.hxx>
-class gp_Pnt;
 class Draw_Color;
 class Draw_Display;
 
@@ -34,46 +33,41 @@ DEFINE_STANDARD_HANDLE(Draw_Box, Draw_Drawable3D)
 //! a 3d box
 class Draw_Box : public Draw_Drawable3D
 {
-
 public:
-
-  
-  Standard_EXPORT Draw_Box(const gp_Pnt& p1, const gp_Pnt& p2, const Draw_Color& col);
-  
-  Standard_EXPORT void DrawOn (Draw_Display& dis) const Standard_OVERRIDE;
-  
-  Standard_EXPORT const gp_Pnt& First() const;
   
-  Standard_EXPORT void First (const gp_Pnt& P);
-  
-  Standard_EXPORT const gp_Pnt& Last() const;
-  
-  Standard_EXPORT void Last (const gp_Pnt& P);
-
-
-
+  //! Constructor
+  Standard_EXPORT Draw_Box(const Bnd_OBB& theOBB,
+                           const Draw_Color& theColor);
 
+  //! Draws myOBB
+  Standard_EXPORT void DrawOn (Draw_Display& theDis) const Standard_OVERRIDE;
+  
   DEFINE_STANDARD_RTTIEXT(Draw_Box,Draw_Drawable3D)
 
 protected:
 
+  //! Converts the point (theX, theY, theZ) in local coordinate system to WCS.
+  void ToWCS(const Standard_Real theX, 
+             const Standard_Real theY,
+             const Standard_Real theZ,
+             gp_Pnt& theP) const;
+
+  //! Moves the point thePt along X-direction of myOBB on the distance theShift.
+  void MoveX(const Standard_Real theShift, gp_Pnt& thePt) const;
 
+  //! Moves the point thePt along Y-direction of myOBB on the distance theShift.
+  void MoveY(const Standard_Real theShift, gp_Pnt& thePt) const;
 
+  //! Moves the point thePt along Z-direction of myOBB on the distance theShift.
+  void MoveZ(const Standard_Real theShift, gp_Pnt& thePt) const;
 
 private:
 
+  //! Oriented bounding box
+  Bnd_OBB myOBB;
 
-  gp_Pnt myFirst;
-  gp_Pnt myLast;
+  //! Color value
   Draw_Color myColor;
-
-
 };
 
-
-
-
-
-
-
 #endif // _Draw_Box_HeaderFile
index b42e3f0..2311d4f 100755 (executable)
@@ -1,4 +1,3 @@
-
 puts "============"
 puts "BUC60849"
 puts "============"
@@ -7,14 +6,18 @@ puts ""
 restore [locate_data_file BUC60849.brep] result
 checkshape result
 
-set bndb [ lindex [bounding result] 3 ]
+bounding -s result -save xmin ymin zmin xmax ymax zmax -dump
+
+smallview
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
 
-if { $bndb  > 100.000001 } {
+if { [dval zmin] > 100.000001 } {
     puts "Faulty BUC60849 : Bounding box of spherical surface is created wroughly."
 } else {
     puts "BUC60849 OK :Bounding box of spherical surface is created properly."
 }
+
 checkprops result -s 125663 
 checkshape result
-checkview -display result -2d -path ${imagedir}/${test_image}.png
 
index 3d33752..5ec0c83 100755 (executable)
@@ -1,4 +1,3 @@
-
 puts "================"
 puts "BUC61037"
 puts "OCC108"
@@ -11,20 +10,10 @@ puts ""
 restore [locate_data_file bug61037.brep] sh1
 checkshape sh1
 
-set rr [bounding sh1]
-regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $rr full v1_x v1_y v1_z v2_x v2_y v2_z
-vertex v1 $v1_x $v1_y $v1_z
-vertex v2 $v2_x $v2_y $v2_z 
-edge result v1 v2
-regexp {Mass +: +([-0-9.+eE]+)} [lprops result] full dis
-if { [expr $dis < 0.201357] } {
-   puts "Faulty BUC61037: Planar circle and bounded face a returns too small bounding box"
-} else {
-   puts "OCC134 OK: bounding box is correct"
-}
-
-checkprops result -l 0.201357 
-checkshape result
-checksection result
-checkview -display result -2d -path ${imagedir}/${test_image}.png
+bounding -s sh1 -dump -shape result
+checkprops result -v 5.78576e-005 -s 0.042162
 
+smallview
+don sh1 result
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
index b612e54..5038fe8 100755 (executable)
@@ -9,21 +9,14 @@ puts ""
 set BugNumber OCC12661
 
 restore [locate_data_file OCC12661.brep] result
-set res [bounding result]
+bounding -s result -save x1 y1 z1 x2 y2 z2
 
-set x1 [lindex ${res} 0]
-set y1 [lindex ${res} 1]
-set z1 [lindex ${res} 2]
-set x2 [lindex ${res} 3]
-set y2 [lindex ${res} 4]
-set z2 [lindex ${res} 5]
-
-checkreal "x1" ${x1} -6.3659273065258741 0 0.001
-checkreal "y1" ${y1} 0.7051405053395956  0 0.001
-checkreal "z1" ${z1} -2.5792617865186296 0 0.001
-checkreal "x2" ${x2} 6.3659273065258795  0 0.001
-checkreal "y2" ${y2} 7.6599592236605769  0 0.001
-checkreal "z2" ${z2} 3.0815250146676485  0 0.001
+checkreal "x1" [dval x1] -6.3659273065258741 0 0.001
+checkreal "y1" [dval y1] 0.7051405053395956  0 0.001
+checkreal "z1" [dval z1] -2.5792617865186296 0 0.001
+checkreal "x2" [dval x2] 6.3659273065258795  0 0.001
+checkreal "y2" [dval y2] 7.6599592236605769  0 0.001
+checkreal "z2" [dval z2] 3.0815250146676485  0 0.001
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
 
index 2df9d61..003551d 100755 (executable)
@@ -16,7 +16,7 @@ offsetshape t b 10 b_1
 
 checkshape t
 
-set bnd_t [bounding t]
+bounding -s t -save xt1 yy zz xt2 yy zz -dump
 set ori [lindex [dtyp t] 2]
 puts "Orientation of thick solid is $ori"
 
@@ -28,7 +28,7 @@ if { [regexp {Faulty} $che] } {
     puts "Faulty ${BugNumber} : checkshape is wrong for h"
 }
 
-set bnd_h [bounding h]
+bounding -s h -save xh1 yy zz xh2 yy zz -dump
 
 renamevar h result
 
@@ -38,8 +38,8 @@ checkshape result
 checknbshapes result -vertex 30 -edge 51 -wire 27 -face 24 -shell 1 -solid 1 -compsolid 0 -compound 1 -shape 135
 
 # 4. Check thickness of box and hole
-set dx_t [expr [lindex $bnd_t 3] - [lindex $bnd_t 0]]
-set dx_h [expr [lindex $bnd_h 3] - [lindex $bnd_h 0]]
+set dx_t [ dval xt2-xt1 ]
+set dx_h [ dval xh2-xh1 ]
 
 if { [expr abs($dx_h - $dx_t)] > 1e-5 } {
   puts "Thickness of solid = $dx_t"
index a7b0a3c..a184a80 100644 (file)
@@ -9,13 +9,7 @@ puts ""
 restore [locate_data_file bug27537.brep] result
 incmesh result 0.2
 
-set bndbox [bounding result]
-set xMin [lindex $bndbox 0]
-set yMin [lindex $bndbox 1]
-set zMin [lindex $bndbox 2]
-set xMax [lindex $bndbox 3]
-set yMax [lindex $bndbox 4]
-set zMax [lindex $bndbox 5]
+bounding -s result -save xMin yMin zMin xMax yMax zMax -dump
 
 mkcurve c result
 bounds c u1 u2
@@ -41,7 +35,7 @@ for {set i 0} {$i <= $nbSamples} {incr i} {
   set x [dval cx]
   set y [dval cy]
   set z [dval cz]
-  if {$x < $xMin || $x > $xMax || $y < $yMin || $y > $yMax || $z < $zMin || $z > $zMax} {
+  if {$x < [dval xMin] || $x > [dval xMax] || $y < [dval yMin] || $y > [dval yMax] || $z < [dval zMin] || $z > [dval zMax] } {
     puts "ERROR: point ($x; $y; $z) is out of bounding box"
     set isOk false
   }
diff --git a/tests/bugs/modalg_7/bug29311_1 b/tests/bugs/modalg_7/bug29311_1
new file mode 100644 (file)
index 0000000..889b431
--- /dev/null
@@ -0,0 +1,49 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+set NbIters 101
+set step [expr 360.0/($NbIters-1) ]
+
+restore [locate_data_file bug29237_no_overlap.lhs.brep] a
+
+# Create AABB for a and put it into "r1" variable
+#   Draw[]> bounding -s a -shape r1
+# The volume of one AABB is
+#   Draw[]> vprops r1 1.0e-12 -full
+#   32736000.276308119
+set Vexp 32736000.276308119
+
+set VMax 0
+set MaxIteration 0
+
+for {set i 1} { $i <= $NbIters} { incr i } {
+  bounding -s a -obb -shape rr$i
+  
+  regexp {Mass +: +([-0-9.+eE]+)} [vprops rr$i 1.0e-12 -full] full Vreal
+  
+  if { $Vreal > $VMax } {
+    set VMax $Vreal
+    set MaxIteration $i
+    copy a amax
+  }
+  
+  if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
+}
+
+set aDeltaMax [ expr 100.0*abs($VMax/$Vexp - 1.0) ]
+
+puts "Delta of computation not greater than $aDeltaMax %. Maximal delta is achieved in $MaxIteration iteration. See \"amax\" shape."
+
+if { $aDeltaMax > 0.1 } {
+  puts "Error: The obtained OBB(s) is not precise."
+}
+
+axo
+donly amax rr${MaxIteration}
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug29311_10 b/tests/bugs/modalg_7/bug29311_10
new file mode 100644 (file)
index 0000000..a707be7
--- /dev/null
@@ -0,0 +1,26 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interferences of OBB
+
+box b1 100 150 200
+copy b1 b2
+trotate b1 -50 -50 -50 1 1 1 -40
+trotate b2 -50 -50 -50 1 1 1 60
+
+if { [regexp {NOT interfered by OBB} [ isbbinterf b1 b2 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
+
+if { [regexp {NOT interfered by OBB} [ isbbinterf b2 b1 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
diff --git a/tests/bugs/modalg_7/bug29311_11 b/tests/bugs/modalg_7/bug29311_11
new file mode 100644 (file)
index 0000000..6b54442
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interfered by AABB but not interfered by OBB
+
+box b1 300 100 100
+trotate b1 0 0 0 0 1 0 -30
+box b2 200 0 50 50 50 50
+
+if { [regexp {NOT interfered by AABB} [ isbbinterf b1 b2 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
+
+if { [regexp {NOT interfered by AABB} [ isbbinterf b2 b1 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
+
+if { ![regexp {NOT interfered by OBB} [ isbbinterf b1 b2 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
+
+if { ![regexp {NOT interfered by OBB} [ isbbinterf b2 b1 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
diff --git a/tests/bugs/modalg_7/bug29311_12 b/tests/bugs/modalg_7/bug29311_12
new file mode 100644 (file)
index 0000000..07b4a92
--- /dev/null
@@ -0,0 +1,14 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+line ll -5 3 8 -1 0 0
+trim ll ll -100 100
+mkedge result ll
+
+bounding -s result -obb
+
diff --git a/tests/bugs/modalg_7/bug29311_13 b/tests/bugs/modalg_7/bug29311_13
new file mode 100644 (file)
index 0000000..2ef6810
--- /dev/null
@@ -0,0 +1,23 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+restore [locate_data_file CTO900_cts19474part.rle] part
+
+compound result
+
+# construct obb for each edge of the shape
+foreach e [explode part e] {
+  if [catch {bounding -s $e -obb}] {
+    puts "Error with $e (exception)"
+    add $e result
+  } else {
+    puts "$e OK"
+  }
+}
+
+checknbshapes result -edge 0
diff --git a/tests/bugs/modalg_7/bug29311_14 b/tests/bugs/modalg_7/bug29311_14
new file mode 100644 (file)
index 0000000..508e7ed
--- /dev/null
@@ -0,0 +1,23 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+restore [locate_data_file CTO900_cts19474part.rle] part
+
+compound result
+
+# construct obb for each face of the shape
+foreach f [explode part f] {
+  if [catch {bounding -s $f -obb}] {
+    puts "Error with $f (exception)"
+    add $f result
+  } else {
+    puts "$f OK"
+  }
+}
+
+checknbshapes result -face 0
diff --git a/tests/bugs/modalg_7/bug29311_15 b/tests/bugs/modalg_7/bug29311_15
new file mode 100644 (file)
index 0000000..8309051
--- /dev/null
@@ -0,0 +1,22 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+set px 1
+set py 2
+set pz 3
+
+vertex vv $px $py $pz
+set log [bounding -s vv -obb -dump]
+
+if {![regexp {Center: +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $log full xc yc zc]} {
+  puts "Error in Dump."
+}
+
+checkreal "XC" $xc $px 1.0e-7 0.0
+checkreal "YC" $yc $py 1.0e-7 0.0
+checkreal "ZC" $zc $pz 1.0e-7 0.0
diff --git a/tests/bugs/modalg_7/bug29311_16 b/tests/bugs/modalg_7/bug29311_16
new file mode 100644 (file)
index 0000000..136d0a8
--- /dev/null
@@ -0,0 +1,51 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+
+set NbIters 31
+set step [expr 360.0/($NbIters-1) ]
+
+restore [locate_data_file OCC26443-shell_2.brep] a
+
+# Check PCA-algorithm
+tclean a
+
+set VMax -1.0e200
+set VMin 1.0e200
+
+set MaxIteration 0
+set MinIteration 0
+
+for {set i 1} { $i <= $NbIters} { incr i } {
+  bounding -s a -obb -shape rr$i
+  
+  regexp {Mass +: +([-0-9.+eE]+)} [vprops rr$i 1.0e-12 -full] full Vreal
+  
+  if { $Vreal > $VMax } {
+    set VMax $Vreal
+    set MaxIteration $i
+    copy a amax
+  }
+  
+  if { $Vreal < $VMin } {
+    set VMin $Vreal
+    set MinIteration $i
+    copy a amin
+  }  
+  
+  if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
+}
+
+checkreal {Transformed BndBoxes} $VMax $VMin 0.0 0.001
+
+puts "The box with maximal volume is achieved in $MaxIteration iteration. See \"amax\" shape."
+puts "The box with minimal volume is achieved in $MinIteration iteration. See \"amin\" shape."
+
+bounding -s amax -obb -dump
+bounding -s amin -obb -dump
+
diff --git a/tests/bugs/modalg_7/bug29311_17 b/tests/bugs/modalg_7/bug29311_17
new file mode 100644 (file)
index 0000000..3582cdb
--- /dev/null
@@ -0,0 +1,51 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+
+set NbIters 31
+set step [expr 360.0/($NbIters-1) ]
+
+restore [locate_data_file OCC26443-shell_2.brep] a
+
+# Check DiTo-algorithm
+incmesh a 0.01
+
+set VMax -1.0e200
+set VMin 1.0e200
+
+set MaxIteration 0
+set MinIteration 0
+
+for {set i 1} { $i <= $NbIters} { incr i } {
+  bounding -s a -obb -shape rr$i
+  
+  regexp {Mass +: +([-0-9.+eE]+)} [vprops rr$i 1.0e-12 -full] full Vreal
+  
+  if { $Vreal > $VMax } {
+    set VMax $Vreal
+    set MaxIteration $i
+    copy a amax
+  }
+  
+  if { $Vreal < $VMin } {
+    set VMin $Vreal
+    set MinIteration $i
+    copy a amin
+  }  
+  
+  if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
+}
+
+checkreal {Transformed BndBoxes} $VMax $VMin 0.0 0.3
+
+puts "The box with maximal volume is achieved in $MaxIteration iteration. See \"amax\" shape."
+puts "The box with minimal volume is achieved in $MinIteration iteration. See \"amin\" shape."
+
+bounding -s amax -obb -dump
+bounding -s amin -obb -dump
+
diff --git a/tests/bugs/modalg_7/bug29311_2 b/tests/bugs/modalg_7/bug29311_2
new file mode 100644 (file)
index 0000000..9b17351
--- /dev/null
@@ -0,0 +1,49 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+set NbIters 101
+set step [expr 360.0/($NbIters-1) ]
+
+restore [locate_data_file bug29237_no_overlap.rhs.brep] a
+
+# Create AABB for a and put it into "r1" variable
+#   Draw[]> bounding -s a -shape r1
+# The volume of one AABB is
+#   Draw[]> vprops r1 1.0e-12 -full
+#   32736000.184203226
+set Vexp 32736000.184203226
+
+set VMax 0
+set MaxIteration 0
+
+for {set i 1} { $i <= $NbIters} { incr i } {
+  bounding -s a -obb -shape rr$i
+  
+  regexp {Mass +: +([-0-9.+eE]+)} [vprops rr$i 1.0e-12 -full] full Vreal
+  
+  if { $Vreal > $VMax } {
+    set VMax $Vreal
+    set MaxIteration $i
+    copy a amax
+  }
+  
+  if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
+}
+
+set aDeltaMax [ expr 100.0*abs($VMax/$Vexp - 1.0) ]
+
+puts "Delta of computation not greater than $aDeltaMax %. Maximal delta is achieved in $MaxIteration iteration. See \"amax\" shape."
+
+if { $aDeltaMax > 30 } {
+  puts "Error: The obtained OBB(s) is not precise."
+}
+
+axo
+donly amax rr${MaxIteration}
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug29311_3 b/tests/bugs/modalg_7/bug29311_3
new file mode 100644 (file)
index 0000000..d27740c
--- /dev/null
@@ -0,0 +1,10 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+bounding -c 50 100 30 180 200 100 -shape result
+checkprops result -v 910000
diff --git a/tests/bugs/modalg_7/bug29311_4 b/tests/bugs/modalg_7/bug29311_4
new file mode 100644 (file)
index 0000000..730b4da
--- /dev/null
@@ -0,0 +1,28 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+ptorus result 20 5 
+trotate result 5 10 15 1 1 1 28
+
+puts "AABB"
+bounding -s result -shape ra -dump -save x1 y1 z1 x2 y2 z2
+
+dump x1 y1 z1 x2 y2 z2
+
+set VaExp [ dval (x2-x1)*(y2-y1)*(z2-z1) ]
+
+checkprops ra -v $VaExp
+
+puts "OBB"
+bounding -s result -shape ro -dump -obb
+
+checkprops ro -v 28694.7
+
+smallview 
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug29311_5 b/tests/bugs/modalg_7/bug29311_5
new file mode 100644 (file)
index 0000000..c4b063f
--- /dev/null
@@ -0,0 +1,24 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interferences of AABB
+
+box b1 100 60 140 20 10 80
+box b2 210 200 80 120 60 90
+
+if { ![regexp {NOT interfered by AABB} [ isbbinterf b1 b2 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
+
+if { ![regexp {NOT interfered by AABB} [ isbbinterf b2 b1 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
diff --git a/tests/bugs/modalg_7/bug29311_6 b/tests/bugs/modalg_7/bug29311_6
new file mode 100644 (file)
index 0000000..f2bea2b
--- /dev/null
@@ -0,0 +1,24 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interferences of AABB
+
+box b1 300 300 300 
+box b2 100 100 100 50 50 50
+
+if { [regexp {NOT interfered by AABB} [ isbbinterf b1 b2 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
+
+if { [regexp {NOT interfered by AABB} [ isbbinterf b2 b1 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
diff --git a/tests/bugs/modalg_7/bug29311_7 b/tests/bugs/modalg_7/bug29311_7
new file mode 100644 (file)
index 0000000..218b233
--- /dev/null
@@ -0,0 +1,24 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interferences of AABB
+
+box b1 300 300 300 
+box b2 200 200 200 111 222 333
+
+if { [regexp {NOT interfered by AABB} [ isbbinterf b1 b2 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
+
+if { [regexp {NOT interfered by AABB} [ isbbinterf b2 b1 ] ] } {
+    puts "Error : Wrong check of AABBs interferences"
+} else {
+    puts "OK : check of AABBs interferences"
+}
diff --git a/tests/bugs/modalg_7/bug29311_8 b/tests/bugs/modalg_7/bug29311_8
new file mode 100644 (file)
index 0000000..6319505
--- /dev/null
@@ -0,0 +1,26 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interferences of OBB
+
+box b1 100 150 200
+copy b1 b2
+trotate b1 -150 -150 -150 1 2 3 -40
+trotate b2 -150 -150 -150 1 5 2 60
+
+if { ![regexp {NOT interfered by OBB} [ isbbinterf b1 b2 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
+
+if { ![regexp {NOT interfered by OBB} [ isbbinterf b2 b1 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
diff --git a/tests/bugs/modalg_7/bug29311_9 b/tests/bugs/modalg_7/bug29311_9
new file mode 100644 (file)
index 0000000..eed8395
--- /dev/null
@@ -0,0 +1,26 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+# Interferences of OBB
+
+box b1 -300 -300 -300 600 600 600
+box b2 100 100 100
+trotate b1 0 0 0 1 2 3 -28
+trotate b2 0 0 0 5 6 7 34
+
+if { [regexp {NOT interfered by OBB} [ isbbinterf b1 b2 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
+
+if { [regexp {NOT interfered by OBB} [ isbbinterf b2 b1 -o ] ] } {
+    puts "Error : Wrong check of OBBs interferences"
+} else {
+    puts "OK : check of OBBs interferences"
+}
index 463c428..3ec05c5 100755 (executable)
@@ -13,19 +13,13 @@ pload XDE
 igesbrep [locate_data_file OCC15570.igs] a *
 tpcompound result
 
-set BoundList [boundingstr result]
-set xmin [lindex ${BoundList} 0]
-set ymin [lindex ${BoundList} 1]
-set zmin [lindex ${BoundList} 2]
-set xmax [lindex ${BoundList} 3]
-set ymax [lindex ${BoundList} 4]
-set zmax [lindex ${BoundList} 5]
+bounding -s result -save xmin ymin zmin xmax ymax zmax -nodraw
 
-checkreal "xmin" ${xmin} -22.500000100000001 0 0.001
-checkreal "ymin" ${ymin} -88.366946209482094 0 0.001
-checkreal "zmin" ${zmin} -1.0000002775557561e-07 0 0.001
-checkreal "xmax" ${xmax} 22.500000100000001 0 0.001
-checkreal "ymax" ${ymax} 22.776076069021901 0 0.001
-checkreal "zmax" ${zmax} 86.12676222997429 0 0.001
+checkreal "xmin" [dval xmin] -22.500000100000001 0 0.001
+checkreal "ymin" [dval ymin] -88.366946209482094 0 0.001
+checkreal "zmin" [dval zmin] -1.0000002775557561e-07 0 0.001
+checkreal "xmax" [dval xmax] 22.500000100000001 0 0.001
+checkreal "ymax" [dval ymax] 22.776076069021901 0 0.001
+checkreal "zmax" [dval zmax] 86.12676222997429 0 0.001
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
index 54aa7b7..92d0880 100755 (executable)
@@ -18,21 +18,14 @@ set exception_status 0
 restore [locate_data_file OCC23165-edge1.brep] e1 
 
 donly e1
-catch { bounding e1 } msg
+catch { bounding -s e1 } msg
 fit
 
 set index [lsearch $msg exception]
 if {$index > -1} {
   set exception_status 1
 } else {
-  set e1_result [bounding e1]
-
-  set e1_x1 [lindex ${e1_result} 0]
-  set e1_y1 [lindex ${e1_result} 1]
-  set e1_z1 [lindex ${e1_result} 2]
-  set e1_x2 [lindex ${e1_result} 3]
-  set e1_y2 [lindex ${e1_result} 4]
-  set e1_z2 [lindex ${e1_result} 5]
+  bounding -s e1 -save e1_x1 e1_y1 e1_z1 e1_x2 e1_y2 e1_z2
 
   set e1_good_x1 -17.610622244944413
   set e1_good_y1 -0.010622244944394899
@@ -41,12 +34,12 @@ if {$index > -1} {
   set e1_good_y2 5.700038816113608
   set e1_good_z2 -1.6251884728673096
 
-  checkreal "e1_x1" ${e1_x1} ${e1_good_x1} 0 0.001
-  checkreal "e1_y1" ${e1_y1} ${e1_good_y1} 0 0.001
-  checkreal "e1_z1" ${e1_z1} ${e1_good_z1} 0 0.001
-  checkreal "e1_x2" ${e1_x2} ${e1_good_x2} 0 0.001
-  checkreal "e1_y2" ${e1_y2} ${e1_good_y2} 0 0.001
-  checkreal "e1_z2" ${e1_z2} ${e1_good_z2} 0 0.001
+  checkreal "e1_x1" [dval e1_x1] ${e1_good_x1} 0 0.001
+  checkreal "e1_y1" [dval e1_y1] ${e1_good_y1} 0 0.001
+  checkreal "e1_z1" [dval e1_z1] ${e1_good_z1} 0 0.001
+  checkreal "e1_x2" [dval e1_x2] ${e1_good_x2} 0 0.001
+  checkreal "e1_y2" [dval e1_y2] ${e1_good_y2} 0 0.001
+  checkreal "e1_z2" [dval e1_z2] ${e1_good_z2} 0 0.001
 }
 
 # 2 step
@@ -54,16 +47,9 @@ restore [locate_data_file OCC23165-curve.rle] c
 mkedge result c 20 36
 
 donly result
-set res [bounding result]
+set res [bounding -s result -save x1 y1 z1 x2 y2 z2 ]
 fit
 
-set x1 [lindex ${res} 0]
-set y1 [lindex ${res} 1]
-set z1 [lindex ${res} 2]
-set x2 [lindex ${res} 3]
-set y2 [lindex ${res} 4]
-set z2 [lindex ${res} 5]
-
 set good_x1 -17.6105835090592
 set good_y1 -4.7133570660117909
 set good_z1 -4.3679100133425806
@@ -71,12 +57,12 @@ set good_x2 -17.589416490940806
 set good_y2 5.7000000802283299
 set good_z2 -1.6252272087525899
 
-checkreal "x1" ${x1} ${good_x1} 0 0.001
-checkreal "y1" ${y1} ${good_y1} 0 0.001
-checkreal "z1" ${z1} ${good_z1} 0 0.001
-checkreal "x2" ${x2} ${good_x2} 0 0.001
-checkreal "y2" ${y2} ${good_y2} 0 0.001
-checkreal "z2" ${z2} ${good_z2} 0 0.001
+checkreal "x1" [dval x1] ${good_x1} 0 0.001
+checkreal "y1" [dval y1] ${good_y1} 0 0.001
+checkreal "z1" [dval z1] ${good_z1} 0 0.001
+checkreal "x2" [dval x2] ${good_x2} 0 0.001
+checkreal "y2" [dval y2] ${good_y2} 0 0.001
+checkreal "z2" [dval z2] ${good_z2} 0 0.001
 
 if { ${exception_status} == 0 } {
    puts "${BugNumber}: OK"
index b12ce5d..a57fe7c 100755 (executable)
@@ -25,11 +25,8 @@ set tol_rel 1.e-7
 checkreal "Distance 1 " ${dist1} ${good_dist} ${tol_abs} ${tol_rel}
 checkreal "Distance 2 " ${dist2} ${good_dist} ${tol_abs} ${tol_rel}
 
-set boundbox [boundingstr a]
-set x0 [lindex $boundbox 0]
-set y0 [lindex $boundbox 1]
-set z0 [lindex $boundbox 2]
-ttranslate a [expr -1 * $x0] [expr -1 * $y0] [expr -1 * $z0]
-ttranslate b [expr -1 * $x0] [expr -1 * $y0] [expr -1 * $z0]
+bounding -s a -save x0 y0 z0 x1 y1 z1 -nodraw
+ttranslate a -x0 -y0 -z0
+ttranslate b -x0 -y0 -z0
 
 checkview -display a -with b -2d -path ${imagedir}/${test_image}.png
index f930792..6da9a58 100755 (executable)
@@ -10,24 +10,11 @@ puts ""
 restore [locate_data_file OCC257.brep] result 
 checkshape result
 
-set bb [bounding result]
+bounding -s result -save x1 y1 z1 x2 y2 z2
 
-set list [split ${bb}]
-set listLength [llength ${list}]
-if { ${listLength} < 6 } {
-   puts "Error : listLength = ${listLength}"
-}
-
-set x1 [lindex ${list} 0]
-set y1 [lindex ${list} 1]
-set z1 [lindex ${list} 2]
-set x2 [lindex ${list} 3]
-set y2 [lindex ${list} 4]
-set z2 [lindex ${list} 5]
-
-set len [expr ${x2} - ${x1}]
-set width  [expr ${y2} - ${y1}]
-set height [expr ${z2} - ${z1}]
+set len    [ dval x2-x1]
+set width  [ dval y2-y1]
+set height [ dval z2-z1]
 
 set R 180
 
index 088098e..460b207 100755 (executable)
@@ -10,14 +10,13 @@ puts ""
 
 restore [locate_data_file OCC566.brep] a 
 
-set err1 [bounding a]
+bounding -s a -save v1_x v1_y v1_z v2_x v2_y v2_z -dump -shape result
 set err2 [OCC566 a]
 
-regexp { *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+)} $err1 full v1_x v1_y v1_z v2_x v2_y v2_z
 regexp { *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+) *([-0-9.+eE]+)} $err2 full v3_x v3_y v3_z v4_x v4_y v4_z
 
-vertex v1 $v1_x $v1_y $v1_z
-vertex v2 $v2_x $v2_y $v2_z
+vertex v1 v1_x v1_y v1_z
+vertex v2 v2_x v2_y v2_z
 
 vertex v3 $v3_x $v3_y $v3_z
 vertex v4 $v4_x $v4_y $v4_z
@@ -40,4 +39,4 @@ if {$err > 1.0} {
     puts " OCC566 OK"
 }
 
-checkview -display result -2d -path ${imagedir}/${test_image}.png
+checkview -display a -with result -2d -path ${imagedir}/${test_image}.png
index b72f065..b5ce418 100755 (executable)
@@ -10,14 +10,7 @@ set BugNumber OCC6503
 
 plane pl 0 0 0 0 0 1
 mkface f pl
-set info_result [bounding f]
-
-set x1 [lindex ${info_result} 0]
-set y1 [lindex ${info_result} 1]
-set z1 [lindex ${info_result} 2]
-set x2 [lindex ${info_result} 3]
-set y2 [lindex ${info_result} 4]
-set z2 [lindex ${info_result} 5]
+set info_result [bounding -s f -save x1 y1 z1 x2 y2 z2]
 
 set good_x1 -1e+100
 set good_y1 -1e+100
@@ -26,9 +19,9 @@ set good_x2 1e+100
 set good_y2 1e+100
 set good_z2 9.9999999999999995e-08
 
-checkreal "x1" ${x1} ${good_x1} 0 0.001
-checkreal "y1" ${y1} ${good_y1} 0 0.001
-checkreal "z1" ${z1} ${good_z1} 0 0.001
-checkreal "x2" ${x2} ${good_x2} 0 0.001
-checkreal "y2" ${y2} ${good_y2} 0 0.001
-checkreal "z2" ${z2} ${good_z2} 0 0.001
+checkreal "x1" [dval x1] ${good_x1} 0 0.001
+checkreal "y1" [dval y1] ${good_y1} 0 0.001
+checkreal "z1" [dval z1] ${good_z1} 0 0.001
+checkreal "x2" [dval x2] ${good_x2} 0 0.001
+checkreal "y2" [dval y2] ${good_y2} 0 0.001
+checkreal "z2" [dval z2] ${good_z2} 0 0.001
index 0e08a8c..81f707a 100644 (file)
@@ -8,11 +8,11 @@ puts ""
 
 bsplinecurve c 3 2 0 4 1 4 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1
 mkedge e c
-set boundResult [bounding e]
+bounding -s e -save Xmin Ymin Zmin Xmax Ymax Zmax
 
-checkreal Xmin [lindex $boundResult 0] 0. 0.1 0.
-checkreal Ymin [lindex $boundResult 1] 0. 0.1 0.
-checkreal Zmin [lindex $boundResult 2] 0. 0.1 0.
-checkreal Xmax [lindex $boundResult 3] 1. 0.1 0.
-checkreal Ymax [lindex $boundResult 4] 1. 0.1 0.
-checkreal Zmax [lindex $boundResult 5] 0. 0.1 0.
+checkreal "Xmin" [dval Xmin]  0. 0.1 0.
+checkreal "Ymin" [dval Ymin] 0. 0.1 0.
+checkreal "Zmin" [dval Zmin] 0. 0.1 0.
+checkreal "Xmax" [dval Xmax] 1. 0.1 0.
+checkreal "Ymax" [dval Ymax] 1. 0.1 0.
+checkreal "Zmax" [dval Zmax] 0. 0.1 0.
index b8df371..a1d948c 100755 (executable)
@@ -6,31 +6,19 @@ puts ""
 ## Bounding box is too big for the face.
 #####################################################################
 
-restore [locate_data_file bug25631_fbx.brep] sh1
+restore [locate_data_file bug25631_fbx.brep] result
 
-set rr [bounding sh1]
-regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $rr full v1_x v1_y v1_z v2_x v2_y v2_z
+bounding -s result -save Xmin Ymin Zmin Xmax Ymax Zmax
 
 set tol_abs 1.0e-4
-set tol_rel 0.0001
-
-set expected_v1_x 102.04999989999993
-checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel}
-
-set expected_v1_y -12.576503364721431
-checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel}
-
-set expected_v1_z -12.267407382031644
-checkreal "v1_z" ${v1_z} ${expected_v1_z} ${tol_abs} ${tol_rel}
-
-set expected_v2_x 145.65000009999983
-checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel}
-
-set expected_v2_y 1.0883692081680807
-checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel}
-
-set expected_v2_z 1.4146362604116396
-checkreal "v2_z" ${v2_z} ${expected_v2_z} ${tol_abs} ${tol_rel}
+set tol_rel 1.0e-4
+
+checkreal "Xmin" [dval Xmin]  102.04999989999993 ${tol_abs} ${tol_rel}
+checkreal "Ymin" [dval Ymin] -12.576503364721431 ${tol_abs} ${tol_rel}
+checkreal "Zmin" [dval Zmin] -12.267407382031644 ${tol_abs} ${tol_rel}
+checkreal "Xmax" [dval Xmax] 145.65000009999983 ${tol_abs} ${tol_rel}
+checkreal "Ymax" [dval Ymax] 1.0883692081680807 ${tol_abs} ${tol_rel}
+checkreal "Zmax" [dval Zmax] 1.4146362604116396 ${tol_abs} ${tol_rel}
 
 smallview
 fit
index 6168564..450c1d5 100755 (executable)
@@ -6,32 +6,21 @@ puts ""
 ## BRepBndLib build too large bounding box in Z direction for planar spline edge.
 #####################################################################
 
-restore [locate_data_file bug26560_planarspline.brep] b1
+restore [locate_data_file bug26560_planarspline.brep] result
 
-set rr [bounding b1]
-regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $rr full v1_x v1_y v1_z v2_x v2_y v2_z
+bounding -s result -save Xmin Ymin Zmin Xmax Ymax Zmax -shape resbox
 
 set tol_abs 1.0e-4
 set tol_rel 0.0001
 
-set expected_v1_x -277.03883383200952
-checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel}
-
-set expected_v1_y -562.56241861670651
-checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel}
-
-set expected_v1_z -9.9999999999999995e-08
-checkreal "v1_z" ${v1_z} ${expected_v1_z} ${tol_abs} ${tol_rel}
-
-set expected_v2_x 20.000000100000001
-checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel}
-
-set expected_v2_y -221.27317426638498
-checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel}
-
-set expected_v2_z 9.9999999999999995e-08
-checkreal "v2_z" ${v2_z} ${expected_v2_z} ${tol_abs} ${tol_rel}
+checkreal "Xmin" [dval Xmin] -277.03883383200952  ${tol_abs} ${tol_rel}
+checkreal "Ymin" [dval Ymin] -562.56241861670651 ${tol_abs} ${tol_rel}
+checkreal "Zmin" [dval Zmin] -9.9999999999999995e-08 ${tol_abs} ${tol_rel}
+checkreal "Xmax" [dval Xmax] 20.000000100000001 ${tol_abs} ${tol_rel}
+checkreal "Ymax" [dval Ymax] -221.27317426638498 ${tol_abs} ${tol_rel}
+checkreal "Zmax" [dval Zmax] 9.9999999999999995e-08 ${tol_abs} ${tol_rel}
 
 smallview
+don result resbox
 fit
-checkview -screenshot -2d -path ${imagedir}/${test_image}.png
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
index 1938ec7..b3c0774 100644 (file)
@@ -6,8 +6,8 @@ puts ""
 # Incorrect bounding box is created for the face
 ##############################################################
 
-restore [locate_data_file bug27261_f1.brep] f1
-bounding f1
+restore [locate_data_file bug27261_f1.brep] result
+bounding -s result -dump
 
 # Visual check.
 smallview
index b2912e1..9820fc4 100644 (file)
@@ -6,8 +6,8 @@ puts ""
 # Incorrect bounding box is created for the face
 ##############################################################
 
-restore [locate_data_file bug27261_f2.brep] f2
-bounding f2
+restore [locate_data_file bug27261_f2.brep] result
+bounding -s result -dump
 
 # Visual check.
 smallview
index d6dfcd9..e5d6260 100644 (file)
@@ -6,24 +6,17 @@ puts ""
 # STEP import missing surfaces
 #######################################################################################
 
-set BugNumber OCC24595
 stepread [locate_data_file bug24595_281390.stp] a *
 explode a_1 f
-set mlog [nbshapes a_1_3]
 
-set status 1
+checknbshapes a_1_3 -wire 1
 
-if (![regexp {WIRE[ ]+: 1} $mlog]) {
-  set status 0
-}
+bounding -s a_1_3 -dump -save Xmin Ymin Zmin Xmax Ymax Zmax
+
+checkreal "Xmin" [dval Xmin] -7.1677412321949925 0.1 0.
+checkreal "Ymin" [dval Ymin] -8.0000000999999994 0.1 0.
+checkreal "Zmin" [dval Zmin] -150.00000009999999 0.1 0.
+checkreal "Xmax" [dval Xmax] 7.1677412321949898 0.1 0.
+checkreal "Ymax" [dval Ymax] 8.0000000999999994 0.1 0.
+checkreal "Zmax" [dval Zmax] -141.99999990000001 0.1 0.
 
-set mlog [bounding a_1_3]
-if (![regexp {(-7.1677412321949925) (-8.0000000999999994) (-150.00000009999999) (7.1677412321949898) (8.0000000999999994) (-141.99999990000001)} $mlog]) {
-  set status 0
-}                        
-                                
-if {$status == 1} {
-  puts "OK ${BugNumber}"
-} else {
-  puts "Faulty ${BugNumber}"
-}
\ No newline at end of file
index 08db1a3..4281732 100644 (file)
@@ -19,10 +19,11 @@ writestl comp $imagedir/${casename}.stl 1
 readstl result $imagedir/${casename}.stl
 
 # check that bounding box is 
-set bnd [boundingstr result]
-checkreal "XMin" [lindex $bnd 0]  0. 1e-5 0.
-checkreal "YMin" [lindex $bnd 1]  0. 1e-5 0.
-checkreal "ZMin" [lindex $bnd 2]  0. 1e-5 0.
-checkreal "XMax" [lindex $bnd 3] 15. 1e-5 0.
-checkreal "YMax" [lindex $bnd 4] 15. 1e-5 0.
-checkreal "ZMax" [lindex $bnd 5] 15. 1e-5 0.
+bounding -s result -save Xmin Ymin Zmin Xmax Ymax Zmax -nodraw
+
+checkreal "Xmin" [dval Xmin] 0.0 1e-5 0.
+checkreal "Ymin" [dval Ymin] 0.0 1e-5 0.
+checkreal "Zmin" [dval Zmin] 0.0 1e-5 0.
+checkreal "Xmax" [dval Xmax] 15. 1e-5 0.
+checkreal "Ymax" [dval Ymax] 15. 1e-5 0.
+checkreal "Zmax" [dval Zmax] 15. 1e-5 0.
index 987d5e6..007055a 100755 (executable)
@@ -15,9 +15,9 @@ set area_RED [lindex ${Property_RED} 2]
 set Property_GREEN [sprops BUC60857_GREEN]
 set area_GREEN [lindex ${Property_GREEN} 2]
 
-boundingstr BUC60857_BLUE xmin_BLUE ymin_BLUE zmin_BLUE xmax_BLUE ymax_BLUE zmax_BLUE
-boundingstr BUC60857_RED xmin_RED ymin_RED zmin_RED xmax_RED ymax_RED zmax_RED
-boundingstr BUC60857_GREEN xmin_GREEN ymin_GREEN zmin_GREEN xmax_GREEN ymax_GREEN zmax_GREEN
+bounding -s BUC60857_BLUE -save xmin_BLUE ymin_BLUE zmin_BLUE xmax_BLUE ymax_BLUE zmax_BLUE -nodraw
+bounding -s BUC60857_RED -save xmin_RED ymin_RED zmin_RED xmax_RED ymax_RED zmax_RED -nodraw
+bounding -s BUC60857_GREEN -save xmin_GREEN ymin_GREEN zmin_GREEN xmax_GREEN ymax_GREEN zmax_GREEN -nodraw
 
 set delta_area_GB [expr abs(${area_GREEN} - ${area_BLUE}) / ${area_BLUE} * 100]
 set delta_area_BR [expr ${area_BLUE} / ${area_RED}]
index 352aa4d..1004859 100644 (file)
@@ -12,10 +12,8 @@ box b1 -100 -50  -2 200 100 1
 
 # text label
 text2brep t "texT | Text\ntexT | Text" -height 50
-set aTB [bounding t]
-set aTX [expr [lindex $aTB 3] * -0.5]
-set aTY [expr [lindex $aTB 4] * -0.5]
-ttranslate t $aTX $aTY 1
+bounding -s t -save xx yy zz aTX aTY zz
+ttranslate t -0.5*aTX -0.5*aTY 1
 
 # sphere
 psphere s 50
index f8e2bed..1a65ea5 100755 (executable)
@@ -23,17 +23,11 @@ if [catch { igesbrep . a 6425 } res] {
 
 renamevar a_1 a2
 
-set size1 [ bounding a1 ]
-set size2 [ bounding a2 ]
+set size1 [ bounding -s a1 -save x1_a1 yy zz x2_a1 yy zz ]
+set size2 [ bounding -s a2 -save x1_a2 yy zz x2_a2 yy zz ]
 
-set x1_a1 [ lindex $size1 0 ]
-set x2_a1 [ lindex $size1 3 ]
-
-set x1_a2 [ lindex $size2 0 ]
-set x2_a2 [ lindex $size2 3 ]
-
-set dim2 [ expr $x2_a2 - $x1_a2 ]
-set dim1 [ expr $x2_a1 - $x1_a1 ]
+set dim2 [ dval x2_a2-x1_a2 ]
+set dim1 [ dval x2_a1-x1_a1 ]
 
 set siz [expr ${dim1} / ${dim2}]
 if { $siz > 25} {
index 6e76ac2..e8866ed 100755 (executable)
@@ -18,14 +18,7 @@ set aSetDY1 200
 set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
-
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 set aLabel 0:2
 SetShape D ${aLabel} aBox1
@@ -47,26 +40,20 @@ Undo D
 # Get a value of the attribute
 GetShape D ${aLabel} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} X1_Box2=${X1_Box2}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box2=${Y1_Box2}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box2=${Z1_Box2}"
-       puts "X2_Box1=${X2_Box1} X2_Box2=${X2_Box2}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box2=${Y2_Box2}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Add TDataStd_Shape attribute: Error"
        return
 }
index d464283..4865ff9 100755 (executable)
@@ -18,14 +18,7 @@ set aSetDY1 200
 set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
-
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 set aLabel 0:2
 SetShape D ${aLabel} aBox1
@@ -53,26 +46,19 @@ Undo D
 # Get a value of the attribute
 GetShape D ${aLabel} aBox4
 
-set aBoundingBox4 [bounding aBox4]
-set X1_Box4 [lindex ${aBoundingBox4} 0]
-set Y1_Box4 [lindex ${aBoundingBox4} 1]
-set Z1_Box4 [lindex ${aBoundingBox4} 2]
-set X2_Box4 [lindex ${aBoundingBox4} 3]
-set Y2_Box4 [lindex ${aBoundingBox4} 4]
-set Z2_Box4 [lindex ${aBoundingBox4} 5]
-
-if { ${X1_Box1} != ${X1_Box4} || 
-     ${Y1_Box1} != ${Y1_Box4} || 
-     ${Z1_Box1} != ${Z1_Box4} || 
-     ${X2_Box1} != ${X2_Box4} || 
-     ${Y2_Box1} != ${Y2_Box4} || 
-     ${Z2_Box1} != ${Z2_Box4} } {
-       puts "X1_Box1=${X1_Box1} X1_Box4=${X1_Box4}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box4=${Y1_Box4}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box4=${Z1_Box4}"
-       puts "X2_Box1=${X2_Box1} X2_Box4=${X2_Box4}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box4=${Y2_Box4}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box4=${Z2_Box4}"
+bounding -s aBox4 -save X1_Box4 Y1_Box4 Z1_Box4 X2_Box4 Y2_Box4 Z2_Box4
+if { [dval X1_Box1] != [dval X1_Box4] || 
+     [dval Y1_Box1] != [dval Y1_Box4] || 
+     [dval Z1_Box1] != [dval Z1_Box4] || 
+     [dval X2_Box1] != [dval X2_Box4] || 
+     [dval Y2_Box1] != [dval Y2_Box4] || 
+     [dval Z2_Box1] != [dval Z2_Box4] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box4=[dval X1_Box4]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box4=[dval Y1_Box4]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box4=[dval Z1_Box4]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box4=[dval X2_Box4]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box4=[dval Y2_Box4]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box4=[dval Z2_Box4]"
        puts "Set a value of TDataStd_Shape attribute: Error"
        return
 }
index 41e8f85..1cc0570 100755 (executable)
@@ -19,13 +19,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 set aLabel 0:2
 SetShape D ${aLabel} aBox1
@@ -55,26 +49,20 @@ if { ${IsDone} != 0 } {
        return
 }
 
-set aBoundingBox5 [bounding aBox5]
-set X1_Box5 [lindex ${aBoundingBox5} 0]
-set Y1_Box5 [lindex ${aBoundingBox5} 1]
-set Z1_Box5 [lindex ${aBoundingBox5} 2]
-set X2_Box5 [lindex ${aBoundingBox5} 3]
-set Y2_Box5 [lindex ${aBoundingBox5} 4]
-set Z2_Box5 [lindex ${aBoundingBox5} 5]
+bounding -s aBox5 -save X1_Box5 Y1_Box5 Z1_Box5 X2_Box5 Y2_Box5 Z2_Box5
 
-if { ${X1_Box1} != ${X1_Box5} || 
-     ${Y1_Box1} != ${Y1_Box5} || 
-     ${Z1_Box1} != ${Z1_Box5} || 
-     ${X2_Box1} != ${X2_Box5} || 
-     ${Y2_Box1} != ${Y2_Box5} || 
-     ${Z2_Box1} != ${Z2_Box5} } {
-       puts "X1_Box1=${X1_Box1} X1_Box5=${X1_Box5}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box5=${Y1_Box5}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box5=${Z1_Box5}"
-       puts "X2_Box1=${X2_Box1} X2_Box5=${X2_Box5}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box5=${Y2_Box5}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box5=${Z2_Box5}"
+if { [dval X1_Box1] != [dval X1_Box5] || 
+     [dval Y1_Box1] != [dval Y1_Box5] || 
+     [dval Z1_Box1] != [dval Z1_Box5] || 
+     [dval X2_Box1] != [dval X2_Box5] || 
+     [dval Y2_Box1] != [dval Y2_Box5] || 
+     [dval Z2_Box1] != [dval Z2_Box5] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box5=[dval X1_Box5]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box5=[dval Y1_Box5]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box5=[dval Z1_Box5]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box5=[dval X2_Box5]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box5=[dval Y2_Box5]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box5=[dval Z2_Box5]"
        puts "Get a value of TDataStd_Shape attribute from restoring document: Error"
        return
 }
index 25076a8..bed8ccc 100755 (executable)
@@ -31,13 +31,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 set aLabel 0:2
 SetShape Doc ${aLabel} aBox1
@@ -67,32 +61,20 @@ if { ${IsDone} != 0 } {
        puts "OCC1228: ERROR (case 2)"
 }
 
-catch {set aBoundingBox5 [bounding aBox5]}
-set X1_Box5 0
-set Y1_Box5 0
-set Z1_Box5 0
-set X2_Box5 0
-set Y2_Box5 0
-set Z2_Box5 0
-catch {set X1_Box5 [lindex ${aBoundingBox5} 0]}
-catch {set Y1_Box5 [lindex ${aBoundingBox5} 1]}
-catch {set Z1_Box5 [lindex ${aBoundingBox5} 2]}
-catch {set X2_Box5 [lindex ${aBoundingBox5} 3]}
-catch {set Y2_Box5 [lindex ${aBoundingBox5} 4]}
-catch {set Z2_Box5 [lindex ${aBoundingBox5} 5]}
+bounding -s aBox5 -save X1_Box5 Y1_Box5 Z1_Box5 X2_Box5 Y2_Box5 Z2_Box5
 
-if { ${X1_Box1} != ${X1_Box5} || 
-     ${Y1_Box1} != ${Y1_Box5} || 
-     ${Z1_Box1} != ${Z1_Box5} || 
-     ${X2_Box1} != ${X2_Box5} || 
-     ${Y2_Box1} != ${Y2_Box5} || 
-     ${Z2_Box1} != ${Z2_Box5} } {
-       puts "X1_Box1=${X1_Box1} X1_Box5=${X1_Box5}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box5=${Y1_Box5}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box5=${Z1_Box5}"
-       puts "X2_Box1=${X2_Box1} X2_Box5=${X2_Box5}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box5=${Y2_Box5}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box5=${Z2_Box5}"
+if { [dval X1_Box1] != [dval X1_Box5] || 
+     [dval Y1_Box1] != [dval Y1_Box5] || 
+     [dval Z1_Box1] != [dval Z1_Box5] || 
+     [dval X2_Box1] != [dval X2_Box5] || 
+     [dval Y2_Box1] != [dval Y2_Box5] || 
+     [dval Z2_Box1] != [dval Z2_Box5] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box5=[dval X1_Box5]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box5=[dval Y1_Box5]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box5=[dval Z1_Box5]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box5=[dval X2_Box5]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box5=[dval Y2_Box5]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box5=[dval Z2_Box5]"
        puts "Get a value of TDataStd_Shape attribute from restoring document: Error"
        puts "OCC1228: ERROR (case 3)"
 } else {
index 11eaf9a..df18327 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 # Create a label
 set aLabel 0:2
@@ -73,32 +67,20 @@ if { ${IsDone} != 0 } {
        puts "OCC1228: ERROR (case 2)"
 }
 
-catch {set aBoundingBox3 [bounding aBox3]}
-set X1_Box3 0
-set Y1_Box3 0
-set Z1_Box3 0
-set X2_Box3 0
-set Y2_Box3 0
-set Z2_Box3 0
-catch {set X1_Box3 [lindex ${aBoundingBox3} 0]}
-catch {set Y1_Box3 [lindex ${aBoundingBox3} 1]}
-catch {set Z1_Box3 [lindex ${aBoundingBox3} 2]}
-catch {set X2_Box3 [lindex ${aBoundingBox3} 3]}
-catch {set Y2_Box3 [lindex ${aBoundingBox3} 4]}
-catch {set Z2_Box3 [lindex ${aBoundingBox3} 5]}
-
-if { ${X1_Box1} != ${X1_Box3} || 
-     ${Y1_Box1} != ${Y1_Box3} || 
-     ${Z1_Box1} != ${Z1_Box3} || 
-     ${X2_Box1} != ${X2_Box3} || 
-     ${Y2_Box1} != ${Y2_Box3} || 
-     ${Z2_Box1} != ${Z2_Box3}   } {
-       puts "X1_Box1=${X1_Box1} X1_Box3=${X1_Box3}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box3=${Y1_Box3}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box3=${Z1_Box3}"
-       puts "X2_Box1=${X2_Box1} X2_Box3=${X2_Box3}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box3=${Y2_Box3}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box3=${Z2_Box3}"
+bounding -s aBox3 -save X1_Box3 Y1_Box3 Z1_Box3 X2_Box3 Y2_Box3 Z2_Box3
+
+if { [dval X1_Box1] != [dval X1_Box3] || 
+     [dval Y1_Box1] != [dval Y1_Box3] || 
+     [dval Z1_Box1] != [dval Z1_Box3] || 
+     [dval X2_Box1] != [dval X2_Box3] || 
+     [dval Y2_Box1] != [dval Y2_Box3] || 
+     [dval Z2_Box1] != [dval Z2_Box3] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box3=[dval X1_Box3]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box3=[dval Y1_Box3]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box3=[dval Z1_Box3]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box3=[dval X2_Box3]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box3=[dval Y2_Box3]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box3=[dval Z2_Box3]"
        puts "Get a value of TNaming_NamedShape attribute from restoring document: Error"
        puts "OCC1228: ERROR (case 3)"
 } else {
index bac87a5..ce28085 100755 (executable)
@@ -35,13 +35,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -81,28 +75,20 @@ if { ${IsDone} != 0 } {
        puts "OCC1228: ERROR (case 2)"
 }
 
-catch {set aBoundingBox2 [bounding aBox2]}
-set X1_Box2 0
-set Y1_Box2 0
-set Z1_Box2 0
-set X2_Box2 0
-set Y2_Box2 0
-set Z2_Box2 0
-catch {set X1_Box2 [lindex ${aBoundingBox2} 0]}
-catch {set Y1_Box2 [lindex ${aBoundingBox2} 1]}
-catch {set Z1_Box2 [lindex ${aBoundingBox2} 2]}
-catch {set X2_Box2 [lindex ${aBoundingBox2} 3]}
-catch {set Y2_Box2 [lindex ${aBoundingBox2} 4]}
-catch {set Z2_Box2 [lindex ${aBoundingBox2} 5]}
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Get a link between attributes of the same document from restoring document: Error"
        puts "OCC1228: ERROR (case 3)"
 } else {
index 1d1fedb..c78b3d7 100644 (file)
@@ -173,7 +173,7 @@ if !$Create_Doc {
   # NamedShape
   eval box Box $test_boxXYZ $test_boxDX $test_boxDY $test_boxDZ
   if [catch {GetShape D 0:1:6 b}] {puts "Error: NamedShape not found"
-  } elseif {[bounding b] != [bounding Box]} {puts "Error: invalid NamedShape"
+  } elseif {[bounding -s b -dump] != [bounding -s Box -dump]} {puts "Error: invalid NamedShape"
   } else {
     checkshape b
     checkprops b -l [expr $test_boxDX * 8 + $test_boxDY * 8 + $test_boxDZ * 8]
index d3242f1..411cf45 100755 (executable)
@@ -18,13 +18,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 # Create a label
 set aLabel 0:2
@@ -51,27 +45,20 @@ Redo D
 # Get a shape from the label
 GetShape D ${aLabel} aBox3
 
-set aBoundingBox3 [bounding aBox3]
-set X1_Box3 [lindex ${aBoundingBox3} 0]
-set Y1_Box3 [lindex ${aBoundingBox3} 1]
-set Z1_Box3 [lindex ${aBoundingBox3} 2]
-set X2_Box3 [lindex ${aBoundingBox3} 3]
-set Y2_Box3 [lindex ${aBoundingBox3} 4]
-set Z2_Box3 [lindex ${aBoundingBox3} 5]
+bounding -s aBox3 -save X1_Box3 Y1_Box3 Z1_Box3 X2_Box3 Y2_Box3 Z2_Box3
 
-if { ${X1_Box1} != ${X1_Box3} || 
-     ${Y1_Box1} != ${Y1_Box3} || 
-     ${Z1_Box1} != ${Z1_Box3} || 
-     ${X2_Box1} != ${X2_Box3} || 
-     ${Y2_Box1} != ${Y2_Box3} || 
-     ${Z2_Box1} != ${Z2_Box3} ||
-     [info exists aBox2] } {
-       puts "X1_Box1=${X1_Box1} X1_Box3=${X1_Box3}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box3=${Y1_Box3}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box3=${Z1_Box3}"
-       puts "X2_Box1=${X2_Box1} X2_Box3=${X2_Box3}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box3=${Y2_Box3}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box3=${Z2_Box3}"
+if { [dval X1_Box1] != [dval X1_Box3] || 
+     [dval Y1_Box1] != [dval Y1_Box3] || 
+     [dval Z1_Box1] != [dval Z1_Box3] || 
+     [dval X2_Box1] != [dval X2_Box3] || 
+     [dval Y2_Box1] != [dval Y2_Box3] || 
+     [dval Z2_Box1] != [dval Z2_Box3] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box3=[dval X1_Box3]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box3=[dval Y1_Box3]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box3=[dval Z1_Box3]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box3=[dval X2_Box3]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box3=[dval Y2_Box3]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box3=[dval Z2_Box3]"
        puts "SetShape command: Error"
        return
 }
index 7e78e56..bb14d46 100755 (executable)
@@ -18,13 +18,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 # Create a label
 set aLabel 0:2
@@ -51,27 +45,20 @@ Redo D
 # Get a shape from the label
 GetShape D ${aLabel} aBox3
 
-set aBoundingBox3 [bounding aBox3]
-set X1_Box3 [lindex ${aBoundingBox3} 0]
-set Y1_Box3 [lindex ${aBoundingBox3} 1]
-set Z1_Box3 [lindex ${aBoundingBox3} 2]
-set X2_Box3 [lindex ${aBoundingBox3} 3]
-set Y2_Box3 [lindex ${aBoundingBox3} 4]
-set Z2_Box3 [lindex ${aBoundingBox3} 5]
+bounding -s aBox3 -save X1_Box3 Y1_Box3 Z1_Box3 X2_Box3 Y2_Box3 Z2_Box3
 
-if { ${X1_Box1} != ${X1_Box3} || 
-     ${Y1_Box1} != ${Y1_Box3} || 
-     ${Z1_Box1} != ${Z1_Box3} || 
-     ${X2_Box1} != ${X2_Box3} || 
-     ${Y2_Box1} != ${Y2_Box3} || 
-     ${Z2_Box1} != ${Z2_Box3} ||
-     [info exists aBox2] } {
-       puts "X1_Box1=${X1_Box1} X1_Box3=${X1_Box3}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box3=${Y1_Box3}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box3=${Z1_Box3}"
-       puts "X2_Box1=${X2_Box1} X2_Box3=${X2_Box3}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box3=${Y2_Box3}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box3=${Z2_Box3}"
+if { [dval X1_Box1] != [dval X1_Box3] || 
+     [dval Y1_Box1] != [dval Y1_Box3] || 
+     [dval Z1_Box1] != [dval Z1_Box3] || 
+     [dval X2_Box1] != [dval X2_Box3] || 
+     [dval Y2_Box1] != [dval Y2_Box3] || 
+     [dval Z2_Box1] != [dval Z2_Box3] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box3=[dval X1_Box3]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box3=[dval Y1_Box3]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box3=[dval Z1_Box3]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box3=[dval X2_Box3]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box3=[dval Y2_Box3]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box3=[dval Z2_Box3]"
        puts "NewShape command: Error"
        return
 }
index 48fd5f0..9db9449 100755 (executable)
@@ -18,13 +18,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 # Create a label
 set aLabel 0:2
@@ -61,26 +55,20 @@ if { ${IsDone} != 0 } {
        return
 }
 
-set aBoundingBox3 [bounding aBox3]
-set X1_Box3 [lindex ${aBoundingBox3} 0]
-set Y1_Box3 [lindex ${aBoundingBox3} 1]
-set Z1_Box3 [lindex ${aBoundingBox3} 2]
-set X2_Box3 [lindex ${aBoundingBox3} 3]
-set Y2_Box3 [lindex ${aBoundingBox3} 4]
-set Z2_Box3 [lindex ${aBoundingBox3} 5]
+bounding -s aBox3 -save X1_Box3 Y1_Box3 Z1_Box3 X2_Box3 Y2_Box3 Z2_Box3
 
-if { ${X1_Box1} != ${X1_Box3} || 
-     ${Y1_Box1} != ${Y1_Box3} || 
-     ${Z1_Box1} != ${Z1_Box3} || 
-     ${X2_Box1} != ${X2_Box3} || 
-     ${Y2_Box1} != ${Y2_Box3} || 
-     ${Z2_Box1} != ${Z2_Box3}   } {
-       puts "X1_Box1=${X1_Box1} X1_Box3=${X1_Box3}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box3=${Y1_Box3}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box3=${Z1_Box3}"
-       puts "X2_Box1=${X2_Box1} X2_Box3=${X2_Box3}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box3=${Y2_Box3}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box3=${Z2_Box3}"
+if { [dval X1_Box1] != [dval X1_Box3] || 
+     [dval Y1_Box1] != [dval Y1_Box3] || 
+     [dval Z1_Box1] != [dval Z1_Box3] || 
+     [dval X2_Box1] != [dval X2_Box3] || 
+     [dval Y2_Box1] != [dval Y2_Box3] || 
+     [dval Z2_Box1] != [dval Z2_Box3] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box3=[dval X1_Box3]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box3=[dval Y1_Box3]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box3=[dval Z1_Box3]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box3=[dval X2_Box3]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box3=[dval Y2_Box3]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box3=[dval Z2_Box3]"
        puts "Get a value of TNaming_NamedShape attribute from restoring document: Error"
        return
 }
index df9227d..b84e674 100755 (executable)
@@ -47,13 +47,7 @@ foreach S [directory [concat $aBox1$ter]] {
        puts "SubShape=$S"
 
        #Memorize a bounding box of the selected sub-shape
-       set aBoundingBox1 [bounding ${S}]
-       set X1_Box1 [lindex ${aBoundingBox1} 0]
-       set Y1_Box1 [lindex ${aBoundingBox1} 1]
-       set Z1_Box1 [lindex ${aBoundingBox1} 2]
-       set X2_Box1 [lindex ${aBoundingBox1} 3]
-       set Y2_Box1 [lindex ${aBoundingBox1} 4]
-       set Z2_Box1 [lindex ${aBoundingBox1} 5]
+       bounding -s ${S} -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
        # Select a sub-shape
        set LABEL [Label D 0:$iSubLabel]
@@ -66,15 +60,9 @@ foreach S [directory [concat $aBox1$ter]] {
        GetShape D ${LABEL} aSubShape
        
        # Get bounding box
-       set aBoundingBox2 [bounding aSubShape]
-       set X1_Box2 [lindex ${aBoundingBox2} 0]
-       set Y1_Box2 [lindex ${aBoundingBox2} 1]
-       set Z1_Box2 [lindex ${aBoundingBox2} 2]
-       set X2_Box2 [lindex ${aBoundingBox2} 3]
-       set Y2_Box2 [lindex ${aBoundingBox2} 4]
-       set Z2_Box2 [lindex ${aBoundingBox2} 5]
+       bounding -s aSubShape -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
        
-       if {${X1_Box1} != ${X1_Box2} || ${Y1_Box1} != ${Y1_Box2} || ${Z1_Box1} != ${Z1_Box2} || ${X2_Box1} != ${X2_Box2} || ${Y2_Box1} != ${Y2_Box2} || ${Z2_Box1} != ${Z2_Box2}} {
+       if {[dval X1_Box1] != [dval X1_Box2] || [dval Y1_Box1] != [dval Y1_Box2] || [dval Z1_Box1] != [dval Z1_Box2] || [dval X2_Box1] != [dval X2_Box2] || [dval Y2_Box1] != [dval Y2_Box2] || [dval Z2_Box1] != [dval Z2_Box2]} {
                puts "SelectGeometry command (${i}): Error"
        }
 }
index 748cda0..66c64d5 100755 (executable)
@@ -47,13 +47,7 @@ foreach S [directory [concat $aBox1$ter]] {
        puts "SubShape=$S"
 
        #Memorize a bounding box of the selected sub-shape
-       set aBoundingBox1 [bounding ${S}]
-       set X1_Box1 [lindex ${aBoundingBox1} 0]
-       set Y1_Box1 [lindex ${aBoundingBox1} 1]
-       set Z1_Box1 [lindex ${aBoundingBox1} 2]
-       set X2_Box1 [lindex ${aBoundingBox1} 3]
-       set Y2_Box1 [lindex ${aBoundingBox1} 4]
-       set Z2_Box1 [lindex ${aBoundingBox1} 5]
+       bounding -s ${S} -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
        # Select a sub-shape
        set LABEL [Label D 0:$iSubLabel]
@@ -66,15 +60,9 @@ foreach S [directory [concat $aBox1$ter]] {
        GetShape D ${LABEL} aSubShape
        
        # Get bounding box
-       set aBoundingBox2 [bounding aSubShape]
-       set X1_Box2 [lindex ${aBoundingBox2} 0]
-       set Y1_Box2 [lindex ${aBoundingBox2} 1]
-       set Z1_Box2 [lindex ${aBoundingBox2} 2]
-       set X2_Box2 [lindex ${aBoundingBox2} 3]
-       set Y2_Box2 [lindex ${aBoundingBox2} 4]
-       set Z2_Box2 [lindex ${aBoundingBox2} 5]
+       bounding -s aSubShape -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
        
-       if {${X1_Box1} != ${X1_Box2} || ${Y1_Box1} != ${Y1_Box2} || ${Z1_Box1} != ${Z1_Box2} || ${X2_Box1} != ${X2_Box2} || ${Y2_Box1} != ${Y2_Box2} || ${Z2_Box1} != ${Z2_Box2}} {
+       if {[dval X1_Box1] != [dval X1_Box2] || [dval Y1_Box1] != [dval Y1_Box2] || [dval Z1_Box1] != [dval Z1_Box2] || [dval X2_Box1] != [dval X2_Box2] || [dval Y2_Box1] != [dval Y2_Box2] || [dval Z2_Box1] != [dval Z2_Box2]} {
                puts "SelectGeometry command (${i}): Error"
        }
 }
index f9c7e9d..b1276e6 100755 (executable)
@@ -47,13 +47,7 @@ foreach S [directory [concat $aBox1$ter]] {
        puts "SubShape=$S"
 
        #Memorize a bounding box of the selected sub-shape
-       set aBoundingBox1 [bounding ${S}]
-       set X1_Box1 [lindex ${aBoundingBox1} 0]
-       set Y1_Box1 [lindex ${aBoundingBox1} 1]
-       set Z1_Box1 [lindex ${aBoundingBox1} 2]
-       set X2_Box1 [lindex ${aBoundingBox1} 3]
-       set Y2_Box1 [lindex ${aBoundingBox1} 4]
-       set Z2_Box1 [lindex ${aBoundingBox1} 5]
+       bounding -s ${S} -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
        # Select a sub-shape
        set LABEL [Label D 0:$iSubLabel]
@@ -66,15 +60,9 @@ foreach S [directory [concat $aBox1$ter]] {
        GetShape D ${LABEL} aSubShape
        
        # Get bounding box
-       set aBoundingBox2 [bounding aSubShape]
-       set X1_Box2 [lindex ${aBoundingBox2} 0]
-       set Y1_Box2 [lindex ${aBoundingBox2} 1]
-       set Z1_Box2 [lindex ${aBoundingBox2} 2]
-       set X2_Box2 [lindex ${aBoundingBox2} 3]
-       set Y2_Box2 [lindex ${aBoundingBox2} 4]
-       set Z2_Box2 [lindex ${aBoundingBox2} 5]
+       bounding -s aSubShape -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
        
-       if {${X1_Box1} != ${X1_Box2} || ${Y1_Box1} != ${Y1_Box2} || ${Z1_Box1} != ${Z1_Box2} || ${X2_Box1} != ${X2_Box2} || ${Y2_Box1} != ${Y2_Box2} || ${Z2_Box1} != ${Z2_Box2}} {
+       if {[dval X1_Box1] != [dval X1_Box2] || [dval Y1_Box1] != [dval Y1_Box2] || [dval Z1_Box1] != [dval Z1_Box2] || [dval X2_Box1] != [dval X2_Box2] || [dval Y2_Box1] != [dval Y2_Box2] || [dval Z2_Box1] != [dval Z2_Box2]} {
                puts "SelectGeometry command (${i}): Error"
        }
 }
index 089b05b..baaca39 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -63,22 +57,20 @@ Redo Doc1
 # Get a shape from 'TLabel1'
 GetShape Doc1 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Copy attributes of the same document: Error"
        return
 }
index ac615da..8589d2b 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -63,22 +57,20 @@ Redo Doc2
 # Get a shape from 'TLabel1'
 GetShape Doc2 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Copy attributes to another document: Error"
        return
 }
index 3a91610..dce34e0 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -63,22 +57,20 @@ Redo Doc1
 # Get a shape from 'TLabel1'
 GetShape Doc1 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Set a link between attributes of the same document: Error"
        return
 }
index 9864c24..9faac9d 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -68,22 +62,20 @@ Redo Doc1
 # Get a shape from 'TLabel1'
 GetShape Doc1 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Set a link between attributes of the same document: Error"
        return
 }
index af538ed..3ade9a3 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -76,22 +70,20 @@ if { ${IsDone} != 0 } {
        return
 }
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Get a link between attributes of the same document from restoring document: Error"
        return
 }
index e1af519..65a5c7f 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -63,22 +57,20 @@ Redo Doc2
 # Get a shape from 'TLabel1'
 GetShape Doc2 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Set a link between attributes of another document: Error"
        return
 }
index e7cac99..0843d4b 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -68,22 +62,20 @@ Redo Doc1
 # Get a shape from 'TLabel1'
 GetShape Doc2 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Set a link between attributes of the same document: Error"
        return
 }
index 2273c11..4907c23 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -74,22 +68,20 @@ Redo Doc1
 # 11. Get a shape from 'TLabel1'
 GetShape Doc1 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} == ${X1_Box2} || 
-     ${Y1_Box1} == ${Y1_Box2} || 
-     ${Z1_Box1} == ${Z1_Box2} || 
-     ${X2_Box1} == ${X2_Box2} || 
-     ${Y2_Box1} == ${Y2_Box2} || 
-     ${Z2_Box1} == ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] == [dval X1_Box2] || 
+     [dval Y1_Box1] == [dval Y1_Box2] || 
+     [dval Z1_Box1] == [dval Z1_Box2] || 
+     [dval X2_Box1] == [dval X2_Box2] || 
+     [dval Y2_Box1] == [dval Y2_Box2] || 
+     [dval Z2_Box1] == [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Updating a link between attributes of the same document: Error"
        return
 }
index 04a15b1..70a731f 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -74,22 +68,20 @@ Redo Doc2
 # Get a shape from 'TLabel1'
 GetShape Doc2 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-if { ${X1_Box1} == ${X1_Box2} || 
-     ${Y1_Box1} == ${Y1_Box2} || 
-     ${Z1_Box1} == ${Z1_Box2} || 
-     ${X2_Box1} == ${X2_Box2} || 
-     ${Y2_Box1} == ${Y2_Box2} || 
-     ${Z2_Box1} == ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] == [dval X1_Box2] || 
+     [dval Y1_Box1] == [dval Y1_Box2] || 
+     [dval Z1_Box1] == [dval Z1_Box2] || 
+     [dval X2_Box1] == [dval X2_Box2] || 
+     [dval Y2_Box1] == [dval Y2_Box2] || 
+     [dval Z2_Box1] == [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Updating a link between attributes of the same document: Error"
        return
 }
index 486b4ed..3c3cc27 100755 (executable)
@@ -30,13 +30,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -54,13 +48,7 @@ set aSetDZ12 2300
 
 box aBox12 ${aSetX12} ${aSetY12} ${aSetZ12} ${aSetDX12} ${aSetDY12} ${aSetDZ12}
 
-set aBoundingBox12 [bounding aBox12]
-set X1_Box12 [lindex ${aBoundingBox12} 0]
-set Y1_Box12 [lindex ${aBoundingBox12} 1]
-set Z1_Box12 [lindex ${aBoundingBox12} 2]
-set X2_Box12 [lindex ${aBoundingBox12} 3]
-set Y2_Box12 [lindex ${aBoundingBox12} 4]
-set Z2_Box12 [lindex ${aBoundingBox12} 5]
+bounding -s aBox12 -save X1_Box12 Y1_Box12 Z1_Box12 X2_Box12 Y2_Box12 Z2_Box12
 
 SetShape Doc1 ${aLabel12} aBox12
 
@@ -111,50 +99,38 @@ Redo Doc2
 # Get a shape from 'TLabel1'
 GetShape Doc2 ${aLabel2} aBox2
 
-set aBoundingBox2 [bounding aBox2]
-set X1_Box2 [lindex ${aBoundingBox2} 0]
-set Y1_Box2 [lindex ${aBoundingBox2} 1]
-set Z1_Box2 [lindex ${aBoundingBox2} 2]
-set X2_Box2 [lindex ${aBoundingBox2} 3]
-set Y2_Box2 [lindex ${aBoundingBox2} 4]
-set Z2_Box2 [lindex ${aBoundingBox2} 5]
+bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
 
 # Get a shape from 'T2Label1'
 GetShape Doc2 ${aLabel22} aBox22
 
-set aBoundingBox22 [bounding aBox22]
-set X1_Box22 [lindex ${aBoundingBox22} 0]
-set Y1_Box22 [lindex ${aBoundingBox22} 1]
-set Z1_Box22 [lindex ${aBoundingBox22} 2]
-set X2_Box22 [lindex ${aBoundingBox22} 3]
-set Y2_Box22 [lindex ${aBoundingBox22} 4]
-set Z2_Box22 [lindex ${aBoundingBox22} 5]
-
-if { ${X1_Box1} == ${X1_Box2} || 
-     ${Y1_Box1} == ${Y1_Box2} || 
-     ${Z1_Box1} == ${Z1_Box2} || 
-     ${X2_Box1} == ${X2_Box2} || 
-     ${Y2_Box1} == ${Y2_Box2} || 
-     ${Z2_Box1} == ${Z2_Box2} ||
-
-     ${X1_Box12} == ${X1_Box22} || 
-     ${Y1_Box12} == ${Y1_Box22} || 
-     ${Z1_Box12} == ${Z1_Box22} || 
-     ${X2_Box12} == ${X2_Box22} || 
-     ${Y2_Box12} == ${Y2_Box22} || 
-     ${Z2_Box12} == ${Z2_Box22} ||
-
-     ${X1_Box2} == ${X1_Box22} || 
-     ${Y1_Box2} == ${Y1_Box22} || 
-     ${Z1_Box2} == ${Z1_Box22} || 
-     ${X2_Box2} == ${X2_Box22} || 
-     ${Y2_Box2} == ${Y2_Box22} || 
-     ${Z2_Box2} == ${Z2_Box22} } {
-
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
-       puts "X1_Box12=${X1_Box12} Y1_Box12=${Y1_Box12} Z1_Box12=${Z1_Box12} X2_Box12=${X2_Box12} Y2_Box12=${Y2_Box12} Z2_Box12=${Z2_Box12}"
-       puts "X1_Box22=${X1_Box22} Y1_Box22=${Y1_Box22} Z1_Box22=${Z1_Box22} X2_Box22=${X2_Box22} Y2_Box22=${Y2_Box22} Z2_Box22=${Z2_Box22}"
+bounding -s aBox22 -save X1_Box22 Y1_Box22 Z1_Box22 X2_Box22 Y2_Box22 Z2_Box22
+
+if { [dval X1_Box1] == [dval X1_Box2] || 
+     [dval Y1_Box1] == [dval Y1_Box2] || 
+     [dval Z1_Box1] == [dval Z1_Box2] || 
+     [dval X2_Box1] == [dval X2_Box2] || 
+     [dval Y2_Box1] == [dval Y2_Box2] || 
+     [dval Z2_Box1] == [dval Z2_Box2] ||
+
+     [dval X1_Box12] == [dval X1_Box22] || 
+     [dval Y1_Box12] == [dval Y1_Box22] || 
+     [dval Z1_Box12] == [dval Z1_Box22] || 
+     [dval X2_Box12] == [dval X2_Box22] || 
+     [dval Y2_Box12] == [dval Y2_Box22] || 
+     [dval Z2_Box12] == [dval Z2_Box22] ||
+
+     [dval X1_Box2] == [dval X1_Box22] || 
+     [dval Y1_Box2] == [dval Y1_Box22] || 
+     [dval Z1_Box2] == [dval Z1_Box22] || 
+     [dval X2_Box2] == [dval X2_Box22] || 
+     [dval Y2_Box2] == [dval Y2_Box22] || 
+     [dval Z2_Box2] == [dval Z2_Box22] } {
+
+       puts "X1_Box1=[dval X1_Box1] Y1_Box1=[dval Y1_Box1] Z1_Box1=[dval Z1_Box1] X2_Box1=[dval X2_Box1] Y2_Box1=[dval Y2_Box1] Z2_Box1=[dval Z2_Box1]"
+       puts "X1_Box2=[dval X1_Box2] Y1_Box2=[dval Y1_Box2] Z1_Box2=[dval Z1_Box2] X2_Box2=[dval X2_Box2] Y2_Box2=[dval Y2_Box2] Z2_Box2=[dval Z2_Box2]"
+       puts "X1_Box12=[dval X1_Box12] Y1_Box12=[dval Y1_Box12] Z1_Box12=[dval Z1_Box12] X2_Box12=[dval X2_Box12] Y2_Box12=[dval Y2_Box12] Z2_Box12=[dval Z2_Box12]"
+       puts "X1_Box22=[dval X1_Box22] Y1_Box22=[dval Y1_Box22] Z1_Box22=[dval Z1_Box22] X2_Box22=[dval X2_Box22] Y2_Box22=[dval Y2_Box22] Z2_Box22=[dval Z2_Box22]"
        puts "Updating all links between attributes of the same document: Error"
        return
 }
index ddb2ff1..3578741 100644 (file)
@@ -37,16 +37,15 @@ proc get_element { type args } {
             global $element
             distmini dd ver $element
             if { [string match "*$type*" [whatis $element]] } {
-               set bbox [bounding $element]
+               set bbox [bounding -s $element -save xx1 yy1 zz1 xx2 yy2 zz2 ]
 # Get distance
-               set dv [lindex [dump dd_val] 5]
-               if {    [expr {
-                       [lindex $bbox 0] - 1e-2 <= $x  && $x  <= [lindex $bbox 3] + 1e-2
-                  &&   [lindex $bbox 1] - 1e-2 <= $y  && $y  <= [lindex $bbox 4] + 1e-2
-                  &&   [lindex $bbox 2] - 1e-2 <= $z  && $z  <= [lindex $bbox 5] + 1e-2
-                  &&   [lindex $bbox 0] - 1e-2 <= $x1 && $x1 <= [lindex $bbox 3] + 1e-2
-                  &&   [lindex $bbox 1] - 1e-2 <= $y1 && $y1 <= [lindex $bbox 4] + 1e-2
-                  &&   [lindex $bbox 2] - 1e-2 <= $z1 && $z1 <= [lindex $bbox 5] + 1e-2
+               set dv [lindex [dump dd_val] 5]
+               if {[expr {[dval xx1-1e-2] <= $x  && $x  <= [dval xx2+1e-2]
+              && [dval yy1-1e-2] <= $y  && $y  <= [dval yy2+1e-2]
+              && [dval zz1-1e-2] <= $z  && $z  <= [dval zz2+1e-2]
+              && [dval xx1-1e-2] <= $x1 && $x1 <= [dval xx2+1e-2]
+              && [dval yy1-1e-2] <= $y1 && $y1 <= [dval yy2+1e-2]
+              && [dval zz1-1e-2] <= $z1 && $z1 <= [dval zz2+1e-2]
                        }]
                   } {
                   if { [llength $res] == 0 } {
index 286b958..895e070 100644 (file)
@@ -12,7 +12,7 @@ if [regexp "Cannot write to the file $file" [binsave b $file]] {
   puts "Error: binrestore"
 } else {
   file delete $file
-  if {[bounding b] != [bounding bb]} {
+  if {[bounding -s b -dump] != [bounding -s bb -dump]} {
     puts "Error: restored shape has another bounding box"
   }
   checkshape bb
index 3e8d37d..4d79588 100644 (file)
@@ -12,7 +12,7 @@ if [regexp "Cannot write to the file $file" [binsave b $file]] {
   puts "Error: binrestore"
 } else {
   file delete $file
-  if {[bounding b] != [bounding bb]} {
+  if {[bounding -s b -dump] != [bounding -s bb -dump]} {
     puts "Error: restored shape has another bounding box"
   }
   checkshape bb
index 60756b8..d8a546c 100644 (file)
@@ -12,7 +12,7 @@ if [regexp "Cannot write to the file $file" [binsave b $file]] {
   puts "Error: binrestore"
 } else {
   file delete $file
-  if {[bounding b] != [bounding bb]} {
+  if {[bounding -s b -dump] != [bounding -s bb -dump]} {
     puts "Error: restored shape has another bounding box"
   }
   checkshape bb
diff --git a/tests/perf/modalg/bug29311 b/tests/perf/modalg/bug29311
new file mode 100644 (file)
index 0000000..ad95d41
--- /dev/null
@@ -0,0 +1,22 @@
+puts "========"
+puts "OCC29311"
+puts "========"
+puts ""
+#################################################
+# Implementation of the Oriented Bounding Boxes (OBB) functionality
+#################################################
+
+set NbIters 101
+set step [expr 360.0/($NbIters-1) ]
+
+restore [locate_data_file bug29237_no_overlap.lhs.brep] a
+for {set i 1} { $i <= $NbIters} { incr i } {
+  bounding -s a -obb -perfmeter OBBL$i 5
+  if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
+}
+
+restore [locate_data_file bug29237_no_overlap.rhs.brep] a
+for {set i 1} { $i <= $NbIters} { incr i } {
+  bounding -s a -obb -perfmeter OBBR$i 5
+  if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
+}
index 06af17a..c74849a 100644 (file)
@@ -11,13 +11,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 set aLabel 0:2
 SetShape D ${aLabel} aBox1
@@ -39,26 +33,20 @@ set IsDone [catch {GetShape DD ${aLabel} aBox5} aResult]
 if { ${IsDone} != 0 } {
     puts "Error : Get a value of TDataStd_Shape attribute from restoring document"
 } else {
-    set aBoundingBox5 [bounding aBox5]
-    set X1_Box5 [lindex ${aBoundingBox5} 0]
-    set Y1_Box5 [lindex ${aBoundingBox5} 1]
-    set Z1_Box5 [lindex ${aBoundingBox5} 2]
-    set X2_Box5 [lindex ${aBoundingBox5} 3]
-    set Y2_Box5 [lindex ${aBoundingBox5} 4]
-    set Z2_Box5 [lindex ${aBoundingBox5} 5]
-
-    if { ${X1_Box1} != ${X1_Box5} || 
-     ${Y1_Box1} != ${Y1_Box5} || 
-     ${Z1_Box1} != ${Z1_Box5} || 
-     ${X2_Box1} != ${X2_Box5} || 
-     ${Y2_Box1} != ${Y2_Box5} || 
-     ${Z2_Box1} != ${Z2_Box5} } {
-       puts "X1_Box1=${X1_Box1} X1_Box5=${X1_Box5}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box5=${Y1_Box5}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box5=${Z1_Box5}"
-       puts "X2_Box1=${X2_Box1} X2_Box5=${X2_Box5}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box5=${Y2_Box5}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box5=${Z2_Box5}"
+    bounding -s aBox5 -save X1_Box5 Y1_Box5 Z1_Box5 X2_Box5 Y2_Box5 Z2_Box5
+
+if { [dval X1_Box1] != [dval X1_Box5] || 
+     [dval Y1_Box1] != [dval Y1_Box5] || 
+     [dval Z1_Box1] != [dval Z1_Box5] || 
+     [dval X2_Box1] != [dval X2_Box5] || 
+     [dval Y2_Box1] != [dval Y2_Box5] || 
+     [dval Z2_Box1] != [dval Z2_Box5] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box5=[dval X1_Box5]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box5=[dval Y1_Box5]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box5=[dval Z1_Box5]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box5=[dval X2_Box5]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box5=[dval Y2_Box5]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box5=[dval Z2_Box5]"
        puts "Error : et a value of TDataStd_Shape attribute from restoring document"
     }
 }
index 197515b..802ada8 100644 (file)
@@ -11,13 +11,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 # Create a label
 set aLabel 0:2
@@ -47,26 +41,20 @@ if { ${IsDone} != 0 } {
     puts ${aResult}
     puts "Error : Get a value of TNaming_NamedShape attribute from restoring document"
 } else {
-    set aBoundingBox3 [bounding aBox3]
-    set X1_Box3 [lindex ${aBoundingBox3} 0]
-    set Y1_Box3 [lindex ${aBoundingBox3} 1]
-    set Z1_Box3 [lindex ${aBoundingBox3} 2]
-    set X2_Box3 [lindex ${aBoundingBox3} 3]
-    set Y2_Box3 [lindex ${aBoundingBox3} 4]
-    set Z2_Box3 [lindex ${aBoundingBox3} 5]
-
-    if { ${X1_Box1} != ${X1_Box3} || 
-     ${Y1_Box1} != ${Y1_Box3} || 
-     ${Z1_Box1} != ${Z1_Box3} || 
-     ${X2_Box1} != ${X2_Box3} || 
-     ${Y2_Box1} != ${Y2_Box3} || 
-     ${Z2_Box1} != ${Z2_Box3}   } {
-       puts "X1_Box1=${X1_Box1} X1_Box3=${X1_Box3}"
-       puts "Y1_Box1=${Y1_Box1} Y1_Box3=${Y1_Box3}"
-       puts "Z1_Box1=${Z1_Box1} Z1_Box3=${Z1_Box3}"
-       puts "X2_Box1=${X2_Box1} X2_Box3=${X2_Box3}"
-       puts "Y2_Box1=${Y2_Box1} Y2_Box3=${Y2_Box3}"
-       puts "Z2_Box1=${Z2_Box1} Z2_Box3=${Z2_Box3}"
+    bounding -s aBox3 -save X1_Box3 Y1_Box3 Z1_Box3 X2_Box3 Y2_Box3 Z2_Box3
+
+if { [dval X1_Box1] != [dval X1_Box3] || 
+     [dval Y1_Box1] != [dval Y1_Box3] || 
+     [dval Z1_Box1] != [dval Z1_Box3] || 
+     [dval X2_Box1] != [dval X2_Box3] || 
+     [dval Y2_Box1] != [dval Y2_Box3] || 
+     [dval Z2_Box1] != [dval Z2_Box3] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box3=[dval X1_Box3]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box3=[dval Y1_Box3]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box3=[dval Z1_Box3]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box3=[dval X2_Box3]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box3=[dval Y2_Box3]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box3=[dval Z2_Box3]"
        puts "Error : Get a value of TNaming_NamedShape attribute from restoring document"
     }
 }
index a378f9d..8d95cf2 100644 (file)
@@ -27,13 +27,7 @@ set aSetDZ1 300
 
 box aBox1 ${aSetX1} ${aSetY1} ${aSetZ1} ${aSetDX1} ${aSetDY1} ${aSetDZ1}
 
-set aBoundingBox1 [bounding aBox1]
-set X1_Box1 [lindex ${aBoundingBox1} 0]
-set Y1_Box1 [lindex ${aBoundingBox1} 1]
-set Z1_Box1 [lindex ${aBoundingBox1} 2]
-set X2_Box1 [lindex ${aBoundingBox1} 3]
-set Y2_Box1 [lindex ${aBoundingBox1} 4]
-set Z2_Box1 [lindex ${aBoundingBox1} 5]
+bounding -s aBox1 -save X1_Box1 Y1_Box1 Z1_Box1 X2_Box1 Y2_Box1 Z2_Box1
 
 SetShape Doc1 ${aLabel1} aBox1
 
@@ -65,22 +59,20 @@ set IsDone [catch {GetShape Doc2 ${aLabel2} aBox2} aResult]
 if { ${IsDone} != 0 } {
     puts "Error : Get a value of TNaming_NamedShape attribute from restoring document"
 } else {
-    set aBoundingBox2 [bounding aBox2]
-    set X1_Box2 [lindex ${aBoundingBox2} 0]
-    set Y1_Box2 [lindex ${aBoundingBox2} 1]
-    set Z1_Box2 [lindex ${aBoundingBox2} 2]
-    set X2_Box2 [lindex ${aBoundingBox2} 3]
-    set Y2_Box2 [lindex ${aBoundingBox2} 4]
-    set Z2_Box2 [lindex ${aBoundingBox2} 5]
-
-    if { ${X1_Box1} != ${X1_Box2} || 
-     ${Y1_Box1} != ${Y1_Box2} || 
-     ${Z1_Box1} != ${Z1_Box2} || 
-     ${X2_Box1} != ${X2_Box2} || 
-     ${Y2_Box1} != ${Y2_Box2} || 
-     ${Z2_Box1} != ${Z2_Box2} } {
-       puts "X1_Box1=${X1_Box1} Y1_Box1=${Y1_Box1} Z1_Box1=${Z1_Box1} X2_Box1=${X2_Box1} Y2_Box1=${Y2_Box1} Z2_Box1=${Z2_Box1}"
-       puts "X1_Box2=${X1_Box2} Y1_Box2=${Y1_Box2} Z1_Box2=${Z1_Box2} X2_Box2=${X2_Box2} Y2_Box2=${Y2_Box2} Z2_Box2=${Z2_Box2}"
+    bounding -s aBox2 -save X1_Box2 Y1_Box2 Z1_Box2 X2_Box2 Y2_Box2 Z2_Box2
+
+if { [dval X1_Box1] != [dval X1_Box2] || 
+     [dval Y1_Box1] != [dval Y1_Box2] || 
+     [dval Z1_Box1] != [dval Z1_Box2] || 
+     [dval X2_Box1] != [dval X2_Box2] || 
+     [dval Y2_Box1] != [dval Y2_Box2] || 
+     [dval Z2_Box1] != [dval Z2_Box2] } {
+       puts "X1_Box1=[dval X1_Box1] X1_Box2=[dval X1_Box2]"
+       puts "Y1_Box1=[dval Y1_Box1] Y1_Box2=[dval Y1_Box2]"
+       puts "Z1_Box1=[dval Z1_Box1] Z1_Box2=[dval Z1_Box2]"
+       puts "X2_Box1=[dval X2_Box1] X2_Box2=[dval X2_Box2]"
+       puts "Y2_Box1=[dval Y2_Box1] Y2_Box2=[dval Y2_Box2]"
+       puts "Z2_Box1=[dval Z2_Box1] Z2_Box2=[dval Z2_Box2]"
        puts "Error : Get a link between attributes of the same document from restoring document"
     }
 }