00001 #ifndef COMPRESSED_MESH_HPP
00002 #define COMPRESSED_MESH_HPP
00003
00008
00009 #include <inttypes.h>
00010 #include <limits>
00011 #include <algorithm>
00012
00013 #include <omp.h>
00014
00015 #include "coucal.h"
00016 #include "uth_log.h"
00017
00018 namespace fpcm
00019 {
00020 namespace CompressedMesh
00021 {
00022
00023 typedef int32_t PTID;
00024 typedef PTID GID;
00025
00026 inline double point_accuracy() { return 10e-3; }
00027
00028 struct CoordMesh{
00029 double origin[3],d[3];
00030 PTID binary_oper[3];
00031 int8_t in_line_digits,line_digits,layer_digits,shift;
00032
00033
00034 static const PTID digits = std::numeric_limits<PTID>::digits;
00035
00036 int createMeshBase(const double* const real_points, const int n_points)
00037 {
00038
00039 mf_check_mem(real_points);
00040
00041 {
00042 double min[3]={std::numeric_limits<double>::max()},
00043 max[3]={std::numeric_limits<double>::min()};
00044 for(int i=0; i < n_points; ++i) {
00045 for(int j=0;j<3;++j) {
00046 if(min[j] > real_points[3*i+j]) {
00047 min[j] = real_points[3*i+j];
00048 }
00049 else if(max[j] < real_points[3*i+j]) {
00050 max[j] = real_points[3*i+j];
00051 }
00052 }
00053 }
00054
00055
00056 const double span[3] = { max[0] - min[0], max[1] - min[1], max[2] - min[2] } ;
00057 const int smallest_dim = std::min_element(span,span+3) - span;
00058
00059 int ratio[3] = { int(span[0]/span[smallest_dim]), int(span[1]/span[smallest_dim]), int(span[2]/span[smallest_dim]) };
00060 int ratio_sum = ratio[0]+ratio[1]+ratio[2];
00061
00062 mf_log_info("Compressed mesh ratios %d : %d : %d",ratio[0],ratio[1],ratio[2]);
00063
00064
00065 const int min_digits=6;
00066 int n_bits = std::numeric_limits<PTID>::digits-(3*min_digits);
00067
00068
00069
00070
00071
00072
00073
00074 double avg = double(n_bits)/double(ratio_sum);
00075
00076 mf_log_info("Avg= %lf",avg);
00077
00078 for(int i=0; i<3 ;++i) {
00079 ratio[i] = min_digits + double(ratio[i])*avg;
00080
00081 }
00082
00083 ratio_sum = ratio[0]+ratio[1]+ratio[2];
00084 assert( ratio_sum <= std::numeric_limits<PTID>::digits );
00085
00086 while(ratio_sum < std::numeric_limits<PTID>::digits) {
00087 ++ratio[smallest_dim];
00088 ++ratio_sum;
00089 }
00090
00091 for(int i=0; i < 3; ++i) {
00092 origin[i] = min[i];
00093 d[i] = span[i] / ((1<<ratio[i])-1);
00094 }
00095
00096 setLengths(ratio[0],ratio[1]);
00097
00098
00099 mf_log_info("Min= %lf, %lf, %lf",min[0],min[1],min[2]);
00100 mf_log_info("Max= %lf, %lf, %lf",max[0],max[1],max[2]);
00101 mf_log_info("Span= %lf, %lf, %lf",span[0],span[1],span[2]);
00102 mf_log_info("Smallest dim=%d",smallest_dim);
00103 mf_log_info("Compressed mesh ratios %d : %d : %d",ratio[0],ratio[1],ratio[2]);
00104 mf_log_info("pt per line=%d, lines=%d, layers=%d",in_line_digits,line_digits,layer_digits);
00105 mf_log_info("binary_oper[3] = %d, %d, %d",binary_oper[0],binary_oper[1],binary_oper[2]);
00106 mf_log_info("d[3]=%lf, %lf, %lf",d[0], d[1], d[2]);
00107
00108 mf_check(min[0] == origin[0], "Error in encoding processor!");
00109 mf_check(min[1] == origin[1], "Error in encoding processor!");
00110 mf_check(min[2] == origin[2], "Error in encoding processor!");
00111 mf_check(max[0] == origin[0]+d[0]*((1<<ratio[0])-1), "Error in encoding processor!");
00112 mf_check(max[1] == origin[1]+d[1]*((1<<ratio[1])-1), "Error in encoding processor!");
00113 mf_check(max[2] == origin[2]+d[2]*((1<<ratio[2])-1), "Error in encoding processor!");
00114 }
00115 }
00116
00117 void setLengths(int lineLengthAs2Pow, int layerLengthAs2Pow)
00118 {
00119 in_line_digits = lineLengthAs2Pow;
00120 line_digits = layerLengthAs2Pow;
00121 layer_digits = digits - (lineLengthAs2Pow+layerLengthAs2Pow);
00122 shift = in_line_digits + line_digits;
00123
00124 binary_oper[0]=0;
00125 binary_oper[1]=0;
00126 binary_oper[2]=0;
00127
00128 for(int i=0;i<in_line_digits; ++i) {
00129 binary_oper[0]|=(1<<i);
00130 }
00131
00132 for(int i=0;i<line_digits; ++i) {
00133 binary_oper[1]|=(1<<i);
00134 }
00135 binary_oper[1] = binary_oper[1] << lineLengthAs2Pow;
00136
00137 for(int i=0;i<layer_digits; ++i) {
00138 binary_oper[2]|=(1<<i);
00139 }
00140 binary_oper[2] = (binary_oper[2] << (lineLengthAs2Pow+layerLengthAs2Pow));
00141 }
00142
00143 inline void getPointCoords(const PTID pt, double* coords) const {
00144 coords[0]=origin[0] + d[0]*(pt & (binary_oper[0])) ;
00145 coords[1]=origin[1] + d[1]*((pt & (binary_oper[1]))>>in_line_digits) ;
00146 coords[2]=origin[2] + d[2]*(pt >> (in_line_digits+line_digits));
00147
00148 }
00149
00150 inline PTID encode(const double* const coords) const {
00151
00152 assert(PTID((coords[0]-origin[0]) / d[0]) < (1<<in_line_digits));
00153 assert(PTID((coords[1]-origin[1]) / d[2])>>in_line_digits < (1<<line_digits));
00154 assert(PTID((coords[2]-origin[2]) / d[2])>>(in_line_digits+line_digits) < (1<<layer_digits));
00155
00156 return PTID((coords[0]-origin[0]) / d[0])
00157 | (PTID((coords[1]-origin[1]) / d[1]) << in_line_digits)
00158 | (PTID((coords[2]-origin[2]) / d[2]) << (line_digits+in_line_digits));
00159 }
00160
00161 inline PTID middle(const PTID p1, const PTID p2) const {
00162 return PTID((p1 & (binary_oper[0]))/2 + (p2 & (binary_oper[0]))/2)
00163 + PTID((p1 & (binary_oper[1]))/2 + (p2 & (binary_oper[1]))/2)
00164 + PTID((p1 & (binary_oper[2]))/2 + (p2 & (binary_oper[2]))/2);
00165 }
00166
00167 inline double X(const PTID pt) const {
00168 return origin[0] + d[0]*double(pt & binary_oper[0]);
00169 }
00170
00171 inline double Y(const PTID pt) const {
00172 return origin[1] + d[1]*((pt>>in_line_digits) & (binary_oper[0]));
00173 }
00174
00175 inline double Z(const PTID pt) const {
00176 return origin[2] + d[2]*(pt >> shift);
00177 }
00178
00179 };
00180
00181 int EncodingProcessor(const double* const real_points, const int n_points, __restrict__ PTID * encoded_points, const CoordMesh& out_mesh);
00182
00183 int TransformProcessor(const PTID *points_in, const int n_size, const CoordMesh& from, const CoordMesh& to, PTID * points_out );
00184
00185 }
00186 }
00187 #endif