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