0025361: Sample "Voxel" crashes during "Demo - Collisions" demonstration
[occt.git] / src / Voxel / Voxel_CollisionDetection.cxx
CommitLineData
b311480e 1// Created on: 2008-07-16
2// Created by: Vladislav ROMASHKO
973c2be1 3// Copyright (c) 2008-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 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
25Voxel_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
41Voxel_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
61void Voxel_CollisionDetection::Destroy()
62{
63 Clear();
64}
65
66Standard_Integer Voxel_CollisionDetection::AddShape(const TopoDS_Shape& shape)
67{
68 Clear();
69 myShapes.Append(shape);
70 return myShapes.Extent();
71}
72
73Standard_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
99void Voxel_CollisionDetection::SetDeflection(const Standard_Real deflection)
100{
101 myDeflection = deflection;
102}
103
104void 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
113void 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
130void Voxel_CollisionDetection::SetUsageOfVolume(const Standard_Boolean usage)
131{
132 myUsageOfVolume = usage;
133}
134
135void Voxel_CollisionDetection::KeepCollisions(const Standard_Boolean keep)
136{
137 myKeepCollisions = keep;
138}
139
140Standard_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
192Standard_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
260Standard_Boolean Voxel_CollisionDetection::HasCollisions() const
261{
262 return myHasCollisions;
263}
264
265const Voxel_BoolDS& Voxel_CollisionDetection::GetCollisions() const
266{
267 return myCollisions;
268}
269
270void Voxel_CollisionDetection::Clear()
271{
272 if (myVoxels)
273 {
7a13ab2d 274 delete[] ((Voxel_BoolDS*)myVoxels);
7fd59977 275 myVoxels = 0;
276 }
277}
278
279Standard_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}