00001 #include "trafu_data.h"
00002 #include "trafupoint.h"
00003
00004 #include <algorithm>
00005 #include <fstream>
00006 #include <sstream>
00007
00008 TraFuData::TraFuData(const char *tfd_filename)
00009 {
00010 if(tfd_filename)
00011 {
00012 this->load_file(tfd_filename);
00013 }else
00014 {
00015 Init();
00016 }
00017 }
00018
00019 void TraFuData::Init()
00020 {
00021 this->m_mapping_points.clear();
00022 this->m_mapping_points.push_back(Mapping_point_t(0, 0, 0, 0, 0, TFP_START));
00023 this->m_mapping_points.push_back(Mapping_point_t(1, 1, 255, 255, 255, TFP_END));
00024 }
00025
00026 Mapping_point_t TraFuData::mapDensity(float density) const
00027 {
00028 Mapping_point_t calc_point;
00029 Mapping_point_iterator_const_t first, second;
00030
00031 second = first = std::upper_bound(this->m_mapping_points.begin(),
00032 this->m_mapping_points.end(),
00033 calc_point);
00034
00035 if(second != this->m_mapping_points.end())
00036 {
00037 first--;
00038
00039 Mapping_point_t range = *second - *first;
00040 float current = (density - first->m_density) / range.m_density;
00041
00042 Mapping_point_t step = range * current;
00043
00044 calc_point = (*first) + range * current;
00045 }else
00046 {
00047 calc_point = this->m_mapping_points.back();
00048 }
00049
00050 return calc_point;
00051 }
00052
00054 struct PointChange_s
00055 {
00056 float density;
00057 float opacity;
00058
00061 float red;
00062 float green;
00063 float blue;
00065
00067 PointChange_s(float n_density, float n_opacity, float n_red, float n_green, float n_blue)
00068 : density(n_density)
00069 , opacity(n_opacity)
00070 , red(n_red)
00071 , green(n_green)
00072 , blue(n_blue)
00073 {
00074 }
00075
00077 friend Mapping_point_t operator *(const PointChange_s &change, const int scalar)
00078 {
00079 return Mapping_point_t(change.density * scalar,
00080 change.opacity * scalar,
00081 change.red * scalar,
00082 change.green * scalar,
00083 change.blue * scalar);
00084 }
00085 };
00086
00087 void TraFuData::createDensityVectorPart(Mapping_point_vector_t &vec,
00088 int first_element,
00089 int number_of_elements,
00090 const Mapping_point_iterator_const_t &lower,
00091 const Mapping_point_iterator_const_t &upper) const
00092 {
00093 Mapping_point_t range = *upper - *lower;
00094 PointChange_s change(range.m_density / number_of_elements,
00095 range.m_opacity / number_of_elements,
00096 static_cast<float>(range.m_colour.red) / number_of_elements,
00097 static_cast<float>(range.m_colour.green) / number_of_elements,
00098 static_cast<float>(range.m_colour.blue) / number_of_elements);
00099
00100 vec[first_element] = *lower;
00101 for(int i = 0; i < number_of_elements; i++)
00102 {
00103 vec[first_element + i] = *lower + (change * i);
00104 }
00105 }
00106
00107 Mapping_point_vector_t TraFuData::createDensityVector(int number_of_elements) const
00108 {
00109 Mapping_point_vector_t vec(number_of_elements);
00110 Mapping_point_iterator_const_t first = m_mapping_points.begin();
00111 Mapping_point_iterator_const_t second = m_mapping_points.begin();
00112 ++second;
00113
00114 int free_elements = number_of_elements - 1;
00115 int current_elements = 0;
00116 float free_density = 1;
00117 float density_range = 0;
00118 int last_element = 0;
00119
00120 while(second != m_mapping_points.end())
00121 {
00122 density_range = (second->m_density - first->m_density);
00123 current_elements = free_elements * (density_range / free_density);
00124 createDensityVectorPart(vec, last_element, current_elements, first, second);
00125 last_element += current_elements;
00126 free_density -= density_range;
00127 free_elements -= current_elements;
00128 first = second++;
00129 }
00130
00131 vec[number_of_elements - 1] = *first;
00132
00133 return vec;
00134 }
00135
00136 void TraFuData::load_file(const char *tfd_filename)
00137 {
00138 std::ifstream in(tfd_filename, std::ios::in | std::ios::binary);
00139 in.exceptions(std::ios::failbit | std::ios::badbit);
00140
00141 int size = 0;
00142 Mapping_point_t *new_element = new Mapping_point_t();
00143
00144 this->m_mapping_points.clear();
00145
00146 try
00147 {
00148 in.read((char*)&size, sizeof(int));
00149
00150 while(1)
00151 {
00152 in.read(reinterpret_cast<char*>(new_element), sizeof(Mapping_point_t));
00153 this->m_mapping_points.push_back(*new_element);
00154 }
00155 }catch(...)
00156 {
00157
00158 }
00159
00160 delete new_element;
00161 }
00162
00163 void TraFuData::save_file(const char *tfd_filename)
00164 {
00165 std::string filename(tfd_filename);
00166 if(std::string::npos == filename.rfind("."))
00167 {
00168 filename.append(std::string(".tf"));
00169 }
00170
00171 std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary);
00172 out.exceptions(std::ios::failbit | std::ios::badbit);
00173
00174 int size = (int)this->m_mapping_points.size();
00175
00176 out.write((char*)&size, sizeof(int));
00177
00178 for(Mapping_point_iterator_t iterPoint = this->m_mapping_points.begin();
00179 iterPoint != this->m_mapping_points.end();
00180 iterPoint++)
00181 {
00182 out.write(reinterpret_cast<char*>(&(*iterPoint)), sizeof(*iterPoint));
00183 }
00184 }