From f9d060bd4f05d1576a3d90b15c32319b60b081d4 Mon Sep 17 00:00:00 2001 From: duv Date: Fri, 10 Jul 2015 14:20:38 +0300 Subject: [PATCH] Voxels for AVD Conflicts: src/Graphic3d/FILES src/Graphic3d/Graphic3d.cdl src/Graphic3d/Graphic3d_Group.cdl src/Graphic3d/Graphic3d_TransferFunction.cxx src/OpenGl/FILES src/Voxel/FILES src/Voxel/Voxel_BoolDS.cxx src/Voxel/Voxel_BooleanOperation.cxx src/Voxel/Voxel_CollisionDetection.cxx src/Voxel/Voxel_ColorDS.cxx src/Voxel/Voxel_DS.cxx src/Voxel/Voxel_FastConverter.cxx src/Voxel/Voxel_FloatDS.cxx src/Voxel/Voxel_Prs.cxx src/Voxel/Voxel_Prs.hxx src/Voxel/Voxel_ROctBoolDS.cxx src/Voxel/Voxel_Reader.cxx src/Voxel/Voxel_Selector.cxx src/Voxel/Voxel_Writer.cxx --- src/BVH/BVH_Box.hxx | 14 + src/Graphic3d/FILES | 30 + src/Graphic3d/Graphic3d-936bf93.cdl | 582 ++++++++ src/Graphic3d/Graphic3d_DenseVolumeData.hxx | 131 ++ src/Graphic3d/Graphic3d_DenseVolumeData.lxx | 127 ++ src/Graphic3d/Graphic3d_Group.cxx | 30 + .../Graphic3d_RgbaTransferFunction.hxx | 296 +++++ .../Graphic3d_RgbaTransferFunction.lxx | 178 +++ .../Graphic3d_TransferFunction.cxx} | 25 +- src/Graphic3d/Graphic3d_TransferFunction.hxx | 74 ++ .../Graphic3d_TransferFunctionFilter.hxx | 52 + ...Graphic3d_TransferFunctionLinearFilter.hxx | 33 + ...Graphic3d_TransferFunctionLinearFilter.lxx | 70 + ...raphic3d_TransferFunctionNearestFilter.hxx | 33 + ...raphic3d_TransferFunctionNearestFilter.lxx | 70 + .../Graphic3d_TransferFunctionNode.hxx | 47 + src/Graphic3d/Graphic3d_Volume.cxx | 73 + src/Graphic3d/Graphic3d_Volume.hxx | 239 ++++ src/Graphic3d/Graphic3d_VolumeData.cxx | 78 ++ src/Graphic3d/Graphic3d_VolumeData.hxx | 147 +++ src/NCollection/NCollection_Vec3.hxx | 9 + src/OpenGl/FILES | 25 +- src/OpenGl/OpenGl_Group.cxx | 18 + src/OpenGl/OpenGl_Group.hxx | 5 + src/OpenGl/OpenGl_Texture.cxx | 91 ++ src/OpenGl/OpenGl_Texture.hxx | 41 +- src/OpenGl/OpenGl_Volume.cxx | 520 ++++++++ src/OpenGl/OpenGl_Volume.hxx | 166 +++ src/QABugs/QABugs_19.cxx | 77 -- src/Shaders/TextRender.fs | 49 + src/Shaders/TextRender.vs | 9 + src/Shaders/VolumeRender.fs | 402 ++++++ src/Shaders/VolumeRender.vs | 12 + src/ViewerTest/ViewerTest_VoxelCommands.cxx | 1034 +-------------- src/Voxel/FILES | 35 +- src/Voxel/Handle_Voxel_Prs.hxx | 30 + src/Voxel/Voxel_BaseReader.hxx | 51 + src/Voxel/Voxel_BoolDS.cxx | 141 -- src/Voxel/Voxel_BooleanOperation.cxx | 230 ---- src/Voxel/Voxel_CollisionDetection.cxx | 295 ----- src/Voxel/Voxel_ColorDS.cxx | 173 --- src/Voxel/Voxel_DS.cxx | 194 --- src/Voxel/Voxel_DicomReader.cxx | 266 ++++ src/Voxel/Voxel_DicomReader.hxx | 42 + src/Voxel/Voxel_FastConverter.cxx | 1174 ----------------- src/Voxel/Voxel_FloatDS.cxx | 116 -- src/Voxel/Voxel_OctBoolDS.cxx | 2 + src/Voxel/Voxel_Prs.cxx | 307 +---- src/Voxel/Voxel_Prs.hxx | 148 +-- src/Voxel/Voxel_ROctBoolDS.cxx | 727 ---------- src/Voxel/Voxel_Reader.cxx | 539 -------- src/Voxel/Voxel_Selector.cxx | 581 -------- src/Voxel/Voxel_TypeDef.hxx | 20 +- src/Voxel/Voxel_VisData.h | 129 -- src/Voxel/Voxel_Writer.cxx | 442 ------- 55 files changed, 4132 insertions(+), 6297 deletions(-) create mode 100644 src/Graphic3d/Graphic3d-936bf93.cdl create mode 100644 src/Graphic3d/Graphic3d_DenseVolumeData.hxx create mode 100644 src/Graphic3d/Graphic3d_DenseVolumeData.lxx create mode 100644 src/Graphic3d/Graphic3d_RgbaTransferFunction.hxx create mode 100644 src/Graphic3d/Graphic3d_RgbaTransferFunction.lxx rename src/{Voxel/Voxel_SplitData.cxx => Graphic3d/Graphic3d_TransferFunction.cxx} (63%) create mode 100644 src/Graphic3d/Graphic3d_TransferFunction.hxx create mode 100644 src/Graphic3d/Graphic3d_TransferFunctionFilter.hxx create mode 100644 src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.hxx create mode 100644 src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.lxx create mode 100644 src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.hxx create mode 100644 src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.lxx create mode 100644 src/Graphic3d/Graphic3d_TransferFunctionNode.hxx create mode 100644 src/Graphic3d/Graphic3d_Volume.cxx create mode 100644 src/Graphic3d/Graphic3d_Volume.hxx create mode 100644 src/Graphic3d/Graphic3d_VolumeData.cxx create mode 100644 src/Graphic3d/Graphic3d_VolumeData.hxx create mode 100644 src/OpenGl/OpenGl_Volume.cxx create mode 100644 src/OpenGl/OpenGl_Volume.hxx create mode 100644 src/Shaders/TextRender.fs create mode 100644 src/Shaders/TextRender.vs create mode 100644 src/Shaders/VolumeRender.fs create mode 100644 src/Shaders/VolumeRender.vs create mode 100644 src/Voxel/Handle_Voxel_Prs.hxx create mode 100644 src/Voxel/Voxel_BaseReader.hxx delete mode 100644 src/Voxel/Voxel_BoolDS.cxx delete mode 100644 src/Voxel/Voxel_BooleanOperation.cxx delete mode 100644 src/Voxel/Voxel_CollisionDetection.cxx delete mode 100644 src/Voxel/Voxel_ColorDS.cxx delete mode 100644 src/Voxel/Voxel_DS.cxx create mode 100644 src/Voxel/Voxel_DicomReader.cxx create mode 100644 src/Voxel/Voxel_DicomReader.hxx delete mode 100644 src/Voxel/Voxel_FastConverter.cxx delete mode 100644 src/Voxel/Voxel_FloatDS.cxx delete mode 100644 src/Voxel/Voxel_ROctBoolDS.cxx delete mode 100644 src/Voxel/Voxel_Reader.cxx delete mode 100644 src/Voxel/Voxel_Selector.cxx delete mode 100644 src/Voxel/Voxel_VisData.h delete mode 100644 src/Voxel/Voxel_Writer.cxx diff --git a/src/BVH/BVH_Box.hxx b/src/BVH/BVH_Box.hxx index 838fb90352..db3b054cde 100644 --- a/src/BVH/BVH_Box.hxx +++ b/src/BVH/BVH_Box.hxx @@ -101,6 +101,20 @@ protected: }; +//! 2D Axis aligned box on single precision reals. +typedef BVH_Box BVH_Box2f; +//! 3D Axis aligned box on single precision reals. +typedef BVH_Box BVH_Box3f; +//! 4D Axis aligned box on single precision reals. +typedef BVH_Box BVH_Box4f; + +//! 2D Axis aligned box on double precision reals. +typedef BVH_Box BVH_Box2d; +//! 3D Axis aligned box on double precision reals. +typedef BVH_Box BVH_Box3d; +//! 4D Axis aligned box on double precision reals. +typedef BVH_Box BVH_Box4d; + namespace BVH { //! Tool class for calculating box center along the given axis. diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 3cbda2dc6e..eb023901f1 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -173,3 +173,33 @@ Graphic3d_ViewAffinity.hxx Graphic3d_WorldViewProjState.hxx Graphic3d_ZLayerId.hxx Graphic3d_ZLayerSettings.hxx +Graphic3d_Vertex.hxx +Graphic3d_Vertex.cxx +Graphic3d_MarkerImage.hxx +Graphic3d_MarkerImage.cxx +Graphic3d_ClipPlane.hxx +Graphic3d_ClipPlane.cxx +Graphic3d_SequenceOfGroup.hxx +Graphic3d_SequenceOfHClipPlane.hxx +Graphic3d_Camera.cxx +Graphic3d_Camera.hxx +Graphic3d_RenderingParams.hxx +Graphic3d_NMapOfTransient.hxx +Graphic3d_BSDF.hxx +Graphic3d_BSDF.cxx +Graphic3d_Volume.hxx +Graphic3d_Volume.cxx +Graphic3d_VolumeData.hxx +Graphic3d_VolumeData.cxx +Graphic3d_DenseVolumeData.hxx +Graphic3d_DenseVolumeData.lxx +Graphic3d_TransferFunction.hxx +Graphic3d_TransferFunction.cxx +Graphic3d_RgbaTransferFunction.hxx +Graphic3d_RgbaTransferFunction.lxx +Graphic3d_TransferFunctionNode.hxx +Graphic3d_TransferFunctionFilter.hxx +Graphic3d_TransferFunctionLinearFilter.hxx +Graphic3d_TransferFunctionLinearFilter.lxx +Graphic3d_TransferFunctionNearestFilter.hxx +Graphic3d_TransferFunctionNearestFilter.lxx \ No newline at end of file diff --git a/src/Graphic3d/Graphic3d-936bf93.cdl b/src/Graphic3d/Graphic3d-936bf93.cdl new file mode 100644 index 0000000000..ddd85f9e70 --- /dev/null +++ b/src/Graphic3d/Graphic3d-936bf93.cdl @@ -0,0 +1,582 @@ +-- Created on: 1993-03-31 +-- Created by: NW,JPB,CAL +-- Copyright (c) 1993-1999 Matra Datavision +-- Copyright (c) 1999-2014 OPEN CASCADE SAS +-- +-- This file is part of Open CASCADE Technology software library. +-- +-- This library is free software; you can redistribute it and/or modify it under +-- the terms of the GNU Lesser General Public License version 2.1 as published +-- by the Free Software Foundation, with special exception defined in the file +-- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +-- distribution for complete text of the license and disclaimer of any warranty. +-- +-- Alternatively, this file may be used under the terms of Open CASCADE +-- commercial license or contractual agreement. + +-- Package : Graphic3d +-- Updated : Vendredi 2 Octobre 1992 +-- Mercredi 31 Mars 1993 +-- Mercredi 19 Janvier 1994 +-- 1/08/97 ; PCT : Ajout texture mapping +-- 11/97 ; CAL : retrait de la dependance avec math +-- 11/97 ; CAL : retrait des DataStructure +-- 04/98 ; FGU : ajout champs 'TOR_EMISSION' +-- 16-09-98; BGN: (S3819) Ajout TypeOfTriedronEcho, +-- TypeOfTriedronPosition. +-- 22-09-98; BGN: S3989 (anciennement S3819): report +-- dans Aspect des TypeOfTriedron* +-- 26-03-99 : FMN ; Compatibilite ascendante: +-- Ajout des anciens noms de materiaux. +-- 09-04-99 : GG ; Compatibilite ascendante: +-- NameOfPhysicalMaterial disparait +-- 23-11-99 : GG ; Add material name DEFAULT +-- 16-06-2000 : ATS : Study G005: class ArrayOfPrimitives +-- and derivated used for model presentation. +-- Required: enumeration TypeOfPrimitive; +-- imported PrimitiveArray; class PrimitiveList. +-- 17-12-01 : GG ; IMP171201 : Add material name UserDefined +-- Thanks to Stephane ROUTELOUS +-- 20-01-2009 : ABD Integration support of system fonts (using FTGL and FreeType) +-- Objective : Specifications definitives + +package Graphic3d + + ---Version: + + ---Purpose: This package permits the creation of 3d graphic objects + -- in a visualiser. + -- These objects, called structures, are composed of groups of + -- primitives and attributes. + -- The group is the smallest editable element of a structure. + -- A structure can be displayed, erased, high-lighted. + -- A transformation can be applied to it. + -- Structures can be connected to form a tree of structures, + -- composed by transformations. + -- The visualiser permits global manipulation of structures. + + ---Keywords: Structure, Group, Primitives, Line, Marker, Text, + -- FillAreas, Vertex, Vector, Material, Font, Shading + ---Warning: + ---References: + +uses + + TCollection, + TColStd, + TColgp, + OSD, + Quantity, + Aspect, + MMgt, + WNT, + Image, + gp, + Font, + Bnd +is + + ----------------------- + -- Category: Exceptions + ----------------------- + + exception AspectTextDefinitionError inherits OutOfRange; + ---Category: Exceptions + + exception CycleError inherits DomainError; + ---Category: Exceptions + + exception GroupDefinitionError inherits OutOfRange; + ---Category: Exceptions + + exception InitialisationError inherits OutOfRange; + ---Category: Exceptions + + exception MaterialDefinitionError inherits OutOfRange; + ---Category: Exceptions + + exception PriorityDefinitionError inherits OutOfRange; + ---Category: Exceptions + + exception StructureDefinitionError inherits OutOfRange; + ---Category: Exceptions + + exception TransformError inherits OutOfRange; + ---Category: Exceptions + + exception VectorError inherits OutOfRange; + ---Category: Exceptions + + ------------------------- + -- Category: Enumerations + ------------------------- + + enumeration NameOfMaterial is + NOM_BRASS, -- laiton (PHYSIC) + NOM_BRONZE, -- bronze (PHYSIC) + NOM_COPPER, -- cuivre (PHYSIC) + NOM_GOLD, -- or (PHYSIC) + + NOM_PEWTER, -- etain (PHYSIC) + + NOM_PLASTER, -- platre (GENERIC) + NOM_PLASTIC, -- plastic (GENERIC) + + NOM_SILVER, -- argent (PHYSIC) + + NOM_STEEL, -- acier (PHYSIC) + + NOM_STONE, -- pierre (PHYSIC) + + NOM_SHINY_PLASTIC, -- plastique brillant (GENERIC) + NOM_SATIN, -- satin (GENERIC) + NOM_METALIZED, -- metallise New (GENERIC) + NOM_NEON_GNC, -- neon New (GENERIC) + NOM_CHROME, -- chrome New (PHYSIC) + NOM_ALUMINIUM, -- aluminium New (PHYSIC) + NOM_OBSIDIAN, -- obsidian New (PHYSIC) + NOM_NEON_PHC, -- neon New (PHYSIC) + NOM_JADE, -- jade New (PHYSIC) + + NOM_CHARCOAL, + + NOM_WATER, + NOM_GLASS, + NOM_DIAMOND, + + NOM_DEFAULT, + NOM_UserDefined -- owner material + end NameOfMaterial; + ---Purpose: Types of aspect materials. + ---Category: Enumerations + + enumeration TypeOfMaterial is MATERIAL_ASPECT, -- Materiel generique + MATERIAL_PHYSIC -- Materiel physique + end TypeOfMaterial; + ---Purpose: Types of materials specifies if a material can change color. + ---Category: Enumerations + + enumeration NameOfTexture1D is NOT_1D_ELEVATION, + NOT_1D_UNKNOWN + end NameOfTexture1D; + ---Purpose: Types of standard textures. + ---Category: Enumerations + + + enumeration NameOfTexture2D is NOT_2D_MATRA, + NOT_2D_ALIENSKIN, + NOT_2D_BLUE_ROCK, + NOT_2D_BLUEWHITE_PAPER, + NOT_2D_BRUSHED, + NOT_2D_BUBBLES, + NOT_2D_BUMP, + NOT_2D_CAST, + NOT_2D_CHIPBD, + NOT_2D_CLOUDS, + NOT_2D_FLESH, + NOT_2D_FLOOR, + NOT_2D_GALVNISD, + NOT_2D_GRASS, + NOT_2D_ALUMINUM, + NOT_2D_ROCK, + NOT_2D_KNURL, + NOT_2D_MAPLE, + NOT_2D_MARBLE, + NOT_2D_MOTTLED, + NOT_2D_RAIN, + NOT_2D_UNKNOWN + end NameOfTexture2D; + ---Purpose: Types of standard textures. + ---Category: Enumerations + + + enumeration NameOfTextureEnv is NOT_ENV_CLOUDS, + NOT_ENV_CV, + NOT_ENV_MEDIT, + NOT_ENV_PEARL, + NOT_ENV_SKY1, + NOT_ENV_SKY2, + NOT_ENV_LINES, + NOT_ENV_ROAD, + NOT_ENV_UNKNOWN + end NameOfTextureEnv; + ---Purpose: Types of standard textures. + ---Category: Enumerations + + enumeration TypeOfTexture is TOT_1D, + TOT_2D, + TOT_2D_MIPMAP; + ---Purpose: Type of the texture file format. + ---Category: Enumerations + + enumeration TypeOfTextureMode is TOTM_OBJECT, + TOTM_SPHERE, + TOTM_EYE, + TOTM_MANUAL, + TOTM_SPRITE; + ---Purpose: Type of the texture projection. + ---Category: Enumerations + + enumeration TypeOfTextureFilter is TOTF_NEAREST, + TOTF_BILINEAR, + TOTF_TRILINEAR; + ---Purpose: Type of the texture filter. + -- Notice that for textures without mipmaps linear interpolation will be used instead of TOTF_BILINEAR and TOTF_TRILINEAR. + ---Category: Enumerations + + enumeration LevelOfTextureAnisotropy is LOTA_OFF, + LOTA_FAST, + LOTA_MIDDLE, + LOTA_QUALITY; + ---Purpose: Level of anisotropy filter. + -- Notice that actual quality depends on hardware capabilities! + ---Category: Enumerations + + enumeration NameOfTexturePlane is NOTP_XY, + NOTP_YZ, + NOTP_ZX, + NOTP_UNKNOWN; + ---Purpose: Type of the texture projection plane for both S and T texture coordinate. + ---Category: Enumerations + + enumeration TypeOfComposition is TOC_REPLACE, + TOC_POSTCONCATENATE + end TypeOfComposition; + ---Purpose: To manage the transformation matrices of structures. + ---Category: Enumerations + + enumeration TypeOfConnection is TOC_ANCESTOR, + TOC_DESCENDANT + end TypeOfConnection; + ---Purpose: To manage the connections between the structures. + ---Category: Enumerations + + enumeration TypeOfPolygon is TOP_UNKNOWN, + TOP_COMPLEX, + TOP_CONCAVE, + TOP_CONVEX + end TypeOfPolygon; + ---Purpose: The type of polygon in a group in a structure. + ---Category: Enumerations + + enumeration TypeOfPrimitive is TOP_UNDEFINED, + TOP_POLYLINE, + TOP_POLYGON, + TOP_TRIANGLEMESH, + TOP_QUADRANGLEMESH, + TOP_TEXT, + TOP_MARKER, + TOP_PARRAY + end TypeOfPrimitive; + ---Purpose: The type of primitive in a group in a structure. + ---Category: Enumerations + + enumeration TypeOfPrimitiveArray is TOPA_UNDEFINED, + TOPA_POINTS, + TOPA_POLYLINES, + TOPA_SEGMENTS, + TOPA_POLYGONS, + TOPA_TRIANGLES, + TOPA_QUADRANGLES, + TOPA_TRIANGLESTRIPS, + TOPA_QUADRANGLESTRIPS, + TOPA_TRIANGLEFANS + end TypeOfPrimitiveArray; + ---Purpose: The type of primitive array in a group in a structure. + ---Category: Enumerations + + enumeration TypeOfReflection is TOR_AMBIENT, + TOR_DIFFUSE, + TOR_SPECULAR, + TOR_EMISSION + end TypeOfReflection; + ---Purpose: Nature of the reflection of a material. + ---Category: Enumerations + + enumeration TypeOfStructure is TOS_WIREFRAME, + TOS_SHADING, + TOS_COMPUTED, + TOS_ALL + end TypeOfStructure; + ---Purpose: Structural attribute indicating if it can be displayed + -- in wireframe, shadow mode, or both. + ---Category: Enumerations + + enumeration TextPath is TP_UP, + TP_DOWN, + TP_LEFT, + TP_RIGHT + end TextPath; + ---Purpose: Direction in which text is displayed. + ---Category: Enumerations + + enumeration HorizontalTextAlignment is HTA_LEFT, + HTA_CENTER, + HTA_RIGHT + end HorizontalTextAlignment; + ---Purpose: Defines the horizontal position of the text + -- relative to its anchor. + ---Category: Enumerations + + enumeration VerticalTextAlignment is VTA_BOTTOM, + VTA_CENTER, + VTA_TOP + end VerticalTextAlignment; + ---Purpose: Defines the vertical position of the text + -- relative to its anchor. + ---Category: Enumerations + + enumeration GroupAspect is ASPECT_LINE, + ASPECT_TEXT, + ASPECT_MARKER, + ASPECT_FILL_AREA + end GroupAspect; + ---Purpose: Identifies primitives aspects defined per group. + -- - ASPECT_LINE: aspect for line primitives; + -- - ASPECT_TEXT: aspect for text primitives; + -- - ASPECT_MARKER: aspect for marker primitives; + -- - ASPECT_FILL_AREA: aspect for face primitives. + + enumeration RenderingMode is + RM_RASTERIZATION, RM_RAYTRACING + end RenderingMode; + ---Purpose: Describes rendering modes. + -- - RM_RASTERIZATION: enables OpenGL rasterization mode; + -- - RM_RAYTRACING: enables GPU ray-tracing mode. + + enumeration TypeOfBackground is + TOB_NONE, TOB_GRADIENT, TOB_TEXTURE + end TypeOfBackground; + ---Purpose: Describes type of view background. + + --------------------------- + -- Category: Imported types + --------------------------- + + imported BndBox4f; + ---Purpose: Redefines BVH_Box for AABB representation + ---Category: Imported types + imported Buffer; + imported Buffer_Handle; + imported BoundBuffer; + imported BoundBuffer_Handle; + imported IndexBuffer; + imported IndexBuffer_Handle; + + imported BndBox4d; + imported BufferType; + + imported BSDF; + + imported CBitFields20; + ---Category: Imported types + + imported CBitFields16; + ---Category: Imported types + + imported CBitFields8; + ---Category: Imported types + + imported CBitFields4; + ---Category: Imported types + + imported CAspectFillArea; + imported CAspectMarker; + imported CAspectLine; + imported CAspectText; + + imported CStructure; + ---Category: Imported types + + pointer CStructurePtr to CStructure from Graphic3d; + + imported CStructure_Handle; + + imported CLight; + ---Category: Imported types + + imported CPlane; + ---Category: Imported types + + imported CUserDraw; + ---Category: Imported types + + imported CView; + ---Category: Imported types + + imported RenderingParams; + ---Purpose: Describes rendering parameters and effects. + ---Category: Imported types + + imported CGraduatedTrihedron; + ---Category: Imported types + + imported ClipPlane; + ---Category: Imported types + + imported ClipPlane_Handle; + + imported CTexture; + + imported CTransPersStruct; + imported TransModeFlags; + + imported MarkerImage; + imported MarkerImage_Handle; + imported Camera_Handle; + + imported transient class Volume; + + primitive PtrFrameBuffer; + primitive Vec2; + primitive Vec3; + primitive Vec4; + imported Mat4; + imported Mat4d; + + imported ZLayerSettings; + primitive ZLayerId; + + -------------------- + -- Category: Classes + -------------------- + + deferred class ArrayOfPrimitives; + + class ArrayOfPoints; + + class ArrayOfPolylines; + + class ArrayOfSegments; + + class ArrayOfPolygons; + + class ArrayOfTriangles; + + class ArrayOfTriangleStrips; + + class ArrayOfTriangleFans; + + class ArrayOfQuadrangles; + + class ArrayOfQuadrangleStrips; + + class AspectLine3d; + ---Category: Classes + + class AspectFillArea3d; + ---Category: Classes + + class AspectMarker3d; + ---Category: Classes + + class AspectText3d; + ---Category: Classes + + deferred class Group; + ---Category: Classes + + class MaterialAspect; + ---Category: Classes + + class Structure; + ---Category: Classes + + pointer StructurePtr to Structure from Graphic3d; + + deferred class GraphicDriver; + + deferred class StructureManager; + ---Category: Classes + + pointer StructureManagerPtr to StructureManager from Graphic3d; + + deferred class DataStructureManager; + ---Category: Classes + + class Vector; + ---Category: Classes + + imported Vertex; + ---Category: Classes + + imported MapOfStructure; + imported SequenceOfDisplayedStructures; + + --------------------------------- + -- Category: Instantiated classes + --------------------------------- + + imported SequenceOfGroup; + + class SequenceOfStructure instantiates + Sequence from TCollection + (Structure from Graphic3d); + ---Category: Instantiated classes + + class HSequenceOfStructure instantiates + HSequence from TCollection + (Structure from Graphic3d, SequenceOfStructure from Graphic3d); + ---Category: Instantiated classes + + class Array1OfVector instantiates + Array1 from TCollection (Vector from Graphic3d); + ---Category: Instantiated classes + + class Array1OfVertex instantiates + Array1 from TCollection (Vertex from Graphic3d); + ---Category: Instantiated classes + + class Array2OfVertex instantiates + Array2 from TCollection (Vertex from Graphic3d); + ---Category: Instantiated classes + + class ListOfShortReal instantiates + List from TCollection (ShortReal from Standard); + ---Category: Instantiated classes + + --ABD Integration support of system fonts (using FTGL and FreeType) + imported NListOfHAsciiString; + ---Category: Instantiated classes + + imported ShaderProgram_Handle; + ---Category: Instantiated classes + + imported SequenceOfHClipPlane; + ---Category: Instantiated classes + -- Sequence of handles on clip planes + + deferred class TextureRoot from Graphic3d; + deferred class TextureMap from Graphic3d; + deferred class Texture1D from Graphic3d; + deferred class Texture2D from Graphic3d; + + class TextureParams from Graphic3d; + class TextureEnv from Graphic3d; + class Texture1Dmanual from Graphic3d; + class Texture1Dsegment from Graphic3d; + class Texture2Dmanual from Graphic3d; + class Texture2Dplane from Graphic3d; + + + enumeration ExportFormat is + + EF_PostScript, + EF_EnhPostScript, + EF_TEX, + EF_PDF, + EF_SVG, + EF_PGF, + EF_EMF + + end ExportFormat; + + + enumeration SortType is + + ST_Simple, -- sorting by depth of center point of primitive(fast) + ST_BSP_Tree -- sorting by BSPTree (slow, but fine result ) + + end SortType; + +end Graphic3d; diff --git a/src/Graphic3d/Graphic3d_DenseVolumeData.hxx b/src/Graphic3d/Graphic3d_DenseVolumeData.hxx new file mode 100644 index 0000000000..b270671e36 --- /dev/null +++ b/src/Graphic3d/Graphic3d_DenseVolumeData.hxx @@ -0,0 +1,131 @@ +// Created on: 2014-12-24 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_DenseVolumeData_HeaderFile +#define _Graphic3d_DenseVolumeData_HeaderFile + +#include +#include +#include + +//! Dense volumetric data of specific type +//! (stores the value in each voxel). +template +class Graphic3d_DenseVolumeData : public Graphic3d_VolumeData +{ +public: + + //! Type of voxel value. + typedef T DataType; + + //! Type of voxel array. + typedef NCollection_Array1 VoxelArray; + +public: + + //! Creates uninitialized dense volumetric data. + Graphic3d_DenseVolumeData(); + + //! Creates dense volumetric data with the given dimensions. + Graphic3d_DenseVolumeData (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ); + + //! Creates dense volumetric data with the given dimensions and data. + Graphic3d_DenseVolumeData (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ, + const NCollection_Handle& theVoxels); + + //! Releases resources of dense volumetric data. + virtual ~Graphic3d_DenseVolumeData(); + +public: + + //! Reinitializes dense volumetric data with the given dimensions. + virtual void Init (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ); + + //! Reinitializes dense volumetric data with the given dimensions and data. + virtual void Init (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ, + const NCollection_Handle& theVoxels); + + //! Returns value at the given voxel. + virtual DataType Voxel (const Standard_Integer theIndex) const + { + return myVoxels->Value (theIndex); + } + + //! Returns value at the given voxel. + virtual DataType Voxel (const Standard_Integer theIndexX, + const Standard_Integer theIndexY, + const Standard_Integer theIndexZ) const + { + return myVoxels->Value (theIndexX + (theIndexY + theIndexZ * myNbVoxY) * myNbVoxX); + } + + //! Sets value at the given voxel. + virtual void SetVoxel (const DataType theValue, + const Standard_Integer theIndex) + { + myVoxels->ChangeValue (theIndex) = theValue; + } + + //! Sets value at the given voxel. + virtual void SetVoxel (const DataType theValue, + const Standard_Integer theIndexX, + const Standard_Integer theIndexY, + const Standard_Integer theIndexZ) + { + myVoxels->ChangeValue (theIndexX + (theIndexY + theIndexZ * myNbVoxY) * myNbVoxX) = theValue; + } + + //! Returns raw voxel data. + NCollection_Handle& Data() + { + return myVoxels; + } + + //! Returns raw voxel data. + const NCollection_Handle& Data() const + { + return myVoxels; + } + + //! Sets raw voxel data (must correspond to dataset size). + void SetData (const NCollection_Handle& theData); + + //! Checks if volumetric data is dense. + virtual Standard_Boolean IsDense() const Standard_OVERRIDE + { + return Standard_True; + } + +protected: + + //! Array of voxels. + NCollection_Handle myVoxels; +}; + +#include + +#endif // _Graphic3d_DenseVolumeData_HeaderFile diff --git a/src/Graphic3d/Graphic3d_DenseVolumeData.lxx b/src/Graphic3d/Graphic3d_DenseVolumeData.lxx new file mode 100644 index 0000000000..8c52aa4954 --- /dev/null +++ b/src/Graphic3d/Graphic3d_DenseVolumeData.lxx @@ -0,0 +1,127 @@ +// Created on: 2014-12-24 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +//======================================================================== +//Function : Graphic3d_DenseVolumeData +//Purpose : +//======================================================================== +template +Graphic3d_DenseVolumeData::Graphic3d_DenseVolumeData() : Graphic3d_VolumeData() +{ + // +} + +//======================================================================== +//Function : Graphic3d_DenseVolumeData +//Purpose : +//======================================================================== +template +Graphic3d_DenseVolumeData::Graphic3d_DenseVolumeData (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ) +: Graphic3d_VolumeData (theBounds, + theNbVoxX, + theNbVoxY, + theNbVoxZ) +{ + myVoxels = new VoxelArray (0, theNbVoxX * theNbVoxY * theNbVoxZ - 1); +} + +//======================================================================== +//Function : Graphic3d_DenseVolumeData +//Purpose : +//======================================================================== +template +Graphic3d_DenseVolumeData::Graphic3d_DenseVolumeData (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ, + const NCollection_Handle& theVoxels) +: Graphic3d_VolumeData (theBounds, + theNbVoxX, + theNbVoxY, + theNbVoxZ) +{ + Standard_ASSERT_RETURN (theVoxels->Length() == theNbVoxX * theNbVoxY * theNbVoxZ, + "Error: Array size is not valid", /* none */); + + myVoxels = theVoxels; +} + +//======================================================================== +//Function : Init +//Purpose : +//======================================================================== +template +void Graphic3d_DenseVolumeData::Init (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ) +{ + init (theBounds, + theNbVoxX, + theNbVoxY, + theNbVoxZ); + + myVoxels = new VoxelArray (0, theNbVoxX * theNbVoxY * theNbVoxZ - 1); +} + +//======================================================================== +//Function : Init +//Purpose : +//======================================================================== +template +void Graphic3d_DenseVolumeData::Init (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ, + const NCollection_Handle& theVoxels) +{ + init (theBounds, + theNbVoxX, + theNbVoxY, + theNbVoxZ); + + Standard_ASSERT_RETURN (theVoxels->Length() == theNbVoxX * theNbVoxY * theNbVoxZ, + "Error: Array size is not valid", /* none */); + + myVoxels = theVoxels; +} + +//======================================================================== +//Function : ~Graphic3d_DenseVolumeData +//Purpose : +//======================================================================== +template +Graphic3d_DenseVolumeData::~Graphic3d_DenseVolumeData() +{ + // +} + +//======================================================================== +//Function : SetData +//Purpose : +//======================================================================== +template +void Graphic3d_DenseVolumeData::SetData (const NCollection_Handle& theData) +{ + Standard_ASSERT_RETURN (theVoxels->Length() == theNbVoxX * theNbVoxY * theNbVoxZ, + "Error: Array size is not valid", /* none */); + + myVoxels = theData; +} \ No newline at end of file diff --git a/src/Graphic3d/Graphic3d_Group.cxx b/src/Graphic3d/Graphic3d_Group.cxx index 6e8cf95e84..d51357c0a6 100644 --- a/src/Graphic3d/Graphic3d_Group.cxx +++ b/src/Graphic3d/Graphic3d_Group.cxx @@ -1065,6 +1065,36 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th Update(); } +// ======================================================================= +// function : AddVolume +// purpose : +// ======================================================================= +void Graphic3d_Group::AddVolume (const Handle(Graphic3d_Volume)& theVolume, + const Standard_Boolean theToEvalMinMax) +{ + if (IsDeleted()) + { + return; + } + + if (theToEvalMinMax && !theVolume->VolumeData().IsNull()) + { + const BVH_Box3d& aBounds = theVolume->VolumeData()->Bounds(); + + myBounds.Add (BVH_Vec4f (static_cast (aBounds.CornerMin().x()), + static_cast (aBounds.CornerMin().y()), + static_cast (aBounds.CornerMin().z()), + 1.f)); + + myBounds.Add (BVH_Vec4f (static_cast (aBounds.CornerMax().x()), + static_cast (aBounds.CornerMax().y()), + static_cast (aBounds.CornerMax().z()), + 1.f)); + } + + Update(); +} + // ======================================================================= // function : Marker // purpose : diff --git a/src/Graphic3d/Graphic3d_RgbaTransferFunction.hxx b/src/Graphic3d/Graphic3d_RgbaTransferFunction.hxx new file mode 100644 index 0000000000..654a8324b0 --- /dev/null +++ b/src/Graphic3d/Graphic3d_RgbaTransferFunction.hxx @@ -0,0 +1,296 @@ +// Created on: 2014-12-24 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_RgbaTransferFunction_HeaderFile +#define _Graphic3d_RgbaTransferFunction_HeaderFile + +#include +#include +#include +#include +#include +#include + +//! Defines RGBA transfer function for specific type of scalar field. +template +class Graphic3d_RgbaTransferFunction : public Graphic3d_TransferFunction +{ +public: + + //! Defines RGB color type. + typedef NCollection_Vec3 ColorType; + + //! Defines type of color node. + typedef Graphic3d_TransferFunctionNode ColorNode; + + //! Defines type of opacity node. + typedef Graphic3d_TransferFunctionNode AlphaNode; + + //! Defines type of color filter tool. + typedef Graphic3d_TransferFunctionFilter ColorFilterTool; + + //! Defines type of opacity filter tool. + typedef Graphic3d_TransferFunctionFilter AlphaFilterTool; + +public: + + //! Creates empty transfer function. + Graphic3d_RgbaTransferFunction(); + + //! Releases resources of transfer function. + ~Graphic3d_RgbaTransferFunction(); + + //! Saves TF to file. + Standard_Boolean SaveToFile (const Standard_Character* theFileName) + { + std::ofstream aStream; + + OSD_OpenStream (aStream, theFileName, std::ios_base::binary); + + if (!aStream.is_open()) + { + return Standard_False; + } + + const Standard_Integer aNbColorNodes = myColorNodes.Size(); + const Standard_Integer aNbAlphaNodes = myAlphaNodes.Size(); + + aStream.write (reinterpret_cast (&aNbColorNodes), sizeof (Standard_Integer)); + aStream.write (reinterpret_cast (&aNbAlphaNodes), sizeof (Standard_Integer)); + + for (Standard_Integer anIdx = 0; anIdx < aNbColorNodes; ++anIdx) + { + PointType aPoint = myColorNodes.Value (anIdx + 1).Point; + + ValueType aR = myColorNodes.Value (anIdx + 1).Value.x(); + ValueType aG = myColorNodes.Value (anIdx + 1).Value.y(); + ValueType aB = myColorNodes.Value (anIdx + 1).Value.z(); + + aStream.write (reinterpret_cast (&aPoint), sizeof (PointType)); + + aStream.write (reinterpret_cast (&aR), sizeof (ValueType)); + aStream.write (reinterpret_cast (&aG), sizeof (ValueType)); + aStream.write (reinterpret_cast (&aB), sizeof (ValueType)); + } + + for (Standard_Integer anIdx = 0; anIdx < aNbAlphaNodes; ++anIdx) + { + PointType aPoint = myAlphaNodes.Value (anIdx + 1).Point; + ValueType aValue = myAlphaNodes.Value (anIdx + 1).Value; + + aStream.write (reinterpret_cast (&aPoint), sizeof (PointType)); + aStream.write (reinterpret_cast (&aValue), sizeof (ValueType)); + } + + aStream.close(); + } + + //! Loads TF from file. + Standard_Boolean LoadFromFile (const Standard_Character* theFileName) + { + std::ifstream aStream; + + OSD_OpenStream (aStream, theFileName, std::ios_base::binary); + + if (!aStream.is_open()) + { + return Standard_False; + } + + Standard_Integer aNbColorNodes = 0; + Standard_Integer aNbAlphaNodes = 0; + + aStream.read (reinterpret_cast (&aNbColorNodes), sizeof (Standard_Integer)); + aStream.read (reinterpret_cast (&aNbAlphaNodes), sizeof (Standard_Integer)); + + if (aNbColorNodes <= 0 || aNbAlphaNodes <= 0) + { + return Standard_False; + } + + myColorNodes.Clear(); + myAlphaNodes.Clear(); + + for (Standard_Integer anIdx = 0; anIdx < aNbColorNodes; ++anIdx) + { + PointType aPoint; + + ValueType aR; + ValueType aG; + ValueType aB; + + aStream.read (reinterpret_cast (&aPoint), sizeof (PointType)); + + aStream.read (reinterpret_cast (&aR), sizeof (ValueType)); + aStream.read (reinterpret_cast (&aG), sizeof (ValueType)); + aStream.read (reinterpret_cast (&aB), sizeof (ValueType)); + + AddNode (aPoint, ColorType (aR, aG, aB)); + } + + for (Standard_Integer anIdx = 0; anIdx < aNbAlphaNodes; ++anIdx) + { + PointType aPoint; + ValueType aValue; + + aStream.read (reinterpret_cast (&aPoint), sizeof (PointType)); + aStream.read (reinterpret_cast (&aValue), sizeof (ValueType)); + + AddNode (aPoint, aValue); + } + + aStream.close(); + + Update(); + } + +public: + + //! Appends color control point. + void AddNode (const PointType thePoint, + const ColorType& theColor) + { + myColorNodes.Append (ColorNode (thePoint, theColor)); + } + + //! Appends opacity control point. + void AddNode (const PointType thePoint, + const ValueType theAlpha) + { + myAlphaNodes.Append (AlphaNode (thePoint, theAlpha)); + } + + //! Appends color-opacity control point. + void AddNode (const PointType thePoint, + const ColorType& theColor, + const ValueType theAlpha) + { + AddNode (thePoint, theColor); + AddNode (thePoint, theAlpha); + } + + //! Returns reference to the given color control point. + ColorNode& ChangeColorNodeData (const Standard_Integer theIndex) + { + return myColorNodes.ChangeValue (theIndex - 1); + } + + //! Returns reference to the given opacity control point. + AlphaNode& ChangeAlphaNodeData (const Standard_Integer theIndex) + { + return myAlphaNodes.ChangeValue (theIndex - 1); + } + + //! Returns const reference to the given color control point. + const ColorNode& ColorNodeData (const Standard_Integer theIndex) const + { + return myColorNodes.Value (theIndex - 1); + } + + //! Returns const reference to the given opacity control point. + const AlphaNode& AlphaNodeData (const Standard_Integer theIndex) const + { + return myAlphaNodes.Value (theIndex - 1); + } + + //! Removes the given color control point. + void RemoveColorNode (const Standard_Integer theIndex) + { + myColorNodes.Remove (theIndex - 1); + } + + //! Removes the given opacity control point. + void RemoveAlphaNode (const Standard_Integer theIndex) + { + myAlphaNodes.Remove (theIndex - 1); + } + + //! Clears all color control points. + void ClearColorNodes() + { + myColorNodes.Clear(); + } + + //! Clears all opacity control points. + void ClearAlphaNodes() + { + myAlphaNodes.Clear(); + } + + //! Returns number of color nodes. + Standard_Integer NbOfColorNodes() const + { + return myColorNodes.Size(); + } + + //! Returns number of opacity nodes. + Standard_Integer NbOfAlphaNodes() const + { + return myAlphaNodes.Size(); + } + + //! Returns color filter. + const NCollection_Handle& ColorFilter() const + { + return myColorFilter; + } + + //! Sets color filter. + void SetColorFilter (const NCollection_Handle& theColorFilter) + { + myColorFilter = theColorFilter; + } + + //! Returns opacity filter. + const NCollection_Handle& AlphaFilter() const + { + return myAlphaFilter; + } + + //! Sets opacity filter. + void SetAlphaFilter (const NCollection_Handle& theAlphaFilter) + { + myAlphaFilter = theAlphaFilter; + } + +public: + + //! Initializes transfer function with default values. + void InitDefault (const Standard_ShortReal theScale, const Standard_Integer theNbOfNodes = 32); + + //! Computes discretization table as 1D image. + virtual Handle(Image_PixMap) ImageTable (Standard_Real& theNormMinValue, + Standard_Real& theNormMaxValue, + const Standard_Integer theNumberOfRows = SIZE_OF_TABLE) const Standard_OVERRIDE; + +protected: + + //! List of color nodes. + NCollection_Sequence myColorNodes; + + //! List of opacity nodes. + NCollection_Sequence myAlphaNodes; + + //! Color filter tool. + mutable NCollection_Handle myColorFilter; + + //! Opacity filter tool. + mutable NCollection_Handle myAlphaFilter; + +}; + +#include + +#endif // _Graphic3d_RgbaTransferFunction_HeaderFile diff --git a/src/Graphic3d/Graphic3d_RgbaTransferFunction.lxx b/src/Graphic3d/Graphic3d_RgbaTransferFunction.lxx new file mode 100644 index 0000000000..b00723454a --- /dev/null +++ b/src/Graphic3d/Graphic3d_RgbaTransferFunction.lxx @@ -0,0 +1,178 @@ +// Created on: 2015-01-28 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +//======================================================================== +//function : Graphic3d_RgbaTransferFunction +//purpose : +//======================================================================== +template +Graphic3d_RgbaTransferFunction::Graphic3d_RgbaTransferFunction() +: Graphic3d_TransferFunction() +{ + // Set default filter -- linear + myColorFilter = new Graphic3d_TransferFunctionLinearFilter; + myAlphaFilter = new Graphic3d_TransferFunctionLinearFilter; +} + +//======================================================================== +//function : ~Graphic3d_RgbaTransferFunction +//purpose : +//======================================================================== +template +Graphic3d_RgbaTransferFunction::~Graphic3d_RgbaTransferFunction() +{ + // +} + +namespace Graphic3d_TransferFunctionTools +{ + //! Node comparator. + template + struct NodeComparator + { + bool operator() (const Node& theNode1, const Node& theNode2) const + { + return theNode1.Point < theNode2.Point; + } + }; + + //! Image constructor. + template + struct ImageConstructor + { + /* Not defined */ + }; + + template<> + struct ImageConstructor + { + static Handle(Image_PixMap) Create (const Standard_Integer theSize) + { + Handle(Image_PixMap) anImage = new Image_PixMap; + + return anImage->InitZero (Image_PixMap::ImgRGBAF, theSize, 1) ? anImage : NULL; + } + }; + + template<> + struct ImageConstructor + { + static Handle(Image_PixMap) Create (const Standard_Integer theSize) + { + Handle(Image_PixMap) anImage = new Image_PixMap; + + return anImage->InitZero (Image_PixMap::ImgRGBA, theSize, 1) ? anImage : NULL; + } + }; +} + +namespace Graphic3d_TransferFunctionTools +{ + //! Performs normalization of integral values to [0, 1] range. + template + struct ValueNormalizer + { + static Standard_Real Get (const T theValue) + { + const T aMinValue = std::numeric_limits::min(); + const T aMaxValue = std::numeric_limits::max(); + + return (theValue - aMinValue) / + static_cast (aMaxValue - aMinValue); + } + }; + + template<> + struct ValueNormalizer + { + static Standard_Real Get (const Standard_Real theValue) + { + return theValue; + } + }; + + template<> + struct ValueNormalizer + { + static Standard_Real Get (const Standard_ShortReal theValue) + { + return theValue; + } + }; +} + +//======================================================================== +//function : ImageTable +//purpose : +//======================================================================== +template +Handle(Image_PixMap) Graphic3d_RgbaTransferFunction::ImageTable (Standard_Real& theNormMinValue, + Standard_Real& theNormMaxValue, + const Standard_Integer theNumberOfRows) const +{ + if (myColorNodes.Size() < 2 + || myAlphaNodes.Size() < 2) + { + return NULL; + } + + std::vector aColorNodes (myColorNodes.begin(), myColorNodes.end()); + std::vector aAlphaNodes (myAlphaNodes.begin(), myAlphaNodes.end()); + + std::sort (aColorNodes.begin(), aColorNodes.end(), + Graphic3d_TransferFunctionTools::NodeComparator()); + std::sort (aAlphaNodes.begin(), aAlphaNodes.end(), + Graphic3d_TransferFunctionTools::NodeComparator()); + + Handle(Image_PixMap) aImageTable = + Graphic3d_TransferFunctionTools::ImageConstructor::Create (theNumberOfRows); + + if (aImageTable.IsNull()) + { + return NULL; + } + + const PointType aMinValue = std::min (aColorNodes.front().Point, + aAlphaNodes.front().Point); + + const PointType aMaxValue = std::max (aColorNodes.back().Point, + aAlphaNodes.back().Point); + + theNormMinValue = Graphic3d_TransferFunctionTools::ValueNormalizer::Get (aMinValue); + theNormMaxValue = Graphic3d_TransferFunctionTools::ValueNormalizer::Get (aMaxValue); + + myColorFilter->Init (&aColorNodes.front(), myColorNodes.Size()); + myAlphaFilter->Init (&aAlphaNodes.front(), myAlphaNodes.Size()); + + Standard_Real aStep = (aMaxValue - aMinValue) / static_cast (theNumberOfRows - 1); + + for (Standard_Integer anIndex = 0; anIndex < theNumberOfRows; ++anIndex) + { + const PointType aPoint = static_cast (aMinValue + aStep * anIndex); + + const ColorType aColor = myColorFilter->Value (aPoint); + const ValueType aAlpha = myAlphaFilter->Value (aPoint); + + NCollection_Vec4& aPixel = aImageTable->ChangeValue > (0, anIndex); + + aPixel = NCollection_Vec4 ( + aColor.x(), aColor.y(), aColor.z(), aAlpha); + } + + return aImageTable; +} \ No newline at end of file diff --git a/src/Voxel/Voxel_SplitData.cxx b/src/Graphic3d/Graphic3d_TransferFunction.cxx similarity index 63% rename from src/Voxel/Voxel_SplitData.cxx rename to src/Graphic3d/Graphic3d_TransferFunction.cxx index ce59c60309..bc1639e054 100644 --- a/src/Voxel/Voxel_SplitData.cxx +++ b/src/Graphic3d/Graphic3d_TransferFunction.cxx @@ -1,6 +1,6 @@ -// Created on: 2008-09-01 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS +// Created on: 2015-01-28 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2015 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -13,20 +13,7 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include -#include - -Voxel_SplitData::Voxel_SplitData():myValues(0),mySplitData(0) -{ - -} - -Standard_Address& Voxel_SplitData::GetValues() -{ - return myValues; -} - -Standard_Address& Voxel_SplitData::GetSplitData() -{ - return mySplitData; -} +IMPLEMENT_STANDARD_HANDLE (Graphic3d_TransferFunction, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_TransferFunction, Standard_Transient) diff --git a/src/Graphic3d/Graphic3d_TransferFunction.hxx b/src/Graphic3d/Graphic3d_TransferFunction.hxx new file mode 100644 index 0000000000..2daefe1462 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunction.hxx @@ -0,0 +1,74 @@ +// Created on: 2015-01-26 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_TransferFunction_HeaderFile +#define _Graphic3d_TransferFunction_HeaderFile + +#include + +//! Defines abstract transfer function that maps values +//! of scalar field to specific RGB color and opacity. +class Graphic3d_TransferFunction : public Standard_Transient +{ +public: + + //! Default size of discretization table. + static const Standard_Integer SIZE_OF_TABLE = 512; + +public: + + //! Creates empty transfer function. + Graphic3d_TransferFunction() : myState (1) + { + // + } + + //! Releases resources of transfer function. + virtual ~Graphic3d_TransferFunction() + { + // + } + + //! Returns current state of transfer function. + Standard_Size State() const + { + return myState; + } + + //! Updates current state of transfer function. + void Update() + { + ++myState; + } + + //! Computes discretization table as 1D image. + virtual Handle(Image_PixMap) ImageTable (Standard_Real& theNormMinValue, + Standard_Real& theNormMaxValue, + const Standard_Integer theNumberOfRows = SIZE_OF_TABLE) const = 0; + +protected: + + //! Current state of transfer function. + Standard_Size myState; + +public: + + DEFINE_STANDARD_RTTI (Graphic3d_TransferFunction) + +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_TransferFunction, Standard_Transient) + +#endif // _Graphic3d_TransferFunction_HeaderFile diff --git a/src/Graphic3d/Graphic3d_TransferFunctionFilter.hxx b/src/Graphic3d/Graphic3d_TransferFunctionFilter.hxx new file mode 100644 index 0000000000..b18823339a --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunctionFilter.hxx @@ -0,0 +1,52 @@ +// Created on: 2014-12-25 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_TransferFunctionFilter_HeaderFile +#define _Graphic3d_TransferFunctionFilter_HeaderFile + +#include + +//! Transfer function filter used for generating discretization table. +template +class Graphic3d_TransferFunctionFilter +{ +public: + + //! Type of control point. + typedef Graphic3d_TransferFunctionNode Node; + +public: + + //! Initializes internal structures. + virtual void Init (const Node* theNodes, + const Standard_Integer theCount) + { + myNodes = theNodes; + myCount = theCount; + } + + //! Returns interpolated value at the given point. + virtual ValueType Value (const PointType thePoint) const = 0; + +protected: + + //! Array of control points. + const Node* myNodes; + + //! Total number of control points. + Standard_Integer myCount; +}; + +#endif // _Graphic3d_TransferFunctionFilter_HeaderFile diff --git a/src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.hxx b/src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.hxx new file mode 100644 index 0000000000..2d11e054af --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.hxx @@ -0,0 +1,33 @@ +// Created on: 2015-01-28 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_TransferFunctionLinearFilter_HeaderFile +#define _Graphic3d_TransferFunctionLinearFilter_HeaderFile + +#include + +//! Linear filter used for generating discretization table. +template +class Graphic3d_TransferFunctionLinearFilter : public Graphic3d_TransferFunctionFilter +{ +public: + + //! Returns interpolated value at the given point. + virtual ValueType Value (const PointType thePoint) const Standard_OVERRIDE; +}; + +#include + +#endif // _Graphic3d_TransferFunctionLinearFilter_HeaderFile diff --git a/src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.lxx b/src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.lxx new file mode 100644 index 0000000000..084bf2590a --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunctionLinearFilter.lxx @@ -0,0 +1,70 @@ +// Created on: 2015-01-28 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +namespace Graphic3d_TransferFunctionTools +{ + template + struct Mix + { + static T Get (const T theVal1, + const T theVal2, + const Standard_Real theAlpha) + { + return static_cast (theVal1 * (1.0 - theAlpha) + theVal2 * theAlpha); + } + + static NCollection_Vec3 Get (const NCollection_Vec3& theVal1, + const NCollection_Vec3& theVal2, + const Standard_Real theAlpha) + { + return NCollection_Vec3 (Get (theVal1.x(), theVal2.x(), theAlpha), + Get (theVal1.y(), theVal2.y(), theAlpha), + Get (theVal1.z(), theVal2.z(), theAlpha)); + } + }; +} + +//======================================================================== +//function : Value +//purpose : +//======================================================================== +template +ValueType Graphic3d_TransferFunctionLinearFilter::Value (const PointType thePoint) const +{ + Standard_ASSERT_RAISE (myCount > 1, + "Error! Transfer function must contain a least 2 control points"); + + if (thePoint <= myNodes[0].Point) + { + return myNodes[0].Value; + } + + for (Standard_Integer anIndex = 1; anIndex < myCount; ++anIndex) + { + if (thePoint < myNodes[anIndex].Point) + { + const Node& aLft = myNodes[anIndex - 1]; + const Node& aRgh = myNodes[anIndex ]; + + return Graphic3d_TransferFunctionTools::Mix::Get ( + aLft.Value, aRgh.Value, (thePoint - aLft.Point) / static_cast (aRgh.Point - aLft.Point)); + } + } + + return myNodes[myCount - 1].Value; +} diff --git a/src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.hxx b/src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.hxx new file mode 100644 index 0000000000..70b3d8ab3e --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.hxx @@ -0,0 +1,33 @@ +// Created on: 2015-01-28 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_TransferFunctionNearestFilter_HeaderFile +#define _Graphic3d_TransferFunctionNearestFilter_HeaderFile + +#include + +//! Nearest filter used for generating discretization table. +template +class Graphic3d_TransferFunctionNearestFilter : public Graphic3d_TransferFunctionFilter +{ +public: + + //! Returns nearest value at the given point. + virtual ValueType Value (const PointType thePoint) const Standard_OVERRIDE; +}; + +#include + +#endif // _Graphic3d_TransferFunctionNearestFilter_HeaderFile \ No newline at end of file diff --git a/src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.lxx b/src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.lxx new file mode 100644 index 0000000000..9abcad8d25 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunctionNearestFilter.lxx @@ -0,0 +1,70 @@ +// Created on: 2015-01-28 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +namespace Graphic3d_TransferFunctionTools +{ + template + struct Nearest + { + static ValueType Get (const Graphic3d_TransferFunctionNode& theNode1, + const Graphic3d_TransferFunctionNode& theNode2, + const PointType& thePoint) + { + const PointType aHalfDistance = (theNode2.Point - theNode1.Point) / static_cast(2); + if ( (thePoint - theNode1.Point) < aHalfDistance) + { + return theNode1.Value; + } + else + { + return theNode2.Value; + } + } + }; +} + +//======================================================================== +//function : Value +//purpose : +//======================================================================== +template +ValueType Graphic3d_TransferFunctionNearestFilter::Value (const PointType thePoint) const +{ + Standard_ASSERT_RAISE (myCount > 1, + "Error! Transfer function must contain a least 2 control points"); + + if (thePoint <= myNodes[0].Point) + { + return myNodes[0].Value; + } + else + { + for (Standard_Integer anIndex = 1; anIndex < myCount; ++anIndex) + { + const Node& aLeft = myNodes[anIndex - 1]; + const Node& aRight = myNodes[anIndex ]; + + if (thePoint <= aRight.Point) + { + return Graphic3d_TransferFunctionTools::Nearest::Get (aLeft, aRight, thePoint); + } + } + + return myNodes[myCount - 1].Value; + } +} diff --git a/src/Graphic3d/Graphic3d_TransferFunctionNode.hxx b/src/Graphic3d/Graphic3d_TransferFunctionNode.hxx new file mode 100644 index 0000000000..a67f31c8d7 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransferFunctionNode.hxx @@ -0,0 +1,47 @@ +// Created on: 2014-12-25 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_TransferFunctionNode_HeaderFile +#define _Graphic3d_TransferFunctionNode_HeaderFile + +#include + +//! Describes control point (knot) of the transfer function. +template +struct Graphic3d_TransferFunctionNode +{ + //! Position of control point. + PointType Point; + + //! Property at the control point. + ValueType Value; + + //! Creates unitialized control point. + Graphic3d_TransferFunctionNode() + { + // + } + + //! Creates new control point. + Graphic3d_TransferFunctionNode (const PointType thePoint, + const ValueType theValue) + : Point (thePoint), + Value (theValue) + { + // + } +}; + +#endif // _Graphic3d_TransferFunctionNode_HeaderFile diff --git a/src/Graphic3d/Graphic3d_Volume.cxx b/src/Graphic3d/Graphic3d_Volume.cxx new file mode 100644 index 0000000000..ba0ea3adbf --- /dev/null +++ b/src/Graphic3d/Graphic3d_Volume.cxx @@ -0,0 +1,73 @@ +// Created on: 2014-12-12 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +IMPLEMENT_STANDARD_HANDLE (Graphic3d_Volume, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Volume, Standard_Transient) + +//================================================= +//function : Graphic3d_Volume +//purpose : +//================================================= +Graphic3d_Volume::Graphic3d_Volume() +: myNumOfSamples (1000), + myOpacityScale (1.0f), + myApplyShading (Standard_False), + myTriCubFilter (Standard_False), + myTraceShadows (Standard_False), + myRandomShift (Standard_False) +{ + Init(); +} + +//================================================= +//function : ~Graphic3d_Volume +//purpose : +//================================================= +Graphic3d_Volume::~Graphic3d_Volume() +{ + // +} + +//================================================= +//function : Init +//purpose : +//================================================= +Standard_Boolean Graphic3d_Volume::Init() +{ + if (myShaderProgram.IsNull()) + { + myShaderProgram = new Graphic3d_ShaderProgram(); + } + + const TCollection_AsciiString& aShaderFolder = Graphic3d_ShaderProgram::ShadersFolder(); + + if (!myShaderProgram->AttachShader (Graphic3d_ShaderObject:: + CreateFromFile (Graphic3d_TOS_VERTEX, aShaderFolder + "/VolumeRender.vs"))) + { + return Standard_False; + } + + if (!myShaderProgram->AttachShader (Graphic3d_ShaderObject:: + CreateFromFile (Graphic3d_TOS_FRAGMENT, aShaderFolder + "/VolumeRender.fs"))) + { + return Standard_False; + } + + return Standard_True; +} + diff --git a/src/Graphic3d/Graphic3d_Volume.hxx b/src/Graphic3d/Graphic3d_Volume.hxx new file mode 100644 index 0000000000..c28556f5ac --- /dev/null +++ b/src/Graphic3d/Graphic3d_Volume.hxx @@ -0,0 +1,239 @@ +// Created on: 2014-12-12 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_Volume_HeaderFile +#define _Graphic3d_Volume_HeaderFile + +#include +#include +#include + +//! Contains definition of 3D volume object. +class Graphic3d_Volume : public Standard_Transient +{ +public: + + //! Creates uninitialized volume object. + Standard_EXPORT Graphic3d_Volume(); + + //! Release resources of volume object. + Standard_EXPORT virtual ~Graphic3d_Volume(); + +public: + + //! Returns volumetric data attached to the volume. + const Handle(Graphic3d_VolumeData)& VolumeData() const + { + return myVolumeData; + } + + //! Attaches the given volumetric data to the volume. + void AttachVolumeData (const Handle(Graphic3d_VolumeData)& theData) + { + myVolumeData = theData; + } + + //! Returns transfer function attached to the volume. + const Handle(Graphic3d_TransferFunction)& TransferFunction() const + { + return myTransFunction; + } + + //! Attaches the given transfer function to the volume. + void AttachTransferFunction (const Handle(Graphic3d_TransferFunction)& theTransFunc) + { + myTransFunction = theTransFunc; + } + + //! Returns maximum number of samples per ray. + Standard_Integer NumOfSamples() const + { + return myNumOfSamples; + } + + //! Sets maximum number of samples per ray. + void SetNumOfSamples (const Standard_Integer theNbOfSamples) + { + myNumOfSamples = theNbOfSamples; + } + + //! Returns scaling factor for volume opacity. + Standard_ShortReal OpacityScale() const + { + return myOpacityScale; + } + + //! Sets scaling factor for volume opacity. + void SetOpacityScale (const Standard_ShortReal theOpacityScale) + { + myOpacityScale = theOpacityScale; + } + + //! Checks if tri-cubic volume filtering is enabled. + Standard_Boolean TriCubFilter() const + { + return myTriCubFilter; + } + + //! Enables/disables tri-cubic volume filtering. + void SetTriCubFilter (const Standard_Boolean theIsEnabled) + { + myTriCubFilter = theIsEnabled; + } + + //! Checks if volume shading is enabled. + Standard_Boolean ApplyShading() const + { + return myApplyShading; + } + + //! Enables/disables volume shading. + void SetApplyShading (const Standard_Boolean theIsEnabled) + { + myApplyShading = theIsEnabled; + } + + //! Checks if tracing of shadow rays is enabled. + Standard_Boolean TraceShadows() const + { + return myTraceShadows; + } + + //! Enables/disables tracing of shadow rays. + void SetTraceShadows (const Standard_Boolean theIsEnabled) + { + myTraceShadows = theIsEnabled; + } + + //! Checks if random shift of rays is enabled. + Standard_Boolean RandomShift() const + { + return myRandomShift; + } + + //! Enables/disables random shift of rays. + void SetRandomShift (const Standard_Boolean theIsEnabled) + { + myRandomShift = theIsEnabled; + } + + //! Checks if iso-surface rendering is enabled. + Standard_Boolean IsoSurfaceMode() const + { + return myIsoSurfaceMode; + } + + //! Enables/disables iso-surface rendering. + void SetIsoSurfaceMode (const Standard_Boolean theIsEnabled) + { + myIsoSurfaceMode = theIsEnabled; + } + + //! Checks if 2D slice rendering is enabled. + Standard_Boolean SliceMode() const + { + return mySliceMode; + } + + //! Enables/disables 2D slice rendering. + void SetSliceMode (const Standard_Boolean theIsEnabled) + { + mySliceMode = theIsEnabled; + } + + //! Normalized [0, 1]. + Standard_ShortReal IsoSurfaceLevel() const + { + return myIsoSurfaceLevel; + } + + //! Normalized [0, 1]. + void SetIsoSurfaceLevel (const Standard_ShortReal theValue) + { + myIsoSurfaceLevel = theValue; + } + + //! Normalized [0, 1]. + Standard_ShortReal SliceLevel() const + { + return mySliceLevel; + } + + //! Normalized [0, 1]. + void SetSliceLevel (const Standard_ShortReal theValue) + { + mySliceLevel = theValue; + } + + //! Returns shader program used for volume visualization. + Handle(Graphic3d_ShaderProgram) ShaderProgram() + { + return myShaderProgram; + } + +protected: + + //! Initializes volume rendering options. + Standard_EXPORT virtual Standard_Boolean Init(); + +protected: + + //! Maximum number of samples per ray. + Standard_Integer myNumOfSamples; + + //! Scaling factor for volume opacity. + Standard_ShortReal myOpacityScale; + + //! Enables/disables volume shading. + Standard_Boolean myApplyShading; + + //! Enables/disables tri-cubic filtering. + Standard_Boolean myTriCubFilter; + + //! Enables/disables tracing of shadow rays. + Standard_Boolean myTraceShadows; + + //! Enables/disables random shift of rays. + Standard_Boolean myRandomShift; + + //! Enables/disables iso-surface rendering. + Standard_Boolean myIsoSurfaceMode; + + //! Enables/disables 2D slice rendering. + Standard_Boolean mySliceMode; + + Standard_ShortReal myIsoSurfaceLevel; + Standard_ShortReal mySliceLevel; + +protected: + + // Volumetric data for visualization. + Handle(Graphic3d_VolumeData) myVolumeData; + + //! Shader program used for volume visualization. + Handle(Graphic3d_ShaderProgram) myShaderProgram; + + //! Transfer function used for colorizing volume. + Handle(Graphic3d_TransferFunction) myTransFunction; + +public: + + DEFINE_STANDARD_RTTI (Graphic3d_Volume) + +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_Volume, Standard_Transient) + +#endif // _Graphic3d_Volume_HeaderFile diff --git a/src/Graphic3d/Graphic3d_VolumeData.cxx b/src/Graphic3d/Graphic3d_VolumeData.cxx new file mode 100644 index 0000000000..2114b1ae13 --- /dev/null +++ b/src/Graphic3d/Graphic3d_VolumeData.cxx @@ -0,0 +1,78 @@ +// Created on: 2014-12-24 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_HANDLE (Graphic3d_VolumeData, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_VolumeData, Standard_Transient) + +//======================================================================== +//function : Graphic3d_VolumeData +//purpose : +//======================================================================== +Graphic3d_VolumeData::Graphic3d_VolumeData() +: myNbVoxX (1), + myNbVoxY (1), + myNbVoxZ (1), + myState (1) +{ + // +} + +//======================================================================== +//function : Graphic3d_VolumeData +//purpose : +//======================================================================== +Graphic3d_VolumeData::Graphic3d_VolumeData (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ) +: myState (1) +{ + init (theBounds, + theNbVoxX, + theNbVoxY, + theNbVoxZ); +} + +//======================================================================== +//function : ~Graphic3d_VolumeData +//purpose : +//======================================================================== +Graphic3d_VolumeData::~Graphic3d_VolumeData() +{ + // +} + +//======================================================================== +//function : init +//purpose : +//======================================================================== +void Graphic3d_VolumeData::init (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ) +{ + myBounds = theBounds; + + myNbVoxX = theNbVoxX; + myNbVoxY = theNbVoxY; + myNbVoxZ = theNbVoxZ; + + myVoxSize = myBounds.Size() * Graphic3d_Vec3d ( + 1.0 / static_cast (theNbVoxX), + 1.0 / static_cast (theNbVoxY), + 1.0 / static_cast (theNbVoxZ)); +} diff --git a/src/Graphic3d/Graphic3d_VolumeData.hxx b/src/Graphic3d/Graphic3d_VolumeData.hxx new file mode 100644 index 0000000000..49310fd44a --- /dev/null +++ b/src/Graphic3d/Graphic3d_VolumeData.hxx @@ -0,0 +1,147 @@ +// Created on: 2014-12-24 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_VolumeData_HeaderFile +#define _Graphic3d_VolumeData_HeaderFile + +#include +#include + +//! Base class for voxel-based volumetric data. +class Graphic3d_VolumeData : public Standard_Transient +{ +public: + + //! Creates empty volumetric data. + Standard_EXPORT Graphic3d_VolumeData(); + + //! Creates volumetric data with the given dimensions. + Standard_EXPORT Graphic3d_VolumeData (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ); + + //! Release resources of volumetric data. + Standard_EXPORT virtual ~Graphic3d_VolumeData(); + +public: + + //! Returns bounding box of volumetric data. + const BVH_Box3d& Bounds() const + { + return myBounds; + } + + //! Sets bounding box of volumetric data. + void SetBounds (const BVH_Box3d& theBounds) + { + myBounds = theBounds; + } + + //! Returns number of voxels in X dimension. + Standard_Integer NbVoxelX() const + { + return myNbVoxX; + } + + //! Returns number of voxels in Y dimension. + Standard_Integer NbVoxelY() const + { + return myNbVoxY; + } + + //! Returns number of voxels in Z dimension. + Standard_Integer NbVoxelZ() const + { + return myNbVoxZ; + } + + //! Returns center of the given voxel. + Graphic3d_Vec3d VoxelCenter (const Standard_Integer theIndexX, + const Standard_Integer theIndexY, + const Standard_Integer theIndexZ) const + { + return myBounds.CornerMin() + myVoxSize * + Graphic3d_Vec3d (static_cast (theIndexX + 0.5), + static_cast (theIndexY + 0.5), + static_cast (theIndexZ + 0.5)); + } + + //! Returns origin (minimum corner) of the given voxel. + Graphic3d_Vec3d VoxelOrigin (const Standard_Integer theIndexX, + const Standard_Integer theIndexY, + const Standard_Integer theIndexZ) const + { + return myBounds.CornerMin() + myVoxSize * + Graphic3d_Vec3d (static_cast (theIndexX), + static_cast (theIndexY), + static_cast (theIndexZ)); + } + + //! Checks if volumetric data is dense. + virtual Standard_Boolean IsDense() const + { + return Standard_False; + } + + //! Returns current state of volumetric data (must be updated by application). + Standard_Size State() const + { + return myState; + } + + //! Updates current state of volumetric data (affects the rendering). + void Update() + { + ++myState; + } + +protected: + + //! Reinitializes volumetric data. + Standard_EXPORT virtual void init (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ); + +protected: + + //! Bounding box of volumetric data. + BVH_Box3d myBounds; + + //! Number of voxels in X dimension. + Standard_Integer myNbVoxX; + //! Number of voxels in Y dimension. + Standard_Integer myNbVoxY; + //! Number of voxels in Z dimension. + Standard_Integer myNbVoxZ; + + //! Size of single voxel (grid step). + Graphic3d_Vec3d myVoxSize; + +private: + + //! Current state of the data. + Standard_Size myState; + +public: + + DEFINE_STANDARD_RTTI (Graphic3d_VolumeData) + +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_VolumeData, Standard_Transient) + +#endif // _Graphic3d_VolumeData_HeaderFile diff --git a/src/NCollection/NCollection_Vec3.hxx b/src/NCollection/NCollection_Vec3.hxx index e0568a25c8..94554aeb4a 100644 --- a/src/NCollection/NCollection_Vec3.hxx +++ b/src/NCollection/NCollection_Vec3.hxx @@ -327,6 +327,15 @@ public: return aCopy; } + //! Convert the vector. + template + NCollection_Vec3 Convert() const + { + return NCollection_Vec3 (static_cast (v[0]), + static_cast (v[1]), + static_cast (v[2])); + } + //! Computes the cross product. static NCollection_Vec3 Cross (const NCollection_Vec3& theVec1, const NCollection_Vec3& theVec2) diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index 7cf6f41472..511b1f2a98 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -153,5 +153,26 @@ OpenGl_VertexBufferCompat.cxx OpenGl_VertexBufferCompat.hxx OpenGl_VertexBufferEditor.hxx OpenGl_View_Raytrace.cxx -OpenGl_TextBuilder.hxx -OpenGl_TextBuilder.cxx \ No newline at end of file +OpenGl_Flipper.hxx +OpenGl_Flipper.cxx +OpenGl_BVHTreeSelector.hxx +OpenGl_BVHTreeSelector.cxx +OpenGl_BVHClipPrimitiveSet.cxx +OpenGl_BVHClipPrimitiveSet.hxx +OpenGl_ArbTexBindless.hxx +Handle_OpenGl_Sampler.hxx +OpenGl_Sampler.hxx +OpenGl_Sampler.cxx +OpenGl_Utils.hxx +OpenGl_Quadric.hxx +OpenGl_Quadric.cxx +OpenGl_Cylinder.hxx +OpenGl_Cylinder.cxx +OpenGl_Disk.hxx +OpenGl_Disk.cxx +OpenGl_Sphere.hxx +OpenGl_Sphere.cxx +OpenGl_BackgroundArray.hxx +OpenGl_BackgroundArray.cxx +OpenGl_Volume.hxx +OpenGl_Volume.cxx diff --git a/src/OpenGl/OpenGl_Group.cxx b/src/OpenGl/OpenGl_Group.cxx index 19bca09c77..705ee38d13 100644 --- a/src/OpenGl/OpenGl_Group.cxx +++ b/src/OpenGl/OpenGl_Group.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -200,6 +201,23 @@ void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theTy Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax); } +// ======================================================================= +// function : AddVolume +// purpose : +// ======================================================================= +void OpenGl_Group::AddVolume (const Handle(Graphic3d_Volume)& theVolume, + const Standard_Boolean theToEvalMinMax) +{ + if (IsDeleted()) + { + return; + } + + AddElement (new OpenGl_Volume (theVolume)); + + Graphic3d_Group::AddVolume (theVolume, theToEvalMinMax); +} + // ======================================================================= // function : Text // purpose : diff --git a/src/OpenGl/OpenGl_Group.hxx b/src/OpenGl/OpenGl_Group.hxx index 2ed5401cdd..d1899d952f 100644 --- a/src/OpenGl/OpenGl_Group.hxx +++ b/src/OpenGl/OpenGl_Group.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,10 @@ public: const Handle(Graphic3d_BoundBuffer)& theBounds, const Standard_Boolean theToEvalMinMax); + //! Add a volume data for display + Standard_EXPORT virtual void AddVolume (const Handle(Graphic3d_Volume)& theVolume, + const Standard_Boolean theToEvalMinMax = Standard_True); + //! Add text element Standard_EXPORT virtual void Text (const Standard_CString theTextUtf, const Graphic3d_Vertex& thePoint, diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 0f08435216..3306d00803 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -747,3 +747,94 @@ bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx, return false; #endif } + +// ======================================================================= +// function : Init3D +// purpose : +// ======================================================================= +bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx, + const Standard_Integer theSizeX, + const Standard_Integer theSizeY, + const Standard_Integer theSizeZ, + const OpenGl_TextureFormat& theFormat, + const void* thePixels) +{ + if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (1, 2)) + { + return false; + } + + myTarget = GL_TEXTURE_3D; + + const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX); + const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY); + const GLsizei aSizeZ = Min (theCtx->MaxTextureSize(), theSizeZ); + + Bind (theCtx); + + if (myParams->Filter() == Graphic3d_TOTF_NEAREST) + { + glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else + { + glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + //const GLint anIntFormat = theFormat.Internal(); + //myTextFormat = theFormat.Format(); + + theCtx->core15->glTexImage3D (GL_PROXY_TEXTURE_3D, + 0, + theFormat.Internal(), + aSizeX, + aSizeY, + aSizeZ, + 0, + theFormat.Format(), + theFormat.DataType(), + NULL); + + GLint aTestSizeX = 0; + GLint aTestSizeY = 0; + GLint aTestSizeZ = 0; + + glGetTexLevelParameteriv ( + GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &aTestSizeX); + glGetTexLevelParameteriv ( + GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &aTestSizeY); + glGetTexLevelParameteriv ( + GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &aTestSizeZ); + + if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0) + { + Unbind (theCtx); + return false; + } + + theCtx->core15->glTexImage3D (GL_TEXTURE_3D, + 0, + theFormat.Internal(), + aSizeX, + aSizeY, + aSizeZ, + 0, + theFormat.Format(), + theFormat.DataType(), + thePixels); + + if (glGetError() != GL_NO_ERROR) + { + Unbind (theCtx); + return false; + } + + mySizeX = aSizeX; + mySizeY = aSizeY; + mySizeZ = aSizeZ; + + Unbind (theCtx); + return true; +} diff --git a/src/OpenGl/OpenGl_Texture.hxx b/src/OpenGl/OpenGl_Texture.hxx index 1a1a0ed955..744d6cd3b4 100644 --- a/src/OpenGl/OpenGl_Texture.hxx +++ b/src/OpenGl/OpenGl_Texture.hxx @@ -49,6 +49,11 @@ struct OpenGl_TextureFormatSelector return GL_NONE; } } + + static GLint DataType() + { + return GL_UNSIGNED_BYTE; + } }; template<> @@ -70,6 +75,11 @@ struct OpenGl_TextureFormatSelector return GL_NONE; } } + + static GLint DataType() + { + return GL_UNSIGNED_SHORT; + } }; template<> @@ -91,6 +101,11 @@ struct OpenGl_TextureFormatSelector return GL_NONE; } } + + static GLint DataType() + { + return GL_FLOAT; + } }; //! Stores parameters of OpenGL texture format. @@ -124,25 +139,36 @@ public: return myInternal; } + //! Returns OpenGL data type of the pixel data. + inline GLint DataType() const + { + return myDataType; + } + //! Returns texture format for specified type and number of channels. template static OpenGl_TextureFormat Create() { - return OpenGl_TextureFormat (N, OpenGl_TextureFormatSelector::Internal (N)); + return OpenGl_TextureFormat (N, + OpenGl_TextureFormatSelector::Internal (N), + OpenGl_TextureFormatSelector::DataType ()); } private: //! Creates new texture format. OpenGl_TextureFormat (const GLint theChannels, - const GLint theInternal) + const GLint theInternal, + const GLint theDataType) : myInternal (theInternal), - myChannels (theChannels) {} + myChannels (theChannels), + myDataType (theDataType) {} private: GLint myInternal; //!< OpenGL internal format of the pixel data GLint myChannels; //!< Number of channels for each pixel (from 1 to 4) + GLint myDataType; //!< OpenGL data type of input pixel data }; @@ -254,6 +280,14 @@ public: const Standard_Integer theSizeY, const OpenGl_TextureFormat& theFormat); + //! Initializes 3D texture rectangle with specified format and size. + Standard_EXPORT bool Init3D (const Handle(OpenGl_Context)& theCtx, + const Standard_Integer theSizeX, + const Standard_Integer theSizeY, + const Standard_Integer theSizeZ, + const OpenGl_TextureFormat& theFormat, + const void* thePixels); + //! @return true if texture was generated within mipmaps Standard_EXPORT const Standard_Boolean HasMipmaps() const; @@ -276,6 +310,7 @@ protected: GLenum myTarget; //!< GL_TEXTURE_1D/GL_TEXTURE_2D GLsizei mySizeX; //!< texture width GLsizei mySizeY; //!< texture height + GLsizei mySizeZ; //!< texture depth GLenum myTextFormat; //!< texture format - GL_RGB, GL_RGBA,... Standard_Boolean myHasMipmaps; //!< flag indicates that texture was uploaded with mipmaps bool myIsAlpha; //!< indicates alpha format diff --git a/src/OpenGl/OpenGl_Volume.cxx b/src/OpenGl/OpenGl_Volume.cxx new file mode 100644 index 0000000000..335a63db13 --- /dev/null +++ b/src/OpenGl/OpenGl_Volume.cxx @@ -0,0 +1,520 @@ +// Created on: 2014-12-10 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include +#include + +// Use this macro to output debug info +#define VOLUME_RENDER_PRINT_INFO + +// ======================================================================= +// function : OpenGl_Volume +// purpose : +// ======================================================================= +OpenGl_Volume::OpenGl_Volume (const Handle(Graphic3d_Volume)& theVolume) +: OpenGl_Element() +{ + // Set invalid states + myVolumeDataState = 0; + myTransFunctState = 0; + + Standard_ASSERT_RAISE (!theVolume.IsNull(), + "Error: Graphic 3D volume object is NULL!"); + + myVolumeSource = theVolume; + + srand (static_cast (time (NULL))); +} + +// ======================================================================= +// function : ~OpenGl_Volume +// purpose : +// ======================================================================= +OpenGl_Volume::~OpenGl_Volume() +{ + // +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void OpenGl_Volume::Release (OpenGl_Context* theContext) +{ + if (!myVolumeDataTex.IsNull()) + { + myVolumeDataTex->Release (theContext); + } + + if (!myTransFunctTex.IsNull()) + { + myTransFunctTex->Release (theContext); + } + + if (myDummyQuad.IsValid()) + { + myDummyQuad.Release (theContext); + } +} + +// ======================================================================= +// function : BuildProgram +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Volume::BuildProgram (const Handle(OpenGl_Context)& theContext) const +{ + if (myIsProgramReady) + { + return Standard_True; + } + + myIsProgramReady = Standard_True; + + if (myVolumeProgGL.IsNull()) + { + TCollection_AsciiString aKey; + + myIsProgramReady &= theContext->ShaderManager()->Create ( + myVolumeSource->ShaderProgram(), aKey, myVolumeProgGL); + } + + if (myIsProgramReady) + { + GetUniformLocations (theContext); + } + + const GLfloat aVertices[] = { -1.f, -1.f, 0.f, + -1.f, 1.f, 0.f, + 1.f, 1.f, 0.f, + 1.f, 1.f, 0.f, + 1.f, -1.f, 0.f, + -1.f, -1.f, 0.f }; + + myDummyQuad.Init (theContext, 3, 6, aVertices); + + return myIsProgramReady = Standard_True; +} + +// ======================================================================= +// function : GetUniformLocations +// purpose : +// ======================================================================= +void OpenGl_Volume::GetUniformLocations (const Handle(OpenGl_Context)& theContext) const +{ + theContext->BindProgram (myVolumeProgGL); + + myLocation.CameraOriginLT = myVolumeProgGL->GetUniformLocation (theContext, "uOriginLT"); + myLocation.CameraOriginLB = myVolumeProgGL->GetUniformLocation (theContext, "uOriginLB"); + myLocation.CameraOriginRT = myVolumeProgGL->GetUniformLocation (theContext, "uOriginRT"); + myLocation.CameraOriginRB = myVolumeProgGL->GetUniformLocation (theContext, "uOriginRB"); + myLocation.CameraDirectLT = myVolumeProgGL->GetUniformLocation (theContext, "uDirectLT"); + myLocation.CameraDirectLB = myVolumeProgGL->GetUniformLocation (theContext, "uDirectLB"); + myLocation.CameraDirectRT = myVolumeProgGL->GetUniformLocation (theContext, "uDirectRT"); + myLocation.CameraDirectRB = myVolumeProgGL->GetUniformLocation (theContext, "uDirectRB"); + + myLocation.NumOfSamples = myVolumeProgGL->GetUniformLocation (theContext, "uNumOfSamples"); + myLocation.TriCubFilter = myVolumeProgGL->GetUniformLocation (theContext, "uTriCubFilter"); + myLocation.ApplyShading = myVolumeProgGL->GetUniformLocation (theContext, "uApplyShading"); + myLocation.TraceShadows = myVolumeProgGL->GetUniformLocation (theContext, "uTraceShadows"); + myLocation.RandomShift = myVolumeProgGL->GetUniformLocation (theContext, "uRandomShift"); + myLocation.VolTexelSize = myVolumeProgGL->GetUniformLocation (theContext, "uVolTexelSize"); + myLocation.NormMinValue = myVolumeProgGL->GetUniformLocation (theContext, "uNormMinValue"); + myLocation.NormMaxValue = myVolumeProgGL->GetUniformLocation (theContext, "uNormMaxValue"); + myLocation.OpacityScale = myVolumeProgGL->GetUniformLocation (theContext, "uOpacityScale"); + myLocation.BoxCornerMin = myVolumeProgGL->GetUniformLocation (theContext, "uBoxCornerMin"); + myLocation.BoxCornerMax = myVolumeProgGL->GetUniformLocation (theContext, "uBoxCornerMax"); + myLocation.TransferFunct = myVolumeProgGL->GetUniformLocation (theContext, "uTransferFunct"); + myLocation.VolumeTexture = myVolumeProgGL->GetUniformLocation (theContext, "uVolumeTexture"); + myLocation.RandomSeed = myVolumeProgGL->GetUniformLocation (theContext, "uRandomSeed"); + + myLocation.IsoSurfaceMode = myVolumeProgGL->GetUniformLocation (theContext, "uIsoSurfaceMode"); + myLocation.TraceSliceMode = myVolumeProgGL->GetUniformLocation (theContext, "uTraceSliceMode"); + + myLocation.IsoSurfaceLevel = myVolumeProgGL->GetUniformLocation (theContext, "uIsoSurfaceLevel"); + myLocation.TraceSliceLevel = myVolumeProgGL->GetUniformLocation (theContext, "uTraceSliceLevel"); +} + +// ======================================================================= +// function : SetUniformValues +// purpose : +// ======================================================================= +void OpenGl_Volume::SetUniformValues (const Handle(OpenGl_Context)& theContext, + const OpenGl_Vec3* theOrigins, + const OpenGl_Vec3* theDirects) const +{ + // Update state of volume and transfer function textures + if (!UpdateTextures (theContext)) + { + return; + } + + const Handle(Graphic3d_VolumeData)& aVolumeData = myVolumeSource->VolumeData(); + + // Set bounding box + myVolumeProgGL->SetUniform (theContext, + myLocation.BoxCornerMin, aVolumeData->Bounds().CornerMin().Convert()); + myVolumeProgGL->SetUniform (theContext, + myLocation.BoxCornerMax, aVolumeData->Bounds().CornerMax().Convert()); + + // Set texture samplers + myVolumeProgGL->SetUniform (theContext, myLocation.VolumeTexture, 0); + myVolumeProgGL->SetUniform (theContext, myLocation.TransferFunct, 1); + + // Set rendering options + myVolumeProgGL->SetUniform (theContext, myLocation.NumOfSamples, myVolumeSource->NumOfSamples()); + myVolumeProgGL->SetUniform (theContext, myLocation.OpacityScale, myVolumeSource->OpacityScale()); + myVolumeProgGL->SetUniform (theContext, myLocation.NormMinValue, static_cast (myNormMinValue)); + myVolumeProgGL->SetUniform (theContext, myLocation.NormMaxValue, static_cast (myNormMaxValue)); + myVolumeProgGL->SetUniform (theContext, myLocation.TriCubFilter, static_cast (myVolumeSource->TriCubFilter())); + myVolumeProgGL->SetUniform (theContext, myLocation.ApplyShading, static_cast (myVolumeSource->ApplyShading())); + myVolumeProgGL->SetUniform (theContext, myLocation.TraceShadows, static_cast (myVolumeSource->TraceShadows())); + myVolumeProgGL->SetUniform (theContext, myLocation.RandomShift, static_cast (myVolumeSource->RandomShift())); + + myVolumeProgGL->SetUniform (theContext, myLocation.IsoSurfaceMode, static_cast (myVolumeSource->IsoSurfaceMode())); + //myVolumeProgGL->SetUniform (theContext, myLocation.TraceSliceMode, static_cast (myVolumeSource->SliceMode())); + + myVolumeProgGL->SetUniform (theContext, myLocation.IsoSurfaceLevel, myVolumeSource->IsoSurfaceLevel()); + myVolumeProgGL->SetUniform (theContext, myLocation.TraceSliceLevel, myVolumeSource->SliceLevel()); + + // Set random seed for to reduce graphic artifacts. + const OpenGl_Vec4 aRandomSeed = OpenGl_Vec4 (static_cast (rand()), + static_cast (rand()), + static_cast (rand()), + static_cast (rand())); + + myVolumeProgGL->SetUniform (theContext, myLocation.RandomSeed, aRandomSeed); + + // Set 3D size of single voxel + const BVH_Vec3f aTexelSize = BVH_Vec3f (1.f / aVolumeData->NbVoxelX(), + 1.f / aVolumeData->NbVoxelX(), + 1.f / aVolumeData->NbVoxelZ()); + + myVolumeProgGL->SetUniform (theContext, myLocation.VolTexelSize, aTexelSize); + + // Set viewing position and orientation + myVolumeProgGL->SetUniform (theContext, myLocation.CameraOriginLB, theOrigins[0]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraOriginRB, theOrigins[1]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraOriginLT, theOrigins[2]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraOriginRT, theOrigins[3]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraDirectLB, theDirects[0]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraDirectRB, theDirects[1]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraDirectLT, theDirects[2]); + myVolumeProgGL->SetUniform (theContext, myLocation.CameraDirectRT, theDirects[3]); +} + +namespace +{ + struct OpenGl_VolumeDataWrapper + { + //! Returns OpenGL texture format. + virtual OpenGl_TextureFormat Format() const = 0; + + //! Returns raw volumetric data. + virtual const GLvoid* Voxels() const = 0; + }; + + template + class OpenGl_DenseVolumeDataWrapper : public OpenGl_VolumeDataWrapper + { + private: + + const Graphic3d_DenseVolumeData* myData; + + public: + + //! Creates new wrapper for dense volumetric data. + OpenGl_DenseVolumeDataWrapper (const Graphic3d_VolumeData& theData) + { + myData = static_cast* > (&theData); + } + + //! Returns OpenGL texture format. + virtual OpenGl_TextureFormat Format() const + { + return OpenGl_TextureFormat::Create(); + } + + //! Returns raw volumetric data. + virtual const GLvoid* Voxels() const + { + return &myData->Data()->First(); + } + }; +} + +// ======================================================================= +// function : UpdateTextures +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Volume::UpdateTextures (const Handle(OpenGl_Context)& theContext) const +{ + const Handle(Graphic3d_VolumeData)& aVolumeData = myVolumeSource->VolumeData(); + + if (aVolumeData.IsNull()) + { + return Standard_False; + } + + Handle(Graphic3d_TextureParams) aParams = new Graphic3d_TextureParams; + + // Set linear filtering of TF and volume data + aParams->SetFilter (Graphic3d_TOTF_TRILINEAR); + + if (myTransFunctTex.IsNull()) + myTransFunctTex = new OpenGl_Texture (aParams); + + if (myVolumeDataTex.IsNull()) + myVolumeDataTex = new OpenGl_Texture (aParams); + + if (myVolumeDataState != aVolumeData->State()) + { +#ifdef VOLUME_RENDER_PRINT_INFO + std::cout << "Info: Updating 3D volume texture" << std::endl; +#endif + + if (aVolumeData->IsDense()) + { + std::auto_ptr aWrapper; + + if (typeid (*aVolumeData) == typeid (Graphic3d_DenseVolumeData)) + { + aWrapper.reset (new OpenGl_DenseVolumeDataWrapper (*aVolumeData)); + } + else if (typeid (*aVolumeData) == typeid (Graphic3d_DenseVolumeData)) + { + aWrapper.reset (new OpenGl_DenseVolumeDataWrapper (*aVolumeData)); + } + else if (typeid (*aVolumeData) == typeid (Graphic3d_DenseVolumeData)) + { + aWrapper.reset (new OpenGl_DenseVolumeDataWrapper (*aVolumeData)); + } + + if (aWrapper.get() == NULL) + { + return Standard_False; + } + + Standard_Boolean aResult = myVolumeDataTex->Init3D (theContext, + aVolumeData->NbVoxelX(), + aVolumeData->NbVoxelY(), + aVolumeData->NbVoxelZ(), + aWrapper->Format(), + aWrapper->Voxels()); + if (!aResult) + { + return Standard_False; + } + } + else + { + // Sparse data are not supported + } + + myVolumeDataState = aVolumeData->State(); + } + + if (myTransFunctState != myVolumeSource->TransferFunction()->State()) + { +#ifdef VOLUME_RENDER_PRINT_INFO + std::cout << "Info: Updating transfer function texture" << std::endl; +#endif + + Handle(Image_PixMap) anImage = myVolumeSource->TransferFunction()->ImageTable (myNormMinValue, + myNormMaxValue); + + if (!myTransFunctTex->Init (theContext, *anImage, Graphic3d_TOT_1D)) + { + return Standard_False; + } + + myTransFunctState = myVolumeSource->TransferFunction()->State(); + } + + myVolumeDataTex->Bind (theContext, GL_TEXTURE0); + myTransFunctTex->Bind (theContext, GL_TEXTURE1); + + return Standard_True; +} + +// ======================================================================= +// function : UpdateCamera +// purpose : +// ======================================================================= +void OpenGl_Volume::UpdateCamera (const OpenGl_Mat4& theOrientation, + const OpenGl_Mat4& theViewMapping, + OpenGl_Vec3 theOrigins[4], + OpenGl_Vec3 theDirects[4]) const +{ + OpenGl_Mat4 theUnviewMat; + + // compute inverse model-view-projection matrix + (theViewMapping * theOrientation).Inverted (theUnviewMat); + + Standard_Integer aOriginIndex = 0; + Standard_Integer aDirectIndex = 0; + + for (Standard_Integer aY = -1; aY <= 1; aY += 2) + { + for (Standard_Integer aX = -1; aX <= 1; aX += 2) + { + OpenGl_Vec4 aOrigin (GLfloat(aX), + GLfloat(aY), + -1.0f, + 1.0f); + + aOrigin = theUnviewMat * aOrigin; + + aOrigin.x() = aOrigin.x() / aOrigin.w(); + aOrigin.y() = aOrigin.y() / aOrigin.w(); + aOrigin.z() = aOrigin.z() / aOrigin.w(); + + OpenGl_Vec4 aDirect (GLfloat(aX), + GLfloat(aY), + 1.0f, + 1.0f); + + aDirect = theUnviewMat * aDirect; + + aDirect.x() = aDirect.x() / aDirect.w(); + aDirect.y() = aDirect.y() / aDirect.w(); + aDirect.z() = aDirect.z() / aDirect.w(); + + aDirect = aDirect - aOrigin; + + GLdouble aInvLen = 1.0 / sqrt (aDirect.x() * aDirect.x() + + aDirect.y() * aDirect.y() + + aDirect.z() * aDirect.z()); + + theOrigins[aOriginIndex++] = OpenGl_Vec3 (static_cast (aOrigin.x()), + static_cast (aOrigin.y()), + static_cast (aOrigin.z())); + + theDirects[aDirectIndex++] = OpenGl_Vec3 (static_cast (aDirect.x() * aInvLen), + static_cast (aDirect.y() * aInvLen), + static_cast (aDirect.z() * aInvLen)); + } + } +} + +// ======================================================================= +// function : Render +// purpose : +// ======================================================================= +void OpenGl_Volume::Render (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + Standard_Boolean anIsGL20Supproted = + atof (reinterpret_cast (glGetString(GL_VERSION))) >= 2.0; + + if (!anIsGL20Supproted) + { + std::cerr << "Error: The current OpenGL version doesn't support Volume Rendering." + << std::endl << "Info: OpenGL version is must be not lower 2.0." << std::endl; + return ; + } + + const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); + + if (!myIsProgramReady) + { + BuildProgram (aContext); + } + + const Standard_Integer aSizeX = theWorkspace->Width(); + const Standard_Integer aSizeY = theWorkspace->Height(); + + glDisable (GL_DEPTH_TEST); + + myDummyQuad.Bind (aContext); + + if (myIsProgramReady) + { + aContext->BindProgram (myVolumeProgGL); + + OpenGl_Mat4 aOrientationMatrix = aContext->WorldViewState.Current(); + OpenGl_Mat4 aViewMappingMatrix = aContext->ProjectionState.Current(); + + OpenGl_Vec3 aOrigins[4]; + OpenGl_Vec3 aDirects[4]; + + UpdateCamera (aOrientationMatrix, + aViewMappingMatrix, + aOrigins, + aDirects); + + SetUniformValues (aContext, + aOrigins, + aDirects); + + myVolumeProgGL->SetUniform (theWorkspace->GetGlContext(), myLocation.TraceSliceMode, myVolumeSource->SliceMode() ? 2 : 0); + + aContext->ModelWorldState.Push(); + aContext->ProjectionState.Push(); + + aContext->ModelWorldState.SetIdentity(); + aContext->ProjectionState.SetIdentity(); + + aContext->ApplyModelWorldMatrix(); + aContext->ApplyProjectionMatrix(); + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + myDummyQuad.BindVertexAttrib (aContext, Graphic3d_TOA_POS); + { + aContext->core20fwd->glVertexAttribPointer ( + Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL); + + aContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6); + } + myDummyQuad.UnbindAttribute (aContext, Graphic3d_TOA_POS); + + if (myVolumeSource->SliceMode()) + { + glViewport (16, + 16, + Min (250, aSizeX - 16), + Min (250, aSizeY - 16)); + + myVolumeProgGL->SetUniform (theWorkspace->GetGlContext(), myLocation.TraceSliceMode, 1); + + myDummyQuad.BindVertexAttrib (aContext, Graphic3d_TOA_POS); + { + aContext->core20fwd->glVertexAttribPointer ( + Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL); + + aContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6); + } + myDummyQuad.UnbindAttribute (aContext, Graphic3d_TOA_POS); + + glViewport (0, 0, aSizeX, aSizeY); + } + + glDisable (GL_BLEND); + + aContext->ModelWorldState.Pop(); + aContext->ProjectionState.Pop(); + + aContext->ApplyModelWorldMatrix(); + aContext->ApplyProjectionMatrix(); + + aContext->BindProgram (NULL); + } + + myDummyQuad.Unbind (aContext); +} diff --git a/src/OpenGl/OpenGl_Volume.hxx b/src/OpenGl/OpenGl_Volume.hxx new file mode 100644 index 0000000000..7b0bf51804 --- /dev/null +++ b/src/OpenGl/OpenGl_Volume.hxx @@ -0,0 +1,166 @@ +// Created on: 2014-12-10 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef OpenGl_Volume_Header +#define OpenGl_Volume_Header + +#include +#include +#include +#include + +#include +#include + +//! Tool object for visualizing volumetric data. +class OpenGl_Volume : public OpenGl_Element +{ +public: + + //! Creates new 3D volume from the base object. + Standard_EXPORT OpenGl_Volume (const Handle(Graphic3d_Volume)& theVolume); + + //! Releases resources of 3D volume. + Standard_EXPORT virtual ~OpenGl_Volume(); + +public: + + //! Releases GPU resources. + Standard_EXPORT virtual void Release (OpenGl_Context* theContext); + + //! Performs volumetric rendering with direct ray-casting. + Standard_EXPORT virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; + +private: + + //! Retrieves uniform locations from the shader program. + void GetUniformLocations (const Handle(OpenGl_Context)& theContext) const; + + //! Updates volume data and transfer function textures. + Standard_Boolean UpdateTextures (const Handle(OpenGl_Context)& theContext) const; + + //! Sets uniform value for active shader program. + void SetUniformValues (const Handle(OpenGl_Context)& theContext, + const OpenGl_Vec3* theOrigins, + const OpenGl_Vec3* theDirects) const; + + //! Builds shader program for volume ray-casting. + Standard_Boolean BuildProgram (const Handle(OpenGl_Context)& theContext) const; + + //! Updates viewing parameters used in volume ray-casting. + void UpdateCamera (const OpenGl_Mat4& theOrientation, + const OpenGl_Mat4& theViewMapping, + OpenGl_Vec3 theOrigins[4], + OpenGl_Vec3 theDirects[4]) const; + +protected: + + //! 3D volume source. + Handle(Graphic3d_Volume) myVolumeSource; + + //! Ready-to-use state of volumetric data. + mutable Standard_Size myVolumeDataState; + + //! Ready-to-use state of transfer function. + mutable Standard_Size myTransFunctState; + + //! Is shader program ready? + mutable Standard_Boolean myIsProgramReady; + + //! OpenGL 3D volumetric data texture. + mutable Handle(OpenGl_Texture) myVolumeDataTex; + + //! OpenGL 1D transfer function texture. + mutable Handle(OpenGl_Texture) myTransFunctTex; + + //! Shader program used for volume rendering. + mutable Handle(OpenGl_ShaderProgram) myVolumeProgGL; + + //! Stores location of uniform variables. + mutable struct Location + { + GLint BoxCornerMin; + GLint BoxCornerMax; + GLint NumOfSamples; + GLint TriCubFilter; + GLint ApplyShading; + GLint TraceShadows; + GLint RandomShift; + GLint OpacityScale; + GLint VolTexelSize; + GLint NormMinValue; + GLint NormMaxValue; + GLint TransferFunct; + GLint VolumeTexture; + GLint RandomSeed; + GLint CameraOriginLT; + GLint CameraOriginLB; + GLint CameraOriginRT; + GLint CameraOriginRB; + GLint CameraDirectLT; + GLint CameraDirectLB; + GLint CameraDirectRT; + GLint CameraDirectRB; + GLint IsoSurfaceMode; + GLint TraceSliceMode; + GLint IsoSurfaceLevel; + GLint TraceSliceLevel; + + Location() + : BoxCornerMin (-1), + BoxCornerMax (-1), + NumOfSamples (-1), + TriCubFilter (-1), + ApplyShading (-1), + TraceShadows (-1), + RandomShift (-1), + OpacityScale (-1), + VolTexelSize (-1), + TransferFunct (-1), + VolumeTexture (-1), + RandomSeed (-1), + CameraOriginLT (-1), + CameraOriginLB (-1), + CameraOriginRT (-1), + CameraOriginRB (-1), + CameraDirectLT (-1), + CameraDirectLB (-1), + CameraDirectRT (-1), + CameraDirectRB (-1), + IsoSurfaceMode (-1), + TraceSliceMode (-1), + IsoSurfaceLevel (-1), + TraceSliceLevel (-1) + { + // + } + + } myLocation; + + //! Screen-size quad for volume ray-casting. + mutable OpenGl_VertexBuffer myDummyQuad; + + //! Normalized min value of the scalar field. + mutable Standard_Real myNormMinValue; + + //! Normalized max value of the scalar field. + mutable Standard_Real myNormMaxValue; + +public: + + DEFINE_STANDARD_ALLOC +}; + +#endif // OpenGl_Volume_Header diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx index 2b3f6e271c..a69dc8b235 100644 --- a/src/QABugs/QABugs_19.cxx +++ b/src/QABugs/QABugs_19.cxx @@ -691,53 +691,6 @@ static Standard_Integer OCC23945 (Draw_Interpretor& /*di*/,Standard_Integer n, c return 0; } -#include -#include -#include -static Standard_Integer OCC24019 (Draw_Interpretor& di, Standard_Integer argc, const char** argv) -{ - if ( argc != 2 ) { - di << "Error: " << argv[0] << " - invalid number of arguments" << "\n"; - return 1; - } - - TCollection_AsciiString aFileName = argv[1]; - TopoDS_Shape aShape; - BRep_Builder aBuilder; - - if (!BRepTools::Read(aShape, aFileName.ToCString(), aBuilder)) { - di << "Error: Could not read a shape!" << "\n"; - return 1; - } - - TopoDS_Solid aShape1 = BRepPrimAPI_MakeSphere(gp_Pnt(20,25,35), 7); - - Standard_Real deflection = 0.005; - Standard_Integer nbThreads = 1; - Standard_Integer nbx = 200, nby = 200, nbz = 200; - Voxel_BoolDS theVoxels(0,0,0, 50, 50, 50, nbx, nby, nbz); - Voxel_BoolDS theVoxels1(0,0,0, 50, 50, 50, nbx, nby, nbz); - - Standard_Integer progress = 0; - Voxel_FastConverter fcp(aShape, theVoxels, deflection, nbx, nby, nbz, nbThreads); - fcp.ConvertUsingSAT(progress, 1); - fcp.FillInVolume(1); - - Voxel_FastConverter fcp1(aShape1, theVoxels1, deflection, nbx, nby, nbz, nbThreads); - fcp1.ConvertUsingSAT(progress, 1); - fcp1.FillInVolume(1); - - Voxel_BooleanOperation op; - Standard_Boolean result = op.Cut(theVoxels1, theVoxels); - if ( result != 1 ) { - di << "Error: invalid boolean operation" << "\n"; - } else { - di << "OK: boolean operation is ok" << "\n"; - } - - return 0; -} - //======================================================================= //function : OCC11758 //purpose : @@ -1331,34 +1284,6 @@ static Standard_Integer OCC24012 (Draw_Interpretor& di, Standard_Integer argc, c return 0; } -#include -static Standard_Integer OCC24051 (Draw_Interpretor& di, Standard_Integer argc, const char ** argv) -{ - if (argc != 1) { - di << "Usage : " << argv[0] << " should be one argument (command name only)"; - return 1; - } - - TopoDS_Shape shape = BRepPrimAPI_MakeBox(gp_Pnt(5, 10, 10), 10, 20, 30).Shape(); - Standard_Integer progress = 0; - Standard_Real deflection = 0.005; - Standard_Integer nbx = 200, nby = 200, nbz = 200; - Voxel_BoolDS theVoxels(-50,-50,-30, 100, 100, 100, nbx, nby, nbz); - Voxel_BoolDS theVoxels1(-50,-50,-30, 100, 100, 100, nbx, nby, nbz); - Standard_Integer nbThreads = 5; - Voxel_FastConverter fcp(shape, theVoxels, deflection, nbx, nby, nbz, nbThreads, Standard_True); - - #ifdef WNT - #pragma omp parallel for - for(int i = 0; i < nbThreads; i++) - fcp.ConvertUsingSAT(progress, i+1); - #endif - - fcp.ConvertUsingSAT(progress); - - return 0; -} - #include #include #include @@ -3947,7 +3872,6 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) { theCommands.Add ("test_offset", "test_offset", __FILE__, test_offset, group); theCommands.Add ("OCC23945", "OCC23945 surfname U V X Y Z [DUX DUY DUZ DVX DVY DVZ [D2UX D2UY D2UZ D2VX D2VY D2VZ D2UVX D2UVY D2UVZ]]", __FILE__, OCC23945,group); theCommands.Add ("OCC24008", "OCC24008 curve surface", __FILE__, OCC24008, group); - theCommands.Add ("OCC24019", "OCC24019 aShape", __FILE__, OCC24019, group); theCommands.Add ("OCC11758", "OCC11758", __FILE__, OCC11758, group); theCommands.Add ("OCC24005", "OCC24005 result", __FILE__, OCC24005, group); theCommands.Add ("OCC24137", "OCC24137 face vertex U V [N]", __FILE__, OCC24137, group); @@ -3956,7 +3880,6 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) { theCommands.Add ("OCC24370", "OCC24370 edge pcurve surface prec", __FILE__, OCC24370, group); theCommands.Add ("OCC24533", "OCC24533", __FILE__, OCC24533, group); theCommands.Add ("OCC24012", "OCC24012 face edge", __FILE__, OCC24012, group); - theCommands.Add ("OCC24051", "OCC24051", __FILE__, OCC24051, group); theCommands.Add ("OCC24086", "OCC24086 face wire", __FILE__, OCC24086, group); theCommands.Add ("OCC24622", "OCC24622 texture={1D|2D}\n Tests sourcing of 1D/2D pixmaps for AIS_TexturedShape", __FILE__, OCC24622, group); theCommands.Add ("OCC24667", "OCC24667 result Wire_spine Profile [Mode [Approx]], no args to get help", __FILE__, OCC24667, group); diff --git a/src/Shaders/TextRender.fs b/src/Shaders/TextRender.fs new file mode 100644 index 0000000000..371708b1bc --- /dev/null +++ b/src/Shaders/TextRender.fs @@ -0,0 +1,49 @@ +#extension GL_EXT_gpu_shader4 : enable + +varying vec2 TexCoord; + +uniform sampler2D ColorTexture; +uniform sampler2D DepthTexture; + +uniform vec3 Pixel; + +#define MAXFLOAT 1.0e15 + +#define ZERO vec3 (0.0, 0.0, 0.0) +#define ONES vec3 (1.0, 1.0, 1.0) + +// ======================================================================= +// function : getAlpha +// purpose : +// ======================================================================= +float getAlpha() +{ + return texture2D (ColorTexture, TexCoord.st).a; +} + +#define EPSILON 2.0e-5 + +// ======================================================================= +// function : main +// purpose : +// ======================================================================= +void main() +{ + vec2 aTexCoord = Pixel.xy / vec2 (textureSize2D (DepthTexture, 0)); + + vec2 aTexCoord1 = gl_FragCoord.xy / vec2 (textureSize2D (DepthTexture, 0)); + + vec4 aColor = vec4 (1.0); + + aColor.a *= getAlpha(); + + if (aColor.a <= 0.285) + discard; + + if (Pixel.z - EPSILON > texture2D (DepthTexture, aTexCoord).x) + discard; + + gl_FragDepth = 0.0; + + gl_FragColor = vec4 (aColor.xyz, aColor.a); +} \ No newline at end of file diff --git a/src/Shaders/TextRender.vs b/src/Shaders/TextRender.vs new file mode 100644 index 0000000000..e36cf9d387 --- /dev/null +++ b/src/Shaders/TextRender.vs @@ -0,0 +1,9 @@ +varying vec2 TexCoord; + +void main (void) +{ + TexCoord = occTexCoord.st; + + // Do fixed functionality vertex transform + gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex; +} \ No newline at end of file diff --git a/src/Shaders/VolumeRender.fs b/src/Shaders/VolumeRender.fs new file mode 100644 index 0000000000..fea6ecede3 --- /dev/null +++ b/src/Shaders/VolumeRender.fs @@ -0,0 +1,402 @@ +// Created on: 2014-12-18 +// Created by: Ilya Sevrikov +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +//! Pixel coords. +varying vec2 vPixel; + +// Viewing position. +uniform vec3 uOriginLT; +uniform vec3 uOriginLB; +uniform vec3 uOriginRT; +uniform vec3 uOriginRB; + +// Viewing direction. +uniform vec3 uDirectLT; +uniform vec3 uDirectLB; +uniform vec3 uDirectRT; +uniform vec3 uDirectRB; + +// 3D volume bounds. +uniform vec3 uBoxCornerMin; +uniform vec3 uBoxCornerMax; + +// 3D volume and TF. +uniform sampler1D uTransferFunct; +uniform sampler3D uVolumeTexture; + +// Rendering parameters. +uniform int uNumOfSamples; +uniform int uTriCubFilter; +uniform int uApplyShading; +uniform int uTraceShadows; +uniform int uRandomShift; +uniform vec3 uVolTexelSize; +uniform float uOpacityScale; +uniform float uNormMinValue; +uniform float uNormMaxValue; +uniform vec4 uRandomSeed; + +uniform int uIsoSurfaceMode; +uniform int uTraceSliceMode; + +uniform float uIsoSurfaceLevel; +uniform float uTraceSliceLevel; + +//! Stores ray parameters. +struct SRay +{ + vec3 Origin; + vec3 Direct; +}; + +#define MAXFLOAT 1.0e15 + +#define ZERO vec3 (0.0, 0.0, 0.0) +#define ONES vec3 (1.0, 1.0, 1.0) + +// ======================================================================= +// function : GenerateRay +// purpose : +// ======================================================================= +SRay GenerateRay (in vec2 thePixel) +{ + vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x); + vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x); + + vec3 aD0 = mix (uDirectLB, uDirectRB, thePixel.x); + vec3 aD1 = mix (uDirectLT, uDirectRT, thePixel.x); + + vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y)); + + return SRay (mix (aP0, aP1, thePixel.y), aDirection); +} + +// ======================================================================= +// function : IntersectBox +// purpose : Computes ray-box intersection +// ======================================================================= +vec2 IntersectBox (in SRay theRay, in vec3 theMinPnt, in vec3 theMaxPnt) +{ + vec3 aTimeBoxMin = (theMinPnt - theRay.Origin) * (1.0 / theRay.Direct); + vec3 aTimeBoxMax = (theMaxPnt - theRay.Origin) * (1.0 / theRay.Direct); + + vec3 aTimeMax = max (aTimeBoxMin, aTimeBoxMax); + vec3 aTimeMin = min (aTimeBoxMin, aTimeBoxMax); + + float aTime1 = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z)); + float aTime2 = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z)); + + return aTime1 > aTime2 || aTime2 < 0.0 ? + vec2 (MAXFLOAT) : vec2 (max (aTime1, 0.0), aTime2); +} + +//======================================================================= +// function : InterpolateCubic +// purpose : Based on 2D cubic interpolation from the paper: +// GPU Gems 2. Fast Third-Order Texture Filtering (Chapter 20) +//======================================================================= +float InterpolateCubic (in vec3 theCoord, in vec3 theCellSize) +{ + vec3 aCoordGrid = theCoord / theCellSize - vec3 (0.5); + + vec3 aIndex = floor (aCoordGrid); + + vec3 aFract = aCoordGrid - aIndex; + vec3 aCompl = vec3 (1.0) - aFract; + + vec3 aCompl2 = aCompl * aCompl; + vec3 aFract2 = aFract * aFract; + + vec3 aW0 = 1.0 / 6.0 * aCompl2 * aCompl; + vec3 aW1 = vec3 (2.0 / 3.0) - 0.5 * aFract2 * (2.0 - aFract); + vec3 aW2 = vec3 (2.0 / 3.0) - 0.5 * aCompl2 * (2.0 - aCompl); + vec3 aW3 = 1.0 / 6.0 * aFract2 * aFract; + + vec3 aG0 = aW0 + aW1; + vec3 aG1 = aW2 + aW3; + + vec3 aH0 = (aW1 / aG0) - vec3 (0.5) + aIndex; + vec3 aH1 = (aW3 / aG1) + vec3 (1.5) + aIndex; + + aH0 *= theCellSize; + aH1 *= theCellSize; + + // fetch the eight linear interpolations + float aTex000 = texture3D (uVolumeTexture, aH0).x; + float aTex100 = texture3D (uVolumeTexture, vec3 (aH1.x, aH0.y, aH0.z)).x; + float aTex010 = texture3D (uVolumeTexture, vec3 (aH0.x, aH1.y, aH0.z)).x; + float aTex110 = texture3D (uVolumeTexture, vec3 (aH1.x, aH1.y, aH0.z)).x; + float aTex001 = texture3D (uVolumeTexture, vec3 (aH0.x, aH0.y, aH1.z)).x; + float aTex101 = texture3D (uVolumeTexture, vec3 (aH1.x, aH0.y, aH1.z)).x; + float aTex011 = texture3D (uVolumeTexture, vec3 (aH0.x, aH1.y, aH1.z)).x; + float aTex111 = texture3D (uVolumeTexture, aH1).x; + + // weigh along the z-direction + aTex000 = mix (aTex001, aTex000, aG0.z); + aTex100 = mix (aTex101, aTex100, aG0.z); + aTex010 = mix (aTex011, aTex010, aG0.z); + aTex110 = mix (aTex111, aTex110, aG0.z); + + // weigh along the y-direction + aTex000 = mix (aTex010, aTex000, aG0.y); + aTex100 = mix (aTex110, aTex100, aG0.y); + + // weigh along the x-direction + return mix (aTex100, aTex000, aG0.x); +} + +//======================================================================= +// function : Field +// purpose : +//======================================================================= +float Field (in vec3 thePoint) +{ + vec3 aTexCoord = (thePoint - uBoxCornerMin) / (uBoxCornerMax - uBoxCornerMin); + + if (uTriCubFilter == 0) + { + return texture3D (uVolumeTexture, aTexCoord).x; + } + + return InterpolateCubic (aTexCoord, uVolTexelSize); +} + +//======================================================================= +// function : TransferFunction +// purpose : +//======================================================================= +vec4 TransferFunction (in float theValue) +{ + return texture1D (uTransferFunct, (theValue - uNormMinValue) / (uNormMaxValue - uNormMinValue)); +} + +//======================================================================= +// function : FieldNormal +// purpose : +//======================================================================= +vec3 FieldNormal (in vec3 thePoint, in vec3 theView, in float theValue) +{ + vec3 aTexCoord = (thePoint - uBoxCornerMin) / (uBoxCornerMax - uBoxCornerMin); + + float aPosX = texture3D (uVolumeTexture, + vec3 (aTexCoord.x + uVolTexelSize.x, aTexCoord.y, aTexCoord.z)).x; + float aPosY = texture3D (uVolumeTexture, + vec3 (aTexCoord.x, aTexCoord.y + uVolTexelSize.y, aTexCoord.z)).x; + float aPosZ = texture3D (uVolumeTexture, + vec3 (aTexCoord.x, aTexCoord.y, aTexCoord.z + uVolTexelSize.z)).x; + + vec3 aNormal = vec3 (aPosX - theValue, + aPosY - theValue, + aPosZ - theValue) / uVolTexelSize; + + float aLength = dot (aNormal, aNormal); + + return aLength > 0.0 ? aNormal * inversesqrt (aLength) : theView; +} + +//======================================================================= +// function : Rand +// purpose : +//======================================================================= +float Rand (in vec4 theVec) +{ + return fract(sin(dot(theVec, uRandomSeed)) * 1000.0); +} + +#define MIN_SAMPLES 25 +#define MAX_OPACITY 0.99 + +//======================================================================= +// function : RaytraceVolume +// purpose : +//======================================================================= +vec4 RaytraceVolume (in SRay theRay, in vec2 theRange) +{ + float aFraction = theRange.y / + length (uBoxCornerMax - uBoxCornerMin); + + int aNbIterations = max (int (uNumOfSamples * aFraction), MIN_SAMPLES); + + float aOpacity = uOpacityScale * aFraction / aNbIterations; + + vec3 aLight = theRay.Direct; + + theRay.Origin += theRange.x * theRay.Direct; + theRay.Direct *= theRange.y / aNbIterations; + + vec4 aResult = vec4 (0.0); // result color + + if (uRandomShift != 0) + { + theRay.Origin += theRay.Direct * (Rand (vec4 (gl_FragCoord.xy, theRay.Origin.xy))); + } + + for (int aStep = 0; aStep < aNbIterations && aResult.w < MAX_OPACITY; ++aStep) + { + float aField = Field (theRay.Origin); + + vec4 aColor = TransferFunction (aField); + + if (uApplyShading != 0) + { + vec3 aNormal = FieldNormal (theRay.Origin, -theRay.Direct, aField); + + aColor.xyz *= max (abs (dot (aNormal, aLight)), 0.2); + } + + float anAlpha = (1.0 - aResult.w) * (aColor.w * aOpacity); + + aResult = vec4 (aResult.x + anAlpha * aColor.x, + aResult.y + anAlpha * aColor.y, + aResult.z + anAlpha * aColor.z, + aResult.w + anAlpha); + + theRay.Origin += theRay.Direct; + } + + return aResult; +} + +//======================================================================= +// function : illumination +// purpose : +//======================================================================= +vec3 illumination (in vec3 point, in vec3 view, in vec3 normal, in vec3 color) +{ + float diffuse = (1.0 + dot (view, normal)) / 2.0; + + float specular = pow (max (0.0, dot (view, normal)), 16.0); + + return (0.5 * color * (1.0 - diffuse) + color * diffuse) + + 0.1 * specular * vec3 (1.0); +} + +//======================================================================= +// function : RaytraceIsosurface +// purpose : +//======================================================================= +vec4 RaytraceIsosurface (in SRay theRay, in vec2 theRange) +{ + vec4 result = vec4 (0.0); + + float fraction = theRange.y / + length (uBoxCornerMax - uBoxCornerMin); + + int intervals = max (int (uNumOfSamples * fraction), MIN_SAMPLES); + + float step = theRange.y / intervals; + + vec3 origin = theRay.Origin + theRange.x * theRay.Direct; + + float curr = Field (origin); + + float level = uNormMinValue + (uNormMaxValue - uNormMinValue) * uIsoSurfaceLevel; + + for (int s = 0; s < intervals; ++s) + { + origin += step * theRay.Direct; + + float next = Field (origin); + + if ((curr - level) * (next - level) < 0.0) + { + float time = step * (next - level) / (curr - next); + + vec3 point = origin + time * theRay.Direct; + + float aValue = Field (point); + + vec4 color = TransferFunction (aValue); + + vec3 normal = FieldNormal (point, -theRay.Direct, aValue); + + vec3 shaded = illumination (point, -theRay.Direct, normal, color.xyz); + + color = vec4 (shaded.x, + shaded.y, + shaded.z, + 1.0); + + return color; + } + + curr = next; + } + + return result; +} + +//======================================================================= +// function : RaytraceSlice +// purpose : +//======================================================================= +vec4 RaytraceSlice (in SRay theRay) +{ + float aField = Field (theRay.Origin); + + vec4 aColor = TransferFunction (aField); + aColor.w *= 2.0; + + bool aBorder = vPixel.x < 0.009 || vPixel.y < 0.009 || vPixel.x > 0.99 || vPixel.y > 0.99; + + return mix (aColor, vec4 (0.75, 0.75, 0.75, 1.0), float (aBorder)); +} + +// ======================================================================= +// function : main +// purpose : +// ======================================================================= +void main() +{ + if (uTraceSliceMode == 1) + { + SRay aRay = SRay (uBoxCornerMin + + (uBoxCornerMax - uBoxCornerMin) * vec3 (vPixel.xy, uTraceSliceLevel), vec3 (0.0, 0.0, -1.0)); + + gl_FragColor = RaytraceSlice (aRay); + return; + } + + SRay aRay = GenerateRay (vPixel); + + vec3 aBoxMax = uBoxCornerMax; + + if (uTraceSliceMode == 2) + { + aBoxMax.z = uBoxCornerMin.z + (uBoxCornerMax.z - uBoxCornerMin.z) * uTraceSliceLevel; + } + + vec2 aRange = IntersectBox (aRay, uBoxCornerMin, aBoxMax); + + vec4 aColor = vec4 (0.0); + + if (aRange.x == MAXFLOAT) + { + discard; + } + + aRange.y -= aRange.x; + + if (uIsoSurfaceMode == 0) + { + aColor = RaytraceVolume (aRay, aRange); + } + else + { + aColor = RaytraceIsosurface (aRay, aRange); + } + + gl_FragColor = aColor; +} \ No newline at end of file diff --git a/src/Shaders/VolumeRender.vs b/src/Shaders/VolumeRender.vs new file mode 100644 index 0000000000..84c1b32467 --- /dev/null +++ b/src/Shaders/VolumeRender.vs @@ -0,0 +1,12 @@ +//! Normalized pixel coordinates. +varying vec2 vPixel; + +void main (void) +{ + vPixel = vec2 ((occVertex.x + 1.0) * 0.5, + (occVertex.y + 1.0) * 0.5); + + vec4 aPosition = occVertex; + + gl_Position = occVertex; +} \ No newline at end of file diff --git a/src/ViewerTest/ViewerTest_VoxelCommands.cxx b/src/ViewerTest/ViewerTest_VoxelCommands.cxx index 41c3280473..b5d899db82 100644 --- a/src/ViewerTest/ViewerTest_VoxelCommands.cxx +++ b/src/ViewerTest/ViewerTest_VoxelCommands.cxx @@ -15,1039 +15,7 @@ #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -// A method parses the input parameters. -static Standard_Boolean GetInputParameters(Standard_Integer nbargs, const char** args, - Standard_Real& x, Standard_Real& y, Standard_Real& z, - Standard_Real& dx, Standard_Real& dy, Standard_Real& dz, - Standard_Integer& nbx, Standard_Integer& nby, Standard_Integer& nbz) -{ - // Default values. - nbx = 10; nby = 10; nbz = 10; - x = 0.0; y = 0.0; z = 0.0; - dx = 1.0; dy = 1.0; dz = 1.0; - - // "voxelboolds 0 0 0 1 1 1 100 100 100" - if (nbargs == 10) - { - nbx = Draw::Atoi(args[7]); - nby = Draw::Atoi(args[8]); - nbz = Draw::Atoi(args[9]); - } - // "voxelboolds 0 0 0 1 1 1" - if (nbargs == 7 || nbargs == 10) - { - dx = Draw::Atof(args[4]); - dy = Draw::Atof(args[5]); - dz = Draw::Atof(args[6]); - } - // "voxelboolds 0 0 0" - if (nbargs == 4 || nbargs == 7 || nbargs == 10) - { - x = Draw::Atof(args[1]); - y = Draw::Atof(args[2]); - z = Draw::Atof(args[3]); - } - // "voxelboolds" - if (nbargs == 1) - { - // use default parameters - } - - return nbargs == 1 || nbargs == 4 || nbargs == 7 || nbargs == 10; -} - -static Standard_Integer VOXELBOOLDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxelboolds [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. BoolDS: - Voxel_BoolDS ds(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - ds.Set(ix, iy, iz, Standard_False); - else - ds.Set(ix, iy, iz, Standard_True); - } - } - } - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - Standard_Boolean value = ds.Get(ix, iy, iz) == Standard_True; - if (ix & 0x01) - { - if (value != Standard_False) - { - di<<"error : voxelboolds"; - return 1; // error - } - } - else - { - if (value != Standard_True) - { - di<<"error : voxelboolds"; - return 1; // error - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELCOLORDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxelcolords [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. ColorDS: - Voxel_ColorDS ds(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - ds.Set(ix, iy, iz, 8); - else - ds.Set(ix, iy, iz, 7); - } - } - } - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - Standard_Byte value = ds.Get(ix, iy, iz); - if (ix & 0x01) - { - if (value != 8) - { - di<<"error : voxelcolords"; - return 1; - } - } - else - { - if (value != 7) - { - di<<"error : voxelcolords"; - return 1; - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELFLOATDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxelfloatds [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. FloatDS: - Voxel_FloatDS ds(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - ds.Set(ix, iy, iz, 8.8f); - else - ds.Set(ix, iy, iz, 7.7f); - } - } - } - - /* - // Write the voxels - Voxel_Writer writer; - writer.SetFormat(Voxel_VFF_BINARY); - writer.SetVoxels(ds); - if (!writer.Write("W:\\OCC621\\samples\\standard\\voxeldemo\\f.vx")) - { - statusBar()->message( "Storage failed... sorry", 2000 ); - return; - } - - // Read the voxels - Voxel_Reader reader; - if (!reader.Read("W:\\OCC621\\samples\\standard\\voxeldemo\\f.vx")) - { - statusBar()->message( "Open failed... sorry", 2000 ); - return; - } - */ - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - float value = ds.Get(ix, iy, iz); - if (ix & 0x01) - { - if (value != 8.8f) - { - di<<"error : voxelfloatds"; - return 1; - } - } - else - { - if (value != 7.7f) - { - di<<"error : voxelfloatds"; - return 1; - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELOCTBOOLDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxeloctboolds [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. OctBoolDS: - Voxel_OctBoolDS ds(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - { - ds.Set(ix, iy, iz, Standard_True); - } - else - { - for (Standard_Integer i = 0; i < 8; i++) - { - if (i & 0x01) - ds.Set(ix, iy, iz, i, Standard_True); - else - ds.Set(ix, iy, iz, i, Standard_False); - } - } - } - } - } - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - { - Standard_Boolean value = ds.Get(ix, iy, iz) == Standard_True; - if (value != Standard_True) - cout<<"Wrong value!"< 0.001) - { - di<<"error : voxelfusefloatds"; - return 1; - } - } - else - { - if (fabs(value - 16.6f) > 0.001) - { - di<<"error : voxelfusefloatds"; - return 1; - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELCUTBOOLDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxelcutboolds [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. Set two BoolDS: - Voxel_BoolDS ds1(x, y, z, dx, dy, dz, nbx, nby, nbz); - Voxel_BoolDS ds2(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - ds1.Set(ix, iy, iz, Standard_True); - } - } - } - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - ds2.Set(ix, iy, iz, Standard_False); - else - ds2.Set(ix, iy, iz, Standard_True); - } - } - } - - // 2. Cut them - - Voxel_BooleanOperation cutter; - if (!cutter.Cut(ds1, ds2)) - { - di<<"error : voxelcutboolds"; - return 1; - } - - // 3. Check result - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - Standard_Boolean value = ds1.Get(ix, iy, iz) == Standard_True; - if (ix & 0x01) - { - if (value != Standard_True) - { - di<<"error : voxelcutboolds"; - return 1; - } - } - else - { - if (value != Standard_False) - { - di<<"error : voxelcutboolds"; - return 1; - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELCUTCOLORDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxelcutcolords [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. Set two ColorDS: - Voxel_ColorDS ds1(x, y, z, dx, dy, dz, nbx, nby, nbz); - Voxel_ColorDS ds2(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - ds1.Set(ix, iy, iz, 11); - } - } - } - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - ds2.Set(ix, iy, iz, 3); - else - ds2.Set(ix, iy, iz, 5); - } - } - } - - // 2. Cut them - - Voxel_BooleanOperation cutter; - if (!cutter.Cut(ds1, ds2)) - { - di<<"error : voxelcutcolords"; - return 1; - } - - // 3. Check result - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - Standard_Byte value = ds1.Get(ix, iy, iz); - if (ix & 0x01) - { - if (value != 8) - { - di<<"error : voxelcutcolords"; - return 1; - } - } - else - { - if (value != 6) - { - di<<"error : voxelcutcolords"; - return 1; - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELCUTFLOATDS(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - // Parse input parameters. - Standard_Real x, y, z, dx, dy, dz; - Standard_Integer ix, iy, iz, nbx, nby, nbz; - if (!GetInputParameters(nbargs, args, x, y, z, dx, dy, dz, nbx, nby, nbz)) - { - di << "Usage: voxelcutfloatds [x, y, z, dx, dy, dz nbx, nby, nbz]"; - return 1; - } - - // 1. Set two FloatDS: - Voxel_FloatDS ds1(x, y, z, dx, dy, dz, nbx, nby, nbz); - Voxel_FloatDS ds2(x, y, z, dx, dy, dz, nbx, nby, nbz); - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - ds1.Set(ix, iy, iz, 11.1f); - } - } - } - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - if (ix & 0x01) - ds2.Set(ix, iy, iz, 3.3f); - else - ds2.Set(ix, iy, iz, 5.5f); - } - } - } - - // 2. Cut them - - Voxel_BooleanOperation cutter; - if (!cutter.Cut(ds1, ds2)) - { - di<<"error : voxelcutcolords"; - return 1; - } - - // 3. Check result - - for (ix = 0; ix < nbx; ix++) - { - for (iy = 0; iy < nby; iy++) - { - for (iz = 0; iz < nbz; iz++) - { - float value = ds1.Get(ix, iy, iz); - if (ix & 0x01) - { - if (fabs(value - 7.8f) > 0.001) - { - di<<"error : voxelcutcolords"; - return 1; - } - } - else - { - if (fabs(value - 5.6f) > 0.001) - { - di<<"error : voxelcutcolords"; - return 1; - } - } - } - } - } - - return 0; -} - -static Standard_Integer VOXELBOOLDSCONVERT(Draw_Interpretor& di, Standard_Integer nbargs, const char** args) -{ - TopoDS_Shape S; - Standard_Integer nbx = 100, nby = 100, nbz = 100; - Standard_Real deflection = 0.1; - Standard_Boolean fast = Standard_True; - Standard_Integer nbthreads = 1; - Standard_Boolean usetriangulation = Standard_False; - Standard_Integer fillInVolume = 0; - - if (nbargs < 2) - { - di << "Usage: voxelbooldsconvert shape [nbx nby nbz deflection 0|1(fast or accurate) nbthreads usetriangulation \ - 0|1|2(fill-in volume: no|yes|yes using shape)]"; - return 1; - } - - // Get shape for conversion. - S = DBRep::Get(args[1]); - - if (nbargs > 2) - { - if (nbargs >= 5) - { - nbx = Draw::Atoi(args[2]); - nby = Draw::Atoi(args[3]); - nbz = Draw::Atoi(args[4]); - } - if (nbargs >= 6) - { - deflection = Draw::Atof(args[5]); - } - if (nbargs >= 7) - { - // 0 means fast, - // 1 means accurate. - fast = Draw::Atoi(args[6]) == 0 ? Standard_True : Standard_False; - } - if (nbargs >= 8) - { - nbthreads = Draw::Atoi(args[7]); - if (nbthreads < 1) - { - di << "Wrong number of threads: 1 .. nb cores"; - return 1; - } - else if (nbthreads > 100) // seems too much... - { - di << "Too many threads..."; - } - } - if (nbargs >= 9) - { - usetriangulation = Draw::Atoi(args[8]) == 0 ? Standard_False : Standard_True; - } - if (nbargs >= 10) - { - fillInVolume = Draw::Atoi(args[9]); - if (fillInVolume < 0 || fillInVolume > 2) - { - di << "Fill-in volume parameter accepts the values: 0 - no, 1 - yes, 2 - yes wusing shape"; - return 1; - } - } - } - - // Call converter. - Voxel_BoolDS ds; - Standard_Boolean ret; - Standard_Integer progress = 0; - Voxel_FastConverter converter(S, ds, deflection, nbx, nby, nbz, nbthreads, usetriangulation); - - // Convert. - if (fast) - ret = converter.Convert(progress); - else - ret = converter.ConvertUsingSAT(progress); - - // Fill-in volume. - if (ret) - { - switch (fillInVolume) - { - case 0: - break; - case 1: - converter.FillInVolume(1, nbthreads); - break; - case 2: - converter.FillInVolume(1, S, nbthreads); - break; - } - } - - return ret == Standard_True ? 0 : 1; -} - -void ViewerTest::VoxelCommands(Draw_Interpretor& theCommands) -{ - const char* g = "Voxel draw-commands"; - // Basic commands. - theCommands.Add("voxelboolds" ,"voxelboolds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELBOOLDS,g); - theCommands.Add("voxelcolords" ,"voxelcolords [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELCOLORDS,g); - theCommands.Add("voxelfloatds" ,"voxelfloatds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELFLOATDS,g); - theCommands.Add("voxeloctboolds" ,"voxeloctboolds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELOCTBOOLDS,g); - theCommands.Add("voxelroctboolds" ,"voxelroctboolds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELROCTBOOLDS,g); - // Boolean operations. - theCommands.Add("voxelfuseboolds" ,"voxelfuseboolds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELFUSEBOOLDS,g); - theCommands.Add("voxelfusecolords","voxelfusecolords [x y z dx dy dz nbx nby nbz]",__FILE__,VOXELFUSECOLORDS,g); - theCommands.Add("voxelfusefloatds","voxelfusefloatds [x y z dx dy dz nbx nby nbz]",__FILE__,VOXELFUSEFLOATDS,g); - theCommands.Add("voxelcutboolds" ,"voxelcutboolds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELCUTBOOLDS,g); - theCommands.Add("voxelcutcolords" ,"voxelcutcolords [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELCUTCOLORDS,g); - theCommands.Add("voxelcutfloatds" ,"voxelcutfloatds [x y z dx dy dz nbx nby nbz]" ,__FILE__,VOXELCUTFLOATDS,g); - // Conversion of a shape into voxels. - theCommands.Add("voxelbooldsconvert", - "voxelbooldsconvert shape [nbx nby nbz deflection 0|1(fast or accurate) nbthreads usetriangulation \ - 0|1|2(fill-in volume: no|yes|yes using shape)]", - __FILE__,VOXELBOOLDSCONVERT,g); } diff --git a/src/Voxel/FILES b/src/Voxel/FILES index 1271ed4fa5..e2ae60e513 100755 --- a/src/Voxel/FILES +++ b/src/Voxel/FILES @@ -1,32 +1,7 @@ -Voxel_BoolDS.cxx -Voxel_BoolDS.hxx -Voxel_BooleanOperation.cxx -Voxel_BooleanOperation.hxx -Voxel_CollisionDetection.cxx -Voxel_CollisionDetection.hxx -Voxel_ColorDS.cxx -Voxel_ColorDS.hxx -Voxel_DS.cxx -Voxel_DS.hxx -Voxel_FastConverter.cxx -Voxel_FastConverter.hxx -Voxel_FloatDS.cxx -Voxel_FloatDS.hxx -Voxel_OctBoolDS.cxx -Voxel_OctBoolDS.hxx +Voxel_TypeDef.hxx +Handle_Voxel_Prs.hxx Voxel_Prs.cxx Voxel_Prs.hxx -Voxel_Reader.cxx -Voxel_Reader.hxx -Voxel_ROctBoolDS.cxx -Voxel_ROctBoolDS.hxx -Voxel_Selector.cxx -Voxel_Selector.hxx -Voxel_SplitData.cxx -Voxel_SplitData.hxx -Voxel_TypeDef.hxx -Voxel_VisData.h -Voxel_VoxelDisplayMode.hxx -Voxel_VoxelFileFormat.hxx -Voxel_Writer.cxx -Voxel_Writer.hxx +Voxel_BaseReader.hxx +Voxel_DicomReader.hxx +Voxel_DicomReader.cxx \ No newline at end of file diff --git a/src/Voxel/Handle_Voxel_Prs.hxx b/src/Voxel/Handle_Voxel_Prs.hxx new file mode 100644 index 0000000000..52362fa04c --- /dev/null +++ b/src/Voxel/Handle_Voxel_Prs.hxx @@ -0,0 +1,30 @@ +// Created on: 2014-11-14 +// Created by: Vladislav ROMASHKO +// Copyright (c) 2008-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Handle_Voxel_Prs_HeaderFile +#define _Handle_Voxel_Prs_HeaderFile + +#include +#include +#include + +class Standard_Transient; +class Handle(Standard_Type); +class Handle(AIS_InteractiveObject); +class Voxel_Prs; + +DEFINE_STANDARD_HANDLE(Voxel_Prs, AIS_InteractiveObject) + +#endif // _Handle_Voxel_Prs_HeaderFile diff --git a/src/Voxel/Voxel_BaseReader.hxx b/src/Voxel/Voxel_BaseReader.hxx new file mode 100644 index 0000000000..c867086334 --- /dev/null +++ b/src/Voxel/Voxel_BaseReader.hxx @@ -0,0 +1,51 @@ +// Created on: 2015-01-29 +// Created by: Ilya Sevrikov +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Voxel_BaseReader_HeaderFile +#define _Voxel_BaseReader_HeaderFile + +#include + +#include + +#include + +//! Defines abstract reader for read volume data and transfer function +class Voxel_BaseReader +{ +public: + + //! Creates empty reader. + Voxel_BaseReader() + { + // + } + + //! Releases resources. + virtual ~Voxel_BaseReader() + { + // + } + + //! Reads volume data from file and returns it. + Standard_EXPORT virtual Standard_Boolean ReadDenseVolumeData (Handle(Graphic3d_VolumeData)& theVolume, + const TCollection_AsciiString& thePath) const = 0; + + //! Reads transfer function from file and returns it. + //Standard_EXPORT virtual Handle(Graphic3d_ParentTransferFunction) ReadTransFunc (const TCollection_AsciiString& thePath) const = 0; + +}; + +#endif //_Voxel_BaseReader_HeaderFile diff --git a/src/Voxel/Voxel_BoolDS.cxx b/src/Voxel/Voxel_BoolDS.cxx deleted file mode 100644 index 20adea5b74..0000000000 --- a/src/Voxel/Voxel_BoolDS.cxx +++ /dev/null @@ -1,141 +0,0 @@ -// Created on: 2008-06-21 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include - -#include -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); -} diff --git a/src/Voxel/Voxel_BooleanOperation.cxx b/src/Voxel/Voxel_BooleanOperation.cxx deleted file mode 100644 index 127120059b..0000000000 --- a/src/Voxel/Voxel_BooleanOperation.cxx +++ /dev/null @@ -1,230 +0,0 @@ -// Created on: 2008-05-21 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include -#include -#include -#include - -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, (Standard_Byte)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; -} diff --git a/src/Voxel/Voxel_CollisionDetection.cxx b/src/Voxel/Voxel_CollisionDetection.cxx deleted file mode 100644 index be57a8f6eb..0000000000 --- a/src/Voxel/Voxel_CollisionDetection.cxx +++ /dev/null @@ -1,295 +0,0 @@ -// Created on: 2008-07-16 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/src/Voxel/Voxel_ColorDS.cxx b/src/Voxel/Voxel_ColorDS.cxx deleted file mode 100644 index 1ec26750f1..0000000000 --- a/src/Voxel/Voxel_ColorDS.cxx +++ /dev/null @@ -1,173 +0,0 @@ -// Created on: 2008-05-08 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include - -#include -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; -} diff --git a/src/Voxel/Voxel_DS.cxx b/src/Voxel/Voxel_DS.cxx deleted file mode 100644 index e7d84111e2..0000000000 --- a/src/Voxel/Voxel_DS.cxx +++ /dev/null @@ -1,194 +0,0 @@ -// Created on: 2008-05-11 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include - -// 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 -{ - GetOrigin(ix, iy, iz, xc, yc, zc); - xc += myHalfDX; - yc += myHalfDY; - zc += myHalfDZ; -} - -void Voxel_DS::GetOrigin(const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz, - Standard_Real& x0, Standard_Real& y0, Standard_Real& z0) const -{ - x0 = myX + ix * myDX; - y0 = myY + iy * myDY; - z0 = myZ + iz * myDZ; -} - -// 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; -} diff --git a/src/Voxel/Voxel_DicomReader.cxx b/src/Voxel/Voxel_DicomReader.cxx new file mode 100644 index 0000000000..57f332a37c --- /dev/null +++ b/src/Voxel/Voxel_DicomReader.cxx @@ -0,0 +1,266 @@ +#include + +#pragma comment(lib, "gdcmCommon.lib") +#pragma comment(lib, "gdcmDICT.lib") +#pragma comment(lib, "gdcmcharls.lib") +#pragma comment(lib, "gdcmDSED.lib") +#pragma comment(lib, "gdcmexpat.lib") +#pragma comment(lib, "gdcmgetopt.lib") +#pragma comment(lib, "gdcmIOD.lib") +#pragma comment(lib, "gdcmjpeg8.lib") +#pragma comment(lib, "gdcmjpeg12.lib") +#pragma comment(lib, "gdcmjpeg16.lib") +#pragma comment(lib, "gdcmMEXD.lib") +#pragma comment(lib, "gdcmMSFF.lib") +#pragma comment(lib, "gdcmopenjpeg.lib") +#pragma comment(lib, "gdcmzlib.lib") +#pragma comment(lib, "socketxx.lib") + + +//========================================= +//function : Voxel_DicomReader +//purpose : +//========================================= +Voxel_DicomReader::Voxel_DicomReader() +{ +} + +#include +#include + +namespace +{ + template + struct DicomTypeCheker + { + /* None */ + }; + + template + struct DicomTypeCheker + { + typedef T Type; + }; + + template + struct DicomTypeSelector + { + /* None */ + }; + + template<> + struct DicomTypeSelector + { + typedef DicomTypeCheker::Type Type; + }; + + template<> + struct DicomTypeSelector + { + typedef DicomTypeCheker::Type Type; + }; + + template<> + struct DicomTypeSelector + { + typedef DicomTypeCheker::Type Type; + }; + + template<> + struct DicomTypeSelector + { + typedef DicomTypeCheker::Type Type; + }; + + class DenseVolumeFiller + { + public: + + virtual void Push (const Standard_Address theBuffer, + const Standard_Integer theIndexZ) = 0; + + virtual Graphic3d_VolumeData* Data() const = 0; + }; + + template + class SpecificDenseVolumeFiller : public DenseVolumeFiller + { + public: + + typedef typename DicomTypeSelector::Type DataType; + + public: + + SpecificDenseVolumeFiller (const BVH_Box3d& theBounds, + const Standard_Integer theNbVoxX, + const Standard_Integer theNbVoxY, + const Standard_Integer theNbVoxZ) + { + myData = new Graphic3d_DenseVolumeData (theBounds, + theNbVoxX, + theNbVoxY, + theNbVoxZ); + } + + virtual void Push (const Standard_Address theBuffer, + const Standard_Integer theIndexZ) + { + const Standard_Integer aNbSliceElems = myData->NbVoxelX() * + myData->NbVoxelY(); + + memcpy (&myData->Data()->ChangeFirst() + + aNbSliceElems * theIndexZ, theBuffer, aNbSliceElems * sizeof (DataType)); + } + + virtual Graphic3d_VolumeData* Data() const + { + return myData; + } + + private: + + //! Dense volumetric data of specific type. + Graphic3d_DenseVolumeData* myData; + + }; +} + +//======================================================================== +//function : ReadDenseVolumeData +//purpose : +//======================================================================== +Standard_Boolean Voxel_DicomReader::ReadDenseVolumeData (Handle(Graphic3d_VolumeData)& theVolumeData, + const TCollection_AsciiString& thePath) const +{ + gdcm::ImageReader aDicomReader; + gdcm::Directory aFolder; + + aFolder.Load (thePath.ToCString()); + + Standard_ASSERT_RETURN (!aFolder.GetFilenames().empty(), + "Error: There are no any files in the directory", Standard_False); + + // read first file to get dataset parameters + aDicomReader.SetFileName (aFolder.GetFilenames().front().c_str()); + + Standard_ASSERT_RETURN (aDicomReader.Read(), + "Error: Failed to read DICOM image", Standard_False); + + gdcm::Image& anImage = aDicomReader.GetImage(); + + Standard_ASSERT_RETURN (!anImage.IsEmpty(), + "Error: DICOM image is empty", Standard_False); + + const Standard_Integer aDimX = anImage.GetDimension (0); + const Standard_Integer aDimY = anImage.GetDimension (1); + const gdcm::PixelFormat aType = anImage.GetPixelFormat(); + + BVH_Box3d aBounds (BVH_Vec3d (anImage.GetOrigin (0), anImage.GetOrigin (1), anImage.GetOrigin (2)), + BVH_Vec3d (anImage.GetOrigin (0), anImage.GetOrigin (1), anImage.GetOrigin (2))); + + aBounds.CornerMax().x() += aDimX * anImage.GetSpacing (0); + aBounds.CornerMax().y() += aDimY * anImage.GetSpacing (1); + + NCollection_Handle aVolumeFiller = NULL; + + switch (aType) + { + case gdcm::PixelFormat::UINT8: + { + aVolumeFiller = new SpecificDenseVolumeFiller ( + aBounds, aDimX, aDimY, static_cast (aFolder.GetFilenames().size())); + } break; + + case gdcm::PixelFormat::UINT16: + { + aVolumeFiller = new SpecificDenseVolumeFiller ( + aBounds, aDimX, aDimY, static_cast (aFolder.GetFilenames().size())); + } break; + + case gdcm::PixelFormat::UINT32: + { + aVolumeFiller = new SpecificDenseVolumeFiller ( + aBounds, aDimX, aDimY, static_cast (aFolder.GetFilenames().size())); + } break; + + case gdcm::PixelFormat::FLOAT32: + { + aVolumeFiller = new SpecificDenseVolumeFiller ( + aBounds, aDimX, aDimY, static_cast (aFolder.GetFilenames().size())); + } break; + } + + if (aVolumeFiller.IsNull()) + { + return Standard_False; // unsupported pixel format + } + + double aSizeZ = 0.0; + for (std::vector::const_iterator anIt = aFolder.GetFilenames().begin(); anIt != aFolder.GetFilenames().end(); ++anIt) + { + if (anIt != aFolder.GetFilenames().begin()) + { + // Sometimes gdcm::ImageReader::GetImage() throw exception. + // This magic solves this trouble + gdcm::File* aFile = new gdcm::File; + aDicomReader.SetFile (*aFile); + aDicomReader.SetFileName (anIt->c_str()); + if (!aDicomReader.CanRead()) + { + continue; + } + + std::cout << anIt->c_str() << std::endl; + + Standard_ASSERT_RETURN (aDicomReader.Read(), + "Error: Failed to read DICOM image", Standard_False); + + anImage = aDicomReader.GetImage(); + + Standard_ASSERT_RETURN (!anImage.IsEmpty(), + "Error: DICOM image is empty", Standard_False); + + if (aDimX != static_cast(anImage.GetDimension (0)) + || aDimY != static_cast(anImage.GetDimension (1)) + || aType != anImage.GetPixelFormat()) + { + return Standard_False; + } + } + + aSizeZ += anImage.GetSpacing (2); + + if (anIt == aFolder.GetFilenames().end() - 1) + { + //aBounds.CornerMax().z() = anImage.GetOrigin (2); // TODO: ? + aBounds.CornerMax().z() = Max (anImage.GetOrigin (2), aBounds.CornerMax().z() + aSizeZ); + } + + const gdcm::PhotometricInterpretation& aPI = anImage.GetPhotometricInterpretation(); + + if (aPI.GetType() == gdcm::PhotometricInterpretation::MONOCHROME1 + || aPI.GetType() == gdcm::PhotometricInterpretation::MONOCHROME2) + { + Standard_Character* aBuffer = new Standard_Character[anImage.GetBufferLength()]; + + if (!anImage.GetBuffer (aBuffer)) + { + return Standard_False; + } + + aVolumeFiller->Push (aBuffer, anIt - aFolder.GetFilenames().begin()); + + delete [] aBuffer; + } + else + { + return Standard_False; + } + } + + theVolumeData = aVolumeFiller->Data(); + + theVolumeData->SetBounds (aBounds); + + return Standard_True; +} diff --git a/src/Voxel/Voxel_DicomReader.hxx b/src/Voxel/Voxel_DicomReader.hxx new file mode 100644 index 0000000000..07fa747d98 --- /dev/null +++ b/src/Voxel/Voxel_DicomReader.hxx @@ -0,0 +1,42 @@ +// Created on: 2015-01-29 +// Created by: Ilya Sevrikov +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Voxel_DicomReader_HeaderFile +#define _Voxel_DicomReader_HeaderFile + +#include +#include + +#include +#include + +#include +#include +#include +#include + +//! Defines reader class for reading dicom files. +class Voxel_DicomReader : public Voxel_BaseReader +{ +public: + //! Creates dicom reader and fills dictionaries. + Standard_EXPORT Voxel_DicomReader(); + + //! Reads volume data from directory and returns it. + Standard_EXPORT Standard_Boolean ReadDenseVolumeData (Handle(Graphic3d_VolumeData)& theVolume, + const TCollection_AsciiString& thePath) const; +}; + +#endif //_Voxel_DicomReader_HeaderFile diff --git a/src/Voxel/Voxel_FastConverter.cxx b/src/Voxel/Voxel_FastConverter.cxx deleted file mode 100644 index 322f5f1c0f..0000000000 --- a/src/Voxel/Voxel_FastConverter.cxx +++ /dev/null @@ -1,1174 +0,0 @@ -// Created on: 2008-05-30 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// 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, - const Standard_Boolean useExistingTriangulation) -:myShape(shape),myVoxels(&voxels), - myDeflection(deflection), - myIsBool(2), - myNbX(nbx),myNbY(nby),myNbZ(nbz), - myNbThreads(nbthreads), - myNbTriangles(0), - myUseExistingTriangulation(useExistingTriangulation) -{ - 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, - const Standard_Boolean useExistingTriangulation) -:myShape(shape),myVoxels(&voxels), - myDeflection(deflection), - myIsBool(1), - myNbX(nbx),myNbY(nby),myNbZ(nbz), - myNbThreads(nbthreads), - myNbTriangles(0), - myUseExistingTriangulation(useExistingTriangulation) -{ - 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, - const Standard_Boolean useExistingTriangulation) -:myShape(shape),myVoxels(&voxels), - myDeflection(deflection), - myIsBool(0), - myNbX(nbx),myNbY(nby),myNbZ(nbz), - myNbThreads(nbthreads), - myNbTriangles(0), - myUseExistingTriangulation(useExistingTriangulation) -{ - 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); - if(myUseExistingTriangulation == Standard_False) - { - for (; expl.More(); expl.Next()) - { - const TopoDS_Face & F = TopoDS::Face(expl.Current()); - Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); - if (T.IsNull() || (T->Deflection() > myDeflection)) - { - triangulate = Standard_True; - break; - } - } - } - - // Re-create the triangulation. - if (triangulate) - { - BRepMesh_IncrementalMesh(myShape, myDeflection); - } - - // Compute the number of triangles. - myNbTriangles = 0; - expl.Init(myShape, TopAbs_FACE); - for (; expl.More(); expl.Next()) - { - const TopoDS_Face & F = TopoDS::Face(expl.Current()); - Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); - if (T.IsNull() == Standard_False) - 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; - - if(myNbTriangles == 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; - if(myNbTriangles < myNbThreads) - { - if(ithread != 1) - return Standard_False; - //in case we're in thread one process all triangles - } - else - { - div_t division = div(myNbTriangles, myNbThreads); - start_thread_triangle = (ithread - 1) * division.quot + 1; - end_thread_triangle = (ithread - 0) * division.quot; - - if(ithread == myNbThreads) - end_thread_triangle += division.rem; - } - - // Convert - TopLoc_Location L; - Standard_Integer iprogress = 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()) - { - const TopoDS_Face & F = TopoDS::Face(expl.Current()); - Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); - if (T.IsNull()) - continue; - - 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 ) - continue; - if (ithread_triangle > end_thread_triangle) - { - if (ithread == 1) - progress = 100; -#ifdef CONV_DUMP - if (ithread == 1) - printf("Progress = %d \r", progress); -#endif - return Standard_True; - } - - 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::ConvertUsingSAT(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; - - if(myNbTriangles == 0) - return Standard_False; - - // Half of size of a voxel (also for Voxel_ROctBoolDS) - 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(); - gp_Pnt extents(dx/2.0, dy/2.0, dz/2.0); - gp_Pnt extents2(dx/4.0, dy/4.0, dz/4.0); - gp_Pnt extents4(dx/8.0, dy/8.0, dz/8.0); - - // Compute the scope of triangles for current thread - Standard_Integer start_thread_triangle = 1, end_thread_triangle = myNbTriangles, ithread_triangle = 0; - if(myNbTriangles < myNbThreads) - { - if(ithread != 1) - return Standard_False; - //in case we're in thread one process all triangles - } - else - { - div_t division = div(myNbTriangles, myNbThreads); - start_thread_triangle = (ithread - 1) * division.quot + 1; - end_thread_triangle = (ithread - 0) * division.quot; - - if(ithread == myNbThreads) - end_thread_triangle += division.rem; - } - - // Convert - TopLoc_Location L; - Standard_Integer iprogress = 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()) - { - const TopoDS_Face & F = TopoDS::Face(expl.Current()); - Handle(Poly_Triangulation) T = BRep_Tool::Triangulation(F, L); - if (T.IsNull()) - continue; - - 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 ) - continue; - if (ithread_triangle > end_thread_triangle) - { - if (ithread == 1) - progress = 100; -#ifdef CONV_DUMP - if (ithread == 1) - printf("Progress = %d \r", progress); -#endif - return Standard_True; - } - - 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; - - // Perform triangle-box intersection to find the voxels resulting from the processed triangle.; - // Using SAT theorem to quickly find the intersection. - ComputeVoxelsNearTriangle(p1, p2, p3, - extents, extents2, extents4, - 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; -} - -Standard_Boolean Voxel_FastConverter::FillInVolume(const Standard_Byte inner, const TopoDS_Shape & shape, 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, isOnVerticalSurface; - - BRepClass3d_SolidClassifier solidClassifier(shape); - Standard_Real xc, yc, zc; - - 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; - isOnVerticalSurface = 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) - { - if(isOnVerticalSurface) - { - isOnVerticalSurface = Standard_False; - ((Voxel_BoolDS*)myVoxels)->GetCenter(ix, iy, iz, xc, yc, zc); - gp_Pnt P(xc, yc, zc); - solidClassifier.Perform(P, Precision::Confusion()); - - if(solidClassifier.State() == TopAbs_IN) - volume = Standard_True; - else - volume = Standard_False; - } - else - volume = !volume; - } - if(prev_surface && surface) - isOnVerticalSurface = Standard_True; - else - isOnVerticalSurface = Standard_False; - prev_surface = surface; - } - if (volume) - continue; - - // Fill-in the volume. - volume = Standard_False; - surface = Standard_False; - prev_surface = Standard_False; - isOnVerticalSurface = 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) - { - if(isOnVerticalSurface) - { - isOnVerticalSurface = Standard_False; - ((Voxel_BoolDS*)myVoxels)->GetCenter(ix, iy, iz, xc, yc, zc); - gp_Pnt P(xc, yc, zc); - solidClassifier.Perform(P, Precision::Confusion()); - - if(solidClassifier.State() == TopAbs_IN) - volume = Standard_True; - else - volume = Standard_False; - } - else - volume = !volume; - } - if (volume && !surface) - { - (myIsBool == 1) ? ((Voxel_BoolDS*)myVoxels)->Set(ix, iy, iz, inner) : - ((Voxel_ColorDS*)myVoxels)->Set(ix, iy, iz, inner); - } - if(prev_surface && surface) - isOnVerticalSurface = Standard_True; - else - isOnVerticalSurface = Standard_False; - 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; - } - } - } - } - } - } -} - -//! This macro quickly finds the min & max values among 3 variables -#define FINDMINMAX(x0, x1, x2, min, max) \ - min = max = x0; \ - if(x1max) max=x1; \ - if(x2max) max=x2; - -static bool planeBoxOverlap(const gp_Vec & normal, const double d, const gp_Pnt & maxbox) -{ - gp_Vec vmin, vmax; - if(normal.X() > 0.0) { vmin.SetX(-maxbox.X()); vmax.SetX(maxbox.X()); } - else { vmin.SetX(maxbox.X()); vmax.SetX(-maxbox.X()); } - - if(normal.Y() > 0.0) { vmin.SetY(-maxbox.Y()); vmax.SetY(maxbox.Y()); } - else { vmin.SetY(maxbox.Y()); vmax.SetY(-maxbox.Y()); } - - if(normal.Z() > 0.0) { vmin.SetZ(-maxbox.Z()); vmax.SetZ(maxbox.Z()); } - else { vmin.SetZ(maxbox.Z()); vmax.SetZ(-maxbox.Z()); } - - if((normal.Dot(vmin)) + d > 0.0) return false; - if((normal.Dot(vmax)) + d>= 0.0) return true; - - return false; -} - -#define AXISTEST_X01(a, b, fa, fb) \ - min = a*v0.Y() - b*v0.Z(); \ - max = a*v2.Y() - b*v2.Z(); \ - if(min>max) {const double tmp=max; max=min; min=tmp; } \ - rad = fa * extents.Y() + fb * extents.Z(); \ - if(min>rad || max<-rad) return false; - -#define AXISTEST_X2(a, b, fa, fb) \ - min = a*v0.Y() - b*v0.Z(); \ - max = a*v1.Y() - b*v1.Z(); \ - if(min>max) {const double tmp=max; max=min; min=tmp; } \ - rad = fa * extents.Y() + fb * extents.Z(); \ - if(min>rad || max<-rad) return false; - -#define AXISTEST_Y02(a, b, fa, fb) \ - min = b*v0.Z() - a*v0.X(); \ - max = b*v2.Z() - a*v2.X(); \ - if(min>max) {const double tmp=max; max=min; min=tmp; } \ - rad = fa * extents.X() + fb * extents.Z(); \ - if(min>rad || max<-rad) return false; - -#define AXISTEST_Y1(a, b, fa, fb) \ - min = b*v0.Z() - a*v0.X(); \ - max = b*v1.Z() - a*v1.X(); \ - if(min>max) {const double tmp=max; max=min; min=tmp; } \ - rad = fa * extents.X() + fb * extents.Z(); \ - if(min>rad || max<-rad) return false; - -#define AXISTEST_Z12(a, b, fa, fb) \ - min = a*v1.X() - b*v1.Y(); \ - max = a*v2.X() - b*v2.Y(); \ - if(min>max) {const double tmp=max; max=min; min=tmp; } \ - rad = fa * extents.X() + fb * extents.Y(); \ - if(min>rad || max<-rad) return false; - -#define AXISTEST_Z0(a, b, fa, fb) \ - min = a*v0.X() - b*v0.Y(); \ - max = a*v1.X() - b*v1.Y(); \ - if(min>max) {const double tmp=max; max=min; min=tmp; } \ - rad = fa * extents.X() + fb * extents.Y(); \ - if(min>rad || max<-rad) return false; - -// compute triangle edges -// - edges lazy evaluated to take advantage of early exits -// - fabs precomputed (half less work, possible since extents are always >0) -// - customized macros to take advantage of the null component -// - axis vector discarded, possibly saves useless movs -#define IMPLEMENT_CLASS3_TESTS \ - double rad; \ - double min, max; \ - \ - const double fey0 = fabs(e0.Y()); \ - const double fez0 = fabs(e0.Z()); \ - AXISTEST_X01(e0.Z(), e0.Y(), fez0, fey0); \ - const double fex0 = fabs(e0.X()); \ - AXISTEST_Y02(e0.Z(), e0.X(), fez0, fex0); \ - AXISTEST_Z12(e0.Y(), e0.X(), fey0, fex0); \ - \ - const double fey1 = fabs(e1.Y()); \ - const double fez1 = fabs(e1.Z()); \ - AXISTEST_X01(e1.Z(), e1.Y(), fez1, fey1); \ - const double fex1 = fabs(e1.X()); \ - AXISTEST_Y02(e1.Z(), e1.X(), fez1, fex1); \ - AXISTEST_Z0(e1.Y(), e1.X(), fey1, fex1); \ - \ - const gp_Vec e2 = v2 - v0; \ - const double fey2 = fabs(e2.Y()); \ - const double fez2 = fabs(e2.Z()); \ - AXISTEST_X2(e2.Z(), e2.Y(), fez2, fey2); \ - const double fex2 = fabs(e2.X()); \ - AXISTEST_Y1(e2.Z(), e2.X(), fez2, fex2); \ - AXISTEST_Z12(e2.Y(), e2.X(), fey2, fex2); - -static bool TriBoxOverlap(const gp_Pnt & p1, const gp_Pnt & p2, const gp_Pnt & p3, - const gp_Pnt & center, const gp_Pnt & extents) -{ - // use separating axis theorem to test overlap between triangle and box - // need to test for overlap in these directions: - // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle - // we do not even need to test these) - // 2) normal of the triangle - // 3) crossproduct(edge from tri, {x,y,z}-directin) - // this gives 3x3=9 more tests - - // move everything so that the boxcenter is in (0,0,0) - gp_Vec v0(center, p1); - gp_Vec v1(center, p2); - gp_Vec v2(center, p3); - - // First, test overlap in the {x,y,z}-directions - double min,max; - // Find min, max of the triangle in x-direction, and test for overlap in X - FINDMINMAX(v0.X(), v1.X(), v2.X(), min, max); - if(min>extents.X() || max<-extents.X()) return false; - - // Same for Y - FINDMINMAX(v0.Y(), v1.Y(), v2.Y(), min, max); - if(min>extents.Y() || max<-extents.Y()) return false; - - // Same for Z - FINDMINMAX(v0.Z(), v1.Z(), v2.Z(), min, max); - if(min>extents.Z() || max<-extents.Z()) return false; - - // 2) Test if the box intersects the plane of the triangle - // compute plane equation of triangle: normal*x+d=0 - // ### could be precomputed since we use the same leaf triangle several times - const gp_Vec e0 = v1 - v0; - const gp_Vec e1 = v2 - v1; - const gp_Vec normal = e0.Crossed(e1); - const double d = -normal.Dot(v0); - if(!planeBoxOverlap(normal, d, extents)) return false; - - // 3) "Class III" tests - //if(mFullPrimBoxTest) - { - IMPLEMENT_CLASS3_TESTS - } - - return true; -} - -void Voxel_FastConverter::ComputeVoxelsNearTriangle(const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pnt& p3, - const gp_Pnt& extents, - const gp_Pnt& extents2, - const gp_Pnt& extents4, - 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; - Standard_Integer ix, iy, iz; - - 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(TriBoxOverlap(p1, p2, p3, pc, extents)) - { - // 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. - 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(TriBoxOverlap(p1, p2, p3, pc, extents2)) - { - //((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(TriBoxOverlap(p1, p2, p3, pc, extents4)) - { - ((Voxel_ROctBoolDS*) myVoxels)->Set(ix, iy, iz, i, j, Standard_True); - } - } // End of "Check level 2". - - } - } // End of "Check level 1". - break; - } - } - } - } - } - } -} diff --git a/src/Voxel/Voxel_FloatDS.cxx b/src/Voxel/Voxel_FloatDS.cxx deleted file mode 100644 index 294f4fe0fc..0000000000 --- a/src/Voxel/Voxel_FloatDS.cxx +++ /dev/null @@ -1,116 +0,0 @@ -// Created on: 2008-05-15 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include - -#include -// 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]; -} diff --git a/src/Voxel/Voxel_OctBoolDS.cxx b/src/Voxel/Voxel_OctBoolDS.cxx index 72b425ca78..0dd6b9fd3e 100644 --- a/src/Voxel/Voxel_OctBoolDS.cxx +++ b/src/Voxel/Voxel_OctBoolDS.cxx @@ -274,6 +274,8 @@ void Voxel_OctBoolDS::OptimizeMemory() value = itr.Value(); if (value == 0 || value == 255) { + + xyz = itr.Key(); ixs.Append(xyz.ix); iys.Append(xyz.iy); diff --git a/src/Voxel/Voxel_Prs.cxx b/src/Voxel/Voxel_Prs.cxx index 8615a92e0d..e0cde80e77 100644 --- a/src/Voxel/Voxel_Prs.cxx +++ b/src/Voxel/Voxel_Prs.cxx @@ -1,4 +1,4 @@ -// Created on: 2008-05-13 +// Created on: 2014-12-17 // Created by: Vladislav ROMASHKO // Copyright (c) 2008-2014 OPEN CASCADE SAS // @@ -13,294 +13,55 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - +#include #include #include -#include -#include -#include -#include -#include -#include -#include - -#include "Voxel_VisData.h" -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; -} +IMPLEMENT_STANDARD_HANDLE (Voxel_Prs, AIS_InteractiveObject) +IMPLEMENT_STANDARD_RTTIEXT(Voxel_Prs, AIS_InteractiveObject) -void Voxel_Prs::SetTriangulation(const Handle(Poly_Triangulation)& theTriangulation) +//======================================================================== +//function : Voxel_Prs +//purpose : +//======================================================================== +Voxel_Prs::Voxel_Prs() : AIS_InteractiveObject (PrsMgr_TOP_AllView) { - Allocate(); - ((Voxel_VisData*)myVisData)->myTriangulation = theTriangulation; + // } -void Voxel_Prs::SetColor(const Quantity_Color& theColor) +//======================================================================== +//function : ~Voxel_Prs +//purpose : +//======================================================================== +Voxel_Prs::~Voxel_Prs() { - 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*/) +//======================================================================== +//function : Compute +//purpose : +//======================================================================== +void Voxel_Prs::Compute (const Handle(PrsMgr_PresentationManager3d)& /*theMgr*/, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer /*theMode*/) { + thePrs->Clear(); -} + Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs); -// Destructor -void Voxel_Prs::Destroy() -{ - if (myVisData) + if (!aGroup.IsNull()) { - delete (Voxel_VisData*) myVisData; - myVisData = 0; + aGroup->AddVolume (myVolume); } } -void Voxel_Prs::Allocate() +//======================================================================== +//function : ComputeSelection +//purpose : +//======================================================================== +void Voxel_Prs::ComputeSelection (const Handle(SelectMgr_Selection)& /*theSelection*/, + const Standard_Integer /*theMode*/) { - 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; + // TODO } diff --git a/src/Voxel/Voxel_Prs.hxx b/src/Voxel/Voxel_Prs.hxx index aba9798c06..d65301035d 100644 --- a/src/Voxel/Voxel_Prs.hxx +++ b/src/Voxel/Voxel_Prs.hxx @@ -1,4 +1,4 @@ -// Created on: 2008-05-06 +// Created on: 2008-05-13 // Created by: Vladislav ROMASHKO // Copyright (c) 2008-2014 OPEN CASCADE SAS // @@ -16,134 +16,60 @@ #ifndef _Voxel_Prs_HeaderFile #define _Voxel_Prs_HeaderFile -#include -#include - -#include +#include #include -#include -#include -#include -#include #include +#include +#include +#include #include -#include -#include -class Poly_Triangulation; -class Quantity_Color; -class Prs3d_Presentation; - +#include +#include -class Voxel_Prs; -DEFINE_STANDARD_HANDLE(Voxel_Prs, AIS_InteractiveObject) - -//! Interactive object for voxels. +//! Interactive object for volumetric data. class Voxel_Prs : public AIS_InteractiveObject { - public: - - //! An empty constructor. + //! Creates empty voxel presentation. Standard_EXPORT Voxel_Prs(); - - //! is a Voxel_BoolDS* object. - Standard_EXPORT void SetBoolVoxels (const Standard_Address theVoxels); - - //! is a Voxel_ColorDS* object. - Standard_EXPORT void SetColorVoxels (const Standard_Address theVoxels); - - //! is a Voxel_ROctBoolDS* object. - Standard_EXPORT void SetROctBoolVoxels (const Standard_Address theVoxels); - - //! Sets a triangulation for visualization. - Standard_EXPORT void SetTriangulation (const Handle(Poly_Triangulation)& theTriangulation); - - //! Sets a display mode for voxels. - Standard_EXPORT void SetDisplayMode (const Voxel_VoxelDisplayMode theMode); - - //! Defines the color of points, quadrangles ... for BoolDS. - Standard_EXPORT virtual void SetColor (const Quantity_Color& theColor) Standard_OVERRIDE; - - //! 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. - Standard_EXPORT void SetColors (const Handle(Quantity_HArray1OfColor)& theColors); - - //! Defines the size of points for all types of voxels. - Standard_EXPORT void SetPointSize (const Standard_Real theSize); - - //! Defines the size of quadrangles in per cents (0 .. 100). - Standard_EXPORT void SetQuadrangleSize (const Standard_Integer theSize); - - //! Defines the transparency value [0 .. 1] for quadrangular visualization. - Standard_EXPORT virtual void SetTransparency (const Standard_Real theTransparency) Standard_OVERRIDE; - - //! 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. - Standard_EXPORT void Highlight (const Standard_Integer ix, const Standard_Integer iy, const Standard_Integer iz); - - //! A destructor of presentation data. - Standard_EXPORT void Destroy(); -~Voxel_Prs() -{ - Destroy(); -} - - //! Simplifies visualization of voxels in case of view rotation, panning and zooming. - Standard_EXPORT void SetDegenerateMode (const Standard_Boolean theDegenerate); - - //! 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. - Standard_EXPORT void SetUsageOfGLlists (const Standard_Boolean theUsage); - - //! Switches visualization of points from smooth to rough. - Standard_EXPORT void SetSmoothPoints (const Standard_Boolean theSmooth); - - //! Defines min-max values for visualization of voxels of ColorDS structure. - //! By default, min value = 1, max value = 15 (all non-zero values). - Standard_EXPORT void SetColorRange (const Standard_Byte theMinValue, const Standard_Byte theMaxValue); - - //! Defines the displayed area of voxels. - //! By default, the range is equal to the box of voxels (all voxels are displayed). - Standard_EXPORT void 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); - - - - DEFINE_STANDARD_RTTI(Voxel_Prs,AIS_InteractiveObject) - -protected: - - - Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, const Handle(Prs3d_Presentation)& thePresentation, const Standard_Integer theMode = 0) Standard_OVERRIDE; + //! Releases resources of voxel presentation. + Standard_EXPORT ~Voxel_Prs(); +public: -private: - - - Standard_EXPORT void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, const Standard_Integer theMode); - - //! Allocates the data structure of visualization. - Standard_EXPORT void Allocate(); - - Standard_Address myVisData; + //! Returns 3D volume object. + Handle(Graphic3d_Volume) Volume() const + { + return myVolume; + } + //! Sets 3D volume object. + void SetVolume (const Handle(Graphic3d_Volume)& theVolume) + { + myVolume = theVolume; + } -}; +protected: + //! Computes 3D volume presentation. + Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& theManager, + const Handle(Prs3d_Presentation)& thePresentation, + const Standard_Integer theMode = 0); + //! Computes 3D volume selection. + Standard_EXPORT void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, + const Standard_Integer theMode); +protected: + //! 3D volume object. + Handle(Graphic3d_Volume) myVolume; +public: + DEFINE_STANDARD_RTTI (Voxel_Prs) +}; -#endif // _Voxel_Prs_HeaderFile +#endif // _Voxel_Prs_HeaderFile \ No newline at end of file diff --git a/src/Voxel/Voxel_ROctBoolDS.cxx b/src/Voxel/Voxel_ROctBoolDS.cxx deleted file mode 100644 index 11b7c966a2..0000000000 --- a/src/Voxel/Voxel_ROctBoolDS.cxx +++ /dev/null @@ -1,727 +0,0 @@ -// Created on: 2008-09-01 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include - -#include -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; -} - -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]); - ((Voxel_SplitData**)myData)[ix] = 0; - } - } - } -} - -// 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; - } - } -} diff --git a/src/Voxel/Voxel_Reader.cxx b/src/Voxel/Voxel_Reader.cxx deleted file mode 100644 index 682eca3b3b..0000000000 --- a/src/Voxel/Voxel_Reader.cxx +++ /dev/null @@ -1,539 +0,0 @@ -// Created on: 2008-08-28 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - - // Read the header - Standard_Byte type; // 0 - bool, 1 - color, 2 - float - Voxel_VoxelFileFormat format; - Standard_Character svoxels[9], sformat[9], stype[9]; - fscanf(f, "%8s %8s %8s\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 = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - Standard_Character line[65], sx[33], sy[33], sz[33]; - - // 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, "%32s %32s %32s\n", sx, sy, sz) != 3) - { - fclose(f); - return Standard_False; - } - x = Atof(sx); y = Atof(sy); z = Atof(sz); - if (fscanf(f, "%32s %32s %32s\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] = (Standard_Byte)value; - } - } - - fclose(f); - return Standard_True; -} - -Standard_Boolean Voxel_Reader::ReadColorAsciiVoxels(const TCollection_ExtendedString& file) -{ - // Open file for reading - FILE* f = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - Standard_Character line[65], sx[33], sy[33], sz[33]; - - // 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, "%32s %32s %32s\n", sx, sy, sz) != 3) - { - fclose(f); - return Standard_False; - } - x = Atof(sx); y = Atof(sy); z = Atof(sz); - if (fscanf(f, "%32s %32s %32s\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] = (Standard_Byte)value; - } - } - - fclose(f); - return Standard_True; -} - -Standard_Boolean Voxel_Reader::ReadFloatAsciiVoxels(const TCollection_ExtendedString& file) -{ - // Open file for reading - FILE* f = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - Standard_Character line[65], sx[33], sy[33], sz[33]; - - // 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, "%32s %32s %32s\n", sx, sy, sz) != 3) - { - fclose(f); - return Standard_False; - } - x = Atof(sx); y = Atof(sy); z = Atof(sz); - if (fscanf(f, "%32s %32s %32s\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 %64s\n", &i1, &i2, line) != 3) - { - fclose(f); - return Standard_False; - } - } - else - { - if (sscanf(line, "%d %64s\n", &i2, line) != 2) - { - fclose(f); - return Standard_False; - } - } - value = (Standard_ShortReal)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 = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - - // Header: skip it - Standard_Character line[65]; - 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] = (Standard_Byte)value; - } - } - - fclose(f); - return Standard_True; -} - -Standard_Boolean Voxel_Reader::ReadColorBinaryVoxels(const TCollection_ExtendedString& file) -{ - // Open file for reading - FILE* f = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - - // Header: skip it - Standard_Character line[65]; - 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] = (Standard_Byte)value; - } - } - - fclose(f); - return Standard_True; -} - -Standard_Boolean Voxel_Reader::ReadFloatBinaryVoxels(const TCollection_ExtendedString& file) -{ - // Open file for reading - FILE* f = OSD_OpenFile(file, "r"); - if (!f) - return Standard_False; - - // Header: skip it - Standard_Character line[65]; - 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; -} diff --git a/src/Voxel/Voxel_Selector.cxx b/src/Voxel/Voxel_Selector.cxx deleted file mode 100644 index 1d01cd5115..0000000000 --- a/src/Voxel/Voxel_Selector.cxx +++ /dev/null @@ -1,581 +0,0 @@ -// Created on: 2008-07-30 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/src/Voxel/Voxel_TypeDef.hxx b/src/Voxel/Voxel_TypeDef.hxx index b49b53597b..7bc87df702 100644 --- a/src/Voxel/Voxel_TypeDef.hxx +++ b/src/Voxel/Voxel_TypeDef.hxx @@ -38,16 +38,20 @@ inline Standard_Boolean IsEqual(const iXYZ& one, const iXYZ& two) #include -typedef NCollection_DataMap iXYZIndex; -typedef NCollection_DataMap iXYZBool; +template +struct iXYZMap +{ + typedef NCollection_DataMap Type; +}; // Defines -#define VOXELS "Voxels" -#define ASCII "Ascii" -#define BINARY "Binary" -#define BOOL "Bool" -#define COLOR "Color" -#define FLOAT "Float" +#define VOXELS "Voxels" +#define ASCII "Ascii" +#define BINARY "Binary" +#define BOOL "Bool" +#define COLOR "Color" +#define FLOAT "Float" +#define VOXELTEMPLATE "VoxelTemplate" #endif // _VOXEL_TYPEDEF_HXX_ diff --git a/src/Voxel/Voxel_VisData.h b/src/Voxel/Voxel_VisData.h deleted file mode 100644 index 80e573377a..0000000000 --- a/src/Voxel/Voxel_VisData.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (c) 1999-2014 OPEN CASCADE SAS - - This file is part of Open CASCADE Technology software library. - - This library is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License version 2.1 as published - by the Free Software Foundation, with special exception defined in the file - OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT - distribution for complete text of the license and disclaimer of any warranty. - - Alternatively, this file may be used under the terms of Open CASCADE - commercial license or contractual agreement. -*/ - -#ifndef _VOXEL_VISDATA_H_ -#define _VOXEL_VISDATA_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -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_ diff --git a/src/Voxel/Voxel_Writer.cxx b/src/Voxel/Voxel_Writer.cxx deleted file mode 100644 index 94aae86072..0000000000 --- a/src/Voxel/Voxel_Writer.cxx +++ /dev/null @@ -1,442 +0,0 @@ -// Created on: 2008-08-28 -// Created by: Vladislav ROMASHKO -// Copyright (c) 2008-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 = OSD_OpenFile(file, "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 = OSD_OpenFile(file, "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 = OSD_OpenFile(file, "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 = OSD_OpenFile(file, "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 = OSD_OpenFile(file, "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 = OSD_OpenFile(file, "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::SquareConfusion(); - 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; -} -- 2.39.5