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 | |
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 | } |