1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

Integration of OCCT 6.5.0 from SVN

This commit is contained in:
bugmaster
2011-03-16 07:30:28 +00:00
committed by bugmaster
parent 4903637061
commit 7fd59977df
16375 changed files with 3882564 additions and 0 deletions

2
src/Voxel/FILES Executable file
View File

@@ -0,0 +1,2 @@
Voxel_VisData.h
Voxel_TypeDef.hxx

96
src/Voxel/Voxel.cdl Executable file
View File

@@ -0,0 +1,96 @@
-- File: Voxel.cdl
-- Created: Sun May 04 09:39:16 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
package Voxel
---Purpose: Data structuire and visualization engine for voxel modeling.
uses
IntCurvesFace,
TCollection,
SelectMgr,
Quantity,
TopTools,
TColStd,
TColgp,
TopoDS,
PrsMgr,
Prs3d,
Poly,
V3d,
AIS,
Bnd,
gp
is
enumeration VoxelDisplayMode is
VDM_POINTS,
VDM_NEARESTPOINTS,
VDM_BOXES,
VDM_NEARESTBOXES
end VoxelDisplayMode;
enumeration VoxelFileFormat is
VFF_ASCII,
VFF_BINARY
end VoxelFileFormat;
-- A base class for all voxels data structures.
class DS;
-- A voxel model keeping a boolean flag for each voxel (1 || 0).
class BoolDS;
-- A voxel model keeping a boolean flag for each voxel
-- with an opportunity to split a voxel into 8 sub-voxels.
class OctBoolDS;
-- A voxel model keeping a boolean flag for each voxel
-- with an opportunity to split a voxel into 8 sub-voxels
-- recursively.
class ROctBoolDS;
private class SplitData;
-- A voxel model keeping 4 bits of information for each voxel (16 colors).
class ColorDS;
-- A voxel model keeping 4 bytes of information for each voxel (a floating-point value).
class FloatDS;
-- A converter of a shape to voxel model.
--class Converter;
-- An internal class searching intersections between a line and a shape.
--class ShapeIntersector;
-- An alternative method of conversion of a shape into voxels.
-- It is faster, but less precise.
class FastConverter;
--- Converts voxels into triangulation
--class Triangulator;
-- Interactive object of voxels
class Prs;
-- Boolean operations for voxels.
class BooleanOperation;
-- Collision detection
class CollisionDetection;
-- Selection of voxels in the viewer 3d
class Selector;
-- Ascii writer/reader of voxels
class Writer;
class Reader;
end Voxel;

74
src/Voxel/Voxel_BoolDS.cdl Executable file
View File

@@ -0,0 +1,74 @@
-- File: Voxel_BoolDS.cdl
-- Created: Sun May 04 09:50:26 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class BoolDS from Voxel inherits DS from Voxel
---Purpose: A 3D voxel model keeping a bool flag (1 or 0)
-- value for each voxel.
is
Create
---Purpose: An empty constructor.
returns BoolDS from Voxel;
Create(x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: A constructor initializing the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
returns BoolDS from Voxel;
Init(me : in out;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: Initialization of the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
is redefined virtual;
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor of the voxel model.
SetZero(me : in out);
---Purpose: The method sets all values equal to 0 (false) and
-- releases the memory.
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
data : Boolean from Standard = Standard_True);
---Purpose: Defines a value for voxel with co-ordinates (ix, iy, iz).
-- Initial state of the model is so that all voxels have value 0 (false),
-- and this data doesn't occupy memory.
-- Memory for data is allocating during setting non-zero values (true).
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns the value of voxel with co-ordinates (ix, iy, iz).
returns Boolean from Standard;
end BoolDS;

131
src/Voxel/Voxel_BoolDS.cxx Executable file
View File

@@ -0,0 +1,131 @@
// File: Voxel_BoolDS.cxx
// Created: Mon Jun 21 14:35:37 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_BoolDS.ixx>
#include <stdlib.h>
static Standard_Byte gbits[8] = {1, 2, 4, 8, 16, 32, 64, 128};
static Standard_Byte gnbits[8] = {255-1, 255-2, 255-4, 255-8, 255-16, 255-32, 255-64, 255-128};
// Empty constructor
Voxel_BoolDS::Voxel_BoolDS():Voxel_DS()
{
}
// Constructor with intialization.
Voxel_BoolDS::Voxel_BoolDS(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
:Voxel_DS()
{
Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
}
// Initialization.
void Voxel_BoolDS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
Destroy();
Voxel_DS::Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
if (!myNbX || !myNbY || !myNbZ)
return;
Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 8.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
myData = (Standard_Address) calloc(nb_slices, sizeof(Standard_Byte*));
}
// Destructor
void Voxel_BoolDS::Destroy()
{
if (myData)
{
SetZero();
free((Standard_Byte**)myData);
myData = 0;
}
}
void Voxel_BoolDS::SetZero()
{
if (myData)
{
Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 8.0));
Standard_Integer ix = 0, nb_slices = RealToInt(ceil(nb_bytes / 8.0));
for (; ix < nb_slices; ix++)
{
if (((Standard_Byte**)myData)[ix])
{
free(((Standard_Byte**)myData)[ix]);
((Standard_Byte**)myData)[ix] = 0;
}
}
}
}
// Access to the boolean information attached to a particular voxel:
// Info: (ix >= 0 && ix < theNb_x), etc.
void Voxel_BoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Boolean data)
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 6;
if (!data && !((Standard_Byte**)myData)[islice])
return; // don't allocate a slice of data for setting a 0 value
// Allocate the slice if it is not done yet.
if (!((Standard_Byte**)myData)[islice])
{
((Standard_Byte**)myData)[islice] = (Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte));
}
// Index within 8 bytes of the slice.
Standard_Integer ibit_in_current_slice = ibit - (islice << 6);
Standard_Integer ibyte = ibit_in_current_slice >> 3;
// Value (byte)
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte];
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit_in_current_slice - (ibyte << 3);
// Set data
if (data != ((value & gbits[shift]) ? Standard_True : Standard_False))
{
if (data)
value |= gbits[shift];
else
value &= gnbits[shift];
((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte] = value;
}
}
Standard_Boolean Voxel_BoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 6;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Standard_Byte**)myData)[islice])
return Standard_False;
// Index within 8 bytes of the slice.
Standard_Integer ibit_in_current_slice = ibit - (islice << 6);
Standard_Integer ibyte = ibit_in_current_slice >> 3;
// Value (byte)
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte];
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit_in_current_slice - (ibyte << 3);
return ((value & gbits[shift]) ? Standard_True : Standard_False);
}

View File

@@ -0,0 +1,102 @@
-- File: Voxel_BooleanOperation.cdl
-- Created: Wed May 21 10:59:19 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class BooleanOperation from Voxel
---Purpose: Boolean operations (fuse, cut)
-- for voxels of the same dimension.
uses
DS from Voxel,
BoolDS from Voxel,
ColorDS from Voxel,
FloatDS from Voxel
is
Create
---Purpose: An empty constructor.
returns BooleanOperation from Voxel;
---Category: Fusion
-- ======
Fuse(me;
theVoxels1 : in out BoolDS from Voxel;
theVoxels2 : in BoolDS from Voxel)
---Purpose: Fuses two cubes of voxels.
-- It modifies the first cube of voxels.
-- It returns false in case of different dimension of the cube,
-- different number of voxels.
returns Boolean from Standard;
Fuse(me;
theVoxels1 : in out ColorDS from Voxel;
theVoxels2 : in ColorDS from Voxel)
---Purpose: Fuses two cubes of voxels.
-- It modifies the first cube of voxels.
-- It returns false in case of different dimension of the cube,
-- different number of voxels.
-- It summerizes the value of corresponding voxels and puts the result to theVoxels1.
-- If the result exceeds 15 or becomes greater, it keeps 15.
returns Boolean from Standard;
Fuse(me;
theVoxels1 : in out FloatDS from Voxel;
theVoxels2 : in FloatDS from Voxel)
---Purpose: Fuses two cubes of voxels.
-- It modifies the first cube of voxels.
-- It returns false in case of different dimension of the cube,
-- different number of voxels.
-- It summerizes the value of corresponding voxels and puts the result to theVoxels1.
returns Boolean from Standard;
---Category: Cut
-- ===
Cut(me;
theVoxels1 : in out BoolDS from Voxel;
theVoxels2 : in BoolDS from Voxel)
---Purpose: Cuts two cubes of voxels.
-- It modifies the first cube of voxels.
-- It returns false in case of different dimension of the cube,
-- different number of voxels.
returns Boolean from Standard;
Cut(me;
theVoxels1 : in out ColorDS from Voxel;
theVoxels2 : in ColorDS from Voxel)
---Purpose: Cuts two cubes of voxels.
-- It modifies the first cube of voxels.
-- It returns false in case of different dimension of the cube,
-- different number of voxels.
-- It subtracts the value of corresponding voxels and puts the result to theVoxels1.
returns Boolean from Standard;
Cut(me;
theVoxels1 : in out FloatDS from Voxel;
theVoxels2 : in FloatDS from Voxel)
---Purpose: Cuts two cubes of voxels.
-- It modifies the first cube of voxels.
-- It returns false in case of different dimension of the cube,
-- different number of voxels.
-- It subtracts the value of corresponding voxels and puts the result to theVoxels1.
returns Boolean from Standard;
---Category: Private area
-- ============
Check(me;
theVoxels1 : DS from Voxel;
theVoxels2 : DS from Voxel)
returns Boolean from Standard
is private;
end BooleanOperation;

View File

