bb974b3a3dccf609605e5e986f86df5ee14079e0
[occt.git] / src / Voxel / Voxel_CollisionDetection.cxx
1 // Created on: 2008-07-16
2 // Created by: Vladislav ROMASHKO
3 // Copyright (c) 2008-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 <Voxel_CollisionDetection.ixx>
17 #include <Voxel_FastConverter.hxx>
18
19 #include <Precision.hxx>
20 #include <BRepBndLib.hxx>
21 #include <TopTools_ListIteratorOfListOfShape.hxx>
22
23
24
25 Voxel_CollisionDetection::Voxel_CollisionDetection()
26 :myDeflection(0.1),
27  myNbX(100),
28  myNbY(100),
29  myNbZ(100),
30  myUsageOfVolume(Standard_False),
31  myKeepCollisions(Standard_False),
32  myXLen(-1.0),
33  myYLen(-1.0),
34  myZLen(-1.0),
35  myVoxels(0),
36  myHasCollisions(Standard_False)
37 {
38
39 }
40
41 Voxel_CollisionDetection::Voxel_CollisionDetection(const Standard_Real deflection,
42                                                    const Standard_Integer nbx,
43                                                    const Standard_Integer nby,
44                                                    const Standard_Integer nbz)
45 :myDeflection(deflection),
46  myNbX(nbx),
47  myNbY(nby),
48  myNbZ(nbz),
49  myUsageOfVolume(Standard_False),
50  myKeepCollisions(Standard_False),
51  myXLen(-1.0),
52  myYLen(-1.0),
53  myZLen(-1.0),
54  myVoxels(0),
55  myHasCollisions(Standard_False)
56 {
57
58 }
59
60 // Destructor
61 void Voxel_CollisionDetection::Destroy()
62 {
63   Clear();
64 }
65
66 Standard_Integer Voxel_CollisionDetection::AddShape(const TopoDS_Shape& shape)
67 {
68   Clear();
69   myShapes.Append(shape);
70   return myShapes.Extent();
71 }
72
73 Standard_Boolean Voxel_CollisionDetection::ReplaceShape(const Standard_Integer ishape,
74                                                         const TopoDS_Shape& shape)
75 {
76   if (ishape == 1)
77   {
78     myShapes.RemoveFirst();
79     myShapes.Prepend(shape);
80     return Standard_True;
81   }
82
83   Standard_Integer i = 1;
84   Standard_Boolean is_replaced = Standard_False;
85   TopTools_ListIteratorOfListOfShape itr(myShapes);
86   for (; itr.More(); itr.Next(), i++)
87   {
88     if (i == ishape)
89     {
90       myShapes.Remove(itr);
91       myShapes.InsertBefore(shape, itr);
92       is_replaced = Standard_True;
93       break;
94     }
95   }
96   return is_replaced;
97 }
98
99 void Voxel_CollisionDetection::SetDeflection(const Standard_Real deflection)
100 {
101   myDeflection = deflection;
102 }
103
104 void Voxel_CollisionDetection::SetNbVoxels(const Standard_Integer nbx,
105                                            const Standard_Integer nby,
106                                            const Standard_Integer nbz)
107 {
108   myNbX = nbx;
109   myNbY = nby;
110   myNbZ = nbz;
111 }
112
113 void Voxel_CollisionDetection::SetBoundaryBox(const Bnd_Box& box)
114 {
115   if (box.IsVoid())
116     return;
117
118   Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
119   box.Get(xmin, ymin, zmin, xmax, ymax, zmax);
120   
121   myX = xmin;
122   myY = ymin;
123   myZ = zmin;
124
125   myXLen = xmax - xmin;
126   myYLen = ymax - ymin;
127   myZLen = zmax - zmin;
128 }
129
130 void Voxel_CollisionDetection::SetUsageOfVolume(const Standard_Boolean usage)
131 {
132   myUsageOfVolume = usage;
133 }
134
135 void Voxel_CollisionDetection::KeepCollisions(const Standard_Boolean keep)
136 {
137   myKeepCollisions = keep;
138 }
139
140 Standard_Boolean Voxel_CollisionDetection::Voxelize(const Standard_Integer ishape)
141 {
142   // Check the arguments
143   if (myNbX <= 0 || myNbY <= 0 || myNbZ <= 0)
144     return Standard_False;
145
146   // Calculate the boundary box of the shapes to define the size of voxels.
147   // This code is called only if the user didn't define the boundary box himself.
148   if (myXLen < 0.0)
149   {
150     Bnd_Box B, b;
151     TopTools_ListIteratorOfListOfShape itrs(myShapes);
152     for (; itrs.More(); itrs.Next())
153     {
154       TopoDS_Shape S = itrs.Value();
155       BRepBndLib::Add(S, b);
156       B.Add(b);
157     }
158     SetBoundaryBox(B);
159   }
160
161   // Voxelize the shapes
162   Standard_Integer progress, ithread = 1, i = 1;
163   TopTools_ListIteratorOfListOfShape itrs(myShapes);
164   for (; itrs.More(); itrs.Next(), i++)
165   {
166     if (ishape != -1 && i != ishape)
167       continue;
168
169     if (!myVoxels)
170       myVoxels = (Standard_Address) new Voxel_BoolDS[myShapes.Extent()];
171     Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[i - 1];
172     if (!CheckVoxels(voxels))
173     {
174       voxels.Init(myX, myY, myZ, myXLen, myYLen, myZLen, myNbX, myNbY, myNbZ);
175     }
176     else
177     {
178       voxels.SetZero();
179     }
180
181     TopoDS_Shape S = itrs.Value();
182     Voxel_FastConverter voxelizer(S, voxels, myDeflection, myNbX, myNbY, myNbZ, 1 /*number of threads */);
183     if (!voxelizer.Convert(progress, ithread))
184       return Standard_False;
185     if (myUsageOfVolume && !voxelizer.FillInVolume(1, ithread))
186       return Standard_False;
187   }
188
189   return Standard_True;
190 }
191
192 Standard_Boolean Voxel_CollisionDetection::Compute()
193 {
194   myHasCollisions = Standard_False;
195
196   // Check voxels of shapes
197   if (!myVoxels)
198     return Standard_False;
199   Standard_Integer ishape = 0, nb_shapes = myShapes.Extent();
200   for (; ishape < nb_shapes; ishape++)
201   {
202     Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[ishape];
203     if (!CheckVoxels(voxels))
204     {
205       return Standard_False;
206     }
207   }
208
209   // Check the resulting voxels
210   Standard_Boolean created = Standard_False;
211   if (!CheckVoxels(myCollisions))
212   {
213     // Create 0-voxels for the result, if it is needed.
214     created = Standard_True;
215     myCollisions.Init(myX, myY, myZ, myXLen, myYLen, myZLen, myNbX, myNbY, myNbZ);
216   }
217
218   // Nullify the voxels of the result (it corresponds to the state of no collisions).
219   if (!myKeepCollisions && !created)
220   {
221     myCollisions.SetZero();
222   }
223   
224   // Check collisions
225   if (nb_shapes)
226   {
227     Standard_Integer ix, iy, iz;
228     Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[0]; // 1st shape
229     for (ix = 0; ix < myNbX; ix++)
230     {
231       for (iy = 0; iy < myNbY; iy++)
232       {
233         for (iz = 0; iz < myNbZ; iz++)
234         {
235           if (voxels.Get(ix, iy, iz))
236           {
237             for (ishape = 1; ishape < nb_shapes; ishape++) // start with second shape
238             {
239               Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[ishape];
240               if (voxels.Get(ix, iy, iz))
241               {
242                 myCollisions.Set(ix, iy, iz, Standard_True);
243                 if (!myHasCollisions)
244                 {
245                   myHasCollisions = Standard_True;
246                 }
247                 break;
248               }
249             }
250           }
251         }
252       }
253     }
254   }
255
256
257   return Standard_True;
258 }
259
260 Standard_Boolean Voxel_CollisionDetection::HasCollisions() const
261 {
262   return myHasCollisions;
263 }
264
265 const Voxel_BoolDS& Voxel_CollisionDetection::GetCollisions() const
266 {
267   return myCollisions;
268 }
269
270 void Voxel_CollisionDetection::Clear()
271 {
272   if (myVoxels)
273   {
274     delete[] ((Voxel_BoolDS*)myVoxels);
275     myVoxels = 0;
276   }
277 }
278
279 Standard_Boolean Voxel_CollisionDetection::CheckVoxels(const Voxel_BoolDS& voxels) const
280 {
281   if (fabs(voxels.GetX() - myX) > Precision::Confusion() ||
282       fabs(voxels.GetY() - myY) > Precision::Confusion() ||
283       fabs(voxels.GetZ() - myZ) > Precision::Confusion() ||
284       fabs(voxels.GetXLen() - myXLen) > Precision::Confusion() ||
285       fabs(voxels.GetYLen() - myYLen) > Precision::Confusion() ||
286       fabs(voxels.GetZLen() - myZLen) > Precision::Confusion() ||
287       voxels.GetNbX() != myNbX ||
288       voxels.GetNbY() != myNbY ||
289       voxels.GetNbZ() != myNbZ)
290   {
291     return Standard_False;
292   }
293   return Standard_True;
294 }