| 1 | // Created on: 2008-05-30 |
| 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 | |
| 20 | |
| 21 | #include <Voxel_FastConverter.ixx> |
| 22 | |
| 23 | #include <Bnd_Box.hxx> |
| 24 | #include <BRep_Tool.hxx> |
| 25 | #include <BRepBndLib.hxx> |
| 26 | #include <BRepMesh.hxx> |
| 27 | |
| 28 | #include <TopoDS.hxx> |
| 29 | #include <TopoDS_Face.hxx> |
| 30 | #include <TopExp_Explorer.hxx> |
| 31 | |
| 32 | #include <gp_Lin2d.hxx> |
| 33 | #include <gce_MakePln.hxx> |
| 34 | |
| 35 | #include <ElSLib.hxx> |
| 36 | #include <Poly_Triangulation.hxx> |
| 37 | #include <IntAna2d_AnaIntersection.hxx> |
| 38 | |
| 39 | // Printing the progress in stdout. |
| 40 | //#define CONV_DUMP |
| 41 | |
| 42 | Voxel_FastConverter::Voxel_FastConverter(const TopoDS_Shape& shape, |
| 43 | Voxel_ROctBoolDS& voxels, |
| 44 | const Standard_Real deflection, |
| 45 | const Standard_Integer nbx, |
| 46 | const Standard_Integer nby, |
| 47 | const Standard_Integer nbz, |
| 48 | const Standard_Integer nbthreads, |
| 49 | const Standard_Boolean useExistingTriangulation) |
| 50 | :myShape(shape),myVoxels(&voxels), |
| 51 | myDeflection(deflection), |
| 52 | myNbX(nbx),myNbY(nby),myNbZ(nbz), |
| 53 | myNbThreads(nbthreads),myIsBool(2), |
| 54 | myNbTriangles(0), |
| 55 | myUseExistingTriangulation(useExistingTriangulation) |
| 56 | { |
| 57 | Init(); |
| 58 | } |
| 59 | |
| 60 | Voxel_FastConverter::Voxel_FastConverter(const TopoDS_Shape& shape, |
| 61 | Voxel_BoolDS& voxels, |
| 62 | const Standard_Real deflection, |
| 63 | const Standard_Integer nbx, |
| 64 | const Standard_Integer nby, |
| 65 | const Standard_Integer nbz, |
| 66 | const Standard_Integer nbthreads, |
| 67 | const Standard_Boolean useExistingTriangulation) |
| 68 | :myShape(shape),myVoxels(&voxels), |
| 69 | myDeflection(deflection), |
| 70 | myNbX(nbx),myNbY(nby),myNbZ(nbz), |
| 71 | myNbThreads(nbthreads),myIsBool(1), |
| 72 | myNbTriangles(0), |
| 73 | myUseExistingTriangulation(useExistingTriangulation) |
| 74 | { |
| 75 | Init(); |
| 76 | } |
| 77 | |
| 78 | Voxel_FastConverter::Voxel_FastConverter(const TopoDS_Shape& shape, |
| 79 | Voxel_ColorDS& voxels, |
| 80 | const Standard_Real deflection, |
| 81 | const Standard_Integer nbx, |
| 82 | const Standard_Integer nby, |
| 83 | const Standard_Integer nbz, |
| 84 | const Standard_Integer nbthreads, |
| 85 | const Standard_Boolean useExistingTriangulation) |
| 86 | :myShape(shape),myVoxels(&voxels), |
| 87 | myDeflection(deflection), |
| 88 | myNbX(nbx),myNbY(nby),myNbZ(nbz), |
| 89 | myNbThreads(nbthreads),myIsBool(0), |
| 90 | myNbTriangles(0), |
| 91 | myUseExistingTriangulation(useExistingTriangulation) |
| 92 | { |
| 93 | Init(); |
| 94 | } |
| 95 | |
| 96 | void Voxel_FastConverter::Init() |
| 97 | { |
| 98 | if (myShape.IsNull()) |
| 99 | return; |
| 100 | if (myNbThreads < 1) |
| 101 | return; |
| 102 | |
| 103 | // Check number of splits. |
| 104 | Voxel_DS* voxels = (Voxel_DS*) myVoxels; |
| 105 | if (voxels->GetNbX() != myNbX || voxels->GetNbY() != myNbY || voxels->GetNbZ() != myNbZ) |
| 106 | { |
| 107 | // Compute boundary box of the shape |
| 108 | Bnd_Box box; |
| 109 | BRepBndLib::Add(myShape, box); |
| 110 | |
| 111 | // Define the voxel model by means of the boundary box of shape |
| 112 | Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; |
| 113 | box.Get(xmin, ymin, zmin, xmax, ymax, zmax); |
| 114 | |
| 115 | // Initialize the voxels. |
| 116 | if (myIsBool == 2) |
| 117 | ((Voxel_ROctBoolDS*) voxels)->Init(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin, myNbX, myNbY, myNbZ); |
| 118 | else if (myIsBool == 1) |
| 119 | ((Voxel_BoolDS*) voxels)->Init(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin, myNbX, myNbY, myNbZ); |
| 120 | else if (myIsBool == 0) |
| 121 | ((Voxel_ColorDS*) voxels)->Init(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin, myNbX, myNbY, myNbZ); |
| 122 | } |
| 123 | |
| 124 | // Check presence of triangulation. |
| 125 | TopLoc_Location L; |
| 126 | Standard_Boolean triangulate = Standard_False; |
| 127 | TopExp_Explorer expl(myShape, TopAbs_FACE); |
| 128 | if(myUseExistingTriangulation == Standard_False) |
| 129 | { |
| 130 | for (; expl.More(); expl.Next()) |
| 131 | { |
| 132 | const TopoDS_Face & F = TopoDS::Face(expl.Current()); |
| 133 | Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); |
| 134 | if (T.IsNull() || (T->Deflection() > myDeflection)) |
| 135 | { |
| 136 | triangulate = Standard_True; |
| 137 | break; |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | // Re-create the triangulation. |
| 143 | if (triangulate) |
| 144 | { |
| 145 | BRepMesh::Mesh(myShape, myDeflection); |
| 146 | } |
| 147 | |
| 148 | // Compute the number of triangles. |
| 149 | myNbTriangles = 0; |
| 150 | expl.Init(myShape, TopAbs_FACE); |
| 151 | for (; expl.More(); expl.Next()) |
| 152 | { |
| 153 | const TopoDS_Face & F = TopoDS::Face(expl.Current()); |
| 154 | Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); |
| 155 | if (T.IsNull() == Standard_False) |
| 156 | myNbTriangles += T->NbTriangles(); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | // Destructor |
| 161 | void Voxel_FastConverter::Destroy() |
| 162 | { |
| 163 | |
| 164 | } |
| 165 | |
| 166 | Standard_Boolean Voxel_FastConverter::Convert(Standard_Integer& progress, |
| 167 | const Standard_Integer ithread) |
| 168 | { |
| 169 | if (ithread == 1) |
| 170 | progress = 0; |
| 171 | #ifdef CONV_DUMP |
| 172 | if (ithread == 1) |
| 173 | printf("Progress = %d \r", progress); |
| 174 | #endif |
| 175 | |
| 176 | if (myNbX <= 0 || myNbY <= 0 || myNbZ <= 0) |
| 177 | return Standard_False; |
| 178 | |
| 179 | if(myNbTriangles == 0) |
| 180 | return Standard_False; |
| 181 | |
| 182 | // Half of diagonal of a voxel |
| 183 | Voxel_DS* ds = (Voxel_DS*) myVoxels; |
| 184 | Standard_Real dx = ds->GetXLen() / (Standard_Real) ds->GetNbX(), |
| 185 | dy = ds->GetYLen() / (Standard_Real) ds->GetNbY(), |
| 186 | dz = ds->GetZLen() / (Standard_Real) ds->GetNbZ(); |
| 187 | Standard_Real hdiagonal = sqrt(dx * dx + dy * dy + dz * dz); |
| 188 | hdiagonal /= 2.0; |
| 189 | |
| 190 | // Compute the scope of triangles for current thread |
| 191 | Standard_Integer start_thread_triangle = 1, end_thread_triangle = myNbTriangles, ithread_triangle = 0; |
| 192 | start_thread_triangle = (ithread - 1) * (myNbTriangles / myNbThreads) + 1; |
| 193 | end_thread_triangle = (ithread - 0) * (myNbTriangles / myNbThreads); |
| 194 | |
| 195 | // Convert |
| 196 | TopLoc_Location L; |
| 197 | Standard_Integer iprogress = 0, prev_progress = 0; |
| 198 | Standard_Integer n1, n2, n3; |
| 199 | Standard_Integer ixmin, iymin, izmin, ixmax, iymax, izmax; |
| 200 | Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; |
| 201 | TopExp_Explorer expl(myShape, TopAbs_FACE); |
| 202 | for (; expl.More(); expl.Next()) |
| 203 | { |
| 204 | const TopoDS_Face & F = TopoDS::Face(expl.Current()); |
| 205 | Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); |
| 206 | if (T.IsNull()) |
| 207 | continue; |
| 208 | |
| 209 | gp_Trsf trsf; |
| 210 | Standard_Boolean transform = !L.IsIdentity(); |
| 211 | if (transform) |
| 212 | trsf = L.Transformation(); |
| 213 | |
| 214 | const TColgp_Array1OfPnt& nodes = T->Nodes(); |
| 215 | const Poly_Array1OfTriangle& triangles = T->Triangles(); |
| 216 | Standard_Integer itriangle = triangles.Lower(), nb_triangles = triangles.Upper(); |
| 217 | for (; itriangle <= nb_triangles; itriangle++) |
| 218 | { |
| 219 | ithread_triangle++; |
| 220 | if (ithread_triangle < start_thread_triangle ) |
| 221 | continue; |
| 222 | if (ithread_triangle > end_thread_triangle) |
| 223 | { |
| 224 | if (ithread == 1) |
| 225 | progress = 100; |
| 226 | #ifdef CONV_DUMP |
| 227 | if (ithread == 1) |
| 228 | printf("Progress = %d \r", progress); |
| 229 | #endif |
| 230 | return Standard_True; |
| 231 | } |
| 232 | |
| 233 | const Poly_Triangle& t = triangles.Value(itriangle); |
| 234 | t.Get(n1, n2, n3); |
| 235 | gp_Pnt p1 = nodes.Value(n1); |
| 236 | gp_Pnt p2 = nodes.Value(n2); |
| 237 | gp_Pnt p3 = nodes.Value(n3); |
| 238 | if (transform) |
| 239 | { |
| 240 | p1.Transform(trsf); |
| 241 | p2.Transform(trsf); |
| 242 | p3.Transform(trsf); |
| 243 | } |
| 244 | |
| 245 | // Get boundary box of the triangle |
| 246 | GetBndBox(p1, p2, p3, xmin, ymin, zmin, xmax, ymax, zmax); |
| 247 | |
| 248 | // Find the range of voxels inside the boudary box of the triangle. |
| 249 | if (!ds->GetVoxel(xmin, ymin, zmin, ixmin, iymin, izmin)) |
| 250 | continue; |
| 251 | if (!ds->GetVoxel(xmax, ymax, zmax, ixmax, iymax, izmax)) |
| 252 | continue; |
| 253 | |
| 254 | // Refuse voxels for whom distance from their center to plane of triangle is greater than half of diagonal. |
| 255 | // Make a line from center of each voxel to the center of triangle and |
| 256 | // compute intersection of the line with sides of triangle. |
| 257 | // Refuse the voxel in case of intersection. |
| 258 | gce_MakePln mkPlane(p1, p2, p3); |
| 259 | if (!mkPlane.IsDone()) |
| 260 | continue; |
| 261 | gp_Pln plane = mkPlane.Value(); |
| 262 | ComputeVoxelsNearTriangle(plane, p1, p2, p3, hdiagonal, ixmin, iymin, izmin, ixmax, iymax, izmax); |
| 263 | |
| 264 | // Progress |
| 265 | if (ithread == 1) |
| 266 | { |
| 267 | iprogress++; |
| 268 | progress = (Standard_Integer) ( (Standard_Real) iprogress / (Standard_Real) myNbTriangles * 100.0 ); |
| 269 | } |
| 270 | #ifdef CONV_DUMP |
| 271 | if (ithread == 1 && prev_progress != progress) |
| 272 | { |
| 273 | printf("Progress = %d \r", progress); |
| 274 | prev_progress = progress; |
| 275 | } |
| 276 | #endif |
| 277 | |
| 278 | } // iteration of triangles |
| 279 | } // iteration of faces |
| 280 | |
| 281 | if (ithread == 1) |
| 282 | progress = 100; |
| 283 | #ifdef CONV_DUMP |
| 284 | if (ithread == 1) |
| 285 | printf("Progress = %d \r", progress); |
| 286 | #endif |
| 287 | return Standard_True; |
| 288 | } |
| 289 | |
| 290 | Standard_Boolean Voxel_FastConverter::FillInVolume(const Standard_Byte inner, |
| 291 | const Standard_Integer ithread) |
| 292 | { |
| 293 | Voxel_DS* ds = (Voxel_DS*) myVoxels; |
| 294 | Standard_Integer ix, iy, iz, nbx = ds->GetNbX(), nby = ds->GetNbY(), nbz = ds->GetNbZ(); |
| 295 | Standard_Boolean prev_surface, surface, volume; |
| 296 | |
| 297 | if (inner) |
| 298 | { |
| 299 | // Fill-in internal voxels by the value "inner" |
| 300 | for (ix = 0; ix < nbx; ix++) |
| 301 | { |
| 302 | for (iy = 0; iy < nby; iy++) |
| 303 | { |
| 304 | // Check existence of volume. |
| 305 | volume = Standard_False; |
| 306 | surface = Standard_False; |
| 307 | prev_surface = Standard_False; |
| 308 | for (iz = 0; iz < nbz; iz++) |
| 309 | { |
| 310 | surface = (myIsBool == 1) ? |
| 311 | ((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz) == Standard_True : |
| 312 | ((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz) > 0; |
| 313 | if (prev_surface && !surface) |
| 314 | { |
| 315 | volume = !volume; |
| 316 | } |
| 317 | prev_surface = surface; |
| 318 | } |
| 319 | if (volume) |
| 320 | continue; |
| 321 | |
| 322 | // Fill-in the volume. |
| 323 | volume = Standard_False; |
| 324 | surface = Standard_False; |
| 325 | prev_surface = Standard_False; |
| 326 | for (iz = 0; iz < nbz; iz++) |
| 327 | { |
| 328 | surface = (myIsBool == 1) ? |
| 329 | ((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz) == Standard_True : |
| 330 | ((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz) > 0; |
| 331 | if (prev_surface && !surface) |
| 332 | { |
| 333 | volume = !volume; |
| 334 | } |
| 335 | if (volume && !surface) |
| 336 | { |
| 337 | (myIsBool == 1) ? ((Voxel_BoolDS*)myVoxels)->Set(ix, iy, iz, inner) : |
| 338 | ((Voxel_ColorDS*)myVoxels)->Set(ix, iy, iz, inner); |
| 339 | } |
| 340 | prev_surface = surface; |
| 341 | } |
| 342 | } |
| 343 | } |
| 344 | } |
| 345 | else |
| 346 | { |
| 347 | // Set value of interbal voxels to 0 ("inner" = 0) |
| 348 | Standard_Boolean next_surface; |
| 349 | for (ix = 0; ix < nbx; ix++) |
| 350 | { |
| 351 | for (iy = 0; iy < nby; iy++) |
| 352 | { |
| 353 | volume = Standard_False; |
| 354 | surface = Standard_False; |
| 355 | prev_surface = Standard_False; |
| 356 | next_surface = Standard_False; |
| 357 | for (iz = 0; iz < nbz; iz++) |
| 358 | { |
| 359 | surface = (myIsBool == 1) ? |
| 360 | ((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz) == Standard_True : |
| 361 | ((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz) > 0; |
| 362 | if (prev_surface != surface) |
| 363 | { |
| 364 | volume = !volume; |
| 365 | } |
| 366 | if (volume && iz + 1 < nbz) |
| 367 | { |
| 368 | next_surface = (myIsBool == 1) ? |
| 369 | ((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz + 1) == Standard_True : |
| 370 | ((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz + 1) > 0; |
| 371 | } |
| 372 | if (volume && prev_surface == surface && next_surface) |
| 373 | { |
| 374 | (myIsBool == 1) ? ((Voxel_BoolDS*)myVoxels)->Set(ix, iy, iz, inner) : |
| 375 | ((Voxel_ColorDS*)myVoxels)->Set(ix, iy, iz, inner); |
| 376 | } |
| 377 | prev_surface = surface; |
| 378 | } |
| 379 | } |
| 380 | } |
| 381 | } |
| 382 | |
| 383 | return Standard_True; |
| 384 | } |
| 385 | |
| 386 | void Voxel_FastConverter::GetBndBox(const gp_Pnt& p1, |
| 387 | const gp_Pnt& p2, |
| 388 | const gp_Pnt& p3, |
| 389 | Standard_Real& xmin, |
| 390 | Standard_Real& ymin, |
| 391 | Standard_Real& zmin, |
| 392 | Standard_Real& xmax, |
| 393 | Standard_Real& ymax, |
| 394 | Standard_Real& zmax) const |
| 395 | { |
| 396 | // P1: |
| 397 | xmin = p1.X(); |
| 398 | ymin = p1.Y(); |
| 399 | zmin = p1.Z(); |
| 400 | xmax = p1.X(); |
| 401 | ymax = p1.Y(); |
| 402 | zmax = p1.Z(); |
| 403 | // P2: |
| 404 | if (xmin > p2.X()) |
| 405 | xmin = p2.X(); |
| 406 | if (ymin > p2.Y()) |
| 407 | ymin = p2.Y(); |
| 408 | if (zmin > p2.Z()) |
| 409 | zmin = p2.Z(); |
| 410 | if (xmax < p2.X()) |
| 411 | xmax = p2.X(); |
| 412 | if (ymax < p2.Y()) |
| 413 | ymax = p2.Y(); |
| 414 | if (zmax < p2.Z()) |
| 415 | zmax = p2.Z(); |
| 416 | // P3: |
| 417 | if (xmin > p3.X()) |
| 418 | xmin = p3.X(); |
| 419 | if (ymin > p3.Y()) |
| 420 | ymin = p3.Y(); |
| 421 | if (zmin > p3.Z()) |
| 422 | zmin = p3.Z(); |
| 423 | if (xmax < p3.X()) |
| 424 | xmax = p3.X(); |
| 425 | if (ymax < p3.Y()) |
| 426 | ymax = p3.Y(); |
| 427 | if (zmax < p3.Z()) |
| 428 | zmax = p3.Z(); |
| 429 | } |
| 430 | |
| 431 | // This method is copied from Voxel_ShapeIntersector.cxx |
| 432 | static Standard_Boolean mayIntersect(const gp_Pnt2d& p11, const gp_Pnt2d& p12, |
| 433 | const gp_Pnt2d& p21, const gp_Pnt2d& p22) |
| 434 | { |
| 435 | if (p11.X() > p21.X() && p11.X() > p22.X() && p12.X() > p21.X() && p12.X() > p22.X()) |
| 436 | return Standard_False; |
| 437 | if (p11.X() < p21.X() && p11.X() < p22.X() && p12.X() < p21.X() && p12.X() < p22.X()) |
| 438 | return Standard_False; |
| 439 | if (p11.Y() > p21.Y() && p11.Y() > p22.Y() && p12.Y() > p21.Y() && p12.Y() > p22.Y()) |
| 440 | return Standard_False; |
| 441 | if (p11.Y() < p21.Y() && p11.Y() < p22.Y() && p12.Y() < p21.Y() && p12.Y() < p22.Y()) |
| 442 | return Standard_False; |
| 443 | return Standard_True; |
| 444 | } |
| 445 | |
| 446 | void Voxel_FastConverter::ComputeVoxelsNearTriangle(const gp_Pln& plane, |
| 447 | const gp_Pnt& p1, |
| 448 | const gp_Pnt& p2, |
| 449 | const gp_Pnt& p3, |
| 450 | const Standard_Real hdiagonal, |
| 451 | const Standard_Integer ixmin, |
| 452 | const Standard_Integer iymin, |
| 453 | const Standard_Integer izmin, |
| 454 | const Standard_Integer ixmax, |
| 455 | const Standard_Integer iymax, |
| 456 | const Standard_Integer izmax) const |
| 457 | { |
| 458 | gp_Pnt pc; |
| 459 | Standard_Real xc, yc, zc, uc, vc, u1, v1, u2, v2, u3, v3; |
| 460 | Standard_Integer ix, iy, iz; |
| 461 | IntAna2d_AnaIntersection intersector2d; |
| 462 | |
| 463 | // Project points of triangle onto the plane |
| 464 | ElSLib::Parameters(plane, p1, u1, v1); |
| 465 | ElSLib::Parameters(plane, p2, u2, v2); |
| 466 | ElSLib::Parameters(plane, p3, u3, v3); |
| 467 | |
| 468 | // Make lines of triangle |
| 469 | gp_Pnt2d p2d1(u1, v1), p2d2(u2, v2), p2d3(u3, v3), p2dt((u1+u2+u3)/3.0,(v1+v2+v3)/3.0), p2dc; |
| 470 | gp_Vec2d v2d12(p2d1, p2d2), v2d23(p2d2, p2d3), v2d31(p2d3, p2d1); |
| 471 | gp_Lin2d L1(p2d1, v2d12), L2(p2d2, v2d23), L3(p2d3, v2d31), Lv; |
| 472 | Standard_Real d1 = p2d1.Distance(p2d2) - Precision::Confusion(), |
| 473 | d2 = p2d2.Distance(p2d3) - Precision::Confusion(), |
| 474 | d3 = p2d3.Distance(p2d1) - Precision::Confusion(), dv; |
| 475 | |
| 476 | Voxel_DS* ds = (Voxel_DS*) myVoxels; |
| 477 | for (ix = ixmin; ix <= ixmax; ix++) |
| 478 | { |
| 479 | for (iy = iymin; iy <= iymax; iy++) |
| 480 | { |
| 481 | for (iz = izmin; iz <= izmax; iz++) |
| 482 | { |
| 483 | ds->GetCenter(ix, iy, iz, xc, yc, zc); |
| 484 | pc.SetCoord(xc, yc, zc); |
| 485 | if (plane.Distance(pc) < hdiagonal) |
| 486 | { |
| 487 | ElSLib::Parameters(plane, pc, uc, vc); |
| 488 | p2dc.SetCoord(uc, vc); |
| 489 | |
| 490 | gp_Vec2d v2dct(p2dc, p2dt); |
| 491 | dv = v2dct.Magnitude() - Precision::Confusion(); |
| 492 | Lv.SetLocation(p2dc); |
| 493 | Lv.SetDirection(v2dct); |
| 494 | |
| 495 | // Side 1: |
| 496 | if (mayIntersect(p2d1, p2d2, p2dc, p2dt)) |
| 497 | { |
| 498 | intersector2d.Perform(Lv, L1); |
| 499 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 500 | { |
| 501 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 502 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 503 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 504 | if (param1 > Precision::Confusion() && param1 < dv && |
| 505 | param2 > Precision::Confusion() && param2 < d1) |
| 506 | { |
| 507 | continue; |
| 508 | } |
| 509 | } |
| 510 | } |
| 511 | |
| 512 | // Side 2: |
| 513 | if (mayIntersect(p2d2, p2d3, p2dc, p2dt)) |
| 514 | { |
| 515 | intersector2d.Perform(Lv, L2); |
| 516 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 517 | { |
| 518 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 519 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 520 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 521 | if (param1 > Precision::Confusion() && param1 < dv && |
| 522 | param2 > Precision::Confusion() && param2 < d2) |
| 523 | { |
| 524 | continue; |
| 525 | } |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | // Side 3: |
| 530 | if (mayIntersect(p2d3, p2d1, p2dc, p2dt)) |
| 531 | { |
| 532 | intersector2d.Perform(Lv, L3); |
| 533 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 534 | { |
| 535 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 536 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 537 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 538 | if (param1 > Precision::Confusion() && param1 < dv && |
| 539 | param2 > Precision::Confusion() && param2 < d3) |
| 540 | { |
| 541 | continue; |
| 542 | } |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | // Set positive value to this voxel: |
| 547 | switch (myIsBool) |
| 548 | { |
| 549 | case 0: |
| 550 | ((Voxel_ColorDS*) myVoxels)->Set(ix, iy, iz, 15); |
| 551 | break; |
| 552 | case 1: |
| 553 | ((Voxel_BoolDS*) myVoxels)->Set(ix, iy, iz, Standard_True); |
| 554 | break; |
| 555 | case 2: |
| 556 | { |
| 557 | //((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, Standard_True); |
| 558 | |
| 559 | // Check intersection between the triangle & sub-voxels of the voxel. |
| 560 | Standard_Real hdiagonal2 = hdiagonal / 2.0, hdiagonal4 = hdiagonal / 4.0; |
| 561 | for (Standard_Integer i = 0; i < 8; i++) |
| 562 | { |
| 563 | ((Voxel_ROctBoolDS*) myVoxels)->GetCenter(ix, iy, iz, i, xc, yc, zc); |
| 564 | pc.SetCoord(xc, yc, zc); |
| 565 | if (plane.Distance(pc) < hdiagonal2) |
| 566 | { |
| 567 | ElSLib::Parameters(plane, pc, uc, vc); |
| 568 | p2dc.SetCoord(uc, vc); |
| 569 | |
| 570 | gp_Vec2d v2dct(p2dc, p2dt); |
| 571 | dv = v2dct.Magnitude() - Precision::Confusion(); |
| 572 | Lv.SetLocation(p2dc); |
| 573 | Lv.SetDirection(v2dct); |
| 574 | |
| 575 | // Side 1: |
| 576 | if (mayIntersect(p2d1, p2d2, p2dc, p2dt)) |
| 577 | { |
| 578 | intersector2d.Perform(Lv, L1); |
| 579 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 580 | { |
| 581 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 582 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 583 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 584 | if (param1 > Precision::Confusion() && param1 < dv && |
| 585 | param2 > Precision::Confusion() && param2 < d1) |
| 586 | { |
| 587 | continue; |
| 588 | } |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | // Side 2: |
| 593 | if (mayIntersect(p2d2, p2d3, p2dc, p2dt)) |
| 594 | { |
| 595 | intersector2d.Perform(Lv, L2); |
| 596 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 597 | { |
| 598 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 599 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 600 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 601 | if (param1 > Precision::Confusion() && param1 < dv && |
| 602 | param2 > Precision::Confusion() && param2 < d2) |
| 603 | { |
| 604 | continue; |
| 605 | } |
| 606 | } |
| 607 | } |
| 608 | |
| 609 | // Side 3: |
| 610 | if (mayIntersect(p2d3, p2d1, p2dc, p2dt)) |
| 611 | { |
| 612 | intersector2d.Perform(Lv, L3); |
| 613 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 614 | { |
| 615 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 616 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 617 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 618 | if (param1 > Precision::Confusion() && param1 < dv && |
| 619 | param2 > Precision::Confusion() && param2 < d3) |
| 620 | { |
| 621 | continue; |
| 622 | } |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | //((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, i, Standard_True); |
| 627 | |
| 628 | // Check intersection between the triangle & sub-voxels of the sub-voxel. |
| 629 | for (Standard_Integer j = 0; j < 8; j++) |
| 630 | { |
| 631 | ((Voxel_ROctBoolDS*) myVoxels)->GetCenter(ix, iy, iz, i, j, xc, yc, zc); |
| 632 | pc.SetCoord(xc, yc, zc); |
| 633 | if (plane.Distance(pc) < hdiagonal4) |
| 634 | { |
| 635 | ElSLib::Parameters(plane, pc, uc, vc); |
| 636 | p2dc.SetCoord(uc, vc); |
| 637 | |
| 638 | gp_Vec2d v2dct(p2dc, p2dt); |
| 639 | dv = v2dct.Magnitude() - Precision::Confusion(); |
| 640 | Lv.SetLocation(p2dc); |
| 641 | Lv.SetDirection(v2dct); |
| 642 | |
| 643 | // Side 1: |
| 644 | if (mayIntersect(p2d1, p2d2, p2dc, p2dt)) |
| 645 | { |
| 646 | intersector2d.Perform(Lv, L1); |
| 647 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 648 | { |
| 649 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 650 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 651 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 652 | if (param1 > Precision::Confusion() && param1 < dv && |
| 653 | param2 > Precision::Confusion() && param2 < d1) |
| 654 | { |
| 655 | continue; |
| 656 | } |
| 657 | } |
| 658 | } |
| 659 | |
| 660 | // Side 2: |
| 661 | if (mayIntersect(p2d2, p2d3, p2dc, p2dt)) |
| 662 | { |
| 663 | intersector2d.Perform(Lv, L2); |
| 664 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 665 | { |
| 666 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 667 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 668 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 669 | if (param1 > Precision::Confusion() && param1 < dv && |
| 670 | param2 > Precision::Confusion() && param2 < d2) |
| 671 | { |
| 672 | continue; |
| 673 | } |
| 674 | } |
| 675 | } |
| 676 | |
| 677 | // Side 3: |
| 678 | if (mayIntersect(p2d3, p2d1, p2dc, p2dt)) |
| 679 | { |
| 680 | intersector2d.Perform(Lv, L3); |
| 681 | if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints()) |
| 682 | { |
| 683 | const IntAna2d_IntPoint& i2d = intersector2d.Point(1); |
| 684 | Standard_Real param1 = i2d.ParamOnFirst(); |
| 685 | Standard_Real param2 = i2d.ParamOnSecond(); |
| 686 | if (param1 > Precision::Confusion() && param1 < dv && |
| 687 | param2 > Precision::Confusion() && param2 < d3) |
| 688 | { |
| 689 | continue; |
| 690 | } |
| 691 | } |
| 692 | } |
| 693 | |
| 694 | ((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, i, j, Standard_True); |
| 695 | } |
| 696 | } // End of "Check level 2". |
| 697 | |
| 698 | } |
| 699 | } // End of "Check level 1". |
| 700 | |
| 701 | break; |
| 702 | } |
| 703 | } |
| 704 | } |
| 705 | } |
| 706 | } |
| 707 | } |
| 708 | } |