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