0030829: BRepExtrema_ShapeProximity crashes with shape from STL/WRL
[occt.git] / src / BRepExtrema / BRepExtrema_TriangleSet.cxx
1 // Created on: 2014-10-20
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepExtrema_TriangleSet.hxx>
17
18 #include <BRep_Tool.hxx>
19 #include <BVH_LinearBuilder.hxx>
20 #include <Poly_Triangulation.hxx>
21
22 IMPLEMENT_STANDARD_RTTIEXT(BRepExtrema_TriangleSet, BVH_PrimitiveSet3d)
23
24 //=======================================================================
25 //function : BRepExtrema_TriangleSet
26 //purpose  : Creates empty triangle set
27 //=======================================================================
28 BRepExtrema_TriangleSet::BRepExtrema_TriangleSet()
29 {
30   // Set default builder - linear BVH (LBVH)
31   myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeDefault, BVH_Constants_MaxTreeDepth);
32 }
33
34 //=======================================================================
35 //function : BRepExtrema_TriangleSet
36 //purpose  : Creates triangle set from the given face
37 //=======================================================================
38 BRepExtrema_TriangleSet::BRepExtrema_TriangleSet (const BRepExtrema_ShapeList& theFaces)
39 {
40   // Set default builder - linear BVH (LBVH)
41   myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeDefault, BVH_Constants_MaxTreeDepth);
42
43   Init (theFaces);
44 }
45
46 //=======================================================================
47 //function : ~BRepExtrema_TriangleSet
48 //purpose  : Releases resources of triangle set
49 //=======================================================================
50 BRepExtrema_TriangleSet::~BRepExtrema_TriangleSet()
51 {
52   //
53 }
54
55 //=======================================================================
56 //function : Size
57 //purpose  : Returns total number of triangles
58 //=======================================================================
59 Standard_Integer BRepExtrema_TriangleSet::Size() const
60 {
61   return static_cast<Standard_Integer> (myTriangles.size());
62 }
63
64 //=======================================================================
65 //function : Box
66 //purpose  : Returns AABB of the given triangle
67 //=======================================================================
68 BVH_Box<Standard_Real, 3> BRepExtrema_TriangleSet::Box (const Standard_Integer theIndex) const
69 {
70   const BVH_Vec4i& aTriangle = myTriangles[theIndex];
71
72   BVH_Vec3d aMinPnt = myVertexArray[aTriangle.x()].cwiseMin (
73     myVertexArray[aTriangle.y()].cwiseMin (myVertexArray[aTriangle.z()]));
74
75   BVH_Vec3d aMaxPnt = myVertexArray[aTriangle.x()].cwiseMax (
76     myVertexArray[aTriangle.y()].cwiseMax (myVertexArray[aTriangle.z()]));
77
78   return BVH_Box<Standard_Real, 3> (aMinPnt, aMaxPnt);
79 }
80
81 //=======================================================================
82 //function : Center
83 //purpose  : Returns centroid position along specified axis
84 //=======================================================================
85 Standard_Real BRepExtrema_TriangleSet::Center (const Standard_Integer theIndex, const Standard_Integer theAxis) const
86 {
87   const BVH_Vec4i& aTriangle = myTriangles[theIndex];
88
89   if (theAxis == 0)
90   {
91     return (1.0 / 3.0) * (myVertexArray[aTriangle.x()].x() +
92                           myVertexArray[aTriangle.y()].x() +
93                           myVertexArray[aTriangle.z()].x());
94   }
95   else if (theAxis == 1)
96   {
97     return (1.0 / 3.0) * (myVertexArray[aTriangle.x()].y() +
98                           myVertexArray[aTriangle.y()].y() +
99                           myVertexArray[aTriangle.z()].y());
100   }
101   else
102   {
103     return (1.0 / 3.0) * (myVertexArray[aTriangle.x()].z() +
104                           myVertexArray[aTriangle.y()].z() +
105                           myVertexArray[aTriangle.z()].z());
106   }
107 }
108
109 //=======================================================================
110 //function : Swap
111 //purpose  : Swaps indices of two specified triangles
112 //=======================================================================
113 void BRepExtrema_TriangleSet::Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2)
114 {
115   std::swap (myTriangles[theIndex1],
116              myTriangles[theIndex2]);
117 }
118
119 //=======================================================================
120 //function : GetFaceID
121 //purpose  : Returns face ID of the given triangle
122 //=======================================================================
123 Standard_Integer BRepExtrema_TriangleSet::GetFaceID (const Standard_Integer theIndex) const
124 {
125   return myTriangles[theIndex].w();
126 }
127
128 //=======================================================================
129 //function : GetVertices
130 //purpose  : Returns vertices of the given triangle
131 //=======================================================================
132 void BRepExtrema_TriangleSet::GetVertices (const Standard_Integer theIndex,
133                                            BVH_Vec3d&             theVertex1,
134                                            BVH_Vec3d&             theVertex2,
135                                            BVH_Vec3d&             theVertex3) const
136 {
137   BVH_Vec4i aTriangle = myTriangles[theIndex];
138
139   theVertex1 = myVertexArray[aTriangle.x()];
140   theVertex2 = myVertexArray[aTriangle.y()];
141   theVertex3 = myVertexArray[aTriangle.z()];
142 }
143
144 //=======================================================================
145 //function : Clear
146 //purpose  : Clears triangle set data
147 //=======================================================================
148 void BRepExtrema_TriangleSet::Clear()
149 {
150   BVH_Array4i anEmptyTriangles;
151   myTriangles.swap (anEmptyTriangles);
152
153   BVH_Array3d anEmptyVertexArray;
154   myVertexArray.swap (anEmptyVertexArray);
155 }
156
157 //=======================================================================
158 //function : Init
159 //purpose  : Initializes triangle set
160 //=======================================================================
161 Standard_Boolean BRepExtrema_TriangleSet::Init (const BRepExtrema_ShapeList& theFaces)
162 {
163   Clear();
164
165   for (Standard_Integer aFaceIdx = 0; aFaceIdx < theFaces.Size(); ++aFaceIdx)
166   {
167     TopLoc_Location aLocation;
168
169     Handle(Poly_Triangulation) aTriangulation =
170       BRep_Tool::Triangulation (theFaces (aFaceIdx), aLocation);
171
172     if (aTriangulation.IsNull())
173     {
174       return Standard_False;
175     }
176
177     const Standard_Integer aVertOffset =
178       static_cast<Standard_Integer> (myVertexArray.size()) - 1;
179
180     for (Standard_Integer aVertIdx = 1; aVertIdx <= aTriangulation->NbNodes(); ++aVertIdx)
181     {
182       gp_Pnt aVertex = aTriangulation->Nodes().Value (aVertIdx);
183
184       aVertex.Transform (aLocation.Transformation());
185
186       myVertexArray.push_back (BVH_Vec3d (aVertex.X(),
187                                           aVertex.Y(),
188                                           aVertex.Z()));
189     }
190
191     for (Standard_Integer aTriIdx = 1; aTriIdx <= aTriangulation->NbTriangles(); ++aTriIdx)
192     {
193       Standard_Integer aVertex1;
194       Standard_Integer aVertex2;
195       Standard_Integer aVertex3;
196
197       aTriangulation->Triangles().Value (aTriIdx).Get (aVertex1,
198                                                        aVertex2,
199                                                        aVertex3);
200
201       myTriangles.push_back (BVH_Vec4i (aVertex1 + aVertOffset,
202                                         aVertex2 + aVertOffset,
203                                         aVertex3 + aVertOffset,
204                                         aFaceIdx));
205     }
206   }
207
208   MarkDirty(); // needs BVH rebuilding
209
210   Standard_ASSERT_RETURN (!BVH().IsNull(),
211     "Error: Failed to build BVH for primitive set", Standard_False);
212
213   return Standard_True;
214 }
215