@@ -0,0 +1,215 @@
// File: Voxel_BooleanOperation.cxx
// Created: Mon May 21 12:34:54 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_BooleanOperation.ixx>
#include <Precision.hxx>
Voxel_BooleanOperation::Voxel_BooleanOperation()
{
}
Standard_Boolean Voxel_BooleanOperation::Fuse( Voxel_BoolDS& theVoxels1,
const Voxel_BoolDS& theVoxels2) const
{
// Check the voxels
if (!Check(theVoxels1, theVoxels2))
return Standard_False;
// Take the values of the second cube and put them to the first one.
Standard_Integer ix, iy, iz;
for (iz = 0; iz < theVoxels2.GetNbZ(); iz++)
{
for (iy = 0; iy < theVoxels2.GetNbY(); iy++)
{
for (ix = 0; ix < theVoxels2.GetNbX(); ix++)
{
Standard_Boolean value2 = theVoxels2.Get(ix, iy, iz);
if (value2)
theVoxels1.Set(ix, iy, iz, value2);
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_BooleanOperation::Fuse( Voxel_ColorDS& theVoxels1,
const Voxel_ColorDS& theVoxels2) const
{
// Check the voxels
if (!Check(theVoxels1, theVoxels2))
return Standard_False;
// Take the values of the second cube and put them to the first one.
Standard_Integer ix, iy, iz;
for (iz = 0; iz < theVoxels2.GetNbZ(); iz++)
{
for (iy = 0; iy < theVoxels2.GetNbY(); iy++)
{
for (ix = 0; ix < theVoxels2.GetNbX(); ix++)
{
Standard_Byte value2 = theVoxels2.Get(ix, iy, iz);
if (value2)
{
Standard_Byte value1 = theVoxels1.Get(ix, iy, iz);
Standard_Byte value = value1 + value2;
if (value > 15)
value = 15;
theVoxels1.Set(ix, iy, iz, value);
}
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_BooleanOperation::Fuse( Voxel_FloatDS& theVoxels1,
const Voxel_FloatDS& theVoxels2) const
{
// Check the voxels
if (!Check(theVoxels1, theVoxels2))
return Standard_False;
// Take the values of the second cube and put them to the first one.
Standard_Integer ix, iy, iz;
for (iz = 0; iz < theVoxels2.GetNbZ(); iz++)
{
for (iy = 0; iy < theVoxels2.GetNbY(); iy++)
{
for (ix = 0; ix < theVoxels2.GetNbX(); ix++)
{
Standard_ShortReal value2 = theVoxels2.Get(ix, iy, iz);
if (value2)
{
Standard_ShortReal value1 = theVoxels1.Get(ix, iy, iz);
theVoxels1.Set(ix, iy, iz, value1 + value2);
}
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_BooleanOperation::Cut( Voxel_BoolDS& theVoxels1,
const Voxel_BoolDS& theVoxels2) const
{
// Check the voxels
if (!Check(theVoxels1, theVoxels2))
return Standard_False;
// Subtract the values.
Standard_Integer ix, iy, iz;
for (iz = 0; iz < theVoxels2.GetNbZ(); iz++)
{
for (iy = 0; iy < theVoxels2.GetNbY(); iy++)
{
for (ix = 0; ix < theVoxels2.GetNbX(); ix++)
{
Standard_Boolean value1 = theVoxels1.Get(ix, iy, iz);
if (value1)
{
Standard_Boolean value2 = theVoxels2.Get(ix, iy, iz);
if (value2)
theVoxels1.Set(ix, iy, iz, Standard_False);
}
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_BooleanOperation::Cut( Voxel_ColorDS& theVoxels1,
const Voxel_ColorDS& theVoxels2) const
{
// Check the voxels
if (!Check(theVoxels1, theVoxels2))
return Standard_False;
// Subtract the values.
Standard_Integer ix, iy, iz;
for (iz = 0; iz < theVoxels2.GetNbZ(); iz++)
{
for (iy = 0; iy < theVoxels2.GetNbY(); iy++)
{
for (ix = 0; ix < theVoxels2.GetNbX(); ix++)
{
Standard_Byte value2 = theVoxels2.Get(ix, iy, iz);
if (value2)
{
Standard_Byte value1 = theVoxels1.Get(ix, iy, iz);
if (value1)
{
Standard_Integer value = value1 - value2;
if (value < 0)
value = 0;
theVoxels1.Set(ix, iy, iz, value);
}
}
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_BooleanOperation::Cut( Voxel_FloatDS& theVoxels1,
const Voxel_FloatDS& theVoxels2) const
{
// Check the voxels
if (!Check(theVoxels1, theVoxels2))
return Standard_False;
// Subtract the values.
Standard_Integer ix, iy, iz;
for (iz = 0; iz < theVoxels2.GetNbZ(); iz++)
{
for (iy = 0; iy < theVoxels2.GetNbY(); iy++)
{
for (ix = 0; ix < theVoxels2.GetNbX(); ix++)
{
Standard_ShortReal value2 = theVoxels2.Get(ix, iy, iz);
if (value2)
{
Standard_ShortReal value1 = theVoxels1.Get(ix, iy, iz);
theVoxels1.Set(ix, iy, iz, value1 - value2);
}
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_BooleanOperation::Check(const Voxel_DS& theVoxels1,
const Voxel_DS& theVoxels2) const
{
// Check the voxels
// Number of splits along X, Y and Z axes.
if (!theVoxels1.GetNbX() && theVoxels1.GetNbX() != theVoxels2.GetNbX())
return Standard_False;
if (!theVoxels1.GetNbY() && theVoxels1.GetNbY() != theVoxels2.GetNbY())
return Standard_False;
if (!theVoxels1.GetNbZ() && theVoxels1.GetNbZ() != theVoxels2.GetNbZ())
return Standard_False;
// Start point
if (fabs(theVoxels1.GetX() - theVoxels2.GetX()) > Precision::Confusion() ||
fabs(theVoxels1.GetY() - theVoxels2.GetY()) > Precision::Confusion() ||
fabs(theVoxels1.GetZ() - theVoxels2.GetZ()) > Precision::Confusion())
{
return Standard_False;
}
// Length along X, Y and Z axes.
if (fabs(theVoxels1.GetXLen() - theVoxels2.GetXLen()) > Precision::Confusion() ||
fabs(theVoxels1.GetYLen() - theVoxels2.GetYLen()) > Precision::Confusion() ||
fabs(theVoxels1.GetZLen() - theVoxels2.GetZLen()) > Precision::Confusion())
{
return Standard_False;
}
return Standard_True;
}

View File

@@ -0,0 +1,162 @@
-- File: Voxel_CollisionDetection.cdl
-- Created: Mon Jul 14 13:18:04 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class CollisionDetection from Voxel
---Purpose: Detects collisions between shapes.
uses
Shape from TopoDS,
ListOfShape from TopTools,
BoolDS from Voxel,
Box from Bnd
is
Create
---Purpose: An empty constructor.
returns CollisionDetection from Voxel;
---Category: Initialization
-- ==============
Create(deflection : Real from Standard;
nbx : Integer from Standard;
nby : Integer from Standard;
nbz : Integer from Standard)
---Purpose: A constructor.
-- It defines deflection of triangulation for the shapes.
-- As lower the deflection is, as proper the triangulation is generated.
-- Also, it defines number of splits along X, Y and Z axes for generation of voxels.
-- As greater the numbers are, as greater number of voxels is used for detection of collision.
returns CollisionDetection from Voxel;
AddShape(me : in out;
shape : Shape from TopoDS)
---Purpose: Adds a shape.
-- Returns an index of the shape.
returns Integer from Standard;
ReplaceShape(me : in out;
ishape : Integer from Standard;
shape : Shape from TopoDS)
---Purpose: Replaces a shape by another one.
-- <ishape> is an index of the shape.
-- This method is useful for moving shape, for example.
returns Boolean from Standard;
SetDeflection(me : in out;
deflection : Real from Standard);
---Purpose: Defines the deflection of triangulation of shapes.
SetNbVoxels(me : in out;
nbx : Integer from Standard;
nby : Integer from Standard;
nbz : Integer from Standard);
---Purpose: Defines the number of voxels along X, Y and Z axes.
SetBoundaryBox(me : in out;
box: Box from Bnd);
---Purpose: Defines a user-defined boundary box for generation of voxels.
-- If this method is not called, the algorithm calculates the boundary box itself.
SetUsageOfVolume(me : in out;
usage : Boolean from Standard);
---Purpose: Defines usage of volume of shapes in collision detection algorithm.
-- Beware, usage of volume a little bit decreases the speed of algorithm.
KeepCollisions(me : in out;
keep : Boolean from Standard);
---Purpose: Doesn't clean the collision points on new call to the method Compute().
-- It allows to see the collisions for a moving shape.
---Category: Computation
-- ===========
-- Call the method in the following order:
-- Voxelize();
-- Compute();
Voxelize(me : in out;
ishape : Integer from Standard = -1)
---Purpose: Prepares data for computation of collisions.
-- It checks the inner parameters (number of voxels along X, Y and Z axes) and
-- voxelizes the shapes.
-- If the shape is not changed since the last call to this method,
-- this method may be not called for this shape.
-- <ishape> - is the index of the shape for processing by this method.
-- If it is equal to -1, all shapes will be processed.
returns Boolean from Standard;
Compute(me : in out)
---Purpose: Computes the collisions.
-- This method may be called many times if, for example, the shapes are being moved.
returns Boolean from Standard;
---Category: Result (collisions)
-- ===================
HasCollisions(me)
---Purpose: Returns true if a collision is detected.
returns Boolean from Standard;
GetCollisions(me)
---C++: return const &
---Purpose: Returns the collided voxels.
returns BoolDS from Voxel;
---Category: Some internal methods
-- =====================
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor.
Clear(me : in out)
---Purpose: An internal method for cleaning the intermediate data.
is private;
CheckVoxels(me;
voxels : BoolDS from Voxel)
---Purpose: An internal method, which checks correspondance
-- of voxels to the parameters defined by user.
returns Boolean from Standard
is private;
fields
-- Initial data.
myShapes : ListOfShape from TopTools;
myDeflection : Real from Standard;
myNbX : Integer from Standard;
myNbY : Integer from Standard;
myNbZ : Integer from Standard;
myUsageOfVolume : Boolean from Standard;
myKeepCollisions : Boolean from Standard;
-- User-defined boundary box of shapes.
myX : Real from Standard;
myY : Real from Standard;
myZ : Real from Standard;
myXLen : Real from Standard;
myYLen : Real from Standard;
myZLen : Real from Standard;
-- An array of voxels of all shapes.
myVoxels : Address from Standard;
-- The result.
myCollisions : BoolDS from Voxel;
myHasCollisions : Boolean from Standard;
end CollisionDetection;

View File

@@ -0,0 +1,284 @@
// File: Voxel_CollisionDetection.cxx
// Created: Mon July 16 12:13:45 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_CollisionDetection.ixx>
#include <Voxel_FastConverter.hxx>
#include <Precision.hxx>
#include <BRepBndLib.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
Voxel_CollisionDetection::Voxel_CollisionDetection()
:myDeflection(0.1),
myNbX(100),
myNbY(100),
myNbZ(100),
myUsageOfVolume(Standard_False),
myKeepCollisions(Standard_False),
myXLen(-1.0),
myYLen(-1.0),
myZLen(-1.0),
myVoxels(0),
myHasCollisions(Standard_False)
{
}
Voxel_CollisionDetection::Voxel_CollisionDetection(const Standard_Real deflection,
const Standard_Integer nbx,
const Standard_Integer nby,
const Standard_Integer nbz)
:myDeflection(deflection),
myNbX(nbx),
myNbY(nby),
myNbZ(nbz),
myUsageOfVolume(Standard_False),
myKeepCollisions(Standard_False),
myXLen(-1.0),
myYLen(-1.0),
myZLen(-1.0),
myVoxels(0),
myHasCollisions(Standard_False)
{
}
// Destructor
void Voxel_CollisionDetection::Destroy()
{
Clear();
}
Standard_Integer Voxel_CollisionDetection::AddShape(const TopoDS_Shape& shape)
{
Clear();
myShapes.Append(shape);
return myShapes.Extent();
}
Standard_Boolean Voxel_CollisionDetection::ReplaceShape(const Standard_Integer ishape,
const TopoDS_Shape& shape)
{
if (ishape == 1)
{
myShapes.RemoveFirst();
myShapes.Prepend(shape);
return Standard_True;
}
Standard_Integer i = 1;
Standard_Boolean is_replaced = Standard_False;
TopTools_ListIteratorOfListOfShape itr(myShapes);
for (; itr.More(); itr.Next(), i++)
{
if (i == ishape)
{
myShapes.Remove(itr);
myShapes.InsertBefore(shape, itr);
is_replaced = Standard_True;
break;
}
}
return is_replaced;
}
void Voxel_CollisionDetection::SetDeflection(const Standard_Real deflection)
{
myDeflection = deflection;
}
void Voxel_CollisionDetection::SetNbVoxels(const Standard_Integer nbx,
const Standard_Integer nby,
const Standard_Integer nbz)
{
myNbX = nbx;
myNbY = nby;
myNbZ = nbz;
}
void Voxel_CollisionDetection::SetBoundaryBox(const Bnd_Box& box)
{
if (box.IsVoid())
return;
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
box.Get(xmin, ymin, zmin, xmax, ymax, zmax);
myX = xmin;
myY = ymin;
myZ = zmin;
myXLen = xmax - xmin;
myYLen = ymax - ymin;
myZLen = zmax - zmin;
}
void Voxel_CollisionDetection::SetUsageOfVolume(const Standard_Boolean usage)
{
myUsageOfVolume = usage;
}
void Voxel_CollisionDetection::KeepCollisions(const Standard_Boolean keep)
{
myKeepCollisions = keep;
}
Standard_Boolean Voxel_CollisionDetection::Voxelize(const Standard_Integer ishape)
{
// Check the arguments
if (myNbX <= 0 || myNbY <= 0 || myNbZ <= 0)
return Standard_False;
// Calculate the boundary box of the shapes to define the size of voxels.
// This code is called only if the user didn't define the boundary box himself.
if (myXLen < 0.0)
{
Bnd_Box B, b;
TopTools_ListIteratorOfListOfShape itrs(myShapes);
for (; itrs.More(); itrs.Next())
{
TopoDS_Shape S = itrs.Value();
BRepBndLib::Add(S, b);
B.Add(b);
}
SetBoundaryBox(B);
}
// Voxelize the shapes
Standard_Integer progress, ithread = 1, i = 1;
TopTools_ListIteratorOfListOfShape itrs(myShapes);
for (; itrs.More(); itrs.Next(), i++)
{
if (ishape != -1 && i != ishape)
continue;
if (!myVoxels)
myVoxels = (Standard_Address) new Voxel_BoolDS[myShapes.Extent()];
Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[i - 1];
if (!CheckVoxels(voxels))
{
voxels.Init(myX, myY, myZ, myXLen, myYLen, myZLen, myNbX, myNbY, myNbZ);
}
else
{
voxels.SetZero();
}
TopoDS_Shape S = itrs.Value();
Voxel_FastConverter voxelizer(S, voxels, myDeflection, myNbX, myNbY, myNbZ, 1 /*number of threads */);
if (!voxelizer.Convert(progress, ithread))
return Standard_False;
if (myUsageOfVolume && !voxelizer.FillInVolume(1, ithread))
return Standard_False;
}
return Standard_True;
}
Standard_Boolean Voxel_CollisionDetection::Compute()
{
myHasCollisions = Standard_False;
// Check voxels of shapes
if (!myVoxels)
return Standard_False;
Standard_Integer ishape = 0, nb_shapes = myShapes.Extent();
for (; ishape < nb_shapes; ishape++)
{
Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[ishape];
if (!CheckVoxels(voxels))
{
return Standard_False;
}
}
// Check the resulting voxels
Standard_Boolean created = Standard_False;
if (!CheckVoxels(myCollisions))
{
// Create 0-voxels for the result, if it is needed.
created = Standard_True;
myCollisions.Init(myX, myY, myZ, myXLen, myYLen, myZLen, myNbX, myNbY, myNbZ);
}
// Nullify the voxels of the result (it corresponds to the state of no collisions).
if (!myKeepCollisions && !created)
{
myCollisions.SetZero();
}
// Check collisions
if (nb_shapes)
{
Standard_Integer ix, iy, iz;
Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[0]; // 1st shape
for (ix = 0; ix < myNbX; ix++)
{
for (iy = 0; iy < myNbY; iy++)
{
for (iz = 0; iz < myNbZ; iz++)
{
if (voxels.Get(ix, iy, iz))
{
for (ishape = 1; ishape < nb_shapes; ishape++) // start with second shape
{
Voxel_BoolDS& voxels = ((Voxel_BoolDS*)myVoxels)[ishape];
if (voxels.Get(ix, iy, iz))
{
myCollisions.Set(ix, iy, iz, Standard_True);
if (!myHasCollisions)
{
myHasCollisions = Standard_True;
}
break;
}
}
}
}
}
}
}
return Standard_True;
}
Standard_Boolean Voxel_CollisionDetection::HasCollisions() const
{
return myHasCollisions;
}
const Voxel_BoolDS& Voxel_CollisionDetection::GetCollisions() const
{
return myCollisions;
}
void Voxel_CollisionDetection::Clear()
{
if (myVoxels)
{
delete ((Voxel_BoolDS*)myVoxels);
myVoxels = 0;
}
}
Standard_Boolean Voxel_CollisionDetection::CheckVoxels(const Voxel_BoolDS& voxels) const
{
if (fabs(voxels.GetX() - myX) > Precision::Confusion() ||
fabs(voxels.GetY() - myY) > Precision::Confusion() ||
fabs(voxels.GetZ() - myZ) > Precision::Confusion() ||
fabs(voxels.GetXLen() - myXLen) > Precision::Confusion() ||
fabs(voxels.GetYLen() - myYLen) > Precision::Confusion() ||
fabs(voxels.GetZLen() - myZLen) > Precision::Confusion() ||
voxels.GetNbX() != myNbX ||
voxels.GetNbY() != myNbY ||
voxels.GetNbZ() != myNbZ)
{
return Standard_False;
}
return Standard_True;
}

74
src/Voxel/Voxel_ColorDS.cdl Executable file
View File

@@ -0,0 +1,74 @@
-- File: Voxel_BoolDS.cdl
-- Created: Sun May 08 12:53:45 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class ColorDS from Voxel inherits DS from Voxel
---Purpose: A 3D voxel model keeping 4 bits for each voxel (one of 16 colors).
is
Create
---Purpose: An empty constructor.
returns ColorDS from Voxel;
Create(x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: A constructor initializing the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
returns ColorDS from Voxel;
Init(me : in out;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: Initialization of the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
is redefined virtual;
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor of the voxel model.
SetZero(me : in out);
---Purpose: The method sets all values equal to 0 (false) and
-- releases the memory.
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
data : Byte from Standard);
---Purpose: Defines a value for voxel with co-ordinates (ix, iy, iz).
-- Only the first four bits are used!
-- Initial state of the model is so that all voxels have value 0x0000,
-- and this data doesn't occupy memory.
-- Memory for data is allocating during setting non-zero values (0x0101, for example).
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns the value of voxel with co-ordinates (ix, iy, iz).
returns Byte from Standard;
end ColorDS;

163
src/Voxel/Voxel_ColorDS.cxx Executable file
View File

@@ -0,0 +1,163 @@
// File: Voxel_ColorDS.cxx
// Created: Mon May 08 12:36:31 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_ColorDS.ixx>
#include <stdlib.h>
static Standard_Byte gbits[8] = {1, 2, 4, 8, 16, 32, 64, 128};
static Standard_Byte gnbits[8] = {255-1, 255-2, 255-4, 255-8, 255-16, 255-32, 255-64, 255-128};
// Empty constructor
Voxel_ColorDS::Voxel_ColorDS():Voxel_DS()
{
}
// Constructor with intialization.
Voxel_ColorDS::Voxel_ColorDS(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
:Voxel_DS()
{
Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
}
// Initialization.
void Voxel_ColorDS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
Destroy();
Voxel_DS::Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
if (!myNbX || !myNbY || !myNbZ)
return;
Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 2.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
myData = (Standard_Address) calloc(nb_slices, sizeof(Standard_Byte*));
}
// Destructor
void Voxel_ColorDS::Destroy()
{
if (myData)
{
SetZero();
free((Standard_Byte**)myData);
myData = 0;
}
}
void Voxel_ColorDS::SetZero()
{
if (myData)
{
Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 2.0));
Standard_Integer ix = 0, nb_slices = RealToInt(ceil(nb_bytes / 32.0));
for (; ix < nb_slices; ix++)
{
if (((Standard_Byte**)myData)[ix])
{
free(((Standard_Byte**)myData)[ix]);
((Standard_Byte**)myData)[ix] = 0;
}
}
}
}
// Access to the boolean information attached to a particular voxel:
// Info: (ix >= 0 && ix < theNb_x), etc.
void Voxel_ColorDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Byte data)
{
Standard_Integer ibit = 4 * (ix + myNbX * iy + myNbXY * iz);
Standard_Integer islice = ibit >> 8;
if (!data && !((Standard_Byte**)myData)[islice])
return; // don't allocate a slice of data for setting a 0 value
// Allocate the slice if it is not done yet.
if (!((Standard_Byte**)myData)[islice])
{
((Standard_Byte**)myData)[islice] = (Standard_Byte*) calloc(32/*number of bytes in slice*/, sizeof(Standard_Byte));
}
// Index within 32 bytes of the slice.
Standard_Integer ibit_in_current_slice = ibit - (islice << 8);
Standard_Integer ibyte = ibit_in_current_slice >> 3;
// Value (byte)
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte];
// Position of data in the 8 bit-"value":
// It is either 0 (first part of the byte) or 2 (second part of the byte)
Standard_Integer shift = ibit_in_current_slice - (ibyte << 3);
// Set data
Standard_Integer i = 0, j = 0, nb = 4; // first part of byte
if (shift == 4)
{
// second part of byte
i = 4;
nb = 8;
}
for (; i < nb; i++, j++)
{
if (data & gbits[j]) // if j-th bit is 1
{
value |= gbits[i]; // set 1 to the i-th bit
}
else
{
value &= gnbits[i]; // set 0 to the i-th bit
}
}
((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte] = value;
}
Standard_Byte Voxel_ColorDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Byte ret = 0;
Standard_Integer ibit = 4 * (ix + myNbX * iy + myNbXY * iz);
Standard_Integer islice = ibit >> 8;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Standard_Byte**)myData)[islice])
return ret;
// Index within 8 bytes of the slice.
Standard_Integer ibit_in_current_slice = ibit - (islice << 8);
Standard_Integer ibyte = ibit_in_current_slice >> 3;
// Value (byte)
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte];
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit_in_current_slice - (ibyte << 3);
// Return a byte with 4 first bits filled-in by the value.
Standard_Integer i = 0, j = 0, nb = 4; // first part of byte
if (shift == 4)
{
// second part of byte
i = 4;
nb = 8;
}
for (; i < nb; i++, j++)
{
if (value & gbits[i]) // if i-th bit is 1
{
ret |= gbits[j]; // set 1 to the j-th bit
}
}
return ret;
}

134
src/Voxel/Voxel_DS.cdl Executable file
View File

@@ -0,0 +1,134 @@
-- File: Voxel_DS.cdl
-- Created: Sun May 07 14:53:46 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class DS from Voxel
---Purpose: A base class for all voxel data structures.
is
Create
---Purpose: An empty constructor.
returns DS from Voxel;
Create(x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: A constructor initializing the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
returns DS from Voxel;
Init(me : in out;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: Initialization of the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
is virtual;
---Purpose: The methods below return initial data of the voxel model.
GetX (me) returns Real from Standard;
GetY (me) returns Real from Standard;
GetZ (me) returns Real from Standard;
GetXLen(me) returns Real from Standard;
GetYLen(me) returns Real from Standard;
GetZLen(me) returns Real from Standard;
GetNbX (me) returns Integer from Standard;
GetNbY (me) returns Integer from Standard;
GetNbZ (me) returns Integer from Standard;
GetCenter(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
xc : out Real from Standard;
yc : out Real from Standard;
zc : out Real from Standard);
---Purpose: Returns the center point of a voxel with co-ordinates (ix, iy, iz).
GetVoxel(me;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
ix : out Integer from Standard;
iy : out Integer from Standard;
iz : out Integer from Standard)
---Purpose: Finds a voxel corresponding to a 3D point.
-- Returns true if it is found.
returns Boolean from Standard;
GetVoxelX(me;
x : Real from Standard;
ix : out Integer from Standard)
---Purpose: Returns x-index of a voxel corresponding to x-coordinate.
returns Boolean from Standard;
GetVoxelY(me;
y : Real from Standard;
iy : out Integer from Standard)
---Purpose: Returns y-index of a voxel corresponding to y-coordinate.
returns Boolean from Standard;
GetVoxelZ(me;
z : Real from Standard;
iz : out Integer from Standard)
---Purpose: Returns z-index of a voxel corresponding to z-coordinate.
returns Boolean from Standard;
fields
-- Flag (1 or 0) attached to each voxel (BoolDS).
-- 4 bits attached to each voxel (ColorDS).
-- Etc.
myData : Address from Standard is protected;
-- Start point of the cube of voxels.
myX : Real from Standard is protected;
myY : Real from Standard is protected;
myZ : Real from Standard is protected;
-- Lengths of cube of voxels along X, Y and Z directions.
myXLen : Real from Standard is protected;
myYLen : Real from Standard is protected;
myZLen : Real from Standard is protected;
-- Number of voxels along X, Y and Z directions.
myNbX : Integer from Standard is protected;
myNbY : Integer from Standard is protected;
myNbZ : Integer from Standard is protected;
--- Optimization data.
myNbXY : Integer from Standard is protected;
myDX : Real from Standard is protected;
myDY : Real from Standard is protected;
myDZ : Real from Standard is protected;
myHalfDX : Real from Standard is protected;
myHalfDY : Real from Standard is protected;
myHalfDZ : Real from Standard is protected;
friends
-- Gives access to myData inorder to make reading/writing much faster.
class Writer from Voxel,
class Reader from Voxel
end DS;

172
src/Voxel/Voxel_DS.cxx Executable file
View File

@@ -0,0 +1,172 @@
// File: Voxel_DS.cxx
// Created: Mon May 11 13:46:35 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_DS.ixx>
// Empty constructor
Voxel_DS::Voxel_DS()
:myData(0),
myX(0.0),myY(0.0),myZ(0.0),
myXLen(0.0),myYLen(0.0),myZLen(0.0),
myNbX(0),myNbY(0),myNbZ(0),
myNbXY(0),myDX(0.0),myDY(0.0),myDZ(0.0),
myHalfDX(0.0),myHalfDY(0.0),myHalfDZ(0.0)
{
}
// Constructor with intialization.
Voxel_DS::Voxel_DS(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
}
// Initialization.
void Voxel_DS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
myX = x;
myY = y;
myZ = z;
myXLen = xlen;
myYLen = ylen;
myZLen = zlen;
myNbX = nbx;
myNbY = nby;
myNbZ = nbz;
myNbXY = myNbX * myNbY;
myDX = myXLen / (Standard_Real) myNbX;
myDY = myYLen / (Standard_Real) myNbY;
myDZ = myZLen / (Standard_Real) myNbZ;
myHalfDX = myDX / 2.0;
myHalfDY = myDY / 2.0;
myHalfDZ = myDZ / 2.0;
}
// Get the initial information on voxels
Standard_Real Voxel_DS::GetX() const
{
return myX;
}
Standard_Real Voxel_DS::GetY() const
{
return myY;
}
Standard_Real Voxel_DS::GetZ() const
{
return myZ;
}
Standard_Real Voxel_DS::GetXLen() const
{
return myXLen;
}
Standard_Real Voxel_DS::GetYLen() const
{
return myYLen;
}
Standard_Real Voxel_DS::GetZLen() const
{
return myZLen;
}
Standard_Integer Voxel_DS::GetNbX() const
{
return myNbX;
}
Standard_Integer Voxel_DS::GetNbY() const
{
return myNbY;
}
Standard_Integer Voxel_DS::GetNbZ() const
{
return myNbZ;
}
void Voxel_DS::GetCenter(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
Standard_Real& xc, Standard_Real& yc, Standard_Real& zc) const
{
xc = myX + ix * myDX + myHalfDX;
yc = myY + iy * myDY + myHalfDY;
zc = myZ + iz * myDZ + myHalfDZ;
}
// The method uses a chordial approach to find the index of voxel by co-ordinate.
static Standard_Integer findIndex(const Standard_Real xstart, const Standard_Real dx,
const Standard_Integer ix1, const Standard_Integer ix2,
const Standard_Real x)
{
if (ix2 - ix1 < 2)
{
if (x < xstart + ix2 * dx)
return ix1;
return ix2;
}
// Middle index
const Standard_Integer ixm = (ix1 + ix2) / 2;
// Check if it is in the first half:
if (x >= xstart + ix1 * dx && x < xstart + ixm * dx)
{
return findIndex(xstart, dx, ix1, ixm, x);
}
return findIndex(xstart, dx, ixm, ix2, x);
}
Standard_Boolean Voxel_DS::GetVoxel(const Standard_Real x, const Standard_Real y, const Standard_Real z,
Standard_Integer& ix, Standard_Integer& iy, Standard_Integer& iz) const
{
// X
if (!GetVoxelX(x, ix))
return Standard_False;
// Y
if (!GetVoxelY(y, iy))
return Standard_False;
// Z
return GetVoxelZ(z, iz);
}
Standard_Boolean Voxel_DS::GetVoxelX(const Standard_Real x,
Standard_Integer& ix) const
{
// X
if (x < myX || x > myX + myXLen)
return Standard_False;
ix = findIndex(myX, myXLen / (Standard_Real) myNbX, 0, myNbX - 1, x);
return Standard_True;
}
Standard_Boolean Voxel_DS::GetVoxelY(const Standard_Real y,
Standard_Integer& iy) const
{
// Y
if (y < myY || y > myY + myYLen)
return Standard_False;
iy = findIndex(myY, myYLen / (Standard_Real) myNbY, 0, myNbY - 1, y);
return Standard_True;
}
Standard_Boolean Voxel_DS::GetVoxelZ(const Standard_Real z,
Standard_Integer& iz) const
{
// Z
if (z < myZ || z > myZ + myZLen)
return Standard_False;
iz = findIndex(myZ, myZLen / (Standard_Real) myNbZ, 0, myNbZ - 1, z);
return Standard_True;
}

126
src/Voxel/Voxel_FastConverter.cdl Executable file
View File

@@ -0,0 +1,126 @@
-- File: Voxel_FastConverter.cdl
-- Created: Mon May 30 12:14:12 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class FastConverter from Voxel
---Purpose: Converts a shape to voxel representation.
-- It does it fast, but with less precision.
-- Also, it doesn't fill-in volumic part of the shape.
uses
Pnt from gp,
Pln from gp,
Shape from TopoDS,
BoolDS from Voxel,
ColorDS from Voxel,
ROctBoolDS from Voxel
is
Create(shape : Shape from TopoDS;
voxels : out BoolDS from Voxel;
delfection : Real from Standard = 0.1;
nbx : Integer from Standard = 10;
nby : Integer from Standard = 10;
nbz : Integer from Standard = 10;
nbthreads : Integer from Standard = 1)
---Purpose: A constructor for conversion of a shape into a cube of boolean voxels.
-- It allocates the voxels in memory.
-- "nbthreads" defines the number of threads used to convert the shape.
returns FastConverter from Voxel;
Create(shape : Shape from TopoDS;
voxels : out ColorDS from Voxel;
delfection : Real from Standard = 0.1;
nbx : Integer from Standard = 10;
nby : Integer from Standard = 10;
nbz : Integer from Standard = 10;
nbthreads : Integer from Standard = 1)
---Purpose: A constructor for conversion of a shape into a cube of colored voxels.
-- It allocates the voxels in memory.
-- "nbthreads" defines the number of threads used to convert the shape.
returns FastConverter from Voxel;
Create(shape : Shape from TopoDS;
voxels : out ROctBoolDS from Voxel;
delfection : Real from Standard = 0.1;
nbx : Integer from Standard = 10;
nby : Integer from Standard = 10;
nbz : Integer from Standard = 10;
nbthreads : Integer from Standard = 1)
---Purpose: A constructor for conversion of a shape into a cube of boolean voxels
-- split into 8 sub-voxels recursively.
-- It allocates the voxels in memory.
-- "nbthreads" defines the number of threads used to convert the shape.
returns FastConverter from Voxel;
Convert(me : in out;
progress : out Integer from Standard;
ithread : Integer from Standard = 1)
---Purpose: Converts a shape into a voxel representation.
-- It sets to 0 the outside volume of the shape and
-- 1 for surfacic part of the shape.
-- "ithread" is the index of the thread for current call of ::Convert().
-- Start numeration of "ithread" with 1, please.
returns Boolean from Standard;
FillInVolume(me : in out;
inner : Byte from Standard;
ithread : Integer from Standard = 1)
---Purpose: Fills-in volume of the shape by a value.
returns Boolean from Standard;
---Category: Private area
-- ============
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor.
Init(me : in out)
is private;
GetBndBox(me;
p1 : Pnt from gp;
p2 : Pnt from gp;
p3 : Pnt from gp;
xmin : out Real from Standard;
ymin : out Real from Standard;
zmin : out Real from Standard;
xmax : out Real from Standard;
ymax : out Real from Standard;
zmax : out Real from Standard)
is private;
ComputeVoxelsNearTriangle(me;
plane : Pln from gp;
p1 : Pnt from gp;
p2 : Pnt from gp;
p3 : Pnt from gp;
hdiag : Real from Standard;
ixmin : Integer from Standard;
iymin : Integer from Standard;
izmin : Integer from Standard;
ixmax : Integer from Standard;
iymax : Integer from Standard;
izmax : Integer from Standard)
is private;
fields
myShape : Shape from TopoDS;
myVoxels : Address from Standard;
myDeflection : Real from Standard;
myIsBool : Integer from Standard; -- 0 - ColorDS, 1 - BoolDS, 2 - ROctBoolDS
myNbX : Integer from Standard;
myNbY : Integer from Standard;
myNbZ : Integer from Standard;
myNbThreads : Integer from Standard;
myNbTriangles : Integer from Standard;
end FastConverter;

668
src/Voxel/Voxel_FastConverter.cxx Executable file
View File

@@ -0,0 +1,668 @@
// File: Voxel_FastConverter.cxx
// Created: Mon May 30 17:55:14 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_FastConverter.ixx>
#include <Bnd_Box.hxx>
#include <BRep_Tool.hxx>
#include <BRepBndLib.hxx>
#include <BRepMesh.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <gp_Lin2d.hxx>
#include <gce_MakePln.hxx>
#include <ElSLib.hxx>
#include <Poly_Triangulation.hxx>
#include <IntAna2d_AnaIntersection.hxx>
// Printing the progress in stdout.
//#define CONV_DUMP
Voxel_FastConverter::Voxel_FastConverter(const TopoDS_Shape& shape,
Voxel_ROctBoolDS& voxels,
const Standard_Real deflection,
const Standard_Integer nbx,
const Standard_Integer nby,
const Standard_Integer nbz,
const Standard_Integer nbthreads)
:myShape(shape),myVoxels(&voxels),
myDeflection(deflection),
myNbX(nbx),myNbY(nby),myNbZ(nbz),
myNbThreads(nbthreads),myIsBool(2),
myNbTriangles(0)
{
Init();
}
Voxel_FastConverter::Voxel_FastConverter(const TopoDS_Shape& shape,
Voxel_BoolDS& voxels,
const Standard_Real deflection,
const Standard_Integer nbx,
const Standard_Integer nby,
const Standard_Integer nbz,
const Standard_Integer nbthreads)
:myShape(shape),myVoxels(&voxels),
myDeflection(deflection),
myNbX(nbx),myNbY(nby),myNbZ(nbz),
myNbThreads(nbthreads),myIsBool(1),
myNbTriangles(0)
{
Init();
}
Voxel_FastConverter::Voxel_FastConverter(const TopoDS_Shape& shape,
Voxel_ColorDS& voxels,
const Standard_Real deflection,
const Standard_Integer nbx,
const Standard_Integer nby,
const Standard_Integer nbz,
const Standard_Integer nbthreads)
:myShape(shape),myVoxels(&voxels),
myDeflection(deflection),
myNbX(nbx),myNbY(nby),myNbZ(nbz),
myNbThreads(nbthreads),myIsBool(0),
myNbTriangles(0)
{
Init();
}
void Voxel_FastConverter::Init()
{
if (myShape.IsNull())
return;
if (myNbThreads < 1)
return;
// Check number of splits.
Voxel_DS* voxels = (Voxel_DS*) myVoxels;
if (voxels->GetNbX() != myNbX || voxels->GetNbY() != myNbY || voxels->GetNbZ() != myNbZ)
{
// Compute boundary box of the shape
Bnd_Box box;
BRepBndLib::Add(myShape, box);
// Define the voxel model by means of the boundary box of shape
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
box.Get(xmin, ymin, zmin, xmax, ymax, zmax);
// Initialize the voxels.
if (myIsBool == 2)
((Voxel_ROctBoolDS*) voxels)->Init(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin, myNbX, myNbY, myNbZ);
else if (myIsBool == 1)
((Voxel_BoolDS*) voxels)->Init(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin, myNbX, myNbY, myNbZ);
else if (myIsBool == 0)
((Voxel_ColorDS*) voxels)->Init(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin, myNbX, myNbY, myNbZ);
}
// Check presence of triangulation.
TopLoc_Location L;
Standard_Boolean triangulate = Standard_False;
TopExp_Explorer expl(myShape, TopAbs_FACE);
for (; expl.More(); expl.Next())
{
TopoDS_Face F = TopoDS::Face(expl.Current());
Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L);
if (T.IsNull() || fabs(T->Deflection() - myDeflection) > Precision::Confusion())
{
triangulate = Standard_True;
break;
}
}
// Re-create the triangulation.
if (triangulate)
{
BRepMesh::Mesh(myShape, myDeflection);
}
// Compute the number of triangles.
myNbTriangles = 0;
expl.Init(myShape, TopAbs_FACE);
for (; expl.More(); expl.Next())
{
TopoDS_Face F = TopoDS::Face(expl.Current());
Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L);
myNbTriangles += T->NbTriangles();
}
}
// Destructor
void Voxel_FastConverter::Destroy()
{
}
Standard_Boolean Voxel_FastConverter::Convert(Standard_Integer& progress,
const Standard_Integer ithread)
{
if (ithread == 1)
progress = 0;
#ifdef CONV_DUMP
if (ithread == 1)
printf("Progress = %d \r", progress);
#endif
if (myNbX <= 0 || myNbY <= 0 || myNbZ <= 0)
return Standard_False;
// Half of diagonal of a voxel
Voxel_DS* ds = (Voxel_DS*) myVoxels;
Standard_Real dx = ds->GetXLen() / (Standard_Real) ds->GetNbX(),
dy = ds->GetYLen() / (Standard_Real) ds->GetNbY(),
dz = ds->GetZLen() / (Standard_Real) ds->GetNbZ();
Standard_Real hdiagonal = sqrt(dx * dx + dy * dy + dz * dz);
hdiagonal /= 2.0;
// Compute the scope of triangles for current thread
Standard_Integer start_thread_triangle = 1, end_thread_triangle = myNbTriangles, ithread_triangle = 0;
start_thread_triangle = (ithread - 1) * (myNbTriangles / myNbThreads) + 1;
end_thread_triangle = (ithread - 0) * (myNbTriangles / myNbThreads);
// Convert
TopLoc_Location L;
Standard_Integer iprogress = 0, prev_progress = 0;
Standard_Integer n1, n2, n3;
Standard_Integer ixmin, iymin, izmin, ixmax, iymax, izmax;
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
TopExp_Explorer expl(myShape, TopAbs_FACE);
for (; expl.More(); expl.Next())
{
TopoDS_Face F = TopoDS::Face(expl.Current());
Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L);
gp_Trsf trsf;
Standard_Boolean transform = !L.IsIdentity();
if (transform)
trsf = L.Transformation();
const TColgp_Array1OfPnt& nodes = T->Nodes();
const Poly_Array1OfTriangle& triangles = T->Triangles();
Standard_Integer itriangle = triangles.Lower(), nb_triangles = triangles.Upper();
for (; itriangle <= nb_triangles; itriangle++)
{
ithread_triangle++;
if (ithread_triangle < start_thread_triangle || ithread_triangle > end_thread_triangle)
continue;
const Poly_Triangle& t = triangles.Value(itriangle);
t.Get(n1, n2, n3);
gp_Pnt p1 = nodes.Value(n1);
gp_Pnt p2 = nodes.Value(n2);
gp_Pnt p3 = nodes.Value(n3);
if (transform)
{
p1.Transform(trsf);
p2.Transform(trsf);
p3.Transform(trsf);
}
// Get boundary box of the triangle
GetBndBox(p1, p2, p3, xmin, ymin, zmin, xmax, ymax, zmax);
// Find the range of voxels inside the boudary box of the triangle.
if (!ds->GetVoxel(xmin, ymin, zmin, ixmin, iymin, izmin))
continue;
if (!ds->GetVoxel(xmax, ymax, zmax, ixmax, iymax, izmax))
continue;
// Refuse voxels for whom distance from their center to plane of triangle is greater than half of diagonal.
// Make a line from center of each voxel to the center of triangle and
// compute intersection of the line with sides of triangle.
// Refuse the voxel in case of intersection.
gce_MakePln mkPlane(p1, p2, p3);
if (!mkPlane.IsDone())
continue;
gp_Pln plane = mkPlane.Value();
ComputeVoxelsNearTriangle(plane, p1, p2, p3, hdiagonal, ixmin, iymin, izmin, ixmax, iymax, izmax);
// Progress
if (ithread == 1)
{
iprogress++;
progress = (Standard_Integer) ( (Standard_Real) iprogress / (Standard_Real) myNbTriangles * 100.0 );
}
#ifdef CONV_DUMP
if (ithread == 1 && prev_progress != progress)
{
printf("Progress = %d \r", progress);
prev_progress = progress;
}
#endif
} // iteration of triangles
} // iteration of faces
if (ithread == 1)
progress = 100;
#ifdef CONV_DUMP
if (ithread == 1)
printf("Progress = %d \r", progress);
#endif
return Standard_True;
}
Standard_Boolean Voxel_FastConverter::FillInVolume(const Standard_Byte inner,
const Standard_Integer ithread)
{
Voxel_DS* ds = (Voxel_DS*) myVoxels;
Standard_Integer ix, iy, iz, nbx = ds->GetNbX(), nby = ds->GetNbY(), nbz = ds->GetNbZ();
Standard_Boolean prev_surface, surface, volume;
if (inner)
{
// Fill-in internal voxels by the value "inner"
for (ix = 0; ix < nbx; ix++)
{
for (iy = 0; iy < nby; iy++)
{
// Check existence of volume.
volume = Standard_False;
surface = Standard_False;
prev_surface = Standard_False;
for (iz = 0; iz < nbz; iz++)
{
surface = (myIsBool == 1) ?
((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz) == Standard_True :
((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz) > 0;
if (prev_surface && !surface)
{
volume = !volume;
}
prev_surface = surface;
}
if (volume)
continue;
// Fill-in the volume.
volume = Standard_False;
surface = Standard_False;
prev_surface = Standard_False;
for (iz = 0; iz < nbz; iz++)
{
surface = (myIsBool == 1) ?
((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz) == Standard_True :
((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz) > 0;
if (prev_surface && !surface)
{
volume = !volume;
}
if (volume && !surface)
{
(myIsBool == 1) ? ((Voxel_BoolDS*)myVoxels)->Set(ix, iy, iz, inner) :
((Voxel_ColorDS*)myVoxels)->Set(ix, iy, iz, inner);
}
prev_surface = surface;
}
}
}
}
else
{
// Set value of interbal voxels to 0 ("inner" = 0)
Standard_Boolean next_surface;
for (ix = 0; ix < nbx; ix++)
{
for (iy = 0; iy < nby; iy++)
{
volume = Standard_False;
surface = Standard_False;
prev_surface = Standard_False;
next_surface = Standard_False;
for (iz = 0; iz < nbz; iz++)
{
surface = (myIsBool == 1) ?
((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz) == Standard_True :
((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz) > 0;
if (prev_surface != surface)
{
volume = !volume;
}
if (volume && iz + 1 < nbz)
{
next_surface = (myIsBool == 1) ?
((Voxel_BoolDS*)myVoxels)->Get(ix, iy, iz + 1) == Standard_True :
((Voxel_ColorDS*)myVoxels)->Get(ix, iy, iz + 1) > 0;
}
if (volume && prev_surface == surface && next_surface)
{
(myIsBool == 1) ? ((Voxel_BoolDS*)myVoxels)->Set(ix, iy, iz, inner) :
((Voxel_ColorDS*)myVoxels)->Set(ix, iy, iz, inner);
}
prev_surface = surface;
}
}
}
}
return Standard_True;
}
void Voxel_FastConverter::GetBndBox(const gp_Pnt& p1,
const gp_Pnt& p2,
const gp_Pnt& p3,
Standard_Real& xmin,
Standard_Real& ymin,
Standard_Real& zmin,
Standard_Real& xmax,
Standard_Real& ymax,
Standard_Real& zmax) const
{
// P1:
xmin = p1.X();
ymin = p1.Y();
zmin = p1.Z();
xmax = p1.X();
ymax = p1.Y();
zmax = p1.Z();
// P2:
if (xmin > p2.X())
xmin = p2.X();
if (ymin > p2.Y())
ymin = p2.Y();
if (zmin > p2.Z())
zmin = p2.Z();
if (xmax < p2.X())
xmax = p2.X();
if (ymax < p2.Y())
ymax = p2.Y();
if (zmax < p2.Z())
zmax = p2.Z();
// P3:
if (xmin > p3.X())
xmin = p3.X();
if (ymin > p3.Y())
ymin = p3.Y();
if (zmin > p3.Z())
zmin = p3.Z();
if (xmax < p3.X())
xmax = p3.X();
if (ymax < p3.Y())
ymax = p3.Y();
if (zmax < p3.Z())
zmax = p3.Z();
}
// This method is copied from Voxel_ShapeIntersector.cxx
static Standard_Boolean mayIntersect(const gp_Pnt2d& p11, const gp_Pnt2d& p12,
const gp_Pnt2d& p21, const gp_Pnt2d& p22)
{
if (p11.X() > p21.X() && p11.X() > p22.X() && p12.X() > p21.X() && p12.X() > p22.X())
return Standard_False;
if (p11.X() < p21.X() && p11.X() < p22.X() && p12.X() < p21.X() && p12.X() < p22.X())
return Standard_False;
if (p11.Y() > p21.Y() && p11.Y() > p22.Y() && p12.Y() > p21.Y() && p12.Y() > p22.Y())
return Standard_False;
if (p11.Y() < p21.Y() && p11.Y() < p22.Y() && p12.Y() < p21.Y() && p12.Y() < p22.Y())
return Standard_False;
return Standard_True;
}
void Voxel_FastConverter::ComputeVoxelsNearTriangle(const gp_Pln& plane,
const gp_Pnt& p1,
const gp_Pnt& p2,
const gp_Pnt& p3,
const Standard_Real hdiagonal,
const Standard_Integer ixmin,
const Standard_Integer iymin,
const Standard_Integer izmin,
const Standard_Integer ixmax,
const Standard_Integer iymax,
const Standard_Integer izmax) const
{
gp_Pnt pc;
Standard_Real xc, yc, zc, uc, vc, u1, v1, u2, v2, u3, v3;
Standard_Integer ix, iy, iz;
IntAna2d_AnaIntersection intersector2d;
// Project points of triangle onto the plane
ElSLib::Parameters(plane, p1, u1, v1);
ElSLib::Parameters(plane, p2, u2, v2);
ElSLib::Parameters(plane, p3, u3, v3);
// Make lines of triangle
gp_Pnt2d p2d1(u1, v1), p2d2(u2, v2), p2d3(u3, v3), p2dt((u1+u2+u3)/3.0,(v1+v2+v3)/3.0), p2dc;
gp_Vec2d v2d12(p2d1, p2d2), v2d23(p2d2, p2d3), v2d31(p2d3, p2d1);
gp_Lin2d L1(p2d1, v2d12), L2(p2d2, v2d23), L3(p2d3, v2d31), Lv;
Standard_Real d1 = p2d1.Distance(p2d2) - Precision::Confusion(),
d2 = p2d2.Distance(p2d3) - Precision::Confusion(),
d3 = p2d3.Distance(p2d1) - Precision::Confusion(), dv;
Voxel_DS* ds = (Voxel_DS*) myVoxels;
for (ix = ixmin; ix <= ixmax; ix++)
{
for (iy = iymin; iy <= iymax; iy++)
{
for (iz = izmin; iz <= izmax; iz++)
{
ds->GetCenter(ix, iy, iz, xc, yc, zc);
pc.SetCoord(xc, yc, zc);
if (plane.Distance(pc) < hdiagonal)
{
ElSLib::Parameters(plane, pc, uc, vc);
p2dc.SetCoord(uc, vc);
gp_Vec2d v2dct(p2dc, p2dt);
dv = v2dct.Magnitude() - Precision::Confusion();
Lv.SetLocation(p2dc);
Lv.SetDirection(v2dct);
// Side 1:
if (mayIntersect(p2d1, p2d2, p2dc, p2dt))
{
intersector2d.Perform(Lv, L1);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d1)
{
continue;
}
}
}
// Side 2:
if (mayIntersect(p2d2, p2d3, p2dc, p2dt))
{
intersector2d.Perform(Lv, L2);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d2)
{
continue;
}
}
}
// Side 3:
if (mayIntersect(p2d3, p2d1, p2dc, p2dt))
{
intersector2d.Perform(Lv, L3);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d3)
{
continue;
}
}
}
// Set positive value to this voxel:
switch (myIsBool)
{
case 0:
((Voxel_ColorDS*) myVoxels)->Set(ix, iy, iz, 15);
break;
case 1:
((Voxel_BoolDS*) myVoxels)->Set(ix, iy, iz, Standard_True);
break;
case 2:
{
//((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, Standard_True);
// Check intersection between the triangle & sub-voxels of the voxel.
Standard_Real hdiagonal2 = hdiagonal / 2.0, hdiagonal4 = hdiagonal / 4.0;
for (Standard_Integer i = 0; i < 8; i++)
{
((Voxel_ROctBoolDS*) myVoxels)->GetCenter(ix, iy, iz, i, xc, yc, zc);
pc.SetCoord(xc, yc, zc);
if (plane.Distance(pc) < hdiagonal2)
{
ElSLib::Parameters(plane, pc, uc, vc);
p2dc.SetCoord(uc, vc);
gp_Vec2d v2dct(p2dc, p2dt);
dv = v2dct.Magnitude() - Precision::Confusion();
Lv.SetLocation(p2dc);
Lv.SetDirection(v2dct);
// Side 1:
if (mayIntersect(p2d1, p2d2, p2dc, p2dt))
{
intersector2d.Perform(Lv, L1);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d1)
{
continue;
}
}
}
// Side 2:
if (mayIntersect(p2d2, p2d3, p2dc, p2dt))
{
intersector2d.Perform(Lv, L2);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d2)
{
continue;
}
}
}
// Side 3:
if (mayIntersect(p2d3, p2d1, p2dc, p2dt))
{
intersector2d.Perform(Lv, L3);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d3)
{
continue;
}
}
}
//((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, i, Standard_True);
// Check intersection between the triangle & sub-voxels of the sub-voxel.
for (Standard_Integer j = 0; j < 8; j++)
{
((Voxel_ROctBoolDS*) myVoxels)->GetCenter(ix, iy, iz, i, j, xc, yc, zc);
pc.SetCoord(xc, yc, zc);
if (plane.Distance(pc) < hdiagonal4)
{
ElSLib::Parameters(plane, pc, uc, vc);
p2dc.SetCoord(uc, vc);
gp_Vec2d v2dct(p2dc, p2dt);
dv = v2dct.Magnitude() - Precision::Confusion();
Lv.SetLocation(p2dc);
Lv.SetDirection(v2dct);
// Side 1:
if (mayIntersect(p2d1, p2d2, p2dc, p2dt))
{
intersector2d.Perform(Lv, L1);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d1)
{
continue;
}
}
}
// Side 2:
if (mayIntersect(p2d2, p2d3, p2dc, p2dt))
{
intersector2d.Perform(Lv, L2);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d2)
{
continue;
}
}
}
// Side 3:
if (mayIntersect(p2d3, p2d1, p2dc, p2dt))
{
intersector2d.Perform(Lv, L3);
if (intersector2d.IsDone() && !intersector2d.ParallelElements() && intersector2d.NbPoints())
{
const IntAna2d_IntPoint& i2d = intersector2d.Point(1);
Standard_Real param1 = i2d.ParamOnFirst();
Standard_Real param2 = i2d.ParamOnSecond();
if (param1 > Precision::Confusion() && param1 < dv &&
param2 > Precision::Confusion() && param2 < d3)
{
continue;
}
}
}
((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, i, j, Standard_True);
}
} // End of "Check level 2".
}
} // End of "Check level 1".
break;
}
}
}
}
}
}
}

74
src/Voxel/Voxel_FloatDS.cdl Executable file
View File

@@ -0,0 +1,74 @@
-- File: Voxel_FloatDS.cdl
-- Created: Sun May 15 13:21:34 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class FloatDS from Voxel inherits DS from Voxel
---Purpose: A 3D voxel model keeping a foating-point
-- value for each voxel.
is
Create
---Purpose: An empty constructor.
returns FloatDS from Voxel;
Create(x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: A constructor initializing the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
returns FloatDS from Voxel;
Init(me : in out;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: Initialization of the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
is redefined virtual;
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor of the voxel model.
SetZero(me : in out);
---Purpose: The method sets all values equal to 0 (false) and
-- releases the memory.
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
data : ShortReal from Standard);
---Purpose: Defines a value for voxel with co-ordinates (ix, iy, iz).
-- Initial state of the model is so that all voxels have value 0.0f,
-- and this data doesn't occupy memory.
-- Memory for data is allocating during setting non-zero values.
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns the value of voxel with co-ordinates (ix, iy, iz).
returns ShortReal from Standard;
end FloatDS;

106
src/Voxel/Voxel_FloatDS.cxx Executable file
View File

@@ -0,0 +1,106 @@
// File: Voxel_FloatDS.cxx
// Created: Mon May 15 13:38:43 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_FloatDS.ixx>
#include <stdlib.h>
// Empty constructor
Voxel_FloatDS::Voxel_FloatDS():Voxel_DS()
{
}
// Constructor with intialization.
Voxel_FloatDS::Voxel_FloatDS(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
:Voxel_DS()
{
Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
}
// Initialization.
void Voxel_FloatDS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
Destroy();
Voxel_DS::Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
if (!myNbX || !myNbY || !myNbZ)
return;
Standard_Integer nb_floats = myNbXY * myNbZ;
Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
myData = (Standard_Address) calloc(nb_slices, sizeof(Standard_ShortReal*));
}
// Destructor
void Voxel_FloatDS::Destroy()
{
if (myData)
{
SetZero();
free((Standard_ShortReal**)myData);
myData = 0;
}
}
void Voxel_FloatDS::SetZero()
{
if (myData)
{
Standard_Integer nb_bytes = myNbXY * myNbZ;
Standard_Integer ix = 0, nb_slices = RealToInt(ceil(nb_bytes / 32.0));
for (; ix < nb_slices; ix++)
{
if (((Standard_ShortReal**)myData)[ix])
{
free(((Standard_ShortReal**)myData)[ix]);
((Standard_ShortReal**)myData)[ix] = 0;
}
}
}
}
// Access to the floating-point information attached to a particular voxel:
// Info: (ix >= 0 && ix < theNb_x), etc.
void Voxel_FloatDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_ShortReal data)
{
Standard_Integer ifloat = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ifloat >> 5;
// Allocate the slice if it is not done yet.
if (!((Standard_ShortReal**)myData)[islice])
{
((Standard_ShortReal**)myData)[islice] =
(Standard_ShortReal*) calloc(32/*number of floating values in slice*/, sizeof(Standard_ShortReal));
}
// Index of start-byte of the value within the slice.
Standard_Integer ivalue = ifloat - (islice << 5);
// Value (float)
((Standard_ShortReal*)((Standard_ShortReal**)myData)[islice])[ivalue] = data;
}
Standard_ShortReal Voxel_FloatDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Integer ifloat = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ifloat >> 5;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Standard_ShortReal**)myData)[islice])
return 0.0f;
// Index of start-byte of the value within the slice.
Standard_Integer ivalue = ifloat - (islice << 5);
// Value (floating-point value)
return ((Standard_ShortReal*)((Standard_ShortReal**)myData)[islice])[ivalue];
}

130
src/Voxel/Voxel_OctBoolDS.cdl Executable file
View File

@@ -0,0 +1,130 @@
-- File: Voxel_OctBoolDS.cdl
-- Created: Sun Aug 26 12:21:23 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class OctBoolDS from Voxel inherits DS from Voxel
---Purpose: A 3D voxel model keeping a boolean flag (1 or 0)
-- value for each voxel, and having an opportunity to split each voxel
-- into 8 sub-voxels.
is
Create
---Purpose: An empty constructor.
returns OctBoolDS from Voxel;
Create(x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: A constructor initializing the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
returns OctBoolDS from Voxel;
Init(me : in out;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: Initialization of the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
is redefined virtual;
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor of the voxel model.
SetZero(me : in out);
---Purpose: The method sets all values equal to 0 (false) and
-- releases the memory.
OptimizeMemory(me : in out);
---Purpose: The method searches voxels with equal-value of sub-voxels
-- and removes them (remaining the value for the voxel).
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
data : Boolean from Standard);
---Purpose: Defines a value for voxel with co-ordinates (ix, iy, iz).
-- If the voxel is split into 8 sub-voxels, the split disappears.
-- Initial state of the model is so that all voxels have value 0 (false),
-- and this data doesn't occupy memory.
-- Memory for data is allocating during setting non-zero values (true).
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
ioct : Integer from Standard;
data : Boolean from Standard);
---Purpose: Defines a value for a sub-voxel of a voxel with co-ordinates (ix, iy, iz).
-- If the voxel is not split into 8 sub-voxels yet, this method splits the voxel.
-- Range of sub-voxels is 0 - 7.
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns the value of voxel with co-ordinates (ix, iy, iz).
-- Warning!: the returned value may not coincide with the value of its 8 sub-voxels.
-- Use the method ::IsSplit() to check whether a voxel has sub-voxels.
returns Boolean from Standard;
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
ioct : Integer from Standard)
---Purpose: Returns the value of a sub-voxel of a voxel with co-ordinates (ix, iy, iz).
-- If the voxel is not split, it returns the value of the voxel.
-- Range of sub-voxels is 0 - 7.
returns Boolean from Standard;
IsSplit(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns true if the voxel is split into 8 sub-voxels.
returns Boolean from Standard;
---Category: Private area
-- ============
Split(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
is private;
UnSplit(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
is private;
fields
mySubVoxels : Address from Standard;
end OctBoolDS;

276
src/Voxel/Voxel_OctBoolDS.cxx Executable file
View File

@@ -0,0 +1,276 @@
// File: Voxel_OctBoolDS.cxx
// Created: Mon Aug 27 15:33:27 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_OctBoolDS.ixx>
#include <Voxel_TypeDef.hxx>
#include <stdlib.h>
static Standard_Byte gbits[8] = {1, 2, 4, 8, 16, 32, 64, 128};
static Standard_Byte gnbits[8] = {255-1, 255-2, 255-4, 255-8, 255-16, 255-32, 255-64, 255-128};
static iXYZ xyz;
// Empty constructor
Voxel_OctBoolDS::Voxel_OctBoolDS():Voxel_DS(),mySubVoxels(0)
{
}
// Constructor with intialization.
Voxel_OctBoolDS::Voxel_OctBoolDS(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
:Voxel_DS(),mySubVoxels(0)
{
Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
}
// Initialization.
void Voxel_OctBoolDS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
Destroy();
Voxel_DS::Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
if (!myNbX || !myNbY || !myNbZ)
return;
Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 8.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
myData = (Standard_Address) calloc(nb_slices, sizeof(Standard_Byte*));
}
// Destructor
void Voxel_OctBoolDS::Destroy()
{
if (myData)
{
SetZero();
free((Standard_Byte**)myData);
myData = 0;
if (mySubVoxels)
{
delete (iXYZBool*)mySubVoxels;
mySubVoxels = 0;
}
}
}
void Voxel_OctBoolDS::SetZero()
{
if (myData)
{
Standard_Integer nb_bytes = RealToInt(ceil(myNbXY * myNbZ / 8.0));
Standard_Integer ix = 0, nb_slices = RealToInt(ceil(nb_bytes / 8.0));
for (; ix < nb_slices; ix++)
{
if (((Standard_Byte**)myData)[ix])
{
free(((Standard_Byte**)myData)[ix]);
((Standard_Byte**)myData)[ix] = 0;
}
}
}
if (mySubVoxels)
{
iXYZBool* map = (iXYZBool*) mySubVoxels;
map->Clear();
}
}
// Access to the boolean information attached to a particular voxel:
// Info: (ix >= 0 && ix < theNb_x), etc.
void Voxel_OctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Boolean data)
{
// All 8 sub-voxels have the same value.
// No need anymore to keep them in memory.
if (IsSplit(ix, iy, iz))
{
UnSplit(ix, iy, iz);
}
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 6;
if (!data && !((Standard_Byte**)myData)[islice])
return; // don't allocate a slice of data for setting a 0 value
// Allocate the slice if it is not done yet.
if (!((Standard_Byte**)myData)[islice])
{
((Standard_Byte**)myData)[islice] = (Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte));
}
// Index within 8 bytes of the slice.
Standard_Integer ibit_in_current_slice = ibit - (islice << 6);
Standard_Integer ibyte = ibit_in_current_slice >> 3;
// Value (byte)
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte];
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit_in_current_slice - (ibyte << 3);
// Set data
if (data != ((value & gbits[shift]) ? Standard_True : Standard_False))
{
if (data)
value |= gbits[shift];
else
value &= gnbits[shift];
((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte] = value;
}
}
void Voxel_OctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer ioct, const Standard_Boolean data)
{
// If the voxel is not split yet, do it now.
if (!IsSplit(ix, iy, iz))
{
Split(ix, iy, iz);
}
// Voxel
xyz.ix = ix;
xyz.iy = iy;
xyz.iz = iz;
// Take the value
Standard_Byte value = ((iXYZBool*)mySubVoxels)->Find(xyz);
// Set data
if (data != ((value & gbits[ioct]) ? Standard_True : Standard_False))
{
if (data)
value |= gbits[ioct];
else
value &= gnbits[ioct];
((iXYZBool*)mySubVoxels)->ChangeFind(xyz) = value;
}
}
Standard_Boolean Voxel_OctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 6;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Standard_Byte**)myData)[islice])
return Standard_False;
// Index within 8 bytes of the slice.
Standard_Integer ibit_in_current_slice = ibit - (islice << 6);
Standard_Integer ibyte = ibit_in_current_slice >> 3;
// Value (byte)
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)myData)[islice])[ibyte];
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit_in_current_slice - (ibyte << 3);
return ((value & gbits[shift]) ? Standard_True : Standard_False);
}
Standard_Boolean Voxel_OctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer ioct) const
{
// If the voxel is not split, return the value of the voxel.
if (!IsSplit(ix, iy, iz))
{
return Get(ix, iy, iz);
}
// Voxel
xyz.ix = ix;
xyz.iy = iy;
xyz.iz = iz;
// Take the value
const Standard_Byte value = ((iXYZBool*)mySubVoxels)->Find(xyz);
// Return data
return (value & gbits[ioct]) ? Standard_True : Standard_False;
}
Standard_Boolean Voxel_OctBoolDS::IsSplit(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
if (!mySubVoxels)
return Standard_False;
// Voxel
xyz.ix = ix;
xyz.iy = iy;
xyz.iz = iz;
return ((iXYZBool*)mySubVoxels)->IsBound(xyz);
}
void Voxel_OctBoolDS::Split(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz)
{
// Voxel
xyz.ix = ix;
xyz.iy = iy;
xyz.iz = iz;
if (mySubVoxels)
{
if (!((iXYZBool*)mySubVoxels)->IsBound(xyz))
{
((iXYZBool*)mySubVoxels)->Bind(xyz, 0);
}
}
else
{
mySubVoxels = (Standard_Address) new iXYZBool;
((iXYZBool*)mySubVoxels)->Bind(xyz, 0);
}
}
void Voxel_OctBoolDS::UnSplit(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz)
{
if (!mySubVoxels)
return;
// Voxel
xyz.ix = ix;
xyz.iy = iy;
xyz.iz = iz;
if (((iXYZBool*)mySubVoxels)->IsBound(xyz))
{
((iXYZBool*)mySubVoxels)->UnBind(xyz);
}
}
void Voxel_OctBoolDS::OptimizeMemory()
{
if (!mySubVoxels)
return;
Standard_Byte value;
iXYZBool::Iterator itr(*((iXYZBool*)mySubVoxels));
for (; itr.More(); itr.Next())
{
value = itr.Value();
if (value == 0 || value == 255)
{
xyz = itr.Key();
Set(xyz.ix, xyz.iy, xyz.iz, value ? Standard_True : Standard_False);
UnSplit(xyz.ix, xyz.iy, xyz.iz);
}
}
// If the map is empty, release it.
if (((iXYZBool*)mySubVoxels)->IsEmpty())
{
delete (iXYZBool*)mySubVoxels;
mySubVoxels = 0;
}
}

