mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: cvMeshSurfaceSimplify: use octree version
This commit is contained in:
@ -1,6 +1,20 @@
|
||||
cvMeshSurfaceSimplify.C
|
||||
|
||||
/*
|
||||
cvMeshSurfaceSimplify_non_octree.C
|
||||
MarchingCubes/MarchingCubes.cpp
|
||||
MarchingCubes/ply.c
|
||||
*/
|
||||
|
||||
MarchingCubes = fastdualoctree_sgp
|
||||
|
||||
$(MarchingCubes)/data_access.cpp
|
||||
$(MarchingCubes)/fparser.cpp
|
||||
$(MarchingCubes)/fpoptimizer.cpp
|
||||
$(MarchingCubes)/MarchingCubes.cpp
|
||||
$(MarchingCubes)/mc_draw.cpp
|
||||
$(MarchingCubes)/morton.cpp
|
||||
$(MarchingCubes)/opt_octree.cpp
|
||||
$(MarchingCubes)/hash_octree.cpp
|
||||
|
||||
cvMeshSurfaceSimplify.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/cvMeshSurfaceSimplify
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
MarchingCubes = fastdualoctree_sgp
|
||||
|
||||
include $(GENERAL_RULES)/CGAL
|
||||
|
||||
EXE_INC = \
|
||||
-IMarchingCubes \
|
||||
-DUNIX \
|
||||
-Wno-old-style-cast \
|
||||
/* -IMarchingCubes */ \
|
||||
-I$(MarchingCubes) \
|
||||
-I../conformalVoronoiMesh/lnInclude \
|
||||
-I$(LIB_SRC)/edgeMesh/lnInclude \
|
||||
-I$(LIB_SRC)/triSurface/lnInclude \
|
||||
@ -9,6 +14,7 @@ EXE_INC = \
|
||||
|
||||
EXE_LIBS = \
|
||||
$(CGAL_LIBS) \
|
||||
-lGL \
|
||||
-lconformalVoronoiMesh \
|
||||
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lscotchDecomp \
|
||||
-ledgeMesh \
|
||||
|
||||
@ -1,343 +0,0 @@
|
||||
/**
|
||||
* @file MarchingCubes.h
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.2
|
||||
* @date 12/08/2002
|
||||
*
|
||||
* @brief MarchingCubes Algorithm
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#ifndef _MARCHINGCUBES_H_
|
||||
#define _MARCHINGCUBES_H_
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// types
|
||||
/** unsigned char alias */
|
||||
typedef unsigned char uchar ;
|
||||
/** signed char alias */
|
||||
typedef signed char schar ;
|
||||
/** isovalue alias */
|
||||
typedef float real ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vertex structure
|
||||
/** \struct Vertex "MarchingCubes.h" MarchingCubes
|
||||
* Position and normal of a vertex
|
||||
* \brief vertex structure
|
||||
* \param x X coordinate
|
||||
* \param y Y coordinate
|
||||
* \param z Z coordinate
|
||||
* \param nx X component of the normal
|
||||
* \param ny Y component of the normal
|
||||
* \param nz Z component of the normal
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
real x, y, z ; /**< Vertex coordinates */
|
||||
real nx, ny, nz ; /**< Vertex normal */
|
||||
} Vertex ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Triangle structure
|
||||
/** \struct Triangle "MarchingCubes.h" MarchingCubes
|
||||
* Indices of the oriented triange vertices
|
||||
* \brief triangle structure
|
||||
* \param v1 First vertex index
|
||||
* \param v2 Second vertex index
|
||||
* \param v3 Third vertex index
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int v1,v2,v3 ; /**< Triangle vertices */
|
||||
} Triangle ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/** Marching Cubes algorithm wrapper */
|
||||
/** \class MarchingCubes
|
||||
* \brief Marching Cubes algorithm.
|
||||
*/
|
||||
class MarchingCubes
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// Constructors
|
||||
public :
|
||||
/**
|
||||
* Main and default constructor
|
||||
* \brief constructor
|
||||
* \param size_x width of the grid
|
||||
* \param size_y depth of the grid
|
||||
* \param size_z height of the grid
|
||||
*/
|
||||
MarchingCubes ( const int size_x = -1, const int size_y = -1, const int size_z = -1 ) ;
|
||||
/** Destructor */
|
||||
~MarchingCubes() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
/** accesses the number of vertices of the generated mesh */
|
||||
inline const int nverts() const { return _nverts ; }
|
||||
/** accesses the number of triangles of the generated mesh */
|
||||
inline const int ntrigs() const { return _ntrigs ; }
|
||||
/** accesses a specific vertex of the generated mesh */
|
||||
inline Vertex * vert( const int i ) const { if( i < 0 || i >= _nverts ) return ( Vertex *)NULL ; return _vertices + i ; }
|
||||
/** accesses a specific triangle of the generated mesh */
|
||||
inline Triangle * trig( const int i ) const { if( i < 0 || i >= _ntrigs ) return (Triangle*)NULL ; return _triangles + i ; }
|
||||
|
||||
/** accesses the vertex buffer of the generated mesh */
|
||||
inline Vertex *vertices () { return _vertices ; }
|
||||
/** accesses the triangle buffer of the generated mesh */
|
||||
inline Triangle *triangles() { return _triangles ; }
|
||||
|
||||
/** accesses the width of the grid */
|
||||
inline const int size_x() const { return _size_x ; }
|
||||
/** accesses the depth of the grid */
|
||||
inline const int size_y() const { return _size_y ; }
|
||||
/** accesses the height of the grid */
|
||||
inline const int size_z() const { return _size_z ; }
|
||||
|
||||
/**
|
||||
* changes the size of the grid
|
||||
* \param size_x width of the grid
|
||||
* \param size_y depth of the grid
|
||||
* \param size_z height of the grid
|
||||
*/
|
||||
inline void set_resolution( const int size_x, const int size_y, const int size_z ) { _size_x = size_x ; _size_y = size_y ; _size_z = size_z ; }
|
||||
/**
|
||||
* selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes
|
||||
* \param originalMC true for the original Marching Cubes
|
||||
*/
|
||||
inline void set_method ( const bool originalMC = false ) { _originalMC = originalMC ; }
|
||||
/**
|
||||
* selects to use data from another class
|
||||
* \param data is the pointer to the external data, allocated as a size_x*size_y*size_z vector running in x first
|
||||
*/
|
||||
inline void set_ext_data ( real *data )
|
||||
{ if( !_ext_data ) delete [] _data ; _ext_data = data != NULL ; if( _ext_data ) _data = data ; }
|
||||
/**
|
||||
* selects to allocate data
|
||||
*/
|
||||
inline void set_int_data () { _ext_data = false ; _data = NULL ; }
|
||||
|
||||
// Data access
|
||||
/**
|
||||
* accesses a specific cube of the grid
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline const real get_data ( const int i, const int j, const int k ) const { return _data[ i + j*_size_x + k*_size_x*_size_y] ; }
|
||||
/**
|
||||
* sets a specific cube of the grid
|
||||
* \param val new value for the cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline void set_data ( const real val, const int i, const int j, const int k ) { _data[ i + j*_size_x + k*_size_x*_size_y] = val ; }
|
||||
|
||||
// Data initialization
|
||||
/** inits temporary structures (must set sizes before call) : the grid and the vertex index per cube */
|
||||
void init_temps () ;
|
||||
/** inits all structures (must set sizes before call) : the temporary structures and the mesh buffers */
|
||||
void init_all () ;
|
||||
/** clears temporary structures : the grid and the main */
|
||||
void clean_temps() ;
|
||||
/** clears all structures : the temporary structures and the mesh buffers */
|
||||
void clean_all () ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exportation
|
||||
public :
|
||||
/**
|
||||
* PLY exportation of the generated mesh
|
||||
* \param fn name of the PLY file to create
|
||||
* \param bin if true, the PLY will be written in binary mode
|
||||
*/
|
||||
void writePLY( const char *fn, bool bin = false ) ;
|
||||
|
||||
/**
|
||||
* PLY importation of a mesh
|
||||
* \param fn name of the PLY file to read from
|
||||
*/
|
||||
void readPLY( const char *fn ) ;
|
||||
|
||||
/**
|
||||
* VRML / Open Inventor exportation of the generated mesh
|
||||
* \param fn name of the IV file to create
|
||||
*/
|
||||
void writeIV ( const char *fn ) ;
|
||||
|
||||
/**
|
||||
* ISO exportation of the input grid
|
||||
* \param fn name of the ISO file to create
|
||||
*/
|
||||
void writeISO( const char *fn ) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Algorithm
|
||||
public :
|
||||
/**
|
||||
* Main algorithm : must be called after init_all
|
||||
* \param iso isovalue
|
||||
*/
|
||||
void run( real iso = (real)0.0 ) ;
|
||||
|
||||
protected :
|
||||
/** tesselates one cube */
|
||||
void process_cube () ;
|
||||
/** tests if the components of the tesselation of the cube should be connected by the interior of an ambiguous face */
|
||||
bool test_face ( schar face ) ;
|
||||
/** tests if the components of the tesselation of the cube should be connected through the interior of the cube */
|
||||
bool test_interior( schar s ) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
protected :
|
||||
/**
|
||||
* computes almost all the vertices of the mesh by interpolation along the cubes edges
|
||||
* \param iso isovalue
|
||||
*/
|
||||
void compute_intersection_points( real iso ) ;
|
||||
|
||||
/**
|
||||
* routine to add a triangle to the mesh
|
||||
* \param trig the code for the triangle as a sequence of edges index
|
||||
* \param n the number of triangles to produce
|
||||
* \param v12 the index of the interior vertex to use, if necessary
|
||||
*/
|
||||
void add_triangle ( const char* trig, char n, int v12 = -1 ) ;
|
||||
|
||||
/** tests and eventually doubles the vertex buffer capacity for a new vertex insertion */
|
||||
void test_vertex_addition() ;
|
||||
/** adds a vertex on the current horizontal edge */
|
||||
int add_x_vertex() ;
|
||||
/** adds a vertex on the current longitudinal edge */
|
||||
int add_y_vertex() ;
|
||||
/** adds a vertex on the current vertical edge */
|
||||
int add_z_vertex() ;
|
||||
/** adds a vertex inside the current cube */
|
||||
int add_c_vertex() ;
|
||||
|
||||
/**
|
||||
* interpolates the horizontal gradient of the implicit function at the lower vertex of the specified cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
real get_x_grad( const int i, const int j, const int k ) const ;
|
||||
/**
|
||||
* interpolates the longitudinal gradient of the implicit function at the lower vertex of the specified cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
real get_y_grad( const int i, const int j, const int k ) const ;
|
||||
/**
|
||||
* interpolates the vertical gradient of the implicit function at the lower vertex of the specified cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
real get_z_grad( const int i, const int j, const int k ) const ;
|
||||
|
||||
/**
|
||||
* accesses the pre-computed vertex index on the lower horizontal edge of a specific cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline int get_x_vert( const int i, const int j, const int k ) const { return _x_verts[ i + j*_size_x + k*_size_x*_size_y] ; }
|
||||
/**
|
||||
* accesses the pre-computed vertex index on the lower longitudinal edge of a specific cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline int get_y_vert( const int i, const int j, const int k ) const { return _y_verts[ i + j*_size_x + k*_size_x*_size_y] ; }
|
||||
/**
|
||||
* accesses the pre-computed vertex index on the lower vertical edge of a specific cube
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline int get_z_vert( const int i, const int j, const int k ) const { return _z_verts[ i + j*_size_x + k*_size_x*_size_y] ; }
|
||||
|
||||
/**
|
||||
* sets the pre-computed vertex index on the lower horizontal edge of a specific cube
|
||||
* \param val the index of the new vertex
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline void set_x_vert( const int val, const int i, const int j, const int k ) { _x_verts[ i + j*_size_x + k*_size_x*_size_y] = val ; }
|
||||
/**
|
||||
* sets the pre-computed vertex index on the lower longitudinal edge of a specific cube
|
||||
* \param val the index of the new vertex
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline void set_y_vert( const int val, const int i, const int j, const int k ) { _y_verts[ i + j*_size_x + k*_size_x*_size_y] = val ; }
|
||||
/**
|
||||
* sets the pre-computed vertex index on the lower vertical edge of a specific cube
|
||||
* \param val the index of the new vertex
|
||||
* \param i abscisse of the cube
|
||||
* \param j ordinate of the cube
|
||||
* \param k height of the cube
|
||||
*/
|
||||
inline void set_z_vert( const int val, const int i, const int j, const int k ) { _z_verts[ i + j*_size_x + k*_size_x*_size_y] = val ; }
|
||||
|
||||
/** prints cube for debug */
|
||||
void print_cube() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
protected :
|
||||
bool _originalMC ; /**< selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes */
|
||||
bool _ext_data ; /**< selects wether to allocate data or use data from another class */
|
||||
|
||||
int _size_x ; /**< width of the grid */
|
||||
int _size_y ; /**< depth of the grid */
|
||||
int _size_z ; /**< height of the grid */
|
||||
real *_data ; /**< implicit function values sampled on the grid */
|
||||
|
||||
int *_x_verts ; /**< pre-computed vertex indices on the lower horizontal edge of each cube */
|
||||
int *_y_verts ; /**< pre-computed vertex indices on the lower longitudinal edge of each cube */
|
||||
int *_z_verts ; /**< pre-computed vertex indices on the lower vertical edge of each cube */
|
||||
|
||||
int _nverts ; /**< number of allocated vertices in the vertex buffer */
|
||||
int _ntrigs ; /**< number of allocated triangles in the triangle buffer */
|
||||
int _Nverts ; /**< size of the vertex buffer */
|
||||
int _Ntrigs ; /**< size of the triangle buffer */
|
||||
Vertex *_vertices ; /**< vertex buffer */
|
||||
Triangle *_triangles ; /**< triangle buffer */
|
||||
|
||||
int _i ; /**< abscisse of the active cube */
|
||||
int _j ; /**< height of the active cube */
|
||||
int _k ; /**< ordinate of the active cube */
|
||||
|
||||
real _cube[8] ; /**< values of the implicit function on the active cube */
|
||||
uchar _lut_entry ; /**< cube sign representation in [0..255] */
|
||||
uchar _case ; /**< case of the active cube in [0..15] */
|
||||
uchar _config ; /**< configuration of the active cube */
|
||||
uchar _subconfig ; /**< subconfiguration of the active cube */
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#endif // _MARCHINGCUBES_H_
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,233 +0,0 @@
|
||||
/*
|
||||
|
||||
Header for PLY polygon files.
|
||||
|
||||
- Greg Turk
|
||||
|
||||
A PLY file contains a single polygonal _object_.
|
||||
|
||||
An object is composed of lists of _elements_. Typical elements are
|
||||
vertices, faces, edges and materials.
|
||||
|
||||
Each type of element for a given object has one or more _properties_
|
||||
associated with the element type. For instance, a vertex element may
|
||||
have as properties three floating-point values x,y,z and three unsigned
|
||||
chars for red, green and blue.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1998 Georgia Institute of Technology. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify and distribute this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided
|
||||
that the above copyright notice and this permission notice appear in
|
||||
all copies of this software and that you do not sell the software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __PLY_H__
|
||||
#define __PLY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define PLY_ASCII 1 /* ascii PLY file */
|
||||
#define PLY_BINARY_BE 2 /* binary PLY file, big endian */
|
||||
#define PLY_BINARY_LE 3 /* binary PLY file, little endian */
|
||||
|
||||
#define PLY_OKAY 0 /* ply routine worked okay */
|
||||
#define PLY_ERROR -1 /* error in ply routine */
|
||||
|
||||
/* scalar data types supported by PLY format */
|
||||
|
||||
#define StartType 0
|
||||
#define Int8 1
|
||||
#define Int16 2
|
||||
#define Int32 3
|
||||
#define Uint8 4
|
||||
#define Uint16 5
|
||||
#define Uint32 6
|
||||
#define Float32 7
|
||||
#define Float64 8
|
||||
#define EndType 9
|
||||
|
||||
#define PLY_SCALAR 0
|
||||
#define PLY_LIST 1
|
||||
#define PLY_STRING 2
|
||||
|
||||
|
||||
typedef struct PlyProperty { /* description of a property */
|
||||
|
||||
char *name; /* property name */
|
||||
int external_type; /* file's data type */
|
||||
int internal_type; /* program's data type */
|
||||
int offset; /* offset bytes of prop in a struct */
|
||||
|
||||
int is_list; /* 0 = scalar, 1 = list, 2 = char string */
|
||||
int count_external; /* file's count type */
|
||||
int count_internal; /* program's count type */
|
||||
int count_offset; /* offset byte for list count */
|
||||
|
||||
} PlyProperty;
|
||||
|
||||
typedef struct PlyElement { /* description of an element */
|
||||
char *name; /* element name */
|
||||
int num; /* number of elements in this object */
|
||||
int size; /* size of element (bytes) or -1 if variable */
|
||||
int nprops; /* number of properties for this element */
|
||||
PlyProperty **props; /* list of properties in the file */
|
||||
char *store_prop; /* flags: property wanted by user? */
|
||||
int other_offset; /* offset to un-asked-for props, or -1 if none*/
|
||||
int other_size; /* size of other_props structure */
|
||||
} PlyElement;
|
||||
|
||||
typedef struct PlyOtherProp { /* describes other properties in an element */
|
||||
char *name; /* element name */
|
||||
int size; /* size of other_props */
|
||||
int nprops; /* number of properties in other_props */
|
||||
PlyProperty **props; /* list of properties in other_props */
|
||||
} PlyOtherProp;
|
||||
|
||||
typedef struct OtherData { /* for storing other_props for an other element */
|
||||
void *other_props;
|
||||
} OtherData;
|
||||
|
||||
typedef struct OtherElem { /* data for one "other" element */
|
||||
char *elem_name; /* names of other elements */
|
||||
int elem_count; /* count of instances of each element */
|
||||
OtherData **other_data; /* actual property data for the elements */
|
||||
PlyOtherProp *other_props; /* description of the property data */
|
||||
} OtherElem;
|
||||
|
||||
typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
|
||||
int num_elems; /* number of other elements */
|
||||
OtherElem *other_list; /* list of data for other elements */
|
||||
} PlyOtherElems;
|
||||
|
||||
#define AVERAGE_RULE 1
|
||||
#define MAJORITY_RULE 2
|
||||
#define MINIMUM_RULE 3
|
||||
#define MAXIMUM_RULE 4
|
||||
#define SAME_RULE 5
|
||||
#define RANDOM_RULE 6
|
||||
|
||||
typedef struct PlyPropRules { /* rules for combining "other" properties */
|
||||
PlyElement *elem; /* element whose rules we are making */
|
||||
int *rule_list; /* types of rules (AVERAGE_PLY, MAJORITY_PLY, etc.) */
|
||||
int nprops; /* number of properties we're combining so far */
|
||||
int max_props; /* maximum number of properties we have room for now */
|
||||
void **props; /* list of properties we're combining */
|
||||
float *weights; /* list of weights of the properties */
|
||||
} PlyPropRules;
|
||||
|
||||
typedef struct PlyRuleList {
|
||||
char *name; /* name of the rule */
|
||||
char *element; /* name of element that rule applies to */
|
||||
char *property; /* name of property that rule applies to */
|
||||
struct PlyRuleList *next; /* pointer for linked list of rules */
|
||||
} PlyRuleList;
|
||||
|
||||
typedef struct PlyFile { /* description of PLY file */
|
||||
FILE *fp; /* file pointer */
|
||||
int file_type; /* ascii or binary */
|
||||
float version; /* version number of file */
|
||||
int num_elem_types; /* number of element types of object */
|
||||
PlyElement **elems; /* list of elements */
|
||||
int num_comments; /* number of comments */
|
||||
char **comments; /* list of comments */
|
||||
int num_obj_info; /* number of items of object information */
|
||||
char **obj_info; /* list of object info items */
|
||||
PlyElement *which_elem; /* element we're currently reading or writing */
|
||||
PlyOtherElems *other_elems; /* "other" elements from a PLY file */
|
||||
PlyPropRules *current_rules; /* current propagation rules */
|
||||
PlyRuleList *rule_list; /* rule list from user */
|
||||
} PlyFile;
|
||||
|
||||
/* memory allocation */
|
||||
/*
|
||||
extern char *my_alloc();
|
||||
*/
|
||||
#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
|
||||
|
||||
|
||||
/* old routines */
|
||||
|
||||
#if 0
|
||||
extern PlyFile *ply_write(FILE *, int, char **, int);
|
||||
extern PlyFile *ply_read(FILE *, int *, char ***);
|
||||
extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *);
|
||||
extern void ply_close(PlyFile *);
|
||||
extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int);
|
||||
#endif
|
||||
|
||||
extern void ply_describe_property( PlyFile * , char * , PlyProperty * );
|
||||
extern void ply_get_property( PlyFile * , char * , PlyProperty * );
|
||||
extern void ply_get_element( PlyFile * , void * );
|
||||
|
||||
|
||||
/*** delcaration of routines ***/
|
||||
|
||||
PlyOtherElems *get_other_element_ply( PlyFile * );
|
||||
|
||||
PlyFile *read_ply( FILE * );
|
||||
PlyFile *write_ply( FILE * , int, char ** , int );
|
||||
extern PlyFile *open_for_writing_ply( char * , int, char ** , int );
|
||||
void close_ply( PlyFile * );
|
||||
void free_ply( PlyFile * );
|
||||
|
||||
void get_info_ply( PlyFile * , float * , int * );
|
||||
void free_other_elements_ply( PlyOtherElems * );
|
||||
|
||||
void append_comment_ply( PlyFile * , char * );
|
||||
void append_obj_info_ply( PlyFile * , char * );
|
||||
void copy_comments_ply( PlyFile * , PlyFile * );
|
||||
void copy_obj_info_ply( PlyFile * , PlyFile * );
|
||||
char* *get_comments_ply( PlyFile * , int * );
|
||||
char* *get_obj_info_ply( PlyFile * , int * );
|
||||
|
||||
char* *get_element_list_ply( PlyFile * , int * );
|
||||
int setup_property_ply( PlyFile * , PlyProperty * );
|
||||
void get_element_ply( PlyFile * , void * );
|
||||
char *setup_element_read_ply( PlyFile * , int, int * );
|
||||
PlyOtherProp *get_other_properties_ply( PlyFile * , int );
|
||||
|
||||
void element_count_ply( PlyFile * , char * , int );
|
||||
void describe_element_ply( PlyFile * , char * , int );
|
||||
void describe_property_ply( PlyFile * , PlyProperty * );
|
||||
void describe_other_properties_ply( PlyFile * , PlyOtherProp * , int );
|
||||
void describe_other_elements_ply( PlyFile * , PlyOtherElems * );
|
||||
void get_element_setup_ply( PlyFile * , char * , int, PlyProperty * );
|
||||
PlyProperty* *get_element_description_ply( PlyFile * , char * , int * , int * );
|
||||
void element_layout_ply( PlyFile * , char * , int, int, PlyProperty * );
|
||||
|
||||
void header_complete_ply( PlyFile * );
|
||||
void put_element_setup_ply( PlyFile * , char * );
|
||||
void put_element_ply( PlyFile * , void * );
|
||||
void put_other_elements_ply( PlyFile * );
|
||||
|
||||
PlyPropRules *init_rule_ply( PlyFile * , char * );
|
||||
void modify_rule_ply( PlyPropRules * , char * , int );
|
||||
void start_props_ply( PlyFile * , PlyPropRules * );
|
||||
void weight_props_ply( PlyFile * , float, void * );
|
||||
void *get_new_props_ply( PlyFile * );
|
||||
void set_prop_rules_ply( PlyFile * , PlyRuleList * );
|
||||
PlyRuleList *append_prop_rule( PlyRuleList * , char * , char * );
|
||||
int matches_rule_name( char * );
|
||||
|
||||
int equal_strings( char * , char * );
|
||||
char *recreate_command_line( int, char *argv[] );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !__PLY_H__ */
|
||||
|
||||
@ -28,6 +28,7 @@ Description
|
||||
Simplifies surfaces by resampling.
|
||||
|
||||
Uses Thomas Lewiner's topology preserving MarchingCubes.
|
||||
(http://zeus.mat.puc-rio.br/tomlew/tomlew_uk.php)
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -37,13 +38,328 @@ Description
|
||||
#include "conformationSurfaces.H"
|
||||
#include "triSurfaceMesh.H"
|
||||
|
||||
#include "MarchingCubes.h"
|
||||
|
||||
#include "opt_octree.h"
|
||||
#include "cube.h"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
class pointConversion
|
||||
{
|
||||
const vector scale_;
|
||||
|
||||
const vector offset_;
|
||||
|
||||
public:
|
||||
|
||||
//- Construct from components
|
||||
pointConversion
|
||||
(
|
||||
const vector scale,
|
||||
const vector offset
|
||||
)
|
||||
:
|
||||
scale_(scale),
|
||||
offset_(offset)
|
||||
{}
|
||||
|
||||
inline Point toLocal(const Foam::point& pt) const
|
||||
{
|
||||
Foam::point p = cmptMultiply(scale_, (pt + offset_));
|
||||
return Point(p.x(), p.y(), p.z());
|
||||
}
|
||||
|
||||
inline Foam::point toGlobal(const Point& pt) const
|
||||
{
|
||||
point p(pt.x(), pt.y(), pt.z());
|
||||
return cmptDivide(p, scale_) - offset_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// For use in Fast-Dual Octree from Thomas Lewiner
|
||||
class distanceCalc
|
||||
:
|
||||
public ::data_access
|
||||
{
|
||||
|
||||
const Level min_level_;
|
||||
|
||||
const conformationSurfaces& geometryToConformTo_;
|
||||
|
||||
const pointConversion& converter_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
scalar signedDistance(const Foam::point& pt) const
|
||||
{
|
||||
const searchableSurfaces& geometry = geometryToConformTo_.geometry();
|
||||
const labelList& surfaces = geometryToConformTo_.surfaces();
|
||||
|
||||
static labelList nearestSurfaces;
|
||||
static scalarField distance;
|
||||
|
||||
static pointField samples(1);
|
||||
samples[0] = pt;
|
||||
|
||||
searchableSurfacesQueries::signedDistance
|
||||
(
|
||||
geometry,
|
||||
surfaces,
|
||||
samples,
|
||||
scalarField(1, GREAT),
|
||||
searchableSurface::OUTSIDE,
|
||||
nearestSurfaces,
|
||||
distance
|
||||
);
|
||||
|
||||
return distance[0];
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
distanceCalc
|
||||
(
|
||||
Level max_level_,
|
||||
real iso_val_,
|
||||
Level min_level,
|
||||
const conformationSurfaces& geometryToConformTo,
|
||||
const pointConversion& converter
|
||||
)
|
||||
:
|
||||
data_access(max_level_,iso_val_),
|
||||
min_level_(min_level),
|
||||
geometryToConformTo_(geometryToConformTo),
|
||||
converter_(converter)
|
||||
{}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~distanceCalc()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- test function
|
||||
virtual bool need_refine( const Cube &c )
|
||||
{
|
||||
int l = c.lv() ;
|
||||
|
||||
if( l >= _max_level ) return false;
|
||||
if( l < min_level_ ) return true;
|
||||
|
||||
treeBoundBox bb
|
||||
(
|
||||
converter_.toGlobal
|
||||
(
|
||||
Point
|
||||
(
|
||||
c.xmin(),
|
||||
c.ymin(),
|
||||
c.zmin()
|
||||
)
|
||||
),
|
||||
converter_.toGlobal
|
||||
(
|
||||
Point
|
||||
(
|
||||
c.xmax(),
|
||||
c.ymax(),
|
||||
c.zmax()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const searchableSurfaces& geometry =
|
||||
geometryToConformTo_.geometry();
|
||||
const labelList& surfaces =
|
||||
geometryToConformTo_.surfaces();
|
||||
|
||||
|
||||
//- Uniform refinement around surface
|
||||
{
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
if (geometry[surfaces[i]].overlaps(bb))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////- Surface intersects bb (but not using intersection test)
|
||||
//scalar ccDist = signedDistance(bb.midpoint());
|
||||
//scalar ccVal = ccDist - _iso_val;
|
||||
//if (mag(ccVal) < SMALL)
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
//const pointField points(bb.points());
|
||||
//forAll(points, pointI)
|
||||
//{
|
||||
// scalar pointVal = signedDistance(points[pointI]) - _iso_val;
|
||||
// if (ccVal*pointVal < 0)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
//return false;
|
||||
|
||||
|
||||
////- Refinement based on intersection with multiple planes.
|
||||
//// Does not work well - too high a ratio between
|
||||
//// neighbouring cubes.
|
||||
//const pointField points(bb.points());
|
||||
//const edgeList& edges = treeBoundBox::edges;
|
||||
//pointField start(edges.size());
|
||||
//pointField end(edges.size());
|
||||
//forAll(edges, i)
|
||||
//{
|
||||
// start[i] = points[edges[i][0]];
|
||||
// end[i] = points[edges[i][1]];
|
||||
//}
|
||||
//Foam::List<Foam::List<pointIndexHit> > hitInfo;
|
||||
//labelListList hitSurfaces;
|
||||
//searchableSurfacesQueries::findAllIntersections
|
||||
//(
|
||||
// geometry,
|
||||
// surfaces,
|
||||
// start,
|
||||
// end,
|
||||
// hitSurfaces,
|
||||
// hitInfo
|
||||
//);
|
||||
//
|
||||
//// Count number of intersections
|
||||
//label nInt = 0;
|
||||
//forAll(hitSurfaces, edgeI)
|
||||
//{
|
||||
// nInt += hitSurfaces[edgeI].size();
|
||||
//}
|
||||
//
|
||||
//if (nInt == 0)
|
||||
//{
|
||||
// // No surface intersected. See if there is one inside
|
||||
// forAll(surfaces, i)
|
||||
// {
|
||||
// if (geometry[surfaces[i]].overlaps(bb))
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
//}
|
||||
//
|
||||
//// Check multiple surfaces
|
||||
//label baseSurfI = -1;
|
||||
//forAll(hitSurfaces, edgeI)
|
||||
//{
|
||||
// const labelList& hSurfs = hitSurfaces[edgeI];
|
||||
// forAll(hSurfs, i)
|
||||
// {
|
||||
// if (baseSurfI == -1)
|
||||
// {
|
||||
// baseSurfI = hSurfs[i];
|
||||
// }
|
||||
// else if (baseSurfI != hSurfs[i])
|
||||
// {
|
||||
// // Multiple surfaces
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// Get normals
|
||||
//DynamicList<pointIndexHit> baseInfo(nInt);
|
||||
//forAll(hitInfo, edgeI)
|
||||
//{
|
||||
// const Foam::List<pointIndexHit>& hits = hitInfo[edgeI];
|
||||
// forAll(hits, i)
|
||||
// {
|
||||
// (void)hits[i].hitPoint();
|
||||
// baseInfo.append(hits[i]);
|
||||
// }
|
||||
//}
|
||||
//vectorField normals;
|
||||
//geometry[surfaces[baseSurfI]].getNormal(baseInfo, normals);
|
||||
//for (label i = 1; i < normals.size(); ++i)
|
||||
//{
|
||||
// if ((normals[0] & normals[i]) < 0.9)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
//labelList regions;
|
||||
//geometry[surfaces[baseSurfI]].getRegion(baseInfo, regions);
|
||||
//for (label i = 1; i < regions.size(); ++i)
|
||||
//{
|
||||
// if (regions[0] != regions[i])
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
//return false;
|
||||
|
||||
|
||||
|
||||
//samples[0] = point(c.xmin(), c.ymin(), c.zmin());
|
||||
//samples[1] = point(c.xmax(), c.ymin(), c.zmin());
|
||||
//samples[2] = point(c.xmax(), c.ymax(), c.zmin());
|
||||
//samples[3] = point(c.xmin(), c.ymax(), c.zmin());
|
||||
//
|
||||
//samples[4] = point(c.xmin(), c.ymin(), c.zmax());
|
||||
//samples[5] = point(c.xmax(), c.ymin(), c.zmax());
|
||||
//samples[6] = point(c.xmax(), c.ymax(), c.zmax());
|
||||
//samples[7] = point(c.xmin(), c.ymax(), c.zmax());
|
||||
|
||||
//scalarField nearestDistSqr(8, GREAT);
|
||||
//
|
||||
//Foam::List<pointIndexHit> nearestInfo;
|
||||
//surf_.findNearest(samples, nearestDistSqr, nearestInfo);
|
||||
//vectorField normals;
|
||||
//surf_.getNormal(nearestInfo, normals);
|
||||
//
|
||||
//for (label i = 1; i < normals.size(); ++i)
|
||||
//{
|
||||
// if ((normals[0] & normals[i]) < 0.5)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
//return false;
|
||||
|
||||
//// Check if surface octree same level
|
||||
//const labelList elems(surf_.tree().findBox(bb));
|
||||
//
|
||||
//if (elems.size() > 1)
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
}
|
||||
|
||||
//- data function
|
||||
virtual real value_at( const Cube &c )
|
||||
{
|
||||
return signedDistance(converter_.toGlobal(c)) - _iso_val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -52,19 +368,16 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
"Re-sample surfaces used in cvMesh operation"
|
||||
);
|
||||
//argList::validArgs.append("inputFile");
|
||||
argList::validArgs.append("(nx ny nz)");
|
||||
argList::validArgs.append("outputName");
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
runTime.functionObjects().off();
|
||||
|
||||
const Vector<label> n(IStringStream(args.args()[1])());
|
||||
const fileName exportName = args.args()[2];
|
||||
const fileName exportName = args.args()[1];
|
||||
|
||||
Info<< "Reading surfaces as specified in the cvMeshDict and"
|
||||
<< " writing re-sampled " << n << " to " << exportName
|
||||
<< " writing a re-sampled surface to " << exportName
|
||||
<< nl << endl;
|
||||
|
||||
cpuTime timer;
|
||||
@ -114,126 +427,100 @@ int main(int argc, char *argv[])
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
|
||||
// Extend
|
||||
treeBoundBox bb = geometryToConformTo.globalBounds();
|
||||
{
|
||||
const vector smallVec = 0.1*bb.span();
|
||||
bb.min() -= smallVec;
|
||||
bb.max() += smallVec;
|
||||
}
|
||||
|
||||
Info<< "Meshing to bounding box " << bb << nl << endl;
|
||||
|
||||
const vector span(bb.span());
|
||||
const vector d
|
||||
(
|
||||
span.x()/(n.x()-1),
|
||||
span.y()/(n.y()-1),
|
||||
span.z()/(n.z()-1)
|
||||
);
|
||||
|
||||
MarchingCubes mc(span.x(), span.y(), span.z() ) ;
|
||||
mc.set_resolution(n.x(), n.y(), n.z());
|
||||
mc.init_all() ;
|
||||
|
||||
|
||||
// Generate points
|
||||
pointField points(mc.size_x()*mc.size_y()*mc.size_z());
|
||||
label pointI = 0;
|
||||
|
||||
point pt;
|
||||
for( int k = 0 ; k < mc.size_z() ; k++ )
|
||||
{
|
||||
pt.z() = bb.min().z() + k*d.z();
|
||||
for( int j = 0 ; j < mc.size_y() ; j++ )
|
||||
{
|
||||
pt.y() = bb.min().y() + j*d.y();
|
||||
for( int i = 0 ; i < mc.size_x() ; i++ )
|
||||
{
|
||||
pt.x() = bb.min().x() + i*d.x();
|
||||
points[pointI++] = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Generated " << points.size() << " sampling points in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
// Compute data
|
||||
const searchableSurfaces& geometry = geometryToConformTo.geometry();
|
||||
const labelList& surfaces = geometryToConformTo.surfaces();
|
||||
|
||||
scalarField signedDist;
|
||||
labelList nearestSurfaces;
|
||||
searchableSurfacesQueries::signedDistance
|
||||
|
||||
const label minLevel = 2;
|
||||
|
||||
// The max cube size follows from the minLevel and the default cube size
|
||||
// (1)
|
||||
const scalar maxSize = 1.0 / (1 << minLevel);
|
||||
const scalar halfMaxSize = 0.5*maxSize;
|
||||
|
||||
|
||||
// Scale the geometry to fit within
|
||||
// halfMaxSize .. 1-halfMaxSize
|
||||
|
||||
scalar wantedRange = 1.0-maxSize;
|
||||
|
||||
const treeBoundBox bb = geometryToConformTo.globalBounds();
|
||||
|
||||
const vector scale = cmptDivide
|
||||
(
|
||||
geometry,
|
||||
surfaces,
|
||||
points,
|
||||
scalarField(points.size(), sqr(GREAT)),
|
||||
searchableSurface::OUTSIDE, // for non-closed surfaces treat as
|
||||
// outside
|
||||
nearestSurfaces,
|
||||
signedDist
|
||||
point(wantedRange, wantedRange, wantedRange),
|
||||
bb.span()
|
||||
);
|
||||
const vector offset =
|
||||
cmptDivide
|
||||
(
|
||||
point(halfMaxSize, halfMaxSize, halfMaxSize),
|
||||
scale
|
||||
)
|
||||
-bb.min();
|
||||
|
||||
|
||||
const pointConversion converter(scale, offset);
|
||||
|
||||
|
||||
// Marching cubes
|
||||
|
||||
OptOctree octree;
|
||||
|
||||
distanceCalc ref
|
||||
(
|
||||
8, //maxLevel
|
||||
0.0, //distance
|
||||
minLevel, //minLevel
|
||||
geometryToConformTo,
|
||||
converter
|
||||
);
|
||||
|
||||
// Fill elements
|
||||
pointI = 0;
|
||||
for( int k = 0 ; k < mc.size_z() ; k++ )
|
||||
{
|
||||
for( int j = 0 ; j < mc.size_y() ; j++ )
|
||||
{
|
||||
for( int i = 0 ; i < mc.size_x() ; i++ )
|
||||
{
|
||||
mc.set_data(float(signedDist[pointI++]), i, j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
octree.refine(&ref);
|
||||
octree.set_impl(&ref);
|
||||
|
||||
Info<< "Determined signed distance in = "
|
||||
Info<< "Calculated octree in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
MarchingCubes& mc = octree.mc();
|
||||
|
||||
mc.run() ;
|
||||
mc.clean_all() ;
|
||||
octree.build_isosurface(&ref) ;
|
||||
|
||||
Info<< "Constructed iso surface in = "
|
||||
Info<< "Constructed iso surface of distance in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
mc.clean_temps() ;
|
||||
|
||||
|
||||
|
||||
// Write output file
|
||||
if (mc.ntrigs() > 0)
|
||||
{
|
||||
Triangle* triangles = mc.triangles();
|
||||
List<labelledTri> tris(mc.ntrigs());
|
||||
forAll(tris, triI)
|
||||
label nTris = mc.ntrigs();
|
||||
Foam::DynamicList<labelledTri> tris(mc.ntrigs());
|
||||
for (label triI = 0; triI < nTris; ++triI)
|
||||
{
|
||||
tris[triI] = labelledTri
|
||||
(
|
||||
triangles[triI].v1,
|
||||
triangles[triI].v2,
|
||||
triangles[triI].v3,
|
||||
0 // region
|
||||
);
|
||||
const Triangle& t = triangles[triI];
|
||||
if (t.v1 != t.v2 && t.v1 != t.v3 && t.v2 != t.v3)
|
||||
{
|
||||
tris.append
|
||||
(
|
||||
labelledTri
|
||||
(
|
||||
triangles[triI].v1,
|
||||
triangles[triI].v2,
|
||||
triangles[triI].v3,
|
||||
0 // region
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vertex* vertices = mc.vertices();
|
||||
Point* vertices = mc.vertices();
|
||||
pointField points(mc.nverts());
|
||||
forAll(points, pointI)
|
||||
{
|
||||
Vertex& v = vertices[pointI];
|
||||
points[pointI] = point
|
||||
(
|
||||
bb.min().x() + v.x*span.x()/mc.size_x(),
|
||||
bb.min().y() + v.y*span.y()/mc.size_y(),
|
||||
bb.min().z() + v.z*span.z()/mc.size_z()
|
||||
);
|
||||
const Point& v = vertices[pointI];
|
||||
points[pointI] = converter.toGlobal(v);
|
||||
}
|
||||
|
||||
|
||||
@ -267,6 +554,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
triSurface s(tris, patches, points, true);
|
||||
tris.clearStorage();
|
||||
|
||||
Info<< "Extracted triSurface in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
@ -274,7 +562,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Find out region on local surface of nearest point
|
||||
{
|
||||
List<pointIndexHit> hitInfo;
|
||||
Foam::List<pointIndexHit> hitInfo;
|
||||
labelList hitSurfaces;
|
||||
geometryToConformTo.findSurfaceNearest
|
||||
(
|
||||
@ -342,7 +630,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
mc.clean_all() ;
|
||||
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -0,0 +1,352 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Application
|
||||
cvMeshSurfaceSimplify
|
||||
|
||||
Description
|
||||
Simplifies surfaces by resampling.
|
||||
|
||||
Uses Thomas Lewiner's topology preserving MarchingCubes.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "Time.H"
|
||||
#include "searchableSurfaces.H"
|
||||
#include "conformationSurfaces.H"
|
||||
#include "triSurfaceMesh.H"
|
||||
|
||||
#include "MarchingCubes.h"
|
||||
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::addNote
|
||||
(
|
||||
"Re-sample surfaces used in cvMesh operation"
|
||||
);
|
||||
//argList::validArgs.append("inputFile");
|
||||
argList::validArgs.append("(nx ny nz)");
|
||||
argList::validArgs.append("outputName");
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
runTime.functionObjects().off();
|
||||
|
||||
const Vector<label> n(IStringStream(args.args()[1])());
|
||||
const fileName exportName = args.args()[2];
|
||||
|
||||
Info<< "Reading surfaces as specified in the cvMeshDict and"
|
||||
<< " writing re-sampled " << n << " to " << exportName
|
||||
<< nl << endl;
|
||||
|
||||
cpuTime timer;
|
||||
|
||||
IOdictionary cvMeshDict
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cvMeshDict",
|
||||
runTime.system(),
|
||||
runTime,
|
||||
IOobject::MUST_READ_IF_MODIFIED,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
);
|
||||
|
||||
// Define/load all geometry
|
||||
searchableSurfaces allGeometry
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cvSearchableSurfaces",
|
||||
runTime.constant(),
|
||||
"triSurface",
|
||||
runTime,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
cvMeshDict.subDict("geometry")
|
||||
);
|
||||
|
||||
Info<< "Geometry read in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
Random rndGen(64293*Pstream::myProcNo());
|
||||
|
||||
conformationSurfaces geometryToConformTo
|
||||
(
|
||||
runTime,
|
||||
rndGen,
|
||||
allGeometry,
|
||||
cvMeshDict.subDict("surfaceConformation")
|
||||
);
|
||||
|
||||
Info<< "Set up geometry in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
|
||||
// Extend
|
||||
treeBoundBox bb = geometryToConformTo.globalBounds();
|
||||
{
|
||||
const vector smallVec = 0.1*bb.span();
|
||||
bb.min() -= smallVec;
|
||||
bb.max() += smallVec;
|
||||
}
|
||||
|
||||
Info<< "Meshing to bounding box " << bb << nl << endl;
|
||||
|
||||
const vector span(bb.span());
|
||||
const vector d
|
||||
(
|
||||
span.x()/(n.x()-1),
|
||||
span.y()/(n.y()-1),
|
||||
span.z()/(n.z()-1)
|
||||
);
|
||||
|
||||
MarchingCubes mc(span.x(), span.y(), span.z() ) ;
|
||||
mc.set_resolution(n.x(), n.y(), n.z());
|
||||
mc.init_all() ;
|
||||
|
||||
|
||||
// Generate points
|
||||
pointField points(mc.size_x()*mc.size_y()*mc.size_z());
|
||||
label pointI = 0;
|
||||
|
||||
point pt;
|
||||
for( int k = 0 ; k < mc.size_z() ; k++ )
|
||||
{
|
||||
pt.z() = bb.min().z() + k*d.z();
|
||||
for( int j = 0 ; j < mc.size_y() ; j++ )
|
||||
{
|
||||
pt.y() = bb.min().y() + j*d.y();
|
||||
for( int i = 0 ; i < mc.size_x() ; i++ )
|
||||
{
|
||||
pt.x() = bb.min().x() + i*d.x();
|
||||
points[pointI++] = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Generated " << points.size() << " sampling points in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
// Compute data
|
||||
const searchableSurfaces& geometry = geometryToConformTo.geometry();
|
||||
const labelList& surfaces = geometryToConformTo.surfaces();
|
||||
|
||||
scalarField signedDist;
|
||||
labelList nearestSurfaces;
|
||||
searchableSurfacesQueries::signedDistance
|
||||
(
|
||||
geometry,
|
||||
surfaces,
|
||||
points,
|
||||
scalarField(points.size(), sqr(GREAT)),
|
||||
searchableSurface::OUTSIDE, // for non-closed surfaces treat as
|
||||
// outside
|
||||
nearestSurfaces,
|
||||
signedDist
|
||||
);
|
||||
|
||||
// Fill elements
|
||||
pointI = 0;
|
||||
for( int k = 0 ; k < mc.size_z() ; k++ )
|
||||
{
|
||||
for( int j = 0 ; j < mc.size_y() ; j++ )
|
||||
{
|
||||
for( int i = 0 ; i < mc.size_x() ; i++ )
|
||||
{
|
||||
mc.set_data(float(signedDist[pointI++]), i, j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Determined signed distance in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
mc.run() ;
|
||||
|
||||
Info<< "Constructed iso surface in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
mc.clean_temps() ;
|
||||
|
||||
|
||||
|
||||
// Write output file
|
||||
if (mc.ntrigs() > 0)
|
||||
{
|
||||
Triangle* triangles = mc.triangles();
|
||||
List<labelledTri> tris(mc.ntrigs());
|
||||
forAll(tris, triI)
|
||||
{
|
||||
tris[triI] = labelledTri
|
||||
(
|
||||
triangles[triI].v1,
|
||||
triangles[triI].v2,
|
||||
triangles[triI].v3,
|
||||
0 // region
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Vertex* vertices = mc.vertices();
|
||||
pointField points(mc.nverts());
|
||||
forAll(points, pointI)
|
||||
{
|
||||
Vertex& v = vertices[pointI];
|
||||
points[pointI] = point
|
||||
(
|
||||
bb.min().x() + v.x*span.x()/mc.size_x(),
|
||||
bb.min().y() + v.y*span.y()/mc.size_y(),
|
||||
bb.min().z() + v.z*span.z()/mc.size_z()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Find correspondence to original surfaces
|
||||
labelList regionOffsets(surfaces.size());
|
||||
label nRegions = 0;
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
const wordList& regions = geometry[surfaces[i]].regions();
|
||||
regionOffsets[i] = nRegions;
|
||||
nRegions += regions.size();
|
||||
}
|
||||
|
||||
|
||||
geometricSurfacePatchList patches(nRegions);
|
||||
nRegions = 0;
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
const wordList& regions = geometry[surfaces[i]].regions();
|
||||
|
||||
forAll(regions, regionI)
|
||||
{
|
||||
patches[nRegions] = geometricSurfacePatch
|
||||
(
|
||||
"patch",
|
||||
geometry[surfaces[i]].name() + "_" + regions[regionI],
|
||||
nRegions
|
||||
);
|
||||
nRegions++;
|
||||
}
|
||||
}
|
||||
|
||||
triSurface s(tris, patches, points, true);
|
||||
|
||||
Info<< "Extracted triSurface in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
|
||||
// Find out region on local surface of nearest point
|
||||
{
|
||||
List<pointIndexHit> hitInfo;
|
||||
labelList hitSurfaces;
|
||||
geometryToConformTo.findSurfaceNearest
|
||||
(
|
||||
s.faceCentres(),
|
||||
scalarField(s.size(), sqr(GREAT)),
|
||||
hitInfo,
|
||||
hitSurfaces
|
||||
);
|
||||
|
||||
// Get region
|
||||
DynamicList<pointIndexHit> surfInfo(hitSurfaces.size());
|
||||
DynamicList<label> surfIndices(hitSurfaces.size());
|
||||
|
||||
forAll(surfaces, surfI)
|
||||
{
|
||||
// Extract info on this surface
|
||||
surfInfo.clear();
|
||||
surfIndices.clear();
|
||||
forAll(hitSurfaces, triI)
|
||||
{
|
||||
if (hitSurfaces[triI] == surfI)
|
||||
{
|
||||
surfInfo.append(hitInfo[triI]);
|
||||
surfIndices.append(triI);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate sideness of these surface points
|
||||
labelList region;
|
||||
geometry[surfaces[surfI]].getRegion(surfInfo, region);
|
||||
|
||||
forAll(region, i)
|
||||
{
|
||||
label triI = surfIndices[i];
|
||||
s[triI].region() = regionOffsets[surfI]+region[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Re-patched surface in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
|
||||
triSurfaceMesh smesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
exportName,
|
||||
runTime.constant(), // instance
|
||||
"triSurface",
|
||||
runTime, // registry
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE,
|
||||
false
|
||||
),
|
||||
s
|
||||
);
|
||||
|
||||
Info<< "writing surfMesh:\n "
|
||||
<< smesh.searchableSurface::objectPath() << nl << endl;
|
||||
smesh.searchableSurface::write();
|
||||
|
||||
Info<< "Written surface in = "
|
||||
<< timer.cpuTimeIncrement() << " s." << nl << endl;
|
||||
}
|
||||
|
||||
mc.clean_all() ;
|
||||
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
BIN
applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/fastdualoctree_sgp/.DS_Store
vendored
Normal file
BIN
applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/fastdualoctree_sgp/.DS_Store
vendored
Normal file
Binary file not shown.
@ -0,0 +1,96 @@
|
||||
PROJECT(fastDualOctree)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
#---------------------------------------------------
|
||||
#----- Dependencies
|
||||
#---------------------------------------------------
|
||||
FIND_PACKAGE(OpenGL REQUIRED)
|
||||
if ( OPENGL_FOUND )
|
||||
message( "-- OpenGL found. include=${OPENGL_INCLUDE_DIR}" )
|
||||
include_directories( ${OPENGL_INCLUDE_DIR} )
|
||||
endif ( OPENGL_FOUND )
|
||||
|
||||
FIND_PACKAGE(ZLIB REQUIRED)
|
||||
if ( ZLIB_FOUND )
|
||||
message( "-- zlib found. include=${ZLIB_INCLUDE_DIR}" )
|
||||
include_directories( ${ZLIB_INCLUDE_DIR} )
|
||||
endif ( ZLIB_FOUND )
|
||||
|
||||
FIND_PACKAGE(PNG REQUIRED)
|
||||
if ( PNG_FOUND )
|
||||
message( "-- PNG found. include=${PNG_INCLUDE_DIR}" )
|
||||
include_directories( ${PNG_INCLUDE_DIR} )
|
||||
endif ( PNG_FOUND )
|
||||
|
||||
##-- GLUI dependency
|
||||
#FIND_PATH(GLUI_INCLUDE_DIR GL/glui.h ~/pub/system/glui-2.36/src/include)
|
||||
#FIND_LIBRARY(GLUI_LIBRARIES
|
||||
# NAMES GLUI glui
|
||||
# GLUT glut
|
||||
# PATHS /usr/local/lib/
|
||||
# /usr/lib/
|
||||
# /opt/graphics/OpenGL/lib
|
||||
# /usr/openwin/lib
|
||||
# /usr/shlib
|
||||
# /usr/X11R6/lib
|
||||
# ~/pub/system/glui-2.36/src/lib
|
||||
# )
|
||||
#if ( GLUI_INCLUDE_DIR )
|
||||
# message( "-- GL/glui.h found. include=${GLUI_INCLUDE_DIR}" )
|
||||
# include_directories( ${GLUI_INCLUDE_DIR} )
|
||||
#else ( GLUI_INCLUDE_DIR )
|
||||
# message( "-- GL/glui.h not found." )
|
||||
#endif ( GLUI_INCLUDE_DIR )
|
||||
#if ( GLUI_LIBRARIES )
|
||||
# message( "-- libglui found. include=${GLUI_LIBRARIES}" )
|
||||
#else( GLUI_LIBRARIES )
|
||||
# message( "-- libglui not found." )
|
||||
#endif ( GLUI_LIBRARIES )
|
||||
|
||||
#---------------------------------------------------
|
||||
# -- Environement variables
|
||||
#---------------------------------------------------
|
||||
if (UNIX)
|
||||
add_definitions(-DUNIX)
|
||||
endif (UNIX)
|
||||
if (WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
endif (WIN32)
|
||||
if (APPLE)
|
||||
add_definitions(-DAPPLE)
|
||||
endif (APPLE)
|
||||
|
||||
#---------------------------------------------------
|
||||
# -- SRCs
|
||||
#---------------------------------------------------
|
||||
|
||||
SET(Perf_SRC ${Perf_SRC}
|
||||
data_access.cpp
|
||||
hash_octree.cpp
|
||||
mc_draw.cpp
|
||||
opt_octree.cpp
|
||||
fparser.cpp
|
||||
leaf_octree.cpp
|
||||
mem_octree.cpp
|
||||
fpoptimizer.cpp
|
||||
MarchingCubes.cpp
|
||||
morton.cpp
|
||||
ptr_octree.cpp
|
||||
)
|
||||
|
||||
#SET(VIZ_SRC ${VIZ_SRC}
|
||||
# viz_glui_cmdline.cpp
|
||||
# viz_glui_controls.cpp
|
||||
# viz_glui_draws.cpp
|
||||
# viz_glui_export.cpp
|
||||
# viz_glui_mouse.cpp
|
||||
#)
|
||||
|
||||
|
||||
add_executable(perf_main perf_main ${Perf_SRC})
|
||||
target_link_libraries(perf_main ${OPENGL_LIBRARIES} ${ZLIB_LIBRARIES})
|
||||
|
||||
|
||||
#add_executable(viz_glui_main viz_glui_main ${Perf_SRC} ${VIZ_SRC} )
|
||||
#target_link_libraries(viz_glui_main ${OPENGL_LIBRARIES} ${ZLIB_LIBRARIES} ${PNG_LIBRARIES} ${GLUI_LIBRARIES})
|
||||
File diff suppressed because it is too large
Load Diff
@ -11,11 +11,7 @@
|
||||
|
||||
|
||||
|
||||
#ifndef _LOOKUPTABLE_H_
|
||||
#define _LOOKUPTABLE_H_
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
@ -773,54 +769,54 @@ static const char tiling6_1_1[48][9] = {
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
static const char tiling6_1_2[48][27] = {
|
||||
/* 67: 0, 1, 6, */ { 1, 12, 3, 12, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 12, 12, 9, 8, 1, 9, 12, 12, 5, 10 },
|
||||
/* 131: 0, 1, 7, */ { 1, 12, 3, 1, 11, 12, 11, 1, 6, 9, 6, 1, 6, 9, 7, 12, 7, 9, 9, 8, 12, 12, 8, 3, 11, 7, 12 },
|
||||
/* 21: 0, 2, 4, */ { 4, 12, 0, 4, 1, 12, 1, 4, 10, 7, 10, 4, 10, 7, 2, 12, 2, 7, 7, 3, 12, 12, 3, 0, 1, 2, 12 },
|
||||
/* 69: 0, 2, 6, */ { 6, 12, 2, 6, 3, 12, 3, 6, 8, 5, 8, 6, 8, 5, 0, 12, 0, 5, 5, 1, 12, 12, 1, 2, 3, 0, 12 },
|
||||
/* 41: 0, 3, 5, */ { 0, 12, 2, 12, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 12, 12, 8, 11, 0, 8, 12, 12, 4, 9 },
|
||||
/* 73: 0, 3, 6, */ { 0, 12, 2, 0, 10, 12, 10, 0, 5, 8, 5, 0, 5, 8, 6, 12, 6, 8, 8, 11, 12, 12, 11, 2, 10, 6, 12 },
|
||||
/* 81: 0, 4, 6, */ { 4, 12, 0, 12, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 12, 12, 7, 3, 4, 7, 12, 12, 6, 5 },
|
||||
/* 97: 0, 5, 6, */ { 4, 12, 6, 12, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 12, 12, 9, 10, 4, 9, 12, 12, 0, 8 },
|
||||
/* 193: 0, 6, 7, */ { 5, 12, 7, 5, 8, 12, 8, 5, 0, 10, 0, 5, 0, 10, 3, 12, 3, 10, 10, 11, 12, 12, 11, 7, 8, 3, 12 },
|
||||
/* 22: 1, 2, 4, */ { 2, 12, 0, 2, 8, 12, 8, 2, 7, 10, 7, 2, 7, 10, 4, 12, 4, 10, 10, 9, 12, 12, 9, 0, 8, 4, 12 },
|
||||
/* 134: 1, 2, 7, */ { 2, 12, 0, 12, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 12, 12, 10, 9, 2, 10, 12, 12, 6, 11 },
|
||||
/* 42: 1, 3, 5, */ { 5, 12, 1, 5, 2, 12, 2, 5, 11, 4, 11, 5, 11, 4, 3, 12, 3, 4, 4, 0, 12, 12, 0, 1, 2, 3, 12 },
|
||||
/* 138: 1, 3, 7, */ { 7, 12, 3, 7, 0, 12, 0, 7, 9, 6, 9, 7, 9, 6, 1, 12, 1, 6, 6, 2, 12, 12, 2, 3, 0, 1, 12 },
|
||||
/* 146: 1, 4, 7, */ { 6, 12, 4, 6, 9, 12, 9, 6, 1, 11, 1, 6, 1, 11, 0, 12, 0, 11, 11, 8, 12, 12, 8, 4, 9, 0, 12 },
|
||||
/* 162: 1, 5, 7, */ { 5, 12, 1, 12, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 12, 12, 4, 0, 5, 4, 12, 12, 7, 6 },
|
||||
/* 194: 1, 6, 7, */ { 5, 12, 7, 12, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 12, 12, 10, 11, 5, 10, 12, 12, 1, 9 },
|
||||
/* 28: 2, 3, 4, */ { 3, 12, 1, 12, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 12, 12, 11, 10, 3, 11, 12, 12, 7, 8 },
|
||||
/* 44: 2, 3, 5, */ { 3, 12, 1, 3, 9, 12, 9, 3, 4, 11, 4, 3, 4, 11, 5, 12, 5, 11, 11, 10, 12, 12, 10, 1, 9, 5, 12 },
|
||||
/* 52: 2, 4, 5, */ { 7, 12, 5, 7, 10, 12, 10, 7, 2, 8, 2, 7, 2, 8, 1, 12, 1, 8, 8, 9, 12, 12, 9, 5, 10, 1, 12 },
|
||||
/* 84: 2, 4, 6, */ { 6, 12, 2, 12, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 12, 12, 5, 1, 6, 5, 12, 12, 4, 7 },
|
||||
/* 148: 2, 4, 7, */ { 6, 12, 4, 12, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 12, 12, 11, 8, 6, 11, 12, 12, 2, 10 },
|
||||
/* 56: 3, 4, 5, */ { 7, 12, 5, 12, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 12, 12, 8, 9, 7, 8, 12, 12, 3, 11 },
|
||||
/* 104: 3, 5, 6, */ { 4, 12, 6, 4, 11, 12, 11, 4, 3, 9, 3, 4, 3, 9, 2, 12, 2, 9, 9, 10, 12, 12, 10, 6, 11, 2, 12 },
|
||||
/* 168: 3, 5, 7, */ { 7, 12, 3, 12, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 12, 12, 6, 2, 7, 6, 12, 12, 5, 4 },
|
||||
/* 87: 0, 1, 2, 4, 6, */ { 3, 12, 7, 3, 4, 12, 4, 3, 9, 2, 9, 3, 9, 2, 5, 12, 5, 2, 2, 6, 12, 12, 6, 7, 4, 5, 12 },
|
||||
/* 151: 0, 1, 2, 4, 7, */ { 6, 12, 4, 12, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 12, 12, 10, 9, 6, 10, 12, 12, 2, 11 },
|
||||
/* 199: 0, 1, 2, 6, 7, */ { 5, 12, 7, 5, 11, 12, 11, 5, 2, 9, 2, 5, 2, 9, 3, 12, 3, 9, 9, 8, 12, 12, 8, 7, 11, 3, 12 },
|
||||
/* 107: 0, 1, 3, 5, 6, */ { 4, 12, 6, 4, 10, 12, 10, 4, 1, 8, 1, 4, 1, 8, 2, 12, 2, 8, 8, 11, 12, 12, 11, 6, 10, 2, 12 },
|
||||
/* 171: 0, 1, 3, 5, 7, */ { 2, 12, 6, 2, 7, 12, 7, 2, 8, 1, 8, 2, 8, 1, 4, 12, 4, 1, 1, 5, 12, 12, 5, 6, 7, 4, 12 },
|
||||
/* 203: 0, 1, 3, 6, 7, */ { 5, 12, 7, 12, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 12, 12, 9, 8, 5, 9, 12, 12, 1, 10 },
|
||||
/* 211: 0, 1, 4, 6, 7, */ { 1, 12, 3, 12, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 12, 12, 10, 11, 1, 10, 12, 12, 5, 9 },
|
||||
/* 227: 0, 1, 5, 6, 7, */ { 1, 12, 3, 1, 8, 12, 8, 1, 4, 10, 4, 1, 4, 10, 7, 12, 7, 10, 10, 11, 12, 12, 11, 3, 8, 7, 12 },
|
||||
/* 61: 0, 2, 3, 4, 5, */ { 7, 12, 5, 7, 9, 12, 9, 7, 0, 11, 0, 7, 0, 11, 1, 12, 1, 11, 11, 10, 12, 12, 10, 5, 9, 1, 12 },
|
||||
/* 93: 0, 2, 3, 4, 6, */ { 1, 12, 5, 1, 6, 12, 6, 1, 11, 0, 11, 1, 11, 0, 7, 12, 7, 0, 0, 4, 12, 12, 4, 5, 6, 7, 12 },
|
||||
/* 109: 0, 2, 3, 5, 6, */ { 4, 12, 6, 12, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 12, 12, 8, 11, 4, 8, 12, 12, 0, 9 },
|
||||
/* 117: 0, 2, 4, 5, 6, */ { 3, 12, 7, 12, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 12, 12, 2, 6, 3, 2, 12, 12, 1, 0 },
|
||||
/* 213: 0, 2, 4, 6, 7, */ { 1, 12, 5, 12, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 12, 12, 0, 4, 1, 0, 12, 12, 3, 2 },
|
||||
/* 121: 0, 3, 4, 5, 6, */ { 0, 12, 2, 0, 11, 12, 11, 0, 7, 9, 7, 0, 7, 9, 6, 12, 6, 9, 9, 10, 12, 12, 10, 2, 11, 6, 12 },
|
||||
/* 233: 0, 3, 5, 6, 7, */ { 0, 12, 2, 12, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 12, 12, 9, 10, 0, 9, 12, 12, 4, 8 },
|
||||
/* 62: 1, 2, 3, 4, 5, */ { 7, 12, 5, 12, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 12, 12, 11, 10, 7, 11, 12, 12, 3, 8 },
|
||||
/* 158: 1, 2, 3, 4, 7, */ { 6, 12, 4, 6, 8, 12, 8, 6, 3, 10, 3, 6, 3, 10, 0, 12, 0, 10, 10, 9, 12, 12, 9, 4, 8, 0, 12 },
|
||||
/* 174: 1, 2, 3, 5, 7, */ { 0, 12, 4, 0, 5, 12, 5, 0, 10, 3, 10, 0, 10, 3, 6, 12, 6, 3, 3, 7, 12, 12, 7, 4, 5, 6, 12 },
|
||||
/* 182: 1, 2, 4, 5, 7, */ { 2, 12, 0, 12, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 12, 12, 11, 8, 2, 11, 12, 12, 6, 10 },
|
||||
/* 214: 1, 2, 4, 6, 7, */ { 2, 12, 0, 2, 9, 12, 9, 2, 5, 11, 5, 2, 5, 11, 4, 12, 4, 11, 11, 8, 12, 12, 8, 0, 9, 4, 12 },
|
||||
/* 186: 1, 3, 4, 5, 7, */ { 2, 12, 6, 12, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 12, 12, 1, 5, 2, 1, 12, 12, 0, 3 },
|
||||
/* 234: 1, 3, 5, 6, 7, */ { 0, 12, 4, 12, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 12, 12, 3, 7, 0, 3, 12, 12, 2, 1 },
|
||||
/* 124: 2, 3, 4, 5, 6, */ { 3, 12, 1, 12, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 12, 12, 8, 9, 3, 8, 12, 12, 7, 11 },
|
||||
/* 188: 2, 3, 4, 5, 7, */ { 3, 12, 1, 3, 10, 12, 10, 3, 6, 8, 6, 3, 6, 8, 5, 12, 5, 8, 8, 9, 12, 12, 9, 1, 10, 5, 12 },
|
||||
/* 67: 0, 1, 6, */ { 1, 12, 3, 12, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 12, 12, 9, 8, 1, 9, 12, 12, 5, 10 },
|
||||
/* 131: 0, 1, 7, */ { 1, 12, 3, 1, 11, 12, 11, 1, 6, 9, 6, 1, 6, 9, 7, 12, 7, 9, 9, 8, 12, 12, 8, 3, 11, 7, 12 },
|
||||
/* 21: 0, 2, 4, */ { 4, 12, 0, 4, 1, 12, 1, 4, 10, 7, 10, 4, 10, 7, 2, 12, 2, 7, 7, 3, 12, 12, 3, 0, 1, 2, 12 },
|
||||
/* 69: 0, 2, 6, */ { 6, 12, 2, 6, 3, 12, 3, 6, 8, 5, 8, 6, 8, 5, 0, 12, 0, 5, 5, 1, 12, 12, 1, 2, 3, 0, 12 },
|
||||
/* 41: 0, 3, 5, */ { 0, 12, 2, 12, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 12, 12, 8, 11, 0, 8, 12, 12, 4, 9 },
|
||||
/* 73: 0, 3, 6, */ { 0, 12, 2, 0, 10, 12, 10, 0, 5, 8, 5, 0, 5, 8, 6, 12, 6, 8, 8, 11, 12, 12, 11, 2, 10, 6, 12 },
|
||||
/* 81: 0, 4, 6, */ { 4, 12, 0, 12, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 12, 12, 7, 3, 4, 7, 12, 12, 6, 5 },
|
||||
/* 97: 0, 5, 6, */ { 4, 12, 6, 12, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 12, 12, 9, 10, 4, 9, 12, 12, 0, 8 },
|
||||
/* 193: 0, 6, 7, */ { 5, 12, 7, 5, 8, 12, 8, 5, 0, 10, 0, 5, 0, 10, 3, 12, 3, 10, 10, 11, 12, 12, 11, 7, 8, 3, 12 },
|
||||
/* 22: 1, 2, 4, */ { 2, 12, 0, 2, 8, 12, 8, 2, 7, 10, 7, 2, 7, 10, 4, 12, 4, 10, 10, 9, 12, 12, 9, 0, 8, 4, 12 },
|
||||
/* 134: 1, 2, 7, */ { 2, 12, 0, 12, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 12, 12, 10, 9, 2, 10, 12, 12, 6, 11 },
|
||||
/* 42: 1, 3, 5, */ { 5, 12, 1, 5, 2, 12, 2, 5, 11, 4, 11, 5, 11, 4, 3, 12, 3, 4, 4, 0, 12, 12, 0, 1, 2, 3, 12 },
|
||||
/* 138: 1, 3, 7, */ { 7, 12, 3, 7, 0, 12, 0, 7, 9, 6, 9, 7, 9, 6, 1, 12, 1, 6, 6, 2, 12, 12, 2, 3, 0, 1, 12 },
|
||||
/* 146: 1, 4, 7, */ { 6, 12, 4, 6, 9, 12, 9, 6, 1, 11, 1, 6, 1, 11, 0, 12, 0, 11, 11, 8, 12, 12, 8, 4, 9, 0, 12 },
|
||||
/* 162: 1, 5, 7, */ { 5, 12, 1, 12, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 12, 12, 4, 0, 5, 4, 12, 12, 7, 6 },
|
||||
/* 194: 1, 6, 7, */ { 5, 12, 7, 12, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 12, 12, 10, 11, 5, 10, 12, 12, 1, 9 },
|
||||
/* 28: 2, 3, 4, */ { 3, 12, 1, 12, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 12, 12, 11, 10, 3, 11, 12, 12, 7, 8 },
|
||||
/* 44: 2, 3, 5, */ { 3, 12, 1, 3, 9, 12, 9, 3, 4, 11, 4, 3, 4, 11, 5, 12, 5, 11, 11, 10, 12, 12, 10, 1, 9, 5, 12 },
|
||||
/* 52: 2, 4, 5, */ { 7, 12, 5, 7, 10, 12, 10, 7, 2, 8, 2, 7, 2, 8, 1, 12, 1, 8, 8, 9, 12, 12, 9, 5, 10, 1, 12 },
|
||||
/* 84: 2, 4, 6, */ { 6, 12, 2, 12, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 12, 12, 5, 1, 6, 5, 12, 12, 4, 7 },
|
||||
/* 148: 2, 4, 7, */ { 6, 12, 4, 12, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 12, 12, 11, 8, 6, 11, 12, 12, 2, 10 },
|
||||
/* 56: 3, 4, 5, */ { 7, 12, 5, 12, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 12, 12, 8, 9, 7, 8, 12, 12, 3, 11 },
|
||||
/* 104: 3, 5, 6, */ { 4, 12, 6, 4, 11, 12, 11, 4, 3, 9, 3, 4, 3, 9, 2, 12, 2, 9, 9, 10, 12, 12, 10, 6, 11, 2, 12 },
|
||||
/* 168: 3, 5, 7, */ { 7, 12, 3, 12, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 12, 12, 6, 2, 7, 6, 12, 12, 5, 4 },
|
||||
/* 87: 0, 1, 2, 4, 6, */ { 3, 12, 7, 3, 4, 12, 4, 3, 9, 2, 9, 3, 9, 2, 5, 12, 5, 2, 2, 6, 12, 12, 6, 7, 4, 5, 12 },
|
||||
/* 151: 0, 1, 2, 4, 7, */ { 6, 12, 4, 12, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 12, 12, 10, 9, 6, 10, 12, 12, 2, 11 },
|
||||
/* 199: 0, 1, 2, 6, 7, */ { 5, 12, 7, 5, 11, 12, 11, 5, 2, 9, 2, 5, 2, 9, 3, 12, 3, 9, 9, 8, 12, 12, 8, 7, 11, 3, 12 },
|
||||
/* 107: 0, 1, 3, 5, 6, */ { 4, 12, 6, 4, 10, 12, 10, 4, 1, 8, 1, 4, 1, 8, 2, 12, 2, 8, 8, 11, 12, 12, 11, 6, 10, 2, 12 },
|
||||
/* 171: 0, 1, 3, 5, 7, */ { 2, 12, 6, 2, 7, 12, 7, 2, 8, 1, 8, 2, 8, 1, 4, 12, 4, 1, 1, 5, 12, 12, 5, 6, 7, 4, 12 },
|
||||
/* 203: 0, 1, 3, 6, 7, */ { 5, 12, 7, 12, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 12, 12, 9, 8, 5, 9, 12, 12, 1, 10 },
|
||||
/* 211: 0, 1, 4, 6, 7, */ { 1, 12, 3, 12, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 12, 12, 10, 11, 1, 10, 12, 12, 5, 9 },
|
||||
/* 227: 0, 1, 5, 6, 7, */ { 1, 12, 3, 1, 8, 12, 8, 1, 4, 10, 4, 1, 4, 10, 7, 12, 7, 10, 10, 11, 12, 12, 11, 3, 8, 7, 12 },
|
||||
/* 61: 0, 2, 3, 4, 5, */ { 7, 12, 5, 7, 9, 12, 9, 7, 0, 11, 0, 7, 0, 11, 1, 12, 1, 11, 11, 10, 12, 12, 10, 5, 9, 1, 12 },
|
||||
/* 93: 0, 2, 3, 4, 6, */ { 1, 12, 5, 1, 6, 12, 6, 1, 11, 0, 11, 1, 11, 0, 7, 12, 7, 0, 0, 4, 12, 12, 4, 5, 6, 7, 12 },
|
||||
/* 109: 0, 2, 3, 5, 6, */ { 4, 12, 6, 12, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 12, 12, 8, 11, 4, 8, 12, 12, 0, 9 },
|
||||
/* 117: 0, 2, 4, 5, 6, */ { 3, 12, 7, 12, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 12, 12, 2, 6, 3, 2, 12, 12, 1, 0 },
|
||||
/* 213: 0, 2, 4, 6, 7, */ { 1, 12, 5, 12, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 12, 12, 0, 4, 1, 0, 12, 12, 3, 2 },
|
||||
/* 121: 0, 3, 4, 5, 6, */ { 0, 12, 2, 0, 11, 12, 11, 0, 7, 9, 7, 0, 7, 9, 6, 12, 6, 9, 9, 10, 12, 12, 10, 2, 11, 6, 12 },
|
||||
/* 233: 0, 3, 5, 6, 7, */ { 0, 12, 2, 12, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 12, 12, 9, 10, 0, 9, 12, 12, 4, 8 },
|
||||
/* 62: 1, 2, 3, 4, 5, */ { 7, 12, 5, 12, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 12, 12, 11, 10, 7, 11, 12, 12, 3, 8 },
|
||||
/* 158: 1, 2, 3, 4, 7, */ { 6, 12, 4, 6, 8, 12, 8, 6, 3, 10, 3, 6, 3, 10, 0, 12, 0, 10, 10, 9, 12, 12, 9, 4, 8, 0, 12 },
|
||||
/* 174: 1, 2, 3, 5, 7, */ { 0, 12, 4, 0, 5, 12, 5, 0, 10, 3, 10, 0, 10, 3, 6, 12, 6, 3, 3, 7, 12, 12, 7, 4, 5, 6, 12 },
|
||||
/* 182: 1, 2, 4, 5, 7, */ { 2, 12, 0, 12, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 12, 12, 11, 8, 2, 11, 12, 12, 6, 10 },
|
||||
/* 214: 1, 2, 4, 6, 7, */ { 2, 12, 0, 2, 9, 12, 9, 2, 5, 11, 5, 2, 5, 11, 4, 12, 4, 11, 11, 8, 12, 12, 8, 0, 9, 4, 12 },
|
||||
/* 186: 1, 3, 4, 5, 7, */ { 2, 12, 6, 12, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 12, 12, 1, 5, 2, 1, 12, 12, 0, 3 },
|
||||
/* 234: 1, 3, 5, 6, 7, */ { 0, 12, 4, 12, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 12, 12, 3, 7, 0, 3, 12, 12, 2, 1 },
|
||||
/* 124: 2, 3, 4, 5, 6, */ { 3, 12, 1, 12, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 12, 12, 8, 9, 3, 8, 12, 12, 7, 11 },
|
||||
/* 188: 2, 3, 4, 5, 7, */ { 3, 12, 1, 3, 10, 12, 10, 3, 6, 8, 6, 3, 6, 8, 5, 12, 5, 8, 8, 9, 12, 12, 9, 1, 10, 5, 12 },
|
||||
};
|
||||
|
||||
//_____________________________________________________________________________
|
||||
@ -1669,8 +1665,8 @@ static const char tiling12_2_[24][24] = {
|
||||
//-----------------------------------------------------------------------------
|
||||
/* 13: face test */
|
||||
static const char test13[2][7] = {
|
||||
/* 165: 0, 2, 5, 7, */ { 1,2,3,4,5,6,7 },
|
||||
/* 90: 1, 3, 4, 6, */ { 2,3,4,1,5,6,7 },
|
||||
/* 165: 0, 2, 5, 7, */ { 1,2,3,4,5,6, 7 },
|
||||
/* 90: 1, 3, 4, 6, */ { 2,3,4,1,5,6,-7 },
|
||||
};
|
||||
|
||||
|
||||
@ -2319,4 +2315,3 @@ static const char casesClassic[256][16] = {
|
||||
|
||||
|
||||
|
||||
#endif // _LOOKUPTABLE_H_
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* @file MarchingCubes.h
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.2
|
||||
* @date 12/08/2002
|
||||
*
|
||||
* @brief MarchingCubes Algorithm
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
#include <map>
|
||||
#include "morton.h"
|
||||
#include "point.h"
|
||||
#include "data_access.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Triangle structure
|
||||
/** \struct Triangle "MarchingCubes.h" MarchingCubes
|
||||
* Indices of the oriented triange vertices
|
||||
* \brief triangle structure
|
||||
* \param v1 First vertex index
|
||||
* \param v2 Second vertex index
|
||||
* \param v3 Third vertex index
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int v1,v2,v3 ; /**< Triangle vertices */
|
||||
} Triangle ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/** Marching Cubes algorithm wrapper */
|
||||
/** \class MarchingCubes
|
||||
* \brief Marching Cubes algorithm.
|
||||
*/
|
||||
class MarchingCubes
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// Constructors
|
||||
public :
|
||||
/**
|
||||
* Main and default constructor
|
||||
* \brief constructor
|
||||
*/
|
||||
MarchingCubes () ;
|
||||
/** Destructor */
|
||||
~MarchingCubes() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
/** accesses the number of vertices of the generated mesh */
|
||||
inline const int nverts() const { return _nverts ; }
|
||||
/** accesses the number of triangles of the generated mesh */
|
||||
inline const int ntrigs() const { return _ntrigs ; }
|
||||
/** accesses a specific vertex of the generated mesh */
|
||||
inline Point * vert( const int i ) const { if( i < 0 || i >= _nverts ) return ( Point *)NULL ; return _vertices + i ; }
|
||||
/** accesses a specific triangle of the generated mesh */
|
||||
inline Triangle * trig( const int i ) const { if( i < 0 || i >= _ntrigs ) return (Triangle*)NULL ; return _triangles + i ; }
|
||||
|
||||
/** accesses the vertex buffer of the generated mesh */
|
||||
inline Point *vertices () { return _vertices ; }
|
||||
/** accesses the triangle buffer of the generated mesh */
|
||||
inline Triangle *triangles() { return _triangles ; }
|
||||
|
||||
/**
|
||||
* selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes
|
||||
* \param originalMC true for the original Marching Cubes
|
||||
*/
|
||||
inline void set_method ( const bool originalMC = false ) { _originalMC = originalMC ; }
|
||||
|
||||
// Data initialization
|
||||
/** inits all structures (must set sizes before call) : the temporary structures and the mesh buffers */
|
||||
void init_all () ;
|
||||
/** clears temporary structures : the grid and the main */
|
||||
void clean_temps() ;
|
||||
/** clears all structures : the temporary structures and the mesh buffers */
|
||||
void clean_all () ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exportation
|
||||
public :
|
||||
/**
|
||||
* OFF exportation of the generated mesh
|
||||
* \param fn name of the IV file to create
|
||||
*/
|
||||
void writeOFF( const char *fn ) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Algorithm
|
||||
public :
|
||||
/** retrieves the isovalues at the cube vertices */
|
||||
real *cube () { return _cube ; }
|
||||
/** retrieves the geometry of the cube */
|
||||
Point *space () { return _space; }
|
||||
/** retrieves the indexes of the cube */
|
||||
Key *indexes() { return _indexes; }
|
||||
/** retrieves the data accessor */
|
||||
data_access *&dat_access() { return _dat_access ; }
|
||||
/**
|
||||
* Main algorithm
|
||||
* \param iso isovalue
|
||||
*/
|
||||
bool tesselate_cube( real iso ) ;
|
||||
|
||||
protected :
|
||||
/** tesselates one cube */
|
||||
bool process_cube () ;
|
||||
/** tests if the components of the tesselation of the cube should be connected by the interior of an ambiguous face */
|
||||
bool test_face ( schar face ) ;
|
||||
/** tests if the components of the tesselation of the cube should be connected through the interior of the cube */
|
||||
bool test_interior( schar s ) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
protected :
|
||||
/** computes almost all the vertices of the mesh by interpolation along the cubes edges */
|
||||
bool compute_intersection_points() ;
|
||||
|
||||
/**
|
||||
* routine to add a triangle to the mesh
|
||||
* \param trig the code for the triangle as a sequence of edges index
|
||||
* \param n the number of triangles to produce
|
||||
* \param v12 the index of the interior vertex to use, if necessary
|
||||
*/
|
||||
void add_triangle ( const char* trig, char n, int v12 = -1 ) ;
|
||||
|
||||
/** tests and eventually doubles the vertex buffer capacity for a new vertex insertion */
|
||||
void test_vertex_addition() ;
|
||||
/** adds a vertex on edge cube[i] cube[j] */
|
||||
bool add_vertex( char i, char j ) ;
|
||||
/** gets the vertex of edge cube[i] cube[j] (no check) */
|
||||
int get_vertex( char i, char j ) { std::map< std::pair< Key,Key >, int >::const_iterator it = _stored_vertices.find( std::make_pair( _indexes[i],_indexes[j] ) ) ; if( it == _stored_vertices.end() ) return -1 ; else return it->second ; }
|
||||
/** adds a vertex inside the current cube */
|
||||
int add_c_vertex() ;
|
||||
|
||||
/** prints cube for debug */
|
||||
void print_cube() ;
|
||||
|
||||
public:
|
||||
/** draw the surface using openGL */
|
||||
void draw_surf() { Triangle *ptr = _triangles ; for( int i = 0 ; i < _ntrigs ; ++i, ++ptr ) { _vertices[ptr->v1].draw() ; _vertices[ptr->v2].draw() ; _vertices[ptr->v3].draw() ; } }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
protected :
|
||||
bool _originalMC ; /**< selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes */
|
||||
|
||||
int _nverts ; /**< number of allocated vertices in the vertex buffer */
|
||||
int _ntrigs ; /**< number of allocated triangles in the triangle buffer */
|
||||
int _Nverts ; /**< size of the vertex buffer */
|
||||
int _Ntrigs ; /**< size of the triangle buffer */
|
||||
Point *_vertices ; /**< vertex buffer */
|
||||
Triangle *_triangles ; /**< triangle buffer */
|
||||
|
||||
std::map< std::pair< Key,Key >, int > _stored_vertices ;
|
||||
|
||||
real _cube[8] ; /**< values of the implicit function on the active cube */
|
||||
Point _space[8] ; /**< coordinates of the active cube */
|
||||
Key _indexes[8] ; /**< indiexs of the active cube */
|
||||
uchar _lut_entry ; /**< cube sign representation in [0..255] */
|
||||
uchar _case ; /**< case of the active cube in [0..15] */
|
||||
uchar _config ; /**< configuration of the active cube */
|
||||
uchar _subconfig ; /**< subconfiguration of the active cube */
|
||||
data_access *_dat_access ; /**< data accessor */
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
|
||||
Statistical optimization of octree searches
|
||||
Fast generation of pointerless octree duals
|
||||
---------------------------------------------------
|
||||
Rener Castro, Thomas Lewiner, H<>lio Lopes, Geovan Tavares, Alex Bordignon
|
||||
Thomas Lewiner, Vin<69>cius Mello, Adelailson Peixoto, Sin<69>sio Pesco, H<>lio Lopes
|
||||
|
||||
|
||||
http://www.matmidia.mat.puc-rio.br/tomlew/publication_page.php?pubkey=octree_cgf
|
||||
http://www.matmidia.mat.puc-rio.br/tomlew/publication_page.php?pubkey=fastdualoctree_sgp
|
||||
|
||||
1. Disclaimer
|
||||
2. Available code compared to the papers
|
||||
3. Octrees implementations
|
||||
4. Morton codes
|
||||
5. Data
|
||||
6. Hash table
|
||||
7. Requirements
|
||||
|
||||
|
||||
Disclaimer
|
||||
--------------
|
||||
This code is implements fast searches and the dual generation of static
|
||||
or dynamic pointer-based or pointerless octrees. It is provided "as is"
|
||||
and can be used freely. We just ask the users who would use this code to
|
||||
mention in their academic paper, patent or software documentation the
|
||||
original articles:
|
||||
|
||||
@article{octree_cgf,
|
||||
author = {Rener Castro and Thomas Lewiner and H<>lio Lopes and Geovan Tavares and Alex Bordignon},
|
||||
title = {Statistical optimization of octree searches},
|
||||
year = {2008},
|
||||
month = {march},
|
||||
journal = {Computer Graphics Forum},
|
||||
volume = {27},
|
||||
number = {6},
|
||||
pages = {1557--1566},
|
||||
publisher = {Eurographics},
|
||||
doi = {10.1111/j.1467-8659.2007.01104.x},
|
||||
url = {\url{http://www.matmidia.mat.puc-rio.br/tomlew/pdfs/octree_cgf.pdf}}
|
||||
}
|
||||
|
||||
@article{fastdualoctree_sgp,
|
||||
author = {Thomas Lewiner and Vin<69>cius Mello and Adelailson Peixoto and Sin<69>sio Pesco and H<>lio Lopes},
|
||||
title = {Fast Generation of Pointerless Octree Duals},
|
||||
year = {2010},
|
||||
month = {july},
|
||||
journal = {Symposium on Geometry Processing 2010},
|
||||
booktitle = {Computer Graphics Forum},
|
||||
volume = {29},
|
||||
number = {5},
|
||||
pages = {1661--1669},
|
||||
publisher = {Wiley},
|
||||
address = {Lyon, France},
|
||||
url = {\url{http://www.matmidia.mat.puc-rio.br/tomlew/pdfs/fastdualoctree_sgp.pdf}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
If you have any comment, correction, question, please feel free to
|
||||
contact me at : lewiner@gmail.com .
|
||||
Thank to David Coeurjolly for the code porting to UNIX.
|
||||
|
||||
|
||||
|
||||
|
||||
Available code compared to the paper
|
||||
----------------------------------------------
|
||||
The code contains simple implementations used to generate the result of
|
||||
our papers. We stripped down the time measurements (which are platform
|
||||
specific) and the robust dual marching cubes
|
||||
(http://www.matmidia.mat.puc-rio.br/tomlew/publication_page.php?pubkey=adaptive_implicit_sibgrapi)
|
||||
code.
|
||||
|
||||
|
||||
|
||||
Octrees implementations
|
||||
------------------------------
|
||||
The code contains implementations of a pointer-based octree
|
||||
("ptr_octree.*" files), pointerless octrees with recursive dual
|
||||
generation ("hash_octree.*"), pointerless octrees with optimized dual
|
||||
generation for the static strategy representing all the nodes
|
||||
("opt_octree.*") or only the leaves ("leaf_octree.*"), and the dynamic
|
||||
strategy ("mem_octree.*"). The octree is chosen at compilation time
|
||||
through the OCTREE_SWITCH macro.
|
||||
|
||||
|
||||
Morton codes
|
||||
-----------------
|
||||
The Morton code operations in dilated integers are all grouped in the
|
||||
"morton.*" files.
|
||||
|
||||
|
||||
Data
|
||||
------
|
||||
The data (implicit function or isogrid) is accessed through the
|
||||
data_access class. The isogrid must be in "iso" format, i.e. a binary
|
||||
file with 32-bits integers nx, ny and nz for the size of the grid,
|
||||
32-bits floats xmin, xmax, ymin<69> for the geometry of the cube, followed
|
||||
by nx.ny.nz 32-bits floats for the data.
|
||||
|
||||
|
||||
Hash table
|
||||
-------------
|
||||
Finally, we made a very simple naive and simple implementations for the
|
||||
hashtable, in open ("hash_ptr.h") or close ("has_noptr.h") modes. The
|
||||
parameters of the hash function are chosen at compilation time through
|
||||
macros defined in the "hash.h" file.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
The graphical interfaces require the openGL libraries with the GLU, glut
|
||||
and glui extension, available at http://glui.sourceforge.net/ .
|
||||
|
||||
We use Juha Nieminen, Joel Yliluoma's function parser for the implicit
|
||||
function, and our Marching Cube's implementation
|
||||
(http://www.matmidia.mat.puc-rio.br/tomlew/publication_page.php?pubkey=marching_cubes_jgt).
|
||||
|
||||
|
||||
Thank you for your interest, and have fun!
|
||||
http://www.matmidia.mat.puc-rio.br/tomlew/
|
||||
@ -0,0 +1,256 @@
|
||||
/**
|
||||
* \file cube.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* \brief Simple cube class
|
||||
*
|
||||
* Simple cube class
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "point.h"
|
||||
|
||||
typedef uchar Level ;
|
||||
extern Level L_INV ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// Simple cube class
|
||||
class Cube : public Point
|
||||
{
|
||||
// Elements
|
||||
protected :
|
||||
Level _lv ; ///< cube level (from 0 on): cube corners have coordinates c(xyz) (+/-) (1/2^(lv+1))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor
|
||||
Cube( const real &cx_ = R_INV, const real &cy_ = R_INV, const real &cz_ = R_INV, Level lv_ = L_INV )
|
||||
: Point(cx_,cy_,cz_), _lv(lv_) {}
|
||||
|
||||
/// Default constructor
|
||||
Cube( const Point& c_, Level lv_ = L_INV )
|
||||
: Point(c_), _lv(lv_) {}
|
||||
|
||||
/// Default constructor
|
||||
Cube( const Cube& c_ )
|
||||
: Point((const Point&)c_), _lv(c_._lv) {}
|
||||
|
||||
/// Destructor
|
||||
~Cube() {}
|
||||
|
||||
/// Assignment operator
|
||||
Cube &operator= ( const Cube &c )
|
||||
{ Point::operator=(c) ; _lv = c._lv ; return *this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public:
|
||||
/// const accessor for point center: x coordinate
|
||||
real cx() const { return Point::x() ; }
|
||||
/// accessor for point center: x coordinate
|
||||
real &cx() { return Point::x() ; }
|
||||
|
||||
/// const accessor for point center: y coordinate
|
||||
real cy() const { return Point::y() ; }
|
||||
/// accessor for point center: y coordinate
|
||||
real &cy() { return Point::y() ; }
|
||||
|
||||
/// const accessor for point center: z coordinate
|
||||
real cz() const { return Point::z() ; }
|
||||
/// accessor for point center: z coordinate
|
||||
real &cz() { return Point::z() ; }
|
||||
|
||||
/// const accessor for a coordinate
|
||||
real coord( Axis a ) const { return Point::operator[](a) ; }
|
||||
/// accessor for a coordinate
|
||||
real &coord( Axis a ) { return Point::operator[](a) ; }
|
||||
|
||||
|
||||
/// const accessor for the cube half size
|
||||
real sz() const { return (real)1.0 / (2<<_lv) ; }
|
||||
/// const accessor for cube level
|
||||
Level lv() const { return _lv ; }
|
||||
/// accessor for cube level
|
||||
Level &lv() { return _lv ; }
|
||||
|
||||
/// const accessor for cube center: min x coordinate
|
||||
real xmin() const { return cx() - sz() ; }
|
||||
/// const accessor for cube center: max x coordinate
|
||||
real xmax() const { return cx() + sz() ; }
|
||||
|
||||
/// const accessor for cube center: min y coordinate
|
||||
real ymin() const { return cy() - sz() ; }
|
||||
/// const accessor for cube center: max y coordinate
|
||||
real ymax() const { return cy() + sz() ; }
|
||||
|
||||
/// const accessor for cube center: min z coordinate
|
||||
real zmin() const { return cz() - sz() ; }
|
||||
/// const accessor for cube center: max z coordinate
|
||||
real zmax() const { return cz() + sz() ; }
|
||||
|
||||
/// const accessor for cube center: min coordinate
|
||||
real coordmin( Axis a ) const { return coord(a) - this->sz() ; }
|
||||
/// const accessor for cube center: max coordinate
|
||||
real coordmax( Axis a ) const { return coord(a) + this->sz() ; }
|
||||
|
||||
//------------------------------------------------
|
||||
// Test
|
||||
public :
|
||||
/// conained
|
||||
bool contains( const real &x_, const real &y_, const real &z_ ) const
|
||||
{
|
||||
real sz_ = sz() ;
|
||||
return
|
||||
( fabs(x_-cx()) <= sz_ ) &&
|
||||
( fabs(y_-cy()) <= sz_ ) &&
|
||||
( fabs(z_-cz()) <= sz_ ) ;
|
||||
}
|
||||
|
||||
/// conained
|
||||
bool contains( const Point &p ) const { return contains( p.x(), p.y(), p.z() ) ; }
|
||||
|
||||
/// epsilon-conained
|
||||
bool contains( const real &x_, const real &y_, const real &z_, const real &epsilon ) const
|
||||
{
|
||||
real sz_ = sz() + epsilon ;
|
||||
return
|
||||
( fabs(x_-cx()) <= sz_ ) &&
|
||||
( fabs(y_-cy()) <= sz_ ) &&
|
||||
( fabs(z_-cz()) <= sz_ ) ;
|
||||
}
|
||||
|
||||
/// epsilon-conained
|
||||
bool contains( const Point &p, const real &epsilon ) const { return contains( p.x(), p.y(), p.z(), epsilon ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Drawing
|
||||
public:
|
||||
/// Draws the cube center with opengl
|
||||
void draw_center () const { ::glVertex3f( (float)x(), (float)y(), (float)z() ) ; }
|
||||
|
||||
/// Draws the cube corners with opengl
|
||||
void draw_corners( real fact = 0.9 ) const
|
||||
{
|
||||
const float ix = (const float) x() ;
|
||||
const float iy = (const float) y() ;
|
||||
const float iz = (const float) z() ;
|
||||
const float is = (const float) (fact*sz()) ;
|
||||
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
}
|
||||
|
||||
/// Draws the cube wire with opengl
|
||||
void draw_wire ( real fact = 0.9 ) const
|
||||
{
|
||||
const float ix = (const float) x() ;
|
||||
const float iy = (const float) y() ;
|
||||
const float iz = (const float) z() ;
|
||||
const float is = (const float) (fact*sz()) ;
|
||||
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
|
||||
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
|
||||
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Draws the cube wire with opengl
|
||||
void draw_fill ( real fact = 0.9 ) const
|
||||
{
|
||||
const float ix = (const float) x() ;
|
||||
const float iy = (const float) y() ;
|
||||
const float iz = (const float) z() ;
|
||||
const float is = (const float) (fact*sz()) ;
|
||||
|
||||
::glNormal3f(0,0,-1);
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
|
||||
::glNormal3f(0,0,1);
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
|
||||
::glNormal3f(-1,0,0);
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
|
||||
::glNormal3f(1,0,0);
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
|
||||
::glNormal3f(0,-1,0);
|
||||
::glVertex3f( ix-is, iy-is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy-is, iz-is ) ;
|
||||
|
||||
::glNormal3f(0,1,0);
|
||||
::glVertex3f( ix-is, iy+is, iz-is ) ;
|
||||
::glVertex3f( ix-is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz+is ) ;
|
||||
::glVertex3f( ix+is, iy+is, iz-is ) ;
|
||||
}
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
// Invalid cube
|
||||
extern Cube C_INV ;
|
||||
|
||||
|
||||
@ -0,0 +1,266 @@
|
||||
/**
|
||||
* @file data_access.cpp
|
||||
* \author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* \author Math Dept, PUC-Rio
|
||||
* \author Matmidia Labs
|
||||
* \date 14/02/2006
|
||||
*
|
||||
* @brief data accesss
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma implementation
|
||||
#endif // WIN32
|
||||
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//_____________________________________________________________________________
|
||||
// data_func
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// crossing data access: parser
|
||||
void data_func::parse()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
if( _formula.empty() )
|
||||
return ;
|
||||
std::string vars("x,y,z") ;
|
||||
int i = _parser.Parse( _formula, vars ) ;
|
||||
if( _parser.GetParseErrorType() != FunctionParser::FP_NO_ERROR )
|
||||
printf( "%s\n%s\n% *d\n", _parser.ErrorMsg(), _formula.c_str(), i, 1 ) ;
|
||||
else
|
||||
_parser.Optimize() ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// crossing data access
|
||||
bool data_func::need_refine( const Cube &c )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
if( _parser.GetParseErrorType() != FunctionParser::FP_NO_ERROR ) return false ;
|
||||
int l = c.lv() ;
|
||||
if( l < 2 ) return true ;
|
||||
if( l >= _max_level ) return false ;
|
||||
|
||||
real cx = c.cx() ;
|
||||
real cy = c.cy() ;
|
||||
real cz = c.cz() ;
|
||||
_v[X] = cx ;
|
||||
_v[Y] = cy ;
|
||||
_v[Z] = cz ;
|
||||
|
||||
real ref_val = _parser.Eval(_v) - _iso_val ;
|
||||
if( fabs(ref_val) < R_EPSILON ) return true ;
|
||||
|
||||
real sz = c.sz() ;
|
||||
for( _v[X] = cx-sz ; _v[X] <= cx+sz ; _v[X] += sz )
|
||||
{
|
||||
for( _v[Y] = cy-sz ; _v[Y] <= cy+sz ; _v[Y] += sz )
|
||||
{
|
||||
for( _v[Z] = cz-sz ; _v[Z] <= cz+sz ; _v[Z] += sz )
|
||||
{
|
||||
real val = _parser.Eval(_v) - _iso_val ;
|
||||
if( ref_val * val < 0 ) return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#ifndef BISSEC_ITER
|
||||
#define BISSEC_ITER 3
|
||||
#endif // BISSEC_ITER
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// interpolation function
|
||||
void data_func::interpolate( real ci, real cj, const Point &pi, const Point &pj, Point &p )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
real u ;
|
||||
Point qi = pi ;
|
||||
Point qj = pj ;
|
||||
for( int i = 0 ; i < BISSEC_ITER ; ++i )
|
||||
{
|
||||
u = ( ci ) / ( ci - cj ) ;
|
||||
p = ((1-u)*qi) + (u*qj) ;
|
||||
|
||||
real c = value_at(p) ;
|
||||
if( c*ci < 0 )
|
||||
{
|
||||
qj = p ;
|
||||
cj = c ;
|
||||
}
|
||||
else if( c*cj < 0 )
|
||||
{
|
||||
qi = p ;
|
||||
ci = c ;
|
||||
}
|
||||
else break ;
|
||||
}
|
||||
u = ( ci ) / ( ci - cj ) ;
|
||||
p = ((1-u)*qi) + (u*qj) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//_____________________________________________________________________________
|
||||
// data_file
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// data data access: load file
|
||||
bool data_file::load_data( const char *fn )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
errno = 0;
|
||||
gzFile isofile = gzopen( fn, "rb" ) ;
|
||||
if( !isofile )
|
||||
{
|
||||
printf( "data_file::load_data couldn't open file %s: %s\n", fn, strerror (errno));
|
||||
return false ;
|
||||
}
|
||||
|
||||
// read size
|
||||
unsigned char buf[sizeof(float)] ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
_size_x = * (int*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
_size_y = * (int*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
_size_z = * (int*)buf ;
|
||||
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float xmin = * (float*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float xmax = * (float*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float ymin = * (float*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float ymax = * (float*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float zmin = * (float*)buf ;
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float zmax = * (float*)buf ;
|
||||
|
||||
// allocate data
|
||||
delete [] _data ;
|
||||
_size_yz = _size_z * _size_y ;
|
||||
uint total_size = _size_x * _size_yz ;
|
||||
if( total_size == 0 ) return false ;
|
||||
|
||||
// cube fitting
|
||||
_max_size = _size_x ;
|
||||
if( _max_size < _size_y ) _max_size = _size_y ;
|
||||
if( _max_size < _size_z ) _max_size = _size_z ;
|
||||
Level p = (Level)floor( log(_max_size)/log(2) ) ;
|
||||
if( _max_size != (1<<p) ) _max_size = 1 << (p+1) ;
|
||||
|
||||
_data = new float[ total_size ] ;
|
||||
if( _data == (float*)NULL ) return false ;
|
||||
|
||||
float min_field = FLT_MAX ;
|
||||
float max_field = -FLT_MAX ;
|
||||
float *data_ptr = _data ;
|
||||
for( uint i = 0 ; i < total_size ; ++i, ++data_ptr )
|
||||
{
|
||||
if( gzread( isofile, buf, sizeof(float) ) < 1 ) return false ;
|
||||
float v = * (float*) buf ;
|
||||
*data_ptr = v ;
|
||||
if( v < min_field ) min_field = v ;
|
||||
if( v > max_field ) max_field = v ;
|
||||
}
|
||||
|
||||
gzclose( isofile ) ;
|
||||
|
||||
printf( "data %s: %dx%dx%d, field originally in [ %f , %f ]\n", fn, (int)_size_x, (int)_size_y, (int)_size_z, min_field, max_field ) ;
|
||||
|
||||
// rescale data in [-1.1]
|
||||
float v_scale = 2.0 / (max_field - min_field) ;
|
||||
data_ptr = _data ;
|
||||
for( uint i = 0 ; i < total_size ; ++i, ++data_ptr )
|
||||
{
|
||||
*data_ptr = v_scale * ( (*data_ptr) - min_field ) - 1.0 ;
|
||||
}
|
||||
|
||||
// cube scaling
|
||||
_sx = (xmax - xmin)/_size_x ;
|
||||
_sy = (ymax - ymin)/_size_y ;
|
||||
_sz = (zmax - zmin)/_size_z ;
|
||||
float s = _sx ;
|
||||
if( s < _sy ) s = _sy ;
|
||||
if( s < _sz ) s = _sz ;
|
||||
_sx /= s ;
|
||||
_sy /= s ;
|
||||
_sz /= s ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// data data access
|
||||
bool data_file::need_refine( const Cube &c )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
int l = c.lv() ;
|
||||
if( l < 2 ) return true ;
|
||||
if( l >= _max_level ) return false ;
|
||||
|
||||
// ajustar se o dado nao for cubico!
|
||||
real sz = c.sz() ;
|
||||
uint i = floor( (c.cx()-sz) * _max_size ) ;
|
||||
uint iM = ceil ( (c.cx()+sz) * _max_size ) ;
|
||||
uint j = floor( (c.cy()-sz) * _max_size ) ;
|
||||
uint jM = ceil ( (c.cy()+sz) * _max_size ) ;
|
||||
uint k = floor( (c.cz()-sz) * _max_size ) ;
|
||||
uint kM = ceil ( (c.cz()+sz) * _max_size ) ;
|
||||
|
||||
if( iM >= _size_x ) iM = _size_x-1 ;
|
||||
if( jM >= _size_y ) jM = _size_y-1 ;
|
||||
if( kM >= _size_z ) kM = _size_z-1 ;
|
||||
|
||||
float iso_min = get_data(iM,jM,kM) ;
|
||||
float iso_max = iso_min ;
|
||||
for( ; i <= iM ; ++i )
|
||||
{
|
||||
for( ; j <= jM ; ++j )
|
||||
{
|
||||
for( ; k <= kM ; ++k )
|
||||
{
|
||||
float iso = get_data(i,j,k) ;
|
||||
if( iso_min > iso ) iso_min = iso ;
|
||||
if( iso_max < iso ) iso_max = iso ;
|
||||
|
||||
if( iso_min*iso_max < 0 ) return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,192 @@
|
||||
/**
|
||||
* @file data_access.h
|
||||
* \author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* \author Math Dept, PUC-Rio
|
||||
* \author Matmidia Labs
|
||||
* \date 14/02/2006
|
||||
*
|
||||
* @brief data accesss
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include "cube.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// data access abstract class
|
||||
class data_access
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
public :
|
||||
Level _max_level; ///< maximal level of a cell
|
||||
real _iso_val; ///< iso value
|
||||
float _sx ; ///< grid x proportion
|
||||
float _sy ; ///< grid y proportion
|
||||
float _sz ; ///< grid z proportion
|
||||
|
||||
|
||||
public :
|
||||
/// constructor
|
||||
data_access( Level max_level_ = 4, real iso_val_ = 0.0 ) : _max_level(max_level_), _iso_val(iso_val_), _sx(1.0f), _sy(1.0f), _sz(1.0f) {}
|
||||
/// destructor
|
||||
virtual ~data_access() {}
|
||||
/// test function
|
||||
virtual bool need_refine( const Cube &c ) = 0 ;
|
||||
/// data function
|
||||
virtual real value_at ( const Cube &c ) = 0 ;
|
||||
/// interpolation function
|
||||
virtual void interpolate( real ci, real cj, const Point &pi, const Point &pj, Point &p )
|
||||
{
|
||||
real u = ( ci ) / ( ci - cj ) ;
|
||||
p = ((1-u)*pi) + (u*pj) ;
|
||||
}
|
||||
} ;
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// may be overridden by the preprocessor
|
||||
#ifndef RAND_THRES
|
||||
# define RAND_THRES 0.2
|
||||
#endif // RAND_THRES
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// basic data access
|
||||
class data_rand : public data_access
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
public:
|
||||
/// test function
|
||||
bool need_refine( const Cube &c )
|
||||
{
|
||||
int l = c.lv() ;
|
||||
if( l < 2 ) return true ;
|
||||
if( l >= _max_level ) return false ;
|
||||
return value_at(c) > RAND_THRES ;
|
||||
}
|
||||
|
||||
/// data function
|
||||
real value_at( const Cube &c ) { return ( (real)rand() ) / ( RAND_MAX >> 1 ) - 1.0 ; }
|
||||
|
||||
/// interpolation function
|
||||
void interpolate( real ci, real cj, const Point &pi, const Point &pj, Point &p )
|
||||
{
|
||||
real u = ( (real)rand() ) / ( RAND_MAX ) ;
|
||||
p = ((1-u)*pi) + (u*pj) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Basics
|
||||
public:
|
||||
/// default constructor
|
||||
data_rand( Level max_level_ ) : data_access(max_level_) {}
|
||||
/// destructor
|
||||
virtual ~data_rand() {}
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
#include "fptypes.h"
|
||||
#include "fparser.h"
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// function crossing data access
|
||||
class data_func : public data_access
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
public:
|
||||
/// implicit function
|
||||
std::string _formula ;
|
||||
|
||||
protected:
|
||||
double _v[3] ;
|
||||
FunctionParser _parser ;
|
||||
|
||||
protected:
|
||||
void parse() ;
|
||||
|
||||
public:
|
||||
/// test function
|
||||
bool need_refine( const Cube &c ) ;
|
||||
|
||||
/// data function
|
||||
real value_at( const Cube &c )
|
||||
{
|
||||
if( _parser.GetParseErrorType() != FunctionParser::FP_NO_ERROR ) return false ;
|
||||
_v[X] = c.cx() ;
|
||||
_v[Y] = c.cy() ;
|
||||
_v[Z] = c.cz() ;
|
||||
real v = _parser.Eval(_v) - _iso_val ;
|
||||
if( _parser.EvalError() ) return -1.0 ;
|
||||
return v ;
|
||||
}
|
||||
|
||||
/// interpolation function
|
||||
void interpolate( real ci, real cj, const Point &pi, const Point &pj, Point &p ) ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Basics
|
||||
public:
|
||||
/// default constructor
|
||||
data_func( Level max_level_, real iso_val_, const std::string &formula_ ) : data_access(max_level_,iso_val_), _formula(formula_) { parse() ; }
|
||||
/// destructor
|
||||
virtual ~data_func() {}
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// iso file data access
|
||||
class data_file : public data_access
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
public:
|
||||
uint _size_x ; ///< width of the grid
|
||||
uint _size_y ; ///< depth of the grid
|
||||
uint _size_z ; ///< height of the grid
|
||||
|
||||
protected:
|
||||
float *_data ; /**< implicit function values sampled on the grid */
|
||||
uint _size_yz ; /**< k skip size */
|
||||
uint _max_size ; /**< bigger side to fit into the cube */
|
||||
|
||||
|
||||
public:
|
||||
bool load_data ( const char *fn ) ;
|
||||
bool has_data ( uint i, uint j, uint k ) { return (i < _size_x) && (j < _size_y) && (k < _size_z) ; }
|
||||
float get_data ( uint i, uint j, uint k ) { return _data[ k + j*_size_z + i*_size_yz] - _iso_val ; }
|
||||
|
||||
/// test function
|
||||
bool need_refine( const Cube &c ) ;
|
||||
/// data function
|
||||
real value_at( const Cube &c )
|
||||
{
|
||||
uint i = (uint)(c.cx()*_max_size) ;
|
||||
uint j = (uint)(c.cy()*_max_size) ;
|
||||
uint k = (uint)(c.cz()*_max_size) ;
|
||||
if( has_data(i,j,k) ) return (real)get_data(i,j,k) ;
|
||||
return -1.0 ;
|
||||
}
|
||||
// linear interpolation: no specification
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Basics
|
||||
public:
|
||||
/// default constructor
|
||||
data_file( Level max_level_, real iso_val_, const char *fn ) : data_access(max_level_,iso_val_), _data((float*)NULL) { load_data( fn ) ; }
|
||||
/// destructor
|
||||
virtual ~data_file() {}
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
@ -0,0 +1,292 @@
|
||||
unsigned nameLength = 0;
|
||||
const unsigned maximumNameLength = 0x80000000U-8;
|
||||
/*
|
||||
Due to the manner the identifier lengths are returned from
|
||||
the readOpcode() function, the maximum supported length for
|
||||
identifiers is 0x7FFFFFFF bytes. We minus 8 here to add some
|
||||
buffer, because of the multibyteness of UTF-8.
|
||||
Function names are limited to 0xFFFF bytes instead, but because
|
||||
function names that long just are not defined, the point is moot.
|
||||
*/
|
||||
const unsigned char* const uptr = (const unsigned char*) input;
|
||||
typedef signed char schar;
|
||||
while(likely(nameLength < maximumNameLength))
|
||||
{
|
||||
unsigned char byte = uptr[nameLength+0];
|
||||
/* Handle the common case of A-Za-z first */
|
||||
if(byte >= 0x40)
|
||||
{
|
||||
if(byte < 0x80) // 0x40..0x7F - most common case
|
||||
{
|
||||
// Valid characters in 40..7F: A-Za-z_
|
||||
// Valid bitmask for 40..5F: 01111111111111111111111111100001
|
||||
// Valid bitmask for 60..7F: 01111111111111111111111111100000
|
||||
if(sizeof(unsigned long) == 8)
|
||||
{
|
||||
const unsigned n = sizeof(unsigned long)*8-32;
|
||||
// ^ avoids compiler warning when not 64-bit
|
||||
unsigned long masklow6bits = 1UL << (byte & 0x3F);
|
||||
if(masklow6bits & ~((1UL << 0) | (0x0FUL << (0x1B ))
|
||||
| (1UL << n) | (0x1FUL << (0x1B+n))))
|
||||
{ ++nameLength; continue; }
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned masklow5bits = 1 << (byte & 0x1F);
|
||||
if((masklow5bits & ~(1 | (0x1F << 0x1B))) || byte == '_')
|
||||
{ ++nameLength; continue; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(byte < 0xF0)
|
||||
{
|
||||
if(byte < 0xE0)
|
||||
{
|
||||
if(byte < 0xC2) break; // 0x80..0xC1
|
||||
if(byte == 0xC2 && uptr[nameLength+1]==0xA0) break; // skip nbsp
|
||||
// C2-DF - next common case when >= 0x40
|
||||
// Valid sequence: C2-DF 80-BF
|
||||
if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
|
||||
nameLength += 2;
|
||||
continue;
|
||||
}
|
||||
if(byte == 0xE0) // E0
|
||||
{
|
||||
// Valid sequence: E0 A0-BF 80-BF
|
||||
if((unsigned char)(uptr[nameLength+1] - 0xA0) > (0xBF-0xA0)) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(byte == 0xED) break; // ED is invalid
|
||||
// Valid sequence: E1-EC 80-BF 80-BF
|
||||
// And: EE-EF 80-BF 80-BF
|
||||
if(byte == 0xE2)
|
||||
{
|
||||
// break on various space characters
|
||||
if(uptr[nameLength+1] == 0x80
|
||||
&& (schar(uptr[nameLength+2]) <= schar(0x8B)
|
||||
|| (uptr[nameLength+2] == 0xAF))) break;
|
||||
if(uptr[nameLength+1] == 0x81
|
||||
&& uptr[nameLength+2] == 0x9F) break;
|
||||
} else
|
||||
if(byte == 0xE3 && uptr[nameLength+1] == 0x80
|
||||
&& uptr[nameLength+2] == 0x80) break; // this too
|
||||
|
||||
if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
|
||||
}
|
||||
if(schar(uptr[nameLength+2]) > schar(0xBF)) break;
|
||||
nameLength += 3;
|
||||
continue;
|
||||
}
|
||||
if(byte == 0xF0) // F0
|
||||
{
|
||||
// Valid sequence: F0 90-BF 80-BF 80-BF
|
||||
if((unsigned char)(uptr[nameLength+1] - 0x90) > (0xBF-0x90)) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(byte > 0xF4) break; // F5-FF are invalid
|
||||
if(byte == 0xF4) // F4
|
||||
{
|
||||
// Valid sequence: F4 80-8F
|
||||
if(schar(uptr[nameLength+1]) > schar(0x8F)) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// F1-F3
|
||||
// Valid sequence: F1-F3 80-BF 80-BF 80-BF
|
||||
if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
|
||||
}
|
||||
}
|
||||
if(schar(uptr[nameLength+2]) > schar(0xBF)) break;
|
||||
if(schar(uptr[nameLength+3]) > schar(0xBF)) break;
|
||||
nameLength += 4;
|
||||
continue;
|
||||
}
|
||||
if(nameLength > 0)
|
||||
{
|
||||
if(sizeof(unsigned long) == 8)
|
||||
{
|
||||
// Valid bitmask for 00..1F: 00000000000000000000000000000000
|
||||
// Valid bitmask for 20..3F: 00000000000000001111111111000000
|
||||
const unsigned n = sizeof(unsigned long)*8-32;
|
||||
// ^ avoids compiler warning when not 64-bit
|
||||
unsigned long masklow6bits = 1UL << byte;
|
||||
if(masklow6bits & (((1UL << 10)-1UL) << (16+n)))
|
||||
{ ++nameLength; continue; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if(byte >= '0' && byte <= '9')
|
||||
{ ++nameLength; continue; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* This function generated with make_function_name_parser.cc */
|
||||
switch(nameLength)
|
||||
{
|
||||
case 2:
|
||||
/* prefix */if('i' == uptr[0]
|
||||
&& 'f' == uptr[1]) return Functions[cIf].enabled() ? (cIf<<16) | 0x80000002U : 2;
|
||||
return 2;
|
||||
case 3:
|
||||
/* prefix */switch(uptr[0]) {
|
||||
case 'a':
|
||||
/* prefix a */if('b' == uptr[1]
|
||||
&& 's' == uptr[2]) return Functions[cAbs].enabled() ? (cAbs<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 'c':
|
||||
/* prefix c */switch(uptr[1]) {
|
||||
case 'o':
|
||||
/* prefix co */switch(uptr[2]) {
|
||||
case 's':
|
||||
/* prefix cos */return Functions[cCos].enabled() ? (cCos<<16) | 0x80000003U : 3;
|
||||
case 't':
|
||||
/* prefix cot */return Functions[cCot].enabled() ? (cCot<<16) | 0x80000003U : 3;
|
||||
default: return 3; }
|
||||
case 's':
|
||||
/* prefix cs */if('c' == uptr[2]) return Functions[cCsc].enabled() ? (cCsc<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
default: return 3; }
|
||||
case 'e':
|
||||
/* prefix e */if('x' == uptr[1]
|
||||
&& 'p' == uptr[2]) return Functions[cExp].enabled() ? (cExp<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 'i':
|
||||
/* prefix i */if('n' == uptr[1]
|
||||
&& 't' == uptr[2]) return Functions[cInt].enabled() ? (cInt<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 'l':
|
||||
/* prefix l */if('o' == uptr[1]
|
||||
&& 'g' == uptr[2]) return Functions[cLog].enabled() ? (cLog<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 'm':
|
||||
/* prefix m */switch(uptr[1]) {
|
||||
case 'a':
|
||||
/* prefix ma */if('x' == uptr[2]) return Functions[cMax].enabled() ? (cMax<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 'i':
|
||||
/* prefix mi */if('n' == uptr[2]) return Functions[cMin].enabled() ? (cMin<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
default: return 3; }
|
||||
case 'p':
|
||||
/* prefix p */if('o' == uptr[1]
|
||||
&& 'w' == uptr[2]) return Functions[cPow].enabled() ? (cPow<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 's':
|
||||
/* prefix s */switch(uptr[1]) {
|
||||
case 'e':
|
||||
/* prefix se */if('c' == uptr[2]) return Functions[cSec].enabled() ? (cSec<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
case 'i':
|
||||
/* prefix si */if('n' == uptr[2]) return Functions[cSin].enabled() ? (cSin<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
default: return 3; }
|
||||
case 't':
|
||||
/* prefix t */if('a' == uptr[1]
|
||||
&& 'n' == uptr[2]) return Functions[cTan].enabled() ? (cTan<<16) | 0x80000003U : 3;
|
||||
return 3;
|
||||
default: return 3; }
|
||||
case 4:
|
||||
/* prefix */switch(uptr[0]) {
|
||||
case 'a':
|
||||
/* prefix a */switch(uptr[1]) {
|
||||
case 'c':
|
||||
/* prefix ac */if('o' == uptr[2]
|
||||
&& 's' == uptr[3]) return Functions[cAcos].enabled() ? (cAcos<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
case 's':
|
||||
/* prefix as */if('i' == uptr[2]
|
||||
&& 'n' == uptr[3]) return Functions[cAsin].enabled() ? (cAsin<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
case 't':
|
||||
/* prefix at */if('a' == uptr[2]
|
||||
&& 'n' == uptr[3]) return Functions[cAtan].enabled() ? (cAtan<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
default: return 4; }
|
||||
case 'c':
|
||||
/* prefix c */switch(uptr[1]) {
|
||||
case 'b':
|
||||
/* prefix cb */if('r' == uptr[2]
|
||||
&& 't' == uptr[3]) return Functions[cCbrt].enabled() ? (cCbrt<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
case 'e':
|
||||
/* prefix ce */if('i' == uptr[2]
|
||||
&& 'l' == uptr[3]) return Functions[cCeil].enabled() ? (cCeil<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
case 'o':
|
||||
/* prefix co */if('s' == uptr[2]
|
||||
&& 'h' == uptr[3]) return Functions[cCosh].enabled() ? (cCosh<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
default: return 4; }
|
||||
case 'e':
|
||||
/* prefix e */switch(uptr[1]) {
|
||||
case 'v':
|
||||
/* prefix ev */if('a' == uptr[2]
|
||||
&& 'l' == uptr[3]) return Functions[cEval].enabled() ? (cEval<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
case 'x':
|
||||
/* prefix ex */if('p' == uptr[2]
|
||||
&& '2' == uptr[3]) return Functions[cExp2].enabled() ? (cExp2<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
default: return 4; }
|
||||
case 'l':
|
||||
/* prefix l */{static const char tmp[3] = {'o','g','2'};
|
||||
if(std::memcmp(uptr+1, tmp, 3) == 0) return Functions[cLog2].enabled() ? (cLog2<<16) | 0x80000004U : 4;
|
||||
return 4; }
|
||||
case 's':
|
||||
/* prefix s */switch(uptr[1]) {
|
||||
case 'i':
|
||||
/* prefix si */if('n' == uptr[2]
|
||||
&& 'h' == uptr[3]) return Functions[cSinh].enabled() ? (cSinh<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
case 'q':
|
||||
/* prefix sq */if('r' == uptr[2]
|
||||
&& 't' == uptr[3]) return Functions[cSqrt].enabled() ? (cSqrt<<16) | 0x80000004U : 4;
|
||||
return 4;
|
||||
default: return 4; }
|
||||
case 't':
|
||||
/* prefix t */{static const char tmp[3] = {'a','n','h'};
|
||||
if(std::memcmp(uptr+1, tmp, 3) == 0) return Functions[cTanh].enabled() ? (cTanh<<16) | 0x80000004U : 4;
|
||||
return 4; }
|
||||
default: return 4; }
|
||||
case 5:
|
||||
/* prefix */switch(uptr[0]) {
|
||||
case 'a':
|
||||
/* prefix a */switch(uptr[1]) {
|
||||
case 'c':
|
||||
/* prefix ac */{static const char tmp[3] = {'o','s','h'};
|
||||
if(std::memcmp(uptr+2, tmp, 3) == 0) return Functions[cAcosh].enabled() ? (cAcosh<<16) | 0x80000005U : 5;
|
||||
return 5; }
|
||||
case 's':
|
||||
/* prefix as */{static const char tmp[3] = {'i','n','h'};
|
||||
if(std::memcmp(uptr+2, tmp, 3) == 0) return Functions[cAsinh].enabled() ? (cAsinh<<16) | 0x80000005U : 5;
|
||||
return 5; }
|
||||
case 't':
|
||||
/* prefix at */if('a' == uptr[2]) {
|
||||
/* prefix ata */if('n' == uptr[3]) {
|
||||
/* prefix atan */switch(uptr[4]) {
|
||||
case '2':
|
||||
/* prefix atan2 */return Functions[cAtan2].enabled() ? (cAtan2<<16) | 0x80000005U : 5;
|
||||
case 'h':
|
||||
/* prefix atanh */return Functions[cAtanh].enabled() ? (cAtanh<<16) | 0x80000005U : 5;
|
||||
default: return 5; }
|
||||
}return 5;}return 5;default: return 5; }
|
||||
case 'f':
|
||||
/* prefix f */{static const char tmp[4] = {'l','o','o','r'};
|
||||
if(std::memcmp(uptr+1, tmp, 4) == 0) return Functions[cFloor].enabled() ? (cFloor<<16) | 0x80000005U : 5;
|
||||
return 5; }
|
||||
case 'l':
|
||||
/* prefix l */{static const char tmp[4] = {'o','g','1','0'};
|
||||
if(std::memcmp(uptr+1, tmp, 4) == 0) return Functions[cLog10].enabled() ? (cLog10<<16) | 0x80000005U : 5;
|
||||
return 5; }
|
||||
case 't':
|
||||
/* prefix t */{static const char tmp[4] = {'r','u','n','c'};
|
||||
if(std::memcmp(uptr+1, tmp, 4) == 0) return Functions[cTrunc].enabled() ? (cTrunc<<16) | 0x80000005U : 5;
|
||||
return 5; }
|
||||
default: return 5; }
|
||||
default: break;
|
||||
}
|
||||
return nameLength;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,159 @@
|
||||
/***************************************************************************\
|
||||
|* Function Parser for C++ v4.0.3 *|
|
||||
|*-------------------------------------------------------------------------*|
|
||||
|* Copyright: Juha Nieminen, Joel Yliluoma *|
|
||||
\***************************************************************************/
|
||||
|
||||
#ifndef ONCE_FPARSER_H_
|
||||
#define ONCE_FPARSER_H_
|
||||
|
||||
#pragma interface
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Visual Studio's warning about missing definitions for the explicit
|
||||
// FunctionParserBase instantiations is irrelevant here.
|
||||
#pragma warning(disable : 4661)
|
||||
#endif
|
||||
|
||||
namespace FPoptimizer_CodeTree { class CodeTree; }
|
||||
|
||||
template<typename Value_t>
|
||||
class FunctionParserBase
|
||||
{
|
||||
public:
|
||||
enum ParseErrorType
|
||||
{
|
||||
SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH,
|
||||
EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS,
|
||||
ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC,
|
||||
UNKNOWN_IDENTIFIER,
|
||||
NO_FUNCTION_PARSED_YET,
|
||||
FP_NO_ERROR
|
||||
};
|
||||
|
||||
typedef Value_t value_type;
|
||||
|
||||
|
||||
int Parse(const char* Function, const std::string& Vars,
|
||||
bool useDegrees = false);
|
||||
int Parse(const std::string& Function, const std::string& Vars,
|
||||
bool useDegrees = false);
|
||||
|
||||
void setDelimiterChar(char);
|
||||
|
||||
const char* ErrorMsg() const;
|
||||
inline ParseErrorType GetParseErrorType() const { return parseErrorType; }
|
||||
|
||||
Value_t Eval(const Value_t* Vars);
|
||||
inline int EvalError() const { return evalErrorType; }
|
||||
|
||||
bool AddConstant(const std::string& name, Value_t value);
|
||||
bool AddUnit(const std::string& name, Value_t value);
|
||||
|
||||
typedef Value_t (*FunctionPtr)(const Value_t*);
|
||||
|
||||
bool AddFunction(const std::string& name,
|
||||
FunctionPtr, unsigned paramsAmount);
|
||||
bool AddFunction(const std::string& name, FunctionParserBase&);
|
||||
|
||||
bool RemoveIdentifier(const std::string& name);
|
||||
|
||||
void Optimize();
|
||||
|
||||
|
||||
int ParseAndDeduceVariables(const std::string& function,
|
||||
int* amountOfVariablesFound = 0,
|
||||
bool useDegrees = false);
|
||||
int ParseAndDeduceVariables(const std::string& function,
|
||||
std::string& resultVarString,
|
||||
int* amountOfVariablesFound = 0,
|
||||
bool useDegrees = false);
|
||||
int ParseAndDeduceVariables(const std::string& function,
|
||||
std::vector<std::string>& resultVars,
|
||||
bool useDegrees = false);
|
||||
|
||||
|
||||
FunctionParserBase();
|
||||
~FunctionParserBase();
|
||||
|
||||
// Copy constructor and assignment operator (implemented using the
|
||||
// copy-on-write technique for efficiency):
|
||||
FunctionParserBase(const FunctionParserBase&);
|
||||
FunctionParserBase& operator=(const FunctionParserBase&);
|
||||
|
||||
|
||||
void ForceDeepCopy();
|
||||
|
||||
|
||||
#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
|
||||
// For debugging purposes only:
|
||||
void PrintByteCode(std::ostream& dest, bool showExpression = true) const;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//========================================================================
|
||||
private:
|
||||
//========================================================================
|
||||
|
||||
// Private data:
|
||||
// ------------
|
||||
char delimiterChar;
|
||||
ParseErrorType parseErrorType;
|
||||
int evalErrorType;
|
||||
|
||||
friend class FPoptimizer_CodeTree::CodeTree;
|
||||
|
||||
struct Data;
|
||||
Data* data;
|
||||
|
||||
bool useDegreeConversion;
|
||||
unsigned evalRecursionLevel;
|
||||
unsigned StackPtr;
|
||||
const char* errorLocation;
|
||||
|
||||
|
||||
// Private methods:
|
||||
// ---------------
|
||||
void CopyOnWrite();
|
||||
bool CheckRecursiveLinking(const FunctionParserBase*) const;
|
||||
bool NameExists(const char*, unsigned);
|
||||
bool ParseVariables(const std::string&);
|
||||
int ParseFunction(const char*, bool);
|
||||
const char* SetErrorType(ParseErrorType, const char*);
|
||||
|
||||
void AddFunctionOpcode(unsigned);
|
||||
void AddImmedOpcode(Value_t v);
|
||||
void incStackPtr();
|
||||
void CompilePowi(int);
|
||||
bool TryCompilePowi(Value_t);
|
||||
|
||||
const char* CompileIf(const char*);
|
||||
const char* CompileFunctionParams(const char*, unsigned);
|
||||
const char* CompileElement(const char*);
|
||||
const char* CompilePossibleUnit(const char*);
|
||||
const char* CompilePow(const char*);
|
||||
const char* CompileUnaryMinus(const char*);
|
||||
const char* CompileMult(const char*);
|
||||
const char* CompileAddition(const char*);
|
||||
const char* CompileComparison(const char*);
|
||||
const char* CompileAnd(const char*);
|
||||
const char* CompileExpression(const char*);
|
||||
inline const char* CompileFunction(const char*, unsigned);
|
||||
inline const char* CompileParenthesis(const char*);
|
||||
inline const char* CompileLiteral(const char*);
|
||||
};
|
||||
|
||||
class FunctionParser: public FunctionParserBase<double> {};
|
||||
class FunctionParser_f: public FunctionParserBase<float> {};
|
||||
class FunctionParser_ld: public FunctionParserBase<long double> {};
|
||||
class FunctionParser_li: public FunctionParserBase<long> {};
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,599 @@
|
||||
/***************************************************************************\
|
||||
|* Function Parser for C++ v4.0.3 *|
|
||||
|*-------------------------------------------------------------------------*|
|
||||
|* Copyright: Juha Nieminen, Joel Yliluoma *|
|
||||
\***************************************************************************/
|
||||
|
||||
// NOTE:
|
||||
// This file contains only internal types for the function parser library.
|
||||
// You don't need to include this file in your code. Include "fparser.hh"
|
||||
// only.
|
||||
|
||||
#ifndef ONCE_FPARSER_AUX_H_
|
||||
#define ONCE_FPARSER_AUX_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
|
||||
#include "mpfr/MpfrFloat.h"
|
||||
#endif
|
||||
|
||||
#ifdef FP_SUPPORT_GMP_INT_TYPE
|
||||
#include "mpfr/GmpInt.h"
|
||||
#endif
|
||||
|
||||
#ifdef ONCE_FPARSER_H_
|
||||
namespace FUNCTIONPARSERTYPES
|
||||
{
|
||||
//==========================================================================
|
||||
// Math funcs
|
||||
//==========================================================================
|
||||
/* fp_pow() is a wrapper for std::pow()
|
||||
* that produces an identical value for
|
||||
* exp(1) ^ 2.0 (0x4000000000000000)
|
||||
* as exp(2.0) (0x4000000000000000)
|
||||
* - std::pow() on x86_64
|
||||
* produces 2.0 (0x3FFFFFFFFFFFFFFF) instead!
|
||||
* See comments below for other special traits.
|
||||
*/
|
||||
template<typename ValueT>
|
||||
inline ValueT fp_pow_with_exp_log(const ValueT& x, const ValueT& y)
|
||||
{
|
||||
// Requirements: x > 0.
|
||||
return fp_exp(fp_log(x) * y);
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
inline ValueT fp_powi(ValueT x, unsigned long y)
|
||||
{
|
||||
// Requirements: y is non-negative integer.
|
||||
ValueT result(1);
|
||||
while(y != 0)
|
||||
{
|
||||
if(y & 1) { result *= x; y -= 1; }
|
||||
else { x *= x; y /= 2; }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
ValueT fp_pow(const ValueT& x, const ValueT& y)
|
||||
{
|
||||
if(x == ValueT(1)) return ValueT(1);
|
||||
// y is now zero or positive
|
||||
|
||||
if(IsIntegerConst(y))
|
||||
{
|
||||
// Use fast binary exponentiation algorithm
|
||||
// See http://en.wikipedia.org/wiki/Exponentiation_by_squaring
|
||||
if(y >= ValueT(0))
|
||||
return fp_powi(x, (long)y);
|
||||
else
|
||||
return ValueT(1) / fp_powi(x, -(long)y);
|
||||
}
|
||||
|
||||
if(y >= ValueT(0))
|
||||
{
|
||||
// y is now positive. Calculate using exp(log(x)*y).
|
||||
// See http://en.wikipedia.org/wiki/Exponentiation#Real_powers
|
||||
if(x > ValueT(0)) return fp_pow_with_exp_log(x, y);
|
||||
if(x == ValueT(0)) return ValueT(0);
|
||||
// At this point, y > 0.0 and x is known to be < 0.0,
|
||||
// because positive and zero cases are already handled.
|
||||
//
|
||||
if(!IsIntegerConst(y*ValueT(16)))
|
||||
return -fp_pow_with_exp_log(-x, y);
|
||||
// ^This is not technically correct, but it allows
|
||||
// functions such as cbrt(x^5), that is, x^(5/3),
|
||||
// to be evaluated when x is negative.
|
||||
// It is too complicated (and slow) to test whether y
|
||||
// is a formed from a ratio of an integer to an odd integer.
|
||||
// (And due to floating point inaccuracy, pointless too.)
|
||||
// For example, x^1.30769230769... is
|
||||
// actually x^(17/13), i.e. (x^17) ^ (1/13).
|
||||
// (-5)^(17/13) gives us now -8.204227562330453.
|
||||
// To see whether the result is right, we can test the given
|
||||
// root: (-8.204227562330453)^13 gives us the value of (-5)^17,
|
||||
// which proves that the expression was correct.
|
||||
//
|
||||
// The y*16 check prevents e.g. (-4)^(3/2) from being calculated,
|
||||
// as it would confuse functioninfo when pow() returns no error
|
||||
// but sqrt() does when the formula is converted into sqrt(x)*x.
|
||||
//
|
||||
// The errors in this approach are:
|
||||
// (-2)^sqrt(2) should produce NaN
|
||||
// or actually sqrt(2)I + 2^sqrt(2),
|
||||
// produces -(2^sqrt(2)) instead.
|
||||
// (Impact: Neglible)
|
||||
// Thus, at worst, we're changing a NaN (or complex)
|
||||
// result into a negative real number result.
|
||||
}
|
||||
else
|
||||
{
|
||||
// y is negative. Utilize the x^y = 1/(x^-y) identity.
|
||||
if(x > ValueT(0)) return fp_pow_with_exp_log(ValueT(1) / x, -y);
|
||||
if(x < ValueT(0))
|
||||
{
|
||||
if(!IsIntegerConst(y*ValueT(-16)))
|
||||
return -fp_pow_with_exp_log(ValueT(-1) / x, -y);
|
||||
// ^ See comment above.
|
||||
}
|
||||
// Remaining case: 0.0 ^ negative number
|
||||
}
|
||||
// This is reached when:
|
||||
// x=0 and y<0
|
||||
// x<0 and y*16 is either positive or negative integer
|
||||
// It is used for producing error values and as a safe fallback.
|
||||
return fp_pow_base(x, y);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// double
|
||||
// -------------------------------------------------------------------------
|
||||
inline double fp_abs(double x) { return fabs(x); }
|
||||
inline double fp_acos(double x) { return acos(x); }
|
||||
inline double fp_asin(double x) { return asin(x); }
|
||||
inline double fp_atan(double x) { return atan(x); }
|
||||
inline double fp_atan2(double x, double y) { return atan2(x, y); }
|
||||
#ifdef FP_SUPPORT_CBRT
|
||||
inline double fp_cbrt(double x) { return cbrt(x); }
|
||||
#else
|
||||
inline double fp_cbrt(double x) { return x>0 ? exp(log( x)/3.0)
|
||||
: x<0 ? -exp(log(-x)/3.0)
|
||||
: 0.0; }
|
||||
#endif
|
||||
inline double fp_ceil(double x) { return ceil(x); }
|
||||
inline double fp_cos(double x) { return cos(x); }
|
||||
inline double fp_cosh(double x) { return cosh(x); }
|
||||
inline double fp_exp(double x) { return exp(x); }
|
||||
inline double fp_floor(double x) { return floor(x); }
|
||||
inline double fp_int(double x) { return floor(x + .5); }
|
||||
inline double fp_log(double x) { return log(x); }
|
||||
inline double fp_log10(double x)
|
||||
{ return log(x) *
|
||||
0.434294481903251827651128918916605082294397005803666566; }
|
||||
inline double fp_mod(double x, double y) { return fmod(x, y); }
|
||||
inline double fp_sin(double x) { return sin(x); }
|
||||
inline double fp_sinh(double x) { return sinh(x); }
|
||||
inline double fp_sqrt(double x) { return sqrt(x); }
|
||||
inline double fp_tan(double x) { return tan(x); }
|
||||
inline double fp_tanh(double x) { return tanh(x); }
|
||||
|
||||
#ifndef FP_SUPPORT_ASINH
|
||||
inline double fp_asinh(double x) { return log(x + sqrt(x*x + 1.0)); }
|
||||
inline double fp_acosh(double x) { return log(x + sqrt(x*x - 1.0)); }
|
||||
inline double fp_atanh(double x) { return log((1.0+x) / (1.0-x)) * 0.5; }
|
||||
#else
|
||||
inline double fp_asinh(double x) { return asinh(x); }
|
||||
inline double fp_acosh(double x) { return acosh(x); }
|
||||
inline double fp_atanh(double x) { return atanh(x); }
|
||||
#endif // FP_SUPPORT_ASINH
|
||||
|
||||
inline double fp_trunc(double x) { return x<0.0 ? ceil(x) : floor(x); }
|
||||
|
||||
inline double fp_pow_base(double x, double y) { return pow(x, y); }
|
||||
|
||||
#ifndef FP_SUPPORT_LOG2
|
||||
inline double fp_log2(double x)
|
||||
{ return log(x) * 1.4426950408889634073599246810018921374266459541529859; }
|
||||
#else
|
||||
inline double fp_log2(double x) { return log2(x); }
|
||||
#endif // FP_SUPPORT_LOG2
|
||||
|
||||
inline double fp_exp2(double x) { return fp_pow(2.0, x); }
|
||||
|
||||
#ifdef FP_EPSILON
|
||||
template<typename Value_t>
|
||||
inline Value_t fp_epsilon() { return FP_EPSILON; }
|
||||
#else
|
||||
template<typename Value_t>
|
||||
inline Value_t fp_epsilon() { return 0.0; }
|
||||
#endif
|
||||
|
||||
#ifdef FP_EPSILON
|
||||
inline bool FloatEqual(double a, double b)
|
||||
{ return fabs(a - b) <= fp_epsilon<double>(); }
|
||||
#else
|
||||
inline bool FloatEqual(double a, double b)
|
||||
{ return a == b; }
|
||||
#endif // FP_EPSILON
|
||||
|
||||
inline bool IsIntegerConst(double a)
|
||||
{ return FloatEqual(a, (double)(long)a); }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// float
|
||||
// -------------------------------------------------------------------------
|
||||
#ifdef FP_SUPPORT_FLOAT_TYPE
|
||||
inline float fp_abs(float x) { return fabsf(x); }
|
||||
inline float fp_acos(float x) { return acosf(x); }
|
||||
inline float fp_asin(float x) { return asinf(x); }
|
||||
inline float fp_atan(float x) { return atanf(x); }
|
||||
inline float fp_atan2(float x, float y) { return atan2f(x, y); }
|
||||
#ifdef FP_SUPPORT_CBRT
|
||||
inline float fp_cbrt(float x) { return cbrtf(x); }
|
||||
#else
|
||||
inline float fp_cbrt(float x) { return x>0 ? expf(logf( x)/3.0f)
|
||||
: x<0 ? -expf(logf(-x)/3.0f)
|
||||
: 0.0f; }
|
||||
#endif
|
||||
inline float fp_ceil(float x) { return ceilf(x); }
|
||||
inline float fp_cos(float x) { return cosf(x); }
|
||||
inline float fp_cosh(float x) { return coshf(x); }
|
||||
inline float fp_exp(float x) { return expf(x); }
|
||||
inline float fp_floor(float x) { return floorf(x); }
|
||||
inline float fp_int(float x) { return floorf(x + .5F); }
|
||||
inline float fp_log(float x) { return logf(x); }
|
||||
inline float fp_log10(float x)
|
||||
{ return logf(x) *
|
||||
0.434294481903251827651128918916605082294397005803666566F; }
|
||||
inline float fp_mod(float x, float y) { return fmodf(x, y); }
|
||||
inline float fp_sin(float x) { return sinf(x); }
|
||||
inline float fp_sinh(float x) { return sinhf(x); }
|
||||
inline float fp_sqrt(float x) { return sqrtf(x); }
|
||||
inline float fp_tan(float x) { return tanf(x); }
|
||||
inline float fp_tanh(float x) { return tanhf(x); }
|
||||
|
||||
#ifndef FP_SUPPORT_ASINH
|
||||
inline float fp_asinh(float x) { return logf(x + sqrt(x*x + 1.0F)); }
|
||||
inline float fp_acosh(float x) { return logf(x + sqrt(x*x - 1.0F)); }
|
||||
inline float fp_atanh(float x) { return logf((1.0F+x) / (1.0F-x)) * 0.5F; }
|
||||
#else
|
||||
inline float fp_asinh(float x) { return asinhf(x); }
|
||||
inline float fp_acosh(float x) { return acoshf(x); }
|
||||
inline float fp_atanh(float x) { return atanhf(x); }
|
||||
#endif // FP_SUPPORT_ASINH
|
||||
|
||||
inline float fp_trunc(float x) { return x<0.0F ? ceilf(x) : floorf(x); }
|
||||
|
||||
inline float fp_pow_base(float x, float y) { return powf(x, y); }
|
||||
|
||||
#ifndef FP_SUPPORT_LOG2
|
||||
inline float fp_log2(float x)
|
||||
{ return logf(x) *
|
||||
1.4426950408889634073599246810018921374266459541529859F; }
|
||||
#else
|
||||
inline float fp_log2(float x) { return log2f(x); }
|
||||
#endif // FP_SUPPORT_LOG2
|
||||
|
||||
inline float fp_exp2(float x) { return fp_pow(2.0F, x); }
|
||||
|
||||
#ifdef FP_EPSILON
|
||||
template<>
|
||||
inline float fp_epsilon<float>() { return 1e-6F; }
|
||||
#else
|
||||
template<>
|
||||
inline float fp_epsilon<float>() { return 0.0F; }
|
||||
#endif
|
||||
|
||||
#ifdef FP_EPSILON
|
||||
inline bool FloatEqual(float a, float b)
|
||||
{ return fabsf(a - b) <= fp_epsilon<float>(); }
|
||||
#else
|
||||
inline bool FloatEqual(float a, float b)
|
||||
{ return a == b; }
|
||||
#endif // FP_EPSILON
|
||||
|
||||
inline bool IsIntegerConst(float a)
|
||||
{ return FloatEqual(a, (float)(long)a); }
|
||||
#endif // FP_SUPPORT_FLOAT_TYPE
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// long double
|
||||
// -------------------------------------------------------------------------
|
||||
#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
|
||||
inline long double fp_abs(long double x) { return fabsl(x); }
|
||||
inline long double fp_acos(long double x) { return acosl(x); }
|
||||
inline long double fp_asin(long double x) { return asinl(x); }
|
||||
inline long double fp_atan(long double x) { return atanl(x); }
|
||||
inline long double fp_atan2(long double x, long double y)
|
||||
{ return atan2l(x, y); }
|
||||
#ifdef FP_SUPPORT_CBRT
|
||||
inline long double fp_cbrt(long double x) { return cbrtl(x); }
|
||||
#else
|
||||
inline long double fp_cbrt(long double x)
|
||||
{ return x>0 ? expl(logl( x)/3.0l)
|
||||
: x<0 ? -expl(logl(-x)/3.0l)
|
||||
: 0.0l; }
|
||||
#endif
|
||||
inline long double fp_ceil(long double x) { return ceill(x); }
|
||||
inline long double fp_cos(long double x) { return cosl(x); }
|
||||
inline long double fp_cosh(long double x) { return coshl(x); }
|
||||
inline long double fp_exp(long double x) { return expl(x); }
|
||||
inline long double fp_floor(long double x) { return floorl(x); }
|
||||
inline long double fp_int(long double x) { return floorl(x + .5L); }
|
||||
inline long double fp_log(long double x) { return logl(x); }
|
||||
inline long double fp_log10(long double x)
|
||||
{ return logl(x) *
|
||||
0.434294481903251827651128918916605082294397005803666566L; }
|
||||
inline long double fp_mod(long double x, long double y)
|
||||
{ return fmodl(x, y); }
|
||||
inline long double fp_sin(long double x) { return sinl(x); }
|
||||
inline long double fp_sinh(long double x) { return sinhl(x); }
|
||||
inline long double fp_sqrt(long double x) { return sqrtl(x); }
|
||||
inline long double fp_tan(long double x) { return tanl(x); }
|
||||
inline long double fp_tanh(long double x) { return tanhl(x); }
|
||||
|
||||
#ifndef FP_SUPPORT_ASINH
|
||||
inline long double fp_asinh(long double x)
|
||||
{ return logl(x + sqrtl(x*x + 1.0L)); }
|
||||
inline long double fp_acosh(long double x)
|
||||
{ return logl(x + sqrtl(x*x - 1.0L)); }
|
||||
inline long double fp_atanh(long double x)
|
||||
{ return logl((1.0L+x) / (1.0L-x)) * 0.5L; }
|
||||
#else
|
||||
inline long double fp_asinh(long double x) { return asinhl(x); }
|
||||
inline long double fp_acosh(long double x) { return acoshl(x); }
|
||||
inline long double fp_atanh(long double x) { return atanhl(x); }
|
||||
#endif // FP_SUPPORT_ASINH
|
||||
|
||||
inline long double fp_trunc(long double x)
|
||||
{ return x<0.0L ? ceill(x) : floorl(x); }
|
||||
|
||||
inline long double fp_pow_base(long double x, long double y)
|
||||
{ return powl(x, y); }
|
||||
|
||||
#ifndef FP_SUPPORT_LOG2
|
||||
inline long double fp_log2(long double x)
|
||||
{ return log(x) * 1.4426950408889634073599246810018921374266459541529859L; }
|
||||
#else
|
||||
inline long double fp_log2(long double x) { return log2l(x); }
|
||||
#endif // FP_SUPPORT_LOG2
|
||||
|
||||
inline long double fp_exp2(long double x) { return fp_pow(2.0L, x); }
|
||||
|
||||
#ifdef FP_EPSILON
|
||||
inline bool FloatEqual(long double a, long double b)
|
||||
{ return fabsl(a - b) <= fp_epsilon<double>(); }
|
||||
#else
|
||||
inline bool FloatEqual(long double a, long double b)
|
||||
{ return a == b; }
|
||||
#endif // FP_EPSILON
|
||||
|
||||
inline bool IsIntegerConst(long double a)
|
||||
{ return FloatEqual(a, (long double)(long)a); }
|
||||
#endif // FP_SUPPORT_LONG_DOUBLE_TYPE
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Long int
|
||||
// -------------------------------------------------------------------------
|
||||
inline long fp_abs(long x) { return x < 0 ? -x : x; }
|
||||
inline long fp_acos(long) { return 0; }
|
||||
inline long fp_asin(long) { return 0; }
|
||||
inline long fp_atan(long) { return 0; }
|
||||
inline long fp_atan2(long, long) { return 0; }
|
||||
inline long fp_cbrt(long) { return 0; }
|
||||
inline long fp_ceil(long x) { return x; }
|
||||
inline long fp_cos(long) { return 0; }
|
||||
inline long fp_cosh(long) { return 0; }
|
||||
inline long fp_exp(long) { return 0; }
|
||||
inline long fp_floor(long x) { return x; }
|
||||
inline long fp_int(long x) { return x; }
|
||||
inline long fp_log(long) { return 0; }
|
||||
inline long fp_log10(long) { return 0; }
|
||||
inline long fp_mod(long x, long y) { return x % y; }
|
||||
inline long fp_pow(long, long) { return 0; }
|
||||
inline long fp_sin(long) { return 0; }
|
||||
inline long fp_sinh(long) { return 0; }
|
||||
inline long fp_sqrt(long) { return 1; }
|
||||
inline long fp_tan(long) { return 0; }
|
||||
inline long fp_tanh(long) { return 0; }
|
||||
inline long fp_asinh(long) { return 0; }
|
||||
inline long fp_acosh(long) { return 0; }
|
||||
inline long fp_atanh(long) { return 0; }
|
||||
inline long fp_trunc(long x) { return x; }
|
||||
inline long fp_pow_base(long, long) { return 0; }
|
||||
inline long fp_log2(long) { return 0; }
|
||||
inline long fp_exp2(long) { return 0; }
|
||||
|
||||
template<>
|
||||
inline long fp_epsilon<long>() { return 0; }
|
||||
|
||||
inline bool IsIntegerConst(long) { return true; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// MpfrFloat
|
||||
// -------------------------------------------------------------------------
|
||||
#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
|
||||
inline MpfrFloat fp_abs(const MpfrFloat& x) { return MpfrFloat::abs(x); }
|
||||
inline MpfrFloat fp_acos(const MpfrFloat& x) { return MpfrFloat::acos(x); }
|
||||
inline MpfrFloat fp_asin(const MpfrFloat& x) { return MpfrFloat::asin(x); }
|
||||
inline MpfrFloat fp_atan(const MpfrFloat& x) { return MpfrFloat::atan(x); }
|
||||
inline MpfrFloat fp_atan2(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::atan2(x, y); }
|
||||
inline MpfrFloat fp_cbrt(const MpfrFloat& x) { return MpfrFloat::cbrt(x); }
|
||||
inline MpfrFloat fp_ceil(const MpfrFloat& x) { return MpfrFloat::ceil(x); }
|
||||
inline MpfrFloat fp_cos(const MpfrFloat& x) { return MpfrFloat::cos(x); }
|
||||
inline MpfrFloat fp_cosh(const MpfrFloat& x) { return MpfrFloat::cosh(x); }
|
||||
inline MpfrFloat fp_exp(const MpfrFloat& x) { return MpfrFloat::exp(x); }
|
||||
inline MpfrFloat fp_floor(const MpfrFloat& x) { return MpfrFloat::floor(x); }
|
||||
inline MpfrFloat fp_int(const MpfrFloat& x) { return MpfrFloat::round(x); }
|
||||
inline MpfrFloat fp_log(const MpfrFloat& x) { return MpfrFloat::log(x); }
|
||||
inline MpfrFloat fp_log10(const MpfrFloat& x) { return MpfrFloat::log10(x); }
|
||||
inline MpfrFloat fp_mod(const MpfrFloat& x, const MpfrFloat& y) { return x % y; }
|
||||
inline MpfrFloat fp_sin(const MpfrFloat& x) { return MpfrFloat::sin(x); }
|
||||
inline MpfrFloat fp_sinh(const MpfrFloat& x) { return MpfrFloat::sinh(x); }
|
||||
inline MpfrFloat fp_sqrt(const MpfrFloat& x) { return MpfrFloat::sqrt(x); }
|
||||
inline MpfrFloat fp_tan(const MpfrFloat& x) { return MpfrFloat::tan(x); }
|
||||
inline MpfrFloat fp_tanh(const MpfrFloat& x) { return MpfrFloat::tanh(x); }
|
||||
inline MpfrFloat fp_asinh(const MpfrFloat& x) { return MpfrFloat::asinh(x); }
|
||||
inline MpfrFloat fp_acosh(const MpfrFloat& x) { return MpfrFloat::acosh(x); }
|
||||
inline MpfrFloat fp_atanh(const MpfrFloat& x) { return MpfrFloat::atanh(x); }
|
||||
inline MpfrFloat fp_trunc(const MpfrFloat& x) { return MpfrFloat::trunc(x); }
|
||||
|
||||
inline MpfrFloat fp_pow(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
|
||||
inline MpfrFloat fp_pow_base(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
|
||||
|
||||
inline MpfrFloat fp_log2(const MpfrFloat& x) { return MpfrFloat::log2(x); }
|
||||
inline MpfrFloat fp_exp2(const MpfrFloat& x) { return MpfrFloat::exp2(x); }
|
||||
|
||||
inline bool IsIntegerConst(const MpfrFloat& a) { return a.isInteger(); }
|
||||
|
||||
template<>
|
||||
inline MpfrFloat fp_epsilon<MpfrFloat>() { return MpfrFloat::someEpsilon(); }
|
||||
#endif // FP_SUPPORT_MPFR_FLOAT_TYPE
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// GMP int
|
||||
// -------------------------------------------------------------------------
|
||||
#ifdef FP_SUPPORT_GMP_INT_TYPE
|
||||
inline GmpInt fp_abs(GmpInt x) { return GmpInt::abs(x); }
|
||||
inline GmpInt fp_acos(GmpInt) { return 0; }
|
||||
inline GmpInt fp_asin(GmpInt) { return 0; }
|
||||
inline GmpInt fp_atan(GmpInt) { return 0; }
|
||||
inline GmpInt fp_atan2(GmpInt, GmpInt) { return 0; }
|
||||
inline GmpInt fp_cbrt(GmpInt) { return 0; }
|
||||
inline GmpInt fp_ceil(GmpInt x) { return x; }
|
||||
inline GmpInt fp_cos(GmpInt) { return 0; }
|
||||
inline GmpInt fp_cosh(GmpInt) { return 0; }
|
||||
inline GmpInt fp_exp(GmpInt) { return 0; }
|
||||
inline GmpInt fp_floor(GmpInt x) { return x; }
|
||||
inline GmpInt fp_int(GmpInt x) { return x; }
|
||||
inline GmpInt fp_log(GmpInt) { return 0; }
|
||||
inline GmpInt fp_log10(GmpInt) { return 0; }
|
||||
inline GmpInt fp_mod(GmpInt x, GmpInt y) { return x % y; }
|
||||
inline GmpInt fp_pow(GmpInt, GmpInt) { return 0; }
|
||||
inline GmpInt fp_sin(GmpInt) { return 0; }
|
||||
inline GmpInt fp_sinh(GmpInt) { return 0; }
|
||||
inline GmpInt fp_sqrt(GmpInt) { return 0; }
|
||||
inline GmpInt fp_tan(GmpInt) { return 0; }
|
||||
inline GmpInt fp_tanh(GmpInt) { return 0; }
|
||||
inline GmpInt fp_asinh(GmpInt) { return 0; }
|
||||
inline GmpInt fp_acosh(GmpInt) { return 0; }
|
||||
inline GmpInt fp_atanh(GmpInt) { return 0; }
|
||||
inline GmpInt fp_trunc(GmpInt x) { return x; }
|
||||
inline GmpInt fp_pow_base(GmpInt, GmpInt) { return 0; }
|
||||
inline GmpInt fp_log2(GmpInt) { return 0; }
|
||||
inline GmpInt fp_exp2(GmpInt) { return 0; }
|
||||
|
||||
template<>
|
||||
inline GmpInt fp_epsilon<GmpInt>() { return 0; }
|
||||
|
||||
inline bool IsIntegerConst(GmpInt) { return true; }
|
||||
#endif // FP_SUPPORT_GMP_INT_TYPE
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Comparison
|
||||
// -------------------------------------------------------------------------
|
||||
#ifdef FP_EPSILON
|
||||
template<typename Value_t>
|
||||
inline bool fp_equal(Value_t x, Value_t y)
|
||||
{ return fp_abs(x - y) <= fp_epsilon<Value_t>(); }
|
||||
|
||||
template<typename Value_t>
|
||||
inline bool fp_nequal(Value_t x, Value_t y)
|
||||
{ return fp_abs(x - y) > fp_epsilon<Value_t>(); }
|
||||
|
||||
template<typename Value_t>
|
||||
inline bool fp_less(Value_t x, Value_t y)
|
||||
{ return x < y - fp_epsilon<Value_t>(); }
|
||||
|
||||
template<typename Value_t>
|
||||
inline bool fp_lessOrEq(Value_t x, Value_t y)
|
||||
{ return x <= y + fp_epsilon<Value_t>(); }
|
||||
#else // FP_EPSILON
|
||||
template<typename Value_t>
|
||||
inline bool fp_equal(Value_t x, Value_t y) { return x == y; }
|
||||
|
||||
template<typename Value_t>
|
||||
inline bool fp_nequal(Value_t x, Value_t y) { return x != y; }
|
||||
|
||||
template<typename Value_t>
|
||||
inline bool fp_less(Value_t x, Value_t y) { return x < y; }
|
||||
|
||||
template<typename Value_t>
|
||||
inline bool fp_lessOrEq(Value_t x, Value_t y) { return x <= y; }
|
||||
#endif // FP_EPSILON
|
||||
|
||||
template<>
|
||||
inline bool fp_equal<long>(long x, long y) { return x == y; }
|
||||
|
||||
template<>
|
||||
inline bool fp_nequal<long>(long x, long y) { return x != y; }
|
||||
|
||||
template<>
|
||||
inline bool fp_less<long>(long x, long y) { return x < y; }
|
||||
|
||||
template<>
|
||||
inline bool fp_lessOrEq<long>(long x, long y) { return x <= y; }
|
||||
|
||||
#ifdef FP_SUPPORT_GMP_INT_TYPE
|
||||
template<>
|
||||
inline bool fp_equal<GmpInt>(GmpInt x, GmpInt y) { return x == y; }
|
||||
|
||||
template<>
|
||||
inline bool fp_nequal<GmpInt>(GmpInt x, GmpInt y) { return x != y; }
|
||||
|
||||
template<>
|
||||
inline bool fp_less<GmpInt>(GmpInt x, GmpInt y) { return x < y; }
|
||||
|
||||
template<>
|
||||
inline bool fp_lessOrEq<GmpInt>(GmpInt x, GmpInt y) { return x <= y; }
|
||||
#endif
|
||||
} // namespace FUNCTIONPARSERTYPES
|
||||
|
||||
#endif // ONCE_FPARSER_H_
|
||||
|
||||
|
||||
#ifndef FP_DISABLE_DOUBLE_TYPE
|
||||
#define FUNCTIONPARSER_INSTANTIATE_DOUBLE \
|
||||
template class FunctionParserBase<double>;
|
||||
#else
|
||||
#define FUNCTIONPARSER_INSTANTIATE_DOUBLE
|
||||
#endif
|
||||
|
||||
#ifdef FP_SUPPORT_FLOAT_TYPE
|
||||
#define FUNCTIONPARSER_INSTANTIATE_FLOAT \
|
||||
template class FunctionParserBase<float>;
|
||||
#else
|
||||
#define FUNCTIONPARSER_INSTANTIATE_FLOAT
|
||||
#endif
|
||||
|
||||
#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
|
||||
#define FUNCTIONPARSER_INSTANTIATE_LONG_DOUBLE \
|
||||
template class FunctionParserBase<long double>;
|
||||
#else
|
||||
#define FUNCTIONPARSER_INSTANTIATE_LONG_DOUBLE
|
||||
#endif
|
||||
|
||||
#ifdef FP_SUPPORT_LONG_INT_TYPE
|
||||
#define FUNCTIONPARSER_INSTANTIATE_LONG_INT \
|
||||
template class FunctionParserBase<long>;
|
||||
#else
|
||||
#define FUNCTIONPARSER_INSTANTIATE_LONG_INT
|
||||
#endif
|
||||
|
||||
#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
|
||||
#define FUNCTIONPARSER_INSTANTIATE_MPFR_FLOAT \
|
||||
template class FunctionParserBase<MpfrFloat>;
|
||||
#else
|
||||
#define FUNCTIONPARSER_INSTANTIATE_MPFR_FLOAT
|
||||
#endif
|
||||
|
||||
#ifdef FP_SUPPORT_GMP_INT_TYPE
|
||||
#define FUNCTIONPARSER_INSTANTIATE_GMP_INT \
|
||||
template class FunctionParserBase<GmpInt>;
|
||||
#else
|
||||
#define FUNCTIONPARSER_INSTANTIATE_GMP_INT
|
||||
#endif
|
||||
|
||||
/* Add 'FUNCTIONPARSER_INSTANTIATE_TYPES' at the end of all .cc files
|
||||
containing FunctionParserBase implementations.
|
||||
*/
|
||||
#define FUNCTIONPARSER_INSTANTIATE_TYPES \
|
||||
FUNCTIONPARSER_INSTANTIATE_DOUBLE \
|
||||
FUNCTIONPARSER_INSTANTIATE_FLOAT \
|
||||
FUNCTIONPARSER_INSTANTIATE_LONG_DOUBLE \
|
||||
FUNCTIONPARSER_INSTANTIATE_LONG_INT \
|
||||
FUNCTIONPARSER_INSTANTIATE_MPFR_FLOAT \
|
||||
FUNCTIONPARSER_INSTANTIATE_GMP_INT
|
||||
|
||||
#endif // ONCE_FPARSER_AUX_H_
|
||||
@ -0,0 +1,139 @@
|
||||
/***************************************************************************\
|
||||
|* Function Parser for C++ v4.0.3 *|
|
||||
|*-------------------------------------------------------------------------*|
|
||||
|* Copyright: Juha Nieminen *|
|
||||
\***************************************************************************/
|
||||
|
||||
// Configuration file
|
||||
// ------------------
|
||||
|
||||
/* NOTE:
|
||||
This file is for the internal use of the function parser only.
|
||||
You don't need to include this file in your source files, just
|
||||
include "fparser.hh".
|
||||
*/
|
||||
|
||||
|
||||
/* Uncomment any of these lines or define them in your compiler settings
|
||||
to enable the correspondent version of the parser. (These are disabled
|
||||
by default because they rely on C99 functions, and non-standard libraries
|
||||
in the case pf MPFR and GMP, and they make compiling needlessly slower
|
||||
and the resulting binary needlessly larger if they are not used in the
|
||||
program.)
|
||||
*/
|
||||
//#define FP_SUPPORT_FLOAT_TYPE
|
||||
#define FP_SUPPORT_LONG_DOUBLE_TYPE
|
||||
//#define FP_SUPPORT_LONG_INT_TYPE
|
||||
//#define FP_SUPPORT_MPFR_FLOAT_TYPE
|
||||
//#define FP_SUPPORT_GMP_INT_TYPE
|
||||
|
||||
/* Uncomment this line of define it in your compiler settings if you want
|
||||
to disable compiling the basic double version of the library, in case
|
||||
one of the above types is used but not the double type. (If the double
|
||||
type is not used, then disabling it makes compiling faster and the
|
||||
resulting binary smaller.)
|
||||
*/
|
||||
//#define FP_DISABLE_DOUBLE_TYPE
|
||||
|
||||
/*
|
||||
Note that these do not change what FunctionParser supports, they only
|
||||
change how the function is evaluated, potentially making it faster when
|
||||
these functions are involved.
|
||||
These will make the source code use asinh(), acosh(), atanh(), exp2()
|
||||
and log2().
|
||||
*/
|
||||
//#define FP_SUPPORT_TR1_MATH_FUNCS
|
||||
|
||||
#ifdef FP_SUPPORT_TR1_MATH_FUNCS
|
||||
#define FP_SUPPORT_ASINH
|
||||
#define FP_SUPPORT_EXP2
|
||||
#define FP_SUPPORT_LOG2
|
||||
#define FP_SUPPORT_CBRT
|
||||
#endif
|
||||
|
||||
/*
|
||||
Comment out the following line to enable the eval() function, which can
|
||||
be used in the function string to recursively call the same function.
|
||||
Note that enabling this function may be dangerous even if the maximum
|
||||
recursion level is limited because it is still possible to write functions
|
||||
using it which take enormous amounts of time to evaluate even though the
|
||||
maximum recursion is never reached. This may be undesirable in some
|
||||
applications.
|
||||
Alternatively you can define the FP_ENABLE_EVAL precompiler constant in
|
||||
your compiler settings.
|
||||
*/
|
||||
#ifndef FP_ENABLE_EVAL
|
||||
#define FP_DISABLE_EVAL
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Maximum recursion level for eval() calls:
|
||||
*/
|
||||
#define FP_EVAL_MAX_REC_LEVEL 1000
|
||||
|
||||
|
||||
/*
|
||||
Whether to use shortcut evaluation for the & and | operators:
|
||||
*/
|
||||
#define FP_DISABLE_SHORTCUT_LOGICAL_EVALUATION
|
||||
#ifndef FP_DISABLE_SHORTCUT_LOGICAL_EVALUATION
|
||||
#define FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
|
||||
#endif
|
||||
|
||||
/*
|
||||
Whether to enable optimizations that may ignore side effects
|
||||
of if() calls, such as changing if(x,!y,0) into x&!y.
|
||||
This is basically the polar opposite of "shortcut logical evaluation".
|
||||
Disabled by default, because it makes eval() rather unsafe.
|
||||
*/
|
||||
#ifdef FP_ENABLE_IGNORE_IF_SIDEEFFECTS
|
||||
#endif
|
||||
|
||||
/*
|
||||
Comment out the following lines out if you are not going to use the
|
||||
optimizer and want a slightly smaller library. The Optimize() method
|
||||
can still be called, but it will not do anything.
|
||||
If you are unsure, just leave it. It won't slow down the other parts of
|
||||
the library.
|
||||
*/
|
||||
//#define FP_NO_SUPPORT_OPTIMIZER
|
||||
#ifndef FP_NO_SUPPORT_OPTIMIZER
|
||||
#define FP_SUPPORT_OPTIMIZER
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Epsilon value used with the comparison operators (must be non-negative):
|
||||
(Comment it out if you don't want to use epsilon in comparisons. Might
|
||||
lead to marginally faster evaluation of the comparison operators, but
|
||||
can introduce inaccuracies in comparisons.)
|
||||
*/
|
||||
#define FP_EPSILON 1e-14
|
||||
|
||||
|
||||
/*
|
||||
No member function of FunctionParser is thread-safe. Most prominently,
|
||||
Eval() is not thread-safe. By uncommenting one of these lines the Eval()
|
||||
function can be made thread-safe at the cost of a possible small overhead.
|
||||
The second version requires that the compiler supports the alloca() function,
|
||||
which is not standard, but is faster.
|
||||
*/
|
||||
//#define FP_USE_THREAD_SAFE_EVAL
|
||||
//#define FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
|
||||
|
||||
/*
|
||||
Uncomment (or define in your compiler options) to disable evaluation checks.
|
||||
(Consult the documentation for details.)
|
||||
*/
|
||||
#define FP_NO_EVALUATION_CHECKS
|
||||
|
||||
|
||||
|
||||
// Temporary settings while double is the only supported type by the optimizer
|
||||
#ifdef FP_DISABLE_DOUBLE_TYPE
|
||||
#ifndef FP_NO_SUPPORT_OPTIMIZER
|
||||
#define FP_NO_SUPPORT_OPTIMIZER
|
||||
#endif
|
||||
#undef FP_SUPPORT_OPTIMIZER
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,267 @@
|
||||
/***************************************************************************\
|
||||
|* Function Parser for C++ v4.0.3 *|
|
||||
|*-------------------------------------------------------------------------*|
|
||||
|* Copyright: Juha Nieminen, Joel Yliluoma *|
|
||||
\***************************************************************************/
|
||||
|
||||
// NOTE:
|
||||
// This file contains only internal types for the function parser library.
|
||||
// You don't need to include this file in your code. Include "fparser.hh"
|
||||
// only.
|
||||
|
||||
#ifndef ONCE_FPARSER_TYPES_H_
|
||||
#define ONCE_FPARSER_TYPES_H_
|
||||
|
||||
#include "fpconfig.h"
|
||||
#include <cstring>
|
||||
|
||||
#ifdef ONCE_FPARSER_H_
|
||||
# include <map>
|
||||
#endif
|
||||
|
||||
namespace FUNCTIONPARSERTYPES
|
||||
{
|
||||
enum OPCODE
|
||||
{
|
||||
// The order of opcodes in the function list must
|
||||
// match that which is in the Functions[] array.
|
||||
cAbs,
|
||||
cAcos, cAcosh,
|
||||
cAsin, cAsinh,
|
||||
cAtan, cAtan2, cAtanh,
|
||||
cCbrt, cCeil,
|
||||
cCos, cCosh, cCot, cCsc,
|
||||
cEval,
|
||||
cExp, cExp2, cFloor, cIf, cInt, cLog, cLog10, cLog2, cMax, cMin,
|
||||
cPow, cSec, cSin, cSinh, cSqrt, cTan, cTanh,
|
||||
cTrunc,
|
||||
|
||||
// These do not need any ordering:
|
||||
// Except that if you change the order of {eq,neq,lt,le,gt,ge}, you
|
||||
// must also change the order in ConstantFolding_ComparisonOperations().
|
||||
cImmed, cJump,
|
||||
cNeg, cAdd, cSub, cMul, cDiv, cMod,
|
||||
cEqual, cNEqual, cLess, cLessOrEq, cGreater, cGreaterOrEq,
|
||||
cNot, cAnd, cOr,
|
||||
cNotNot, /* Protects the double-not sequence from optimizations */
|
||||
|
||||
cDeg, cRad, /* Multiplication and division by 180 / pi */
|
||||
|
||||
cFCall, cPCall,
|
||||
|
||||
#ifdef FP_SUPPORT_OPTIMIZER
|
||||
cFetch, /* Same as Dup, except with absolute index
|
||||
* (next value is index) */
|
||||
cPopNMov, /* cPopNMov(x,y) moves [y] to [x] and deletes anything
|
||||
* above [x]. Used for disposing of temporaries.
|
||||
*/
|
||||
cLog2by, /* log2by(x,y) = log2(x) * y */
|
||||
#endif
|
||||
cAbsAnd, /* As cAnd, but assume both operands are absolute values */
|
||||
cAbsOr, /* As cOr, but assume both operands are absolute values */
|
||||
cAbsNot, /* As cAbsNot, but assume the operand is an absolute value */
|
||||
cAbsNotNot, /* As cAbsNotNot, but assume the operand is an absolute value */
|
||||
cAbsIf, /* As cAbsIf, but assume the 1st operand is an absolute value */
|
||||
|
||||
cDup, /* Duplicates the last value in the stack: Push [Stacktop] */
|
||||
cInv, /* Inverts the last value in the stack (x = 1/x) */
|
||||
cSqr, /* squares the last operand in the stack, no push/pop */
|
||||
cRDiv, /* reverse division (not x/y, but y/x) */
|
||||
cRSub, /* reverse subtraction (not x-y, but y-x) */
|
||||
cRSqrt, /* inverse square-root (1/sqrt(x)) */
|
||||
|
||||
cNop,
|
||||
VarBegin
|
||||
};
|
||||
|
||||
#ifdef ONCE_FPARSER_H_
|
||||
struct FuncDefinition
|
||||
{
|
||||
enum FunctionFlags
|
||||
{
|
||||
Enabled = 0x01,
|
||||
AngleIn = 0x02,
|
||||
AngleOut = 0x04,
|
||||
OkForInt = 0x08
|
||||
};
|
||||
|
||||
#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
|
||||
const char name[8];
|
||||
#else
|
||||
struct name { } name;
|
||||
#endif
|
||||
unsigned params : 8;
|
||||
unsigned flags : 8;
|
||||
|
||||
inline bool enabled() const { return flags != 0; }
|
||||
inline bool okForInt() const { return (flags & OkForInt) != 0; }
|
||||
};
|
||||
|
||||
#ifndef FP_DISABLE_EVAL
|
||||
# define FP_EVAL_FUNCTION_ENABLED \
|
||||
FuncDefinition::Enabled | FuncDefinition::OkForInt
|
||||
#else
|
||||
# define FP_EVAL_FUNCTION_ENABLED 0
|
||||
#endif
|
||||
#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
|
||||
# define FP_FNAME(n) n
|
||||
#else
|
||||
# define FP_FNAME(n) {}
|
||||
#endif
|
||||
// This list must be in the same order as that in OPCODE enum,
|
||||
// because the opcode value is used to index this array, and
|
||||
// the pointer to array element is used for generating the opcode.
|
||||
const FuncDefinition Functions[]=
|
||||
{
|
||||
/*cAbs */ { FP_FNAME("abs"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::OkForInt },
|
||||
/*cAcos */ { FP_FNAME("acos"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleOut },
|
||||
/*cAcosh*/ { FP_FNAME("acosh"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleOut },
|
||||
/*cAsin */ { FP_FNAME("asin"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleOut },
|
||||
/*cAsinh*/ { FP_FNAME("asinh"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleOut },
|
||||
/*cAtan */ { FP_FNAME("atan"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleOut },
|
||||
/*cAtan2*/ { FP_FNAME("atan2"), 2,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleOut },
|
||||
/*cAtanh*/ { FP_FNAME("atanh"), 1, FuncDefinition::Enabled },
|
||||
/*cCbrt */ { FP_FNAME("cbrt"), 1, FuncDefinition::Enabled },
|
||||
/*cCeil */ { FP_FNAME("ceil"), 1, FuncDefinition::Enabled },
|
||||
/*cCos */ { FP_FNAME("cos"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cCosh */ { FP_FNAME("cosh"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cCot */ { FP_FNAME("cot"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cCsc */ { FP_FNAME("csc"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cEval */ { FP_FNAME("eval"), 0, FP_EVAL_FUNCTION_ENABLED },
|
||||
/*cExp */ { FP_FNAME("exp"), 1, FuncDefinition::Enabled },
|
||||
/*cExp2 */ { FP_FNAME("exp2"), 1, FuncDefinition::Enabled },
|
||||
/*cFloor*/ { FP_FNAME("floor"), 1, FuncDefinition::Enabled },
|
||||
/*cIf */ { FP_FNAME("if"), 0,
|
||||
FuncDefinition::Enabled | FuncDefinition::OkForInt },
|
||||
/*cInt */ { FP_FNAME("int"), 1, FuncDefinition::Enabled },
|
||||
/*cLog */ { FP_FNAME("log"), 1, FuncDefinition::Enabled },
|
||||
/*cLog10*/ { FP_FNAME("log10"), 1, FuncDefinition::Enabled },
|
||||
/*cLog2 */ { FP_FNAME("log2"), 1, FuncDefinition::Enabled },
|
||||
/*cMax */ { FP_FNAME("max"), 2,
|
||||
FuncDefinition::Enabled | FuncDefinition::OkForInt },
|
||||
/*cMin */ { FP_FNAME("min"), 2,
|
||||
FuncDefinition::Enabled | FuncDefinition::OkForInt },
|
||||
/*cPow */ { FP_FNAME("pow"), 2, FuncDefinition::Enabled },
|
||||
/*cSec */ { FP_FNAME("sec"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cSin */ { FP_FNAME("sin"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cSinh */ { FP_FNAME("sinh"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cSqrt */ { FP_FNAME("sqrt"), 1,
|
||||
FuncDefinition::Enabled },
|
||||
/*cTan */ { FP_FNAME("tan"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cTanh */ { FP_FNAME("tanh"), 1,
|
||||
FuncDefinition::Enabled | FuncDefinition::AngleIn },
|
||||
/*cTrunc*/ { FP_FNAME("trunc"), 1,
|
||||
FuncDefinition::Enabled }
|
||||
};
|
||||
#undef FP_FNAME
|
||||
|
||||
struct NamePtr
|
||||
{
|
||||
const char* name;
|
||||
unsigned nameLength;
|
||||
|
||||
NamePtr(const char* n, unsigned l): name(n), nameLength(l) {}
|
||||
|
||||
inline bool operator==(const NamePtr& rhs) const
|
||||
{
|
||||
return nameLength == rhs.nameLength
|
||||
&& std::memcmp(name, rhs.name, nameLength) == 0;
|
||||
}
|
||||
inline bool operator<(const NamePtr& rhs) const
|
||||
{
|
||||
for(unsigned i = 0; i < nameLength; ++i)
|
||||
{
|
||||
if(i == rhs.nameLength) return false;
|
||||
const char c1 = name[i], c2 = rhs.name[i];
|
||||
if(c1 < c2) return true;
|
||||
if(c2 < c1) return false;
|
||||
}
|
||||
return nameLength < rhs.nameLength;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Value_t>
|
||||
struct NameData
|
||||
{
|
||||
enum DataType { CONSTANT, UNIT, FUNC_PTR, PARSER_PTR, VARIABLE };
|
||||
DataType type;
|
||||
unsigned index;
|
||||
Value_t value;
|
||||
|
||||
NameData(DataType t, unsigned v) : type(t), index(v), value() { }
|
||||
NameData(DataType t, Value_t v) : type(t), index(), value(v) { }
|
||||
NameData() { }
|
||||
};
|
||||
|
||||
template<typename Value_t>
|
||||
class namePtrsType: public
|
||||
std::map<
|
||||
FUNCTIONPARSERTYPES::NamePtr,
|
||||
FUNCTIONPARSERTYPES::NameData<Value_t>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]);
|
||||
#endif // ONCE_FPARSER_H_
|
||||
}
|
||||
|
||||
#ifdef ONCE_FPARSER_H_
|
||||
#include <vector>
|
||||
|
||||
template<typename Value_t>
|
||||
struct FunctionParserBase<Value_t>::Data
|
||||
{
|
||||
unsigned referenceCounter;
|
||||
|
||||
unsigned numVariables;
|
||||
std::string variablesString;
|
||||
FUNCTIONPARSERTYPES::namePtrsType<Value_t> namePtrs;
|
||||
|
||||
struct FuncPtrData
|
||||
{
|
||||
union
|
||||
{
|
||||
FunctionPtr funcPtr;
|
||||
FunctionParserBase<Value_t>* parserPtr;
|
||||
};
|
||||
unsigned params;
|
||||
};
|
||||
|
||||
std::vector<FuncPtrData> FuncPtrs;
|
||||
std::vector<FuncPtrData> FuncParsers;
|
||||
|
||||
std::vector<unsigned> ByteCode;
|
||||
std::vector<Value_t> Immed;
|
||||
#ifndef FP_USE_THREAD_SAFE_EVAL
|
||||
std::vector<Value_t> Stack;
|
||||
// Note: When Stack exists,
|
||||
// Stack.size() and StackSize are mutually redundant.
|
||||
#endif
|
||||
unsigned StackSize;
|
||||
|
||||
Data();
|
||||
Data(const Data&);
|
||||
Data& operator=(const Data&); // not implemented on purpose
|
||||
~Data();
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "fpaux.h"
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file hash.h
|
||||
* @author Thomas Lewiner
|
||||
* @version
|
||||
* @date
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#ifndef _HASH_H_
|
||||
#define _HASH_H_
|
||||
|
||||
// may be overridden by the preprocessor
|
||||
#ifndef USE_HASH_PTR
|
||||
# define USE_HASH_PTR 1
|
||||
#endif // USE_HASH_PTR
|
||||
|
||||
// may be overridden by the preprocessor
|
||||
#ifndef HASH_BITS
|
||||
# define HASH_BITS 22
|
||||
#endif // HASH_BITS
|
||||
|
||||
#ifndef NON_HASH_BITS
|
||||
# define NON_HASH_BITS 22
|
||||
#endif // HASH_BITS
|
||||
|
||||
|
||||
|
||||
|
||||
#if USE_HASH_PTR
|
||||
|
||||
// #define HASH_HAS_ERASE 1
|
||||
# include "hash_ptr.h"
|
||||
|
||||
#else // USE_HASH_PTR
|
||||
|
||||
# undef HASH_HAS_ERASE
|
||||
# include "hash_noptr.h"
|
||||
|
||||
#endif // USE_HASH_PTR
|
||||
|
||||
|
||||
#endif // _HASH_H_
|
||||
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @file hash_noptr.h
|
||||
* @author Thomas Lewiner
|
||||
* @version
|
||||
* @date
|
||||
*
|
||||
* @brief Hash table without pointers
|
||||
*
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#ifndef _HASH_H_
|
||||
# error This header should not be included directly! include hash.h instead
|
||||
#endif // _HASH_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdlib.h> // memset
|
||||
|
||||
#include "morton.h"
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Class hash
|
||||
template < typename Data > class Hash
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
public:
|
||||
typedef uint cntr ;
|
||||
// static const cntr HASH_BITS = 16 ;
|
||||
// static const cntr NON_HASH_BITS = 64-HASH_BITS ;
|
||||
static const cntr HASH_SIZE = ((cntr)1<<HASH_BITS) ;
|
||||
static const cntr HASH_MASK = HASH_SIZE-1 ;
|
||||
static const cntr SKIP_MINI = 11 ;
|
||||
static const cntr SKIP_BITS = 3 ;
|
||||
static const cntr SKIP_MASK = ((cntr)1<<SKIP_BITS)-1 ;
|
||||
|
||||
typedef struct { Key key ; Data data ; } KeyData ;
|
||||
static KeyData KD_INV ;
|
||||
|
||||
protected:
|
||||
// KeyData _hash[HASH_SIZE] ;
|
||||
KeyData *_hash ; // allocate dynamically since stack memory is limited
|
||||
|
||||
public:
|
||||
// Constructor & Desctructor
|
||||
Hash () { _hash = new KeyData[HASH_SIZE] ; reset() ; }
|
||||
~Hash () { delete [] _hash ; }
|
||||
|
||||
void reset() { memset( _hash, KEY_INV, HASH_SIZE*sizeof(KeyData) ) ; KD_INV.key = KEY_INV ; }
|
||||
|
||||
inline cntr hash( Key k ) const ;
|
||||
|
||||
cntr size() const
|
||||
{
|
||||
cntr s = 0 ;
|
||||
cntr n = HASH_SIZE ;
|
||||
KeyData *ptr = _hash ;
|
||||
for( ; n > 0 ; --n, ++ptr )
|
||||
s += ( ptr->key != KEY_INV ) ;
|
||||
return s ;
|
||||
}
|
||||
|
||||
bool insert( KeyData d )
|
||||
{
|
||||
cntr h = hash( d.key ) ;
|
||||
KeyData *p = _hash + h ;
|
||||
const cntr skip = ((d.key>>HASH_BITS) & SKIP_MASK) + SKIP_MINI ;
|
||||
cntr overflow = skip ;
|
||||
while( p->key != KEY_INV && p->key != d.key )
|
||||
{ // collision
|
||||
h += skip ;
|
||||
if( h < HASH_SIZE )
|
||||
p += skip ;
|
||||
else
|
||||
{
|
||||
h &= HASH_MASK ;
|
||||
p = _hash + h ;
|
||||
if( !(overflow--) )
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
*p = d ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
const KeyData operator[] ( Key k ) const
|
||||
{
|
||||
cntr h = hash( k ) ;
|
||||
const KeyData *p = _hash + h ;
|
||||
const cntr skip = ((k>>HASH_BITS) & SKIP_MASK) + SKIP_MINI ;
|
||||
cntr overflow = skip ;
|
||||
while( p->key != k && p->key != KEY_INV )
|
||||
{ // collision
|
||||
h += skip ;
|
||||
if( h < HASH_SIZE )
|
||||
p += skip ;
|
||||
else
|
||||
{
|
||||
h &= HASH_MASK ;
|
||||
p = _hash + h ;
|
||||
if( !(overflow--) )
|
||||
return KD_INV ;
|
||||
}
|
||||
}
|
||||
return *p ;
|
||||
}
|
||||
|
||||
KeyData &operator[] ( Key k )
|
||||
{
|
||||
cntr h = hash( k ) ;
|
||||
KeyData *p = _hash + h ;
|
||||
const cntr skip = ((k>>HASH_BITS) & SKIP_MASK) + SKIP_MINI ;
|
||||
cntr overflow = skip ;
|
||||
while( p->key != k && p->key != KEY_INV )
|
||||
{ // collision
|
||||
h += skip ;
|
||||
if( h < HASH_SIZE )
|
||||
p += skip ;
|
||||
else
|
||||
{
|
||||
h &= HASH_MASK ;
|
||||
p = _hash + h ;
|
||||
if( !(overflow--) )
|
||||
return KD_INV ;
|
||||
}
|
||||
}
|
||||
return *p ;
|
||||
}
|
||||
|
||||
|
||||
bool contains( Key k ) const { return (*this)[k].key == k ; }
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
// iterator
|
||||
public :
|
||||
/// iterator
|
||||
class iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
iterator( Hash<Data> &hash_, cntr id_ = 0 ) : _ptr(hash_._hash+id_), _last(hash_._hash+HASH_SIZE) { while( _ptr != _last && _ptr->key == KEY_INV ) ++_ptr ; }
|
||||
|
||||
/// destructor
|
||||
~iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
iterator( const iterator &it ) : _ptr(it._ptr), _last(it._last) {}
|
||||
|
||||
/// assignment operator
|
||||
iterator &operator = ( const iterator &it )
|
||||
{ _ptr = it._ptr; _last = it._last; return *this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const iterator &it ) const { return _ptr == it._ptr ; }
|
||||
/// inequality operator
|
||||
inline bool operator !=( const iterator &it ) const { return _ptr != it._ptr ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _ptr != _last ; }
|
||||
|
||||
/// key accessor
|
||||
inline const Key &key() const { return _ptr->key ; }
|
||||
|
||||
/// value accessor
|
||||
inline const Data &operator * () const { return _ptr->data ; }
|
||||
|
||||
/// value accessor
|
||||
inline Data &operator * () { return _ptr->data ; }
|
||||
|
||||
/// accesses the next position
|
||||
inline iterator &operator ++() { while( (++_ptr != _last) && _ptr->key == KEY_INV ) ; return *this ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
KeyData *_ptr ; ///< position pointer
|
||||
const KeyData *_last ; ///< last position pointer
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
// const_iterator
|
||||
public :
|
||||
/// const_iterator
|
||||
class const_iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
const_iterator( const Hash<Data> &hash_, cntr id_ = 0 ) : _ptr(hash_._hash+id_), _last(hash_._hash+HASH_SIZE) { while( _ptr != _last && _ptr->key == KEY_INV ) ++_ptr ; }
|
||||
|
||||
/// destructor
|
||||
~const_iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
const_iterator( const const_iterator &it ) : _ptr(it._ptr), _last(it._last) {}
|
||||
|
||||
/// assignment operator
|
||||
const_iterator &operator = ( const const_iterator &it )
|
||||
{ _ptr = it._ptr; _last = it._last; return *this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const const_iterator &it ) const { return _ptr == it._ptr ; }
|
||||
/// inequality operator
|
||||
inline bool operator !=( const const_iterator &it ) const { return _ptr != it._ptr ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _ptr != _last ; }
|
||||
|
||||
/// key accessor
|
||||
inline const Key &key() const { return _ptr->key ; }
|
||||
|
||||
/// value accessor
|
||||
inline const Data &operator * () const { return _ptr->data ; }
|
||||
|
||||
/// accesses the next position
|
||||
inline const_iterator &operator ++() { while( (++_ptr != _last) && _ptr->key == KEY_INV ) ; return *this ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
const KeyData * _ptr ; ///< position pointer
|
||||
const KeyData * const _last ; ///< last position pointer
|
||||
};
|
||||
|
||||
public :
|
||||
/// Node iterator creation
|
||||
iterator begin( cntr id = 0 ) { return iterator( *this, id ) ; }
|
||||
/// Node const iterator creation
|
||||
const_iterator cbegin( cntr id = 0 ) { return const_iterator( *this, id ) ; }
|
||||
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
/// hash function specification: no inversion
|
||||
template <> inline Hash<real >::cntr Hash<real >::hash( Key k ) const { return k & HASH_MASK ; }
|
||||
|
||||
/// hash function specification: inversion
|
||||
template <> inline Hash<Level>::cntr Hash<Level>::hash( Key k ) const { return (k>>NON_HASH_BITS) & HASH_MASK ; }
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,352 @@
|
||||
/**
|
||||
* \file hash_octree.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* Octree structure with hashtable and hierarchical operations
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "mlist.h"
|
||||
#include "cube.h"
|
||||
#include "hash.h"
|
||||
#include "MarchingCubes.h"
|
||||
#include "mc_draw.h"
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// HashOctree
|
||||
/// \class HashOctree HashOctree.h
|
||||
class HashOctree
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// forward declaration
|
||||
public:
|
||||
class geom_cell ;
|
||||
class cell_iterator ;
|
||||
class leaf_iterator ;
|
||||
|
||||
// Elements
|
||||
protected:
|
||||
/// Octree cell data structure
|
||||
typedef Hash<real> HashField ;
|
||||
|
||||
/// Hashtable of the octree nodes
|
||||
HashField _hash ;
|
||||
|
||||
/// Maximal level of the octree (for find_adjacent)
|
||||
Level _max_level ;
|
||||
|
||||
/// Maximal field of the octree
|
||||
real _max_field ;
|
||||
|
||||
/// Isosurface
|
||||
MarchingCubes _mc ;
|
||||
|
||||
/// Isosurface Draw
|
||||
MC_Draw _mc_draw ;
|
||||
|
||||
/// Dual run memory consumption
|
||||
uint _dual_temp_memory ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs a octree with and empty root
|
||||
HashOctree() { init() ; }
|
||||
|
||||
/// Destructor: Free memory
|
||||
~HashOctree() { clear() ; }
|
||||
|
||||
|
||||
/// Create the root
|
||||
void init() ;
|
||||
|
||||
/// Memory cleaning
|
||||
void clear() { clear_octree() ; _mc.clean_all() ; }
|
||||
|
||||
/// Delete the content of the octree
|
||||
void clear_octree() ;
|
||||
|
||||
/// Check that only the leaves have data
|
||||
bool check () ;
|
||||
|
||||
/// Prints statistics about the octree
|
||||
void stats() ;
|
||||
|
||||
|
||||
/// Return the maximal level of the octree
|
||||
Level max_level() const { return _max_level ; }
|
||||
|
||||
/// Return the maximal field of the octree
|
||||
real max_field() const { return _max_field ; }
|
||||
|
||||
/// Return the isosurface
|
||||
MarchingCubes &mc() { return _mc ; }
|
||||
|
||||
/// Return the isosurface draw
|
||||
MC_Draw &mc_draw() { return _mc_draw ; }
|
||||
|
||||
/// set the values of each leaf from the implicit function
|
||||
bool set_impl( data_access *ref = NULL ) ;
|
||||
|
||||
/// Refine the octree according to the data access
|
||||
bool refine( data_access *ref = NULL ) ;
|
||||
|
||||
/// Adapt the octree according to the data access
|
||||
bool adapt( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the octree with wireframe
|
||||
bool draw_wire() ;
|
||||
|
||||
/// Draw the octree with dots
|
||||
bool draw_centers() ;
|
||||
|
||||
/// Dual function type
|
||||
typedef bool hash_dual_walker( HashOctree &fo, Key *keys ) ;
|
||||
|
||||
/// Walk on the dual cubes
|
||||
bool dual_cubes_walk( hash_dual_walker &walker ) ;
|
||||
|
||||
/// Build the isosurface using dual marching cubes
|
||||
bool build_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the isosurface on-the-fly using dual marching cubes
|
||||
bool direct_draw_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the dual octree with wireframe
|
||||
bool draw_dual() ;
|
||||
|
||||
/// Do nothing, just for dual generation timing
|
||||
bool dual_timing() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterators
|
||||
public:
|
||||
/// Create an iterator traversing the tree from the root
|
||||
inline cell_iterator cells_begin() { return cell_iterator( *this ) ; }
|
||||
|
||||
/// Create an iterator traversing the leaves of the tree from the root
|
||||
inline leaf_iterator leaves_begin() { return leaf_iterator( *this ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// search operations
|
||||
public:
|
||||
/// Find cells of the octree at a given position
|
||||
bool find_leaf( real x, real y, real z, geom_cell &cell ) const ;
|
||||
|
||||
/// Find cells of the octree inside a given box of center x,y,z and half side r
|
||||
bool find_radius( real x, real y, real z, real r, List<geom_cell> &cells ) const ;
|
||||
|
||||
/// Find adjacent cells of the octree to a given cell
|
||||
bool adjacent( const geom_cell &cell, List<geom_cell> &cells ) const ;
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( Key k ) const { return !is_inv( _hash[k].data ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// I/O
|
||||
public:
|
||||
|
||||
/// Draws the intersecting cells of a plane with the octree with color
|
||||
void draw_plane ( real nx, real ny, real nz, real d ) ;
|
||||
|
||||
/// Draws the intersection of a plane with the octree with color
|
||||
void draw_slice ( real nx, real ny, real nz, real d, float alpha ) ;
|
||||
|
||||
/// Draws the isosurface of level l inside the dual graph
|
||||
void draw_iso () { _mc.draw_surf() ; }
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Iterator Cell
|
||||
public :
|
||||
/// Auxiliary structure to traverse the octree
|
||||
class geom_cell : public Cube
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class HashOctree ;
|
||||
|
||||
protected:
|
||||
Key _key ; ///< octree cell
|
||||
real _field ; ///< field associated to the cell
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs an iterator from a cell
|
||||
geom_cell( Key key_ = KEY_INV, real field_ = R_INV ) : Cube(key2cube(key_)), _key(key_), _field(field_) {}
|
||||
|
||||
/// Destructor
|
||||
~geom_cell() {}
|
||||
|
||||
/// Copy constructor
|
||||
geom_cell( const geom_cell &i ) : Cube(i), _key(i._key), _field(i._field) {}
|
||||
|
||||
/// Assignment operator
|
||||
geom_cell &operator = ( const geom_cell &i )
|
||||
{ Cube::operator=(i) ; _key = i._key ; _field = i._field ; return *this; }
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Public constant accessors
|
||||
public :
|
||||
/// key const accessor
|
||||
inline Key key() const { return _key ; }
|
||||
/// key accessor
|
||||
inline Key &key() { return _key ; }
|
||||
|
||||
/// id const accessor
|
||||
inline real operator*() const { return _field ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Tests
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const geom_cell &i ) const { return key() == i.key() ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const geom_cell &i ) const { return key() != i.key() ; }
|
||||
|
||||
/// leaf test
|
||||
inline bool is_leaf() const { return !is_inv(*(*this)) ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return key() != KEY_INV ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// sons
|
||||
inline bool sons( geom_cell *s /*[8]*/, const HashField &hash )
|
||||
{
|
||||
if( is_leaf() ) return false ;
|
||||
|
||||
Key k = _key << 3 ;
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
s[i]._key = k | i ;
|
||||
s[i]._field = hash[k|i].data ;
|
||||
(Cube&)s[i] = key2cube(s[i]._key) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
/// get son from side i
|
||||
inline bool son( int i , geom_cell &s, const HashField &hash )
|
||||
{
|
||||
if( is_leaf() ) return false ;
|
||||
s._key = (key() << 3) | i ;
|
||||
s._field = hash[s._key].data ;
|
||||
(Cube&)s = key2cube(s._key) ;
|
||||
return true ;
|
||||
}
|
||||
};
|
||||
|
||||
const geom_cell geom_root() const { const Key root_key = 1 ; return geom_cell( root_key, _hash[root_key].data ) ; }
|
||||
const geom_cell geom_key ( Key k ) const { return geom_cell( k, _hash[k].data ) ; }
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Cell Iterator
|
||||
public :
|
||||
/// Octree cell iterator : Traverse the octree returning basic information on the cells
|
||||
class cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class HashOctree ;
|
||||
|
||||
protected:
|
||||
/// Octree traversal iterator
|
||||
HashField::iterator _it ;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor : Constructs an iterator from a cell
|
||||
cell_iterator( HashOctree &o ) : _it( o._hash.begin() ) {}
|
||||
|
||||
/// Destructor
|
||||
~cell_iterator() {}
|
||||
|
||||
/// Copy constructor
|
||||
cell_iterator( const cell_iterator &i ) : _it(i._it) {}
|
||||
|
||||
/// Assignment operator
|
||||
cell_iterator &operator = ( const cell_iterator &i )
|
||||
{ _it = i._it; return *this; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const cell_iterator &i ) const { return _it == i._it ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const cell_iterator &i ) const { return _it != i._it ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _it() ; }
|
||||
|
||||
/// next position
|
||||
inline cell_iterator &operator ++() { ++_it ; return *this ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
// cell accessor
|
||||
inline geom_cell top() const { return geom_cell( key(), *_it ) ; }
|
||||
|
||||
/// id accessor
|
||||
inline real &operator*() { return *_it ; }
|
||||
|
||||
/// level accessor
|
||||
inline Level lv() { return key_level(_it.key()) ; }
|
||||
|
||||
/// size accessor
|
||||
inline real sz() { return Cube(0,0,0,lv()).sz() ; }
|
||||
|
||||
/// key accessor
|
||||
inline Key key() const { return _it.key() ; }
|
||||
|
||||
/// points accessor
|
||||
inline bool is_leaf() const { return !is_inv(*_it) ; }
|
||||
|
||||
/// Draws the cell wire with opengl
|
||||
void draw_wire () const { top().draw_wire () ; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// Octree leaf iterator : Traverse the octree returning basic information on the leaves
|
||||
class leaf_iterator : public cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
public :
|
||||
leaf_iterator( HashOctree &o ) : cell_iterator( o )
|
||||
{ if( (*this)() && !this->is_leaf() ) ++(*this) ; }
|
||||
|
||||
|
||||
/// next position
|
||||
inline leaf_iterator &operator ++()
|
||||
{
|
||||
cell_iterator &it = *this ;
|
||||
do ++it ; while ( it() && !it.is_leaf() ) ;
|
||||
return *this ;
|
||||
}
|
||||
} ;
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
@ -0,0 +1,292 @@
|
||||
/**
|
||||
* @file hash_ptr.h
|
||||
* @author Thomas Lewiner
|
||||
* @version
|
||||
* @date
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#ifndef _HASH_H_
|
||||
# error This header should not be included directly! include hash.h instead
|
||||
#endif // _HASH_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#define HASH_HAS_ERASE 1
|
||||
|
||||
#include <stdlib.h> // memset
|
||||
#include <string.h>
|
||||
#include <stdio.h> //printf
|
||||
#include "mlist.h" // memset
|
||||
|
||||
#include "morton.h"
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Class hash
|
||||
template < typename Data > class Hash
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
public:
|
||||
typedef uint cntr ;
|
||||
// static const cntr HASH_BITS = 16 ;
|
||||
// static const cntr NON_HASH_BITS = 64-HASH_BITS ;
|
||||
static const cntr HASH_SIZE = ((cntr)1<<HASH_BITS) ;
|
||||
static const cntr HASH_MASK = HASH_SIZE-1 ;
|
||||
|
||||
// Bucket associative data
|
||||
typedef struct KeyData
|
||||
{
|
||||
Key key ;
|
||||
Data data ;
|
||||
|
||||
/// comparison based on the key only
|
||||
bool operator==( const struct KeyData& rhs) const { return key == rhs.key ; }
|
||||
|
||||
/// comparison based on the key only
|
||||
bool operator!=( const struct KeyData& rhs) const { return key != rhs.key ; }
|
||||
|
||||
} KeyData ;
|
||||
static KeyData KD_INV ;
|
||||
|
||||
class iterator ;
|
||||
|
||||
public:
|
||||
typedef List<KeyData> KeyBucket ;
|
||||
typedef typename KeyBucket::iterator keybucket_iterator ;
|
||||
typedef typename KeyBucket::const_iterator keybucket_const_iterator ;
|
||||
|
||||
protected:
|
||||
// KeyBucket _hash[HASH_SIZE] ;
|
||||
KeyBucket *_hash ; // allocate dynamically since stack memory is limited
|
||||
|
||||
public:
|
||||
// Constructor & Desctructor
|
||||
Hash () { _hash = new KeyBucket[HASH_SIZE] ; }
|
||||
~Hash () { delete [] _hash ; }
|
||||
|
||||
void reset()
|
||||
{
|
||||
cntr n = HASH_SIZE ;
|
||||
KeyBucket *ptr = _hash ;
|
||||
for( ; n > 0 ; --n, ++ptr )
|
||||
{
|
||||
(*ptr).clear() ;
|
||||
}
|
||||
KD_INV.key = KEY_INV ;
|
||||
}
|
||||
|
||||
cntr size() const
|
||||
{
|
||||
cntr s = 0 ;
|
||||
cntr n = HASH_SIZE ;
|
||||
KeyBucket *ptr = _hash ;
|
||||
for( ; n > 0 ; --n, ++ptr )
|
||||
s += ptr->size() ;
|
||||
return s ;
|
||||
}
|
||||
|
||||
void stats() const
|
||||
{
|
||||
static const cntr MAX_COLLISION = 32 ;
|
||||
cntr colls[MAX_COLLISION] ;
|
||||
memset( colls, 0, MAX_COLLISION*sizeof(cntr) ) ;
|
||||
KeyBucket *ptr = _hash ;
|
||||
for( cntr n = HASH_SIZE ; n > 0 ; --n, ++ptr )
|
||||
{
|
||||
cntr s = ptr->size() ;
|
||||
if( s >= MAX_COLLISION ) s = MAX_COLLISION-1 ;
|
||||
++colls[s] ;
|
||||
}
|
||||
|
||||
printf( "Hashtable collisions: [\t") ;
|
||||
for( cntr n = 0 ; n < MAX_COLLISION ; ++n )
|
||||
printf( "%d\t", colls[n] ) ;
|
||||
printf( "\t]\n") ;
|
||||
}
|
||||
|
||||
inline cntr hash( Key k ) const ;
|
||||
|
||||
bool insert( KeyData d )
|
||||
{
|
||||
cntr h = hash( d.key ) ;
|
||||
KeyBucket &l = _hash[h] ;
|
||||
return l.insert_unique( d ) ;
|
||||
}
|
||||
|
||||
const KeyData operator[] ( Key k ) const
|
||||
{
|
||||
cntr h = hash( k ) ;
|
||||
KeyData kd ; kd.key = k ;
|
||||
keybucket_const_iterator it = _hash[h].cfind( kd ) ;
|
||||
if( !it() ) return KD_INV ;
|
||||
return *it ;
|
||||
}
|
||||
|
||||
KeyData &operator[] ( Key k )
|
||||
{
|
||||
cntr h = hash( k ) ;
|
||||
KeyData kd ; kd.key = k ;
|
||||
keybucket_iterator it = _hash[h].find( kd ) ;
|
||||
if( !it() ) return KD_INV ;
|
||||
return *it ;
|
||||
}
|
||||
|
||||
KeyData erase( Key k )
|
||||
{
|
||||
cntr h = hash( k ) ;
|
||||
KeyData kd ; kd.key = k ;
|
||||
if( _hash[h].remove( kd ) )
|
||||
return kd ;
|
||||
return KD_INV ;
|
||||
}
|
||||
|
||||
bool contains( Key k ) const { return (*this)[k].key == k ; }
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
// iterators
|
||||
public :
|
||||
/// iterator
|
||||
class iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
iterator( Hash<Data> &hash_, Key id_ = 0 ) : _ptr(hash_._hash+id_), _last(hash_._hash+HASH_SIZE)
|
||||
{
|
||||
while( _ptr != _last && _ptr->empty() )
|
||||
++_ptr ;
|
||||
if( _ptr != _last )
|
||||
_l_it = _ptr->begin() ;
|
||||
}
|
||||
|
||||
/// destructor
|
||||
~iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
iterator( const iterator &it ) : _ptr(it._ptr), _last(it._last), _l_it(it._l_it) {}
|
||||
|
||||
/// assignment operator
|
||||
iterator &operator = ( const iterator &it )
|
||||
{ _ptr = it._ptr; _last = it._last; _l_it = it._l_it ; return *this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const iterator &it ) const { return _ptr == it._ptr && _l_it == it._l_it ; }
|
||||
/// inequality operator
|
||||
inline bool operator !=( const iterator &it ) const { return _ptr != it._ptr || _l_it != it._l_it ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _ptr != _last ; }
|
||||
|
||||
/// key accessor
|
||||
inline const Key &key() const { return (*_l_it).key ; }
|
||||
|
||||
/// value accessor
|
||||
inline const Data &operator * () const { return (*_l_it).data ; }
|
||||
|
||||
/// value accessor
|
||||
inline Data &operator * () { return (*_l_it).data ; }
|
||||
|
||||
/// accesses the next position
|
||||
inline iterator &operator ++() {
|
||||
if( !(++_l_it)() )
|
||||
{
|
||||
while( _ptr != _last && (*(++_ptr)).empty() ) ;
|
||||
if( _ptr != _last )
|
||||
_l_it = _ptr->begin() ;
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
KeyBucket *_ptr ; ///< position pointer
|
||||
const KeyBucket *_last ; ///< last position pointer
|
||||
keybucket_iterator _l_it ; ///< list iterator inside a bucket
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
// const_iterator
|
||||
public :
|
||||
/// const_iterator
|
||||
class const_iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
const_iterator( Hash<Data> &hash_, Key id_ = 0 ) : _ptr(hash_._hash+id_), _last(hash_._hash+HASH_SIZE)
|
||||
{
|
||||
while( _ptr != _last && _ptr->empty() )
|
||||
++_ptr ;
|
||||
if( _ptr != _last )
|
||||
_l_it = _ptr->cbegin() ;
|
||||
}
|
||||
|
||||
/// destructor
|
||||
~const_iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
const_iterator( const const_iterator &it ) : _ptr(it._ptr), _last(it._last), _l_it(it._l_it) {}
|
||||
|
||||
/// assignment operator
|
||||
const_iterator &operator = ( const const_iterator &it )
|
||||
{ _ptr = it._ptr; _last = it._last; _l_it = it._l_it ; return *this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const const_iterator &it ) const { return _ptr == it._ptr && _l_it == it._l_it ; ; }
|
||||
/// inequality operator
|
||||
inline bool operator !=( const const_iterator &it ) const { return _ptr != it._ptr || _l_it != it._l_it ; ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _ptr != _last ; }
|
||||
|
||||
/// key accessor
|
||||
inline const Key &key() const { return (*_l_it).key ; }
|
||||
|
||||
/// value accessor
|
||||
inline const Data &operator * () const { return (*_l_it).data ; }
|
||||
|
||||
/// accesses the next position
|
||||
inline const_iterator &operator ++() {
|
||||
if( !(++_l_it)() )
|
||||
{
|
||||
while( _ptr != _last && (*(++_ptr)).empty() ) ;
|
||||
if( _ptr != _last )
|
||||
_l_it = _ptr->cbegin() ;
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
const KeyBucket * _ptr ; ///< position pointer
|
||||
const KeyBucket * const _last ; ///< last position pointer
|
||||
keybucket_const_iterator _l_it ; ///< list iterator inside a bucket
|
||||
};
|
||||
|
||||
public :
|
||||
/// Node iterator creation
|
||||
iterator begin( cntr id = 0 ) { return iterator( *this, id ) ; }
|
||||
/// Node const iterator creation
|
||||
const_iterator cbegin( cntr id = 0 ) { return const_iterator( *this, id ) ; }
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
/// hash function specification: no inversion
|
||||
template <> inline Hash<real >::cntr Hash<real >::hash( Key k ) const { return k & HASH_MASK ; }
|
||||
|
||||
/// hash function specification: inversion
|
||||
template <> inline Hash<Level>::cntr Hash<Level>::hash( Key k ) const { return (k>>NON_HASH_BITS) & HASH_MASK ; }
|
||||
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file implfuns.h
|
||||
* @author Thomas Lewiner
|
||||
* @version
|
||||
* @date
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#define NFUNS 38
|
||||
|
||||
// implicit functions
|
||||
const char *fun_list[NFUNS] =
|
||||
{
|
||||
"Type Formula" ,
|
||||
"Sphere" ,
|
||||
"Ellipsoid" ,
|
||||
"Hyperboloid" ,
|
||||
"Plane" ,
|
||||
"Cubic" ,
|
||||
"Cushin" ,
|
||||
"Cassini" ,
|
||||
"Tangle cube" ,
|
||||
"Chair" ,
|
||||
"Cyclide" ,
|
||||
"2 Spheres" ,
|
||||
"2 Torii" ,
|
||||
"Heart" ,
|
||||
"Smile" ,
|
||||
"Spheres in" ,
|
||||
"Spheres dif" ,
|
||||
"Cross cap" ,
|
||||
"Weird cube" ,
|
||||
"Klein bottle" ,
|
||||
"Steiner's roman" ,
|
||||
"Hunt's surface" ,
|
||||
"Cayley cubic" ,
|
||||
"Clebsch cubic" ,
|
||||
"Barth sextic" ,
|
||||
"Barth decic" ,
|
||||
"Steiner relative",
|
||||
"Mitre" ,
|
||||
"Glob tear" ,
|
||||
"Piri tear" ,
|
||||
"Gumdrop torus" ,
|
||||
"Bretzel" ,
|
||||
"Blob" ,
|
||||
"Bifolia" ,
|
||||
"Lemniscate" ,
|
||||
"Planes" ,
|
||||
"Cylinders" ,
|
||||
"Torus" ,
|
||||
} ;
|
||||
|
||||
// implicit functions
|
||||
const char *fun_def [NFUNS] =
|
||||
{
|
||||
/* Type Formula */ "f(x,y,z)",
|
||||
/* Sphere */ "4*x^2-4*x+2.51+4*y^2-4*y+4*z^2-4*z",
|
||||
/* Ellipsoid */ "8*x^2-8*x+3.51+4*y^2-4*y+4*z^2-4*z",
|
||||
/* Hyperboloid */ "8*x^2-8*x-.1-4*y^2+4*y-4*z^2+4*z",
|
||||
/* Plane */ "x+y+z",
|
||||
/* Cubic */ "16*y^2-16*y+10-64*x^3+96*x^2-44*x",
|
||||
/* Cushin */ "112.5*z+81*y*z^2+51.75*x+119.25*y-135*y*z-38.8125+162*x^3-81*x^4+162*y^3+216*z^3-81*y^4-81*z^4-162*x*y-132.75*x^2-200.25*y^2-220.5*z^2+162*x*y^2+81*x*z-81*x*z^2-81*x^2*z-162*x^2*y^2-81*y^2*z^2+162*x^2*y+135*y^2*z+81*z^2*x^2",
|
||||
/* Cassini */ "-167.6778*z-267.2672*y*z^2-167.6778*x-205.1322*y+267.2672*y*z+59.74405625-267.2672*x^3+133.6336*x^4-267.2672*y^3-267.2672*z^3+133.6336*y^4+133.6336*z^4+267.2672*x*y+301.3114*x^2+338.7658*y^2+301.3114*z^2-267.2672*x*y^2+267.2672*x*z-267.2672*x*z^2-267.2672*x^2*z+267.2672*x^2*y^2+267.2672*y^2*z^2-267.2672*x^2*y-267.2672*y^2*z+267.2672*z^2*x^2",
|
||||
/* Tangle cube */ "-468*z-468*x-468*y+1296*y^4+1764*x^2+1764*y^2+1764*z^2+1296*z^4-2592*x^3+119.8-2592*y^3+1296*x^4-2592*z^3",
|
||||
/* Chair */ "-18250*z-36000*y*z^2-2250*x-18250*y+52000*y*z+4626.5625-20000*x^3+10000*x^4-20000*y^3-4000*z^3+10000*y^4+2000*z^4-12000*x*y+12250*x^2+28250*y^2+20250*z^2+12000*x*y^2+20000*x*z-36000*x*z^2-20000*x^2*z-12000*x^2*y^2+36000*y^2*z^2+12000*x^2*y-52000*y^2*z+36000*z^2*x^2",
|
||||
/* Cyclide */ "-11.23227514*x^2-6.0015984*x^4-6.0015984*y^4-6.0015984*z^4-13.56959251*z^2+12.0031968*y*z^2+12.0031968*z^3+6.027648307*x+7.256824512*y-13.25842291*y^2+12.0031968*y^3+12.0031968*x^2*z-9.79449408*x*y+9.79449408*x*y^2-9.79449408*x*z+9.79449408*x*z^2-12.0031968*x^2*y^2-12.0031968*y^2*z^2-12.0031968*z^2*x^2+7.567994112*z+12.0031968*y^2*z+12.0031968*x^2*y-12.0031968*y*z-2.289346823+9.79449408*x^3",
|
||||
/* 2 Spheres */ "(40000*x^2-52400*x+48853+40000*y^2-52400*y+40000*z^2-52400*z)*(4000*x^2-2800*x+1207+4000*y^2-2800*y+4000*z^2-2800*z)",
|
||||
/* 2 Torii */ "-6.929911075*x -6.559601218*z -40.61779736*z^3 +56.91300912*z^4 -17.17986918*y^7 +4.294967296*y^8 -55.95084095*z^5 +38.69346103*z^6 +38.69346103*x^6 +4.294967296*z^8 -17.17986918*x^7 +37.0828483*y^6 +4.294967296*x^8 -17.17986918*z^7 +20.40667127*z^2 -51.53960755*y^3*z^4 -89.2368375*x^4*y -41.69153918*x^3 +51.53960755*x*z^5 -51.11900275*y^5 -51.53960755*x^2*z^5 -51.53960755*y^5*z^2 +92.57432908*x^3*y +87.74249087*y^3*z -5.938337301*y +17.84876088*y^2 -35.13389168*y^3 +1.174097113 -51.53960755*y^2*z^5 +51.53960755*x^5*y -62.4313134*x*y^2 +50.14452444*y^4 +51.53960755*y^5*z -67.27041824*x^2*z -62.06100354*y*z^2 +114.4697704*y^2*z^4 +17.17986918*y^2*z^6 +88.81623269*y^3*x +112.8591576*y^4*z^2 +114.4697704*x^4*y^2 -87.08935385*y^4*z +25.76980378*y^4*z^4 +103.0792151*x^3*z^3 +103.0792151*y^3*z^3 -87.08935385*y^4*x +112.8591576*y^4*x^2 +90.42684543*y*z^3 +51.53960755*y*z^5 +116.0803831*x^2*z^4 +17.17986918*x^2*z^6 -146.2614203*x^3*z^2 +94.72181273*x^3*z +25.76980378*x^4*z^4 -51.53960755*x^4*z^3 -88.16309567*y*z^4 +25.43751542*y*z -90.31057932*x*z^4 -90.31057932*x^4*z +116.0803831*x^4*z^2 -139.2820984*y^3*z^2 -17.17986918*y^6*z -140.3558402*y^3*x^2 +17.17986918*x^6*z^2 +94.72181273*x*z^3 +17.17986918*y^6*z^2 -143.0401948*x^3*y^2 -17.17986918*x^6*z -17.17986918*x*z^6 -51.53960755*x^3*z^4 +51.53960755*x^5*z -51.53960755*x^5*z^2 +103.0792151*x^3*y^3 +17.17986918*x^6*y^2 -17.17986918*x^6*y +51.53960755*y^5*x -17.17986918*y*z^6 -51.53960755*y^5*x^2 -17.17986918*y^6*x +17.17986918*y^6*x^2 +25.76980378*x^4*y^4 -143.0401948*y^2*z^3 -146.2614203*x^2*z^3 +26.71500605*x*y +28.49944647*x*z -67.27041824*x*z^2 +125.3614762*x^2*y^2 +123.7508635*y^2*z^2 -60.82070066*y^2*z +131.8111938*z^2*x^2 +21.31385204*x^2 +51.53960755*y^4*z*x +103.0792151*y^2*z^3*x +51.53960755*y^2*z^2*x^4 -51.53960755*y^4*z^2*x +103.0792151*y^3*z^2*x -103.0792151*y^2*z^2*x^3 -51.53960755*x^4*y^2*z +103.0792151*x^2*z^3*y -51.53960755*x^2*z^4*y +103.0792151*x^3*y^2*z -51.53960755*y^2*z^4*x +51.53960755*y^4*z^2*x^2 -103.0792151*y^3*z^2*x^2 +51.53960755*y^2*z^4*x^2 -103.0792151*y^2*z^3*x^2 +51.53960755*x*z^4*y +51.53960755*x^4*y*z -51.53960755*y^4*z*x^2 -103.0792151*x^3*y*z -51.53960755*x^4*y*z^2 +103.0792151*x^3*y*z^2 -103.0792151*x*z^3*y -103.0792151*y^3*z*x +103.0792151*y^3*z*x^2 +125.8603256*y*z^2*x -177.3999332*x^2*y*z^2 -177.3999332*x^2*z*y^2 +125.8603256*y^2*z*x -177.3999332*x*y^2*z^2 +228.9395407*y^2*z^2*x^2 -74.32071807*y*z*x +125.8603256*y*z*x^2 -64.41223599*x^2*y -51.53960755*x^5*y^2 +57.44988003*x^4 -55.95084095*x^5 -51.53960755*x^4*y^3 -51.53960755*x^3*y^4 -51.53960755*y^4*z^3",
|
||||
/* Heart */ "-697.347066*z-2684.277024*y*z^2-1347.168628*x-687.693448*y+926.747328*y^2*z^4+3706.989312*y^3*x+926.747328*y^4*z^2+3706.989312*x^4*y^2-926.747328*y^4*z-1853.494656*y^4*x+1853.494656*y^4*x^2+1972.308416*y*z^3+1853.494656*x^2*z^4-7413.978624*x^3*z^2+7413.978624*x^3*z-926.747328*y*z^4+1668.419376*y*z-1853.494656*x*z^4+7413.978624*x^3*y-3706.989312*x^4*z+3706.989312*x^4*z^2+1853.494656*y^3*z-1853.494656*y^3*z^2-3706.989312*y^3*x^2+3718.870688*x*z^3-7413.978624*x^3*y^2-3706.989312*x^4*y-1972.308416*y^2*z^3-3718.870688*x^2*z^3+195.187199+3706.989312*y*z^2*x-3706.989312*x^2*y*z^2-3706.989312*x^2*z*y^2+3706.989312*y^2*z*x-3706.989312*x*y^2*z^2+3706.989312*y^2*z^2*x^2-8788.562432*x^3+10572.59674*x^4-1888.224832*y^3-1920.898616*z^3+1716.401856*y^4+1716.401856*z^4-926.747328*z^5+308.915776*z^6-7413.978624*x^5+2471.326208*x^6-926.747328*y^5+308.915776*y^6+3158.618112*x*y+4505.78674*x^2+1477.347976*y^2+1511.506932*z^2-3706.989312*y*z*x-5012.112768*x*y^2+3706.989312*y*z*x^2+3167.529144*x*z-5029.934832*x*z^2-6874.518456*x^2*z+8719.10208*x^2*y^2+3611.024352*y^2*z^2-6865.607424*x^2*y-2595.166704*y^2*z+8736.924144*z^2*x^2",
|
||||
/* Smile */ "-12348*z-435632*y^3-27216*y*z^2-17834.8125*x-35974.25*y-327680*y^7+733184*y^6-891648*y^4*x+11664*y*z^3+972*x^3*z+21168*y*z+2304*y^3*z+8748*x*z^3+46656*x^6*y^2-58320*x^6*y+5162.816406-1100160*y^3*x^2+11664*y*z^2*x+5184*y^2*z*x-72987.75*x^3+95610.375*x^4-20412*z^3+6561*z^4+65536*y^8-89667*x^5+60507*x^6-26244*x^7+6561*x^8+41910.1875*x^2+23814*z^2+712044*x^2*y^2-257499*x^2*y-18144*y*z*x+3888*y*z*x^2-311040*x^4*y^3+174960*x^5*y-139968*x^5*y^2+622080*x^3*y^3+552960*y^5*x-552960*y^5*x^2-147456*y^6*x+1016064*y^4*x^2+789888*y^3*x+340632*x^3*y-957440*y^5-315900*x^4*y-408060*x*y^2-248832*x^3*y^4+147456*y^6*x^2+124416*x^4*y^4-660960*x^3*y^2+155243*y^2+797792*y^4+447120*x^4*y^2+120591*x*y+15876*x*z-20412*x*z^2-6804*x^2*z+7776*y^2*z^2-12096*y^2*z+4374*z^2*x^2",
|
||||
/* Spheres in */ "-(8*(4*x^2-4*x+3+4*y^2-4*y+4*z^2-4*z))*(-1+sqrt(4*x^2-4*x+3+4*y^2-4*y+4*z^2-4*z))",
|
||||
/* Spheres dif */ "-496*z-4416*y*z^2-560*x-560*y+6912*y^2*z^4+1024*y^2*z^6+9728*y^3*x+7296*y^4*z^2+13056*x^4*y^2-7680*y^4*z-6144*x^4*y^3+1536*y^4*z^4+6144*x^3*z^3+6144*y^3*z^3-9984*y^4*x+13056*y^4*x^2+5760*y*z^3+3072*y*z^5-3072*x^2*z^5+6912*x^2*z^4+1024*x^2*z^6-9472*x^3*z^2+6144*x^5*y-6144*x^5*y^2+7680*x^3*z+1536*x^4*z^4-3072*x^4*z^3-5376*y*z^4-3072*y^3*z^4+4608*y^4*z*x+6144*y^2*z^3*x+3072*y^2*z^2*x^4-3072*y^4*z^2*x+6144*y^3*z^2*x-6144*y^2*z^2*x^3-4608*x^4*y^2*z+6144*x^2*z^3*y-3072*x^2*z^4*y+9216*x^3*y^2*z-3072*y^2*z^4*x+3072*y^4*z^2*x^2-6144*y^3*z^2*x^2+3072*y^2*z^4*x^2-6144*y^2*z^3*x^2+3072*x*z^4*y+4608*x^4*y*z-4608*y^4*z*x^2-9216*x^3*y*z-3072*x^4*y*z^2+6144*x^3*y*z^2-6144*x*z^3*y-9216*y^3*z*x+9216*y^3*z*x^2+2112*y*z-5376*x*z^4+9728*x^3*y-7680*x^4*z+7296*x^4*z^2+7680*y^3*z-9472*y^3*z^2-1536*y^6*z-15872*y^3*x^2+1024*x^6*z^2+5760*x*z^3+1024*y^6*z^2-3072*y^4*z^3-15872*x^3*y^2-1536*x^6*z+3072*x*z^5-1024*x*z^6-3072*x^3*z^4+4608*x^5*z-3072*x^5*z^2+12288*x^3*y^3+2048*x^6*y^2-2048*x^6*y+6144*y^5*x-1024*y*z^6-6144*y^5*x^2+4608*y^5*z-3072*y^5*z^2-9984*x^4*y-2048*y^6*x-6144*x^3*y^4+2048*y^6*x^2+3072*x^4*y^4-8832*y^2*z^3-8832*x^2*z^3-3072*y^2*z^5+96+8448*y*z^2*x-11520*x^2*y*z^2-15360*x^2*z*y^2+10752*y^2*z*x-11520*x*y^2*z^2+14592*y^2*z^2*x^2-3776*x^3+5600*x^4-3776*y^3-2560*z^3+5600*y^4+3440*z^4-2048*y^7+512*y^8-3328*z^5+2304*z^6-5888*x^5+4352*x^6-5888*y^5+256*z^8-2048*x^7+4352*y^6+512*x^8-1024*z^7+2496*x*y+1808*x^2+1808*y^2+1392*z^2-6144*y*z*x-6336*x*y^2+10752*y*z*x^2+2112*x*z-4416*x*z^2-5184*x^2*z+13248*x^2*y^2+8640*y^2*z^2-6336*x^2*y-5184*y^2*z+8640*z^2*x^2",
|
||||
/* Cross cap */ ".4*sqrt(100*x-10)*x^2-0.08*sqrt(100*x-10)*x+0.008*sqrt(100*x-10)+.4*sqrt(100*x-10)*y^2-0.08*sqrt(100*x-10)*y+1.6*sqrt(100*x-10)*z^2-.8*sqrt(100*x-10)*z+.1*sqrt(100*y-10)*y^2-0.02*sqrt(100*y-10)*y+0.001*sqrt(100*y-10)+.4*sqrt(100*y-10)*z^2-.4*sqrt(100*y-10)*z",
|
||||
/* Weird cube */ "59136*z-10240*y^3-10240*x^3+59136*x+59136*y+204800*z^2*x^2+204800*y^2*z^2-23232+204800*x^2*y^2-102400*x^2*y-102400*x^2*z-297216*x*z+128000*z^2-512000*y*z*x^2+128000*x^2+1566720*y*z*x-102400*x*z^2-512000*y*z^2*x-512000*y^2*z*x-102400*z^3-297216*y*z+102400*y^3*x-102400*y*z^2+102400*x^3*z+102400*x^3*y-102400*x*y^2+128000*y^2+102400*y*z^3-297216*x*y+102400*y^3*z-102400*y^2*z+102400*x*z^3",
|
||||
/* Klein bottle */ "-244615.68*y^3-304335.36*x^3-96138.60864*y-786432*z^5-453427.2*y^3*z^2+1139015.68*z^4-139968*y^4*x-255052.8*y^3*x^2+248832*x^4*z^2-248832*x^4*z+33252.70426+46656*x^6+46656*y^6+1051729.92*y^2*z^2+493102.08*x^2*y^2+442368*x^2*z^4-497664*x^3*z^2-403046.4*y*z^4-442368*x*z^4-344176.128*x^2*y-705392.64*x^2*z+497664*y^2*z^2*x^2+480030.72*x*z-484761.6*y*z*x+555332.4032*z^2+453427.2*y*z*x^2+243162.3168*x^2-931184.64*x*z^2+453427.2*y*z^2*x+525312*y^2*z*x-991887.36*z^3+392220.672*y*z+255052.8*y^3*x-779599.872*y*z^2+525312*x^3*z+255052.8*x^3*y-127526.4*y^5-127526.4*x^4*y-366958.08*x*y^2-497664*x*y^2*z^2+262144*z^6-497664*x^2*z*y^2-453427.2*x^2*y*z^2+1106288.64*z^2*x^2-139968*x^5-279936*x^3*y^2-884736*x^2*z^3-120681.6768*x+196337.664*y^2-191443.7632*z+231206.4*y^4+261895.68*x^4-884736*y^2*z^3+806092.8*y*z^3+442368*y^2*z^4+248832*y^4*z^2+139968*x^4*y^2-248832*y^4*z+139968*y^4*x^2+232316.928*x*y+453427.2*y^3*z-623185.92*y^2*z+933888*x*z^3",
|
||||
/* Steiner's roman */ "0.03125*y^2+.125*y*z*x-0.00390625-0.0625*y^2*z-0.0625*y*z^2+0.03125*z^2-0.0625*x^2*z+0.03125*x^2+0.0625*x^2*y^2+0.0625*z^2*x^2+0.0625*y^2*z^2-0.0625*x^2*y-0.0625*x*y^2-0.0625*x*z^2",
|
||||
/* Hunt's surface */ "-321408*y-559872*z^5+1446336*z^4+933120*z^2*x^2-1990656*y^2*z^3+559872*x^4*z^2+1990656*y*z^2*x-559872*x^4*z-1990656*x^3*y^2-3538944*y^3*x^2+1119744*x*z^3-3538944*y^3*z^2-1959552*z^3-1469664*x^3+37719-1119744*x^3*z^2+1119744*x^3*z-1658880*y*z^2-1769472*y^4*z+1990656*y*z^3+1990656*x^3*y+3538944*y^3*z+3428352*y^2*z^2+1534464*x*y+186624*x^6+559872*x^2*z^4-995328*y*z^4-559872*x*z^4-373248*x^2*z-186624*x*z-3334144*y^3+4288512*y^4+1201392*x^4+1990656*y^2*z*x-1990656*x*y^2*z^2+3538944*y^3*x+1769472*y^4*z^2+1769472*y^4*x^2-1769472*y^4*x+1990656*y*z*x^2+802872*x^2-1990656*y*z*x-3303936*x*y^2-2433024*y^2*z-373248*x*z^2+663552*y*z-995328*x^4*y+4299264*x^2*y^2+1990656*y^2*z^2*x^2+186624*z^6-559872*x^5-3145728*y^5+1048576*y^6-2529792*x^2*y-161352*x-229392*z-1990656*x^2*y*z^2-1990656*x^2*z*y^2+1115856*z^2+995328*y^2*z^4+995328*x^4*y^2-1119744*x^2*z^3+1464192*y^2",
|
||||
/* Cayley cubic */ "264-512*z-512*x-512*y+320*y^2-320*x^2*y-320*x^2*z-320*x*y^2+672*x*y-320*x*z^2+672*x*z-320*y^2*z-320*y*z^2+672*y*z+320*z^2+320*x^2",
|
||||
/* Clebsch cubic */ "8154-15300*z-15300*x-15300*y+4176*y^2+4176*z^2+24480*x*y+24480*y*z+5184*x^3-12096*x*y^2-12096*y^2*z-12096*x*z^2-12096*y*z^2+24480*x*z-12096*x^2*y-12096*x^2*z+4176*x^2+3456*y*z*x+5184*z^3+5184*y^3",
|
||||
/* Barth sextic */ "-2846.637681*z-75426.87093*y*z^2-2846.637681*x-2846.637681*y+224595.2132*y^3*z^2+42893.86887*y^2*z^4+85787.73774*y^3*x-42893.86887*y^4*x+42893.86887*y^4*x^2+85787.73774*y*z^3-85787.73774*x^3*z^2+85787.73774*x^3*z-42893.86887*y*z^4+32533.00206*y*z-42893.86887*x^4*z+42893.86887*x^4*z^2-85787.73774*y^3*x^2-85787.73774*y^2*z^3+571.8691769+36870.73567*x^3-18435.36784*x^4+36870.73567*y^3+36870.73567*z^3-18435.36784*y^4-18435.36784*z^4+32533.00206*x*y-15588.73016*x^2-15588.73016*y^2-15588.73016*z^2-112297.6066*x^2*z^4+112297.6066*x*z^4+277614.9509*y^2*z^2*x^2-75426.87093*x*y^2-277614.9509*y*z*x+277614.9509*y*z*x^2+277614.9509*y*z^2*x+277614.9509*y^2*z*x-224595.2132*x^3*y+112297.6066*x^4*y-277614.9509*x*y^2*z^2-277614.9509*x^2*z*y^2-277614.9509*x^2*y*z^2+224595.2132*x^3*y^2+224595.2132*x^2*z^3-112297.6066*y^4*z^2-112297.6066*x^4*y^2+112297.6066*y^4*z+32533.00206*x*z+79764.60454*x*z^2-75426.87093*x^2*z-36870.73567*x^2*y^2-36870.73567*y^2*z^2-224595.2132*y^3*z-224595.2132*x*z^3+79764.60454*x^2*y+79764.60454*y^2*z-36870.73567*z^2*x^2",
|
||||
/* Barth decic */ "25.33143961*y^2*z^2*x^4 +25.15700632*y^4*z^2*x -34.82908387*y^2*z^4 +8.917960033*y^4*z^2 +0.04360832264*y^4*z^4 +16.49570037*y^4*z +8.917960033*x^4*y^2 -42.37063678*x^4*y^3 -34.82908387*y^4*x^2 +2.299854983*y^7*z^2 +25.37005208*x^4*y^5 +33.65896395*x^6*y^2*z -100.9768918*x^3*y^2*z^4 +1.198101193*x^3 +246.5161156*y^2*z^2*x^2 +25.36672152*x^3*y^4 +6.515326172*y^6*x^2 +44.38789864*y^2*z*x +6.273208191*y^5*z^2 +0.05111641659 +201.9537837*x^2*z^3*y^3 -8.109285345*x^3*z^2 +117.9808071*y^2*z^3*x +0.8487421525*x^8 -8.109285345*y^3*x^2 +6.515326172*x^6*z^2 +33.83339724*x^3*y^3 +50.48844592*x^4*y^2*z^4 -33.65896395*y^6*z*x +100.9768918*x^5*y*z +6.273208191*x^2*z^5 +100.9768918*x^4*y^3*z -201.9537837*x^3*y*z^3 -4.774233544*x^2*z^6 -21.54557109*x^5*y -3.716625642*x^3*z +6.273208191*x^5*y^2 +0.04360832264*x^4*z^4 -100.9768918*x^2*z^3*y^4 +33.65896395*y^2*z^6*x +16.49570037*x*z^4 +16.49570037*x^4*y -120.2077842*x^2*y*z^2 +9.865021177*x*z^6 -42.37063678*x^3*z^4 -3.39496861*x^7 -15.2723629*x^4*z^5 -2.299854983*x*z^7 +25.15700632*x^2*z^4*y +117.9808071*x^3*y^2*z +25.15700632*y^2*z^4*x +50.48844592*x^2*z^4*y^4 -25.60810291*x^3*y^2 -14.9720102*x^6*z -100.9768918*x^5*y^2*z -100.9768918*x^2*z^4*y^3 +6.515326172*y^2*z^6 -3.716625642*y^3*x -5.046246117*y*z^2 -100.9768918*x^4*y^3*z^2 -50.48844592*y^4*z^4*x +100.9768918*x^3*y^4*z +2.299854983*x^7*y^2 -3.940860141*y^8*x +5.090787632*y^6*z^4 -15.2723629*x^5*y^4 +0.8487421525*y^8 +2.299854983*x^2*z^7 -0.5749637458*x^2*z^8 -75.64545224*y^4*z*x -100.9768918*y^5*z*x^2 -50.48844592*x^4*y*z^4 +25.33143961*y^4*z^2*x^2 +1.198101193*z^3 +100.9768918*y^5*z*x +0.9611245006*y^5 -120.2077842*x^2*z*y^2 +3.940860141*y^2*z^8 -10.18157526*x^6*y^3 -8.456684027*x^4*y^6 +201.9537837*x^3*y^2*z^3 -100.9768918*x^2*z^5*y +19.60032929*y*z^4 -15.76344056*x^7*z^2 -3.940860141*x^8*z +0.2347202588*x^3*y +19.60032929*x^4*z +9.865021177*y^6*z -19.05645904*y*z*x -10.25601137*x^5*z +9.865021177*x^6*y +0.4659238756*x^2 -0.3389589536*x -0.3389589536*y +1.198101193*y^3 -3.380386036*y^4 -3.380386036*x^4 -8.109285345*y^2*z^3 -25.60810291*x^2*z^3 -4.774233544*x^6*y^2 +117.9808071*y^3*z^2*x -218.9576989*y^2*z^2*x^3 +25.15700632*x^4*y^2*z +117.9808071*x^2*z^3*y +100.9768918*x^2*z^5*y^2 +33.65896395*y^6*z*x^2 -33.65896395*x^6*y*z +100.9768918*y^4*z^3*x -50.48844592*x^4*y^4*z -50.74010416*x^3*y^5 -3.39496861*y^7 -5.892963096*x*z^2 -5.046246117*x^2*z -100.9768918*y^5*z^2*x -100.9768918*y^2*z^5*x -21.54557109*y^5*z +0.9611245006*z^5 +18.5125231*z^2*x^2 +25.15700632*x^4*y*z^2 -17.00391526*x^3*y*z -33.65896395*x*z^6*y +100.9768918*y^3*z^4*x +5.090787632*x^4*z^6 -34.82908387*x^4*z^2 +2.567983615*x*z +100.9768918*x^3*y*z^4 +3.940860141*x^8*z^2 -8.456684027*x^6*z^4 +16.91336805*y^3*z^6 +30.54472579*y^5*z^3 -15.76344056*y^7*x^2 +15.76344056*y^7*x +30.54472579*x^3*z^5 +25.37005208*x^5*z^4 +25.37005208*y^4*z^5 -10.18157526*y^6*z^3 +33.65896395*x^2*z^6*y -100.9768918*x^4*y^2*z^3 -15.2723629*y^5*z^4 -50.74010416*y^3*z^5 -100.9768918*x^3*y^4*z^2 +50.48844592*x^4*y^4*z^2 -201.9537837*x^3*y^3*z +0.5749637458*y^8*z -0.5749637458*y^8*z^2 +35.62606345*y^5*x^2 -100.9768918*x^5*y*z^2 +3.640421878*z^6 +0.9611245006*x^5 -21.54557109*x*z^5 +0.4659238756*y^2 -33.65896395*x^6*y^2*z^2 -33.65896395*y^6*z^2*x^2 +0.5749637458*x^8*y -0.5749637458*x^8*y^2 +0.2347202588*x*z^3 +3.640421878*x^6 +25.36672152*x^4*z^3 +25.36672152*y^3*z^4 +0.4659238756*z^2 -0.3389589536*z -120.2077842*x*y^2*z^2 +100.9768918*x*z^5*y +30.54472579*x^5*y^3 +16.91336805*x^6*z^3 -33.65896395*x^2*z^6*y^2 +33.65896395*x^6*y*z^2 +201.9537837*x^3*y^3*z^2 +2.567983615*x*y +18.5125231*x^2*y^2 -15.76344056*y^2*z^7 +5.090787632*x^6*y^4 -3.940860141*y*z^8 +100.9768918*y^5*z^2*x^2 +0.04360832264*x^4*y^4 +35.62606345*x^5*z^2 +117.9808071*x^3*y*z^2 -17.00391526*x*z^3*y +35.62606345*y^2*z^5 -4.774233544*y^6*z^2 -42.37063678*y^4*z^3 +0.5749637458*x*z^8 +3.940860141*y^8*x^2 -2.299854983*x^7*y -3.380386036*z^4 +0.2347202588*y^3*z -25.60810291*y^3*z^2 +16.91336805*x^3*y^6 +3.640421878*y^6 +33.83339724*x^3*z^3 +33.83339724*y^3*z^3 +19.60032929*y^4*x +8.917960033*x^2*z^4 -10.25601137*y*z^5 -3.716625642*y*z^3 -5.892963096*y^2*z -5.892963096*x^2*y +33.65896395*y^6*z^2*x +100.9768918*x^5*y^2*z^2 +44.38789864*y*z*x^2 +44.38789864*y*z^2*x -3.39496861*z^7 -10.18157526*x^3*z^6 +100.9768918*x^4*y*z^3 -5.046246117*x*y^2 -10.25601137*y^5*x -14.9720102*y*z^6 +15.76344056*y*z^7 +0.8487421525*z^8 -75.64545224*x*z^4*y -75.64545224*x^4*y*z +25.15700632*y^4*z*x^2 +18.5125231*y^2*z^2 -14.9720102*y^6*x -8.456684027*y^4*z^6 +2.567983615*y*z +15.76344056*x^7*z -218.9576989*y^3*z^2*x^2 +25.33143961*y^2*z^4*x^2 -218.9576989*y^2*z^3*x^2 -17.00391526*y^3*z*x +117.9808071*y^3*z*x^2 -201.9537837*y^3*z^3*x -50.74010416*x^5*z^3 -2.299854983*y^7*z",
|
||||
/* Steiner relative */ "2-8*y*z*x-2*z-2*x-10*y+8*y^2-16*x*y^2-16*x^2*y+16*x^2*y^2+20*x*y-16*z^2*x^2+16*x^2*z+16*x*z^2+20*y*z-16*y*z^2-16*y^2*z+16*y^2*z^2-12*x*z",
|
||||
/* Mitre */ "4-8*z-16*x-12*y+28*y^2-16*x*y^2-16*x^2*y+16*x^2*y^2+16*x*y+16*z^2*x^2-16*x^2*z-16*x*z^2+16*y*z-16*y*z^2-16*y^2*z+16*y^2*z^2+16*x*z+8*z^2+16*y^4+16*x^4-32*x^3+32*x^2-32*y^3",
|
||||
/* Glob tear */ "16*x^5-32*x^4+24*x^3-8*x^2+x-2-4*y^2+4*y-4*z^2+4*z",
|
||||
/* Piri tear */ "x^4-1*x^3+y^2-1*y+.5+z^2-1*z",
|
||||
/* Gumdrop torus */ "-1792*z-2048*y*z^2-2368*x-1792*y+2048*y*z-2048*x^3+1024*x^4-2048*y^3-2048*z^3+1024*y^4+1024*z^4+4352*x*y+3392*x^2+2816*y^2+2816*z^2+641-4352*x*y^2+4352*x*z-4352*x*z^2-4352*x^2*z+4352*x^2*y^2+2048*y^2*z^2-4352*x^2*y-2048*y^2*z+4352*z^2*x^2",
|
||||
/* Bretzel */ "-1*z-4.5*x-2.53125*y+7.59375*y^2-18*x*y^2+18*x*y+72*x^4*y^2-72*x^4*y-144*x^3*y^2+144*x^3*y+z^2+5.0625*y^4+674*x^4+.55640625-196*x^3+38.5*x^2-1408*x^5+256*x^8-1024*x^7+1664*x^6+90*x^2*y^2-90*x^2*y-10.125*y^3",
|
||||
/* Blob */ "9*x^2-8.1*x+4.895+9*y^2-8.1*y+9*z^2-9*z+sin(12*x-5.4)+sin(12*y-5.4)+sin(12*z-6)",
|
||||
/* Bifolia */ "4-16*z-16*x+4*y^2+8*x^2*y^2+32*z^2*x^2-32*x^2*z-8*x*y^2-32*x*z^2+32*x*z+8*y^2*z^2-8*y^2*z+32*z^2+y^4+16*z^4+16*x^4-32*x^3+32*x^2-32*z^3-12*x^2*y+12*x*y-6*y-12*y*z^2+12*y*z",
|
||||
/* Lemniscate */ "16*x^4-32*x^3+20*x^2-4*x+2+4*y^2-4*y+4*z^2-4*z",
|
||||
/* Planes */ "x*y",
|
||||
/* Cylinders */ "((4*x-2)^2+(4*y-2)^2)^4+((4*x-2)^2+(4*z-2)^2)^4-((4*x-2)^2+(4*y-2)^2)^4*((4*x-2)^2+(4*z-2)^2)^4",
|
||||
/* Torus */ "(1.4-sqrt((6*x-3)^2+(6*y-3)^2))^2+(6*z-3)^2-1.44"
|
||||
} ;
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,332 @@
|
||||
/**
|
||||
* \file leaf_octree.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* Octree structure without intermediate nodes, hashtable and optimized operations
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "mlist.h"
|
||||
#include "cube.h"
|
||||
#include "hash.h"
|
||||
#include "MarchingCubes.h"
|
||||
#include "mc_draw.h"
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
#ifdef HASH_HAS_ERASE
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// LeafOctree
|
||||
/// \class LeafOctree LeafOctree.h
|
||||
class LeafOctree
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// forward declaration
|
||||
public:
|
||||
class geom_cell ;
|
||||
class leaf_iterator ;
|
||||
|
||||
// Elements
|
||||
protected:
|
||||
/// Octree cell data structure
|
||||
typedef Hash<real> HashField ;
|
||||
|
||||
/// Hashtable of the octree nodes
|
||||
HashField _hash ;
|
||||
|
||||
/// Level distribution of the octree
|
||||
uint _level_dist[MAX_LEVEL+1] ;
|
||||
|
||||
/// Optimal level for direct search in the octree
|
||||
Level _opt_level ;
|
||||
|
||||
/// Maximal field of the octree
|
||||
real _max_field ;
|
||||
|
||||
/// Isosurface
|
||||
MarchingCubes _mc ;
|
||||
|
||||
/// Isosurface Draw
|
||||
MC_Draw _mc_draw ;
|
||||
|
||||
private:
|
||||
/// Octree vertices data structure
|
||||
typedef Hash<Level> HashVerts ;
|
||||
/// Hashtable of the octree vertices
|
||||
HashVerts _verts ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs a octree with and empty root
|
||||
LeafOctree() { init() ; }
|
||||
|
||||
/// Destructor: Free memory
|
||||
~LeafOctree() { clear() ; }
|
||||
|
||||
|
||||
/// Create the root
|
||||
void init() ;
|
||||
|
||||
/// Memory cleaning
|
||||
void clear() { clear_octree() ; _mc.clean_all() ; }
|
||||
|
||||
/// Delete the content of the octree
|
||||
void clear_octree() ;
|
||||
|
||||
/// Compute the optimal level
|
||||
void compute_opt_level() ;
|
||||
|
||||
/// Check that only the leaves have data
|
||||
bool check () ;
|
||||
|
||||
/// Prints statistics about the octree
|
||||
void stats() const ;
|
||||
|
||||
|
||||
/// Return the maximal level of the octree
|
||||
Level max_level() const { Level lv = MAX_LEVEL ; while( lv > 0 && !_level_dist[lv] ) --lv ; return lv ; }
|
||||
|
||||
/// Return the optimal level of the octree
|
||||
Level opt_level() const { return _opt_level ; }
|
||||
|
||||
/// Return the optimal level of the octree
|
||||
Level &opt_level() { return _opt_level ; }
|
||||
|
||||
/// Return the maximal field of the octree
|
||||
real max_field() const { return _max_field ; }
|
||||
|
||||
/// Return the isosurface
|
||||
MarchingCubes &mc() { return _mc ; }
|
||||
|
||||
/// Return the isosurface draw
|
||||
MC_Draw &mc_draw() { return _mc_draw ; }
|
||||
|
||||
/// set the values of each leaf from the implicit function
|
||||
bool set_impl( data_access *ref = NULL ) ;
|
||||
|
||||
/// Refine the octree according to the data access
|
||||
bool refine( data_access *ref = NULL ) ;
|
||||
|
||||
/// Adapt the octree according to the data access
|
||||
bool adapt( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the octree with wireframe
|
||||
bool draw_wire() ;
|
||||
|
||||
/// Draw the octree with dots
|
||||
bool draw_centers() ;
|
||||
|
||||
/// Dual function type
|
||||
typedef bool leaf_dual_walker( LeafOctree &fo, Key *keys ) ;
|
||||
|
||||
/// Compute primal vertices
|
||||
bool compute_primal_verts() ;
|
||||
|
||||
/// Walk on the dual cubes
|
||||
bool dual_cubes_walk( leaf_dual_walker &walker ) ;
|
||||
|
||||
/// Build the isosurface using dual marching cubes
|
||||
bool build_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the isosurface on-the-fly using dual marching cubes
|
||||
bool direct_draw_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the dual octree with wireframe
|
||||
bool draw_dual() ;
|
||||
|
||||
/// Do nothing, just for dual generation timing
|
||||
bool dual_timing() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterators
|
||||
public:
|
||||
/// Create an iterator traversing the leaves of the tree from the root
|
||||
inline leaf_iterator leaves_begin() { return leaf_iterator( *this ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// search operations
|
||||
public:
|
||||
/// Find cells of the octree at a given position
|
||||
bool find_leaf( Key k, Level o_lv, geom_cell &cell ) const ;
|
||||
bool find_leaf( Key k, geom_cell &cell ) const { return find_leaf( k, opt_level(), cell ) ; }
|
||||
bool find_leaf( real x, real y, real z, geom_cell &cell ) const { return find_leaf( cube2key( Cube(x,y,z,MAX_LEVEL) ), opt_level(), cell ) ; }
|
||||
|
||||
/// Find cells of the octree inside a given box of center x,y,z and half side r
|
||||
bool find_radius( real x, real y, real z, real r, List<geom_cell> &cells ) const ;
|
||||
|
||||
/// Find adjacent cells of the octree to a given cell
|
||||
bool adjacent( Key k, List<geom_cell> &cells ) const ;
|
||||
bool adjacent( const geom_cell &cell, List<geom_cell> &cells ) const { return adjacent( cell.key(), cells ) ; }
|
||||
|
||||
/// Node existence
|
||||
bool node_exists( Key k, HashField::KeyData &kd ) const { kd = _hash[k] ; return kd.key != KEY_INV ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// I/O
|
||||
public:
|
||||
|
||||
/// Draws the intersecting cells of a plane with the octree with color
|
||||
void draw_plane ( real nx, real ny, real nz, real d ) ;
|
||||
|
||||
/// Draws the intersection of a plane with the octree with color
|
||||
void draw_slice ( real nx, real ny, real nz, real d, float alpha ) ;
|
||||
|
||||
/// Draws the isosurface of level l inside the dual graph
|
||||
void draw_iso () { _mc.draw_surf() ; }
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Iterator Cell
|
||||
public :
|
||||
/// Auxiliary structure to traverse the octree
|
||||
class geom_cell : public Cube
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class LeafOctree ;
|
||||
|
||||
protected:
|
||||
Key _key ; ///< octree cell
|
||||
real _field ; ///< field associated to the cell
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor
|
||||
geom_cell( Key key_ = KEY_INV, real field_ = R_INV ) : Cube(key2cube(key_)), _key(key_), _field(field_) {}
|
||||
|
||||
/// Default constructor
|
||||
geom_cell( HashField::KeyData kd ) : Cube(key2cube(kd.key)), _key(kd.key), _field(kd.data) {}
|
||||
|
||||
/// Destructor
|
||||
~geom_cell() {}
|
||||
|
||||
/// Copy constructor
|
||||
geom_cell( const geom_cell &i ) : Cube(i), _key(i._key), _field(i._field) {}
|
||||
|
||||
/// Assignment operator
|
||||
geom_cell &operator = ( const geom_cell &i )
|
||||
{ Cube::operator=(i) ; _key = i._key ; _field = i._field ; return *this; }
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Public constant accessors
|
||||
public :
|
||||
/// key const accessor
|
||||
inline Key key() const { return _key ; }
|
||||
/// key accessor
|
||||
inline Key &key() { return _key ; }
|
||||
|
||||
/// id const accessor
|
||||
inline real operator*() const { return _field ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Tests
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const geom_cell &i ) const { return key() == i.key() ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const geom_cell &i ) const { return key() != i.key() ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return key() != KEY_INV ; }
|
||||
};
|
||||
|
||||
const geom_cell geom_root() const { const Key root_key = 1 ; return geom_cell( root_key, _hash[root_key].data ) ; }
|
||||
const geom_cell geom_key ( Key k ) const { return geom_cell( k, _hash[k].data ) ; }
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Cell Iterator
|
||||
public :
|
||||
/// Octree cell iterator : Traverse the octree returning basic information on the cells
|
||||
class leaf_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class LeafOctree ;
|
||||
|
||||
protected:
|
||||
/// Octree traversal iterator
|
||||
HashField::iterator _it ;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor : Constructs an iterator from a cell
|
||||
leaf_iterator( LeafOctree &o ) : _it( o._hash.begin() ) {}
|
||||
|
||||
/// Destructor
|
||||
~leaf_iterator() {}
|
||||
|
||||
/// Copy constructor
|
||||
leaf_iterator( const leaf_iterator &i ) : _it(i._it) {}
|
||||
|
||||
/// Assignment operator
|
||||
leaf_iterator &operator = ( const leaf_iterator &i )
|
||||
{ _it = i._it; return *this; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const leaf_iterator &i ) const { return _it == i._it ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const leaf_iterator &i ) const { return _it != i._it ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _it() ; }
|
||||
|
||||
/// next position
|
||||
inline leaf_iterator &operator ++() { ++_it ; return *this ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
// cell accessor
|
||||
inline geom_cell top() const { return geom_cell( key(), *_it ) ; }
|
||||
|
||||
/// id accessor
|
||||
inline real &operator*() { return *_it ; }
|
||||
|
||||
/// level accessor
|
||||
inline Level lv() { return key_level(_it.key()) ; }
|
||||
|
||||
/// size accessor
|
||||
inline real sz() { return Cube(0,0,0,lv()).sz() ; }
|
||||
|
||||
/// key accessor
|
||||
inline Key key() const { return _it.key() ; }
|
||||
|
||||
/// points accessor
|
||||
inline bool is_leaf() const { return !is_inv(*_it) ; }
|
||||
|
||||
/// Draws the cell wire with opengl
|
||||
void draw_wire () const { top().draw_wire () ; }
|
||||
|
||||
};
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#else // HASH_HAS_ERASE
|
||||
|
||||
#include "opt_octree.h"
|
||||
typedef OptOctree LeafOctree ;
|
||||
|
||||
#endif // HASH_HAS_ERASE
|
||||
|
||||
@ -0,0 +1,695 @@
|
||||
/**
|
||||
* @file md_draw.cpp
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.2
|
||||
* @date 12/08/2002
|
||||
*
|
||||
* @brief MC_Draw Direct Draw Algorithm
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma implementation
|
||||
#endif // WIN32
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
#include "mc_draw.h"
|
||||
#include "LookUpTable.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// print cube for debug
|
||||
void MC_Draw::print_cube() { printf( "\t%f %f %f %f %f %f %f %f\n", _cube[0], _cube[1], _cube[2], _cube[3], _cube[4], _cube[5], _cube[6], _cube[7]) ; }
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// main algorithm
|
||||
bool MC_Draw::tesselate_cube( real iso )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
for( int p = 0 ; p < 8 ; ++p )
|
||||
{
|
||||
real &v = _cube[p] ;
|
||||
v -= iso ;
|
||||
if( fabs( v ) < R_EPSILON ) v = R_EPSILON ;
|
||||
}
|
||||
|
||||
if( !compute_intersection_points() ) return false ;
|
||||
|
||||
_lut_entry = 0 ;
|
||||
for( int p = 0 ; p < 8 ; ++p )
|
||||
{
|
||||
if( _cube[p] > 0 ) _lut_entry += 1 << p ;
|
||||
}
|
||||
|
||||
return process_cube( ) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Compute the intersection points
|
||||
bool MC_Draw::compute_intersection_points()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
bool res = false ;
|
||||
res |= add_vertex( 0,1 ) ;
|
||||
res |= add_vertex( 1,2 ) ;
|
||||
res |= add_vertex( 2,3 ) ;
|
||||
res |= add_vertex( 3,0 ) ;
|
||||
|
||||
res |= add_vertex( 4,5 ) ;
|
||||
res |= add_vertex( 5,6 ) ;
|
||||
res |= add_vertex( 6,7 ) ;
|
||||
res |= add_vertex( 7,4 ) ;
|
||||
|
||||
res |= add_vertex( 0,4 ) ;
|
||||
res |= add_vertex( 1,5 ) ;
|
||||
res |= add_vertex( 2,6 ) ;
|
||||
res |= add_vertex( 3,7 ) ;
|
||||
|
||||
return res ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Test a face
|
||||
// if face>0 return true if the face contains a part of the surface
|
||||
bool MC_Draw::test_face( schar face )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
real A,B,C,D ;
|
||||
|
||||
switch( face )
|
||||
{
|
||||
case -1 : case 1 : A = _cube[0] ; B = _cube[4] ; C = _cube[5] ; D = _cube[1] ; break ;
|
||||
case -2 : case 2 : A = _cube[1] ; B = _cube[5] ; C = _cube[6] ; D = _cube[2] ; break ;
|
||||
case -3 : case 3 : A = _cube[2] ; B = _cube[6] ; C = _cube[7] ; D = _cube[3] ; break ;
|
||||
case -4 : case 4 : A = _cube[3] ; B = _cube[7] ; C = _cube[4] ; D = _cube[0] ; break ;
|
||||
case -5 : case 5 : A = _cube[0] ; B = _cube[3] ; C = _cube[2] ; D = _cube[1] ; break ;
|
||||
case -6 : case 6 : A = _cube[4] ; B = _cube[7] ; C = _cube[6] ; D = _cube[5] ; break ;
|
||||
default : printf( "Invalid face code %d\n", face ) ; print_cube() ; A = B = C = D = 0 ;
|
||||
};
|
||||
|
||||
if( fabs( A*C - B*D ) < R_EPSILON )
|
||||
return face >= 0 ;
|
||||
return face * A * ( A*C - B*D ) >= 0 ; // face and A invert signs
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Test the interior of a cube
|
||||
// if s == 7, return true if the interior is empty
|
||||
// if s ==-7, return false if the interior is empty
|
||||
bool MC_Draw::test_interior( schar s )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
real t, At=0, Bt=0, Ct=0, Dt=0, a, b ;
|
||||
char test = 0 ;
|
||||
char edge = -1 ; // reference edge of the triangulation
|
||||
|
||||
switch( _case )
|
||||
{
|
||||
case 4 :
|
||||
case 10 :
|
||||
a = ( _cube[4] - _cube[0] ) * ( _cube[6] - _cube[2] ) - ( _cube[7] - _cube[3] ) * ( _cube[5] - _cube[1] ) ;
|
||||
b = _cube[2] * ( _cube[4] - _cube[0] ) + _cube[0] * ( _cube[6] - _cube[2] )
|
||||
- _cube[1] * ( _cube[7] - _cube[3] ) - _cube[3] * ( _cube[5] - _cube[1] ) ;
|
||||
t = - b / (2*a) ;
|
||||
if( t<0 || t>1 ) return s>0 ;
|
||||
|
||||
At = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
|
||||
Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
|
||||
Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
|
||||
Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
|
||||
break ;
|
||||
|
||||
case 6 :
|
||||
case 7 :
|
||||
case 12 :
|
||||
case 13 :
|
||||
switch( _case )
|
||||
{
|
||||
case 6 : edge = test6 [_config][2] ; break ;
|
||||
case 7 : edge = test7 [_config][4] ; break ;
|
||||
case 12 : edge = test12[_config][3] ; break ;
|
||||
case 13 : edge = tiling13_5_1[_config][_subconfig][0] ; break ;
|
||||
}
|
||||
switch( edge )
|
||||
{
|
||||
case 0 :
|
||||
t = _cube[0] / ( _cube[0] - _cube[1] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[3] + ( _cube[2] - _cube[3] ) * t ;
|
||||
Ct = _cube[7] + ( _cube[6] - _cube[7] ) * t ;
|
||||
Dt = _cube[4] + ( _cube[5] - _cube[4] ) * t ;
|
||||
break ;
|
||||
case 1 :
|
||||
t = _cube[1] / ( _cube[1] - _cube[2] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[0] + ( _cube[3] - _cube[0] ) * t ;
|
||||
Ct = _cube[4] + ( _cube[7] - _cube[4] ) * t ;
|
||||
Dt = _cube[5] + ( _cube[6] - _cube[5] ) * t ;
|
||||
break ;
|
||||
case 2 :
|
||||
t = _cube[2] / ( _cube[2] - _cube[3] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[1] + ( _cube[0] - _cube[1] ) * t ;
|
||||
Ct = _cube[5] + ( _cube[4] - _cube[5] ) * t ;
|
||||
Dt = _cube[6] + ( _cube[7] - _cube[6] ) * t ;
|
||||
break ;
|
||||
case 3 :
|
||||
t = _cube[3] / ( _cube[3] - _cube[0] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[2] + ( _cube[1] - _cube[2] ) * t ;
|
||||
Ct = _cube[6] + ( _cube[5] - _cube[6] ) * t ;
|
||||
Dt = _cube[7] + ( _cube[4] - _cube[7] ) * t ;
|
||||
break ;
|
||||
case 4 :
|
||||
t = _cube[4] / ( _cube[4] - _cube[5] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[7] + ( _cube[6] - _cube[7] ) * t ;
|
||||
Ct = _cube[3] + ( _cube[2] - _cube[3] ) * t ;
|
||||
Dt = _cube[0] + ( _cube[1] - _cube[0] ) * t ;
|
||||
break ;
|
||||
case 5 :
|
||||
t = _cube[5] / ( _cube[5] - _cube[6] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[4] + ( _cube[7] - _cube[4] ) * t ;
|
||||
Ct = _cube[0] + ( _cube[3] - _cube[0] ) * t ;
|
||||
Dt = _cube[1] + ( _cube[2] - _cube[1] ) * t ;
|
||||
break ;
|
||||
case 6 :
|
||||
t = _cube[6] / ( _cube[6] - _cube[7] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[5] + ( _cube[4] - _cube[5] ) * t ;
|
||||
Ct = _cube[1] + ( _cube[0] - _cube[1] ) * t ;
|
||||
Dt = _cube[2] + ( _cube[3] - _cube[2] ) * t ;
|
||||
break ;
|
||||
case 7 :
|
||||
t = _cube[7] / ( _cube[7] - _cube[4] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[6] + ( _cube[5] - _cube[6] ) * t ;
|
||||
Ct = _cube[2] + ( _cube[1] - _cube[2] ) * t ;
|
||||
Dt = _cube[3] + ( _cube[0] - _cube[3] ) * t ;
|
||||
break ;
|
||||
case 8 :
|
||||
t = _cube[0] / ( _cube[0] - _cube[4] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
|
||||
Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
|
||||
Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
|
||||
break ;
|
||||
case 9 :
|
||||
t = _cube[1] / ( _cube[1] - _cube[5] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
|
||||
Ct = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
|
||||
Dt = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
|
||||
break ;
|
||||
case 10 :
|
||||
t = _cube[2] / ( _cube[2] - _cube[6] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
|
||||
Ct = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
|
||||
Dt = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
|
||||
break ;
|
||||
case 11 :
|
||||
t = _cube[3] / ( _cube[3] - _cube[7] ) ;
|
||||
At = 0 ;
|
||||
Bt = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
|
||||
Ct = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
|
||||
Dt = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
|
||||
break ;
|
||||
default : printf( "Invalid edge %d\n", edge ) ; print_cube() ; break ;
|
||||
}
|
||||
break ;
|
||||
|
||||
default : printf( "Invalid ambiguous case %d\n", _case ) ; print_cube() ; break ;
|
||||
}
|
||||
|
||||
if( At >= 0 ) test ++ ;
|
||||
if( Bt >= 0 ) test += 2 ;
|
||||
if( Ct >= 0 ) test += 4 ;
|
||||
if( Dt >= 0 ) test += 8 ;
|
||||
switch( test )
|
||||
{
|
||||
case 0 : return s>0 ;
|
||||
case 1 : return s>0 ;
|
||||
case 2 : return s>0 ;
|
||||
case 3 : return s>0 ;
|
||||
case 4 : return s>0 ;
|
||||
case 5 : if( At * Ct - Bt * Dt < R_EPSILON ) return s>0 ; break ;
|
||||
case 6 : return s>0 ;
|
||||
case 7 : return s<0 ;
|
||||
case 8 : return s>0 ;
|
||||
case 9 : return s>0 ;
|
||||
case 10 : if( At * Ct - Bt * Dt >= R_EPSILON ) return s>0 ; break ;
|
||||
case 11 : return s<0 ;
|
||||
case 12 : return s>0 ;
|
||||
case 13 : return s<0 ;
|
||||
case 14 : return s<0 ;
|
||||
case 15 : return s<0 ;
|
||||
}
|
||||
|
||||
return s<0 ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Process a unit cube
|
||||
bool MC_Draw::process_cube( )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
if( _originalMC )
|
||||
{
|
||||
char nt = 0 ;
|
||||
while( casesClassic[_lut_entry][3*nt] != -1 ) nt++ ;
|
||||
draw_triangle( casesClassic[_lut_entry], nt ) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
int v12 = -1 ;
|
||||
_case = cases[_lut_entry][0] ;
|
||||
_config = cases[_lut_entry][1] ;
|
||||
_subconfig = 0 ;
|
||||
|
||||
switch( _case )
|
||||
{
|
||||
case 0 :
|
||||
break ;
|
||||
|
||||
case 1 :
|
||||
draw_triangle( tiling1[_config], 1 ) ;
|
||||
break ;
|
||||
|
||||
case 2 :
|
||||
draw_triangle( tiling2[_config], 2 ) ;
|
||||
break ;
|
||||
|
||||
case 3 :
|
||||
if( test_face( test3[_config]) )
|
||||
draw_triangle( tiling3_2[_config], 4 ) ; // 3.2
|
||||
else
|
||||
draw_triangle( tiling3_1[_config], 2 ) ; // 3.1
|
||||
break ;
|
||||
|
||||
case 4 :
|
||||
if( test_interior( test4[_config]) )
|
||||
draw_triangle( tiling4_1[_config], 2 ) ; // 4.1.1
|
||||
else
|
||||
draw_triangle( tiling4_2[_config], 6 ) ; // 4.1.2
|
||||
break ;
|
||||
|
||||
case 5 :
|
||||
draw_triangle( tiling5[_config], 3 ) ;
|
||||
break ;
|
||||
|
||||
case 6 :
|
||||
if( test_face( test6[_config][0]) )
|
||||
draw_triangle( tiling6_2[_config], 5 ) ; // 6.2
|
||||
else
|
||||
{
|
||||
if( test_interior( test6[_config][1]) )
|
||||
draw_triangle( tiling6_1_1[_config], 3 ) ; // 6.1.1
|
||||
else
|
||||
{
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling6_1_2[_config], 9 , v12) ; // 6.1.2
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
case 7 :
|
||||
if( test_face( test7[_config][0] ) ) _subconfig += 1 ;
|
||||
if( test_face( test7[_config][1] ) ) _subconfig += 2 ;
|
||||
if( test_face( test7[_config][2] ) ) _subconfig += 4 ;
|
||||
switch( _subconfig )
|
||||
{
|
||||
case 0 :
|
||||
draw_triangle( tiling7_1[_config], 3 ) ; break ;
|
||||
case 1 :
|
||||
draw_triangle( tiling7_2[_config][0], 5 ) ; break ;
|
||||
case 2 :
|
||||
draw_triangle( tiling7_2[_config][1], 5 ) ; break ;
|
||||
case 3 :
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling7_3[_config][0], 9, v12 ) ; break ;
|
||||
case 4 :
|
||||
draw_triangle( tiling7_2[_config][2], 5 ) ; break ;
|
||||
case 5 :
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling7_3[_config][1], 9, v12 ) ; break ;
|
||||
case 6 :
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling7_3[_config][2], 9, v12 ) ; break ;
|
||||
case 7 :
|
||||
if( test_interior( test7[_config][3]) )
|
||||
draw_triangle( tiling7_4_2[_config], 9 ) ;
|
||||
else
|
||||
draw_triangle( tiling7_4_1[_config], 5 ) ;
|
||||
break ;
|
||||
};
|
||||
break ;
|
||||
|
||||
case 8 :
|
||||
draw_triangle( tiling8[_config], 2 ) ;
|
||||
break ;
|
||||
|
||||
case 9 :
|
||||
draw_triangle( tiling9[_config], 4 ) ;
|
||||
break ;
|
||||
|
||||
case 10 :
|
||||
if( test_face( test10[_config][0]) )
|
||||
{
|
||||
if( test_face( test10[_config][1]) )
|
||||
draw_triangle( tiling10_1_1_[_config], 4 ) ; // 10.1.1
|
||||
else
|
||||
{
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling10_2[_config], 8, v12 ) ; // 10.2
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( test_face( test10[_config][1]) )
|
||||
{
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling10_2_[_config], 8, v12 ) ; // 10.2
|
||||
}
|
||||
else
|
||||
{
|
||||
if( test_interior( test10[_config][2]) )
|
||||
draw_triangle( tiling10_1_1[_config], 4 ) ; // 10.1.1
|
||||
else
|
||||
draw_triangle( tiling10_1_2[_config], 8 ) ; // 10.1.2
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
case 11 :
|
||||
draw_triangle( tiling11[_config], 4 ) ;
|
||||
break ;
|
||||
|
||||
case 12 :
|
||||
if( test_face( test12[_config][0]) )
|
||||
{
|
||||
if( test_face( test12[_config][1]) )
|
||||
draw_triangle( tiling12_1_1_[_config], 4 ) ; // 12.1.1
|
||||
else
|
||||
{
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling12_2[_config], 8, v12 ) ; // 12.2
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( test_face( test12[_config][1]) )
|
||||
{
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling12_2_[_config], 8, v12 ) ; // 12.2
|
||||
}
|
||||
else
|
||||
{
|
||||
if( test_interior( test12[_config][2]) )
|
||||
draw_triangle( tiling12_1_1[_config], 4 ) ; // 12.1.1
|
||||
else
|
||||
draw_triangle( tiling12_1_2[_config], 8 ) ; // 12.1.2
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
case 13 :
|
||||
if( test_face( test13[_config][0] ) ) _subconfig += 1 ;
|
||||
if( test_face( test13[_config][1] ) ) _subconfig += 2 ;
|
||||
if( test_face( test13[_config][2] ) ) _subconfig += 4 ;
|
||||
if( test_face( test13[_config][3] ) ) _subconfig += 8 ;
|
||||
if( test_face( test13[_config][4] ) ) _subconfig += 16 ;
|
||||
if( test_face( test13[_config][5] ) ) _subconfig += 32 ;
|
||||
switch( subconfig13[_subconfig] )
|
||||
{
|
||||
case 0 :/* 13.1 */
|
||||
draw_triangle( tiling13_1[_config], 4 ) ; break ;
|
||||
|
||||
case 1 :/* 13.2 */
|
||||
draw_triangle( tiling13_2[_config][0], 6 ) ; break ;
|
||||
case 2 :/* 13.2 */
|
||||
draw_triangle( tiling13_2[_config][1], 6 ) ; break ;
|
||||
case 3 :/* 13.2 */
|
||||
draw_triangle( tiling13_2[_config][2], 6 ) ; break ;
|
||||
case 4 :/* 13.2 */
|
||||
draw_triangle( tiling13_2[_config][3], 6 ) ; break ;
|
||||
case 5 :/* 13.2 */
|
||||
draw_triangle( tiling13_2[_config][4], 6 ) ; break ;
|
||||
case 6 :/* 13.2 */
|
||||
draw_triangle( tiling13_2[_config][5], 6 ) ; break ;
|
||||
|
||||
case 7 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][0], 10, v12 ) ; break ;
|
||||
case 8 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][1], 10, v12 ) ; break ;
|
||||
case 9 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][2], 10, v12 ) ; break ;
|
||||
case 10 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][3], 10, v12 ) ; break ;
|
||||
case 11 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][4], 10, v12 ) ; break ;
|
||||
case 12 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][5], 10, v12 ) ; break ;
|
||||
case 13 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][6], 10, v12 ) ; break ;
|
||||
case 14 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][7], 10, v12 ) ; break ;
|
||||
case 15 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][8], 10, v12 ) ; break ;
|
||||
case 16 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][9], 10, v12 ) ; break ;
|
||||
case 17 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][10], 10, v12 ) ; break ;
|
||||
case 18 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3[_config][11], 10, v12 ) ; break ;
|
||||
|
||||
case 19 :/* 13.4 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_4[_config][0], 12, v12 ) ; break ;
|
||||
case 20 :/* 13.4 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_4[_config][1], 12, v12 ) ; break ;
|
||||
case 21 :/* 13.4 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_4[_config][2], 12, v12 ) ; break ;
|
||||
case 22 :/* 13.4 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_4[_config][3], 12, v12 ) ; break ;
|
||||
|
||||
case 23 :/* 13.5 */
|
||||
_subconfig = 0 ;
|
||||
if( test_interior( test13[_config][6] ) )
|
||||
draw_triangle( tiling13_5_1[_config][0], 6 ) ;
|
||||
else
|
||||
draw_triangle( tiling13_5_2[_config][0], 10 ) ;
|
||||
break ;
|
||||
case 24 :/* 13.5 */
|
||||
_subconfig = 1 ;
|
||||
if( test_interior( test13[_config][6] ) )
|
||||
draw_triangle( tiling13_5_1[_config][1], 6 ) ;
|
||||
else
|
||||
draw_triangle( tiling13_5_2[_config][1], 10 ) ;
|
||||
break ;
|
||||
case 25 :/* 13.5 */
|
||||
_subconfig = 2 ;
|
||||
if( test_interior( test13[_config][6] ) )
|
||||
draw_triangle( tiling13_5_1[_config][2], 6 ) ;
|
||||
else
|
||||
draw_triangle( tiling13_5_2[_config][2], 10 ) ;
|
||||
break ;
|
||||
case 26 :/* 13.5 */
|
||||
_subconfig = 3 ;
|
||||
if( test_interior( test13[_config][6] ) )
|
||||
draw_triangle( tiling13_5_1[_config][3], 6 ) ;
|
||||
else
|
||||
draw_triangle( tiling13_5_2[_config][3], 10 ) ;
|
||||
break ;
|
||||
|
||||
case 27 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][0], 10, v12 ) ; break ;
|
||||
case 28 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][1], 10, v12 ) ; break ;
|
||||
case 29 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][2], 10, v12 ) ; break ;
|
||||
case 30 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][3], 10, v12 ) ; break ;
|
||||
case 31 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][4], 10, v12 ) ; break ;
|
||||
case 32 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][5], 10, v12 ) ; break ;
|
||||
case 33 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][6], 10, v12 ) ; break ;
|
||||
case 34 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][7], 10, v12 ) ; break ;
|
||||
case 35 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][8], 10, v12 ) ; break ;
|
||||
case 36 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][9], 10, v12 ) ; break ;
|
||||
case 37 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][10], 10, v12 ) ; break ;
|
||||
case 38 :/* 13.3 */
|
||||
comp_c_vertex() ;
|
||||
draw_triangle( tiling13_3_[_config][11], 10, v12 ) ; break ;
|
||||
|
||||
case 39 :/* 13.2 */
|
||||
draw_triangle( tiling13_2_[_config][0], 6 ) ; break ;
|
||||
case 40 :/* 13.2 */
|
||||
draw_triangle( tiling13_2_[_config][1], 6 ) ; break ;
|
||||
case 41 :/* 13.2 */
|
||||
draw_triangle( tiling13_2_[_config][2], 6 ) ; break ;
|
||||
case 42 :/* 13.2 */
|
||||
draw_triangle( tiling13_2_[_config][3], 6 ) ; break ;
|
||||
case 43 :/* 13.2 */
|
||||
draw_triangle( tiling13_2_[_config][4], 6 ) ; break ;
|
||||
case 44 :/* 13.2 */
|
||||
draw_triangle( tiling13_2_[_config][5], 6 ) ; break ;
|
||||
|
||||
case 45 :/* 13.1 */
|
||||
draw_triangle( tiling13_1_[_config], 4 ) ; break ;
|
||||
|
||||
default :
|
||||
printf("Marching Cubes: Impossible case 13?\n" ) ; print_cube() ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case 14 :
|
||||
draw_triangle( tiling14[_config], 4 ) ;
|
||||
break ;
|
||||
};
|
||||
|
||||
return true ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Adding triangles
|
||||
void MC_Draw::draw_triangle( const char* trig_, char n, int v12 )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
for( int t = 0 ; t < 3*n ; t++ )
|
||||
{
|
||||
switch( trig_[t] )
|
||||
{
|
||||
case 0 : _verts[0][1].draw() ; break ;
|
||||
case 1 : _verts[1][2].draw() ; break ;
|
||||
case 2 : _verts[2][3].draw() ; break ;
|
||||
case 3 : _verts[3][0].draw() ; break ;
|
||||
case 4 : _verts[4][5].draw() ; break ;
|
||||
case 5 : _verts[5][6].draw() ; break ;
|
||||
case 6 : _verts[6][7].draw() ; break ;
|
||||
case 7 : _verts[7][4].draw() ; break ;
|
||||
case 8 : _verts[0][4].draw() ; break ;
|
||||
case 9 : _verts[1][5].draw() ; break ;
|
||||
case 10 : _verts[2][6].draw() ; break ;
|
||||
case 11 : _verts[3][7].draw() ; break ;
|
||||
case 12 : _c_vert .draw() ; break ;
|
||||
default : break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Adding vertices
|
||||
bool MC_Draw::add_vertex( char i, char j )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
real ci = _cube[i] ;
|
||||
real cj = _cube[j] ;
|
||||
if( ci * cj >= 0 ) { _verts[i][j] = P_INV ; return false ; }
|
||||
|
||||
_dat_access->interpolate( ci,cj, _space[i],_space[j], _verts[i][j] ) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool MC_Draw::comp_c_vertex( )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
real u = 0 ;
|
||||
|
||||
_c_vert.x() = _c_vert.y() = _c_vert.z() = 0 ;
|
||||
|
||||
// Computes the average of the intersection points of the cube
|
||||
Point &v01 = _verts[0][1] ; if( v01 != P_INV ) { ++u ; _c_vert += v01 ; }
|
||||
Point &v12 = _verts[1][2] ; if( v12 != P_INV ) { ++u ; _c_vert += v12 ; }
|
||||
Point &v23 = _verts[2][3] ; if( v23 != P_INV ) { ++u ; _c_vert += v23 ; }
|
||||
Point &v30 = _verts[3][0] ; if( v30 != P_INV ) { ++u ; _c_vert += v30 ; }
|
||||
Point &v45 = _verts[4][5] ; if( v45 != P_INV ) { ++u ; _c_vert += v45 ; }
|
||||
Point &v56 = _verts[5][6] ; if( v56 != P_INV ) { ++u ; _c_vert += v56 ; }
|
||||
Point &v67 = _verts[6][7] ; if( v67 != P_INV ) { ++u ; _c_vert += v67 ; }
|
||||
Point &v74 = _verts[7][4] ; if( v74 != P_INV ) { ++u ; _c_vert += v74 ; }
|
||||
Point &v04 = _verts[0][4] ; if( v04 != P_INV ) { ++u ; _c_vert += v04 ; }
|
||||
Point &v15 = _verts[1][5] ; if( v15 != P_INV ) { ++u ; _c_vert += v15 ; }
|
||||
Point &v26 = _verts[2][6] ; if( v26 != P_INV ) { ++u ; _c_vert += v26 ; }
|
||||
Point &v37 = _verts[3][7] ; if( v37 != P_INV ) { ++u ; _c_vert += v37 ; }
|
||||
|
||||
_c_vert /= u ;
|
||||
|
||||
return u > 0 ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @file mc_draw.h
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.2
|
||||
* @date 12/08/2002
|
||||
*
|
||||
* @brief MarchingCubes Direct Draw
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
#include <map>
|
||||
#include "point.h"
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/** Marching Cubes algorithm wrapper */
|
||||
/** \class MarchingCubes Direct Draw
|
||||
* \brief Marching Cubes Direct Draw.
|
||||
*/
|
||||
class MC_Draw
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// Constructors
|
||||
public :
|
||||
/**
|
||||
* Main and default constructor
|
||||
* \brief constructor
|
||||
*/
|
||||
MC_Draw () : _originalMC(true) {}
|
||||
/** Destructor */
|
||||
~MC_Draw () {}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
/**
|
||||
* selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes
|
||||
* \param originalMC true for the original Marching Cubes
|
||||
*/
|
||||
inline void set_method ( const bool originalMC = false ) { _originalMC = originalMC ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Algorithm
|
||||
public :
|
||||
/** retrieves the isovalues at the cube vertices */
|
||||
real *cube () { return _cube ; }
|
||||
/** retrieves the geometry of the cube */
|
||||
Point *space () { return _space; }
|
||||
/** retrieves the data accessor */
|
||||
data_access *&dat_access() { return _dat_access ; }
|
||||
|
||||
/**
|
||||
* Main algorithm
|
||||
* \param iso isovalue
|
||||
*/
|
||||
bool tesselate_cube( real iso ) ;
|
||||
|
||||
protected :
|
||||
/** tesselates one cube */
|
||||
bool process_cube () ;
|
||||
/** tests if the components of the tesselation of the cube should be connected by the interior of an ambiguous face */
|
||||
bool test_face ( schar face ) ;
|
||||
/** tests if the components of the tesselation of the cube should be connected through the interior of the cube */
|
||||
bool test_interior( schar s ) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
protected :
|
||||
/** computes almost all the vertices of the mesh by interpolation along the cubes edges */
|
||||
bool compute_intersection_points() ;
|
||||
|
||||
/** adds a vertex on edge cube[i] cube[j] */
|
||||
bool add_vertex( char i, char j ) ;
|
||||
|
||||
/** compute a vertex inside the current cube */
|
||||
bool comp_c_vertex() ;
|
||||
|
||||
/**
|
||||
* routine to add a triangle to the mesh
|
||||
* \param trig the code for the triangle as a sequence of edges index
|
||||
* \param n the number of triangles to produce
|
||||
* \param v12 the index of the interior vertex to use, if necessary
|
||||
*/
|
||||
void draw_triangle ( const char* trig, char n, int v12 = -1 ) ;
|
||||
|
||||
/** prints cube for debug */
|
||||
void print_cube() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
protected :
|
||||
bool _originalMC ; /**< selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes */
|
||||
|
||||
real _cube[8] ; /**< values of the implicit function on the active cube */
|
||||
Point _space[8] ; /**< coordinates of the active cube */
|
||||
Point _verts[8][8] ; /**< coordinates of the vertices, per edge */
|
||||
Point _c_vert ; /**< coordinates of the central vertex */
|
||||
uchar _lut_entry ; /**< cube sign representation in [0..255] */
|
||||
uchar _case ; /**< case of the active cube in [0..15] */
|
||||
uchar _config ; /**< configuration of the active cube */
|
||||
uchar _subconfig ; /**< subconfiguration of the active cube */
|
||||
data_access *_dat_access ; /**< data accessor */
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,367 @@
|
||||
/**
|
||||
* \file mem_octree.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* Octree structure with hashtable and optimized operations without auxiliary memory
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "mlist.h"
|
||||
#include "cube.h"
|
||||
#include "hash.h"
|
||||
#include "MarchingCubes.h"
|
||||
#include "mc_draw.h"
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// MemOctree
|
||||
/// \class MemOctree MemOctree.h
|
||||
class MemOctree
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// forward declaration
|
||||
public:
|
||||
class geom_cell ;
|
||||
class cell_iterator ;
|
||||
class leaf_iterator ;
|
||||
|
||||
// Elements
|
||||
protected:
|
||||
/// Octree cell data structure
|
||||
typedef Hash<real> HashField ;
|
||||
|
||||
/// Hashtable of the octree nodes
|
||||
HashField _hash ;
|
||||
|
||||
/// Level distribution of the octree
|
||||
uint _level_dist[MAX_LEVEL+1] ;
|
||||
|
||||
/// Memimal level for direct search in the octree
|
||||
Level _opt_level ;
|
||||
|
||||
/// Maximal field of the octree
|
||||
real _max_field ;
|
||||
|
||||
/// Isosurface
|
||||
MarchingCubes _mc ;
|
||||
|
||||
/// Isosurface Draw
|
||||
MC_Draw _mc_draw ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs a octree with and empty root
|
||||
MemOctree() { init() ; }
|
||||
|
||||
/// Destructor: Free memory
|
||||
~MemOctree() { clear() ; }
|
||||
|
||||
|
||||
/// Create the root
|
||||
void init() ;
|
||||
|
||||
/// Memory cleaning
|
||||
void clear() { clear_octree() ; _mc.clean_all() ; }
|
||||
|
||||
/// Delete the content of the octree
|
||||
void clear_octree() ;
|
||||
|
||||
/// Compute the optimal level
|
||||
void compute_opt_level() ;
|
||||
|
||||
/// Check that only the leaves have data
|
||||
bool check () ;
|
||||
|
||||
/// Prints statistics about the octree
|
||||
void stats() const ;
|
||||
|
||||
/// Return the maximal level of the octree
|
||||
Level max_level() const { Level lv = MAX_LEVEL ; while( lv > 0 && !_level_dist[lv] ) --lv ; return lv ; }
|
||||
|
||||
/// Return the optimal level of the octree
|
||||
Level opt_level() const { return _opt_level ; }
|
||||
|
||||
/// Return the optimal level of the octree
|
||||
Level &opt_level() { return _opt_level ; }
|
||||
|
||||
/// Return the maximal field of the octree
|
||||
real max_field() const { return _max_field ; }
|
||||
|
||||
/// Return the isosurface
|
||||
MarchingCubes &mc() { return _mc ; }
|
||||
|
||||
/// Return the isosurface draw
|
||||
MC_Draw &mc_draw() { return _mc_draw ; }
|
||||
|
||||
/// set the values of each leaf from the implicit function
|
||||
bool set_impl( data_access *ref = NULL ) ;
|
||||
|
||||
/// Refine the octree according to the data access
|
||||
bool refine( data_access *ref = NULL ) ;
|
||||
|
||||
/// Adapt the octree according to the data access
|
||||
bool adapt( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the octree with wireframe
|
||||
bool draw_wire() ;
|
||||
|
||||
/// Draw the octree with dots
|
||||
bool draw_centers() ;
|
||||
|
||||
/// Dual function type
|
||||
typedef bool mem_dual_walker( MemOctree &fo, Key *keys ) ;
|
||||
|
||||
/// Walk on the dual cubes
|
||||
bool dual_cubes_walk( mem_dual_walker &walker ) ;
|
||||
|
||||
/// Build the isosurface using dual marching cubes
|
||||
bool build_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the isosurface on-the-fly using dual marching cubes
|
||||
bool direct_draw_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the dual octree with wireframe
|
||||
bool draw_dual() ;
|
||||
|
||||
/// Do nothing, just for dual generation timing
|
||||
bool dual_timing() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterators
|
||||
public:
|
||||
/// Create an iterator traversing the tree from the root
|
||||
inline cell_iterator cells_begin() { return cell_iterator( *this ) ; }
|
||||
|
||||
/// Create an iterator traversing the leaves of the tree from the root
|
||||
inline leaf_iterator leaves_begin() { return leaf_iterator( *this ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// search operations
|
||||
public:
|
||||
/// Find cells of the octree at a given position
|
||||
bool find_leaf( Key k, Level o_lv, geom_cell &cell ) const ;
|
||||
bool find_leaf( Key k, geom_cell &cell ) const { return find_leaf( k, opt_level(), cell ) ; }
|
||||
bool find_leaf( real x, real y, real z, geom_cell &cell ) const { return find_leaf( cube2key( Cube(x,y,z,MAX_LEVEL) ), opt_level(), cell ) ; }
|
||||
|
||||
/// Find cells of the octree inside a given box of center x,y,z and half side r
|
||||
bool find_radius( real x, real y, real z, real r, List<geom_cell> &cells ) const ;
|
||||
|
||||
/// Find adjacent cells of the octree to a given cell
|
||||
bool adjacent( Key k, List<geom_cell> &cells ) const ;
|
||||
bool adjacent( const geom_cell &cell, List<geom_cell> &cells ) const { return adjacent( cell.key(), cells ) ; }
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( const HashField::KeyData &kd ) const { return !is_inv( kd.data ) ; }
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( Key k, real &d ) const { const HashField::KeyData &kd = _hash[k] ; d = kd.data ; return is_leaf( kd ) ; }
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( Key k ) const { return is_leaf( _hash[k] ) ; }
|
||||
|
||||
/// Node existence
|
||||
bool node_exists( Key k, HashField::KeyData &kd ) const { kd = _hash[k] ; return kd.key != KEY_INV ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// I/O
|
||||
public:
|
||||
|
||||
/// Draws the intersecting cells of a plane with the octree with color
|
||||
void draw_plane ( real nx, real ny, real nz, real d ) ;
|
||||
|
||||
/// Draws the intersection of a plane with the octree with color
|
||||
void draw_slice ( real nx, real ny, real nz, real d, float alpha ) ;
|
||||
|
||||
/// Draws the isosurface of level l inside the dual graph
|
||||
void draw_iso () { _mc.draw_surf() ; }
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Iterator Cell
|
||||
public :
|
||||
/// Auxiliary structure to traverse the octree
|
||||
class geom_cell : public Cube
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class MemOctree ;
|
||||
|
||||
protected:
|
||||
Key _key ; ///< octree cell
|
||||
real _field ; ///< field associated to the cell
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor
|
||||
geom_cell( Key key_ = KEY_INV, real field_ = R_INV ) : Cube(key2cube(key_)), _key(key_), _field(field_) {}
|
||||
|
||||
/// Default constructor
|
||||
geom_cell( HashField::KeyData kd ) : Cube(key2cube(kd.key)), _key(kd.key), _field(kd.data) {}
|
||||
|
||||
/// Destructor
|
||||
~geom_cell() {}
|
||||
|
||||
/// Copy constructor
|
||||
geom_cell( const geom_cell &i ) : Cube(i), _key(i._key), _field(i._field) {}
|
||||
|
||||
/// Assignment operator
|
||||
geom_cell &operator = ( const geom_cell &i )
|
||||
{ Cube::operator=(i) ; _key = i._key ; _field = i._field ; return *this; }
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Public constant accessors
|
||||
public :
|
||||
/// key const accessor
|
||||
inline Key key() const { return _key ; }
|
||||
/// key accessor
|
||||
inline Key &key() { return _key ; }
|
||||
|
||||
/// id const accessor
|
||||
inline real operator*() const { return _field ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Tests
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const geom_cell &i ) const { return key() == i.key() ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const geom_cell &i ) const { return key() != i.key() ; }
|
||||
|
||||
/// leaf test
|
||||
inline bool is_leaf() const { return !is_inv(*(*this)) ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return key() != KEY_INV ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// sons
|
||||
inline bool sons( geom_cell *s /*[8]*/, const HashField &hash )
|
||||
{
|
||||
if( is_leaf() ) return false ;
|
||||
|
||||
Key k = _key << 3 ;
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
s[i]._key = k | i ;
|
||||
s[i]._field = hash[k|i].data ;
|
||||
(Cube&)s[i] = key2cube(s[i]._key) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
};
|
||||
|
||||
const geom_cell geom_root() const { const Key root_key = 1 ; return geom_cell( root_key, _hash[root_key].data ) ; }
|
||||
const geom_cell geom_key ( Key k ) const { return geom_cell( k, _hash[k].data ) ; }
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Cell Iterator
|
||||
public :
|
||||
/// Octree cell iterator : Traverse the octree returning basic information on the cells
|
||||
class cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class MemOctree ;
|
||||
|
||||
protected:
|
||||
/// Octree traversal iterator
|
||||
HashField::iterator _it ;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor : Constructs an iterator from a cell
|
||||
cell_iterator( MemOctree &o ) : _it( o._hash.begin() ) {}
|
||||
|
||||
/// Destructor
|
||||
~cell_iterator() {}
|
||||
|
||||
/// Copy constructor
|
||||
cell_iterator( const cell_iterator &i ) : _it(i._it) {}
|
||||
|
||||
/// Assignment operator
|
||||
cell_iterator &operator = ( const cell_iterator &i )
|
||||
{ _it = i._it; return *this; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const cell_iterator &i ) const { return _it == i._it ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const cell_iterator &i ) const { return _it != i._it ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _it() ; }
|
||||
|
||||
/// next position
|
||||
inline cell_iterator &operator ++() { ++_it ; return *this ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
// cell accessor
|
||||
inline geom_cell top() const { return geom_cell( key(), *_it ) ; }
|
||||
|
||||
/// id accessor
|
||||
inline real &operator*() { return *_it ; }
|
||||
|
||||
/// level accessor
|
||||
inline Level lv() { return key_level(_it.key()) ; }
|
||||
|
||||
/// size accessor
|
||||
inline real sz() { return Cube(0,0,0,lv()).sz() ; }
|
||||
|
||||
/// key accessor
|
||||
inline Key key() const { return _it.key() ; }
|
||||
|
||||
/// points accessor
|
||||
inline bool is_leaf() const { return !is_inv(*_it) ; }
|
||||
|
||||
/// Draws the cell wire with opengl
|
||||
void draw_wire () const { top().draw_wire () ; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// Octree leaf iterator : Traverse the octree returning basic information on the leaves
|
||||
class leaf_iterator : public cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
public :
|
||||
leaf_iterator( MemOctree &o ) : cell_iterator( o )
|
||||
{ if( (*this)() && !this->is_leaf() ) ++(*this) ; }
|
||||
|
||||
|
||||
/// next position
|
||||
inline leaf_iterator &operator ++()
|
||||
{
|
||||
cell_iterator &it = *this ;
|
||||
do ++it ; while ( it() && !it.is_leaf() ) ;
|
||||
return *this ;
|
||||
}
|
||||
} ;
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,502 @@
|
||||
/**
|
||||
* @file mlist.h
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @version 0.3
|
||||
* @date 28/06/2004
|
||||
*
|
||||
* @brief template list class
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h> // qsort
|
||||
|
||||
typedef unsigned int lsize ;
|
||||
typedef const lsize clsize ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// template list class
|
||||
template <typename T> class List
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// types
|
||||
public :
|
||||
class node ;
|
||||
class iterator ;
|
||||
class const_iterator ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// default constructors
|
||||
public :
|
||||
/// default constructors
|
||||
List() : _first((node*)NULL) {}
|
||||
|
||||
/// one-element constructor
|
||||
List( const T &val ) : _first((node*)NULL) { insert(val) ; }
|
||||
|
||||
/// copy constructor (reverse order)
|
||||
List( const List<T> &l ) : _first((node*)NULL)
|
||||
{
|
||||
for( const_iterator it = l.cbegin() ; it() ; ++it )
|
||||
insert( *it ) ;
|
||||
}
|
||||
|
||||
/// assignment operator
|
||||
List<T> &operator = ( const List<T> &l ) { if( this != &l) { clear() ; for( const_iterator it = l.cbegin() ; it() ; ++it ) insert( *it ) ; } return *this; }
|
||||
|
||||
/// destructor
|
||||
~List() { clear() ; }
|
||||
|
||||
/// number of elements of the list
|
||||
clsize size() const { lsize n = 0 ; for( const_iterator it = cbegin() ; it() ; ++it ) ++n ; return n ; }
|
||||
|
||||
/// number of elements of the list
|
||||
bool size_greater( clsize m ) const { lsize n = 0 ; for( const_iterator it = cbegin() ; it() ; ++it ) { if(++n > m) return true ; } return false ; }
|
||||
|
||||
/// number of elements of the list
|
||||
bool size_greater_or_equal( clsize m ) const { if( m == 0 ) return true ; lsize n = 0 ; for( const_iterator it = cbegin() ; it() ; ++it ) { if(++n >= m) return true ; } return false ; }
|
||||
|
||||
/// tests if the list has one element
|
||||
bool empty () const { return _first == (node*)NULL ; }
|
||||
|
||||
/// tests if the list has two elements
|
||||
bool single() const { return !empty() && _first->next() == (node*)NULL ; }
|
||||
|
||||
/// tests if the list has three elements
|
||||
bool pair () const { return !empty() && _first->next() != (node*)NULL && _first->next()->next() == (node*)NULL ; }
|
||||
|
||||
/// tests if the list has more than three elements
|
||||
bool triple() const { return !empty() && _first->next() != (node*)NULL && _first->next()->next() != (node*)NULL ; }
|
||||
|
||||
const T first () const { return _first->val() ; } ///< first element accessor
|
||||
T &first () { return _first->val() ; } ///< first element accessor
|
||||
const T second() const { return _first->next()->val() ; } ///< second element accessor
|
||||
T &second() { return _first->next()->val() ; } ///< second element accessor
|
||||
const T third () const { return _first->next()->next()->val() ; } ///< third element accessor
|
||||
T &third () { return _first->next()->next()->val() ; } ///< third element accessor
|
||||
|
||||
/// get the first two elements
|
||||
bool firsts( T &t1, T &t2 ) const { if( !empty() ) { t1 = first() ; if( !single() ) { t2 = second() ; return true ; } } return false ; }
|
||||
/// get the first three elements
|
||||
bool firsts( T &t1, T &t2, T &t3 ) const { if( firsts( t1,t2 ) ) { if( !pair() ) t3 = third() ; return true ; } return false ; }
|
||||
|
||||
const T top () const { return _first->val() ; } ///< first element accessor
|
||||
T &top () { return _first->val() ; } ///< first element accessor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// clear
|
||||
public :
|
||||
/// destructor
|
||||
void clear()
|
||||
{
|
||||
node *p = _first ;
|
||||
while( p != (node*)NULL )
|
||||
{
|
||||
node *n = p->next() ;
|
||||
delete p ;
|
||||
p = n ;
|
||||
}
|
||||
_first = (node*)NULL ;
|
||||
}
|
||||
|
||||
/// emptyness test
|
||||
inline bool empty() { return _first == (node*)NULL ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// find and replace
|
||||
public :
|
||||
/// membership test
|
||||
const_iterator cfind( const T &val ) const { for( const_iterator it = cbegin() ; it() ; ++it ) if( (*it) == val ) return it ; return cend() ; }
|
||||
|
||||
/// membership test
|
||||
iterator find( const T &val ) { for( iterator it = begin() ; it() ; ++it ) if( (*it) == val ) return it ; return end() ; }
|
||||
|
||||
/// membership test (return also the last pointer for eventual remotion)
|
||||
iterator find( const T &val, iterator &lst ) { lst = end() ; for( iterator it = begin() ; it() ; ++it ) { if( *it == val ) return it ; lst = it ; } return end() ; }
|
||||
|
||||
/// membership test
|
||||
clsize pos( const T &val ) const { lsize i = 0 ; for( const_iterator it = cbegin() ; it() ; ++it, ++i ) if( *it == val ) return i ; return (clsize)-1 ; }
|
||||
|
||||
/// get the minimal element
|
||||
const_iterator min_val() const { if( empty() ) return cend() ; const_iterator it = cbegin(), m = it ; for( ++it ; it() ; ++it ) { if( *it < *m ) m = it ; } return m ; }
|
||||
|
||||
/// get the minimal element
|
||||
iterator min_val() { if( empty() ) return end() ; iterator it = begin(), m = it ; for( ++it ; it() ; ++it ) { if( *it < *m ) m = it ; } return m ; }
|
||||
|
||||
/// get the maximal element
|
||||
const_iterator max_val() const { if( empty() ) return cend() ; const_iterator it = cbegin(), m = it ; for( ++it ; it() ; ++it ) { if( *it > *m ) m = it ; } return m ; }
|
||||
|
||||
/// get the maximal element
|
||||
iterator max_val() { if( empty() ) return end() ; iterator it = begin(), m = it ; for( ++it ; it() ; ++it ) { if( *it > *m ) m = it ; } return m ; }
|
||||
|
||||
/// replacing the elements of a list
|
||||
clsize replace( const T &old_val, const T &new_val )
|
||||
{
|
||||
lsize n = 0 ;
|
||||
for( iterator it = begin() ; it() ; ++it )
|
||||
if( *it == old_val ) { *it = new_val ; ++n ; }
|
||||
return n ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element insertion
|
||||
public :
|
||||
/// insertion at the beginning
|
||||
inline void push_front( const T &val ) { _first = new node( val, _first ) ; }
|
||||
|
||||
/// insertion in the middle
|
||||
iterator push_after( const T &val, iterator i = begin() )
|
||||
{
|
||||
if( i == end() ) { push_front( val ) ; return begin() ; }
|
||||
i._node->next() = new node( val, i._node->next() ) ;
|
||||
return ++i ;
|
||||
}
|
||||
|
||||
/// insertion at the end
|
||||
iterator push_back( const T &val )
|
||||
{
|
||||
return push_after( val, last() ) ;
|
||||
}
|
||||
|
||||
/// insertion
|
||||
inline void insert( const T &val ) { push_front( val ) ; }
|
||||
|
||||
/// insertion
|
||||
inline void push( const T &val ) { push_front( val ) ; }
|
||||
|
||||
/// insertion without duplicates
|
||||
inline bool insert_unique( const T &val ) { if( !find(val)() ) {push_front( val ); return true;} return false; }
|
||||
|
||||
|
||||
/// list insertion (reverse, at the begining)
|
||||
void insert( const List<T> &l )
|
||||
{ for( const_iterator lit = l.cbegin() ; lit() ; ++lit ) insert( *lit ) ; }
|
||||
|
||||
/// list insertion without duplicates (reverse, at the begining)
|
||||
void insert_unique( const List<T> &l )
|
||||
{ for( const_iterator lit = l.cbegin() ; lit() ; ++lit ) insert_unique( *lit ) ; }
|
||||
|
||||
/// list insertion (ordered)
|
||||
void insert_ordered( const List<T> &l )
|
||||
{
|
||||
const_iterator lit = l.cbegin() ;
|
||||
iterator it = push_back( *lit ) ;
|
||||
for( ; lit() ; ++lit )
|
||||
it = push_after( *lit, it ) ;
|
||||
}
|
||||
|
||||
|
||||
/// copy a list and clear its content
|
||||
void insert_and_clear( List<T> &l )
|
||||
{
|
||||
if( this == &l ) return ;
|
||||
iterator lst = last() ;
|
||||
if( lst() )
|
||||
lst._node->next() = l._first ;
|
||||
else
|
||||
_first = l._first ;
|
||||
l._first = NULL ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element remotion
|
||||
public :
|
||||
/// removing the first element of the list
|
||||
void remove_first()
|
||||
{
|
||||
node *p = _first->next() ;
|
||||
delete _first ;
|
||||
_first = p ;
|
||||
}
|
||||
|
||||
/// removing the first element of the list
|
||||
void pop() { remove_first() ; }
|
||||
|
||||
/// removing elements from the list
|
||||
void remove_next( iterator &prev )
|
||||
{
|
||||
node *p ;
|
||||
if( prev == end() )
|
||||
{ p = _first->next() ; delete _first ; _first = p ; }
|
||||
else if( prev._node )
|
||||
{ p = prev._node->next() ; prev._node->next() = p->next() ; delete p ; }
|
||||
}
|
||||
|
||||
/// removing elements from the list
|
||||
bool remove( T &val )
|
||||
{
|
||||
iterator prev = end() ;
|
||||
for( iterator it = begin() ; it() ; )
|
||||
{
|
||||
if( *it != val ) { prev = it ; ++it ; continue ; }
|
||||
val = *it ;
|
||||
node *p ;
|
||||
if( prev == end() )
|
||||
{ p = _first->next() ; delete _first ; _first = p ; it = begin() ; }
|
||||
else
|
||||
{ p = it._node ; prev._node->next() = it._node->next() ; delete p ; it = prev ; ++it ; }
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
/// removing elements from the list
|
||||
clsize remove_all( const T &val )
|
||||
{
|
||||
lsize n = 0 ;
|
||||
iterator prev = end() ;
|
||||
for( iterator it = begin() ; it() ; )
|
||||
{
|
||||
if( *it != val ) { prev = it ; ++it ; continue ; }
|
||||
node *p ;
|
||||
if( prev == end() )
|
||||
{ p = _first->next() ; delete _first ; _first = p ; it = begin() ; }
|
||||
else
|
||||
{ p = it._node ; prev._node->next() = it._node->next() ; delete p ; it = prev ; ++it ; }
|
||||
++n ;
|
||||
if( !it() ) return n ;
|
||||
}
|
||||
return n ;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// sort
|
||||
public :
|
||||
/// array transform
|
||||
void get_array( T *a, clsize sz /*= size()*/ )
|
||||
{
|
||||
lsize i = 0 ;
|
||||
for( const_iterator it = cbegin() ; it() && i < sz ; ++it, ++i )
|
||||
a[i] = *it ;
|
||||
}
|
||||
|
||||
/// array transform
|
||||
T *get_array( clsize sz /*= size()*/ )
|
||||
{
|
||||
T *a = new T[sz] ;
|
||||
get_array( a,sz ) ;
|
||||
return a ;
|
||||
}
|
||||
|
||||
/// array read
|
||||
void set_array( clsize sz = 0, const T *a = (const T*)NULL )
|
||||
{
|
||||
clear() ;
|
||||
if( sz == 0 ) return ;
|
||||
push_front( a[0] ) ;
|
||||
iterator it = begin() ;
|
||||
for( lsize i = 1 ; i < sz ; ++i )
|
||||
it = push_after( a[i], it ) ;
|
||||
}
|
||||
|
||||
/// sort
|
||||
void sort( int compare(const void*,const void*) )
|
||||
{
|
||||
clsize sz = size() ;
|
||||
T *a = get_array( sz ) ;
|
||||
qsort( (void*)a, sz, sizeof(T), compare ) ;
|
||||
set_array( sz, a ) ;
|
||||
delete [] a ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
node *_first; ///< link to the first element
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// node representation
|
||||
public :
|
||||
/// node of a list
|
||||
class node
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
node( T val_, node *next_ = (node*)NULL ) : _val (val_) , _next (next_) {}
|
||||
|
||||
/// destructor
|
||||
~node() {}
|
||||
|
||||
/// copy constructor
|
||||
node( const node &n ) : _val(n.val()), _next(n.next()) {}
|
||||
|
||||
/// assignment operator
|
||||
node &operator = ( const node &n )
|
||||
{ _val = n.val(); _next = n.next(); return this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
inline const T &val () const { return _val ; } ///< accesses the value of the node
|
||||
inline const node *next() const { return _next ; } ///< accesses the next element
|
||||
|
||||
inline T &val () { return _val ; } ///< accesses the value of the node
|
||||
inline node *&next() { return _next ; } ///< accesses the next element
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
T _val ; ///< value
|
||||
node *_next; ///< link to the next element
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// const_iterator
|
||||
public :
|
||||
/// list const iterator
|
||||
class const_iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
const_iterator( node *n = (node*)NULL ) : _node(n) {}
|
||||
|
||||
/// destructor
|
||||
~const_iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
const_iterator( const const_iterator &i ) : _node(i._node) {}
|
||||
|
||||
/// assignment operator
|
||||
const_iterator &operator = ( const const_iterator &i )
|
||||
{ _node = i._node; return *this; }
|
||||
|
||||
friend class List<T> ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
inline bool operator ==( const const_iterator &i ) const { return _node == i._node ; } ///< equality operator
|
||||
inline bool operator !=( const const_iterator &i ) const { return _node != i._node ; } ///< inequality operator
|
||||
inline bool operator ()() const { return _node != (node*)NULL ; } ///< validation operator
|
||||
inline const T &operator * () const { return _node->val() ; } ///< value accessor
|
||||
inline const_iterator &operator ++() { _node = _node->next() ; return *this ; } ///< accesses the next position
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
node *_node; ///< node position
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterator
|
||||
public :
|
||||
/// list iterator
|
||||
class iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
iterator( node *n = (node*)NULL ) : _node(n) {}
|
||||
|
||||
/// destructor
|
||||
~iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
iterator( const iterator &i ) : _node(i._node) {}
|
||||
|
||||
/// assignment operator
|
||||
iterator &operator = ( const iterator &i )
|
||||
{ _node = i._node; return *this; }
|
||||
|
||||
friend class List <T> ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
inline bool operator ==( const iterator &i ) const { return _node == i._node ; } ///< equality operator
|
||||
inline bool operator !=( const iterator &i ) const { return _node != i._node ; } ///< inequality operator
|
||||
inline bool operator ()() const { return _node != (node*)NULL ; } ///< validation operator
|
||||
inline T &operator * () const { return _node->val() ; } ///< value accessor
|
||||
inline iterator &operator ++() { _node = _node->next() ; return *this ; } ///< accesses the next position
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
node *_node; ///< node position
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterator creation
|
||||
public :
|
||||
inline const_iterator cbegin() const { return const_iterator( _first ) ; } ///< iterator creation
|
||||
inline const_iterator cend () const { return const_iterator( (node*)NULL ) ; } ///< iterator end
|
||||
inline iterator begin() { return iterator( _first ) ; } ///< iterator creation
|
||||
inline iterator end () { return iterator( (node*)NULL ) ; } ///< iterator end
|
||||
|
||||
/// last position
|
||||
iterator last () { iterator lst = end(), it = begin() ; while( it() ) { lst = it ; ++it ; } return lst ; }
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// template list class
|
||||
template <typename T> class Queue : public List<T>
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
// default constructors
|
||||
public :
|
||||
/// default constructors
|
||||
Queue() : List<T>() { _last = this->end() ; }
|
||||
|
||||
/// one-element constructor
|
||||
Queue( const T &val ) : List<T>( val ) { _last = this->begin() ; }
|
||||
|
||||
/// copy constructor (reverse order)
|
||||
Queue( const Queue<T> &q ) : List<T>()
|
||||
{ for( typename List<T>::const_iterator it = q.cbegin() ; it() ; ++it ) Queue<T>::insert( *it ) ; }
|
||||
|
||||
/// assignment operator
|
||||
Queue<T> &operator = ( const Queue<T> &q )
|
||||
{ if( this != &q) { this->clear() ; for( typename List<T>::const_iterator it = q.cbegin() ; it() ; ++it ) insert( *it ) ; } return *this; }
|
||||
|
||||
/// destructor
|
||||
~Queue() { this->clear() ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element insertion
|
||||
public :
|
||||
/// insertion at the end
|
||||
inline void insert( const T &val )
|
||||
{ _last = push_after( val, _last ) ; }
|
||||
|
||||
/// queue insertion
|
||||
void insert( const Queue<T> &l )
|
||||
{ for( typename List<T>::const_iterator lit = l.cbegin() ; lit() ; ++lit ) insert( *lit ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// stqndqrd function
|
||||
public :
|
||||
/// first element
|
||||
inline const T front() const { return this->first() ; }
|
||||
|
||||
/// insertion at the end
|
||||
inline void push( const T &val ) { this->insert( val ) ; }
|
||||
|
||||
/// deletion at the beginning
|
||||
inline void pop () { this->remove_first() ; if( this->empty() ) _last = this->end() ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
typename List<T>::iterator _last; ///< link to the last element
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
@ -0,0 +1,458 @@
|
||||
/**
|
||||
* \file morton.cpp
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Rener Pereira de Castro <rener@mat.puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* \brief Morton codes manipulation
|
||||
*
|
||||
* Morton codes manipulation
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma implementation
|
||||
#endif // WIN32
|
||||
|
||||
#include "morton.h"
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// static
|
||||
#ifdef UNIX
|
||||
real R_INV = strtof("NAN(char-sequence)", NULL); //nanf(0) ;
|
||||
#else
|
||||
real R_INV = nan(0) ;
|
||||
#endif
|
||||
|
||||
Level L_INV = (Level)-1 ;
|
||||
Point P_INV( R_INV, R_INV, R_INV ) ;
|
||||
Cube C_INV( P_INV, L_INV ) ;
|
||||
Key KEY_INV = 0 ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Static Members Aux
|
||||
|
||||
|
||||
// 1 << ((dz==0)+(dy==0)+(dx==0))
|
||||
static const char nsubneighbors[27] = { 1, // Direction (-1,-1,-1)
|
||||
2, // Direction (-1,-1, 0)
|
||||
1, // Direction (-1,-1, 1)
|
||||
2, // Direction (-1, 0,-1)
|
||||
4, // Direction (-1, 0, 0)
|
||||
2, // Direction (-1, 0, 1)
|
||||
1, // Direction (-1, 1,-1)
|
||||
2, // Direction (-1, 1, 0)
|
||||
1, // Direction (-1, 1, 1)
|
||||
2, // Direction ( 0,-1,-1)
|
||||
4, // Direction ( 0,-1, 0)
|
||||
2, // Direction ( 0,-1, 1)
|
||||
4, // Direction ( 0, 0,-1)
|
||||
0, // Direction ( 0, 0, 0)
|
||||
4, // Direction ( 0, 0, 1)
|
||||
2, // Direction ( 0, 1,-1)
|
||||
4, // Direction ( 0, 1, 0)
|
||||
2, // Direction ( 0, 1, 1)
|
||||
1, // Direction ( 1,-1,-1)
|
||||
2, // Direction ( 1,-1, 0)
|
||||
1, // Direction ( 1,-1, 1)
|
||||
2, // Direction ( 1, 0,-1)
|
||||
4, // Direction ( 1, 0, 0)
|
||||
2, // Direction ( 1, 0, 1)
|
||||
1, // Direction ( 1, 1,-1)
|
||||
2, // Direction ( 1, 1, 0)
|
||||
1, // Direction ( 1, 1, 1)
|
||||
};
|
||||
|
||||
static const char l3b[27][4] = { {7,-1,-1,-1},{6, 7,-1,-1},{6,-1,-1,-1},{5, 7,-1,-1},{4, 5, 6, 7},{4, 6,-1,-1},{ 5,-1,-1,-1},
|
||||
{4, 5,-1,-1},{4,-1,-1,-1},{3, 7,-1,-1},{2, 3, 6, 7},{2, 6,-1,-1},{1, 3, 5, 7},{-1,-1,-1,-1},
|
||||
{0, 2, 4, 6},{1, 5,-1,-1},{0, 1, 4, 5},{0, 4,-1,-1},{3,-1,-1,-1},{2, 3,-1,-1},{ 2,-1,-1,-1},
|
||||
{1, 3,-1,-1},{0, 1, 2, 3},{0, 2,-1,-1},{1,-1,-1,-1},{0, 1,-1,-1},{0,-1,-1,-1},};
|
||||
//_____________________________________________________________________________
|
||||
// Contraction and Dilatation Masks
|
||||
static const uint three_2 = 9 ;
|
||||
static const uint three_1 = 3 ;
|
||||
static const uint three_0 = 1 ;
|
||||
static const uint shift_2a = 18, shift_2b = 36 ;
|
||||
static const uint shift_1a = 6, shift_1b = 12 ;
|
||||
static const uint shift_0a = 2, shift_0b = 4 ;
|
||||
static const Key dilate_mask_2 = (Key)0x7FC0000FF80001FFLL ; // bits 1 from 0-9, 27-36 and 54-63
|
||||
static const Key dilate_mask_1 = (Key)0x01C0E070381C0E07LL ; // bits 1 from 0-3, 9-12, 18-21,...
|
||||
static const Key dilate_mask_0 = (Key)0x9249249249249249LL ; // bits 1 at 0,3,6,9,12,...
|
||||
static const Key dilate_tz = (Key)0x4924924924924924LL ; // bits 1 at 2,5,8,11,14,... rigth to left
|
||||
static const Key dilate_ty = (Key)0x2492492492492492LL ; // bits 1 at 1,4,7,10,13,...
|
||||
static const Key dilate_tx = (Key)0x9249249249249249LL ; // bits 1 at 0,3,6,9,12,...
|
||||
static const Key dilate_t1 = (Key)0xB6DB6DB6DB6DB6DBLL ; // bits 0 at 2,5,8,11,14,... = ~tz
|
||||
static const Key dilate_t2 = (Key)0xDB6DB6DB6DB6DB6DLL ; // bits 0 at 1,4,7,10,13,... = ~ty
|
||||
static const Key dilate_t3 = (Key)0x6DB6DB6DB6DB6DB6LL ; // bits 0 at 0,3,6,9,12,... = ~tx
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Step Directions Find Neighbours - 26 (dz,dy,dx)
|
||||
static const Key dir_neigh[27] = { (Key)0xFFFFFFFFFFFFFFFFLL , // Direction (-1,-1,-1)
|
||||
(Key)0x6DB6DB6DB6DB6DB6LL , // Direction (-1,-1, 0)
|
||||
(Key)0x6DB6DB6DB6DB6DB7LL , // Direction (-1,-1, 1)
|
||||
(Key)0xDB6DB6DB6DB6DB6DLL , // Direction (-1, 0,-1)
|
||||
(Key)0x4924924924924924LL , // Direction (-1, 0, 0)
|
||||
(Key)0x4924924924924925LL , // Direction (-1, 0, 1)
|
||||
(Key)0xDB6DB6DB6DB6DB6FLL , // Direction (-1, 1,-1)
|
||||
(Key)0x4924924924924926LL , // Direction (-1, 1, 0)
|
||||
(Key)0x4924924924924927LL , // Direction (-1, 1, 1)
|
||||
(Key)0xB6DB6DB6DB6DB6DBLL , // Direction ( 0,-1,-1)
|
||||
(Key)0x2492492492492492LL , // Direction ( 0,-1, 0)
|
||||
(Key)0x2492492492492493LL , // Direction ( 0,-1, 1)
|
||||
(Key)0x9249249249249249LL , // Direction ( 0, 0,-1)
|
||||
(Key)0x0000000000000000LL , // Direction ( 0, 0, 0)
|
||||
(Key)0x0000000000000001LL , // Direction ( 0, 0, 1)
|
||||
(Key)0x924924924924924BLL , // Direction ( 0, 1,-1)
|
||||
(Key)0x0000000000000002LL , // Direction ( 0, 1, 0)
|
||||
(Key)0x0000000000000003LL , // Direction ( 0, 1, 1)
|
||||
(Key)0xB6DB6DB6DB6DB6DFLL , // Direction ( 1,-1,-1)
|
||||
(Key)0x2492492492492496LL , // Direction ( 1,-1, 0)
|
||||
(Key)0x2492492492492497LL , // Direction ( 1,-1, 1)
|
||||
(Key)0x924924924924924DLL , // Direction ( 1, 0,-1)
|
||||
(Key)0x0000000000000004LL , // Direction ( 1, 0, 0)
|
||||
(Key)0x0000000000000005LL , // Direction ( 1, 0, 1)
|
||||
(Key)0x924924924924924FLL , // Direction ( 1, 1,-1)
|
||||
(Key)0x0000000000000006LL , // Direction ( 1, 1, 0)
|
||||
(Key)0x0000000000000007LL , // Direction ( 1, 1, 1)
|
||||
};
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// octree depth level associated to a morton key ( = (bit length - 1) / 3 )
|
||||
Level key_level ( Key k )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
static const real lg2_3 = 1.0 / (log(2)*3) ;
|
||||
if( k == KEY_INV ) return L_INV ;
|
||||
return (Level) floor( log(k) * lg2_3 ) ;
|
||||
/*
|
||||
Level count = 0 ;
|
||||
do
|
||||
{
|
||||
k >>= 3 ;
|
||||
++count;
|
||||
}
|
||||
while( k > 0 ) ;
|
||||
|
||||
return count-1 ;
|
||||
*/
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// containment text implemented directly onf the key
|
||||
bool key_contains( Key k_big, Key k_small )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
while( (k_small!=KEY_INV) && ((k_small>>3) != k_big) )
|
||||
k_small >>= 3;
|
||||
return k_small != KEY_INV ;
|
||||
// k_small & 7
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// convert an octree cube to a morton key using integer contraction
|
||||
Key cube2key ( const Cube &c )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
uint level = c.lv();
|
||||
Key m = 1 << level ;
|
||||
real sz = (real) m ;
|
||||
|
||||
Key bz = (Key) floor( c.z() * sz ) ;
|
||||
Key by = (Key) floor( c.y() * sz ) ;
|
||||
Key bx = (Key) floor( c.x() * sz ) ;
|
||||
/*
|
||||
if( bz >= m ) bz = m-1 ;
|
||||
if( by >= m ) by = m-1 ;
|
||||
if( bx >= m ) bx = m-1 ;
|
||||
*/
|
||||
|
||||
if( level > three_2 )
|
||||
{
|
||||
bz = ( bz | (bz << shift_2a) | (bz << shift_2b) ) & dilate_mask_2 ;
|
||||
by = ( by | (by << shift_2a) | (by << shift_2b) ) & dilate_mask_2 ;
|
||||
bx = ( bx | (bx << shift_2a) | (bx << shift_2b) ) & dilate_mask_2 ;
|
||||
}
|
||||
if( level > three_1 )
|
||||
{
|
||||
bz = ( bz | (bz << shift_1a) | (bz << shift_1b) ) & dilate_mask_1 ;
|
||||
by = ( by | (by << shift_1a) | (by << shift_1b) ) & dilate_mask_1 ;
|
||||
bx = ( bx | (bx << shift_1a) | (bx << shift_1b) ) & dilate_mask_1 ;
|
||||
}
|
||||
if( level > three_0 )
|
||||
{
|
||||
bz = ( bz | (bz << shift_0a) | (bz << shift_0b) ) & dilate_mask_0 ;
|
||||
by = ( by | (by << shift_0a) | (by << shift_0b) ) & dilate_mask_0 ;
|
||||
bx = ( bx | (bx << shift_0a) | (bx << shift_0b) ) & dilate_mask_0 ;
|
||||
}
|
||||
return (Key(1) << (3*level)) | (bz << 2) | (by << 1) | bx ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// convert a morton key to a key using integer dilation
|
||||
const Cube key2cube ( Key key )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
if( key == KEY_INV )
|
||||
return C_INV ;
|
||||
|
||||
Level level = key_level( key ) ;
|
||||
Key bz( (key >> 2) & dilate_mask_0 ) ;
|
||||
Key by( (key >> 1) & dilate_mask_0 ) ;
|
||||
Key bx( ( key ) & dilate_mask_0 ) ;
|
||||
|
||||
if( level > three_0 )
|
||||
{
|
||||
bz = ( bz | (bz >> shift_0a) | (bz >> shift_0b) ) & dilate_mask_1 ;
|
||||
by = ( by | (by >> shift_0a) | (by >> shift_0b) ) & dilate_mask_1 ;
|
||||
bx = ( bx | (bx >> shift_0a) | (bx >> shift_0b) ) & dilate_mask_1 ;
|
||||
|
||||
if( level > three_1 )
|
||||
{
|
||||
bz = ( bz | (bz >> shift_1a) | (bz >> shift_1b) ) & dilate_mask_2 ;
|
||||
by = ( by | (by >> shift_1a) | (by >> shift_1b) ) & dilate_mask_2 ;
|
||||
bx = ( bx | (bx >> shift_1a) | (bx >> shift_1b) ) & dilate_mask_2 ;
|
||||
|
||||
if( level > three_2 )
|
||||
{
|
||||
bz = bz | (bz >> shift_2a) | (bz >> shift_2b) ;
|
||||
by = by | (by >> shift_2a) | (by >> shift_2b) ;
|
||||
bx = bx | (bx >> shift_2a) | (bx >> shift_2b) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Key length_mask = (1 << level) -1 ;
|
||||
bz &= length_mask ;
|
||||
by &= length_mask ;
|
||||
bx &= length_mask ;
|
||||
|
||||
Cube c ;
|
||||
c.lv() = level ;
|
||||
real sz = c.sz() ;
|
||||
real sz2 = sz*2 ;
|
||||
c.z() = (real)(bz) * sz2 + sz ;
|
||||
c.y() = (real)(by) * sz2 + sz ;
|
||||
c.x() = (real)(bx) * sz2 + sz ;
|
||||
|
||||
return c ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// addition in dilated integer
|
||||
Key addition_locate_code( const Key& N , const Key& DN )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
return (
|
||||
( ((N | dilate_t1) + (DN & dilate_tz)) & dilate_tz ) |
|
||||
( ((N | dilate_t2) + (DN & dilate_ty)) & dilate_ty ) |
|
||||
( ((N | dilate_t3) + (DN & dilate_tx)) & dilate_tx )
|
||||
);
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// addition in dilated integer
|
||||
Key substraction_locate_code( const Key& N , const Key& DN )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
return (
|
||||
( ((N & dilate_tz) - (DN & dilate_tz)) & dilate_tz ) |
|
||||
( ((N & dilate_ty) - (DN & dilate_ty)) & dilate_ty ) |
|
||||
( ((N & dilate_tx) - (DN & dilate_tx)) & dilate_tx )
|
||||
);
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// generate a list of 27 neighbor keys of same level, with their direction, indexed by 9*(dz+1) + 3*(dy+1) + (dx+1)
|
||||
bool neighbor_keys( Key k, Key *neighbors )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
Level nbits_neigh = 3*key_level(k) ;
|
||||
for( uint dir = 0 ; dir < 27 ; ++dir )
|
||||
{
|
||||
Key &nk = neighbors[dir] ;
|
||||
if( dir == 13 ) { nk = KEY_INV ; continue ; }
|
||||
nk = addition_locate_code( k , dir_neigh[dir] ) ;
|
||||
if( (nk >> nbits_neigh) != 1 )
|
||||
nk = KEY_INV ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// generate a list of the subneighbor keys from a neighbor direction
|
||||
// returns the number of subneighbors
|
||||
char subneighbor_keys( Key k, char dir, std::stack<Key> &subneighbors )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
k <<= 3 ;
|
||||
char nsub = nsubneighbors[dir] ;
|
||||
for( char i = 0 ; i < nsub ; ++i )
|
||||
{
|
||||
subneighbors.push( k | l3b[dir][i] ) ;
|
||||
}
|
||||
return nsub ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
void print_binary( const Key k )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
printf( "0x" ) ;
|
||||
for( char i = 63 ; i >= 0 ; --i )
|
||||
printf( "%c", (k>>i)&1 ? '1' : '0' ) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// generate a list of 8 vertices keys
|
||||
Level vertices_keys( Key k, Key *verts )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
Level lv = key_level(k) ;
|
||||
Key lv_k = 1 << (3*lv) ;
|
||||
Key lv_K = lv_k << 1 ;
|
||||
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
Key vk = addition_locate_code( k,i ) ;
|
||||
|
||||
if( vk >= lv_K || !((vk-lv_k)&dilate_tx) || !((vk-lv_k)&dilate_ty) || !((vk-lv_k)&dilate_tz) )
|
||||
{
|
||||
verts[i] = KEY_INV ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
verts[i] = vk << 3*(MAX_LEVEL - lv) ;
|
||||
}
|
||||
return lv ;
|
||||
|
||||
/*
|
||||
Level lv = key_level(k) ;
|
||||
Key lv_k = 1 << (3*lv) ;
|
||||
Key lv_K = lv_k << 1 ;
|
||||
|
||||
Cube c = key2cube(k) ;
|
||||
const real ix = c.x () ;
|
||||
const real iy = c.y () ;
|
||||
const real iz = c.z () ;
|
||||
const real is = c.sz() ;
|
||||
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
Key vk = addition_locate_code( k,i ) ;
|
||||
Cube v( (i&1) ? ix+is : ix-is,
|
||||
(i&2) ? iy+is : iy-is,
|
||||
(i&4) ? iz+is : iz-is,
|
||||
MAX_LEVEL ) ;
|
||||
bool invalid = (
|
||||
v.x() <= 0.0 || v.x() >= 1 ||
|
||||
v.y() <= 0.0 || v.y() >= 1 ||
|
||||
v.z() <= 0.0 || v.z() >= 1
|
||||
) ;
|
||||
bool k_invalid = vk >= lv_K || !((vk-lv_k)&dilate_tx) || !((vk-lv_k)&dilate_ty) || !((vk-lv_k)&dilate_tz) ;
|
||||
if( invalid != k_invalid )
|
||||
printf( "problem\n" ) ;
|
||||
if( invalid )
|
||||
{
|
||||
verts[i] = KEY_INV ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
vk <<= 3*(MAX_LEVEL - lv) ;
|
||||
verts[i] = cube2key(v) ;
|
||||
if( vk != verts[i] )
|
||||
printf( "problem\n" ) ;
|
||||
}
|
||||
return c.lv() ;
|
||||
*/
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// generate a list of 8 dual vertices keys from a vertex key and the deepest neighbor level
|
||||
bool dual_vertices_keys( Key k, Level lv, Key *dual_verts )
|
||||
//_____________________________________________________________________________
|
||||
{
|
||||
Key dk = k >> (3*(MAX_LEVEL - lv)) ;
|
||||
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
dual_verts[i] = substraction_locate_code( dk,i ) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
/*
|
||||
Key dk = k >> (3*(MAX_LEVEL - lv)) ;
|
||||
|
||||
Cube c = key2cube( k ) ;
|
||||
c.lv() = lv ;
|
||||
|
||||
const real ix = c.x () ;
|
||||
const real iy = c.y () ;
|
||||
const real iz = c.z () ;
|
||||
const real is = c.sz() ;
|
||||
|
||||
// print_binary( k ) ;
|
||||
// printf( " <- \n" ) ;
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
Cube dv( (i&1) ? ix+is : ix-is,
|
||||
(i&2) ? iy+is : iy-is,
|
||||
(i&4) ? iz+is : iz-is,
|
||||
lv ) ;
|
||||
|
||||
dual_verts[i] = cube2key(dv) ;
|
||||
if( substraction_locate_code( dk,7-i) != dual_verts[i] )
|
||||
printf( "problem\n" ) ;
|
||||
// print_binary( dual_verts[i] ) ;
|
||||
// printf( "\n" ) ;
|
||||
// print_binary( substraction_locate_code( dk,7-i) ) ;
|
||||
// printf( "\n" ) ;
|
||||
}
|
||||
// printf( "\n" ) ;
|
||||
|
||||
return true ;
|
||||
*/
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
// testar que dois cubos se intersectam???
|
||||
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* \file morton.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Rener Pereira de Castro <rener@mat.puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* \brief Morton codes manipulation
|
||||
*
|
||||
* Morton codes manipulation
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stack>
|
||||
#include "cube.h"
|
||||
|
||||
typedef uint64_t Key;
|
||||
extern Key KEY_INV ;
|
||||
const uint MAX_LEVEL = (sizeof(Key)*8-1)/3 ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
/// octree depth level associated to a morton key ( = (bit length - 1) / 3 )
|
||||
Level key_level ( Key k ) ;
|
||||
|
||||
/// containment text implemented directly onf the key
|
||||
bool key_contains( Key k_big, Key k_small ) ;
|
||||
|
||||
/// convert an octree cube to a morton key using integer contraction
|
||||
Key cube2key ( const Cube &c ) ;
|
||||
|
||||
/// convert a morton key to a key using integer dilation
|
||||
const Cube key2cube ( Key k ) ;
|
||||
|
||||
/// generate a list of 27 neighbor keys of same level, with their direction, indexed by 9*(dx+1) + 3*(dy+1) + (dz+1)
|
||||
bool neighbor_keys( Key k, Key *neighbors ) ;
|
||||
|
||||
/// generate a list of the subneighbor keys from a neighbor direction, and return the number of subneighbors
|
||||
char subneighbor_keys( Key k, char dir, std::stack<Key> &subneighbors ) ;
|
||||
|
||||
/// generate a list of 8 vertices keys from a cell key
|
||||
Level vertices_keys( Key k, Key *verts ) ;
|
||||
|
||||
/// generate a list of 8 dual vertices keys from a vertex key and the deepest neighbor level
|
||||
bool dual_vertices_keys( Key k, Level lv, Key *dual_verts ) ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,261 @@
|
||||
/**
|
||||
* \file mvector.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* \brief light array container
|
||||
*
|
||||
* Light array container
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // memcpy, memset
|
||||
#include <mlist.h>
|
||||
|
||||
/// unsigned int alias
|
||||
typedef unsigned int uint ;
|
||||
/// const unsigned int alias
|
||||
typedef const uint cuint ;
|
||||
|
||||
/// default data size
|
||||
#define INITIAL_MVECTOR_SIZE ((uint)1024)
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// mvector
|
||||
/// \class mvector mvector.h
|
||||
template< typename Data > class mvector
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// Constructors
|
||||
public :
|
||||
/// Constructor
|
||||
mvector() : _data((Data*)NULL), _allocated_size(0), _used_size(0) {} ;
|
||||
|
||||
/// Destructor
|
||||
~mvector() { clear() ; }
|
||||
|
||||
// no copy on purpose
|
||||
|
||||
//------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// delete the data
|
||||
void clear() { free(_data) ; _data = (Data*)NULL ; _allocated_size = 0 ; _used_size = 0 ; _deleted.clear() ; }
|
||||
|
||||
/// estimation of the memory that will be used
|
||||
bool reserve( uint n )
|
||||
{
|
||||
if( n < INITIAL_MVECTOR_SIZE ) n = INITIAL_MVECTOR_SIZE ;
|
||||
if( n <= _allocated_size ) return true ;
|
||||
|
||||
Data *temp = _data ;
|
||||
_data = (Data*)malloc( n*sizeof(Data) ) ;
|
||||
if( temp ) memcpy( _data, temp, _used_size*sizeof(Data) ) ;
|
||||
memset( _data + _used_size, 0, (n-_used_size)*sizeof(Data) ) ;
|
||||
free( temp ) ;
|
||||
|
||||
_allocated_size = n ;
|
||||
return _data != (Data*)NULL ;
|
||||
}
|
||||
|
||||
/// reserve space for n new elements
|
||||
bool reserve_more( uint n )
|
||||
{
|
||||
if( _used_size + n > _allocated_size + _deleted.size() )
|
||||
{
|
||||
uint new_size = 2*_allocated_size ;
|
||||
if( new_size < _used_size + n ) new_size = _used_size + n ;
|
||||
//return reserve( 2*_allocated_size ) ;
|
||||
return reserve( new_size ) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
/// insert n new elements
|
||||
bool allocate_more( uint n )
|
||||
{
|
||||
if( !reserve_more( n ) ) return false ;
|
||||
_used_size += n ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
/// add one more element and
|
||||
Data &add( uint &id )
|
||||
{
|
||||
if( _deleted.empty() )
|
||||
{
|
||||
id = _used_size ;
|
||||
allocate_more( 1 ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = _deleted.first() ;
|
||||
_deleted.remove_first() ;
|
||||
}
|
||||
return at(id) ;
|
||||
}
|
||||
|
||||
/// lazy remotion
|
||||
bool remove( uint id )
|
||||
{
|
||||
if( id+1 == _used_size )
|
||||
--_used_size ;
|
||||
else
|
||||
_deleted.insert(id) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
// Accessor
|
||||
public :
|
||||
/// size accessor
|
||||
uint size() { return _used_size - _deleted.size() ; }
|
||||
|
||||
/// size accessor
|
||||
uint used_size() { return _used_size ; }
|
||||
|
||||
/// non checked const accessor
|
||||
const Data &at( uint id ) const { return _data[id] ; }
|
||||
/// non checked accessor
|
||||
Data &at( uint id ) { return _data[id] ; }
|
||||
|
||||
/// non checked const accessor
|
||||
const Data &operator[]( uint id ) const { return at(id) ; }
|
||||
/// non checked accessor
|
||||
Data &operator[]( uint id ) { return at(id) ; }
|
||||
|
||||
/// non checked pointer accessor
|
||||
Data *operator +( uint id ) { return _data + id ; }
|
||||
|
||||
/// id range validity check
|
||||
bool is_valid( uint id ) { return (id < size() && id>=0) ; }
|
||||
|
||||
/// id validity check
|
||||
bool is_deleted( uint id ) { return is_valid(id) && _deleted.find(id) () ; }
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
/// main data array
|
||||
Data *_data ;
|
||||
|
||||
/// real data size
|
||||
uint _allocated_size ;
|
||||
|
||||
/// filled data size
|
||||
uint _used_size ;
|
||||
|
||||
/// deleted data
|
||||
List<uint> _deleted ;
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
// iterator
|
||||
public :
|
||||
/// iterator
|
||||
class iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
iterator( mvector<Data> &vec_, uint id_ = 0 ) : _vec(vec_), _id(id_) {}
|
||||
|
||||
/// destructor
|
||||
~iterator() {}
|
||||
|
||||
/// copy constructor
|
||||
iterator( const iterator &it ) : _vec(it._vec), _id(it._id) {}
|
||||
|
||||
/// assignment operator
|
||||
iterator &operator = ( const iterator &it )
|
||||
{ _vec = it._vec; _id = it._id; return *this; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const iterator &it ) const { return &_vec == &it._vec && _id == it._id ; }
|
||||
/// inequality operator
|
||||
inline bool operator !=( const iterator &it ) const { return &_vec != &it._vec || _id != it._id ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _vec.is_valid( _id ) ; }
|
||||
|
||||
/// id accessor
|
||||
inline uint id () const { return _id ; }
|
||||
|
||||
/// value accessor
|
||||
inline const Data &operator * () const { return _vec[_id] ; }
|
||||
|
||||
/// value accessor
|
||||
inline Data &operator * () { return _vec[_id] ; }
|
||||
|
||||
/// accesses the next position
|
||||
inline iterator &operator ++() { do ++_id ; while( _vec.is_valid(_id) && _vec.is_deleted(_id) ) ; return *this ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
mvector<Data> &_vec ; ///< data vector
|
||||
uint _id ; ///< node position
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
// const_iterator
|
||||
public :
|
||||
/// const_iterator
|
||||
class const_iterator
|
||||
{
|
||||
public :
|
||||
// constructors
|
||||
/// default constructors
|
||||
const_iterator( const mvector<Data> &vec_, uint id_ = 0 ) : _vec(vec_), _id(id_) {}
|
||||
|
||||
/// destructor
|
||||
~const_iterator() {}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const const_iterator &it ) const { return &_vec == &it._vec && _id == it._id ; }
|
||||
/// inequality operator
|
||||
inline bool operator !=( const const_iterator &it ) const { return &_vec != &it._vec || _id != it._id ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _vec.is_valid( _id ) ; }
|
||||
|
||||
/// id accessor
|
||||
inline uint id () const { return _id ; }
|
||||
|
||||
/// value accessor
|
||||
inline const Data &operator * () const { return _vec[_id] ; }
|
||||
|
||||
/// accesses the next position
|
||||
inline const_iterator &operator ++() { do ++_id ; while( _vec.is_valid(_id) && _vec.is_deleted(_id) ) ; return *this ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Elements
|
||||
private :
|
||||
const mvector<Data> &_vec ; ///< data vector
|
||||
uint _id ; ///< node position
|
||||
};
|
||||
|
||||
public :
|
||||
/// Node iterator creation
|
||||
iterator begin( uint id = 0 ) { return iterator( *this, id ) ; }
|
||||
/// Node const iterator creation
|
||||
const_iterator cbegin( uint id = 0 ) { return const_iterator( *this, id ) ; }
|
||||
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,376 @@
|
||||
/**
|
||||
* \file opt_octree.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* Octree structure with hashtable and optimized operations
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "mlist.h"
|
||||
#include "cube.h"
|
||||
#include "hash.h"
|
||||
#include "MarchingCubes.h"
|
||||
#include "mc_draw.h"
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// OptOctree
|
||||
/// \class OptOctree OptOctree.h
|
||||
class OptOctree
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// forward declaration
|
||||
public:
|
||||
class geom_cell ;
|
||||
class cell_iterator ;
|
||||
class leaf_iterator ;
|
||||
|
||||
// Elements
|
||||
protected:
|
||||
/// Octree cell data structure
|
||||
typedef Hash<real> HashField ;
|
||||
|
||||
/// Hashtable of the octree nodes
|
||||
HashField _hash ;
|
||||
|
||||
/// Level distribution of the octree
|
||||
uint _level_dist[MAX_LEVEL+1] ;
|
||||
|
||||
/// Optimal level for direct search in the octree
|
||||
Level _opt_level ;
|
||||
|
||||
/// Maximal field of the octree
|
||||
real _max_field ;
|
||||
|
||||
/// Isosurface
|
||||
MarchingCubes _mc ;
|
||||
|
||||
/// Isosurface Draw
|
||||
MC_Draw _mc_draw ;
|
||||
|
||||
private :
|
||||
/// Octree vertices data structure
|
||||
typedef Hash<Level> HashVerts ;
|
||||
/// Hashtable of the octree vertices
|
||||
HashVerts _verts ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs a octree with and empty root
|
||||
OptOctree() { init() ; }
|
||||
|
||||
/// Destructor: Free memory
|
||||
~OptOctree() { clear() ; }
|
||||
|
||||
|
||||
/// Create the root
|
||||
void init() ;
|
||||
|
||||
/// Memory cleaning
|
||||
void clear() { clear_octree() ; _mc.clean_all() ; }
|
||||
|
||||
/// Delete the content of the octree
|
||||
void clear_octree() ;
|
||||
|
||||
/// Compute the optimal level
|
||||
void compute_opt_level() ;
|
||||
|
||||
/// Check that only the leaves have data
|
||||
bool check () ;
|
||||
|
||||
/// Prints statistics about the octree
|
||||
void stats() const ;
|
||||
|
||||
/// Return the maximal level of the octree
|
||||
Level max_level() const { Level lv = MAX_LEVEL ; while( lv > 0 && !_level_dist[lv] ) --lv ; return lv ; }
|
||||
|
||||
/// Return the optimal level of the octree
|
||||
Level opt_level() const { return _opt_level ; }
|
||||
|
||||
/// Return the optimal level of the octree
|
||||
Level &opt_level() { return _opt_level ; }
|
||||
|
||||
/// Return the maximal field of the octree
|
||||
real max_field() const { return _max_field ; }
|
||||
|
||||
/// Return the isosurface
|
||||
MarchingCubes &mc() { return _mc ; }
|
||||
|
||||
/// Return the isosurface draw
|
||||
MC_Draw &mc_draw() { return _mc_draw ; }
|
||||
|
||||
/// set the values of each leaf from the implicit function
|
||||
bool set_impl( data_access *ref = NULL ) ;
|
||||
|
||||
/// Refine the octree according to the data access
|
||||
bool refine( data_access *ref = NULL ) ;
|
||||
|
||||
/// Adapt the octree according to the data access
|
||||
bool adapt( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the octree with wireframe
|
||||
bool draw_wire() ;
|
||||
|
||||
/// Draw the octree with dots
|
||||
bool draw_centers() ;
|
||||
|
||||
/// Dual function type
|
||||
typedef bool opt_dual_walker( OptOctree &fo, Key *keys ) ;
|
||||
|
||||
/// Compute primal vertices
|
||||
bool compute_primal_verts() ;
|
||||
|
||||
/// Walk on the dual cubes
|
||||
bool dual_cubes_walk( opt_dual_walker &walker ) ;
|
||||
|
||||
/// Build the isosurface using dual marching cubes
|
||||
bool build_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the isosurface on-the-fly using dual marching cubes
|
||||
bool direct_draw_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the dual octree with wireframe
|
||||
bool draw_dual() ;
|
||||
|
||||
/// Do nothing, just for dual generation timing
|
||||
bool dual_timing() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterators
|
||||
public:
|
||||
/// Create an iterator traversing the tree from the root
|
||||
inline cell_iterator cells_begin() { return cell_iterator( *this ) ; }
|
||||
|
||||
/// Create an iterator traversing the leaves of the tree from the root
|
||||
inline leaf_iterator leaves_begin() { return leaf_iterator( *this ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// search operations
|
||||
public:
|
||||
/// Find cells of the octree at a given position
|
||||
bool find_leaf( Key k, Level o_lv, geom_cell &cell ) const ;
|
||||
bool find_leaf( Key k, geom_cell &cell ) const { return find_leaf( k, opt_level(), cell ) ; }
|
||||
bool find_leaf( real x, real y, real z, geom_cell &cell ) const { return find_leaf( cube2key( Cube(x,y,z,MAX_LEVEL) ), opt_level(), cell ) ; }
|
||||
|
||||
/// Find cells of the octree inside a given box of center x,y,z and half side r
|
||||
bool find_radius( real x, real y, real z, real r, List<geom_cell> &cells ) const ;
|
||||
|
||||
/// Find adjacent cells of the octree to a given cell
|
||||
bool adjacent( Key k, List<geom_cell> &cells ) const ;
|
||||
bool adjacent( const geom_cell &cell, List<geom_cell> &cells ) const { return adjacent( cell.key(), cells ) ; }
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( const HashField::KeyData &kd ) const { return !is_inv( kd.data ) ; }
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( Key k, real &d ) const { const HashField::KeyData &kd = _hash[k] ; d = kd.data ; return is_leaf( kd ) ; }
|
||||
|
||||
/// Leaf test based on the field value
|
||||
bool is_leaf( Key k ) const { return is_leaf( _hash[k] ) ; }
|
||||
|
||||
/// Node existence
|
||||
bool node_exists( Key k, HashField::KeyData &kd ) const { kd = _hash[k] ; return kd.key != KEY_INV ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// I/O
|
||||
public:
|
||||
|
||||
/// Draws the intersecting cells of a plane with the octree with color
|
||||
void draw_plane ( real nx, real ny, real nz, real d ) ;
|
||||
|
||||
/// Draws the intersection of a plane with the octree with color
|
||||
void draw_slice ( real nx, real ny, real nz, real d, float alpha ) ;
|
||||
|
||||
/// Draws the isosurface of level l inside the dual graph
|
||||
void draw_iso () { _mc.draw_surf() ; }
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Iterator Cell
|
||||
public :
|
||||
/// Auxiliary structure to traverse the octree
|
||||
class geom_cell : public Cube
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class OptOctree ;
|
||||
|
||||
protected:
|
||||
Key _key ; ///< octree cell
|
||||
real _field ; ///< field associated to the cell
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor
|
||||
geom_cell( Key key_ = KEY_INV, real field_ = R_INV ) : Cube(key2cube(key_)), _key(key_), _field(field_) {}
|
||||
|
||||
/// Default constructor
|
||||
geom_cell( HashField::KeyData kd ) : Cube(key2cube(kd.key)), _key(kd.key), _field(kd.data) {}
|
||||
|
||||
/// Destructor
|
||||
~geom_cell() {}
|
||||
|
||||
/// Copy constructor
|
||||
geom_cell( const geom_cell &i ) : Cube(i), _key(i._key), _field(i._field) {}
|
||||
|
||||
/// Assignment operator
|
||||
geom_cell &operator = ( const geom_cell &i )
|
||||
{ Cube::operator=(i) ; _key = i._key ; _field = i._field ; return *this; }
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Public constant accessors
|
||||
public :
|
||||
/// key const accessor
|
||||
inline Key key() const { return _key ; }
|
||||
/// key accessor
|
||||
inline Key &key() { return _key ; }
|
||||
|
||||
/// id const accessor
|
||||
inline real operator*() const { return _field ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Tests
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const geom_cell &i ) const { return key() == i.key() ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const geom_cell &i ) const { return key() != i.key() ; }
|
||||
|
||||
/// leaf test
|
||||
inline bool is_leaf() const { return !is_inv(*(*this)) ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return key() != KEY_INV ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// sons
|
||||
inline bool sons( geom_cell *s /*[8]*/, const HashField &hash )
|
||||
{
|
||||
if( is_leaf() ) return false ;
|
||||
|
||||
Key k = _key << 3 ;
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
s[i]._key = k | i ;
|
||||
s[i]._field = hash[k|i].data ;
|
||||
(Cube&)s[i] = key2cube(s[i]._key) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
};
|
||||
|
||||
const geom_cell geom_root() const { const Key root_key = 1 ; return geom_cell( root_key, _hash[root_key].data ) ; }
|
||||
const geom_cell geom_key ( Key k ) const { return geom_cell( k, _hash[k].data ) ; }
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Cell Iterator
|
||||
public :
|
||||
/// Octree cell iterator : Traverse the octree returning basic information on the cells
|
||||
class cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class OptOctree ;
|
||||
|
||||
protected:
|
||||
/// Octree traversal iterator
|
||||
HashField::iterator _it ;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor : Constructs an iterator from a cell
|
||||
cell_iterator( OptOctree &o ) : _it( o._hash.begin() ) {}
|
||||
|
||||
/// Destructor
|
||||
~cell_iterator() {}
|
||||
|
||||
/// Copy constructor
|
||||
cell_iterator( const cell_iterator &i ) : _it(i._it) {}
|
||||
|
||||
/// Assignment operator
|
||||
cell_iterator &operator = ( const cell_iterator &i )
|
||||
{ _it = i._it; return *this; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const cell_iterator &i ) const { return _it == i._it ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const cell_iterator &i ) const { return _it != i._it ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return _it() ; }
|
||||
|
||||
/// next position
|
||||
inline cell_iterator &operator ++() { ++_it ; return *this ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
// cell accessor
|
||||
inline geom_cell top() const { return geom_cell( key(), *_it ) ; }
|
||||
|
||||
/// id accessor
|
||||
inline real &operator*() { return *_it ; }
|
||||
|
||||
/// level accessor
|
||||
inline Level lv() { return key_level(_it.key()) ; }
|
||||
|
||||
/// size accessor
|
||||
inline real sz() { return Cube(0,0,0,lv()).sz() ; }
|
||||
|
||||
/// key accessor
|
||||
inline Key key() const { return _it.key() ; }
|
||||
|
||||
/// points accessor
|
||||
inline bool is_leaf() const { return !is_inv(*_it) ; }
|
||||
|
||||
/// Draws the cell wire with opengl
|
||||
void draw_wire () const { top().draw_wire () ; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// Octree leaf iterator : Traverse the octree returning basic information on the leaves
|
||||
class leaf_iterator : public cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
public :
|
||||
leaf_iterator( OptOctree &o ) : cell_iterator( o )
|
||||
{ if( (*this)() && !this->is_leaf() ) ++(*this) ; }
|
||||
|
||||
|
||||
/// next position
|
||||
inline leaf_iterator &operator ++()
|
||||
{
|
||||
cell_iterator &it = *this ;
|
||||
do ++it ; while ( it() && !it.is_leaf() ) ;
|
||||
return *this ;
|
||||
}
|
||||
} ;
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,265 @@
|
||||
/**
|
||||
* \file perf_main.cpp
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* Octree performances test
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
/*
|
||||
with pointers
|
||||
level 10,12: hash 27, non hash 31
|
||||
level 8: hash 27, non hash 37
|
||||
|
||||
without pointers
|
||||
level 10: hash 21, non hash 31
|
||||
level 8: hash 21, non hash 37/40
|
||||
*/
|
||||
|
||||
|
||||
#define OCTREE_SWITCH 2
|
||||
|
||||
#ifdef OCTREE_SWITCH
|
||||
# if OCTREE_SWITCH==0
|
||||
# define OCTREE_PTR 1
|
||||
# elif OCTREE_SWITCH==1
|
||||
# define OCTREE_HASH 1
|
||||
# elif OCTREE_SWITCH==2
|
||||
# define OCTREE_OPT 1
|
||||
# elif OCTREE_SWITCH==3
|
||||
# define OCTREE_LEAF 1
|
||||
# elif OCTREE_SWITCH==4
|
||||
# define OCTREE_MEM 1
|
||||
# endif // OCTREE_SWITCH
|
||||
#endif // OCTREE_SWITCH
|
||||
|
||||
|
||||
// switch values between pointer and hash octree
|
||||
#if !OCTREE_PTR && !OCTREE_HASH && !OCTREE_OPT && !OCTREE_LEAF && !OCTREE_MEM
|
||||
// # define OCTREE_PTR 1
|
||||
// # define OCTREE_HASH 1
|
||||
# define OCTREE_OPT 1
|
||||
// # define OCTREE_LEAF 1
|
||||
// # define OCTREE_MEM 1
|
||||
#endif // !OCTREE_PTR && !OCTREE_HASH && !OCTREE_OPT && !OCTREE_LEAF && !OCTREE_MEM
|
||||
|
||||
|
||||
#ifdef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_LEAF
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "0 pointer"
|
||||
# include "ptr_octree.h"
|
||||
/// octree type
|
||||
typedef PtrOctree Octree ;
|
||||
#endif //OCTREE_PTR
|
||||
|
||||
|
||||
#ifdef OCTREE_HASH
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_LEAF
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "1 hash"
|
||||
# include "hash_octree.h"
|
||||
/// octree type
|
||||
typedef HashOctree Octree ;
|
||||
#endif //OCTREE_HASH
|
||||
|
||||
|
||||
#ifdef OCTREE_OPT
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_LEAF
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "2 opt"
|
||||
# include "opt_octree.h"
|
||||
/// octree type
|
||||
typedef OptOctree Octree ;
|
||||
#endif //OCTREE_OPT
|
||||
|
||||
|
||||
#ifdef OCTREE_LEAF
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "3 leaf"
|
||||
# include "leaf_octree.h"
|
||||
/// octree type
|
||||
typedef LeafOctree Octree ;
|
||||
#endif //OCTREE_LEAF
|
||||
|
||||
|
||||
#ifdef OCTREE_MEM
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_LEAF
|
||||
# define OCTREE_STRING "4 mem"
|
||||
# include "mem_octree.h"
|
||||
/// octree type
|
||||
typedef MemOctree Octree ;
|
||||
#endif //OCTREE_MEM
|
||||
|
||||
|
||||
#ifndef NPOINTS
|
||||
# define NPOINTS 100
|
||||
#endif // NPOINTS
|
||||
|
||||
#ifndef RADIUS
|
||||
# define RADIUS (0.003f)
|
||||
#endif // RADIUS
|
||||
|
||||
#ifndef NDUALS
|
||||
# define NDUALS 10
|
||||
#endif // NDUALS
|
||||
|
||||
#ifndef MLEVEL
|
||||
# define MLEVEL 5
|
||||
#endif // MLEVEL
|
||||
|
||||
#ifndef IMPLFUN // set to 0 for random
|
||||
# define IMPLFUN 1
|
||||
#endif // IMPLFUN
|
||||
|
||||
#ifndef ISOVAL
|
||||
# define ISOVAL 0.5
|
||||
#endif // ISOVAL
|
||||
|
||||
|
||||
#include "hash.h"
|
||||
#include "implfuns.h"
|
||||
#include <stdio.h>
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//
|
||||
int main( int argc , char* argv[] )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
#if OCTREE_LEAF && !USE_HASH_PTR
|
||||
return 0 ;
|
||||
#endif // OCTREE_LEAF && !USE_HASH_PTR
|
||||
|
||||
srand(77) ;
|
||||
// Chrono::ResetClocks() ;
|
||||
|
||||
printf( "\n\n\n-----------------------------------------------------------------------------\n"
|
||||
OCTREE_STRING
|
||||
"\n\thash\t%s\tpointers\n"
|
||||
"\thash bits =\t%d\n"
|
||||
"\tnon hash bits=\t%d\n"
|
||||
"\tmax_level =\t%d\n"
|
||||
"\tdensity =\t%f\n"
|
||||
"\tnpoints =\t%d\n"
|
||||
"\tradius =\t%f\n"
|
||||
"\timplicit function =\t%s\n"
|
||||
"\tisovalue =\t%f\n"
|
||||
"\tnumber of duals=\t%d\n\n",
|
||||
(USE_HASH_PTR ? "with" : "without"), HASH_BITS, NON_HASH_BITS, MLEVEL, RAND_THRES, NPOINTS, RADIUS, fun_list[IMPLFUN], ISOVAL, NDUALS ) ;
|
||||
fflush(stdout);
|
||||
|
||||
/// main data structure
|
||||
Octree octree ;
|
||||
#if IMPLFUN==0
|
||||
data_rand ref( MLEVEL ) ;
|
||||
octree.refine( &ref ) ;
|
||||
#else // IMPLFUN
|
||||
data_func ref( MLEVEL, ISOVAL, fun_def[IMPLFUN] ) ;
|
||||
octree.refine( &ref ) ;
|
||||
octree.set_impl( &ref ) ;
|
||||
#endif // IMPLFUN
|
||||
fflush(stdout);
|
||||
|
||||
|
||||
/*
|
||||
//-------------------------------------------------
|
||||
// search for random points
|
||||
Chrono::ResetClocks() ;
|
||||
printf( "\n\nRandom Points\n" ) ;
|
||||
for( int i = 0 ; i < NPOINTS ; ++i )
|
||||
{
|
||||
real x = (real)rand()/(real)RAND_MAX;
|
||||
real y = (real)rand()/(real)RAND_MAX;
|
||||
real z = (real)rand()/(real)RAND_MAX;
|
||||
Octree::geom_cell gc ;
|
||||
List<Octree::geom_cell> gc_list ;
|
||||
octree.find_leaf( x,y,z, gc ) ;
|
||||
octree.find_radius( x,y,z, RADIUS, gc_list ) ; gc_list.clear() ;
|
||||
octree.adjacent( gc, gc_list ) ; gc_list.clear() ;
|
||||
}
|
||||
Chrono::PrintClocks() ;
|
||||
fflush(stdout);
|
||||
//-------------------------------------------------
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// search for all leaves once
|
||||
printf( "\nLeaves\n" ) ;
|
||||
Chrono::ResetClocks() ;
|
||||
for( Octree::leaf_iterator it = octree.leaves_begin() ; it() ; ++it )
|
||||
{
|
||||
Octree::geom_cell g_it = it.top() ;
|
||||
Octree::geom_cell gc ;
|
||||
List<Octree::geom_cell> gc_list ;
|
||||
octree.find_leaf( g_it.cx(), g_it.cy(), g_it.cz(), gc ) ;
|
||||
octree.find_radius( g_it.cx(), g_it.cy(), g_it.cz(), RADIUS, gc_list ) ; gc_list.clear() ;
|
||||
octree.adjacent( gc, gc_list ) ; gc_list.clear() ;
|
||||
}
|
||||
Chrono::PrintClocks() ;
|
||||
fflush(stdout);
|
||||
//-------------------------------------------------
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// search for all points at the maximal level
|
||||
printf( "\n\nGrid\n" ) ;
|
||||
Level lv = octree.max_level() - 4 ;
|
||||
real step = 1.0 / (1 << lv) ;
|
||||
Chrono::ResetClocks() ;
|
||||
for( real x = 0.0 ; x <= 1.0 ; x += step )
|
||||
{
|
||||
for( real y = 0.0 ; y <= 1.0 ; y += step )
|
||||
{
|
||||
for( real z = 0.0 ; z <= 1.0 ; z += step )
|
||||
{
|
||||
Octree::geom_cell gc ;
|
||||
List<Octree::geom_cell> gc_list ;
|
||||
octree.find_leaf( x,y,z, gc ) ;
|
||||
octree.find_radius( x,y,z, RADIUS, gc_list ) ; gc_list.clear() ;
|
||||
octree.adjacent( gc, gc_list ) ; gc_list.clear() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
Chrono::PrintClocks() ;
|
||||
fflush(stdout);
|
||||
//-------------------------------------------------
|
||||
*/
|
||||
|
||||
//-------------------------------------------------
|
||||
// build many duals
|
||||
printf( "\n\nDuals\n" ) ;
|
||||
// Chrono::ResetClocks() ;
|
||||
for( int i = 0 ; i < NDUALS ; ++i )
|
||||
{
|
||||
#if IMPLFUN==0
|
||||
octree.dual_timing() ;
|
||||
#else // IMPLFUN
|
||||
octree.mc().clean_all() ;
|
||||
octree.build_isosurface(&ref) ;
|
||||
#endif // IMPLFUN
|
||||
}
|
||||
// Chrono::PrintClocks() ;
|
||||
octree.stats() ;
|
||||
fflush(stdout);
|
||||
//-------------------------------------------------
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
@ -0,0 +1,289 @@
|
||||
/**
|
||||
* \file point.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* \brief (Point/Vector Class).
|
||||
*/
|
||||
/**------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <float.h> // FLT_EPSILON
|
||||
#include <math.h> // nan
|
||||
#ifdef UNIX
|
||||
#include <GL/gl.h>
|
||||
#else
|
||||
#include <OpenGL/GL.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
/** real number type */
|
||||
typedef float real ;
|
||||
typedef const real creal ;
|
||||
#define R_PI ((creal)3.1415926535897932384626433832795)
|
||||
#define R_EPSILON ((real)FLT_EPSILON)
|
||||
inline bool is_inv( real x ) { return isnan(x) ; }
|
||||
extern real R_INV ;
|
||||
|
||||
/** integer number aliases */
|
||||
typedef signed char schar ;
|
||||
typedef unsigned char uchar ;
|
||||
typedef unsigned int uint ;
|
||||
typedef const int cint ;
|
||||
typedef const uint cuint ;
|
||||
|
||||
/** \brief Axis Definition */
|
||||
enum Axis { X = 0, Y = 1, Z = 2 } ;
|
||||
//------------------------------------------------
|
||||
|
||||
|
||||
/** \brief point with normal */
|
||||
class Point
|
||||
{
|
||||
protected :
|
||||
real _x, _y, _z ;
|
||||
|
||||
public :
|
||||
Point() : _x(R_INV), _y(R_INV), _z(R_INV) {}
|
||||
Point( creal x_, creal y_, creal z_ ) : _x(x_), _y(y_), _z(z_) {}
|
||||
Point( const Point &p_ ) : _x(p_._x), _y(p_._y), _z(p_._z) {}
|
||||
Point &operator = ( const Point &p_ )
|
||||
{ _x=p_._x ; _y=p_._y ; _z=p_._z ; return *this; }
|
||||
|
||||
|
||||
public :
|
||||
inline real &x() { return _x ; }
|
||||
inline real &y() { return _y ; }
|
||||
inline real &z() { return _z ; }
|
||||
inline creal x() const { return _x ; }
|
||||
inline creal y() const { return _y ; }
|
||||
inline creal z() const { return _z ; }
|
||||
|
||||
inline creal &operator[] ( Axis a ) const
|
||||
{ switch( a ) {
|
||||
case X : return _x ;
|
||||
case Y : return _y ;
|
||||
case Z : return _z ;
|
||||
default: return R_INV ;
|
||||
} }
|
||||
inline real &operator[] ( Axis a )
|
||||
{ switch( a ) {
|
||||
case X : return _x ;
|
||||
case Y : return _y ;
|
||||
case Z : return _z ;
|
||||
default: return R_INV ;
|
||||
} }
|
||||
|
||||
/**------------------------------------------------------------------------------------*/
|
||||
inline bool valid()
|
||||
{
|
||||
return
|
||||
( !is_inv( x() ) ) &&
|
||||
( !is_inv( y() ) ) &&
|
||||
( !is_inv( z() ) ) ;
|
||||
}
|
||||
inline bool invalid()
|
||||
{
|
||||
return
|
||||
( is_inv( x() ) ) ||
|
||||
( is_inv( y() ) ) ||
|
||||
( is_inv( z() ) ) ;
|
||||
}
|
||||
|
||||
|
||||
/**------------------------------------------------------------------------------------*/
|
||||
// Basic operations
|
||||
|
||||
/// +=
|
||||
inline Point &operator+= ( const Point &p_ )
|
||||
{
|
||||
x() += p_.x() ; y() += p_.y() ; z() += p_.z() ;
|
||||
return *this ;
|
||||
}
|
||||
/// unary -
|
||||
inline const Point operator- ()
|
||||
{
|
||||
x() = -x() ; y() = -y() ; z() = -z() ;
|
||||
return *this ;
|
||||
}
|
||||
/// -=
|
||||
inline Point &operator-= ( const Point &p_ )
|
||||
{
|
||||
x() -= p_.x() ; y() -= p_.y() ; z() -= p_.z() ;
|
||||
return *this ;
|
||||
}
|
||||
/// *= scalar
|
||||
inline Point &operator*= ( const real l )
|
||||
{
|
||||
x() *= l ; y() *= l ; z() *= l ;
|
||||
return *this ;
|
||||
}
|
||||
/// /= scalar
|
||||
inline Point &operator/= ( const real l )
|
||||
{
|
||||
if( fabs(l) < R_EPSILON ) return *this ;
|
||||
real s = 1.0/l ;
|
||||
return *this *= s ;
|
||||
}
|
||||
|
||||
|
||||
/**------------------------------------------------------------------------------------*/
|
||||
// Norms
|
||||
inline real length () const
|
||||
{
|
||||
return hypot( hypot( x(), y() ), z() ) ;
|
||||
}
|
||||
inline real norm () const { return length() ; }
|
||||
inline real dist ( const Point &p_ ) const { Point r = *this ; r -= p_ ; return r.length() ; }
|
||||
|
||||
inline bool operator== ( const Point &p_ ) const { return dist( p_ ) < R_EPSILON ; }
|
||||
inline bool operator!= ( const Point &p_ ) const { return !( *this == p_ ) ; }
|
||||
|
||||
inline bool normalize()
|
||||
{
|
||||
real l = length() ;
|
||||
if( l < R_EPSILON ) return false ;
|
||||
*this /= l ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
/** replaces p by the by-coordinate minimum of p and p_ */
|
||||
inline void pmin( const Point &p_ )
|
||||
{
|
||||
if( x() > p_.x() ) x() = p_.x() ;
|
||||
if( y() > p_.y() ) y() = p_.y() ;
|
||||
if( z() > p_.z() ) z() = p_.z() ;
|
||||
}
|
||||
|
||||
/** replaces p by the by-coordinate maximum of p and p_ */
|
||||
inline void pmax( const Point &p_ )
|
||||
{
|
||||
if( x() < p_.x() ) x() = p_.x() ;
|
||||
if( y() < p_.y() ) y() = p_.y() ;
|
||||
if( z() < p_.z() ) z() = p_.z() ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Drawing
|
||||
public:
|
||||
/// Draws the point with opengl
|
||||
void draw () const { ::glVertex3f( (float)x(), (float)y(), (float)z() ) ; }
|
||||
} ;
|
||||
|
||||
// Valid point
|
||||
extern Point P_INV ;
|
||||
|
||||
|
||||
/**------------------------------------------------------------------------------------*/
|
||||
// Geometric Operations
|
||||
|
||||
/// +
|
||||
inline const Point operator+ ( const Point &p, const Point &p_ )
|
||||
{
|
||||
Point r = p ;
|
||||
return (r += p_) ;
|
||||
}
|
||||
/// -
|
||||
inline const Point operator- ( const Point &p, const Point &p_ )
|
||||
{
|
||||
Point r = p ;
|
||||
return r -= p_ ;
|
||||
}
|
||||
/// * scalar
|
||||
inline const Point operator* ( const Point &p, const real l )
|
||||
{
|
||||
Point r = p ;
|
||||
return r *= l ;
|
||||
}
|
||||
/// * scalar
|
||||
inline const Point operator* ( const real l, const Point &p )
|
||||
{
|
||||
return p * l ;
|
||||
}
|
||||
/// / scalar
|
||||
inline const Point operator/ ( const Point &p, const real l )
|
||||
{
|
||||
Point r = p ;
|
||||
return r /= l ;
|
||||
}
|
||||
|
||||
/// scalar (dot) product
|
||||
inline real operator* ( const Point &p, const Point &p_ )
|
||||
{
|
||||
return p.x()*p_.x() + p.y()*p_.y() + p.z()*p_.z() ;
|
||||
}
|
||||
/// vector (cross) product
|
||||
static inline const Point operator^ ( const Point &p, const Point &p_ )
|
||||
{
|
||||
Point r ;
|
||||
r.x() = p.y() * p_.z() - p.z() * p_.y() ;
|
||||
r.y() = p.z() * p_.x() - p.x() * p_.z() ;
|
||||
r.z() = p.x() * p_.y() - p.y() * p_.x() ;
|
||||
return r ;
|
||||
}
|
||||
static inline real det( const Point &p, const Point &q, const Point &r )
|
||||
{
|
||||
return
|
||||
p.x()*q.y()*r.z() + p.y()*q.z()*r.x() + p.z()*q.x()*r.y() -
|
||||
p.z()*q.y()*r.x() - p.x()*q.z()*r.y() - p.y()*q.x()*r.z() ;
|
||||
}
|
||||
|
||||
|
||||
/**------------------------------------------------------------------------------------*/
|
||||
// Geometric Operations
|
||||
|
||||
inline real length ( const Point &p ) { return p.length() ; }
|
||||
inline real norm ( const Point &p ) { return p.norm() ; }
|
||||
inline real dist ( const Point &p, const Point &p_ ) { return p.dist(p_) ; }
|
||||
inline real sqdist ( const Point &p, const Point &p_ ) { Point r = p-p_ ; return r*r ; }
|
||||
|
||||
/** \brief Computes the normal of a triangle
|
||||
* \param const Point &v0
|
||||
* \param const Point &v1
|
||||
* \param const Point &v2 */
|
||||
inline const Point normal (const Point & v0, const Point & v1, const Point & v2)
|
||||
{
|
||||
Point n = ( v1-v0 ) ^ ( v2 - v0 ) ;
|
||||
n.normalize() ;
|
||||
return n ;
|
||||
}
|
||||
|
||||
/** \brief Computes the area of a triangle
|
||||
* \param const Point &v0
|
||||
* \param const Point &v1
|
||||
* \param const Point &v2 */
|
||||
inline real area (const Point & v0, const Point & v1, const Point & v2)
|
||||
{
|
||||
return 0.5 * norm( ( v1-v0 ) ^ ( v2 - v0 ) );
|
||||
}
|
||||
|
||||
/** \brief Computes the cotangent of ange v v1,v v2
|
||||
* \param const Point &v
|
||||
* \param const Point &v1
|
||||
* \param const Point &v2 */
|
||||
inline const real cotan (const Point & v, const Point & v1, const Point & v2)
|
||||
{
|
||||
Point u = v1-v ;
|
||||
Point w = v2-v ;
|
||||
return (u*w) / norm( u ^ w ) ;
|
||||
}
|
||||
|
||||
/** \brief Computes the middle of an edge
|
||||
* \param const Point &v0
|
||||
* \param const Point &v1 */
|
||||
inline const Point middle (const Point & v0, const Point & v1)
|
||||
{
|
||||
return 0.5 * (v0+v1) ;
|
||||
}
|
||||
|
||||
|
||||
inline void pmin( Point &p, const Point &p_ ) { p.pmin( p_ ) ; }
|
||||
inline void pmax( Point &p, const Point &p_ ) { p.pmax( p_ ) ; }
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,400 @@
|
||||
/**
|
||||
* \file ptr_octree.h
|
||||
* \author Thomas Lewiner <tomlew@puc-rio.br>
|
||||
* \author Matmidia Lab, Math Dept, PUC-Rio
|
||||
* \date 10/01/2010
|
||||
*
|
||||
* Octree structure with son-brother pointers
|
||||
*/
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include <stack>
|
||||
#include "mlist.h"
|
||||
#include "cube.h"
|
||||
#include "MarchingCubes.h"
|
||||
#include "mc_draw.h"
|
||||
#include "data_access.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// PtrOctree
|
||||
/// \class PtrOctree PtrOctree.h
|
||||
class PtrOctree
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// forward declaration
|
||||
public:
|
||||
class geom_cell ;
|
||||
class cell_iterator ;
|
||||
class leaf_iterator ;
|
||||
|
||||
// Elements
|
||||
protected:
|
||||
/// Octree cell data structure
|
||||
typedef struct cell
|
||||
{
|
||||
struct cell *brother ; ///< next brother of the cell
|
||||
struct cell *first_son ; ///< first son of the cell
|
||||
real field ; ///< field supported by the cell
|
||||
} cell ;
|
||||
|
||||
/// Root of the octree
|
||||
cell _root ;
|
||||
|
||||
/// Maximal level of the octree (for find_adjacent)
|
||||
Level _max_level ;
|
||||
|
||||
/// Maximal field of the octree
|
||||
real _max_field ;
|
||||
|
||||
/// Isosurface
|
||||
MarchingCubes _mc ;
|
||||
|
||||
/// Isosurface Draw
|
||||
MC_Draw _mc_draw ;
|
||||
|
||||
/// Dual run memory consumption
|
||||
uint _dual_temp_memory ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs a octree with and empty root
|
||||
PtrOctree() { init() ; }
|
||||
|
||||
/// Destructor: Free memory
|
||||
~PtrOctree() { clear() ; }
|
||||
|
||||
|
||||
/// Create the root
|
||||
void init() ;
|
||||
|
||||
/// Memory cleaning
|
||||
void clear() { clear_octree() ; _mc.clean_all() ; }
|
||||
|
||||
/// Delete the branch below a given node
|
||||
void clear_branch( cell *b ) ;
|
||||
|
||||
/// Delete the content of the octree
|
||||
void clear_octree() { clear_branch( &_root ) ; }
|
||||
|
||||
/// Check that only the leaves have data
|
||||
bool check () ;
|
||||
|
||||
/// Prints statistics about the octree
|
||||
void stats() ;
|
||||
|
||||
|
||||
/// Return the maximal level of the octree
|
||||
Level max_level() const { return _max_level ; }
|
||||
|
||||
/// Return the maximal field of the octree
|
||||
real max_field() const { return _max_field ; }
|
||||
|
||||
/// Return the isosurface
|
||||
MarchingCubes &mc() { return _mc ; }
|
||||
|
||||
/// Return the isosurface draw
|
||||
MC_Draw &mc_draw() { return _mc_draw ; }
|
||||
|
||||
/// set the values of each leaf from the implicit function
|
||||
bool set_impl( data_access *ref = NULL ) ;
|
||||
|
||||
/// Refine the octree according to the data access
|
||||
bool refine( data_access *ref = NULL ) ;
|
||||
|
||||
/// Adapt the octree according to the data access
|
||||
bool adapt( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the octree with wireframe
|
||||
bool draw_wire() ;
|
||||
|
||||
/// Draw the octree with dots
|
||||
bool draw_centers() ;
|
||||
|
||||
/// Dual function type
|
||||
typedef bool ptr_dual_walker( PtrOctree &fo, geom_cell *cells ) ;
|
||||
|
||||
/// Walk on the dual cubes
|
||||
bool dual_cubes_walk( ptr_dual_walker &walker ) ;
|
||||
|
||||
/// Build the isosurface using dual marching cubes
|
||||
bool build_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the isosurface on-the-fly using dual marching cubes
|
||||
bool direct_draw_isosurface( data_access *ref = NULL ) ;
|
||||
|
||||
/// Draw the dual octree with wireframe
|
||||
bool draw_dual() ;
|
||||
|
||||
/// Do nothing, just for dual generation timing
|
||||
bool dual_timing() ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iterators
|
||||
public:
|
||||
/// Create an iterator traversing the tree from the root
|
||||
inline cell_iterator cells_begin() { return cell_iterator( &_root ) ; }
|
||||
|
||||
/// Create an iterator traversing the leaves of the tree from the root
|
||||
inline leaf_iterator leaves_begin() { return leaf_iterator( &_root ) ; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// search operations
|
||||
public:
|
||||
/// Find cells of the octree at a given position
|
||||
bool find_leaf( real x, real y, real z, geom_cell &cell ) ;
|
||||
|
||||
/// Find cells of the octree inside a given box of center x,y,z and half side r
|
||||
bool find_radius( real x, real y, real z, real r, List<geom_cell> &cells ) ;
|
||||
|
||||
/// Find adjacent cells of the octree to a given cell
|
||||
bool adjacent( const geom_cell &cell, List<geom_cell> &cells ) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// I/O
|
||||
public:
|
||||
|
||||
/// Draws the intersecting cells of a plane with the octree with color
|
||||
void draw_plane ( real nx, real ny, real nz, real d ) ;
|
||||
|
||||
/// Draws the intersection of a plane with the octree with color
|
||||
void draw_slice ( real nx, real ny, real nz, real d, float alpha ) ;
|
||||
|
||||
/// Draws the isosurface of level l inside the dual graph
|
||||
void draw_iso () { _mc.draw_surf() ; }
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Iterator Cell
|
||||
public :
|
||||
/// Auxiliary structure to traverse the octree
|
||||
class geom_cell : public Cube
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class PtrOctree ;
|
||||
|
||||
protected:
|
||||
PtrOctree::cell *_cell ; ///< octree cell
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor: Constructs an iterator from a cell
|
||||
geom_cell( PtrOctree::cell *cell_ = NULL, real cx_ = 0.5, real cy_ = 0.5, real cz_ = 0.5, Level lv_ = 0 )
|
||||
: Cube(cx_,cy_,cz_,lv_), _cell(cell_) {}
|
||||
|
||||
/// Destructor
|
||||
~geom_cell() {}
|
||||
|
||||
|
||||
/// Copy constructor
|
||||
geom_cell( const geom_cell &i )
|
||||
: Cube(i), _cell(i._cell) {}
|
||||
|
||||
/// Assignment operator
|
||||
geom_cell &operator = ( const geom_cell &i )
|
||||
{ Cube::operator=(i); _cell=i._cell; return *this; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Public constant accessors
|
||||
public :
|
||||
/// cell const accessor
|
||||
inline const PtrOctree::cell * cell() const { return _cell ; }
|
||||
/// cell accessor
|
||||
inline PtrOctree::cell *&cell() { return _cell ; }
|
||||
|
||||
/// first son const accessor
|
||||
inline const PtrOctree::cell * first_son() const { return _cell->first_son ; }
|
||||
/// first son accessor
|
||||
inline PtrOctree::cell *&first_son() { return _cell->first_son ; }
|
||||
|
||||
/// brother const accessor
|
||||
inline const PtrOctree::cell * brother() const { return _cell->brother ; }
|
||||
/// brother accessor
|
||||
inline PtrOctree::cell *&brother() { return _cell->brother ; }
|
||||
|
||||
/// id const accessor
|
||||
inline real operator*() const { return cell()->field ; }
|
||||
/// id accessor
|
||||
inline real &operator*() { return cell()->field ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Tests
|
||||
public :
|
||||
/// equality operator
|
||||
inline bool operator ==( const geom_cell &i ) const { return cell() == i.cell() ; }
|
||||
|
||||
/// inequality operator
|
||||
inline bool operator !=( const geom_cell &i ) const { return cell() != i.cell() ; }
|
||||
|
||||
/// leaf test
|
||||
inline bool is_leaf() const { return first_son() == NULL ; }
|
||||
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return cell() != NULL ; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// sons
|
||||
inline bool sons( geom_cell *s /*[8]*/ )
|
||||
{
|
||||
if( !first_son() ) return false ;
|
||||
|
||||
int level_ = lv() + 1 ;
|
||||
real sz_ = sz() / 2.0 ;
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
s[i].cell () = (i==0) ? first_son() : s[i-1].brother() ;
|
||||
s[i].lv () = level_ ;
|
||||
s[i].cx () = (i&1) ? cx() + sz_ : cx() - sz_ ;
|
||||
s[i].cy () = (i&2) ? cy() + sz_ : cy() - sz_ ;
|
||||
s[i].cz () = (i&4) ? cz() + sz_ : cz() - sz_ ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
/// get son from side i
|
||||
inline bool son( int i , geom_cell &s )
|
||||
{
|
||||
if( is_leaf() ) return false ;
|
||||
|
||||
real sz_ = s.sz() / 2.0 ;
|
||||
++s.lv() ;
|
||||
s.cx() = (i&1) ? cx() + sz_ : cx() - sz_ ;
|
||||
s.cy() = (i&2) ? cy() + sz_ : cy() - sz_ ;
|
||||
s.cz() = (i&4) ? cz() + sz_ : cz() - sz_ ;
|
||||
|
||||
s.cell() = first_son() ;
|
||||
while( --i > -1 ) s.cell() = s.brother() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Cell Iterator
|
||||
public :
|
||||
/// Octree cell iterator : Traverse the octree returning basic information on the cells
|
||||
class cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
friend class PtrOctree ;
|
||||
|
||||
protected:
|
||||
/// Octree traversal stack
|
||||
std::stack<geom_cell> _s ;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructors
|
||||
public:
|
||||
/// Default constructor : Constructs an iterator from a cell
|
||||
cell_iterator( PtrOctree::cell *root = NULL, real cx_ = 0.5, real cy_ = 0.5, real cz_ = 0.5, Level lv_ = 0 )
|
||||
{ if( root ) _s.push( geom_cell( root, cx_, cy_, cz_, lv_ ) ) ; }
|
||||
|
||||
/// Destructor
|
||||
~cell_iterator() {}
|
||||
|
||||
/// Copy constructor
|
||||
cell_iterator( const cell_iterator &i ) : _s(i._s) {}
|
||||
|
||||
/// Assignment operator
|
||||
cell_iterator &operator = ( const cell_iterator &i )
|
||||
{ _s = i._s; return *this; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Operations
|
||||
public :
|
||||
/// validation operator
|
||||
inline bool operator ()() const { return !_s.empty() ; }
|
||||
|
||||
/// next position
|
||||
inline cell_iterator &operator ++()
|
||||
{
|
||||
if( _s.empty() ) return *this ;
|
||||
geom_cell n = _s.top() ; _s.pop() ;
|
||||
if( n.is_leaf() ) return *this ;
|
||||
|
||||
// depth first search
|
||||
geom_cell sons[8] ;
|
||||
n.sons( sons ) ;
|
||||
for( int i = 0 ; i < 8 ; ++i )
|
||||
_s.push( sons[i] ) ;
|
||||
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Accessors
|
||||
public :
|
||||
/// geom_cell accessor
|
||||
inline geom_cell &top() { return _s.top() ; }
|
||||
|
||||
/// id accessor
|
||||
inline real &operator*() { return * _s.top() ; }
|
||||
|
||||
/// level accessor
|
||||
inline Level &lv() { return _s.top().lv() ; }
|
||||
|
||||
/// center x position accessor
|
||||
inline real &cx() { return _s.top().cx() ; }
|
||||
|
||||
/// center y position accessor
|
||||
inline real &cy() { return _s.top().cy() ; }
|
||||
|
||||
/// center y position accessor
|
||||
inline real &cz() { return _s.top().cz() ; }
|
||||
|
||||
/// size accessor
|
||||
inline real sz() { return _s.top().sz() ; }
|
||||
|
||||
/// points accessor
|
||||
inline bool is_leaf() const { return _s.top().is_leaf() ; }
|
||||
|
||||
/// inside test
|
||||
inline bool contains( real x, real y, real z ) const { return _s.top().contains( x,y,z ) ; }
|
||||
|
||||
/// get son from its side:
|
||||
inline bool son( int i , geom_cell &s_ ) { return _s.top().son(i,s_) ; }
|
||||
|
||||
/// Draws the cell wire with opengl
|
||||
void draw_wire () const { _s.top().draw_wire () ; }
|
||||
|
||||
protected :
|
||||
/// stack accessor for ad hoc iterations
|
||||
inline std::stack< geom_cell > &s() { return _s ; }
|
||||
};
|
||||
|
||||
|
||||
/// Octree leaf iterator : Traverse the octree returning basic information on the leaves
|
||||
class leaf_iterator : public cell_iterator
|
||||
//---------------------------------------------------------------------------
|
||||
{
|
||||
public :
|
||||
leaf_iterator( PtrOctree::cell *root = NULL, real cx_ = 0.5, real cy_ = 0.5, real cz_ = 0.5, Level lv_ = 0 ) : cell_iterator( root, cx_,cy_,cz_,lv_ )
|
||||
{ if( root && !this->is_leaf() ) ++(*this) ; }
|
||||
|
||||
|
||||
/// next position
|
||||
inline leaf_iterator &operator ++()
|
||||
{
|
||||
cell_iterator &it = *this ;
|
||||
do ++it ; while ( it() && !it.is_leaf() ) ;
|
||||
return *this ;
|
||||
}
|
||||
} ;
|
||||
} ;
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file glui_cmdline.cpp
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.1
|
||||
* @date 20/08/2007
|
||||
*
|
||||
* @brief Example Graphical interface: command line parser
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma implementation "viz_glui_defs.h"
|
||||
#endif // WIN32
|
||||
|
||||
#include "viz_glui_defs.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// parse command line
|
||||
bool parse_command_line(int argc, char* argv[])
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
bool quit = false ;
|
||||
|
||||
for( int i = 1 ; i < argc ; ++i )
|
||||
{
|
||||
if ( !strcmp( argv[i], "-lv" ) )
|
||||
{
|
||||
if( ++i != argc ) { max_level = atoi( argv[i] ) ; }
|
||||
}
|
||||
|
||||
else if( !strcmp( argv[i], "+ortho" ) )
|
||||
{
|
||||
ortho = true ;
|
||||
}
|
||||
else if( !strcmp( argv[i], "-ortho" ) )
|
||||
{
|
||||
ortho = false ;
|
||||
}
|
||||
else if( !strcmp( argv[i], "-pos" ) )
|
||||
{
|
||||
if( ++i != argc ) { obj_pos[0] = atof( argv[i] ) ; }
|
||||
if( ++i != argc ) { obj_pos[1] = atof( argv[i] ) ; }
|
||||
if( ++i != argc ) { obj_pos[2] = atof( argv[i] ) ; }
|
||||
}
|
||||
else if( !strcmp( argv[i], "-rot" ) )
|
||||
{
|
||||
for( int j = 0 ; j < 16 ; ++j )
|
||||
if( ++i != argc ) { view_rotate[j] = atof( argv[i] ) ; }
|
||||
}
|
||||
else if( !strcmp( argv[i], "-view" ) )
|
||||
{
|
||||
control_cb( LOAD_VIEWPORT_ID ) ;
|
||||
}
|
||||
else if( !strcmp( argv[i], "-q" ) )
|
||||
{
|
||||
quit = true ;
|
||||
}
|
||||
else if( !strcmp( argv[i], "-h" ) )
|
||||
{
|
||||
printf( "usage %s [-in file.xyz] [-q]\n", argv[0] ) ;
|
||||
}
|
||||
}
|
||||
// glui_side ->sync_live() ;
|
||||
glui_bottom->sync_live() ;
|
||||
|
||||
return quit ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
@ -0,0 +1,346 @@
|
||||
/**
|
||||
* @file glui_controls.cpp
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.1
|
||||
* @date 30/05/2006
|
||||
*
|
||||
* @brief Octree graphical interface: interface controls
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma implementation "viz_glui_defs.h"
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "viz_glui_defs.h"
|
||||
#include "implfuns.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// declarations of this file
|
||||
|
||||
// main object: octree
|
||||
Octree octree ;
|
||||
|
||||
// switch between implicit funciont or volumetric data
|
||||
int impl_data = SWITCH_DATA ;
|
||||
|
||||
// octree implicit data wrapper
|
||||
data_func *dat_func = NULL ;
|
||||
|
||||
// octree data file wrapper
|
||||
data_file *dat_data = NULL ;
|
||||
|
||||
|
||||
// maximal level of the tree
|
||||
int max_level = 4;
|
||||
|
||||
// isovalue
|
||||
float iso_val = 0.0 ;
|
||||
|
||||
// curvature threshold
|
||||
float curv_thres = 0.5 ;
|
||||
|
||||
// selected implicit function
|
||||
int curr_fun = 0 ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// main glui class: (right) side panel
|
||||
GLUI *glui_side = NULL ;
|
||||
|
||||
// bottom panel
|
||||
GLUI *glui_bottom = NULL ;
|
||||
|
||||
// name of the import file
|
||||
GLUI_FileBrowser *file_browser ;
|
||||
|
||||
// iso file
|
||||
GLUI_String filename ;
|
||||
|
||||
// formula of the implicit function
|
||||
GLUI_String impl_fun ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// control events callback
|
||||
void control_cb( int control ) ;
|
||||
|
||||
// create side panel
|
||||
void create_side_panel() ;
|
||||
|
||||
// create bottom panel
|
||||
void create_bottom_panel() ;
|
||||
|
||||
/// set file extension
|
||||
int set_ext( const char ext[4] ) ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// control events callback
|
||||
void control_cb( int control )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
data_access *ref = NULL ;
|
||||
switch( impl_data )
|
||||
{
|
||||
case SWITCH_IMPL : ref = dat_func ; break ;
|
||||
case SWITCH_DATA : ref = dat_data ; break ;
|
||||
}
|
||||
|
||||
switch( control )
|
||||
{
|
||||
case SET_IMPL_DATA_ID :
|
||||
switch( impl_data )
|
||||
{
|
||||
case SWITCH_IMPL : delete dat_func ; dat_func = new data_func ( max_level, iso_val, impl_fun ) ; break ;
|
||||
case SWITCH_DATA : delete dat_data ; dat_data = new data_file ( max_level, iso_val, filename.c_str() ) ; break ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case SET_VAL_ID :
|
||||
if( !ref ) break ;
|
||||
ref->_max_level = max_level ;
|
||||
ref->_iso_val = iso_val ;
|
||||
octree.set_impl( ref ) ;
|
||||
octree.check() ;
|
||||
break ;
|
||||
|
||||
case REFINE_ID :
|
||||
if( !ref ) break ;
|
||||
ref->_max_level = max_level ;
|
||||
ref->_iso_val = iso_val ;
|
||||
octree.clear() ;
|
||||
octree.refine( ref ) ;
|
||||
octree.set_impl( ref ) ;
|
||||
octree.check() ;
|
||||
break ;
|
||||
|
||||
case ADAPT_ID :
|
||||
if( !ref ) break ;
|
||||
ref->_max_level = max_level ;
|
||||
ref->_iso_val = iso_val ;
|
||||
octree.adapt( ref ) ;
|
||||
octree.set_impl( ref ) ;
|
||||
octree.check() ;
|
||||
break ;
|
||||
|
||||
case ISO_BUILD_ID :
|
||||
if( !ref ) break ;
|
||||
ref->_iso_val = iso_val ;
|
||||
octree.build_isosurface(ref) ;
|
||||
octree.mc().writeOFF("iso.off") ;
|
||||
octree.check() ;
|
||||
break ;
|
||||
|
||||
// set implicit function
|
||||
case FUN_ID :
|
||||
if( curr_fun == 0 ) break ;
|
||||
impl_fun.clear() ;
|
||||
impl_fun = fun_def[curr_fun] ;
|
||||
control_cb( SET_IMPL_DATA_ID ) ;
|
||||
control_cb( ADAPT_ID ) ;
|
||||
glui_bottom->sync_live() ;
|
||||
break ;
|
||||
|
||||
|
||||
// load/save viewpoint
|
||||
case SAVE_VIEWPORT_ID : save_viewport() ; break ;
|
||||
|
||||
case LOAD_VIEWPORT_ID : load_viewport() ; glui_bottom->sync_live() ; break ;
|
||||
|
||||
// reset rotation
|
||||
case RESET_ROTATION_ID :
|
||||
view_rotate[ 0] = view_rotate[ 5] = view_rotate[10] = view_rotate[15] = 1.0f ;
|
||||
view_rotate[ 1] = view_rotate[ 2] = view_rotate[ 3] = view_rotate[ 4] = 0.0f ;
|
||||
view_rotate[ 6] = view_rotate[ 7] = view_rotate[ 8] = view_rotate[ 9] = 0.0f ;
|
||||
view_rotate[11] = view_rotate[12] = view_rotate[13] = view_rotate[14] = 0.0f ;
|
||||
break ;
|
||||
|
||||
// reset translation
|
||||
case RESET_TRANSLATION_ID : obj_pos[0] = obj_pos[1] = 0.0f ; break ;
|
||||
// reset zoom
|
||||
case RESET_ZOOM_ID : obj_pos[2] = 0.0f ; break ;
|
||||
|
||||
// changed a parameter
|
||||
case REDRAW_ID : break ;
|
||||
|
||||
// changed a parameter
|
||||
case FILENAME_ID : filename = file_browser->current_dir + file_browser->get_file() ;
|
||||
|
||||
// orthographic/perspective projection
|
||||
case PROJ_ID : reshape (0,0) ; break ;
|
||||
|
||||
case EXIT_ID :
|
||||
delete dat_func ;
|
||||
delete dat_data ;
|
||||
octree.clear() ;
|
||||
exit(0) ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
}
|
||||
|
||||
::glutPostRedisplay();
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// create side panel
|
||||
void create_side_panel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
glui_side = NULL ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// create bottom panel
|
||||
void create_bottom_panel()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
GLUI_Rollout *roll ;
|
||||
GLUI_EditText *text ;
|
||||
GLUI_Rotation *rot ;
|
||||
GLUI_Translation *trans;
|
||||
GLUI_RadioGroup *radio;
|
||||
GLUI_Listbox *list ;
|
||||
GLUI_Scrollbar *sb ;
|
||||
|
||||
glui_bottom = GLUI_Master.create_glui("controls") ; //create_glui_subwindow( main_window, GLUI_SUBWINDOW_BOTTOM );
|
||||
|
||||
//--------------------------------------------------//
|
||||
|
||||
file_browser = new GLUI_FileBrowser( glui_bottom, "iso file", false, FILENAME_ID, control_cb ) ;
|
||||
file_browser->current_dir = "data" ;
|
||||
file_browser->fbreaddir( "data" ) ;
|
||||
|
||||
filename = "data/engine.iso.gz";
|
||||
text = glui_bottom ->add_edittext( "iso file" , filename ) ;
|
||||
text->set_w( 200 ) ;
|
||||
|
||||
list = glui_bottom->add_listbox( "Implicit Functions:", &curr_fun, FUN_ID, control_cb );
|
||||
for( int i=0; i<NFUNS; i++ ) list->add_item( i, fun_list[i] );
|
||||
|
||||
impl_fun = "";
|
||||
text = glui_bottom ->add_edittext( "impl fun" , impl_fun ) ;
|
||||
text->set_w( 200 ) ;
|
||||
|
||||
|
||||
//--------------------------------------------------//
|
||||
//
|
||||
roll = glui_bottom ->add_rollout( "iso value", true );
|
||||
sb = new GLUI_Scrollbar( roll, "iso value in [-1,1]",GLUI_SCROLL_HORIZONTAL, &iso_val, ADAPT_ID,control_cb);
|
||||
sb->set_float_limits(-1,1);
|
||||
sb->set_speed( .005f );
|
||||
|
||||
roll = glui_bottom ->add_rollout( "level in [2,7]", true );
|
||||
sb = new GLUI_Scrollbar( roll, "level", GLUI_SCROLL_HORIZONTAL, &max_level, ADAPT_ID, control_cb);
|
||||
sb->set_int_limits(2,7);
|
||||
sb->set_speed( .005f );
|
||||
|
||||
//--------------------------------------------------//
|
||||
glui_bottom->add_column( true );
|
||||
radio = glui_bottom->add_radiogroup( &impl_data, SET_IMPL_DATA_ID, control_cb ) ;
|
||||
glui_bottom->add_radiobutton_to_group( radio, "Implicit function" ) ;
|
||||
glui_bottom->add_radiobutton_to_group( radio, "Direct data file" ) ;
|
||||
|
||||
//--------------------------------------------------//
|
||||
|
||||
|
||||
glui_bottom ->add_button ( "load" , SET_IMPL_DATA_ID, control_cb ) ;
|
||||
glui_bottom ->add_button ( "set values", SET_VAL_ID , control_cb ) ;
|
||||
glui_bottom ->add_button ( "refine" , REFINE_ID, control_cb ) ;
|
||||
glui_bottom ->add_button ( "adapt" , ADAPT_ID , control_cb ) ;
|
||||
|
||||
|
||||
//--------------------------------------------------//
|
||||
// display element
|
||||
glui_bottom->add_checkbox( "ortho" , &ortho , PROJ_ID , control_cb );
|
||||
glui_bottom->add_checkbox( "octree" , &show_octree , REDRAW_ID, control_cb );
|
||||
glui_bottom->add_checkbox( "nodes" , &show_nodes , REDRAW_ID, control_cb );
|
||||
glui_bottom->add_checkbox( "dual" , &show_dual , REDRAW_ID, control_cb );
|
||||
glui_bottom->add_checkbox( "surface" , &show_iso , REDRAW_ID, control_cb );
|
||||
glui_bottom->add_checkbox( "dir surf" , &show_direct_iso , SET_VAL_ID, control_cb );
|
||||
glui_bottom->add_checkbox( "dir sur w", &show_direct_iso_wire, SET_VAL_ID, control_cb );
|
||||
|
||||
|
||||
glui_bottom ->add_button ( "Isosurface", ISO_BUILD_ID, control_cb ) ;
|
||||
|
||||
// glui_bottom->add_button( "Redraw", REDRAW_ID, control_cb ) ;
|
||||
|
||||
glui_bottom ->add_button( "Open View", LOAD_VIEWPORT_ID, control_cb ) ;
|
||||
glui_bottom ->add_button( "Save View", SAVE_VIEWPORT_ID, control_cb ) ;
|
||||
glui_bottom ->add_button( "Quit", EXIT_ID, control_cb );
|
||||
glui_bottom->add_column( true );
|
||||
|
||||
|
||||
glui_bottom->add_column( true );
|
||||
|
||||
//--------------------------------------------------//
|
||||
// position
|
||||
roll = glui_bottom ->add_rollout( "3D position", true );
|
||||
objects_rot = glui_bottom->add_rotation_to_panel( roll, "Objects", view_rotate );
|
||||
objects_rot->set_spin( 1.0f );
|
||||
glui_bottom->add_button_to_panel( roll, "Reset", RESET_ROTATION_ID, control_cb ) ;
|
||||
glui_bottom->add_column_to_panel( roll, false );
|
||||
|
||||
objects_mv = glui_bottom->add_translation_to_panel( roll, "Objects XY", GLUI_TRANSLATION_XY, obj_pos );
|
||||
objects_mv->set_speed( .005f );
|
||||
glui_bottom->add_button_to_panel( roll, "Reset", RESET_TRANSLATION_ID, control_cb ) ;
|
||||
glui_bottom->add_column_to_panel( roll, false );
|
||||
|
||||
objects_zm = glui_bottom->add_translation_to_panel( roll, "Objects Z", GLUI_TRANSLATION_Z, &obj_pos[2] );
|
||||
objects_zm->set_speed( .005f );
|
||||
glui_bottom->add_button_to_panel( roll, "Reset", RESET_ZOOM_ID, control_cb ) ;
|
||||
|
||||
|
||||
//--------------------------------------------------//
|
||||
// Lights
|
||||
roll = glui_bottom->add_rollout( "Lights", true );
|
||||
rot = glui_bottom->add_rotation_to_panel( roll, "Blue Light", light0_rotation );
|
||||
rot->set_spin( .82f );
|
||||
|
||||
rot = glui_bottom->add_rotation_to_panel( roll, "Orange Light", light1_rotation );
|
||||
rot->set_spin( .82f );
|
||||
|
||||
|
||||
glui_bottom->add_column_to_panel( roll, false );
|
||||
|
||||
glui_bottom->add_checkbox_to_panel( roll, "On", &light0_enabled );
|
||||
text = glui_bottom->add_edittext_to_panel( roll, "Id (%)", GLUI_EDITTEXT_INT, &light0_intensity );
|
||||
text->set_int_limits( 0, 100 );
|
||||
text->set_w(4) ;
|
||||
text = glui_bottom->add_edittext_to_panel( roll, "Is (%)", GLUI_EDITTEXT_INT, &light0_intensity2 );
|
||||
text->set_int_limits( 0, 100 );
|
||||
text->set_w(4) ;
|
||||
|
||||
glui_bottom->add_checkbox_to_panel( roll, "On", &light1_enabled );
|
||||
text = glui_bottom->add_edittext_to_panel( roll, "Id (%)", GLUI_EDITTEXT_INT, &light1_intensity );
|
||||
text->set_int_limits( 0, 100 );
|
||||
text->set_w(4) ;
|
||||
text = glui_bottom->add_edittext_to_panel( roll, "Is (%)", GLUI_EDITTEXT_INT, &light1_intensity2 );
|
||||
text->set_int_limits( 0, 100 );
|
||||
text->set_w(4) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
@ -0,0 +1,361 @@
|
||||
/**
|
||||
* @file glui_defs.h
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.1
|
||||
* @date 30/05/2006
|
||||
*
|
||||
* @brief Octree graphical interface
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma interface
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include <GL/glui.h> // openGL user interface
|
||||
|
||||
|
||||
#define OCTREE_SWITCH 4
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// octree switch
|
||||
#ifdef OCTREE_SWITCH
|
||||
# if OCTREE_SWITCH==0
|
||||
# define OCTREE_PTR 1
|
||||
# elif OCTREE_SWITCH==1
|
||||
# define OCTREE_HASH 1
|
||||
# elif OCTREE_SWITCH==2
|
||||
# define OCTREE_OPT 1
|
||||
# elif OCTREE_SWITCH==3
|
||||
# define OCTREE_LEAF 1
|
||||
# elif OCTREE_SWITCH==4
|
||||
# define OCTREE_MEM 1
|
||||
# endif // OCTREE_SWITCH
|
||||
#endif // OCTREE_SWITCH
|
||||
|
||||
|
||||
// switch values between pointer and hash octree
|
||||
#if !OCTREE_PTR && !OCTREE_HASH && !OCTREE_OPT && !OCTREE_LEAF && !OCTREE_MEM
|
||||
// # define OCTREE_PTR 1
|
||||
// # define OCTREE_HASH 1
|
||||
# define OCTREE_OPT 1
|
||||
// # define OCTREE_LEAF 1
|
||||
// # define OCTREE_MEM 1
|
||||
#endif // !OCTREE_PTR && !OCTREE_HASH && !OCTREE_OPT && !OCTREE_LEAF && !OCTREE_MEM
|
||||
|
||||
|
||||
#ifdef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_LEAF
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "pointer octree"
|
||||
# include "ptr_octree.h"
|
||||
/// octree type
|
||||
typedef PtrOctree Octree ;
|
||||
#endif //OCTREE_PTR
|
||||
|
||||
|
||||
#ifdef OCTREE_HASH
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_LEAF
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "hash octree"
|
||||
# include "hash_octree.h"
|
||||
/// octree type
|
||||
typedef HashOctree Octree ;
|
||||
#endif //OCTREE_HASH
|
||||
|
||||
|
||||
#ifdef OCTREE_OPT
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_LEAF
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "optimized octree"
|
||||
# include "opt_octree.h"
|
||||
/// octree type
|
||||
typedef OptOctree Octree ;
|
||||
#endif //OCTREE_OPT
|
||||
|
||||
|
||||
#ifdef OCTREE_LEAF
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_MEM
|
||||
# define OCTREE_STRING "leaf octree"
|
||||
# include "leaf_octree.h"
|
||||
/// octree type
|
||||
typedef LeafOctree Octree ;
|
||||
#endif //OCTREE_LEAF
|
||||
|
||||
|
||||
#ifdef OCTREE_MEM
|
||||
# undef OCTREE_PTR
|
||||
# undef OCTREE_HASH
|
||||
# undef OCTREE_OPT
|
||||
# undef OCTREE_LEAF
|
||||
# define OCTREE_STRING "mem octree"
|
||||
# include "mem_octree.h"
|
||||
/// octree type
|
||||
typedef MemOctree Octree ;
|
||||
#endif //OCTREE_MEM
|
||||
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define PRINT_GL_DEBUG { if( ::glGetError() != GL_NO_ERROR ) printf( "openGL watch at line %d: %s\n", __LINE__, ::gluErrorString( ::glGetError() ) ) ; }
|
||||
#else // _DEBUG
|
||||
#define PRINT_GL_DEBUG {}
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// Main objects
|
||||
|
||||
/// main object: octree
|
||||
extern Octree octree ;
|
||||
|
||||
/// switch between implicit funciont or volumetric data
|
||||
extern int impl_data ;
|
||||
|
||||
/// switch values between implicit funciont or volumetric data
|
||||
enum { SWITCH_IMPL = 0, SWITCH_DATA = 1 } ;
|
||||
|
||||
/// octree implicit data wrapper
|
||||
extern data_func *dat_func ;
|
||||
|
||||
/// octree data file wrapper
|
||||
extern data_file *dat_data ;
|
||||
|
||||
/// maximal level of the tree
|
||||
extern int max_level ;
|
||||
|
||||
/// isovalue
|
||||
extern float iso_val ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Display elements
|
||||
|
||||
/// display element switch: octree wireframe
|
||||
extern int show_octree ;
|
||||
/// display element switch: octree cells' centers
|
||||
extern int show_nodes ;
|
||||
/// display element switch: octree dual
|
||||
extern int show_dual ;
|
||||
/// display element switch: isosurface of the field
|
||||
extern int show_iso ;
|
||||
/// display element switch: direct drawing isosurface of the field
|
||||
extern int show_direct_iso ;
|
||||
/// display element switch: direct drawing wire isosurface of the field
|
||||
extern int show_direct_iso_wire ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GLUI windows
|
||||
|
||||
/// main window id
|
||||
extern int main_window ;
|
||||
|
||||
/// main glui class: (right) side panel
|
||||
extern GLUI *glui_side ;
|
||||
|
||||
/// bottom panel
|
||||
extern GLUI *glui_bottom ;
|
||||
|
||||
|
||||
/// create side panel
|
||||
void create_side_panel() ;
|
||||
|
||||
/// create bottom panel
|
||||
void create_bottom_panel() ;
|
||||
|
||||
/// control events callback
|
||||
void control_cb( int control ) ;
|
||||
|
||||
/// parse command line
|
||||
bool parse_command_line(int argc, char* argv[]) ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Lights
|
||||
|
||||
/// enable blue light
|
||||
extern int light0_enabled ;
|
||||
|
||||
/// enable orange light
|
||||
extern int light1_enabled ;
|
||||
|
||||
/// blue light intensity
|
||||
extern int light0_intensity ;
|
||||
|
||||
/// orange light intensity
|
||||
extern int light1_intensity ;
|
||||
|
||||
/// blue light intensity (specular)
|
||||
extern int light0_intensity2 ;
|
||||
|
||||
/// orange light intensity (specular)
|
||||
extern int light1_intensity2 ;
|
||||
|
||||
/// blue light diffuse color
|
||||
extern float light0_diffuse[4] ;
|
||||
|
||||
/// orange light diffuse color
|
||||
extern float light1_diffuse[4] ;
|
||||
|
||||
/// blue light position
|
||||
extern float light0_rotation[16] ;
|
||||
|
||||
/// orange light position
|
||||
extern float light1_rotation[16] ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// mouse and object movements
|
||||
|
||||
/// motion type (-1 -> no motion, 0 -> rotate, 1 -> zoom, 2 -> translate)
|
||||
extern int motion_type ;
|
||||
|
||||
/// window trackball
|
||||
extern GLUI_Rotation mouse_rot ;
|
||||
/// panel trackball
|
||||
extern GLUI_Rotation *objects_rot ;
|
||||
/// window translation
|
||||
extern GLUI_Translation mouse_mv ;
|
||||
/// panel translation
|
||||
extern GLUI_Translation *objects_mv ;
|
||||
/// window zoom
|
||||
extern GLUI_Translation mouse_zm ;
|
||||
/// panel zoom
|
||||
extern GLUI_Translation *objects_zm ;
|
||||
|
||||
/// number of calls for updating the GLUI control
|
||||
extern int ncalls ;
|
||||
|
||||
/// export movie switch
|
||||
extern int export_movie ;
|
||||
|
||||
/// automatic rotation
|
||||
extern int auto_rotate ;
|
||||
|
||||
/// automatic x translation
|
||||
extern int auto_translate_x ;
|
||||
|
||||
/// automatic y translation
|
||||
extern int auto_translate_y ;
|
||||
|
||||
/// automatic zoom
|
||||
extern int auto_zoom ;
|
||||
|
||||
/// automatic plane
|
||||
extern int auto_translate_d ;
|
||||
|
||||
/// mouse x position
|
||||
extern int mouse_x ;
|
||||
|
||||
/// mouse y position
|
||||
extern int mouse_y ;
|
||||
|
||||
/// init mouse and window controls
|
||||
void init_trackballs() ;
|
||||
|
||||
/// mouse events tracking
|
||||
void mouse(int button, int button_state, int x, int y ) ;
|
||||
|
||||
/// mouse motion tracking
|
||||
void motion(int x, int y ) ;
|
||||
|
||||
/// keyboard events
|
||||
void keyboard(unsigned char key, int x, int y);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// implicit function
|
||||
|
||||
/// implicit function formula
|
||||
extern GLUI_String impl_fun ;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// i/o filenames
|
||||
|
||||
/// iso file
|
||||
extern GLUI_String filename ;
|
||||
|
||||
/// file browser
|
||||
extern GLUI_FileBrowser *file_browser ;
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// drawing parameters
|
||||
|
||||
/// orthographic / perspective projection switch
|
||||
extern int ortho ;
|
||||
/// object rotation
|
||||
extern float view_rotate[16] ;
|
||||
/// object translation
|
||||
extern float obj_pos [3 ] ;
|
||||
|
||||
/// point size
|
||||
extern int point_size;
|
||||
|
||||
/// 3D projection matrix
|
||||
void project( int o, float sx, float sy, int &tx, int &ty, int &tw, int &th ) ;
|
||||
|
||||
/// window resizing
|
||||
void reshape( int x, int y ) ;
|
||||
|
||||
/// main drawing function
|
||||
void display() ;
|
||||
|
||||
/// print screen
|
||||
void export_png() ;
|
||||
|
||||
/// load viewport
|
||||
void load_viewport() ;
|
||||
/// save viewport
|
||||
void save_viewport() ;
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
/// Callback ids
|
||||
enum
|
||||
{
|
||||
SET_IMPL_DATA_ID ,
|
||||
SET_VAL_ID ,
|
||||
REFINE_ID ,
|
||||
ADAPT_ID ,
|
||||
ISO_BUILD_ID ,
|
||||
SEARCH_ID ,
|
||||
FUN_ID ,
|
||||
|
||||
SAVE_VIEWPORT_ID ,
|
||||
LOAD_VIEWPORT_ID ,
|
||||
|
||||
RESET_ROTATION_ID ,
|
||||
RESET_TRANSLATION_ID ,
|
||||
RESET_ZOOM_ID ,
|
||||
|
||||
REDRAW_ID ,
|
||||
FILENAME_ID ,
|
||||
PROJ_ID ,
|
||||
|
||||
EXIT_ID
|
||||
};
|
||||
//_____________________________________________________________________________
|
||||
|
||||
@ -0,0 +1,321 @@
|
||||
/**
|
||||
* @file glui_draws.cpp
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.1
|
||||
* @date 30/05/2006
|
||||
*
|
||||
* @brief Octree graphical interface: drawing commands
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma implementation "viz_glui_defs.h"
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "viz_glui_defs.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// declarations of this file
|
||||
|
||||
|
||||
// display element switches
|
||||
int show_octree = 1 ;
|
||||
int show_nodes = 0 ;
|
||||
int show_dual = 0 ;
|
||||
int show_iso = 0 ;
|
||||
int show_direct_iso = 0 ;
|
||||
int show_direct_iso_wire = 0 ;
|
||||
|
||||
// orthographic / perspective projection
|
||||
int ortho = 0 ;
|
||||
|
||||
// object transformation
|
||||
float view_rotate[16] = { 1.0f,0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f,0.0f, 0.0f,0.0f,1.0f,0.0f, 0.0f,0.0f,0.0f,1.0f };
|
||||
float obj_pos [3 ] = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// lights
|
||||
int light0_enabled = 1 ;
|
||||
int light1_enabled = 0 ;
|
||||
int light0_intensity = 100 ;
|
||||
int light1_intensity = 60 ;
|
||||
int light0_intensity2 = 50 ;
|
||||
int light1_intensity2 = 30 ;
|
||||
GLfloat light0_diffuse [ 4] = {.7f, .7f, 1.0f, 1.0f};
|
||||
GLfloat light1_diffuse [ 4] = {.9f, .7f, 0.2f, 1.0f};
|
||||
GLfloat light0_position[ 4] = {.5f, .5f, 10.0f, 0.0f};
|
||||
GLfloat light1_position[ 4] = {-1.0f, -1.0f, 10.0f, 0.0f};
|
||||
GLfloat light0_rotation[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
|
||||
GLfloat light1_rotation[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 3D projection matrix
|
||||
void project( int o, float sx, float sy, int &tx, int &ty, int &tw, int &th ) ;
|
||||
|
||||
// window resizing
|
||||
void reshape( int x, int y ) ;
|
||||
|
||||
// main drawing function
|
||||
void display() ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// 3D projection matrix
|
||||
void project( int o, float sx, float sy, int &tx, int &ty, int &tw, int &th )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// get viewport
|
||||
GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
|
||||
|
||||
tw = (int)( tw * sx );
|
||||
th = (int)( th * sy );
|
||||
::glViewport( tx, ty, tw, th );
|
||||
|
||||
// sets the projection matrix
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadIdentity();
|
||||
|
||||
// sets the viewport
|
||||
if( o )
|
||||
{
|
||||
if( th > tw )
|
||||
::glOrtho( -1.2, 1.2, -1.2*(double)th/tw, 1.2*(double)th/tw, 0.0, 10.0 ) ;
|
||||
else
|
||||
::glOrtho( -1.2*(double)tw/th, 1.2*(double)tw/th, -1.2, 1.2, 0.0, 10.0 ) ;
|
||||
}
|
||||
else
|
||||
::gluPerspective( 45.0, th>0?(double)tw/th:1.0, 0.5, 10.0 );
|
||||
|
||||
::gluLookAt( 0.0f,0.0f,3.0f, 0.0f,0.0f,0.5f, 0.0f,1.0f,0.0f ) ;
|
||||
|
||||
// switch to the modelview matrix
|
||||
::glMatrixMode( GL_MODELVIEW );
|
||||
::glLoadIdentity();
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// window resizing
|
||||
void reshape( int x, int y )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
::glutSetWindow(main_window);
|
||||
|
||||
int tx, ty, tw, th;
|
||||
project( ortho, 1.0f, 1.0f, tx, ty, tw, th ) ;
|
||||
|
||||
// sets the window trackball
|
||||
mouse_rot.set_w( tw ) ;
|
||||
mouse_rot.set_h( th ) ;
|
||||
mouse_mv .set_w( tw ) ;
|
||||
mouse_mv .set_h( th ) ;
|
||||
mouse_zm .set_w( tw ) ;
|
||||
mouse_zm .set_h( th ) ;
|
||||
|
||||
// redisplay
|
||||
::glutPostRedisplay();
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// main drawing function
|
||||
void display()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
::glutSetWindow(main_window);
|
||||
|
||||
// clear screen
|
||||
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
if( !true ) { ::glutSwapBuffers(); return ; }
|
||||
|
||||
int tx, ty, tw, th ;
|
||||
project( ortho, 1.0f, 1.0f, tx, ty, tw, th ) ;
|
||||
|
||||
::glEnable( GL_DEPTH_TEST );
|
||||
::glShadeModel(GL_SMOOTH);
|
||||
::glEnable(GL_LIGHTING);
|
||||
|
||||
//::glDisable (GL_LIGHTING);
|
||||
float val[3] ;
|
||||
if ( light0_enabled )
|
||||
{
|
||||
::glEnable( GL_LIGHT0 ) ;
|
||||
|
||||
val[0] = light0_diffuse[0] * light0_intensity / 100 ;
|
||||
val[1] = light0_diffuse[1] * light0_intensity / 100 ;
|
||||
val[2] = light0_diffuse[2] * light0_intensity / 100 ;
|
||||
::glLightfv(GL_LIGHT0, GL_DIFFUSE, val );
|
||||
|
||||
val[0] = light0_diffuse[0] * light0_intensity2 / 100 ;
|
||||
val[1] = light0_diffuse[1] * light0_intensity2 / 100 ;
|
||||
val[2] = light0_diffuse[2] * light0_intensity2 / 100 ;
|
||||
::glLightfv(GL_LIGHT0, GL_SPECULAR, val );
|
||||
const GLfloat light0_ambient[4] = {0.1f, 0.1f, 0.3f, 1.0f};
|
||||
::glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
|
||||
|
||||
|
||||
::glLoadIdentity();
|
||||
::glMultMatrixf( light0_rotation );
|
||||
::glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
|
||||
|
||||
}
|
||||
else
|
||||
::glDisable( GL_LIGHT0 );
|
||||
|
||||
if ( light1_enabled )
|
||||
{
|
||||
::glEnable( GL_LIGHT1 );
|
||||
|
||||
val[0] = light1_diffuse[0] * light1_intensity / 100 ;
|
||||
val[1] = light1_diffuse[1] * light1_intensity / 100 ;
|
||||
val[2] = light1_diffuse[2] * light1_intensity / 100 ;
|
||||
::glLightfv(GL_LIGHT1, GL_DIFFUSE, val );
|
||||
|
||||
val[0] = light1_diffuse[0] * light1_intensity2 / 100 ;
|
||||
val[1] = light1_diffuse[1] * light1_intensity2 / 100 ;
|
||||
val[2] = light1_diffuse[2] * light1_intensity2 / 100 ;
|
||||
::glLightfv(GL_LIGHT1, GL_SPECULAR, val );
|
||||
const GLfloat light1_ambient[4] = {0.1f, 0.1f, 0.3f, 1.0f};
|
||||
::glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
|
||||
|
||||
::glLoadIdentity();
|
||||
::glMultMatrixf( light1_rotation );
|
||||
::glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
|
||||
|
||||
}
|
||||
else
|
||||
::glDisable( GL_LIGHT1 );
|
||||
|
||||
// transformation matrix
|
||||
::glLoadIdentity();
|
||||
::glTranslatef( obj_pos[0], obj_pos[1], obj_pos[2] );
|
||||
if( ortho )
|
||||
{
|
||||
::glScalef( 1.0+obj_pos[2], 1.0+obj_pos[2], 1.0+obj_pos[2] ) ;
|
||||
::glEnable( GL_NORMALIZE );
|
||||
}
|
||||
else
|
||||
{
|
||||
::glDisable( GL_NORMALIZE );
|
||||
}
|
||||
|
||||
::glMultMatrixf( view_rotate );
|
||||
::glTranslatef( -0.5f, -0.5f, -0.5f );
|
||||
PRINT_GL_DEBUG ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 3D display
|
||||
|
||||
data_access *ref = NULL ;
|
||||
switch( impl_data )
|
||||
{
|
||||
case SWITCH_IMPL : ref = dat_func ; break ;
|
||||
case SWITCH_DATA : ref = dat_data ; break ;
|
||||
}
|
||||
if( ref )
|
||||
::glScalef( ref->_sx, ref->_sy, ref->_sz ) ;
|
||||
|
||||
// octree wireframe
|
||||
if( show_octree )
|
||||
{
|
||||
::glDisable( GL_TEXTURE_1D ) ;
|
||||
::glLineWidth( 0.5 ) ;
|
||||
::glColor3f( 0.3f, 0.3f, 0.5f ) ;
|
||||
::glBegin( GL_LINES ) ;
|
||||
{
|
||||
octree.draw_wire() ;
|
||||
}
|
||||
::glEnd() ; // GL_LINES
|
||||
}
|
||||
|
||||
|
||||
// cells' centers
|
||||
if( show_nodes )
|
||||
{
|
||||
::glEnable( GL_TEXTURE_1D ) ;
|
||||
::glPointSize( 4.0 ) ;
|
||||
::glColor3f( 0.0f, 0.8f, 0.2f ) ;
|
||||
::glBegin( GL_POINTS ) ;
|
||||
{
|
||||
octree.draw_centers() ;
|
||||
}
|
||||
::glEnd() ; // GL_POINTS
|
||||
}
|
||||
|
||||
// octree dual
|
||||
if( show_dual )
|
||||
{
|
||||
::glDisable( GL_TEXTURE_1D ) ;
|
||||
::glDisable(GL_LIGHTING);
|
||||
octree.draw_dual() ;
|
||||
::glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
// isosurface of the field
|
||||
if( show_iso )
|
||||
{
|
||||
::glDisable( GL_TEXTURE_1D ) ;
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;
|
||||
::glColor3f( 0.3f, 0.3f, 0.5f ) ;
|
||||
::glBegin( GL_TRIANGLES ) ;
|
||||
octree.draw_iso() ;
|
||||
::glEnd() ; // GL_TRIANGLES
|
||||
|
||||
::glEnable(GL_LIGHTING);
|
||||
::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) ;
|
||||
::glColor3f( 0.6f, 0.6f, 0.7f ) ;
|
||||
::glBegin( GL_TRIANGLES ) ;
|
||||
octree.draw_iso() ;
|
||||
::glEnd() ; // GL_TRIANGLES
|
||||
}
|
||||
|
||||
if( ref && show_direct_iso_wire )
|
||||
{
|
||||
::glDisable( GL_TEXTURE_1D ) ;
|
||||
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;
|
||||
::glColor3f( 0.3f, 0.3f, 0.5f ) ;
|
||||
::glBegin( GL_TRIANGLES ) ;
|
||||
octree.direct_draw_isosurface(ref) ;
|
||||
::glEnd() ; // GL_TRIANGLES
|
||||
}
|
||||
|
||||
if( ref && show_direct_iso )
|
||||
{
|
||||
::glDisable( GL_TEXTURE_1D ) ;
|
||||
|
||||
::glEnable(GL_LIGHTING);
|
||||
::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) ;
|
||||
::glColor3f( 0.6f, 0.6f, 0.7f ) ;
|
||||
::glBegin( GL_TRIANGLES ) ;
|
||||
octree.direct_draw_isosurface(ref) ;
|
||||
::glEnd() ; // GL_TRIANGLES
|
||||
}
|
||||
|
||||
PRINT_GL_DEBUG ;
|
||||
|
||||
// next frame
|
||||
::glutSwapBuffers();
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,323 @@
|
||||
/**
|
||||
* @file glui_export.cpp
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.1
|
||||
* @date 20/08/2007
|
||||
*
|
||||
* @brief Example Graphical interface: screen image exporatation
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#pragma implementation "viz_glui_defs.h"
|
||||
#endif // WIN32
|
||||
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
#include "viz_glui_defs.h"
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// declarations of this file
|
||||
|
||||
// set file extension of filename
|
||||
int set_ext( const char ext[3], char *fn ) ;
|
||||
|
||||
// PPM export
|
||||
void export_ppm() ;
|
||||
|
||||
// PNG image export
|
||||
void export_png() ;
|
||||
|
||||
// Viewport save
|
||||
void save_viewport() ;
|
||||
|
||||
// Viewport load
|
||||
void load_viewport() ;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// set file extension of filename
|
||||
int set_ext( const char ext[3], char *fn )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
strcpy( fn, filename.c_str() ) ;
|
||||
int l = (int)strlen(fn) ;
|
||||
if( l == 0 ) return 0 ;
|
||||
if( fn[l-4] != '.' )
|
||||
{
|
||||
strcat( fn, "." ) ;
|
||||
strcat( fn, ext ) ;
|
||||
}
|
||||
else if( strcmp( fn + l-3, ext ) )
|
||||
{
|
||||
fn[l-3] = ext[0] ;
|
||||
fn[l-2] = ext[1] ;
|
||||
fn[l-1] = ext[2] ;
|
||||
}
|
||||
|
||||
return l ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// PPM export
|
||||
void export_ppm()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
char fn[1024] ;
|
||||
set_ext( "ppm", fn ) ;
|
||||
FILE *fp = fopen( fn, "w" ) ;
|
||||
if( !fp ) return ;
|
||||
|
||||
int tx, ty, tw, th;
|
||||
glutSetWindow(main_window);
|
||||
GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
|
||||
|
||||
// read openGL buffer
|
||||
int buf_size = (tw * th * 3);
|
||||
unsigned char *buffer = new unsigned char[buf_size] ;
|
||||
memset(buffer, 0, buf_size * sizeof(unsigned char)) ;
|
||||
display() ;
|
||||
glFinish() ;
|
||||
glPixelStorei( GL_PACK_ALIGNMENT, 1 ); // Force 1-byte alignment
|
||||
glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
|
||||
glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
|
||||
glPixelStorei( GL_PACK_SKIP_PIXELS,0 );
|
||||
glReadPixels(tx, ty, tw, th, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
// write the header
|
||||
fprintf(fp, "P6\n%d %d\n", tw, th);
|
||||
fprintf(fp, "# %s (Affine Surface by Thomas Lewiner)\n", fn ) ;
|
||||
fprintf(fp, "255\n");
|
||||
|
||||
// write file
|
||||
for (int i = 0; i < buf_size; ++i)
|
||||
fputc( buffer[i], fp ) ;
|
||||
|
||||
delete [] buffer ;
|
||||
|
||||
fclose(fp);
|
||||
printf( "exported image to PPM file %s\n", fn ) ;
|
||||
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//
|
||||
void export_tga()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
char fn[1024] ;
|
||||
set_ext("tga", fn) ;
|
||||
FILE *fp = fopen( fn, "w" ) ;
|
||||
if (!fp)
|
||||
return ;
|
||||
|
||||
int tx, ty, tw, th;
|
||||
glutSetWindow(main_window);
|
||||
GLUI_Master.get_viewport_area(&tx, &ty, &tw, &th);
|
||||
|
||||
int buf_size = 18 + (tw* th * 3); // HEADER_SIZE ==> 18
|
||||
unsigned char* buffer = new unsigned char[buf_size] ;
|
||||
memset(buffer, 0, buf_size * sizeof(unsigned char)) ;
|
||||
|
||||
// Header
|
||||
buffer[2] = 2; // Non-compressed
|
||||
buffer[12] = tw & 255;
|
||||
buffer[13] = (tw >> 8) & 255 ;
|
||||
buffer[14] = th & 255;
|
||||
buffer[15] = (th >> 8) & 255 ;
|
||||
buffer[16] = 24; // 24 bits per pixel
|
||||
|
||||
// Read openGL buffer
|
||||
display() ;
|
||||
glFinish() ;
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); // Force 1-byte alignment
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
||||
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
||||
glReadPixels(tx, ty, tw, th, GL_RGB, GL_UNSIGNED_BYTE, buffer + 18);
|
||||
|
||||
// Conversion from RGB to BGR
|
||||
for (int i = 18; i < buf_size; i += 3)
|
||||
{
|
||||
unsigned char temp = buffer[i];
|
||||
buffer[i] = buffer[i + 2];
|
||||
buffer[i + 2] = temp;
|
||||
}
|
||||
|
||||
// Write file
|
||||
fwrite(buffer, sizeof(unsigned char), buf_size, fp);
|
||||
fclose(fp);
|
||||
delete[] buffer ;
|
||||
printf("exported image to TGA file %s\n", fn ) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//
|
||||
void save_viewport()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
char fn[1024] ;
|
||||
set_ext( "view", fn ) ;
|
||||
FILE *fp = fopen( fn, "w" ) ;
|
||||
if( !fp ) return ;
|
||||
fprintf( fp, "rotate:\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\n",
|
||||
view_rotate[ 0], view_rotate[ 1], view_rotate[ 2], view_rotate[ 3],
|
||||
view_rotate[ 4], view_rotate[ 5], view_rotate[ 6], view_rotate[ 7],
|
||||
view_rotate[ 8], view_rotate[ 9], view_rotate[10], view_rotate[11],
|
||||
view_rotate[12], view_rotate[13], view_rotate[14], view_rotate[15] ) ;
|
||||
fprintf( fp, "translate:\t%f %f %f\n", obj_pos[0], obj_pos[1], obj_pos[2] ) ;
|
||||
|
||||
fprintf( fp, "plane rotate:\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f\n\n",
|
||||
1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0, 0.0 ) ;
|
||||
|
||||
fprintf( fp, "corner size:\t%f %f\n", 0.0,0.0 ) ;
|
||||
fprintf( fp, "corner trans:\t%f %f %f\n", 0.0,0.0,1.0 ) ;
|
||||
|
||||
|
||||
fprintf( fp, "light 0:\n\t%d %d %d\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\n\n",
|
||||
light0_enabled, light0_intensity, light0_intensity2,
|
||||
light0_diffuse [ 0], light0_diffuse [ 1], light0_diffuse [ 2], light0_diffuse [ 3],
|
||||
light0_rotation[ 0], light0_rotation[ 1], light0_rotation[ 2], light0_rotation[ 3],
|
||||
light0_rotation[ 4], light0_rotation[ 5], light0_rotation[ 6], light0_rotation[ 7],
|
||||
light0_rotation[ 8], light0_rotation[ 9], light0_rotation[10], light0_rotation[11],
|
||||
light0_rotation[12], light0_rotation[13], light0_rotation[14], light0_rotation[15] ) ;
|
||||
|
||||
fprintf( fp, "light 1:\n\t%d %d %d\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\n\n",
|
||||
light1_enabled, light1_intensity, light1_intensity2,
|
||||
light1_diffuse [ 0], light1_diffuse [ 1], light1_diffuse [ 2], light1_diffuse [ 3],
|
||||
light1_rotation[ 0], light1_rotation[ 1], light1_rotation[ 2], light1_rotation[ 3],
|
||||
light1_rotation[ 4], light1_rotation[ 5], light1_rotation[ 6], light1_rotation[ 7],
|
||||
light1_rotation[ 8], light1_rotation[ 9], light1_rotation[10], light1_rotation[11],
|
||||
light1_rotation[12], light1_rotation[13], light1_rotation[14], light1_rotation[15] ) ;
|
||||
|
||||
fclose( fp ) ;
|
||||
|
||||
printf("saved viewport to file %s\n", fn ) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//
|
||||
void load_viewport()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
char fn[1024] ;
|
||||
set_ext("view",fn) ;
|
||||
FILE* fp = fopen( fn, "r" ) ;
|
||||
if( !fp ) return ;
|
||||
fscanf( fp, "rotate: %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ",
|
||||
view_rotate + 0, view_rotate + 1, view_rotate + 2, view_rotate + 3,
|
||||
view_rotate + 4, view_rotate + 5, view_rotate + 6, view_rotate + 7,
|
||||
view_rotate + 8, view_rotate + 9, view_rotate + 10, view_rotate + 11,
|
||||
view_rotate + 12, view_rotate + 13, view_rotate + 14, view_rotate + 15 ) ;
|
||||
fscanf( fp, "translate: %f %f %f ", obj_pos + 0, obj_pos + 1, obj_pos + 2 ) ;
|
||||
|
||||
fscanf ( fp, "plane rotate:\n\t%*f %*f %*f %*f\n\t%*f %*f %*f %*f\n\t%*f %*f %*f %*f\n\t%*f %*f %*f %*f\n\t%*f\n\n" ) ;
|
||||
|
||||
fscanf ( fp, "corner size:\t%*f %*f\n" ) ;
|
||||
fscanf ( fp, "corner trans:\t%*f %*f %*f\n" ) ;
|
||||
|
||||
|
||||
fscanf ( fp, "light 0:\n\t%d %d %d\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\n\n",
|
||||
&light0_enabled, &light0_intensity, &light0_intensity2,
|
||||
light0_diffuse + 0, light0_diffuse + 1, light0_diffuse + 2, light0_diffuse + 3,
|
||||
light0_rotation + 0, light0_rotation + 1, light0_rotation + 2, light0_rotation + 3,
|
||||
light0_rotation + 4, light0_rotation + 5, light0_rotation + 6, light0_rotation + 7,
|
||||
light0_rotation + 8, light0_rotation + 9, light0_rotation + 10, light0_rotation + 11,
|
||||
light0_rotation + 12, light0_rotation + 13, light0_rotation + 14, light0_rotation + 15 ) ;
|
||||
|
||||
fscanf ( fp, "light 1:\n\t%d %d %d\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\t%f %f %f %f\n\n\n",
|
||||
&light1_enabled, &light1_intensity, &light1_intensity2,
|
||||
light1_diffuse + 0, light1_diffuse + 1, light1_diffuse + 2, light1_diffuse + 3,
|
||||
light1_rotation + 0, light1_rotation + 1, light1_rotation + 2, light1_rotation + 3,
|
||||
light1_rotation + 4, light1_rotation + 5, light1_rotation + 6, light1_rotation + 7,
|
||||
light1_rotation + 8, light1_rotation + 9, light1_rotation + 10, light1_rotation + 11,
|
||||
light1_rotation + 12, light1_rotation + 13, light1_rotation + 14, light1_rotation + 15 ) ;
|
||||
|
||||
fclose( fp ) ;
|
||||
|
||||
printf("loaded viewport from file %s\n", fn ) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// PNG export
|
||||
void export_png()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
char fn[1024] ;
|
||||
set_ext( "png", fn ) ;
|
||||
FILE *fp = fopen( fn, "wb" ) ;
|
||||
if( !fp ) return ;
|
||||
|
||||
int tx, ty, tw, th;
|
||||
glutSetWindow(main_window);
|
||||
GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
|
||||
|
||||
// read openGL buffer
|
||||
int buf_size = (tw * th * 3);
|
||||
unsigned char *buffer = new unsigned char[buf_size] ;
|
||||
memset(buffer, 0, buf_size * sizeof(unsigned char)) ;
|
||||
display() ;
|
||||
glFinish() ;
|
||||
glPixelStorei( GL_PACK_ALIGNMENT, 1 ); // Force 1-byte alignment
|
||||
glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
|
||||
glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
|
||||
glPixelStorei( GL_PACK_SKIP_PIXELS,0 );
|
||||
glReadPixels(tx, ty, tw, th, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL);
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_IHDR(png_ptr, info_ptr, tw, th, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
for (int i=0; i<th; i++)
|
||||
png_write_row(png_ptr, &(buffer[3*tw*((th-1) - i)]));
|
||||
png_write_end(png_ptr, NULL);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
delete [] buffer ;
|
||||
|
||||
fclose(fp);
|
||||
printf( "exported image to PNG file %s\n", fn ) ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,312 @@
|
||||
/**
|
||||
* @file glui_mouse.cpp
|
||||
* @author Thomas Lewiner <thomas.lewiner@polytechnique.org>
|
||||
* @author Math Dept, PUC-Rio
|
||||
* @version 0.1
|
||||
* @date 30/05/2006
|
||||
*
|
||||
* @brief Octree Graphical interface: mouse controls
|
||||
*/
|
||||
//________________________________________________
|
||||
|
||||
|
||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||
#pragma implementation "viz_glui_defs.h"
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#include "viz_glui_defs.h"
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// declarations of this file
|
||||
|
||||
// motion type (-1 -> no motion, 0 -> rotate, 1 -> zoom, 2 -> translate)
|
||||
int motion_type = -1 ;
|
||||
|
||||
// panel and window trackballs and sliders
|
||||
GLUI_Rotation mouse_rot, *objects_rot, *plane_rot ;
|
||||
GLUI_Translation mouse_mv , *objects_mv , *plane_trans ;
|
||||
GLUI_Translation mouse_zm , *objects_zm ;
|
||||
|
||||
// number of calls for updating the GLUI control
|
||||
int ncalls = 0 ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// init mouse and window controls
|
||||
void init_trackballs() ;
|
||||
|
||||
// mouse events tracking
|
||||
void mouse(int button, int button_state, int x, int y ) ;
|
||||
|
||||
// mouse motion tracking
|
||||
void motion(int x, int y ) ;
|
||||
|
||||
// automatic rotation
|
||||
int auto_rotate = 0 ;
|
||||
|
||||
// automatic x translation
|
||||
int auto_translate_x = 0 ;
|
||||
|
||||
// automatic y translation
|
||||
int auto_translate_y = 0 ;
|
||||
|
||||
// automatic zoom
|
||||
int auto_zoom = 0 ;
|
||||
|
||||
// automatic plane
|
||||
int auto_translate_d = 0 ;
|
||||
|
||||
// mouse x position
|
||||
int mouse_x = 0 ;
|
||||
|
||||
// mouse y position
|
||||
int mouse_y = 0 ;
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// init mouse and window controls
|
||||
void init_trackballs()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
// init trackball
|
||||
|
||||
int tx,ty,tw,th ;
|
||||
GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
|
||||
|
||||
mouse_rot.set_spin(0.05f) ;
|
||||
mouse_rot.set_w( tw ) ;
|
||||
mouse_rot.set_h( th ) ;
|
||||
mouse_rot.set_ptr_val( view_rotate );
|
||||
mouse_rot.init_live() ;
|
||||
|
||||
mouse_mv.set_speed(0.005f) ;
|
||||
mouse_mv.set_w( tw ) ;
|
||||
mouse_mv.set_h( th ) ;
|
||||
mouse_mv.set_ptr_val( obj_pos );
|
||||
mouse_mv.init_live() ;
|
||||
|
||||
mouse_mv.trans_type = GLUI_TRANSLATION_XY;
|
||||
mouse_mv.float_array_size = 2 ;
|
||||
mouse_mv.hidden = true ;
|
||||
|
||||
mouse_zm.set_speed(0.01f) ;
|
||||
mouse_zm.set_w( tw ) ;
|
||||
mouse_zm.set_h( th ) ;
|
||||
mouse_zm.set_ptr_val( &obj_pos[2] );
|
||||
mouse_zm.init_live() ;
|
||||
|
||||
mouse_zm.trans_type = GLUI_TRANSLATION_Z ;
|
||||
mouse_zm.float_array_size = 1 ;
|
||||
mouse_zm.hidden = true ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// mouse events
|
||||
void mouse(int button, int button_state, int x, int y )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
mouse_x = x ;
|
||||
mouse_y = y ;
|
||||
|
||||
// determine motion type
|
||||
if ( glutGetModifiers() & GLUT_ACTIVE_CTRL ) motion_type = 1 ;
|
||||
else if( glutGetModifiers() & GLUT_ACTIVE_SHIFT ) motion_type = 2 ;
|
||||
else if( glutGetModifiers() & GLUT_ACTIVE_ALT ) motion_type = 3 ;
|
||||
else motion_type = 0 ;
|
||||
|
||||
switch( motion_type )
|
||||
{
|
||||
// rotation
|
||||
case 0 :
|
||||
// line selection
|
||||
if ( button == GLUT_LEFT_BUTTON){
|
||||
if (button_state == GLUT_DOWN )
|
||||
{
|
||||
mouse_rot.init_live() ;
|
||||
mouse_rot.mouse_down_handler(x,y) ;
|
||||
}
|
||||
if ( button_state != GLUT_DOWN )
|
||||
{
|
||||
mouse_rot.mouse_up_handler(x,y,1) ;
|
||||
motion_type = -1 ;
|
||||
}
|
||||
objects_rot->sync_live(0,1) ;
|
||||
}
|
||||
if ( button == GLUT_RIGHT_BUTTON && button_state == GLUT_DOWN)
|
||||
{
|
||||
}
|
||||
break ;
|
||||
|
||||
// zoom
|
||||
case 1 :
|
||||
if ( button == GLUT_LEFT_BUTTON && button_state == GLUT_DOWN )
|
||||
{
|
||||
mouse_zm.init_live() ;
|
||||
mouse_zm.glui = glui_bottom ;
|
||||
mouse_zm.mouse_down_handler(x,y) ;
|
||||
mouse_zm.glui = NULL ;
|
||||
|
||||
}
|
||||
if ( button_state != GLUT_DOWN )
|
||||
{
|
||||
mouse_zm.glui = glui_bottom ;
|
||||
mouse_zm.mouse_up_handler(x,y,1) ;
|
||||
mouse_zm.glui = NULL ;
|
||||
motion_type = -1 ;
|
||||
}
|
||||
objects_zm->sync_live(0,1) ;
|
||||
break ;
|
||||
|
||||
// translation
|
||||
case 2 :
|
||||
if ( button == GLUT_LEFT_BUTTON && button_state == GLUT_DOWN )
|
||||
{
|
||||
mouse_mv.init_live() ;
|
||||
mouse_mv.glui = glui_bottom ;
|
||||
mouse_mv.mouse_down_handler(x,y) ;
|
||||
mouse_mv.glui = NULL ;
|
||||
}
|
||||
if ( button_state != GLUT_DOWN )
|
||||
{
|
||||
mouse_mv.glui = glui_bottom ;
|
||||
mouse_mv.mouse_up_handler(x,y,1) ;
|
||||
mouse_mv.glui = NULL ;
|
||||
motion_type = -1 ;
|
||||
}
|
||||
objects_mv->sync_live(0,1) ;
|
||||
break ;
|
||||
|
||||
// no movement
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
ncalls = 0 ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// keyboard
|
||||
void keyboard(unsigned char key, int x, int y)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case 's':
|
||||
export_png();
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
export_movie = !export_movie;
|
||||
break;
|
||||
|
||||
case 'r' :
|
||||
if( auto_rotate == -1 ) auto_rotate = 0 ;
|
||||
else auto_rotate = -1 ;
|
||||
break ;
|
||||
|
||||
case 'R' :
|
||||
if( auto_rotate == +1 ) auto_rotate = 0 ;
|
||||
else auto_rotate = +1 ;
|
||||
break ;
|
||||
|
||||
case 'D' :
|
||||
if( auto_translate_d == -1 ) auto_translate_d = 0 ;
|
||||
else auto_translate_d = -1 ;
|
||||
break ;
|
||||
|
||||
case 'd' :
|
||||
if( auto_translate_d == +1 ) auto_translate_d = 0 ;
|
||||
else auto_translate_d = +1 ;
|
||||
break ;
|
||||
|
||||
case 'X' :
|
||||
if( auto_translate_x == -1 ) auto_translate_x = 0 ;
|
||||
else auto_translate_x = -1 ;
|
||||
break ;
|
||||
|
||||
case 'x' :
|
||||
if( auto_translate_x == +1 ) auto_translate_x = 0 ;
|
||||
else auto_translate_x = +1 ;
|
||||
break ;
|
||||
|
||||
case 'Y' :
|
||||
if( auto_translate_y == -1 ) auto_translate_y = 0 ;
|
||||
else auto_translate_y = -1 ;
|
||||
break ;
|
||||
|
||||
case 'y' :
|
||||
if( auto_translate_y == +1 ) auto_translate_y = 0 ;
|
||||
else auto_translate_y = +1 ;
|
||||
break ;
|
||||
|
||||
case 'Z' :
|
||||
if( auto_zoom == -1 ) auto_zoom = 0 ;
|
||||
else auto_zoom = -1 ;
|
||||
break ;
|
||||
|
||||
case 'z' :
|
||||
if( auto_zoom == +1 ) auto_zoom = 0 ;
|
||||
else auto_zoom = +1 ;
|
||||
break ;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// motion
|
||||
void motion(int x, int y )
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
mouse_x = x ;
|
||||
mouse_y = y ;
|
||||
|
||||
switch( motion_type )
|
||||
{
|
||||
// rotation
|
||||
case 0 :
|
||||
mouse_rot.glui = glui_bottom ;
|
||||
mouse_rot.iaction_mouse_held_down_handler(x,y,1);
|
||||
mouse_rot.glui = NULL ;
|
||||
if( ++ncalls > 10 ) { objects_rot->sync_live(0,1) ; ncalls = 0 ; }
|
||||
break ;
|
||||
|
||||
// zoom
|
||||
case 1 :
|
||||
mouse_zm.glui = glui_bottom ;
|
||||
mouse_zm.iaction_mouse_held_down_handler(x,y,1);
|
||||
mouse_zm.glui = NULL ;
|
||||
|
||||
if( ++ncalls > 10 ) { objects_zm->sync_live(0,1) ; ncalls = 0 ; }
|
||||
break ;
|
||||
|
||||
// translation
|
||||
case 2 :
|
||||
mouse_mv.glui = glui_bottom ;
|
||||
mouse_mv.iaction_mouse_held_down_handler(x,y,1);
|
||||
mouse_mv.glui = NULL ;
|
||||
|
||||
if( ++ncalls > 10 ) { objects_mv->sync_live(0,1) ; ncalls = 0 ; }
|
||||
break ;
|
||||
|
||||
// no movement
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
::glutPostRedisplay() ;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
Binary file not shown.
Reference in New Issue
Block a user