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