152
src/Voxel/Voxel_Prs.cdl Executable file
View File

@@ -0,0 +1,152 @@
-- File: Voxel_Prs.cdl
-- Created: Tue May 06 15:41:47 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class Prs from Voxel inherits InteractiveObject from AIS
---Purpose: Interactive object for voxels.
uses
Presentation from Prs3d,
PresentationManager3d from PrsMgr,
Selection from SelectMgr,
Color from Quantity,
HArray1OfColor from Quantity,
HArray1OfReal from TColStd,
VoxelDisplayMode from Voxel,
Triangulation from Poly
is
Create
---Purpose: An empty constructor.
returns mutable Prs from Voxel;
---Category: Set Voxels
-- ==========
SetBoolVoxels(me : mutable;
theVoxels : Address from Standard);
---Purpose: <theVoxels> is a Voxel_BoolDS* object.
SetColorVoxels(me : mutable;
theVoxels : Address from Standard);
---Purpose: <theVoxels> is a Voxel_ColorDS* object.
SetROctBoolVoxels(me : mutable;
theVoxels : Address from Standard);
---Purpose: <theVoxels> is a Voxel_ROctBoolDS* object.
SetTriangulation(me : mutable;
theTriangulation : Triangulation from Poly);
---Purpose: Sets a triangulation for visualization.
---Category: Visual attributes
-- =================
SetDisplayMode(me : mutable;
theMode : VoxelDisplayMode from Voxel);
---Purpose: Sets a display mode for voxels.
SetColor(me : mutable;
theColor : Color from Quantity)
---Purpose: Defines the color of points, quadrangles ... for BoolDS.
is redefined;
SetColors(me : mutable;
theColors : HArray1OfColor from Quantity);
---Purpose: Defines the color of points, quadrangles... for ColorDS.
-- For ColorDS the size of array is 0 .. 15.
-- 0 - means no color, this voxel is not drawn.
SetPointSize(me : mutable;
theSize : Real from Standard);
---Purpose: Defines the size of points for all types of voxels.
SetQuadrangleSize(me : mutable;
theSize : Integer from Standard);
---Purpose: Defines the size of quadrangles in per cents (0 .. 100).
SetTransparency(me : mutable;
theTransparency : Real from Standard)
---Purpose: Defines the transparency value [0 .. 1] for quadrangular visualization.
is redefined;
Highlight(me : mutable;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard);
---Purpose: Highlights a voxel.
-- It doesn't re-computes the whole interactive object,
-- but only marks a voxels as "highlighted".
-- The voxel becomes highlighted on next swapping of buffers.
-- In order to unhighlight a voxel, set ix = iy = iz = -1.
---Category: Compute
-- =======
Compute(me : mutable;
thePresentationManager : PresentationManager3d from PrsMgr;
thePresentation : mutable Presentation from Prs3d;
theMode : Integer from Standard = 0)
is redefined
protected;
ComputeSelection(me : mutable;
theSelection : mutable Selection from SelectMgr;
theMode : Integer from Standard)
is private;
Allocate(me : mutable)
---Purpose: Allocates the data structure of visualization.
is private;
Destroy(me : mutable);
---C++: alias ~
---Purpose: A destructor of presentation data.
SetDegenerateMode(me : mutable;
theDegenerate : Boolean from Standard);
---Purpose: Simplifies visualization of voxels in case of view rotation, panning and zooming.
SetUsageOfGLlists(me : mutable;
theUsage : Boolean from Standard);
---Purpose: GL lists accelerate view rotation, panning and zooming operations, but
-- it takes additional memory...
-- It is up to the user of this interactive object to decide whether
-- he has enough memory and may use GL lists or
-- he is lack of memory and usage of GL lists is not recommended.
-- By default, usage of GL lists is on.
-- Also, as I noticed, the view without GL lists looks more precisely.
SetSmoothPoints(me : mutable;
theSmooth : Boolean from Standard);
---Purpose: Switches visualization of points from smooth to rough.
SetColorRange(me : mutable;
theMinValue : Byte from Standard;
theMaxValue : Byte from Standard);
---Purpose: Defines min-max values for visualization of voxels of ColorDS structure.
-- By default, min value = 1, max value = 15 (all non-zero values).
SetSizeRange(me : mutable;
theDisplayedXMin : Real from Standard;
theDisplayedXMax : Real from Standard;
theDisplayedYMin : Real from Standard;
theDisplayedYMax : Real from Standard;
theDisplayedZMin : Real from Standard;
theDisplayedZMax : Real from Standard);
---Purpose: Defines the displayed area of voxels.
-- By default, the range is equal to the box of voxels (all voxels are displayed).
fields
myVisData : Address from Standard;
end Prs;

292
src/Voxel/Voxel_Prs.cxx Executable file
View File

@@ -0,0 +1,292 @@
// File: Voxel_Prs.cxx
// Created: Mon May 13 12:35:52 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_Prs.ixx>
#include "Voxel_VisData.h"
#include <Prs3d_Root.hxx>
#include <Graphic3d_Group.hxx>
#include <Graphic3d_MaterialAspect.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
Voxel_Prs::Voxel_Prs():AIS_InteractiveObject(PrsMgr_TOP_AllView),myVisData(0)
{
}
void Voxel_Prs::SetBoolVoxels(const Standard_Address theVoxels)
{
Allocate();
((Voxel_VisData*)myVisData)->myBoolVoxels = (Voxel_BoolDS*) theVoxels;
}
void Voxel_Prs::SetColorVoxels(const Standard_Address theVoxels)
{
Allocate();
((Voxel_VisData*)myVisData)->myColorVoxels = (Voxel_ColorDS*) theVoxels;
}
void Voxel_Prs::SetROctBoolVoxels(const Standard_Address theVoxels)
{
Allocate();
((Voxel_VisData*)myVisData)->myROctBoolVoxels = (Voxel_ROctBoolDS*) theVoxels;
}
void Voxel_Prs::SetTriangulation(const Handle(Poly_Triangulation)& theTriangulation)
{
Allocate();
((Voxel_VisData*)myVisData)->myTriangulation = theTriangulation;
}
void Voxel_Prs::SetColor(const Quantity_Color& theColor)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myColor = theColor;
}
void Voxel_Prs::SetPointSize(const Standard_Real theSize)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myPointSize = theSize;
}
void Voxel_Prs::SetQuadrangleSize(const Standard_Integer theSize)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myQuadrangleSize = theSize;
}
void Voxel_Prs::SetColors(const Handle(Quantity_HArray1OfColor)& theColors)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myColors = theColors;
}
void Voxel_Prs::SetDisplayMode(const Voxel_VoxelDisplayMode theMode)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myDisplayMode = theMode;
}
void Voxel_Prs::SetTransparency(const Standard_Real theTransparency)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myTransparency = theTransparency;
}
static void setMaterial(const Handle(Graphic3d_Group)& G,
const Quantity_Color& C,
const Standard_Real T)
{
Graphic3d_MaterialAspect material(Graphic3d_NOM_PLASTIC);
material.SetColor(C);
material.SetTransparency(T);
Handle(Graphic3d_AspectFillArea3d) aspect =
new Graphic3d_AspectFillArea3d(Aspect_IS_SOLID, C, C, Aspect_TOL_SOLID, 1, material, material);
aspect->SetDistinguishOff();
aspect->SetEdgeOff();
aspect->SetTextureMapOff();
G->SetPrimitivesAspect(aspect);
}
void Voxel_Prs::Compute(const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
const Handle(Prs3d_Presentation)& thePresentation,
const Standard_Integer /*theMode*/)
{
thePresentation->Clear();
if (!myVisData)
return;
if (((Voxel_VisData*)myVisData)->myBoolVoxels)
{
// Reset GL lists.
// BoolDS
((Voxel_VisData*)myVisData)->myDisplay.myBoolPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsFirst = 1;
}
if (((Voxel_VisData*)myVisData)->myColorVoxels)
{
// Reset GL lists.
// ColorDS
((Voxel_VisData*)myVisData)->myDisplay.myColorPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsFirst = 1;
}
if (((Voxel_VisData*)myVisData)->myROctBoolVoxels)
{
// Reset GL lists.
// ROctBoolDS
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsFirst = 1;
}
// Set data to the user draw function.
Handle(Graphic3d_Group) G = Prs3d_Root::CurrentGroup(thePresentation);
if (((Voxel_VisData*)myVisData)->myDisplay.myDisplayMode == Voxel_VDM_BOXES ||
((Voxel_VisData*)myVisData)->myDisplay.myDisplayMode == Voxel_VDM_NEARESTBOXES ||
!((Voxel_VisData*)myVisData)->myTriangulation.IsNull())
{
setMaterial(G, ((Voxel_VisData*)myVisData)->myDisplay.myColor,
((Voxel_VisData*)myVisData)->myDisplay.myTransparency);
// Reset normals of triangulation
if (!((Voxel_VisData*)myVisData)->myTriangulation.IsNull())
{
((Voxel_VisData*)myVisData)->myNormalsOfNodes.Nullify();
((Voxel_VisData*)myVisData)->myDisplay.myTriangulationList = -1;
}
}
G->UserDraw(myVisData);
}
void Voxel_Prs::ComputeSelection(const Handle(SelectMgr_Selection)& /*theSelection*/,
const Standard_Integer /*theMode*/)
{
}
// Destructor
void Voxel_Prs::Destroy()
{
if (myVisData)
{
delete (Voxel_VisData*) myVisData;
myVisData = 0;
}
}
void Voxel_Prs::Allocate()
{
if (!myVisData)
{
myVisData = new Voxel_VisData;
((Voxel_VisData*)myVisData)->myBoolVoxels = 0;
((Voxel_VisData*)myVisData)->myColorVoxels = 0;
((Voxel_VisData*)myVisData)->myROctBoolVoxels = 0;
// Points
// BoolDS
((Voxel_VisData*)myVisData)->myDisplay.myBoolPointsList = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[0] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[1] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[2] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[3] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[4] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[5] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsList[6] = -1;
// ROctBoolDS
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolPointsList = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[0] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[1] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[2] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[3] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[4] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[5] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsList[6] = -1;
// ColorDS:
((Voxel_VisData*)myVisData)->myDisplay.myColorPointsList = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[0] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[1] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[2] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[3] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[4] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[5] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsList[6] = -1;
((Voxel_VisData*)myVisData)->myDisplay.myColorMinValue = 1;
((Voxel_VisData*)myVisData)->myDisplay.myColorMaxValue = 15;
((Voxel_VisData*)myVisData)->myDisplay.myPointSize = 1.0;
((Voxel_VisData*)myVisData)->myDisplay.myQuadrangleSize = 100;
((Voxel_VisData*)myVisData)->myDisplay.myTransparency = 0.0;
((Voxel_VisData*)myVisData)->myDisplay.myDegenerateMode = 0;
((Voxel_VisData*)myVisData)->myDisplay.myUsageOfGLlists = 1;
((Voxel_VisData*)myVisData)->myDisplay.mySmoothPoints = 0;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedXMin = -DBL_MAX;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedXMax = DBL_MAX;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedYMin = -DBL_MAX;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedYMax = DBL_MAX;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedZMin = -DBL_MAX;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedZMax = DBL_MAX;
((Voxel_VisData*)myVisData)->myDisplay.myTriangulationList = -1;
((Voxel_VisData*)myVisData)->myDisplay.myHighlightx = -1;
((Voxel_VisData*)myVisData)->myDisplay.myHighlighty = -1;
((Voxel_VisData*)myVisData)->myDisplay.myHighlightz = -1;
}
}
void Voxel_Prs::SetDegenerateMode(const Standard_Boolean theDegenerate)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myDegenerateMode = (theDegenerate == Standard_True);
}
void Voxel_Prs::SetUsageOfGLlists(const Standard_Boolean theUsage)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myUsageOfGLlists = (theUsage == Standard_True);
}
void Voxel_Prs::SetSmoothPoints(const Standard_Boolean theSmooth)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.mySmoothPoints = (theSmooth == Standard_True);
}
void Voxel_Prs::SetColorRange(const Standard_Byte theMinValue,
const Standard_Byte theMaxValue)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myColorMinValue = theMinValue;
((Voxel_VisData*)myVisData)->myDisplay.myColorMaxValue = theMaxValue;
// Reset GL lists
((Voxel_VisData*)myVisData)->myDisplay.myColorPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsFirst = 1;
}
void Voxel_Prs::SetSizeRange(const Standard_Real theDisplayedXMin,
const Standard_Real theDisplayedXMax,
const Standard_Real theDisplayedYMin,
const Standard_Real theDisplayedYMax,
const Standard_Real theDisplayedZMin,
const Standard_Real theDisplayedZMax)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedXMin = theDisplayedXMin;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedXMax = theDisplayedXMax;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedYMin = theDisplayedYMin;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedYMax = theDisplayedYMax;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedZMin = theDisplayedZMin;
((Voxel_VisData*)myVisData)->myDisplay.myDisplayedZMax = theDisplayedZMax;
// Reset GL lists
((Voxel_VisData*)myVisData)->myDisplay.myBoolPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myBoolNearestPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myColorPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myColorNearestPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolPointsFirst = 1;
((Voxel_VisData*)myVisData)->myDisplay.myROctBoolNearestPointsFirst = 1;
}
void Voxel_Prs::Highlight(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz)
{
Allocate();
((Voxel_VisData*)myVisData)->myDisplay.myHighlightx = ix;
((Voxel_VisData*)myVisData)->myDisplay.myHighlighty = iy;
((Voxel_VisData*)myVisData)->myDisplay.myHighlightz = iz;
}

177
src/Voxel/Voxel_ROctBoolDS.cdl Executable file
View File

@@ -0,0 +1,177 @@
-- File: Voxel_ROctBoolDS.cdl
-- Created: Sun Sep 01 10:36:25 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class ROctBoolDS from Voxel inherits DS from Voxel
---Purpose: A 3D voxel model keeping a boolean flag (1 or 0)
-- value for each voxel, and having an opportunity to split each voxel
-- into 8 sub-voxels recursively.
is
Create
---Purpose: An empty constructor.
returns ROctBoolDS from Voxel;
Create(x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: A constructor initializing the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
returns ROctBoolDS from Voxel;
Init(me : in out;
x : Real from Standard;
y : Real from Standard;
z : Real from Standard;
x_len : Real from Standard;
y_len : Real from Standard;
z_len : Real from Standard;
nb_x : Integer from Standard;
nb_y : Integer from Standard;
nb_z : Integer from Standard)
---Purpose: Initialization of the voxel model.
-- (x, y, z) - the start point of the box.
-- (x_len, y_len, z_len) - lengths in x, y and z directions along axes of a co-ordinate system.
-- (nb_x, nb_y, nb_z) - number of splits (voxels) along x, y and z directions.
is redefined virtual;
Destroy(me : in out);
---C++: alias ~
---Purpose: A destructor of the voxel model.
SetZero(me : in out);
---Purpose: The method sets all values equal to 0 (false) and
-- releases the memory.
OptimizeMemory(me : in out);
---Purpose: The method searches voxels with equal-value of sub-voxels
-- and removes them (remaining the value for the voxel).
---Category: Set
-- ===
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
data : Boolean from Standard);
---Purpose: Defines a value for voxel with co-ordinates (ix, iy, iz).
-- If the voxel is split into 8 sub-voxels, the split disappears.
-- Initial state of the model is so that all voxels have value 0 (false),
-- and this data doesn't occupy memory.
-- Memory for data is allocating during setting non-zero values (true).
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
ioct1 : Integer from Standard;
data : Boolean from Standard);
---Purpose: Defines a value for a sub-voxel of a voxel with co-ordinates (ix, iy, iz).
-- If the voxel is not split into 8 sub-voxels yet, this method splits the voxel.
-- Range of sub-voxels is 0 - 7.
Set(me : in out;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
ioct1 : Integer from Standard;
ioct2 : Integer from Standard;
data : Boolean from Standard);
---Purpose: Defines a value for a sub-voxel of a sub-voxel of a voxel with co-ordinates (ix, iy, iz).
-- If the voxel is not split into 8 sub-voxels yet, this method splits the voxel.
-- Range of sub-voxels is 0 - 7.
---Category: Get
-- ===
IsSplit(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns true if the voxel is split into 8 sub-voxels.
returns Boolean from Standard;
Deepness(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns the deepness of splits of a voxel.
-- 0 - no splits (::IsSplit() being called would return false).
-- 1 - the voxel is split into 8 sub-voxels.
-- 2 - the voxels is split into 8 sub-voxels,
-- and each of the sub-voxels is split into 8 sub-sub-voxels.
-- 3 - ...
returns Integer from Standard;
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard)
---Purpose: Returns the value of voxel with co-ordinates (ix, iy, iz).
-- Warning!: the returned value may not coincide with the value of its 8 sub-voxels.
-- Use the method ::IsSplit() to check whether a voxel has sub-voxels.
returns Boolean from Standard;
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
ioct1 : Integer from Standard)
---Purpose: Returns the value of a sub-voxel of a voxel with co-ordinates (ix, iy, iz).
-- If the voxel is not split, it returns the value of the voxel.
-- Range of sub-voxels is 0 - 7.
returns Boolean from Standard;
Get(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
ioct1 : Integer from Standard;
ioct2 : Integer from Standard)
---Purpose: Returns the value of a sub-voxel of a sub-voxel of a voxel with co-ordinates (ix, iy, iz).
-- If the voxel is not split, it returns the value of the voxel.
-- Range of sub-voxels is 0 - 7.
returns Boolean from Standard;
---Category: Services
-- ========
GetCenter(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
i : Integer from Standard;
xc : out Real from Standard;
yc : out Real from Standard;
zc : out Real from Standard);
---Purpose: Returns the center point of a sub-voxel with co-ordinates (ix, iy, iz, i).
GetCenter(me;
ix : Integer from Standard;
iy : Integer from Standard;
iz : Integer from Standard;
i : Integer from Standard;
j : Integer from Standard;
xc : out Real from Standard;
yc : out Real from Standard;
zc : out Real from Standard);
---Purpose: Returns the center point of a sub-voxel with co-ordinates (ix, iy, iz, i, j).
end ROctBoolDS;

717
src/Voxel/Voxel_ROctBoolDS.cxx Executable file
View File

@@ -0,0 +1,717 @@
// File: Voxel_ROctBoolDS.cxx
// Created: Mon Sep 01 11:00:08 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_ROctBoolDS.ixx>
#include <Voxel_SplitData.hxx>
#include <stdlib.h>
static Standard_Byte gbits[8] = {1, 2, 4, 8, 16, 32, 64, 128};
static Standard_Byte gnbits[8] = {255-1, 255-2, 255-4, 255-8, 255-16, 255-32, 255-64, 255-128};
/* Data structure of the ROctBoolDS
SplitData: 1 byte (8 values)
(a) SplitData: 8 bytes (64 values)
(b) SplitData: 64 bytes (512 values)
(c) SplitData: ...
(d) SplitData: ...
*/
// Empty constructor
Voxel_ROctBoolDS::Voxel_ROctBoolDS():Voxel_DS()
{
}
// Constructor with intialization.
Voxel_ROctBoolDS::Voxel_ROctBoolDS(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
:Voxel_DS()
{
Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
}
// Initialization.
void Voxel_ROctBoolDS::Init(const Standard_Real x, const Standard_Real y, const Standard_Real z,
const Standard_Real xlen, const Standard_Real ylen, const Standard_Real zlen,
const Standard_Integer nbx, const Standard_Integer nby, const Standard_Integer nbz)
{
Destroy();
Voxel_DS::Init(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
if (!myNbX || !myNbY || !myNbZ)
return;
Standard_Integer nb_slices = RealToInt(ceil(myNbXY * myNbZ / 8.0));
myData = (Standard_Address) calloc(nb_slices, sizeof(Voxel_SplitData*));
}
// Destructor
void Voxel_ROctBoolDS::Destroy()
{
if (myData)
{
SetZero();
free((Voxel_SplitData**)myData);
myData = 0;
}
}
// A recursive method of deletion of data.
static void SetZeroSplitData(Voxel_SplitData* data)
{
// Values:
free((Standard_Byte*) data->GetValues());
data->GetValues() = 0;
if (data->GetSplitData())
{
SetZeroSplitData((Voxel_SplitData*) data->GetSplitData());
}
delete (data);
data = 0;
}
void Voxel_ROctBoolDS::SetZero()
{
if (myData)
{
Standard_Integer ix = 0, nb_slices = RealToInt(ceil(myNbXY * myNbZ / 8.0));
for (; ix < nb_slices; ix++)
{
if (((Voxel_SplitData**)myData)[ix])
{
SetZeroSplitData((Voxel_SplitData*)((Voxel_SplitData**)myData)[ix]);
}
}
}
}
// Access to the boolean information attached to a particular voxel:
// Info: (ix >= 0 && ix < theNb_x), etc.
void Voxel_ROctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Boolean data)
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
if (!data && !((Voxel_SplitData**)myData)[islice])
return; // don't allocate a slice of data for setting a 0 value
// Allocate the slice if it is not done yet.
if (!((Voxel_SplitData**)myData)[islice])
{
((Voxel_SplitData**)myData)[islice] = (Voxel_SplitData*) new Voxel_SplitData;
// Values:
((Voxel_SplitData**)myData)[islice]->GetValues() =
(Standard_Byte*) calloc(1/*one byte: 8 1-bit values*/, sizeof(Standard_Byte));
// Sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData() = 0;
}
// Value
Standard_Byte value = *((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues());
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit - (islice << 3);
// Set data
if (data != ((value & gbits[shift]) ? Standard_True : Standard_False))
{
if (data)
value |= gbits[shift];
else
value &= gnbits[shift];
*((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues()) = value;
}
// Set the same value to sub-voxels.
if (((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
{
// Get sub-value
Standard_Byte subvalue = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[shift];
// Set sub-value
if (subvalue != (data ? 255 : 0))
{
subvalue = data ? 255 : 0;
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[shift] = subvalue;
}
// Set the same value to sub-sub-voxels.
if (((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())
{
// Start index of 64-bit value (index of byte of sub-sub-voxel).
Standard_Integer ibyte2 = (shift << 3);
for (Standard_Integer ioct2 = 0; ioct2 < 8; ioct2++)
{
// Get sub-sub-value
Standard_Byte subsubvalue = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2 + ioct2];
// Set sub-sub-value
if (subsubvalue != (data ? 255 : 0))
{
subsubvalue = data ? 255 : 0;
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2 + ioct2] = subsubvalue;
}
}
}
}
}
void Voxel_ROctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer ioct1, const Standard_Boolean data)
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
if (!data && !((Voxel_SplitData**)myData)[islice])
return; // don't allocate a slice of data for setting a 0 value
// Allocate the slice if it is not done yet.
if (!((Voxel_SplitData**)myData)[islice])
{
((Voxel_SplitData**)myData)[islice] = (Voxel_SplitData*) new Voxel_SplitData;
// Values:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues() =
(Standard_Byte*) calloc(1/*one byte: 8 1-bit values*/, sizeof(Standard_Byte));
// Sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData() = 0;
}
// Check sub-voxels of the first level
if (!((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
{
// Sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData() = (Voxel_SplitData*) new Voxel_SplitData;
// Value of sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues() =
(Standard_Byte*) calloc(8/*eight bytes: 8 sub-voxels for each voxel*/, sizeof(Standard_Byte));
// Set parent value
Standard_Byte parent_value = *((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues());
if (parent_value)
{
for (Standard_Integer shift = 0; shift < 8; shift++)
{
if ((parent_value & gbits[shift]) ? Standard_True : Standard_False)
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[shift] = 255;
}
else
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[shift] = 0;
}
}
}
// Sub-sub-voxels
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData() = 0;
}
// Index of sub-voxel corresponding to ioct1: 8 voxels correspond to 64 sub-voxels.
Standard_Integer ibyte = ibit - (islice << 3);
// Value
Standard_Byte value = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[ibyte];
// Set data
if (data != ((value & gbits[ioct1]) ? Standard_True : Standard_False))
{
if (data)
value |= gbits[ioct1];
else
value &= gnbits[ioct1];
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[ibyte] = value;
}
// Set the same value to sub-voxels.
if (((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())
{
// Start index of 64-bit value (index of byte of sub-sub-voxel).
Standard_Integer ibyte2 = (ibyte << 3) + ioct1;
// Get sub-sub-value
Standard_Byte subsubvalue = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2];
// Set sub-sub-value
if (subsubvalue != (data ? 255 : 0))
{
subsubvalue = data ? 255 : 0;
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2] = subsubvalue;
}
}
}
void Voxel_ROctBoolDS::Set(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer ioct1, const Standard_Integer ioct2, const Standard_Boolean data)
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
if (!data && !((Voxel_SplitData**)myData)[islice])
return; // don't allocate a slice of data for setting a 0 value
// Allocate the slice if it is not done yet.
if (!((Voxel_SplitData**)myData)[islice])
{
((Voxel_SplitData**)myData)[islice] = (Voxel_SplitData*) new Voxel_SplitData;
// Values:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues() =
(Standard_Byte*) calloc(1/*one byte: 8 1-bit values*/, sizeof(Standard_Byte));
// Sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData() = 0;
}
// Check sub-voxels of the first level
if (!((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
{
// Sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData() = (Voxel_SplitData*) new Voxel_SplitData;
// Value of sub-voxels:
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues() =
(Standard_Byte*) calloc(8/*eight bytes: 8 sub-voxels for each voxel*/, sizeof(Standard_Byte));
// Set parent value
Standard_Byte parent_value = *((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues());
if (parent_value)
{
for (Standard_Integer shift = 0; shift < 8; shift++)
{
if ((parent_value & gbits[shift]) ? Standard_True : Standard_False)
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[shift] = 255;
}
else
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[shift] = 0;
}
}
}
// Sub-sub-voxels
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData() = 0;
}
// Check sub-voxels of the second level
if (!((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())
{
// Sub-voxels 2:
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData() =
(Voxel_SplitData*) new Voxel_SplitData;
// Value of sub-voxels 2:
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues() =
(Standard_Byte*) calloc(64/*sixty four bytes: 8 sub-voxels for each sub-voxel for each voxel*/,
sizeof(Standard_Byte));
// Set parent value
for (Standard_Integer ibyte1 = 0; ibyte1 < 8; ibyte1++)
{
Standard_Byte parent_value = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[ibyte1];
if (parent_value)
{
Standard_Integer ibyte2 = (ibyte1 << 3);
for (Standard_Integer shift = 0; shift < 8; shift++)
{
if ((parent_value & gbits[shift]) ? Standard_True : Standard_False)
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2 + shift] = 255;
}
else
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2 + shift] = 0;
}
}
}
}
// Sub-sub-sub-voxels
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetSplitData() = 0;
}
// Index of sub-voxel corresponding to ioct1: 8 voxels correspond to 64 sub-voxels.
Standard_Integer ibyte1 = ibit - (islice << 3); // imdex of byte of 8-byte value (sub-voxel 1).
Standard_Integer ibyte2 = (ibyte1 << 3) + ioct1; // index of byte of 64-byte value (sub-voxel 2)
// Value
Standard_Byte value = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2];
// Set data
if (data != ((value & gbits[ioct2]) ? Standard_True : Standard_False))
{
if (data)
value |= gbits[ioct2];
else
value &= gnbits[ioct2];
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2] = value;
}
}
Standard_Boolean Voxel_ROctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Voxel_SplitData**)myData)[islice])
return Standard_False;
// Value (byte)
Standard_Byte value = *((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues());
// Position of data in the 8 bit-"value".
Standard_Integer shift = ibit - (islice << 3);
return ((value & gbits[shift]) ? Standard_True : Standard_False);
}
Standard_Boolean Voxel_ROctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer ioct1) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Voxel_SplitData**)myData)[islice])
return Standard_False;
// If the voxel is not split, return the value of the voxel.
if (!((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
return Get(ix, iy, iz);
// Index of sub-voxel corresponding to ioct1: 8 voxels correspond to 64 sub-voxels.
Standard_Integer ibyte = ibit - (islice << 3);
// Value
Standard_Byte value = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[ibyte];
return ((value & gbits[ioct1]) ? Standard_True : Standard_False);
}
Standard_Boolean Voxel_ROctBoolDS::Get(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer ioct1, const Standard_Integer ioct2) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
// If the slice of data is not allocated, it means that its values are 0.
if (!((Voxel_SplitData**)myData)[islice])
return Standard_False;
// If the voxel is not split, return the value of the voxel.
if (!((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
return Get(ix, iy, iz);
// If the split voxel (sub-voxel 1) is not split, return the value of the sub-voxel 1.
if (!((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())
return Get(ix, iy, iz, ioct1);
// Index of sub-voxel corresponding to ioct1: 8 voxels correspond to 64 sub-voxels.
Standard_Integer ibyte1 = ibit - (islice << 3); // index of byte of 8-byte value (sub-voxel 1).
Standard_Integer ibyte2 = (ibyte1 << 3) + ioct1; // index of byte of 64-byte value (sub-voxel 2)
// Value
Standard_Byte value = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2];
return ((value & gbits[ioct2]) ? Standard_True : Standard_False);
}
Standard_Boolean Voxel_ROctBoolDS::IsSplit(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
// If the voxel has no value, it is not split.
if (!((Voxel_SplitData**)myData)[islice])
return Standard_False;
// Check existence of sub-voxels
if (((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
return Standard_True;
return Standard_False;
}
Standard_Integer Voxel_ROctBoolDS::Deepness(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz) const
{
Standard_Integer ibit = ix + myNbX * iy + myNbXY * iz;
Standard_Integer islice = ibit >> 3;
// If the voxel has no value, it is not split.
if (!((Voxel_SplitData**)myData)[islice])
return 0;
// Test deepness.
if (((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
{
if (((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())
{
return 2;
}
else
{
return 1;
}
}
return 0;
}
void Voxel_ROctBoolDS::OptimizeMemory()
{
// Iterate the array of voxels checking coincidence of values of sub-voxels.
Standard_Integer islice = 0, nb_slices = RealToInt(ceil(myNbXY * myNbZ / 8.0));
for (; islice < nb_slices; islice++)
{
if (!((Voxel_SplitData**)myData)[islice])
continue;
if (((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())
{
Standard_Boolean suppress = Standard_False;
// Second level of sub-voxels
if (((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())
{
suppress = Standard_False;
Standard_Byte value1 = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[0];
if (value1 == 0 || value1 == 255)
{
suppress = Standard_True;
for (Standard_Integer ibyte2 = 1; ibyte2 < 64; ibyte2++)
{
Standard_Byte value2 = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData())->GetValues())[ibyte2];
if (value2 != value1)
{
suppress = Standard_False;
break;
}
}
}
if (suppress)
{
SetZeroSplitData((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData());
((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetSplitData() = 0;
// Set value to upper level
for (Standard_Integer ibyte1 = 0; ibyte1 < 8; ibyte1++)
{
((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[ibyte1] = value1;
}
}
else
{
// If we don't suppress sub-sub-voxels, we don't touch sub-voxels.
continue;
}
}
// First level of sub-voxels
suppress = Standard_False;
Standard_Byte value1 = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[0];
if (value1 == 0 || value1 == 255)
{
suppress = Standard_True;
for (Standard_Integer ibyte1 = 1; ibyte1 < 8; ibyte1++)
{
Standard_Byte value2 = ((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData())->GetValues())[ibyte1];
if (value2 != value1)
{
suppress = Standard_False;
break;
}
}
}
if (suppress)
{
SetZeroSplitData((Voxel_SplitData*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData());
((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetSplitData() = 0;
// Set value to upper level
*((Standard_Byte*)((Voxel_SplitData*)((Voxel_SplitData**)myData)[islice])->GetValues()) = value1;
}
}
}
}
void Voxel_ROctBoolDS::GetCenter(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer i,
Standard_Real& xc, Standard_Real& yc, Standard_Real& zc) const
{
xc = myX + ix * myDX;
yc = myY + iy * myDY;
zc = myZ + iz * myDZ;
switch (i)
{
case 0:
{
xc += 0.5 * myHalfDX;
yc += 0.5 * myHalfDY;
zc += 0.5 * myHalfDZ;
break;
}
case 1:
{
xc += 1.5 * myHalfDX;
yc += 0.5 * myHalfDY;
zc += 0.5 * myHalfDZ;
break;
}
case 2:
{
xc += 0.5 * myHalfDX;
yc += 1.5 * myHalfDY;
zc += 0.5 * myHalfDZ;
break;
}
case 3:
{
xc += 1.5 * myHalfDX;
yc += 1.5 * myHalfDY;
zc += 0.5 * myHalfDZ;
break;
}
case 4:
{
xc += 0.5 * myHalfDX;
yc += 0.5 * myHalfDY;
zc += 1.5 * myHalfDZ;
break;
}
case 5:
{
xc += 1.5 * myHalfDX;
yc += 0.5 * myHalfDY;
zc += 1.5 * myHalfDZ;
break;
}
case 6:
{
xc += 0.5 * myHalfDX;
yc += 1.5 * myHalfDY;
zc += 1.5 * myHalfDZ;
break;
}
case 7:
{
xc += 1.5 * myHalfDX;
yc += 1.5 * myHalfDY;
zc += 1.5 * myHalfDZ;
break;
}
}
}
void Voxel_ROctBoolDS::GetCenter(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer i, const Standard_Integer j,
Standard_Real& xc, Standard_Real& yc, Standard_Real& zc) const
{
xc = myX + ix * myDX;
yc = myY + iy * myDY;
zc = myZ + iz * myDZ;
switch (i)
{
case 0:
{
break;
}
case 1:
{
xc += myHalfDX;
break;
}
case 2:
{
yc += myHalfDY;
break;
}
case 3:
{
xc += myHalfDX;
yc += myHalfDY;
break;
}
case 4:
{
zc += myHalfDZ;
break;
}
case 5:
{
xc += myHalfDX;
zc += myHalfDZ;
break;
}
case 6:
{
yc += myHalfDY;
zc += myHalfDZ;
break;
}
case 7:
{
xc += myHalfDX;
yc += myHalfDY;
zc += myHalfDZ;
break;
}
}
switch (j)
{
case 0:
{
xc += 0.25 * myHalfDX;
yc += 0.25 * myHalfDY;
zc += 0.25 * myHalfDZ;
break;
}
case 1:
{
xc += 0.75 * myHalfDX;
yc += 0.25 * myHalfDY;
zc += 0.25 * myHalfDZ;
break;
}
case 2:
{
xc += 0.25 * myHalfDX;
yc += 0.75 * myHalfDY;
zc += 0.25 * myHalfDZ;
break;
}
case 3:
{
xc += 0.75 * myHalfDX;
yc += 0.75 * myHalfDY;
zc += 0.25 * myHalfDZ;
break;
}
case 4:
{
xc += 0.25 * myHalfDX;
yc += 0.25 * myHalfDY;
zc += 0.75 * myHalfDZ;
break;
}
case 5:
{
xc += 0.75 * myHalfDX;
yc += 0.25 * myHalfDY;
zc += 0.75 * myHalfDZ;
break;
}
case 6:
{
xc += 0.25 * myHalfDX;
yc += 0.75 * myHalfDY;
zc += 0.75 * myHalfDZ;
break;
}
case 7:
{
xc += 0.75 * myHalfDX;
yc += 0.75 * myHalfDY;
zc += 0.75 * myHalfDZ;
break;
}
}
}

101
src/Voxel/Voxel_Reader.cdl Executable file
View File

@@ -0,0 +1,101 @@
-- File: Voxel_Reader.cdl
-- Created: Wed Aug 28 17:23:34 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class Reader from Voxel
---Purpose: Reads a cube of voxels from disk.
-- Beware, a caller of the reader is responsible for deletion of the read voxels.
uses
BoolDS from Voxel,
ColorDS from Voxel,
FloatDS from Voxel,
ExtendedString from TCollection
is
Create
---Purpose: An empty constructor.
returns Reader from Voxel;
Read(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads the voxels from disk
returns Boolean from Standard;
IsBoolVoxels(me)
---Purpose: Informs the user about the type of voxels he has read.
returns Boolean from Standard;
IsColorVoxels(me)
---Purpose: Informs the user about the type of voxels he has read.
returns Boolean from Standard;
IsFloatVoxels(me)
---Purpose: Informs the user about the type of voxels he has read.
returns Boolean from Standard;
GetBoolVoxels(me)
---Purpose: Returns a pointer to the read 1bit voxels.
returns Address from Standard;
GetColorVoxels(me)
---Purpose: Returns a pointer to the read 4bit voxels.
returns Address from Standard;
GetFloatVoxels(me)
---Purpose: Returns a pointer to the read 4bytes voxels.
returns Address from Standard;
---Private area
-- ============
ReadBoolAsciiVoxels(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads 1bit voxels from disk in ASCII format.
returns Boolean from Standard
is private;
ReadColorAsciiVoxels(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads 4bit voxels from disk in ASCII format.
returns Boolean from Standard
is private;
ReadFloatAsciiVoxels(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads 4bytes voxels from disk in ASCII format.
returns Boolean from Standard
is private;
ReadBoolBinaryVoxels(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads 1bit voxels from disk in BINARY format.
returns Boolean from Standard
is private;
ReadColorBinaryVoxels(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads 4bit voxels from disk in BINARY format.
returns Boolean from Standard
is private;
ReadFloatBinaryVoxels(me : in out;
file : ExtendedString from TCollection)
---Purpose: Reads 4bytes voxels from disk in BINARY format.
returns Boolean from Standard
is private;
fields
myBoolVoxels : Address from Standard;
myColorVoxels : Address from Standard;
myFloatVoxels : Address from Standard;
end Reader;

527
src/Voxel/Voxel_Reader.cxx Executable file
View File

@@ -0,0 +1,527 @@
// File: Voxel_Reader.cxx
// Created: Wed Aug 28 19:34:33 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_Reader.ixx>
#include <Voxel_BoolDS.hxx>
#include <Voxel_ColorDS.hxx>
#include <Voxel_FloatDS.hxx>
#include <Voxel_VoxelFileFormat.hxx>
#include <Voxel_TypeDef.hxx>
#include <TCollection_AsciiString.hxx>
Voxel_Reader::Voxel_Reader():myBoolVoxels(0),myColorVoxels(0),myFloatVoxels(0)
{
}
Standard_Boolean Voxel_Reader::Read(const TCollection_ExtendedString& file)
{
// Open file in ASCII mode to read header
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
if (!f)
return Standard_False;
// Read the header
Standard_Byte type; // 0 - bool, 1 - color, 2 - float
Voxel_VoxelFileFormat format;
Standard_Character svoxels[8], sformat[8], stype[8];
fscanf(f, "%s %s %s\n", svoxels, sformat, stype);
fclose(f);
// Take format, type of voxels.
// Voxels
if (strcmp(svoxels, VOXELS))
return Standard_False;
// Format
if (strcmp(sformat, ASCII) == 0)
format = Voxel_VFF_ASCII;
else if (strcmp(sformat, BINARY) == 0)
format = Voxel_VFF_BINARY;
else
return Standard_False;
// Type of voxels
if (strcmp(stype, BOOL) == 0)
type = 0;
else if (strcmp(stype, COLOR) == 0)
type = 1;
else if (strcmp(stype, FLOAT) == 0)
type = 2;
else
return Standard_False;
// Read the rest
switch (format)
{
case Voxel_VFF_ASCII:
{
switch (type)
{
case 0:
return ReadBoolAsciiVoxels(file);
case 1:
return ReadColorAsciiVoxels(file);
case 2:
return ReadFloatAsciiVoxels(file);
}
}
case Voxel_VFF_BINARY:
{
switch (type)
{
case 0:
return ReadBoolBinaryVoxels(file);
case 1:
return ReadColorBinaryVoxels(file);
case 2:
return ReadFloatBinaryVoxels(file);
}
}
}
// No voxels or no format description is found:
return Standard_False;
}
Standard_Boolean Voxel_Reader::IsBoolVoxels() const
{
return (myBoolVoxels != 0);
}
Standard_Boolean Voxel_Reader::IsColorVoxels() const
{
return (myColorVoxels != 0);
}
Standard_Boolean Voxel_Reader::IsFloatVoxels() const
{
return (myFloatVoxels != 0);
}
Standard_Address Voxel_Reader::GetBoolVoxels() const
{
return myBoolVoxels;
}
Standard_Address Voxel_Reader::GetColorVoxels() const
{
return myColorVoxels;
}
Standard_Address Voxel_Reader::GetFloatVoxels() const
{
return myFloatVoxels;
}
static Standard_Boolean has_slice(const Standard_CString line)
{
Standard_Integer i = 0, nb_spaces = 0;
while (line[i] != '\0')
{
if (line[i] == ' ')
nb_spaces++;
i++;
}
return (nb_spaces == 2);
}
Standard_Boolean Voxel_Reader::ReadBoolAsciiVoxels(const TCollection_ExtendedString& file)
{
// Open file for reading
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
if (!f)
return Standard_False;
Standard_Character line[64], sx[32], sy[32], sz[32];
// Header: skip it
fgets(line, 64, f);
// Location, size, number of splits
Standard_Integer nbx = 0, nby = 0, nbz = 0;
Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
if (fscanf(f, "%s %s %s\n", sx, sy, sz) != 3)
{
fclose(f);
return Standard_False;
}
x = atof(sx); y = atof(sy); z = atof(sz);
if (fscanf(f, "%s %s %s\n", sx, sy, sz) != 3)
{
fclose(f);
return Standard_False;
}
xlen = atof(sx); ylen = atof(sy); zlen = atof(sz);
if (fscanf(f, "%d %d %d\n", &nbx, &nby, &nbz) != 3)
{
fclose(f);
return Standard_False;
}
// Allocate the voxels
myBoolVoxels = (Standard_Address) new Voxel_BoolDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
// Data
// Copied from Voxel_BoolDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 8.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
// myData[0 .. nb_slices - 1][0 .. 7]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0, value = 0;
while (!feof(f))
{
fgets(line, 64, f);
if (has_slice(line))
{
if (sscanf(line, "%d %d %d\n", &i1, &i2, &value) != 3)
{
fclose(f);
return Standard_False;
}
}
else
{
if (sscanf(line, "%d %d\n", &i2, &value) != 2)
{
fclose(f);
return Standard_False;
}
}
// Set value
if (!((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])
{
((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1] =
(Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte));
}
(((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])[i2] = value;
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Reader::ReadColorAsciiVoxels(const TCollection_ExtendedString& file)
{
// Open file for reading
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
if (!f)
return Standard_False;
Standard_Character line[64], sx[32], sy[32], sz[32];
// Header: skip it
fgets(line, 64, f);
// Location, size, number of splits
Standard_Integer nbx = 0, nby = 0, nbz = 0;
Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
if (fscanf(f, "%s %s %s\n", sx, sy, sz) != 3)
{
fclose(f);
return Standard_False;
}
x = atof(sx); y = atof(sy); z = atof(sz);
if (fscanf(f, "%s %s %s\n", sx, sy, sz) != 3)
{
fclose(f);
return Standard_False;
}
xlen = atof(sx); ylen = atof(sy); zlen = atof(sz);
if (fscanf(f, "%d %d %d\n", &nbx, &nby, &nbz) != 3)
{
fclose(f);
return Standard_False;
}
// Allocate the voxels
myColorVoxels = (Standard_Address) new Voxel_ColorDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
// Data
// Copied from Voxel_ColorDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 2.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0, value = 0;
while (!feof(f))
{
fgets(line, 64, f);
if (has_slice(line))
{
if (sscanf(line, "%d %d %d\n", &i1, &i2, &value) != 3)
{
fclose(f);
return Standard_False;
}
}
else
{
if (sscanf(line, "%d %d\n", &i2, &value) != 2)
{
fclose(f);
return Standard_False;
}
}
// Set value
if (!((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])
{
((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1] =
(Standard_Byte*) calloc(32/*number of bytes in slice*/, sizeof(Standard_Byte));
}
(((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])[i2] = value;
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Reader::ReadFloatAsciiVoxels(const TCollection_ExtendedString& file)
{
// Open file for reading
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
if (!f)
return Standard_False;
Standard_Character line[64], sx[32], sy[32], sz[32];
// Header: skip it
fgets(line, 64, f);
// Location, size, number of splits
Standard_Integer nbx = 0, nby = 0, nbz = 0;
Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
if (fscanf(f, "%s %s %s\n", sx, sy, sz) != 3)
{
fclose(f);
return Standard_False;
}
x = atof(sx); y = atof(sy); z = atof(sz);
if (fscanf(f, "%s %s %s\n", sx, sy, sz) != 3)
{
fclose(f);
return Standard_False;
}
xlen = atof(sx); ylen = atof(sy); zlen = atof(sz);
if (fscanf(f, "%d %d %d\n", &nbx, &nby, &nbz) != 3)
{
fclose(f);
return Standard_False;
}
// Allocate the voxels
myFloatVoxels = (Standard_Address) new Voxel_FloatDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
// Data
// Copied from Voxel_FloatDS.cxx:
Standard_Integer nb_floats = nbx * nby * nbz;
Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
Standard_ShortReal value = 0.0;
while (!feof(f))
{
fgets(line, 64, f);
if (has_slice(line))
{
if (sscanf(line, "%d %d %s\n", &i1, &i2, line) != 3)
{
fclose(f);
return Standard_False;
}
}
else
{
if (sscanf(line, "%d %s\n", &i2, line) != 2)
{
fclose(f);
return Standard_False;
}
}
value = atof(line);
// Set value
if (!((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])
{
((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1] =
(Standard_ShortReal*) calloc(32/*number of floats in slice*/, sizeof(Standard_ShortReal));
}
(((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])[i2] = value;
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Reader::ReadBoolBinaryVoxels(const TCollection_ExtendedString& file)
{
// Open file for reading
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "rb");
if (!f)
return Standard_False;
// Header: skip it
Standard_Character line[64];
fgets(line, 64, f);
// Location, size, number of splits
Standard_Integer nbx = 0, nby = 0, nbz = 0;
Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
fread(&x, sizeof(Standard_Real), 1, f);
fread(&y, sizeof(Standard_Real), 1, f);
fread(&z, sizeof(Standard_Real), 1, f);
fread(&xlen, sizeof(Standard_Real), 1, f);
fread(&ylen, sizeof(Standard_Real), 1, f);
fread(&zlen, sizeof(Standard_Real), 1, f);
fread(&nbx, sizeof(Standard_Integer), 1, f);
fread(&nby, sizeof(Standard_Integer), 1, f);
fread(&nbz, sizeof(Standard_Integer), 1, f);
// Allocate the voxels
myBoolVoxels = (Standard_Address) new Voxel_BoolDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
// Data
// Copied from Voxel_BoolDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 8.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
// myData[0 .. nb_slices - 1][0 .. 7]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0, value = 0;
while (!feof(f))
{
fread(&i1, sizeof(Standard_Integer), 1, f);
fread(&i2, sizeof(Standard_Integer), 1, f);
fread(&value, sizeof(Standard_Byte), 1, f);
// Set value
if (!((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])
{
((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1] =
(Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte));
}
(((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])[i2] = value;
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Reader::ReadColorBinaryVoxels(const TCollection_ExtendedString& file)
{
// Open file for reading
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "rb");
if (!f)
return Standard_False;
// Header: skip it
Standard_Character line[64];
fgets(line, 64, f);
// Location, size, number of splits
Standard_Integer nbx = 0, nby = 0, nbz = 0;
Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
fread(&x, sizeof(Standard_Real), 1, f);
fread(&y, sizeof(Standard_Real), 1, f);
fread(&z, sizeof(Standard_Real), 1, f);
fread(&xlen, sizeof(Standard_Real), 1, f);
fread(&ylen, sizeof(Standard_Real), 1, f);
fread(&zlen, sizeof(Standard_Real), 1, f);
fread(&nbx, sizeof(Standard_Integer), 1, f);
fread(&nby, sizeof(Standard_Integer), 1, f);
fread(&nbz, sizeof(Standard_Integer), 1, f);
// Allocate the voxels
myColorVoxels = (Standard_Address) new Voxel_ColorDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
// Data
// Copied from Voxel_ColorDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 2.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0, value = 0;
while (!feof(f))
{
fread(&i1, sizeof(Standard_Integer), 1, f);
fread(&i2, sizeof(Standard_Integer), 1, f);
fread(&value, sizeof(Standard_Byte), 1, f);
// Set value
if (!((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])
{
((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1] =
(Standard_Byte*) calloc(32/*number of bytes in slice*/, sizeof(Standard_Byte));
}
(((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])[i2] = value;
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Reader::ReadFloatBinaryVoxels(const TCollection_ExtendedString& file)
{
// Open file for reading
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "rb");
if (!f)
return Standard_False;
// Header: skip it
Standard_Character line[64];
fgets(line, 64, f);
// Location, size, number of splits
Standard_Integer nbx = 0, nby = 0, nbz = 0;
Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
fread(&x, sizeof(Standard_Real), 1, f);
fread(&y, sizeof(Standard_Real), 1, f);
fread(&z, sizeof(Standard_Real), 1, f);
fread(&xlen, sizeof(Standard_Real), 1, f);
fread(&ylen, sizeof(Standard_Real), 1, f);
fread(&zlen, sizeof(Standard_Real), 1, f);
fread(&nbx, sizeof(Standard_Integer), 1, f);
fread(&nby, sizeof(Standard_Integer), 1, f);
fread(&nbz, sizeof(Standard_Integer), 1, f);
// Allocate the voxels
myFloatVoxels = (Standard_Address) new Voxel_FloatDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
// Data
// Copied from Voxel_FloatDS.cxx:
Standard_Integer nb_floats = nbx * nby * nbz;
Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
Standard_ShortReal value = 0.0;
while (!feof(f))
{
fread(&i1, sizeof(Standard_Integer), 1, f);
fread(&i2, sizeof(Standard_Integer), 1, f);
fread(&value, sizeof(Standard_ShortReal), 1, f);
// Set value
if (!((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])
{
((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1] =
(Standard_ShortReal*) calloc(32/*number of floats in slice*/, sizeof(Standard_ShortReal));
}
(((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])[i2] = value;
}
}
fclose(f);
return Standard_True;
}

62
src/Voxel/Voxel_Selector.cdl Executable file
View File

@@ -0,0 +1,62 @@
-- File: Voxel_Selector.cdl
-- Created: Wed Jul 30 15:36:49 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class Selector from Voxel
---Purpose: Detects voxels in the viewer 3d under the mouse cursor.
uses
View from V3d,
BoolDS from Voxel,
ColorDS from Voxel,
ROctBoolDS from Voxel
is
Create
---Purpose: An empty constructor.
returns Selector from Voxel;
Create(view : View from V3d)
---Purpose: A constructor of the selector,
-- which initializes the classes
-- by a view, where the user selects the voxels.
returns Selector from Voxel;
Init(me : in out;
view : View from V3d);
---Purpose: Initializes the selector by a view,
-- where the user selects the voxels.
SetVoxels(me : in out;
voxels : BoolDS from Voxel);
---Purpose: Defines the voxels (1bit).
SetVoxels(me : in out;
voxels : ColorDS from Voxel);
---Purpose: Defines the voxels (4bit).
SetVoxels(me : in out;
voxels : ROctBoolDS from Voxel);
---Purpose: Defines the voxels (1bit recursive splitting).
Detect(me : in out;
winx : Integer from Standard;
winy : Integer from Standard;
ix : out Integer from Standard;
iy : out Integer from Standard;
iz : out Integer from Standard)
---Purpose: Detects a voxel under the mouse cursor.
returns Boolean from Standard;
fields
myView : View from V3d;
myVoxels : Address from Standard;
myIsBool : Integer from Standard; -- 0 - ColorDS, 1 - BoolDS, 2 - ROctBoolDS
end Selector;

569
src/Voxel/Voxel_Selector.cxx Executable file
View File

@@ -0,0 +1,569 @@
// File: Voxel_Selector.cxx
// Created: Wed Jul 30 16:46:13 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_Selector.ixx>
#include <gp_Pnt.hxx>
#include <gp_Lin.hxx>
#include <gp_Dir.hxx>
#include <gp_Pln.hxx>
#include <IntAna_Quadric.hxx>
#include <IntAna_IntConicQuad.hxx>
#include <TColStd_MapOfInteger.hxx>
Voxel_Selector::Voxel_Selector():myVoxels(0)
{
}
Voxel_Selector::Voxel_Selector(const Handle(V3d_View)& view):myView(view),myVoxels(0)
{
}
void Voxel_Selector::Init(const Handle(V3d_View)& view)
{
myView = view;
}
void Voxel_Selector::SetVoxels(const Voxel_BoolDS& voxels)
{
myIsBool = 1;
myVoxels = (void*) &voxels;
}
void Voxel_Selector::SetVoxels(const Voxel_ColorDS& voxels)
{
myIsBool = 0;
myVoxels = (void*) &voxels;
}
void Voxel_Selector::SetVoxels(const Voxel_ROctBoolDS& voxels)
{
myIsBool = 2;
myVoxels = (void*) &voxels;
}
// This function is copied from ViewerTest_RelationCommands.cxx
static Standard_Boolean ComputeIntersection(const gp_Lin& L,const gp_Pln& ThePl, gp_Pnt& TheInter)
{
static IntAna_Quadric TheQuad;
TheQuad.SetQuadric(ThePl);
static IntAna_IntConicQuad QQ;
QQ.Perform(L,TheQuad);
if(QQ.IsDone()){
if(QQ.NbPoints()>0){
TheInter = QQ.Point(1);
return Standard_True;
}
}
return Standard_False;
}
static inline Standard_Integer GetIVoxel(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz,
const Standard_Integer nbx, const Standard_Integer nbxy)
{
return ix + iy * nbx + iz * nbxy;
}
static inline Standard_Boolean Get(const Standard_Address voxels, const Standard_Integer isBool,
const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz)
{
switch (isBool)
{
case 0:
return ((Voxel_ColorDS*) voxels)->Get(ix, iy, iz) > 0;
case 1:
return ((Voxel_BoolDS*) voxels)->Get(ix, iy, iz);
case 2:
{
Standard_Integer deepness = ((Voxel_ROctBoolDS*) voxels)->Deepness(ix, iy, iz);
switch (deepness)
{
case 0:
return ((Voxel_ROctBoolDS*) voxels)->Get(ix, iy, iz);
case 1:
{
for (Standard_Integer i = 0; i < 8; i++)
{
if (((Voxel_ROctBoolDS*) voxels)->Get(ix, iy, iz, i) == Standard_True)
return Standard_True;
}
break;
}
case 2:
{
for (Standard_Integer i = 0; i < 8; i++)
{
for (Standard_Integer j = 0; j < 8; j++)
{
if (((Voxel_ROctBoolDS*) voxels)->Get(ix, iy, iz, i, j) == Standard_True)
return Standard_True;
}
}
break;
}
}
}
}
return Standard_False;
}
Standard_Boolean Voxel_Selector::Detect(const Standard_Integer winx, const Standard_Integer winy,
Standard_Integer& ixdetect, Standard_Integer& iydetect, Standard_Integer& izdetect)
{
ixdetect = -1; iydetect = -1; izdetect = -1;
if (myView.IsNull() || !myVoxels)
return Standard_False;
Voxel_DS* ds = 0;
switch (myIsBool)
{
case 0:
ds = (Voxel_ColorDS*) myVoxels;
break;
case 1:
ds = (Voxel_BoolDS*) myVoxels;
break;
case 2:
ds = (Voxel_ROctBoolDS*) myVoxels;
break;
}
Standard_Integer nbx = ds->GetNbX(), nby = ds->GetNbY(), nbz = ds->GetNbZ(), nbxy = nbx * nby;
// Construct a line perpendicular to the screen
Standard_Real eyex, eyey, eyez, nx, ny, nz;
myView->Convert(winx, winy, eyex, eyey, eyez);
myView->Proj(nx, ny, nz);
gp_Pnt peye(eyex, eyey, eyez);
gp_Lin line(peye, gp_Dir(nx, ny, nz));
// Find the first voxel meeting the line at entrance to the cube of voxels.
// Construct planes of the cube of voxels
Standard_Real xstart = ds->GetX(), ystart = ds->GetY(), zstart = ds->GetZ();
Standard_Real xlen = ds->GetXLen(), ylen = ds->GetYLen(), zlen = ds->GetZLen();
Standard_Real xend = xstart + xlen, yend = ystart + ylen, zend = zstart + zlen;
gp_Pln xplane_minus(gp_Pnt(xstart, ystart, zstart), -gp::DX());
gp_Pln xplane_plus (gp_Pnt(xend, ystart, zstart), gp::DX());
gp_Pln yplane_minus(gp_Pnt(xstart, ystart, zstart), -gp::DY());
gp_Pln yplane_plus (gp_Pnt(xstart, yend, zstart), gp::DY());
gp_Pln zplane_minus(gp_Pnt(xstart, ystart, zstart), -gp::DZ());
gp_Pln zplane_plus (gp_Pnt(xstart, ystart, zend), gp::DZ());
// Intersect the planes with the line.
gp_Pnt pintersection, p;
Standard_Real depth = DBL_MAX, d;
Standard_Integer iplane = -1; // not found
if (ComputeIntersection(line, xplane_minus, p)) // -X
{
if (p.Y() >= ystart && p.Y() <= yend &&
p.Z() >= zstart && p.Z() <= zend)
{
p.SetX(xstart);
depth = peye.SquareDistance(p);
iplane = 0;
pintersection = p;
}
}
if (ComputeIntersection(line, xplane_plus, p)) // +X
{
if (p.Y() >= ystart && p.Y() <= yend &&
p.Z() >= zstart && p.Z() <= zend)
{
d = peye.SquareDistance(p);
if (d < depth)
{
p.SetX(xend);
depth = d;
iplane = 1;
pintersection = p;
}
}
}
if (ComputeIntersection(line, yplane_minus, p)) // -Y
{
if (p.X() >= xstart && p.X() <= xend &&
p.Z() >= zstart && p.Z() <= zend)
{
d = peye.SquareDistance(p);
if (d < depth)
{
p.SetY(ystart);
depth = d;
iplane = 2;
pintersection = p;
}
}
}
if (ComputeIntersection(line, yplane_plus, p)) // +Y
{
if (p.X() >= xstart && p.X() <= xend &&
p.Z() >= zstart && p.Z() <= zend)
{
d = peye.SquareDistance(p);
if (d < depth)
{
p.SetY(yend);
depth = d;
iplane = 3;
pintersection = p;
}
}
}
if (ComputeIntersection(line, zplane_minus, p)) // -Z
{
if (p.X() >= xstart && p.X() <= xend &&
p.Y() >= ystart && p.Y() <= yend)
{
d = peye.SquareDistance(p);
if (d < depth)
{
p.SetZ(zstart);
depth = d;
iplane = 4;
pintersection = p;
}
}
}
if (ComputeIntersection(line, zplane_plus, p)) // +Z
{
if (p.X() >= xstart && p.X() <= xend &&
p.Y() >= ystart && p.Y() <= yend)
{
d = peye.SquareDistance(p);
if (d < depth)
{
p.SetZ(zend);
depth = d;
iplane = 5;
pintersection = p;
}
}
}
// Find the voxel on the detected plane
if (iplane == -1)
return Standard_False;
Standard_Integer ix, iy, iz;
if (!ds->GetVoxel(pintersection.X(), pintersection.Y(), pintersection.Z(), ix, iy, iz))
return Standard_False;
ixdetect = ix; iydetect = iy; izdetect = iz;
// Find a non-zero voxel at the line
Standard_Real xmin = xlen / Standard_Real(nbx),
ymin = ylen / Standard_Real(nby),
zmin = zlen / Standard_Real(nbz),
vmin = sqrt(xmin * xmin + ymin * ymin + zmin * zmin) / 2.0;
Standard_Real xc, yc, zc, dist, distmin = DBL_MAX;
TColStd_MapOfInteger passed;
while (!Get(myVoxels, myIsBool, ixdetect, iydetect, izdetect))
{
// Memorize already checked voxels
if (!passed.Add(GetIVoxel(ixdetect, iydetect, izdetect, nbx, nbxy)))
return Standard_False;
distmin = DBL_MAX;
ix = ixdetect; iy = iydetect; iz = izdetect;
//1: -X neighbour
if (ix - 1 >= 0 && !passed.Contains(GetIVoxel(ix - 1, iy, iz, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy; izdetect = iz;
distmin = dist;
}
}
//2: +X neighbour
if (ix + 1 < nbx && !passed.Contains(GetIVoxel(ix + 1, iy, iz, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy; izdetect = iz;
distmin = dist;
}
}
//3: -Y neighbour
if (iy - 1 >= 0 && !passed.Contains(GetIVoxel(ix, iy - 1, iz, nbx, nbxy)))
{
ds->GetCenter(ix, iy - 1, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy - 1; izdetect = iz;
distmin = dist;
}
}
//4: +Y neighbour
if (iy + 1 < nby && !passed.Contains(GetIVoxel(ix, iy + 1, iz, nbx, nbxy)))
{
ds->GetCenter(ix, iy + 1, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy + 1; izdetect = iz;
distmin = dist;
}
}
//5: -Z neighbour
if (iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix, iy, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix, iy, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy; izdetect = iz - 1;
distmin = dist;
}
}
//6: +Z neighbour
if (iz + 1 < nbz && !passed.Contains(GetIVoxel(ix, iy, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix, iy, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy; izdetect = iz + 1;
distmin = dist;
}
}
// Diagonal voxels
//7: -X-Y neighbour
if (ix - 1 >= 0 && iy - 1 >= 0 && !passed.Contains(GetIVoxel(ix - 1, iy - 1, iz, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy - 1, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy - 1; izdetect = iz;
distmin = dist;
}
}
//8: -X-Z neighbour
if (ix - 1 >= 0 && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix - 1, iy, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy; izdetect = iz - 1;
distmin = dist;
}
}
//9: -Y-Z neighbour
if (iy - 1 >= 0 && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix, iy - 1, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix, iy - 1, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy - 1; izdetect = iz - 1;
distmin = dist;
}
}
//10: +X-Y neighbour
if (ix + 1 < nbx && iy - 1 >= 0 && !passed.Contains(GetIVoxel(ix + 1, iy - 1, iz, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy - 1, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy - 1; izdetect = iz;
distmin = dist;
}
}
//11: +X-Z neighbour
if (ix + 1 < nbx && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix + 1, iy, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy; izdetect = iz - 1;
distmin = dist;
}
}
//12: +Y-Z neighbour
if (iy + 1 < nby && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix, iy + 1, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix, iy + 1, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy + 1; izdetect = iz - 1;
distmin = dist;
}
}
//13: -X+Y neighbour
if (ix - 1 >= 0 && iy + 1 < nby && !passed.Contains(GetIVoxel(ix - 1, iy + 1, iz, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy + 1, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy + 1; izdetect = iz;
distmin = dist;
}
}
//14: -X+Z neighbour
if (ix - 1 >= 0 && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix - 1, iy, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy; izdetect = iz + 1;
distmin = dist;
}
}
//15: -Y+Z neighbour
if (iy - 1 >= 0 && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix, iy - 1, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix, iy - 1, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy - 1; izdetect = iz + 1;
distmin = dist;
}
}
//16: +X+Y neighbour
if (ix + 1 < nbx && iy + 1 < nby && !passed.Contains(GetIVoxel(ix + 1, iy + 1, iz, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy + 1, iz, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy + 1; izdetect = iz;
distmin = dist;
}
}
//17: +X+Z neighbour
if (ix + 1 < nbx && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix + 1, iy, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy; izdetect = iz + 1;
distmin = dist;
}
}
//18: +Y+Z neighbour
if (iy + 1 < nby && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix, iy + 1, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix, iy + 1, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix; iydetect = iy + 1; izdetect = iz + 1;
distmin = dist;
}
}
// Farest neighbours
//19: -X-Y-Z neighbour
if (ix - 1 >= 0 && iy - 1 >= 0 && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix - 1, iy - 1, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy - 1, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy - 1; izdetect = iz - 1;
distmin = dist;
}
}
//20: +X-Y-Z neighbour
if (ix + 1 < nbx && iy - 1 >= 0 && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix + 1, iy - 1, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy - 1, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy - 1; izdetect = iz - 1;
distmin = dist;
}
}
//21: -X+Y-Z neighbour
if (ix - 1 >= 0 && iy + 1 < nby && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix - 1, iy + 1, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy + 1, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy + 1; izdetect = iz - 1;
distmin = dist;
}
}
//22: -X-Y+Z neighbour
if (ix - 1 >= 0 && iy - 1 >= 0 && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix - 1, iy - 1, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy - 1, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy - 1; izdetect = iz + 1;
distmin = dist;
}
}
//23: +X+Y-Z neighbour
if (ix + 1 < nbx && iy + 1 < nby && iz - 1 >= 0 && !passed.Contains(GetIVoxel(ix + 1, iy + 1, iz - 1, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy + 1, iz - 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy + 1; izdetect = iz - 1;
distmin = dist;
}
}
//24: +X-Y+Z neighbour
if (ix + 1 < nbx && iy - 1 >= 0 && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix + 1, iy - 1, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy - 1, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy - 1; izdetect = iz + 1;
distmin = dist;
}
}
//25: -X+Y+Z neighbour
if (ix - 1 >= 0 && iy + 1 < nby && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix - 1, iy + 1, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix - 1, iy + 1, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix - 1; iydetect = iy + 1; izdetect = iz + 1;
distmin = dist;
}
}
//26: +X+Y+Z neighbour
if (ix + 1 < nbx && iy + 1 < nby && iz + 1 < nbz && !passed.Contains(GetIVoxel(ix + 1, iy + 1, iz + 1, nbx, nbxy)))
{
ds->GetCenter(ix + 1, iy + 1, iz + 1, xc, yc, zc);
dist = line.Distance(gp_Pnt(xc, yc, zc));
if (dist < vmin && dist < distmin)
{
ixdetect = ix + 1; iydetect = iy + 1; izdetect = iz + 1;
distmin = dist;
}
}
} // End of while (zero-voxel...
if (!Get(myVoxels, myIsBool, ixdetect, iydetect, izdetect))
return Standard_False;
return Standard_True;
}

35
src/Voxel/Voxel_SplitData.cdl Executable file
View File

@@ -0,0 +1,35 @@
-- File: Voxel_SplitData.cdl
-- Created: Sun Sep 01 10:36:25 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
private class SplitData from Voxel
---Purpose: A container of split information.
-- An instance of this class is used as a slice
-- in inner representation of recursive octtree voxels.
is
Create
---Purpose: An empty constructor.
returns SplitData from Voxel;
GetValues(me : in out)
---Purpose: Gives access to the values.
---C++: return &
returns Address from Standard;
GetSplitData(me : in out)
---Purpose: Gives access to the next split data.
---C++: return &
returns Address from Standard;
fields
myValues : Address from Standard;
mySplitData : Address from Standard;
end SplitData;

21
src/Voxel/Voxel_SplitData.cxx Executable file
View File

@@ -0,0 +1,21 @@
// File: Voxel_SplitData.cxx
// Created: Mon Sep 01 10:47:22 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_SplitData.ixx>
Voxel_SplitData::Voxel_SplitData():myValues(0),mySplitData(0)
{
}
Standard_Address& Voxel_SplitData::GetValues()
{
return myValues;
}
Standard_Address& Voxel_SplitData::GetSplitData()
{
return mySplitData;
}

42
src/Voxel/Voxel_TypeDef.hxx Executable file
View File

@@ -0,0 +1,42 @@
#ifndef _VOXEL_TYPEDEF_HXX_
#define _VOXEL_TYPEDEF_HXX_
// Basic data types
typedef struct
{
Standard_Integer ix;
Standard_Integer iy;
Standard_Integer iz;
} iXYZ;
// Maps and Tables
inline Standard_Integer HashCode(const iXYZ& me, const Standard_Integer upper)
{
return (Abs(me.ix + me.iy + me.iz) % upper) + 1;
}
inline Standard_Boolean IsEqual(const iXYZ& one, const iXYZ& two)
{
return one.ix == two.ix && one.iy == two.iy && one.iz == two.iz;
}
#include <NCollection_DefineBaseCollection.hxx>
DEFINE_BASECOLLECTION(iXYZbase, iXYZ)
#include <NCollection_DefineDataMap.hxx>
DEFINE_DATAMAP(iXYZIndex, iXYZbase, iXYZ, Standard_Integer)
DEFINE_DATAMAP(iXYZBool, iXYZbase, iXYZ, Standard_Byte)
// Defines
#define VOXELS "Voxels"
#define ASCII "Ascii"
#define BINARY "Binary"
#define BOOL "Bool"
#define COLOR "Color"
#define FLOAT "Float"
#endif // _VOXEL_TYPEDEF_HXX_

114
src/Voxel/Voxel_VisData.h Executable file
View File

@@ -0,0 +1,114 @@
#ifndef _VOXEL_VISDATA_H_
#define _VOXEL_VISDATA_H_
#include <Quantity_Color.hxx>
#include <Quantity_HArray1OfColor.hxx>
#include <TShort_HArray1OfShortReal.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColgp_HArray1OfDir.hxx>
#include <Poly_Triangulation.hxx>
#include <Voxel_BoolDS.hxx>
#include <Voxel_ColorDS.hxx>
#include <Voxel_ROctBoolDS.hxx>
#include <Voxel_VoxelDisplayMode.hxx>
enum VoxelDirection
{
None,
Xminus,
Xplus,
Yminus,
Yplus,
Zminus,
Zplus
};
typedef struct
{
/* Display mode */
Voxel_VoxelDisplayMode myDisplayMode;
/* Range of displayed values */
/* BoolDS */
/* No range */
/* ColorDS */
Standard_Byte myColorMinValue;
Standard_Byte myColorMaxValue;
/* Range of displayed size */
Standard_Real myDisplayedXMin;
Standard_Real myDisplayedXMax;
Standard_Real myDisplayedYMin;
Standard_Real myDisplayedYMax;
Standard_Real myDisplayedZMin;
Standard_Real myDisplayedZMax;
/* Colors */
Quantity_Color myColor;
Handle(Quantity_HArray1OfColor) myColors;
/* Size, width... */
Standard_Real myPointSize;
Standard_Integer myQuadrangleSize; /* 0% .. 100% */
Standard_Byte mySmoothPoints;
/* Transparency */
Standard_Real myTransparency;
/* GL lists of each display mode */
/* BoolDS */
/* POINTS */
Standard_Integer myBoolPointsList;
Standard_Byte myBoolPointsFirst;
/* NEAREST POINTS */
Standard_Integer myBoolNearestPointsList[7];
Standard_Byte myBoolNearestPointsFirst;
/* ColorDS */
/* POINTS */
Standard_Integer myColorPointsList;
Standard_Byte myColorPointsFirst;
/* NEAREST POINTS */
Standard_Integer myColorNearestPointsList[7];
Standard_Byte myColorNearestPointsFirst;
/* ROctBoolDS */
/* POINTS */
Standard_Integer myROctBoolPointsList;
Standard_Byte myROctBoolPointsFirst;
/* NEAREST POINTS */
Standard_Integer myROctBoolNearestPointsList[7];
Standard_Byte myROctBoolNearestPointsFirst;
/* TRIANGULATION */
Standard_Integer myTriangulationList;
/* Usage of GL lists */
Standard_Byte myUsageOfGLlists;
/* Degenerate mode */
Standard_Byte myDegenerateMode;
/* Highlighted voxel */
Standard_Integer myHighlightx;
Standard_Integer myHighlighty;
Standard_Integer myHighlightz;
} DisplayData;
typedef struct
{
// Voxels
Voxel_BoolDS* myBoolVoxels;
Voxel_ColorDS* myColorVoxels;
Voxel_ROctBoolDS* myROctBoolVoxels;
// Triangulation
Handle(Poly_Triangulation) myTriangulation;
Handle(TColgp_HArray1OfDir) myNormalsOfNodes;
// Display
DisplayData myDisplay;
} Voxel_VisData;
#endif // _VOXEL_VISDATA_H_

97
src/Voxel/Voxel_Writer.cdl Executable file
View File

@@ -0,0 +1,97 @@
-- File: Voxel_Writer.cdl
-- Created: Wed Aug 28 11:23:33 2008
-- Author: Vladislav ROMASHKO
-- <vladislav.romashko@opencascade.com>
---Copyright: Open CASCADE S.A.
class Writer from Voxel
---Purpose: Writes a cube of voxels on disk.
uses
VoxelFileFormat from Voxel,
BoolDS from Voxel,
ColorDS from Voxel,
FloatDS from Voxel,
ExtendedString from TCollection
is
Create
---Purpose: An empty constructor.
returns Writer from Voxel;
SetFormat(me : in out;
format : VoxelFileFormat from Voxel);
---Purpose: Defines the file format for voxels.
-- ASCII - slow and occupies more space on disk.
-- BINARY - fast and occupies less space on disk.
SetVoxels(me : in out;
voxels : BoolDS from Voxel);
---Purpose: Defines the voxels (1bit).
SetVoxels(me : in out;
voxels : ColorDS from Voxel);
---Purpose: Defines the voxels (4bit).
SetVoxels(me : in out;
voxels : FloatDS from Voxel);
---Purpose: Defines the voxels (4bytes).
Write(me;
file : ExtendedString from TCollection)
---Purpose: Writes the voxels on disk
-- using the defined format and file name.
returns Boolean from Standard;
---Private area
-- ============
WriteBoolAsciiVoxels(me;
file : ExtendedString from TCollection)
---Purpose: Writes 1bit voxels on disk in ASCII format.
returns Boolean from Standard
is private;
WriteColorAsciiVoxels(me;
file : ExtendedString from TCollection)
---Purpose: Writes 4bit voxels on disk in ASCII format.
returns Boolean from Standard
is private;
WriteFloatAsciiVoxels(me;
file : ExtendedString from TCollection)
---Purpose: Writes 4bytes voxels on disk in ASCII format.
returns Boolean from Standard
is private;
WriteBoolBinaryVoxels(me;
file : ExtendedString from TCollection)
---Purpose: Writes 1bit voxels on disk in BINARY format.
returns Boolean from Standard
is private;
WriteColorBinaryVoxels(me;
file : ExtendedString from TCollection)
---Purpose: Writes 4bit voxels on disk in BINARY format.
returns Boolean from Standard
is private;
WriteFloatBinaryVoxels(me;
file : ExtendedString from TCollection)
---Purpose: Writes 4bytes voxels on disk in BINARY format.
returns Boolean from Standard
is private;
fields
myFormat : VoxelFileFormat from Voxel;
myBoolVoxels : Address from Standard;
myColorVoxels : Address from Standard;
myFloatVoxels : Address from Standard;
end Writer;

427
src/Voxel/Voxel_Writer.cxx Executable file
View File

@@ -0,0 +1,427 @@
// File: Voxel_Writer.cxx
// Created: Wed Aug 28 14:36:15 2008
// Author: Vladislav ROMASHKO
// <vladislav.romashko@opencascade.com>
#include <Voxel_Writer.ixx>
#include <Voxel_TypeDef.hxx>
#include <Precision.hxx>
#include <TCollection_AsciiString.hxx>
Voxel_Writer::Voxel_Writer():myFormat(Voxel_VFF_ASCII),myBoolVoxels(0),myColorVoxels(0),myFloatVoxels(0)
{
}
void Voxel_Writer::SetFormat(const Voxel_VoxelFileFormat format)
{
myFormat = format;
}
void Voxel_Writer::SetVoxels(const Voxel_BoolDS& voxels)
{
myBoolVoxels = (Standard_Address) &voxels;
myColorVoxels = 0;
myFloatVoxels = 0;
}
void Voxel_Writer::SetVoxels(const Voxel_ColorDS& voxels)
{
myBoolVoxels = 0;
myColorVoxels = (Standard_Address) &voxels;
myFloatVoxels = 0;
}
void Voxel_Writer::SetVoxels(const Voxel_FloatDS& voxels)
{
myBoolVoxels = 0;
myColorVoxels = 0;
myFloatVoxels = (Standard_Address) &voxels;
}
Standard_Boolean Voxel_Writer::Write(const TCollection_ExtendedString& file) const
{
switch (myFormat)
{
case Voxel_VFF_ASCII:
{
if (myBoolVoxels)
return WriteBoolAsciiVoxels(file);
else if (myColorVoxels)
return WriteColorAsciiVoxels(file);
else if (myFloatVoxels)
return WriteFloatAsciiVoxels(file);
}
case Voxel_VFF_BINARY:
{
if (myBoolVoxels)
return WriteBoolBinaryVoxels(file);
else if (myColorVoxels)
return WriteColorBinaryVoxels(file);
else if (myFloatVoxels)
return WriteFloatBinaryVoxels(file);
}
}
// No voxels or no format description is found:
return Standard_False;
}
Standard_Boolean Voxel_Writer::WriteBoolAsciiVoxels(const TCollection_ExtendedString& file) const
{
Voxel_BoolDS* ds = (Voxel_BoolDS*) myBoolVoxels;
if (!ds->myData)
return Standard_False;
// Open file for writing
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "w+");
if (!f)
return Standard_False;
// Header: file format, type of voxels
fprintf(f, VOXELS);
fprintf(f, " ");
fprintf(f, ASCII);
fprintf(f, " ");
fprintf(f, BOOL);
fprintf(f, "\n");
// Location, size, number of splits
fprintf(f, "%g %g %g\n", ds->GetX(), ds->GetY(), ds->GetZ());
fprintf(f, "%g %g %g\n", ds->GetXLen(), ds->GetYLen(), ds->GetZLen());
fprintf(f, "%d %d %d\n", ds->GetNbX(), ds->GetNbY(), ds->GetNbZ());
// Data
// Copied from Voxel_BoolDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(ds->GetNbX() * ds->GetNbY() * ds->GetNbZ() / 8.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
// myData[0 .. nb_slices - 1][0 .. 7]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
for (i1 = 0; i1 < nb_slices; i1++)
{
if (((Standard_Byte**)ds->myData)[i1])
{
Standard_Boolean has_value = Standard_False;
fprintf(f, "%d ", i1); // index of slice
for (i2 = 0; i2 < 8; i2++)
{
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)ds->myData)[i1])[i2];
if (value)
{
has_value = Standard_True;
fprintf(f, "%d %d\n", i2, value);
}
}
if (!has_value)
{
fprintf(f, "0 0\n");
}
}
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Writer::WriteColorAsciiVoxels(const TCollection_ExtendedString& file) const
{
Voxel_ColorDS* ds = (Voxel_ColorDS*) myColorVoxels;
if (!ds->myData)
return Standard_False;
// Open file for writing
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "w+");
if (!f)
return Standard_False;
// Header: file format, type of voxels
fprintf(f, VOXELS);
fprintf(f, " ");
fprintf(f, ASCII);
fprintf(f, " ");
fprintf(f, COLOR);
fprintf(f, "\n");
// Location, size, number of splits
fprintf(f, "%g %g %g\n", ds->GetX(), ds->GetY(), ds->GetZ());
fprintf(f, "%g %g %g\n", ds->GetXLen(), ds->GetYLen(), ds->GetZLen());
fprintf(f, "%d %d %d\n", ds->GetNbX(), ds->GetNbY(), ds->GetNbZ());
// Data
// Copied from Voxel_ColorDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(ds->GetNbX() * ds->GetNbY() * ds->GetNbZ() / 2.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
for (i1 = 0; i1 < nb_slices; i1++)
{
if (((Standard_Byte**)ds->myData)[i1])
{
Standard_Boolean has_value = Standard_False;
fprintf(f, "%d ", i1); // index of slice
for (i2 = 0; i2 < 32; i2++)
{
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)ds->myData)[i1])[i2];
if (value)
{
has_value = Standard_True;
fprintf(f, "%d %d\n", i2, value);
}
}
if (!has_value)
{
fprintf(f, "0 0\n");
}
}
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Writer::WriteFloatAsciiVoxels(const TCollection_ExtendedString& file) const
{
Voxel_FloatDS* ds = (Voxel_FloatDS*) myFloatVoxels;
if (!ds->myData)
return Standard_False;
// Open file for writing
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "w+");
if (!f)
return Standard_False;
// Header: file format, type of voxels
fprintf(f, VOXELS);
fprintf(f, " ");
fprintf(f, ASCII);
fprintf(f, " ");
fprintf(f, FLOAT);
fprintf(f, "\n");
// Location, size, number of splits
fprintf(f, "%g %g %g\n", ds->GetX(), ds->GetY(), ds->GetZ());
fprintf(f, "%g %g %g\n", ds->GetXLen(), ds->GetYLen(), ds->GetZLen());
fprintf(f, "%d %d %d\n", ds->GetNbX(), ds->GetNbY(), ds->GetNbZ());
// Data
// Copied from Voxel_FloatDS.cxx:
Standard_Integer nb_floats = ds->GetNbX() * ds->GetNbY() * ds->GetNbZ();
Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
for (i1 = 0; i1 < nb_slices; i1++)
{
if (((Standard_ShortReal**)ds->myData)[i1])
{
Standard_Boolean has_value = Standard_False;
fprintf(f, "%d ", i1); // index of slice
for (i2 = 0; i2 < 32; i2++)
{
Standard_ShortReal value = ((Standard_ShortReal*)((Standard_ShortReal**)ds->myData)[i1])[i2];
if (value)
{
has_value = Standard_True;
fprintf(f, "%d %g\n", i2, value);
}
}
if (!has_value)
{
fprintf(f, "0 0\n");
}
}
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Writer::WriteBoolBinaryVoxels(const TCollection_ExtendedString& file) const
{
Voxel_BoolDS* ds = (Voxel_BoolDS*) myBoolVoxels;
if (!ds->myData)
return Standard_False;
// Open file for writing
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "wb");
if (!f)
return Standard_False;
// Header: file format, type of voxels
fprintf(f, VOXELS);
fprintf(f, " ");
fprintf(f, BINARY);
fprintf(f, " ");
fprintf(f, BOOL);
fprintf(f, "\n");
// Location, size, number of splits
fwrite(&(ds->myX), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myY), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myZ), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myXLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myYLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myZLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myNbX), sizeof(Standard_Integer), 1, f);
fwrite(&(ds->myNbY), sizeof(Standard_Integer), 1, f);
fwrite(&(ds->myNbZ), sizeof(Standard_Integer), 1, f);
// Data
// Copied from Voxel_BoolDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(ds->GetNbX() * ds->GetNbY() * ds->GetNbZ() / 8.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
// myData[0 .. nb_slices - 1][0 .. 7]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
for (i1 = 0; i1 < nb_slices; i1++)
{
if (((Standard_Byte**)ds->myData)[i1])
{
for (i2 = 0; i2 < 8; i2++)
{
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)ds->myData)[i1])[i2];
if (value)
{
fwrite(&i1, sizeof(Standard_Integer), 1, f);
fwrite(&i2, sizeof(Standard_Integer), 1, f);
fwrite(&value, sizeof(Standard_Byte), 1, f);
}
}
}
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Writer::WriteColorBinaryVoxels(const TCollection_ExtendedString& file) const
{
Voxel_ColorDS* ds = (Voxel_ColorDS*) myColorVoxels;
if (!ds->myData)
return Standard_False;
// Open file for writing
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "wb");
if (!f)
return Standard_False;
// Header: file format, type of voxels
fprintf(f, VOXELS);
fprintf(f, " ");
fprintf(f, BINARY);
fprintf(f, " ");
fprintf(f, COLOR);
fprintf(f, "\n");
// Location, size, number of splits
fwrite(&(ds->myX), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myY), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myZ), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myXLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myYLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myZLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myNbX), sizeof(Standard_Integer), 1, f);
fwrite(&(ds->myNbY), sizeof(Standard_Integer), 1, f);
fwrite(&(ds->myNbZ), sizeof(Standard_Integer), 1, f);
// Data
// Copied from Voxel_ColorDS.cxx:
Standard_Integer nb_bytes = RealToInt(ceil(ds->myNbX * ds->myNbY * ds->myNbZ / 2.0));
Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
for (i1 = 0; i1 < nb_slices; i1++)
{
if (((Standard_Byte**)ds->myData)[i1])
{
for (i2 = 0; i2 < 32; i2++)
{
Standard_Byte value = ((Standard_Byte*)((Standard_Byte**)ds->myData)[i1])[i2];
if (value)
{
fwrite(&i1, sizeof(Standard_Integer), 1, f);
fwrite(&i2, sizeof(Standard_Integer), 1, f);
fwrite(&value, sizeof(Standard_Byte), 1, f);
}
}
}
}
}
fclose(f);
return Standard_True;
}
Standard_Boolean Voxel_Writer::WriteFloatBinaryVoxels(const TCollection_ExtendedString& file) const
{
Voxel_FloatDS* ds = (Voxel_FloatDS*) myFloatVoxels;
if (!ds->myData)
return Standard_False;
// Open file for writing
FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "wb");
if (!f)
return Standard_False;
// Header: file format, type of voxels
fprintf(f, VOXELS);
fprintf(f, " ");
fprintf(f, BINARY);
fprintf(f, " ");
fprintf(f, FLOAT);
fprintf(f, "\n");
// Location, size, number of splits
fwrite(&(ds->myX), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myY), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myZ), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myXLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myYLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myZLen), sizeof(Standard_Real), 1, f);
fwrite(&(ds->myNbX), sizeof(Standard_Integer), 1, f);
fwrite(&(ds->myNbY), sizeof(Standard_Integer), 1, f);
fwrite(&(ds->myNbZ), sizeof(Standard_Integer), 1, f);
// Data
// Copied from Voxel_FloatDS.cxx:
Standard_Integer nb_floats = ds->myNbX * ds->myNbY * ds->myNbZ;
Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
// myData[0 .. nb_slices - 1][0 .. 31]
if (nb_slices)
{
Standard_Integer i1 = 0, i2 = 0;
Standard_Real small = Precision::Confusion() * Precision::Confusion();
for (i1 = 0; i1 < nb_slices; i1++)
{
if (((Standard_ShortReal**)ds->myData)[i1])
{
for (i2 = 0; i2 < 32; i2++)
{
Standard_ShortReal value = ((Standard_ShortReal*)((Standard_ShortReal**)ds->myData)[i1])[i2];
if (fabs(value) > small)
{
fwrite(&i1, sizeof(Standard_Integer), 1, f);
fwrite(&i2, sizeof(Standard_Integer), 1, f);
fwrite(&value, sizeof(Standard_ShortReal), 1, f);
}
}
}
}
}
fclose(f);
return Standard_True;
}