Commit f1402849e5be2c2d9ce26a0d7f4c74b5748b8a74

Authored by dmayerich
0 parents

renewed commit

Showing 101 changed files with 25830 additions and 0 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 101 files are displayed.

CHECK_OPENGL_ERROR.h 0 → 100755
  1 +++ a/CHECK_OPENGL_ERROR.h
  1 +#ifndef RTS_OPENGL_ERROR
  2 +#define RTS_OPENGL_ERROR
  3 +
  4 +#include <stdio.h>
  5 +#include <GL/gl.h>
  6 +#include <GL/glu.h>
  7 +
  8 +#define CHECK_OPENGL_ERROR \
  9 +{ GLenum error; \
  10 + while ( (error = glGetError()) != GL_NO_ERROR) { \
  11 + printf( "OpenGL ERROR: %s\nCHECK POINT: %s (line %d)\n", gluErrorString(error), __FILE__, __LINE__ ); \
  12 + } \
  13 +}
  14 +
  15 +#endif
0 16 \ No newline at end of file
... ...
PerformanceDataTemplate.h 0 → 100755
  1 +++ a/PerformanceDataTemplate.h
  1 +// add the following to a cpp file:
  2 +// PerformanceData PD;
  3 +
  4 +
  5 +#pragma once
  6 +#include <ostream>
  7 +using namespace std;
  8 +
  9 +enum PerformanceDataType
  10 +{
  11 + PD_DISPLAY=0,
  12 + PD_SPS,
  13 + PD_UNUSED0,
  14 +
  15 + //my stuff
  16 + SIMULATE_SPECTRUM,
  17 + SIMULATE_GPU,
  18 + KRAMERS_KRONIG,
  19 +
  20 +
  21 +
  22 + //end my stuff
  23 + PERFORMANCE_DATA_TYPE_COUNT
  24 +};
  25 +
  26 +static char PDTypeNames[][255] = {
  27 + "Display ",
  28 + "Simulation Total ",
  29 + " ----------------- ",
  30 + //my stuff
  31 + "Simulate Spectrum ",
  32 + " GPU Portion ",
  33 + "Kramers-Kronig ",
  34 +
  35 + //end my stuff
  36 +
  37 +};
  38 +#ifdef WIN32
  39 +#include <stdio.h>
  40 +#include <windows.h>
  41 +#include <float.h>
  42 +
  43 +#include <iostream>
  44 +#include <iomanip>
  45 +
  46 +//-------------------------------------------------------------------------------
  47 +
  48 +class PerformanceData
  49 +{
  50 +public:
  51 + PerformanceData() { ClearAll(); QueryPerformanceFrequency(&cps); }
  52 + ~PerformanceData(){}
  53 +
  54 + void ClearAll()
  55 + {
  56 + for ( int i=0; i<PERFORMANCE_DATA_TYPE_COUNT; i++ ) {
  57 + for ( int j=0; j<256; j++ ) times[i][j] = 0;
  58 + pos[i] = 0;
  59 + minTime[i] = 0xFFFFFFFF;
  60 + maxTime[i] = 0;
  61 + totalTime[i] = 0;
  62 + dataReady[i] = false;
  63 + }
  64 + }
  65 +
  66 + void StartTimer( int type ) { QueryPerformanceCounter( &startTime[type] );}
  67 + void EndTimer( int type ) {
  68 + LARGE_INTEGER endTime;
  69 + QueryPerformanceCounter( &endTime );
  70 + double t = (double)(endTime.QuadPart - startTime[type].QuadPart);
  71 + //unsigned int t = GetTickCount() - startTime[type];
  72 + if ( t < minTime[type] ) minTime[type] = t;
  73 + if ( t > maxTime[type] ) maxTime[type] = t;
  74 + totalTime[type] -= times[type][ pos[type] ];
  75 + times[type][ pos[type] ] = t;
  76 + totalTime[type] += t;
  77 + pos[type]++;
  78 + if ( pos[type] == 0 ) dataReady[type] = true;
  79 + }
  80 +
  81 + void PrintResult( ostream &os,int i=PERFORMANCE_DATA_TYPE_COUNT)
  82 + {
  83 + os.setf(ios::fixed);
  84 + if ((i<PERFORMANCE_DATA_TYPE_COUNT)&&(i>=0)){
  85 + double a = GetAvrgTime(i);
  86 + if ( a )
  87 + os<< PDTypeNames[i]<<" : avrg="<<setw(8)<<setprecision(3)<<a<<"\tmin="<<setw(8)<<setprecision(3)<< GetMinTime(i) <<"\tmax="<<setw(8)<<setprecision(3)<< GetMaxTime(i) <<endl ;
  88 + else
  89 + os<< PDTypeNames[i]<<" : avrg= -----\tmin= -----\tmax= -----"<<endl;
  90 + }
  91 + }
  92 +
  93 + void PrintResults( ostream &os)
  94 + {
  95 + for ( int i=0; i<PERFORMANCE_DATA_TYPE_COUNT; i++ )
  96 + PrintResult(os,i);
  97 + }
  98 +
  99 + double GetLastTime( int type ) { return times[type][pos[type]]; }
  100 + double GetAvrgTime( int type ) { double a = 1000.0 * totalTime[type] / (float)cps.QuadPart / ( (dataReady[type]) ? 256.0 : (double)pos[type] ); return (_finite(a))? a:0; }
  101 + double GetMinTime( int type ) { return 1000.0 * minTime[type] / (float)cps.LowPart; }
  102 + double GetMaxTime( int type ) { return 1000.0 * maxTime[type] / (float)cps.LowPart; }
  103 +
  104 +private:
  105 + double times[PERFORMANCE_DATA_TYPE_COUNT][256];
  106 + unsigned char pos[PERFORMANCE_DATA_TYPE_COUNT];
  107 + LARGE_INTEGER startTime[PERFORMANCE_DATA_TYPE_COUNT];
  108 + double minTime[ PERFORMANCE_DATA_TYPE_COUNT ];
  109 + double maxTime[ PERFORMANCE_DATA_TYPE_COUNT ];
  110 + double totalTime[ PERFORMANCE_DATA_TYPE_COUNT ];
  111 + bool dataReady[ PERFORMANCE_DATA_TYPE_COUNT ];
  112 + LARGE_INTEGER cps;
  113 +};
  114 +
  115 +//-------------------------------------------------------------------------------
  116 +#else
  117 +
  118 +class PerformanceData{
  119 +public:
  120 + PerformanceData() {;};
  121 + ~PerformanceData(){;};
  122 + void ClearAll(){;};
  123 + void StartTimer( int type ) {;};
  124 + void EndTimer( int type ) {;};
  125 + void PrintResults( ostream &os){;};
  126 + void PrintResult( ostream &os, int i=PERFORMANCE_DATA_TYPE_COUNT){;};
  127 + double GetLastTime( int type ) { return 0.0; };
  128 + double GetAvrgTime( int type ) { return 0.0; };
  129 + double GetMinTime( int type ) { return 0.0; };
  130 + double GetMaxTime( int type ) { return 0.0; };
  131 +};
  132 +
  133 +#endif
  134 +//-------------------------------------------------------------------------------
  135 +
  136 +extern PerformanceData PD;
  137 +
  138 +//-------------------------------------------------------------------------------
... ...
cudaHandleError.h 0 → 100755
  1 +++ a/cudaHandleError.h
  1 +#include <stdio.h>
  2 +#include "cuda_runtime.h"
  3 +#include "device_launch_parameters.h"
  4 +
  5 +#ifndef CUDA_HANDLE_ERROR_H
  6 +#define CUDA_HANDLE_ERROR_H
  7 +
  8 +//handle error macro
  9 +static void HandleError( cudaError_t err, const char *file, int line ) {
  10 + if (err != cudaSuccess) {
  11 + FILE* outfile = fopen("cudaErrorLog.txt", "w");
  12 + fprintf(outfile, "%s in %s at line %d\n", cudaGetErrorString( err ), file, line );
  13 + fclose(outfile);
  14 + exit( EXIT_FAILURE );
  15 + printf("%s in %s at line %d\n", cudaGetErrorString( err ), file, line );
  16 + }
  17 +}
  18 +#define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))
  19 +
  20 +static cudaEvent_t tStartEvent;
  21 +static cudaEvent_t tStopEvent;
  22 +static void gpuStartTimer()
  23 +{
  24 + //set up timing events
  25 + cudaEventCreate(&tStartEvent);
  26 + cudaEventCreate(&tStopEvent);
  27 + cudaEventRecord(tStartEvent, 0);
  28 +}
  29 +
  30 +static float gpuStopTimer()
  31 +{
  32 + cudaEventRecord(tStopEvent, 0);
  33 + cudaEventSynchronize(tStopEvent);
  34 + float elapsedTime;
  35 + cudaEventElapsedTime(&elapsedTime, tStartEvent, tStopEvent);
  36 + cudaEventDestroy(tStartEvent);
  37 + cudaEventDestroy(tStopEvent);
  38 + return elapsedTime;
  39 +}
  40 +
  41 +#endif
... ...
cuda_callable.h 0 → 100644
  1 +++ a/cuda_callable.h
  1 +#ifndef CUDA_CALLABLE
  2 +
  3 +//define the CUDA_CALLABLE macro (will prefix all members)
  4 +#ifdef __CUDACC__
  5 +#define CUDA_CALLABLE __host__ __device__
  6 +#else
  7 +#define CUDA_CALLABLE
  8 +#endif
  9 +
  10 +#endif
... ...
objJedi.cpp 0 → 100755
  1 +++ a/objJedi.cpp
  1 +/*BUG NOTES
  2 +The standard function calls for inserting vertices don't work anymore. I've fixed points
  3 +but everything beyond that has to be updated.
  4 +*/
  5 +
  6 +#include "objJedi.h"
  7 +#include "rtsvector3D.h"
  8 +#include "rtspoint3D.h"
  9 +#include <string>
  10 +//variable for use in global functions
  11 +rtsOBJ g_OBJ;
  12 +
  13 +/********UTILITY METHODS*******************************/
  14 +void rtsOBJ::Scale(float scale_x, float scale_y, float scale_z)
  15 +{
  16 + vector<vertex_position>::iterator i;
  17 + for(i = v_list.begin(); i!= v_list.end(); i++)
  18 + {
  19 + (*i).x *= scale_x;
  20 + (*i).y *= scale_y;
  21 + (*i).z *= scale_z;
  22 + }
  23 +}
  24 +
  25 +void rtsOBJ::Translate(float trans_x, float trans_y, float trans_z)
  26 +{
  27 + vector<vertex_position>::iterator i;
  28 + for(i = v_list.begin(); i!= v_list.end(); i++)
  29 + {
  30 + (*i).x += trans_x;
  31 + (*i).y += trans_y;
  32 + (*i).z += trans_z;
  33 + }
  34 +
  35 +}
  36 +
  37 +float rtsOBJ::GetDistance(float x, float y, float z)
  38 +{
  39 + //gets the distance between the specified point and the nearest surface of the OBJ
  40 + //currently only works for lines
  41 +
  42 + //cout<<"Primitives: "<<primitives.size()<<endl;
  43 + int num_primitives = primitives.size();
  44 + point3D<double> p0, p1, p2;
  45 + double min_dist = 255;
  46 + double dist, numerator, denominator;
  47 + int p, l;
  48 + vector3D<double> v, w;
  49 + double c1, c2, b;
  50 + point3D<double> Pb;
  51 +
  52 + //for each line
  53 + for(l=0; l<num_primitives; l++)
  54 + {
  55 + if(primitives[l].type & OBJ_LINES)
  56 + {
  57 + //for each point
  58 + for(p = 1; p<primitives[l].p.size(); p++)
  59 + {
  60 +
  61 + vertex_position v1 = v_list[primitives[l].p[p-1].v];
  62 + vertex_position v2 = v_list[primitives[l].p[p].v];
  63 + p1.x = v1.x;
  64 + p1.y = v1.y;
  65 + p1.z = v1.z;
  66 + p2.x = v2.x;
  67 + p2.y = v2.y;
  68 + p2.z = v2.z;
  69 +
  70 + p0.x = x;
  71 + p0.y = y;
  72 + p0.z = z;
  73 +
  74 + v = p2 - p1;
  75 + w = p0 - p1;
  76 + if((c1 = w*v) <= 0)
  77 + dist = (p1 - p0).Length();
  78 + else if((c2 = v*v) <= c1)
  79 + dist = (p2 - p0).Length();
  80 + else
  81 + {
  82 + b = c1/c2;
  83 + Pb = p1 + b*v;
  84 + dist = (Pb - p0).Length();
  85 + }
  86 + if(dist < min_dist)
  87 + min_dist = dist;
  88 +
  89 +
  90 +
  91 + }
  92 + }
  93 + }
  94 + //cout<<"---------------------------------------------"<<endl;
  95 +
  96 + return min_dist;
  97 +
  98 +
  99 +}
  100 +
  101 +/********CLASS METHOD DEFINITIONS**********************/
  102 +//constructors
  103 +
  104 +//constructor
  105 +rtsOBJ::rtsOBJ()
  106 +{
  107 + g_CurrentMode = OBJ_NONE;
  108 + g_NumVertices = 0;
  109 + g_AttributeMask = 0x0;
  110 + g_AttributeResetMask = 0x0;
  111 + g_LatestVT = 0;
  112 + g_LatestVN = 0;
  113 +
  114 + m_bounds.min.x = m_bounds.min.y = m_bounds.min.z = 99999;
  115 + m_bounds.max.x = m_bounds.max.y = m_bounds.max.z = -99999;
  116 +
  117 + current_primitive_mask = 0x0;
  118 +}
  119 +
  120 +void rtsOBJ::CopyOBJ(const rtsOBJ& obj)
  121 +{
  122 + current_vt = obj.current_vt;
  123 + current_vn = obj.current_vn;
  124 + vt_changed = obj.vt_changed; //true if a new vt or vn was inserted since the last vertex
  125 + vn_changed = obj.vn_changed;
  126 + current_primitive_mask = obj.current_primitive_mask; //defines what coordinates are being used by the current primitive
  127 + //global variable storing the current render mode
  128 + g_CurrentMode = obj.g_CurrentMode;
  129 + //output file stream
  130 + //g_objFile = obj.g_objFile;
  131 + //obj file object
  132 + //objData g_OBJ;
  133 + //number of vertices since the last BEGIN
  134 + g_NumVertices = obj.g_NumVertices;
  135 + /*Attribute mask. This indicates what attributes are stored for each vertex.
  136 + Only a single mask applies to each vertex between objBegin() and objEnd(). The
  137 + attribute mask is flipped the first time an attribute is set but it is fixed after
  138 + the first vertex is passed.*/
  139 + g_AttributeMask = obj.g_AttributeMask;
  140 + /*Attribute reset mask. This indicates whether or not an attribute has been
  141 + reset since the last vertex was rendered. This applies to OBJ_VT and OBJ_VN*/
  142 + g_AttributeResetMask = obj.g_AttributeResetMask;
  143 + //latest texture coordinate sent
  144 + g_LatestVT = obj.g_LatestVT;
  145 + //latest vertex normal sent
  146 + g_LatestVN = obj.g_LatestVN;
  147 + m_bounds = obj.m_bounds;
  148 +
  149 +
  150 + v_list = obj.v_list;
  151 + vt_list = obj.vt_list;
  152 + vn_list = obj.vn_list;
  153 + primitives = obj.primitives;
  154 +
  155 + points = obj.points;
  156 + lines = obj.lines;
  157 + faces = obj.faces;
  158 +}
  159 +
  160 +//opens an obj file for rendering
  161 +OBJint rtsOBJ::objOpen(const char* filename)
  162 +{
  163 + g_objFile.open(filename);
  164 + return OBJ_OK;
  165 +}
  166 +
  167 +//close the obj file
  168 +OBJint rtsOBJ::objClose()
  169 +{
  170 + //TODO: write obj data
  171 + f_OutputVertices();
  172 + f_OutputTextureCoordinates();
  173 + f_OutputVertexNormals();
  174 + f_OutputPoints();
  175 + f_OutputLines();
  176 + f_OutputFaces();
  177 +
  178 + //close the file
  179 + g_objFile.close();
  180 +
  181 + //delete all of the data from the global object
  182 + f_ClearAll();
  183 + return OBJ_OK;
  184 +}
  185 +
  186 +OBJint rtsOBJ::objBegin(OBJint mode)
  187 +{
  188 + //make sure that we aren't currently rendering
  189 + if(g_CurrentMode != OBJ_NONE)
  190 + return OBJ_ERROR;
  191 + //make sure that the given mode is valid
  192 + if(mode < OBJ_POINTS || mode > OBJ_POLYGON)
  193 + return OBJ_ERROR;
  194 +
  195 + //otherwise, go ahead and set the mode
  196 + g_CurrentMode = mode;
  197 + //set the number of vertices to zero
  198 + g_NumVertices = 0;
  199 +
  200 + //reset the current state primitive state
  201 + current_primitive_mask = 0x0;
  202 +
  203 + return OBJ_OK;
  204 +}
  205 +
  206 +OBJint rtsOBJ::objEnd()
  207 +{
  208 + OBJint error = OBJ_OK;
  209 + //check to make sure the number of rendered vertices is valid for the current mode
  210 + switch(g_CurrentMode)
  211 + {
  212 + case OBJ_NONE:
  213 + //can't quit if we haven't started
  214 + error = OBJ_ERROR;
  215 + break;
  216 + case OBJ_LINES:
  217 + //if less than two vertices or an odd number of vertices
  218 + if(g_NumVertices < 2 || g_NumVertices%2 != 0)
  219 + {
  220 + //if there wasn't a vertex at all
  221 + if(g_NumVertices == 0)
  222 + error = OBJ_ERROR;
  223 + //if there was at least one vertex
  224 + else
  225 + {
  226 + //pop the last line off the list
  227 + primitives.pop_back();
  228 + lines.pop_back();
  229 + error = OBJ_ERROR;
  230 + }
  231 + }
  232 + break;
  233 + case OBJ_LINE_STRIP:
  234 + //if less than two vertices
  235 + if(g_NumVertices < 2)
  236 + {
  237 + //if there wasn't a vertex at all
  238 + if(g_NumVertices == 0)
  239 + error = OBJ_ERROR;
  240 + //if there was at least one vertex
  241 + else
  242 + {
  243 + //pop the last line off the list
  244 + primitives.pop_back();
  245 + lines.pop_back();
  246 + error = OBJ_ERROR;
  247 + }
  248 + }
  249 + break;
  250 + case OBJ_LINE_LOOP:
  251 + //if less than three vertices
  252 + if(g_NumVertices < 3)
  253 + {
  254 + //pop the last line off the list
  255 + primitives.pop_back();
  256 + lines.pop_back();
  257 + error = OBJ_ERROR;
  258 + }
  259 + //connect the first and last points
  260 + else
  261 + {
  262 + error = f_TerminateLineLoop();
  263 + }
  264 + break;
  265 + case OBJ_TRIANGLES:
  266 + //if less than three vertices or not a power of three
  267 + if(g_NumVertices < 3 || g_NumVertices%3 !=0)
  268 + {
  269 + primitives.pop_back();
  270 + faces.pop_back();
  271 + error = OBJ_ERROR;
  272 + }
  273 + break;
  274 + case OBJ_TRIANGLE_STRIP:
  275 + //if less than three vertices
  276 + if(g_NumVertices < 3)
  277 + {
  278 + primitives.pop_back();
  279 + faces.pop_back();
  280 + error = OBJ_ERROR;
  281 + }
  282 + break;
  283 + case OBJ_TRIANGLE_FAN:
  284 + //if less than three vertices
  285 + if(g_NumVertices < 3)
  286 + {
  287 + primitives.pop_back();
  288 + faces.pop_back();
  289 + error = OBJ_ERROR;
  290 + }
  291 + break;
  292 + case OBJ_QUADS:
  293 + if(g_NumVertices < 4 || g_NumVertices%4 != 0)
  294 + {
  295 + primitives.pop_back();
  296 + faces.pop_back();
  297 + error = OBJ_ERROR;
  298 + }
  299 + break;
  300 + case OBJ_QUAD_STRIP:
  301 + //has to be at least 4 vertices and an even number
  302 + if(g_NumVertices < 4 || g_NumVertices%2 != 0)
  303 + {
  304 + primitives.pop_back();
  305 + faces.pop_back();
  306 + error = OBJ_ERROR;
  307 + }
  308 + break;
  309 + case OBJ_POLYGON:
  310 + //has to be at least three vertices
  311 + if(g_NumVertices < 3)
  312 + {
  313 + primitives.pop_back();
  314 + faces.pop_back();
  315 + error = OBJ_ERROR;
  316 + }
  317 + break;
  318 + }
  319 +
  320 + //reset the attribute mask
  321 + g_AttributeMask = 0x0;
  322 + //just for closure, reset the attribute reset mask
  323 + g_AttributeResetMask = 0x0;
  324 + //stop rendering
  325 + g_CurrentMode = OBJ_NONE;
  326 + return error;
  327 +}
  328 +
  329 +OBJint rtsOBJ::f_InsertVertexf(float x, float y, float z, float w, unsigned char mask)
  330 +{
  331 + //make sure we're rendering
  332 + if(g_CurrentMode == OBJ_NONE)
  333 + return OBJ_ERROR;
  334 +
  335 + //insert the vertex into the vertex vector
  336 + vertex_position v;
  337 + v.x = x; v.y = y; v.z=z; v.w=w; v.mask = mask;
  338 + v_list.push_back(v);
  339 + f_AdjustExtents(v); //set the bounding box
  340 + //insert texture coordinate and normal if specified for this primitive
  341 + if((current_primitive_mask & OBJ_VT) && (vt_changed))
  342 + vt_list.push_back(current_vt);
  343 + if((current_primitive_mask & OBJ_VN) && (vn_changed))
  344 + vn_list.push_back(current_vn);
  345 +
  346 +
  347 + //increment the number of vertices inserted
  348 + g_NumVertices++;
  349 +
  350 + //handle each case of the vertex creation individually
  351 + OBJint error = OBJ_OK;
  352 + switch(g_CurrentMode)
  353 + {
  354 + case OBJ_POINTS:
  355 + error = f_InsertPointVertex();
  356 + break;
  357 + case OBJ_LINES:
  358 + error = f_InsertLineVertex();
  359 + break;
  360 + case OBJ_LINE_LOOP:
  361 + error = f_InsertLineLoopVertex();
  362 + break;
  363 + case OBJ_LINE_STRIP:
  364 + error = f_InsertLineStripVertex();
  365 + break;
  366 + case OBJ_TRIANGLES:
  367 + error = f_InsertTriangleVertex();
  368 + break;
  369 + case OBJ_TRIANGLE_STRIP:
  370 + error = f_InsertTriangleStripVertex();
  371 + break;
  372 + case OBJ_TRIANGLE_FAN:
  373 + error = f_InsertTriangleFanVertex();
  374 + break;
  375 + case OBJ_QUADS:
  376 + error = f_InsertQuadVertex();
  377 + break;
  378 + case OBJ_QUAD_STRIP:
  379 + error = f_InsertQuadStripVertex();
  380 + break;
  381 + case OBJ_POLYGON:
  382 + error = f_InsertPolygonVertex();
  383 + break;
  384 + }
  385 + //set the reset mask to zero
  386 + g_AttributeResetMask = 0x0;
  387 +
  388 + //set the attribute mask to include vertex position
  389 + g_AttributeMask = g_AttributeMask | OBJ_V;
  390 +
  391 + //return the result of the insertion
  392 + return error;
  393 +}
  394 +
  395 +OBJint rtsOBJ::objVertex1f(float x)
  396 +{
  397 + return f_InsertVertexf(x, 0.0, 0.0, 0.0, OBJ_V_X);
  398 +}
  399 +
  400 +OBJint rtsOBJ::objVertex2f(float x, float y)
  401 +{
  402 + return f_InsertVertexf(x, y, 0.0, 0.0, OBJ_V_X | OBJ_V_Y);
  403 +}
  404 +
  405 +OBJint rtsOBJ::objVertex3f(float x, float y, float z)
  406 +{
  407 + return f_InsertVertexf(x, y, z, 0.0, OBJ_V_X | OBJ_V_Y | OBJ_V_Z);
  408 +
  409 +}
  410 +
  411 +OBJint rtsOBJ::objVertex4f(float x, float y, float z, float w)
  412 +{
  413 + return f_InsertVertexf(x, y, z, w, OBJ_V_X | OBJ_V_Y | OBJ_V_Z | OBJ_V_W);
  414 +}
  415 +
  416 +OBJint rtsOBJ::objNormal3f(float i, float j, float k)
  417 +{
  418 + return f_InsertNormalf(i, j, k, OBJ_VN_I | OBJ_VN_J | OBJ_VN_K);
  419 +}
  420 +OBJint rtsOBJ::objNormal2f(float i, float j)
  421 +{
  422 + return f_InsertNormalf(i, j, 0.0, OBJ_VN_I | OBJ_VN_J);
  423 +}
  424 +
  425 +OBJint rtsOBJ::objNormal1f(float i)
  426 +{
  427 + return f_InsertNormalf(i, 0.0, 0.0, OBJ_VN_I);
  428 +}
  429 +
  430 +OBJint rtsOBJ::f_InsertNormalf(float i, float j, float k, unsigned char mask)
  431 +{
  432 + /*DEPRECATED
  433 + //if the mode is not rendering faces, there is an error
  434 + if(g_CurrentMode < OBJ_TRIANGLES)
  435 + return OBJ_ERROR;
  436 + //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written)
  437 + if(!(g_AttributeMask & OBJ_VN))
  438 + {
  439 + //if a vertex has been rendered, then we can't change the attribute, so exit
  440 + if(g_NumVertices > 0)
  441 + return OBJ_ERROR;
  442 + else
  443 + //otherwise, just set the attribute flag
  444 + g_AttributeMask = g_AttributeMask | OBJ_VN;
  445 + }
  446 +
  447 +
  448 + //insert the new normal into the normal list for the file
  449 + vertex_normal new_vn;
  450 + new_vn.i = i; new_vn.j = j; new_vn.k = k;
  451 + new_vn.mask = mask;
  452 + vn_list.push_back(new_vn);
  453 + */
  454 + current_vn.i = i; //set the current texture state to the given coordinates
  455 + current_vn.j = j;
  456 + current_vn.k = k;
  457 + current_vn.mask = mask; //set the mask as appropriate
  458 + vn_changed = true; //the texture coordinate state has changed
  459 + current_primitive_mask = current_primitive_mask | OBJ_VN; //the current primitive now uses texture coordinates (if it didn't previously)
  460 +
  461 + return OBJ_OK;
  462 +}
  463 +
  464 +OBJint rtsOBJ::objTexCoord3f(float u, float v, float w)
  465 +{
  466 + return f_InsertTexCoordf(u, v, w, OBJ_VT_U | OBJ_VT_V | OBJ_VT_W);
  467 +}
  468 +
  469 +OBJint rtsOBJ::objTexCoord2f(float u, float v)
  470 +{
  471 + return f_InsertTexCoordf(u, v, 0.0, OBJ_VT_U | OBJ_VT_V);
  472 +}
  473 +
  474 +OBJint rtsOBJ::objTexCoord1f(float u)
  475 +{
  476 + return f_InsertTexCoordf(u, 0.0, 0.0, OBJ_VT_U);
  477 +}
  478 +
  479 +OBJint rtsOBJ::f_InsertTexCoordf(float u, float v, float w, unsigned char mask)
  480 +{
  481 + /*
  482 + DEPRECATED
  483 + //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written)
  484 + if(!(g_AttributeMask & OBJ_VT))
  485 + {
  486 + //if a vertex has been rendered, then we can't change the attribute, so exit
  487 + if(g_NumVertices > 0)
  488 + return OBJ_ERROR;
  489 + else
  490 + //otherwise, just set the attribute flag
  491 + g_AttributeMask = g_AttributeMask | OBJ_VT;
  492 + }
  493 +
  494 + //insert the new texture coordinate into the list for the file
  495 + vertex_texture new_vt;
  496 + new_vt.u = u; new_vt.v = v; new_vt.w = w;
  497 + new_vt.mask = mask;
  498 + vt_list.push_back(new_vt);
  499 + */
  500 + current_vt.u = u; //set the current texture state to the given coordinates
  501 + current_vt.v = v;
  502 + current_vt.w = w;
  503 + current_vt.mask = mask; //set the mask as appropriate
  504 + vt_changed = true; //the texture coordinate state has changed
  505 + current_primitive_mask = current_primitive_mask | OBJ_VT; //the current primitive now uses texture coordinates (if it didn't previously)
  506 +
  507 + return OBJ_OK;
  508 +}
  509 +
  510 +
  511 +void rtsOBJ::insertVertexPosition(float x, float y, float z, unsigned char mask)
  512 +{
  513 + vertex_position v;
  514 + v.x = x;
  515 + v.y = y;
  516 + v.z = z;
  517 + v.mask = mask;
  518 +
  519 + v_list.push_back(v);
  520 +}
  521 +
  522 +void rtsOBJ::insertLine(unsigned int num_points, unsigned int* pointlist, unsigned int* normallist, unsigned int* texturelist)
  523 +{
  524 + //create the new primitive
  525 + primitive line;
  526 + line.type = OBJ_LINES;
  527 + line.mask = 0;
  528 +
  529 + //set the mask based on the passed data
  530 + if(pointlist != NULL)
  531 + line.mask = line.mask | OBJ_V;
  532 + if(normallist != NULL)
  533 + line.mask = line.mask | OBJ_VN;
  534 + if(texturelist != NULL)
  535 + line.mask = line.mask | OBJ_VT;
  536 +
  537 + //insert the line
  538 + int v;
  539 + vertex new_vert;
  540 + for(v=0; v<num_points; v++)
  541 + {
  542 + if(pointlist)
  543 + new_vert.v = pointlist[v];
  544 + if(normallist)
  545 + new_vert.vn = normallist[v];
  546 + if(texturelist)
  547 + new_vert.vt = texturelist[v];
  548 + line.p.push_back(new_vert);
  549 + }
  550 + //insert the new primitive into the list
  551 + primitives.push_back(line);
  552 +}
  553 +OBJint rtsOBJ::f_InsertPointVertex()
  554 +{
  555 + //insert the most recent point into the most recent point list
  556 + //if this is the first vertex, create the point list
  557 + if(g_NumVertices == 1)
  558 + {
  559 + primitive new_p; //create the new point
  560 + new_p.type = OBJ_POINTS;
  561 + new_p.mask = current_primitive_mask;
  562 + points.push_back(primitives.size()); //store the primitive id in the points list
  563 + primitives.push_back(new_p);
  564 + }
  565 +
  566 + //find the id of the most recent primitive
  567 + unsigned int p_index = primitives.size() - 1;
  568 + //find the index of the recent point
  569 + vertex p;
  570 + p.v = v_list.size() - 1;
  571 + //insert the indices for texture coordinates and normal if necessary
  572 + if(primitives[p_index].mask & OBJ_VT)
  573 + p.vt = vt_list.size() - 1;
  574 + if(primitives[p_index].mask & OBJ_VN)
  575 + p.vn = vn_list.size() - 1;
  576 +
  577 + //insert the vertex index into the primitive's point list
  578 + primitives[p_index].p.push_back(p);
  579 +
  580 + //push the point into the points list if it is not the only point in the primitive
  581 + if(g_NumVertices > 1)
  582 + points.push_back(p_index);
  583 +
  584 + return OBJ_OK;
  585 +}
  586 +
  587 +OBJint rtsOBJ::f_InsertLineVertex()
  588 +{
  589 + //if this is an odd vertex, create a new line
  590 + if(g_NumVertices%2 == 1)
  591 + {
  592 + f_CreateNewLine();
  593 + }
  594 +
  595 + f_InsertNewLineVertex();
  596 +
  597 + return OBJ_OK;
  598 +}
  599 +OBJint rtsOBJ::f_InsertLineLoopVertex()
  600 +{
  601 + //technically, this is the same as inserting a line strip vertex
  602 + f_InsertLineStripVertex();
  603 + return OBJ_OK;
  604 +}
  605 +
  606 +OBJint rtsOBJ::f_InsertLineStripVertex()
  607 +{
  608 + if(g_NumVertices == 1)
  609 + {
  610 + f_CreateNewLine();
  611 + }
  612 +
  613 + f_InsertNewLineVertex();
  614 +
  615 + return OBJ_OK;
  616 +}
  617 +
  618 +OBJint rtsOBJ::f_InsertTriangleVertex()
  619 +{
  620 + //if this is the first vertex in a triangle, create a new triangle
  621 + if(g_NumVertices%3 == 1)
  622 + {
  623 + f_CreateNewFace();
  624 + }
  625 +
  626 +
  627 + f_InsertNewFaceVertex();
  628 +
  629 + return OBJ_OK;
  630 +}
  631 +OBJint rtsOBJ::f_InsertTriangleStripVertex()
  632 +{
  633 + //in the special case of the first three vertices, just create a triangle
  634 + if(g_NumVertices <4)
  635 + f_InsertTriangleVertex();
  636 + else
  637 + {
  638 +
  639 + //create a new face for the new triangle
  640 + f_CreateNewFace();
  641 +
  642 + //insert the last two vertices from the previous triangle
  643 + f_InsertPreviousFaceVertex(1);
  644 + f_InsertPreviousFaceVertex(2);
  645 + //insert the new vertex
  646 + f_InsertNewFaceVertex();
  647 + }
  648 +
  649 + return OBJ_OK;
  650 +}
  651 +OBJint rtsOBJ::f_InsertTriangleFanVertex()
  652 +{
  653 + //in the special case of the first three vertices, just create a triangle
  654 + if(g_NumVertices <4)
  655 + f_InsertTriangleVertex();
  656 + else
  657 + {
  658 + //create a new face for the new triangle
  659 + f_CreateNewFace();
  660 + //add the previous vertices to the face
  661 + f_InsertFirstFaceVertex(0);
  662 + f_InsertPreviousFaceVertex(2);
  663 + //insert the current vertex
  664 + f_InsertNewFaceVertex();
  665 + }
  666 +
  667 + return OBJ_OK;
  668 +}
  669 +OBJint rtsOBJ::f_InsertQuadVertex()
  670 +{
  671 + //if this is the first vertex in a quad, create a new quad
  672 + if(g_NumVertices%4 == 1)
  673 + {
  674 + f_CreateNewFace();
  675 + }
  676 +
  677 + f_InsertNewFaceVertex();
  678 +
  679 + return OBJ_OK;
  680 +}
  681 +OBJint rtsOBJ::f_InsertQuadStripVertex()
  682 +{
  683 + //in the case of one of the first four vertices, just create a quad
  684 + if(g_NumVertices < 5)
  685 + f_InsertQuadVertex();
  686 + //if the vertex is odd (it will be the third vertex of a quad)
  687 + else if(g_NumVertices%2 == 1)
  688 + {
  689 + //create a new face for the new quad
  690 + f_CreateNewFace();
  691 + //add the previous two vertices
  692 + f_InsertPreviousFaceVertex(2);
  693 + f_InsertPreviousFaceVertex(3);
  694 + //add the current vertex
  695 + f_InsertNewFaceVertex();
  696 + }
  697 + else
  698 + {
  699 + //if this is the last vertex of the quad, just add it
  700 + f_InsertNewFaceVertex();
  701 +
  702 + }
  703 + return OBJ_OK;
  704 +}
  705 +OBJint rtsOBJ::f_InsertPolygonVertex()
  706 +{
  707 + //if this is the first vertex, create the quad
  708 + if(g_NumVertices == 1)
  709 + {
  710 + f_CreateNewFace();
  711 + }
  712 + f_InsertNewFaceVertex();
  713 +
  714 + return OBJ_OK;
  715 +}
  716 +
  717 +OBJint rtsOBJ::f_InsertPreviousFaceVertex(unsigned int v_index)
  718 +{
  719 + /*Finds the vertex used in the previous face with the given index and
  720 + inserts it into the current face. This limits the redundancy in the file
  721 + for re-used vertices (in strips and fans). This also transfers texture
  722 + and normal information.*/
  723 +
  724 + //find the index of the previous face
  725 + unsigned int prev_f_index = primitives.size() - 2;
  726 + //find the index of the current face
  727 + unsigned int f_index = prev_f_index +1;
  728 + //add the vertex information from the previous face to this face
  729 + primitives[f_index].p.push_back(primitives[prev_f_index].p[v_index]);
  730 +
  731 + return OBJ_OK;
  732 +}
  733 +
  734 +OBJint rtsOBJ::f_InsertFirstFaceVertex(unsigned int v_index)
  735 +{
  736 + /*Finds the vertex used in the first face (since the last objBegin())
  737 + with the given index and inserts it at the end of the current face.
  738 + This includes texture and normal information.*/
  739 +
  740 + //The result depends on the type of face being rendered
  741 + //So far, this function only applies to triangle fans
  742 + if(g_CurrentMode != OBJ_TRIANGLE_FAN)
  743 + return OBJ_ERROR;
  744 +
  745 + //calculate the number of faces that have been rendered
  746 + unsigned int num_faces = g_NumVertices - 2;
  747 + //find the index of the first face
  748 + unsigned int first_f_index = primitives.size() - num_faces;
  749 + //find the index of the current face
  750 + unsigned int f_index = primitives.size() - 1;
  751 + //transfer the vertex information from the first face to this one
  752 + primitives[f_index].p.push_back(primitives[first_f_index].p[v_index]);
  753 +
  754 +
  755 + return OBJ_OK;
  756 +}
  757 +
  758 +OBJint rtsOBJ::f_InsertNewFaceVertex()
  759 +{
  760 + /*This inserts information about the current vertex into the current face*/
  761 + //find the new vertex index
  762 + vertex p;
  763 + p.v = v_list.size() -1;
  764 + p.vt = vt_list.size() - 1;
  765 + p.vn = vn_list.size() -1;
  766 + //find the face index
  767 + unsigned int f_index = primitives.size() -1;
  768 + //INSERT VERTEX AND ATTRIBUTE DATA
  769 + //just add the vertex to the face
  770 + primitives[f_index].p.push_back(p);
  771 +
  772 + return OBJ_OK;
  773 +}
  774 +
  775 +OBJint rtsOBJ::f_InsertNewLineVertex()
  776 +{
  777 + /*This inserts information about the current vertex into the current line*/
  778 + //find the new vertex index
  779 + vertex p;
  780 + p.v = v_list.size() -1;
  781 + p.vt = vt_list.size() - 1;
  782 + //find the line index
  783 + unsigned int l_index = primitives.size() -1;
  784 +
  785 + //ADD VERTEX AND ATTRIBUTE INFORMATION
  786 + //add the vertex to the line
  787 + primitives[l_index].p.push_back(p);
  788 +
  789 + return OBJ_OK;
  790 +}
  791 +
  792 +OBJint rtsOBJ::f_CreateNewFace()
  793 +{
  794 + primitive new_f;
  795 + new_f.type = OBJ_FACE;
  796 + new_f.mask = g_AttributeMask;
  797 + faces.push_back(primitives.size());
  798 + primitives.push_back(new_f);
  799 +
  800 +
  801 + return OBJ_OK;
  802 +}
  803 +
  804 +OBJint rtsOBJ::f_CreateNewLine()
  805 +{
  806 + primitive new_l;
  807 + new_l.type = OBJ_LINES;
  808 + new_l.mask = g_AttributeMask;
  809 + lines.push_back(primitives.size());
  810 + primitives.push_back(new_l);
  811 +
  812 + return OBJ_OK;
  813 +}
  814 +
  815 +
  816 +OBJint rtsOBJ::f_TerminateLineLoop()
  817 +{
  818 + /*This function just terminates the line loop by setting the last vertex
  819 + to the first vertex.*/
  820 + if(g_CurrentMode != OBJ_LINE_LOOP)
  821 + return OBJ_ERROR;
  822 + //find the index for the current line
  823 + unsigned int l_index = lines.size() -1;
  824 + //insert the first vertex as the last vertex
  825 + primitives[l_index].p.push_back(primitives[l_index].p[0]);
  826 +
  827 + return OBJ_OK;
  828 +}
  829 +
  830 +void rtsOBJ::f_OutputVertices()
  831 +{
  832 + //get the number of vertices in the object
  833 + unsigned int v_num = v_list.size();
  834 + for(unsigned int i=0; i<v_num; i++)
  835 + {
  836 + g_objFile<<"v";
  837 + if(v_list[i].mask & OBJ_V_X)
  838 + g_objFile<<" "<<v_list[i].x;
  839 + if(v_list[i].mask & OBJ_V_Y)
  840 + g_objFile<<" "<<v_list[i].y;
  841 + if(v_list[i].mask & OBJ_V_Z)
  842 + g_objFile<<" "<<v_list[i].z;
  843 + if(v_list[i].mask & OBJ_V_W)
  844 + g_objFile<<" "<<v_list[i].w;
  845 + g_objFile<<endl;
  846 + }
  847 +
  848 +}
  849 +
  850 +void rtsOBJ::f_OutputVertexNormals()
  851 +{
  852 + //get the number of normals in the object
  853 + unsigned int vn_num = vn_list.size();
  854 + for(unsigned int i=0; i<vn_num; i++)
  855 + {
  856 + g_objFile<<"vn ";
  857 + if(vn_list[i].mask & OBJ_VN_I)
  858 + {
  859 + g_objFile<<vn_list[i].i;
  860 + if(vn_list[i].mask & OBJ_VN_J)
  861 + {
  862 + g_objFile<<" "<<vn_list[i].j;
  863 + if(vn_list[i].mask & OBJ_VN_K)
  864 + g_objFile<<" "<<vn_list[i].k;
  865 + }
  866 + }
  867 + g_objFile<<endl;
  868 + }
  869 +}
  870 +
  871 +void rtsOBJ::f_OutputTextureCoordinates()
  872 +{
  873 + //get the number of vertices in the object
  874 + unsigned int vt_num = vt_list.size();
  875 + for(unsigned int i=0; i<vt_num; i++)
  876 + {
  877 + g_objFile<<"vt ";
  878 + if(vt_list[i].mask & OBJ_VT_U)
  879 + {
  880 + g_objFile<<vt_list[i].u;
  881 + if(vt_list[i].mask & OBJ_VT_V)
  882 + {
  883 + g_objFile<<" "<<vt_list[i].v;
  884 + if(vt_list[i].mask & OBJ_VT_W)
  885 + g_objFile<<" "<<vt_list[i].w;
  886 + }
  887 + }
  888 + g_objFile<<endl;
  889 + }
  890 +}
  891 +
  892 +void rtsOBJ::f_OutputPoints()
  893 +{
  894 + /*
  895 + //get the number of point vectors
  896 + unsigned int p_num = points.size();
  897 +
  898 + //for each point vector, output the points
  899 + for(unsigned int i=0; i<p_num; i++)
  900 + {
  901 + g_objFile<<"p";
  902 + unsigned int v_num = points[i].p.size();
  903 + for(unsigned int j=0; j<v_num; j++)
  904 + {
  905 + g_objFile<<" "<<points[i].p[j].v+1;
  906 + }
  907 + g_objFile<<endl;
  908 + }
  909 + */
  910 +}
  911 +
  912 +void rtsOBJ::f_OutputLines()
  913 +{
  914 + /*
  915 + //get the number of line vectors
  916 + unsigned int l_num = lines.size();
  917 +
  918 + //for each line vector, output the associated points
  919 + for(unsigned int i=0; i<l_num; i++)
  920 + {
  921 + g_objFile<<"l";
  922 + unsigned int v_num = lines[i].p.size();
  923 + for(unsigned int j=0; j<v_num; j++)
  924 + {
  925 + g_objFile<<" "<<lines[i].p[j].v+1;
  926 + //output texture coordinate if there are any
  927 + if(lines[i].mask & OBJ_VT)
  928 + g_objFile<<"/"<<lines[i].p[j].vt+1;
  929 + }
  930 + g_objFile<<endl;
  931 + }
  932 + */
  933 +}
  934 +
  935 +void rtsOBJ::f_OutputFaces()
  936 +{
  937 + /*
  938 + //get the number of faces
  939 + unsigned int f_num = faces.size();
  940 +
  941 + //for each face, output the associated points
  942 + for(unsigned int i=0; i<f_num; i++)
  943 + {
  944 + g_objFile<<"f";
  945 + //get the number of face vertices
  946 + unsigned int v_num = faces[i].p.size();
  947 + for(unsigned int j=0; j<v_num; j++)
  948 + {
  949 + g_objFile<<" "<<faces[i].p[j].v+1;
  950 + //if there are texture coordinates
  951 + if(faces[i].mask & OBJ_VT)
  952 + g_objFile<<"/"<<faces[i].p[j].vt+1;
  953 + //if there is a normal
  954 + if(faces[i].mask & OBJ_VN)
  955 + {
  956 + //but no texture coordinates, put an extra slash
  957 + if(!(faces[i].mask & OBJ_VT))
  958 + g_objFile<<"/";
  959 + g_objFile<<"/"<<faces[i].p[j].vn+1;
  960 + }
  961 +
  962 + }
  963 + g_objFile<<endl;
  964 + }
  965 + */
  966 +}
  967 +
  968 +void rtsOBJ::f_ClearAll()
  969 +{
  970 + rtsOBJ();
  971 + //clear all data from the global obj function
  972 + faces.clear();
  973 + lines.clear();
  974 + points.clear();
  975 + v_list.clear();
  976 + vn_list.clear();
  977 + vt_list.clear();
  978 + primitives.clear();
  979 +}
  980 +
  981 +/*GLOBAL FUNCTION DEFINITIONS*/
  982 +//initialize the OBJ file
  983 +OBJint objOpen(char* filename)
  984 +{
  985 + return g_OBJ.objOpen(filename);
  986 +}
  987 +//close the obj file
  988 +OBJint objClose()
  989 +{
  990 + return g_OBJ.objClose();
  991 +}
  992 +
  993 +//start rendering in a certain mode
  994 +OBJint objBegin(OBJint mode)
  995 +{
  996 + return g_OBJ.objBegin(mode);
  997 +}
  998 +//stop the current rendering sequence
  999 +OBJint objEnd(void)
  1000 +{
  1001 + return g_OBJ.objEnd();
  1002 +}
  1003 +//render a vertex to the file
  1004 +OBJint objVertex1f(float x)
  1005 +{
  1006 + return g_OBJ.objVertex1f(x);
  1007 +}
  1008 +
  1009 +OBJint objVertex2f(float x, float y)
  1010 +{
  1011 + return g_OBJ.objVertex2f(x, y);
  1012 +}
  1013 +
  1014 +OBJint objVertex3f(float x, float y, float z)
  1015 +{
  1016 + return g_OBJ.objVertex3f(x, y, z);
  1017 +}
  1018 +
  1019 +OBJint objVertex4f(float x, float y, float z, float w)
  1020 +{
  1021 + return g_OBJ.objVertex4f(x, y, z, w);
  1022 +}
  1023 +//set a normal vector for a vertex
  1024 +OBJint objNormal3f(float i, float j, float k)
  1025 +{
  1026 + return g_OBJ.objNormal3f(i, j, k);
  1027 +}
  1028 +OBJint objNormal2f(float i, float j)
  1029 +{
  1030 + return g_OBJ.objNormal2f(i, j);
  1031 +}
  1032 +OBJint objNormal1f(float i)
  1033 +{
  1034 + return g_OBJ.objNormal1f(i);
  1035 +}
  1036 +//set a texture coordinate for a vertex
  1037 +OBJint objTexCoord3f(float u, float v, float w)
  1038 +{
  1039 + return g_OBJ.objTexCoord3f(u, v, w);
  1040 +}
  1041 +
  1042 +OBJint objTexCoord2f(float u, float v)
  1043 +{
  1044 + return g_OBJ.objTexCoord2f(u,v);
  1045 +}
  1046 +
  1047 +OBJint objTexCoord1f(float u)
  1048 +{
  1049 + return g_OBJ.objTexCoord1f(u);
  1050 +}
  1051 +
  1052 +OBJint rtsOBJ::f_ReadPosition(ifstream &infile)
  1053 +{
  1054 + vertex_position new_vertex;
  1055 + //get each coordinate
  1056 + infile>>new_vertex.x;
  1057 + new_vertex.mask = OBJ_V_X;
  1058 +
  1059 + if(infile.peek() == ' ')
  1060 + {
  1061 + infile>>new_vertex.y;
  1062 + new_vertex.mask = new_vertex.mask | OBJ_V_Y;
  1063 + }
  1064 + if(infile.peek() == ' ')
  1065 + {
  1066 + infile>>new_vertex.z;
  1067 + new_vertex.mask = new_vertex.mask | OBJ_V_Z;
  1068 + }
  1069 + if(infile.peek() == ' ')
  1070 + {
  1071 + infile>>new_vertex.w;
  1072 + new_vertex.mask = new_vertex.mask | OBJ_V_W;
  1073 + }
  1074 + int c = infile.peek();
  1075 + //ignore the rest of the line
  1076 + infile.ignore(1000, '\n');
  1077 + c = infile.peek();
  1078 +
  1079 + //cout<<"vertex read: "<<new_vertex.x<<","<<new_vertex.y<<","<<new_vertex.z<<","<<new_vertex.w<<endl;
  1080 + //insert the vertex into the list
  1081 + v_list.push_back(new_vertex);
  1082 +
  1083 + //adjust the extents of the model
  1084 + f_AdjustExtents(new_vertex);
  1085 +
  1086 + return OBJ_OK;
  1087 +}
  1088 +
  1089 +OBJint rtsOBJ::f_ReadNormal(ifstream &infile)
  1090 +{
  1091 + vertex_normal new_normal;
  1092 + infile>>new_normal.i;
  1093 + new_normal.mask = OBJ_VN_I;
  1094 + //get every other component
  1095 + if(infile.peek() == ' ')
  1096 + {
  1097 + infile>>new_normal.j;
  1098 + new_normal.mask = new_normal.mask | OBJ_VN_J;
  1099 + }
  1100 + if(infile.peek() == ' ')
  1101 + {
  1102 + infile>>new_normal.k;
  1103 + new_normal.mask = new_normal.mask | OBJ_VN_K;
  1104 + }
  1105 + //ignore the rest of the line
  1106 + infile.ignore(1000, '\n');
  1107 + //insert the normal
  1108 + vn_list.push_back(new_normal);
  1109 +
  1110 + return OBJ_OK;
  1111 +}
  1112 +
  1113 +OBJint rtsOBJ::f_ReadTexCoord(ifstream &infile)
  1114 +{
  1115 + vertex_texture new_texcoord;
  1116 + infile>>new_texcoord.u;
  1117 + new_texcoord.mask = OBJ_VT_U;
  1118 + //get every other component
  1119 + if(infile.peek() == ' ')
  1120 + {
  1121 + infile>>new_texcoord.v;
  1122 + new_texcoord.mask = new_texcoord.mask | OBJ_VT_V;
  1123 + }
  1124 + if(infile.peek() == ' ')
  1125 + {
  1126 + infile>>new_texcoord.w;
  1127 + new_texcoord.mask = new_texcoord.mask | OBJ_VT_W;
  1128 + }
  1129 +
  1130 + //ignore the rest of the line
  1131 + infile.ignore(1000, '\n');
  1132 + //insert the texture coordinate
  1133 + vt_list.push_back(new_texcoord);
  1134 +
  1135 + return OBJ_OK;
  1136 +
  1137 +}
  1138 +
  1139 +OBJint rtsOBJ::f_ReadVertex(ifstream &infile, vertex &new_point, unsigned char &mask)
  1140 +{
  1141 + //store the line vertex
  1142 + infile>>new_point.v;
  1143 + new_point.v--;
  1144 + mask = OBJ_V;
  1145 + //new_face.v.push_back(new_v - 1);
  1146 + if(infile.peek() == '/')
  1147 + {
  1148 + infile.get();
  1149 + //if there actually is a texcoord
  1150 + if(infile.peek() != '/')
  1151 + {
  1152 + infile>>new_point.vt; //get the index
  1153 + new_point.vt--;
  1154 + mask = mask | OBJ_VT; //update the mask
  1155 + //new_face.vt.push_back(new_vt - 1);
  1156 + }
  1157 + }
  1158 + //check for a normal
  1159 + if(infile.peek() == '/')
  1160 + {
  1161 + infile.get();
  1162 + infile>>new_point.vn; //get the index
  1163 + new_point.vn--;
  1164 + mask = mask | OBJ_VN; //update the mask
  1165 + }
  1166 +
  1167 + return OBJ_OK;
  1168 +}
  1169 +
  1170 +OBJint rtsOBJ::f_ReadPrimitive(ifstream &infile, primitive_type type)
  1171 +{
  1172 + //create a new point list
  1173 + primitive new_primitive;
  1174 + new_primitive.type = type;
  1175 + //until the end of the line
  1176 + while(infile.peek() != '\n')
  1177 + {
  1178 + //read each point
  1179 + if(infile.peek() == ' ')
  1180 + infile.get();
  1181 + else
  1182 + {
  1183 + vertex new_point;
  1184 + f_ReadVertex(infile, new_point, new_primitive.mask);
  1185 + new_primitive.p.push_back(new_point);
  1186 + }
  1187 + }
  1188 + //ignore the rest of the line
  1189 + infile.ignore(1000, '\n');
  1190 +
  1191 + //push the id of the primitive into the new list
  1192 + //:DEBUG:
  1193 + if(type == OBJ_POINTS)
  1194 + points.push_back(primitives.size());
  1195 + else if(type == OBJ_LINES)
  1196 + lines.push_back(primitives.size());
  1197 + else if(type == OBJ_FACE)
  1198 + faces.push_back(primitives.size());
  1199 +
  1200 + primitives.push_back(new_primitive); //push the new primitive
  1201 +
  1202 + return OBJ_OK;
  1203 +}
  1204 +
  1205 +
  1206 +OBJint rtsOBJ::f_AdjustExtents(vertex_position v)
  1207 +{
  1208 + if(v.x < m_bounds.min.x)
  1209 + m_bounds.min.x = v.x;
  1210 + if(v.y < m_bounds.min.y)
  1211 + m_bounds.min.y = v.y;
  1212 + if(v.z < m_bounds.min.z)
  1213 + m_bounds.min.z = v.z;
  1214 +
  1215 + if(v.x > m_bounds.max.x) m_bounds.max.x = v.x;
  1216 + if(v.y > m_bounds.max.y) m_bounds.max.y = v.y;
  1217 + if(v.z > m_bounds.max.z) m_bounds.max.z = v.z;
  1218 +
  1219 + return OBJ_OK;
  1220 +}
  1221 +
  1222 +OBJint rtsOBJ::f_LoadOBJ(const char* filename)
  1223 +{
  1224 + f_ClearAll();
  1225 + //open the file as a stream
  1226 + ifstream infile;
  1227 + infile.open(filename);
  1228 + if(!infile.is_open())
  1229 + return OBJ_ERROR;
  1230 +
  1231 + unsigned int vertices = 0;
  1232 +
  1233 + string token;
  1234 + infile>>token;
  1235 + while(!infile.eof())
  1236 + {
  1237 + //if the token is some vertex property
  1238 + if(token == "v")
  1239 + f_ReadPosition(infile);
  1240 + else if(token == "vn")
  1241 + f_ReadNormal(infile);
  1242 + else if(token == "vt")
  1243 + f_ReadTexCoord(infile);
  1244 + else if(token == "p")
  1245 + f_ReadPrimitive(infile, OBJ_POINTS);
  1246 + else if(token == "l")
  1247 + f_ReadPrimitive(infile, OBJ_LINES);
  1248 + else if(token == "f")
  1249 + f_ReadPrimitive(infile, OBJ_FACE);
  1250 + else
  1251 + infile.ignore(9999, '\n');
  1252 + //vertices++;
  1253 +
  1254 + infile>>token;
  1255 + }
  1256 +
  1257 +}
  1258 +
  1259 +OBJint rtsOBJ::f_LoadSWC(const char* filename)
  1260 +{
  1261 + f_ClearAll();
  1262 + //open the file as a stream
  1263 + ifstream infile;
  1264 + infile.open(filename);
  1265 + if(!infile.is_open())
  1266 + return OBJ_ERROR;
  1267 +
  1268 + vector<vertex_position> swcVertices;
  1269 + float token;
  1270 + objBegin(OBJ_LINES);
  1271 + while(!infile.eof())
  1272 + {
  1273 + vertex_position v;
  1274 + infile>>token; //get the id
  1275 + infile>>token; //get the fiber type
  1276 + infile>>v.x; //get the node position
  1277 + infile>>v.y;
  1278 + infile>>v.z;
  1279 + infile>>token; //get the radius
  1280 + infile>>token; //get the parent
  1281 +
  1282 + //insert the node into the swc vector
  1283 + swcVertices.push_back(v);
  1284 + //now draw the line from the parent to the current node
  1285 + if(token != -1)
  1286 + {
  1287 + objVertex3f(swcVertices[token-1].x, swcVertices[token-1].y, swcVertices[token-1].z);
  1288 + objVertex3f(v.x, v.y, v.z);
  1289 + }
  1290 + }
  1291 + objEnd();
  1292 +
  1293 +
  1294 + return OBJ_OK;
  1295 +
  1296 +}
  1297 +OBJint rtsOBJ::LoadFile(const char* filename)
  1298 +{
  1299 + string strFilename = filename;
  1300 + int length = strFilename.length();
  1301 + string extension = strFilename.substr(strFilename.length() - 3, 3);
  1302 + if(!extension.compare(string("obj")))
  1303 + return f_LoadOBJ(filename);
  1304 + else if(!extension.compare(string("swc")))
  1305 + return f_LoadSWC(filename);
  1306 + else return f_LoadOBJ(filename);
  1307 +
  1308 +}
  1309 +
  1310 +OBJint rtsOBJ::SaveFile(const char* filename)
  1311 +{
  1312 + //open the file as a stream
  1313 + ofstream outfile;
  1314 + outfile.open(filename);
  1315 + if(!outfile.is_open())
  1316 + return OBJ_ERROR;
  1317 +
  1318 + //output vertex positions
  1319 + vector<vertex_position>::iterator v;
  1320 + for(v=v_list.begin(); v!= v_list.end(); v++)
  1321 + {
  1322 + outfile<<"v";
  1323 + if((*v).mask & OBJ_V_X)
  1324 + {
  1325 + outfile<<' '<<(*v).x;
  1326 + if((*v).mask & OBJ_V_Y)
  1327 + {
  1328 + outfile<<' '<<(*v).y;
  1329 + if((*v).mask & OBJ_V_Z)
  1330 + {
  1331 + outfile<<' '<<(*v).z;
  1332 + if((*v).mask & OBJ_V_W)
  1333 + outfile<<' '<<(*v).w;
  1334 + }
  1335 + }
  1336 + }
  1337 + outfile<<'\n';
  1338 + }
  1339 +
  1340 + //output vertex texture coordinates
  1341 + vector<vertex_texture>::iterator vt;
  1342 + for(vt=vt_list.begin(); vt!= vt_list.end(); vt++)
  1343 + {
  1344 + outfile<<"vt";
  1345 + if((*vt).mask & OBJ_VT_U)
  1346 + {
  1347 + outfile<<' '<<(*vt).u;
  1348 + if((*vt).mask & OBJ_VT_V)
  1349 + {
  1350 + outfile<<' '<<(*vt).v;
  1351 + if((*vt).mask & OBJ_VT_W)
  1352 + outfile<<' '<<(*vt).w;
  1353 + }
  1354 + }
  1355 + outfile<<'\n';
  1356 + }
  1357 +
  1358 + //output vertex normal coordinates
  1359 + vector<vertex_normal>::iterator vn;
  1360 + for(vn=vn_list.begin(); vn!= vn_list.end(); vn++)
  1361 + {
  1362 + outfile<<"vn";
  1363 + if((*vn).mask & OBJ_VN_I)
  1364 + {
  1365 + outfile<<' '<<(*vn).i;
  1366 + if((*vn).mask & OBJ_VN_J)
  1367 + {
  1368 + outfile<<' '<<(*vn).j;
  1369 + if((*vn).mask & OBJ_VN_K)
  1370 + outfile<<' '<<(*vn).k;
  1371 + }
  1372 + }
  1373 + outfile<<'\n';
  1374 + }
  1375 +
  1376 + //output each primitive
  1377 + vector<primitive>::iterator p;
  1378 + vector<vertex>::iterator vert;
  1379 + for(p=primitives.begin(); p!= primitives.end(); p++)
  1380 + {
  1381 + switch((*p).type)
  1382 + {
  1383 + case OBJ_POINTS:
  1384 + outfile<<"p"; //output the points token
  1385 + break;
  1386 + case OBJ_LINES:
  1387 + outfile<<"l"; //output the lines token
  1388 + break;
  1389 + case OBJ_FACE:
  1390 + outfile<<"f"; //output the face token
  1391 + break;
  1392 + }
  1393 +
  1394 + //for each vertex in the list for the primitive
  1395 + for(vert = (*p).p.begin(); vert != (*p).p.end(); vert++)
  1396 + {
  1397 + outfile<<' '<<(*vert).v + 1;
  1398 + if((*p).mask & OBJ_VT)
  1399 + outfile<<'/'<<(*vert).vt + 1;
  1400 + if((*p).mask & OBJ_VN)
  1401 + {
  1402 + if(!((*p).mask & OBJ_VT))
  1403 + outfile<<'/';
  1404 + outfile<<'/'<<(*vert).vn + 1;
  1405 + }
  1406 + }
  1407 + outfile<<'\n';
  1408 +
  1409 + }
  1410 +
  1411 +
  1412 +
  1413 +}
  1414 +
  1415 +//get methods
  1416 +unsigned int rtsOBJ::getNumVertices(){return v_list.size();}
  1417 +unsigned int rtsOBJ::getNumLines(){return lines.size();}
  1418 +unsigned int rtsOBJ::getNumFaces(){return faces.size();}
  1419 +unsigned int rtsOBJ::getNumPointLists(){return points.size();}
  1420 +unsigned int rtsOBJ::getNumTexCoords(){return vt_list.size();}
  1421 +unsigned int rtsOBJ::getNumNormals(){return vn_list.size();}
  1422 +
  1423 +//these functions return the coordinate index as well as the value
  1424 +unsigned int rtsOBJ::getNumFaceVertices(unsigned int face){return primitives[face].p.size();}
  1425 +unsigned int rtsOBJ::getFaceVertex(unsigned int face, unsigned int vertex){return primitives[face].p[vertex].v;}
  1426 +unsigned int rtsOBJ::getFaceNormal(unsigned int face, unsigned int normal){return primitives[face].p[normal].vn;}
  1427 +unsigned int rtsOBJ::getFaceTexCoord(unsigned int face, unsigned int texcoord){return primitives[face].p[texcoord].vt;}
  1428 +unsigned int rtsOBJ::getNumLineVertices(unsigned int line){return primitives[line].p.size();}
  1429 +unsigned int rtsOBJ::getLineVertex(unsigned int line, unsigned int vertex){return primitives[line].p[vertex].v;}
  1430 +unsigned int rtsOBJ::getLineTexCoord(unsigned int line, unsigned int texcoord){return primitives[line].p[texcoord].vt;}
  1431 +point3D<float> rtsOBJ::getVertex3d(unsigned int index)
  1432 +{
  1433 + return point3D<float>(v_list[index].x, v_list[index].y, v_list[index].z);
  1434 +}
  1435 +point3D<float> rtsOBJ::getTexCoord3d(unsigned int index)
  1436 +{
  1437 + return point3D<float>(vt_list[index].u, vt_list[index].v, vt_list[index].w);
  1438 +}
  1439 +point3D<float> rtsOBJ::getNormal3d(unsigned int index)
  1440 +{
  1441 + return point3D<float>(vn_list[index].i, vn_list[index].j, vn_list[index].k);
  1442 +}
  1443 +vertex_position rtsOBJ::getVertex(unsigned int index){return v_list[index];}
  1444 +vertex_texture rtsOBJ::getTexCoord(unsigned int index){return vt_list[index];}
  1445 +vertex_normal rtsOBJ::getNormal(unsigned int index){return vn_list[index];}
  1446 +
  1447 +
  1448 +unsigned int rtsOBJ::getPrimitiveType(unsigned int primitive)
  1449 +{
  1450 + /*
  1451 + switch(primitives[i].type)
  1452 + {
  1453 + case OBJ_POINTS:
  1454 + return OBJ_POINTS;
  1455 + break;
  1456 + case OBJ_LINES:
  1457 + return OBJ_LINES;
  1458 + break;
  1459 + case OBJ_FACE:
  1460 + f_RenderFace(i);
  1461 + break;
  1462 + }*/
  1463 + return 0;
  1464 +}
  1465 +/****************************************************/
  1466 +/*******Iterator Methods*****************************/
  1467 +/****************************************************/
  1468 +
  1469 +rtsOBJ::iterator rtsOBJ::begin()
  1470 +{
  1471 + //create an iterator that will be returned and assign it to this OBJ
  1472 + iterator result;
  1473 + result.obj = this;
  1474 + result.end_object = false;
  1475 + result.end_primitive = false;
  1476 +
  1477 + //if there are no primitives, return the end iterator
  1478 + if(primitives.size() == 0)
  1479 + return end();
  1480 +
  1481 + //start at the beginning of the primitive array
  1482 + result.primitive_index = 0;
  1483 +
  1484 + return result;
  1485 +}
  1486 +
  1487 +rtsOBJ::iterator rtsOBJ::end()
  1488 +{
  1489 + //create an end iterator to return
  1490 + iterator result;
  1491 + result.obj = this;
  1492 + result.end_primitive = true;
  1493 + result.primitive_index = result.obj->primitives.size();
  1494 +
  1495 + return result;
  1496 +}
  1497 +
  1498 +void rtsOBJ::iterator::operator++()
  1499 +{
  1500 + primitive_index++;
  1501 + if(primitive_index >= obj->primitives.size())
  1502 + (*this) = obj->end();
  1503 +
  1504 +}
  1505 +
  1506 +bool rtsOBJ::iterator::operator ==(rtsOBJ::iterator operand)
  1507 +{
  1508 + if(operand.primitive_index == primitive_index)
  1509 + return true;
  1510 + else return false;
  1511 +}
  1512 +
  1513 +bool rtsOBJ::iterator::operator !=(rtsOBJ::iterator operand)
  1514 +{
  1515 + if(operand.primitive_index != primitive_index)
  1516 + return true;
  1517 + else return false;
  1518 +}
  1519 +
  1520 +unsigned int rtsOBJ::iterator::operator*()
  1521 +{
  1522 + return primitive_index;
  1523 +}
  1524 +
  1525 +void rtsOBJ::iterator::print()
  1526 +{
  1527 + cout<<"This is a test"<<endl;
  1528 +}
  1529 +
  1530 +
  1531 +
0 1532 \ No newline at end of file
... ...
objJedi.h 0 → 100755
  1 +++ a/objJedi.h
  1 +#ifndef OBJJEDI_H
  2 +#define OBJJEDI_H
  3 +
  4 +/*OBJ reader and writer.
  5 +
  6 +One aspect of the writer is based on OpenGL output commands. You can send OpenGL commands
  7 +(replacing "gl" and "GL" with "obj" and "OBJ" respectively to render to an Wavefront OBJ file
  8 +*/
  9 +
  10 +//#include "rtsMath.h"
  11 +#include "rtsLinearAlgebra.h"
  12 +#include <vector>
  13 +#include <fstream>
  14 +#include <iostream>
  15 +#include <string.h>
  16 +using namespace std;
  17 +
  18 +//masks for valid vertex components
  19 +#define OBJ_V_X 0x1
  20 +#define OBJ_V_Y 0x2
  21 +#define OBJ_V_Z 0x4
  22 +#define OBJ_V_W 0x8
  23 +
  24 +#define OBJ_VT_U 0x1
  25 +#define OBJ_VT_V 0x2
  26 +#define OBJ_VT_W 0x4
  27 +
  28 +#define OBJ_VN_I 0x1
  29 +#define OBJ_VN_J 0x2
  30 +#define OBJ_VN_K 0x4
  31 +
  32 +#define OBJ_V 0x1
  33 +#define OBJ_VT 0x2
  34 +#define OBJ_VN 0x4
  35 +
  36 +//primitive types
  37 +typedef unsigned char primitive_type;
  38 +
  39 +#define OBJ_END 0x0
  40 +#define OBJ_POINTS 0x1
  41 +#define OBJ_LINES 0x2
  42 +#define OBJ_FACE 0x3
  43 +
  44 +
  45 +#define OBJ_INVALID ULONG_MAX
  46 +//define the point structures
  47 +struct vertex_position{float x,y,z,w; unsigned char mask;};
  48 +struct vertex_texture{float u,v,w; unsigned char mask;};
  49 +struct vertex_normal{float i,j,k; unsigned char mask;};
  50 +//the point structure contains indices to the relative 3-vectors in the lists
  51 +struct vertex
  52 +{
  53 + unsigned int v;
  54 + unsigned int vt;
  55 + unsigned int vn;
  56 +};
  57 +
  58 +struct primitive
  59 +{
  60 + vector<vertex> p; //indices to the point
  61 + unsigned char mask; //mask describing which features (v, vt, vn) are used
  62 + primitive_type type; //the type of primitive (points, lines, face)
  63 +};
  64 +
  65 +//axis-aligned bounding box
  66 +struct AABB
  67 +{
  68 + vertex_position min;
  69 + vertex_position max;
  70 +};
  71 +
  72 +//create variable types
  73 +typedef unsigned int OBJint;
  74 +
  75 +//define the OBJ data class
  76 +class rtsOBJ
  77 +{
  78 +private:
  79 +
  80 + /*Current state variables. These variables are committed to the OBJ object
  81 + when a vertex is added. However, we are careful to only add them once (if they don't
  82 + change with every vertex.
  83 + */
  84 + vertex_texture current_vt;
  85 + vertex_normal current_vn;
  86 + bool vt_changed; //true if a new vt or vn was inserted since the last vertex
  87 + bool vn_changed;
  88 + unsigned char current_primitive_mask; //defines what coordinates are being used by the current primitive
  89 + //global variable storing the current render mode
  90 + OBJint g_CurrentMode;
  91 + //output file stream
  92 + ofstream g_objFile;
  93 + //obj file object
  94 + //objData g_OBJ;
  95 + //number of vertices since the last BEGIN
  96 + unsigned int g_NumVertices;
  97 + /*Attribute mask. This indicates what attributes are stored for each vertex.
  98 + Only a single mask applies to each vertex between objBegin() and objEnd(). The
  99 + attribute mask is flipped the first time an attribute is set but it is fixed after
  100 + the first vertex is passed.*/
  101 + unsigned char g_AttributeMask;
  102 + /*Attribute reset mask. This indicates whether or not an attribute has been
  103 + reset since the last vertex was rendered. This applies to OBJ_VT and OBJ_VN*/
  104 + unsigned char g_AttributeResetMask;
  105 + //latest texture coordinate sent
  106 + unsigned int g_LatestVT;
  107 + //latest vertex normal sent
  108 + unsigned int g_LatestVN;
  109 +
  110 + //extents of the points in the OBJ file
  111 + AABB m_bounds;
  112 +
  113 + OBJint f_InsertPointVertex();
  114 + OBJint f_InsertLineVertex();
  115 + OBJint f_InsertLineLoopVertex();
  116 + OBJint f_InsertLineStripVertex();
  117 + OBJint f_InsertTriangleVertex();
  118 + OBJint f_InsertTriangleStripVertex();
  119 + OBJint f_InsertTriangleFanVertex();
  120 + OBJint f_InsertQuadVertex();
  121 + OBJint f_InsertQuadStripVertex();
  122 + OBJint f_InsertPolygonVertex();
  123 + OBJint f_InsertPreviousFaceVertex(unsigned int v_index);
  124 + OBJint f_InsertFirstFaceVertex(unsigned int v_index);
  125 + OBJint f_InsertNewFaceVertex();
  126 + OBJint f_InsertNewLineVertex();
  127 + OBJint f_CreateNewFace();
  128 + OBJint f_CreateNewLine();
  129 + OBJint f_TerminateLineLoop();
  130 + OBJint f_LoadOBJ(const char* filename);
  131 + OBJint f_LoadSWC(const char* filename);
  132 +
  133 + //insert coordinate commands
  134 + //these are used to handle coordinates of different dimensions (and are called by the associated public function)
  135 + OBJint f_InsertVertexf(float x, float y, float z, float w, unsigned char mask);
  136 + OBJint f_InsertTexCoordf(float u, float v, float w, unsigned char mask);
  137 + OBJint f_InsertNormalf(float i, float j, float k, unsigned char mask);
  138 + //output functions
  139 + void f_OutputVertices();
  140 + void f_OutputPoints();
  141 + void f_OutputLines();
  142 + void f_OutputFaces();
  143 + void f_OutputVertexNormals();
  144 + void f_OutputTextureCoordinates();
  145 + void f_ClearAll();
  146 +
  147 + //methods for reading from a file
  148 + OBJint f_ReadPosition(ifstream &infile);
  149 + OBJint f_ReadNormal(ifstream &infile);
  150 + OBJint f_ReadTexCoord(ifstream &infile);
  151 + OBJint f_ReadVertex(ifstream &infile, vertex &new_point, unsigned char &mask);
  152 + OBJint f_ReadPrimitive(ifstream &infile, primitive_type type);
  153 + OBJint f_AdjustExtents(vertex_position v);
  154 +
  155 +public:
  156 + /*These vectors store the vertex and primitive data from the obj file.
  157 + All vertices, texture coordinates, and normals are stored in m_v, m_vt, m_vn
  158 + respectively. The vectors for each primitive store an index into m_v, m_vt,
  159 + and m_vn identifying the associated coordinate. Basically, the data is stored
  160 + in a structure very similar to the OBJ file itself.
  161 + */
  162 + vector<vertex_position> v_list;
  163 + vector<vertex_texture> vt_list;
  164 + vector<vertex_normal> vn_list;
  165 + vector<primitive> primitives;
  166 +
  167 + vector<unsigned int> points;
  168 + vector<unsigned int> lines;
  169 + vector<unsigned int> faces;
  170 +
  171 +public:
  172 +
  173 + OBJint objOpen(const char* filename);
  174 + OBJint objBegin(OBJint obj_mode);
  175 + OBJint objEnd();
  176 + OBJint objClose();
  177 + OBJint objNormal3f(float i, float j, float k);
  178 + OBJint objNormal2f(float i, float j);
  179 + OBJint objNormal1f(float i);
  180 + OBJint objTexCoord3f(float u, float v, float w);
  181 + OBJint objTexCoord2f(float u, float v);
  182 + OBJint objTexCoord1f(float u);
  183 + OBJint objVertex1f(float x);
  184 + OBJint objVertex2f(float x, float y);
  185 + OBJint objVertex3f(float x, float y, float z);
  186 + OBJint objVertex4f(float x, float y, float z, float w);
  187 + OBJint LoadFile(const char* filename);
  188 + OBJint SaveFile(const char* filename);
  189 +
  190 + //direct insertion methods
  191 + void insertVertexPosition(float x, float y, float z, unsigned char mask = OBJ_V_X | OBJ_V_Y | OBJ_V_Z);
  192 + void insertLine(unsigned int num_points, unsigned int* pointlist, unsigned int* normallist, unsigned int* texturelist);
  193 +
  194 + //get methods
  195 + unsigned int getNumVertices();
  196 + unsigned int getNumLines();
  197 + unsigned int getNumFaces();
  198 + unsigned int getNumPointLists();
  199 + unsigned int getNumTexCoords();
  200 + unsigned int getNumNormals();
  201 +
  202 + //these functions return the coordinate index as well as the value
  203 + unsigned int getNumFaceVertices(unsigned int face);
  204 + unsigned int getFaceVertex(unsigned int face, unsigned int vertex);
  205 + unsigned int getFaceNormal(unsigned int face, unsigned int normal);
  206 + unsigned int getFaceTexCoord(unsigned int face, unsigned int texcoord);
  207 + unsigned int getNumLineVertices(unsigned int line);
  208 + unsigned int getLineVertex(unsigned int line, unsigned int vertex);
  209 + unsigned int getLineTexCoord(unsigned int line, unsigned int texcoord);
  210 + point3D<float> getVertex3d(unsigned int index);
  211 + point3D<float> getTexCoord3d(unsigned int index);
  212 + point3D<float> getNormal3d(unsigned int index);
  213 + vertex_position getVertex(unsigned int index);
  214 + vertex_texture getTexCoord(unsigned int index);
  215 + vertex_normal getNormal(unsigned int index);
  216 + AABB getBoundingBox(){return m_bounds;}
  217 + void Scale(float scale_x, float scale_y, float scale_z);
  218 + void Translate(float trans_x, float trans_y, float trans_z);
  219 +
  220 + float GetDistance(float x, float y, float z);
  221 +
  222 + //return data about primitives
  223 + unsigned int getPrimitiveType(unsigned int primitive);
  224 +
  225 + //constructors
  226 + rtsOBJ();
  227 + void CopyOBJ(const rtsOBJ& obj);
  228 + //assignment
  229 + rtsOBJ& operator=(const rtsOBJ& obj)
  230 + {
  231 + CopyOBJ(obj);
  232 + return *this;
  233 + }
  234 + //copy
  235 + rtsOBJ(const rtsOBJ& obj)
  236 + {
  237 + CopyOBJ(obj);
  238 + //return *this;
  239 + }
  240 +
  241 +
  242 +
  243 + //Iterator stuff
  244 + class iterator
  245 + {
  246 + friend class rtsOBJ;
  247 + private:
  248 + rtsOBJ* obj;
  249 + bool end_primitive;
  250 + bool end_object;
  251 + unsigned int primitive_index;
  252 + public:
  253 + unsigned int operator*();
  254 + void operator++();
  255 + bool operator==(rtsOBJ::iterator operand);
  256 + bool operator!=(rtsOBJ::iterator operand);
  257 + unsigned int size(){return obj->primitives[primitive_index].p.size();};
  258 + void print();
  259 + };
  260 +
  261 + iterator begin();
  262 + iterator end();
  263 +};
  264 +
  265 +//define error codes
  266 +#define OBJ_OK 0x0100
  267 +#define OBJ_ERROR 0x0101
  268 +
  269 +//define the different modes
  270 +#define OBJ_NONE 0x0
  271 +#define OBJ_POINTS 0x1
  272 +#define OBJ_LINES 0x2
  273 +#define OBJ_LINE_STRIP 0x3
  274 +#define OBJ_LINE_LOOP 0x4
  275 +#define OBJ_TRIANGLES 0x5
  276 +#define OBJ_TRIANGLE_STRIP 0x6
  277 +#define OBJ_TRIANGLE_FAN 0x7
  278 +#define OBJ_QUADS 0x8
  279 +#define OBJ_QUAD_STRIP 0x9
  280 +#define OBJ_POLYGON 0x10
  281 +
  282 +
  283 +
  284 +
  285 +
  286 +
  287 +//initialize the OBJ file
  288 +OBJint objOpen(char* filename);
  289 +//close the obj file
  290 +OBJint objClose();
  291 +
  292 +//start rendering in a certain mode
  293 +OBJint objBegin(OBJint mode);
  294 +//stop the current rendering sequence
  295 +OBJint objEnd(void);
  296 +//render a vertex to the file
  297 +OBJint objVertex1f(float x);
  298 +OBJint objVertex2f(float x, float y);
  299 +OBJint objVertex3f(float x, float y, float z);
  300 +OBJint objVertex4f(float x, float y, float z, float w);
  301 +//set a normal vector for a vertex
  302 +OBJint objNormal3f(float i, float j, float k);
  303 +OBJint objNormal2f(float i, float j);
  304 +OBJint objNormal1f(float i);
  305 +//set a texture coordinate for a vertex
  306 +OBJint objTexCoord3f(float u, float v, float w);
  307 +OBJint objTexCoord2f(float u, float v);
  308 +OBJint objTexCoord1f(float u);
  309 +
  310 +//global variable for global functions
  311 +extern rtsOBJ g_OBJ;
  312 +
  313 +/*BUG NOTES
  314 +The standard function calls for inserting vertices don't work anymore. I've fixed points
  315 +but everything beyond that has to be updated.
  316 +*/
  317 +
  318 +#include "objJedi.h"
  319 +#include "rtsVector3d.h"
  320 +#include "rtsPoint3d.h"
  321 +#include <string>
  322 +//variable for use in global functions
  323 +rtsOBJ g_OBJ;
  324 +
  325 +/********UTILITY METHODS*******************************/
  326 +void rtsOBJ::Scale(float scale_x, float scale_y, float scale_z)
  327 +{
  328 + vector<vertex_position>::iterator i;
  329 + for(i = v_list.begin(); i!= v_list.end(); i++)
  330 + {
  331 + (*i).x *= scale_x;
  332 + (*i).y *= scale_y;
  333 + (*i).z *= scale_z;
  334 + }
  335 +}
  336 +
  337 +void rtsOBJ::Translate(float trans_x, float trans_y, float trans_z)
  338 +{
  339 + vector<vertex_position>::iterator i;
  340 + for(i = v_list.begin(); i!= v_list.end(); i++)
  341 + {
  342 + (*i).x += trans_x;
  343 + (*i).y += trans_y;
  344 + (*i).z += trans_z;
  345 + }
  346 +
  347 +}
  348 +
  349 +float rtsOBJ::GetDistance(float x, float y, float z)
  350 +{
  351 + //gets the distance between the specified point and the nearest surface of the OBJ
  352 + //currently only works for lines
  353 +
  354 + //cout<<"Primitives: "<<primitives.size()<<endl;
  355 + unsigned int num_primitives = primitives.size();
  356 + point3D<float> p0, p1, p2;
  357 + float min_dist = 255;
  358 + float dist;
  359 + unsigned int p, l;
  360 + vector3D<float> v, w;
  361 + float c1, c2, b;
  362 + point3D<float> Pb;
  363 +
  364 + //for each line
  365 + for(l=0; l<num_primitives; l++)
  366 + {
  367 + if(primitives[l].type & OBJ_LINES)
  368 + {
  369 + //for each point
  370 + for(p = 1; p<primitives[l].p.size(); p++)
  371 + {
  372 +
  373 + vertex_position v1 = v_list[primitives[l].p[p-1].v];
  374 + vertex_position v2 = v_list[primitives[l].p[p].v];
  375 + p1.x = v1.x;
  376 + p1.y = v1.y;
  377 + p1.z = v1.z;
  378 + p2.x = v2.x;
  379 + p2.y = v2.y;
  380 + p2.z = v2.z;
  381 +
  382 + p0.x = x;
  383 + p0.y = y;
  384 + p0.z = z;
  385 +
  386 + v = p2 - p1;
  387 + w = p0 - p1;
  388 + if((c1 = w*v) <= 0)
  389 + dist = (p1 - p0).Length();
  390 + else if((c2 = v*v) <= c1)
  391 + dist = (p2 - p0).Length();
  392 + else
  393 + {
  394 + b = c1/c2;
  395 + Pb = p1 + b*v;
  396 + dist = (Pb - p0).Length();
  397 + }
  398 + if(dist < min_dist)
  399 + min_dist = dist;
  400 +
  401 +
  402 +
  403 + }
  404 + }
  405 + }
  406 + //cout<<"---------------------------------------------"<<endl;
  407 +
  408 + return min_dist;
  409 +
  410 +
  411 +}
  412 +
  413 +/********CLASS METHOD DEFINITIONS**********************/
  414 +//constructors
  415 +
  416 +//constructor
  417 +rtsOBJ::rtsOBJ()
  418 +{
  419 + g_CurrentMode = OBJ_NONE;
  420 + g_NumVertices = 0;
  421 + g_AttributeMask = 0x0;
  422 + g_AttributeResetMask = 0x0;
  423 + g_LatestVT = 0;
  424 + g_LatestVN = 0;
  425 +
  426 + m_bounds.min.x = m_bounds.min.y = m_bounds.min.z = 99999;
  427 + m_bounds.max.x = m_bounds.max.y = m_bounds.max.z = -99999;
  428 +
  429 + current_primitive_mask = 0x0;
  430 +}
  431 +
  432 +void rtsOBJ::CopyOBJ(const rtsOBJ& obj)
  433 +{
  434 + current_vt = obj.current_vt;
  435 + current_vn = obj.current_vn;
  436 + vt_changed = obj.vt_changed; //true if a new vt or vn was inserted since the last vertex
  437 + vn_changed = obj.vn_changed;
  438 + current_primitive_mask = obj.current_primitive_mask; //defines what coordinates are being used by the current primitive
  439 + //global variable storing the current render mode
  440 + g_CurrentMode = obj.g_CurrentMode;
  441 + //output file stream
  442 + //g_objFile = obj.g_objFile;
  443 + //obj file object
  444 + //objData g_OBJ;
  445 + //number of vertices since the last BEGIN
  446 + g_NumVertices = obj.g_NumVertices;
  447 + /*Attribute mask. This indicates what attributes are stored for each vertex.
  448 + Only a single mask applies to each vertex between objBegin() and objEnd(). The
  449 + attribute mask is flipped the first time an attribute is set but it is fixed after
  450 + the first vertex is passed.*/
  451 + g_AttributeMask = obj.g_AttributeMask;
  452 + /*Attribute reset mask. This indicates whether or not an attribute has been
  453 + reset since the last vertex was rendered. This applies to OBJ_VT and OBJ_VN*/
  454 + g_AttributeResetMask = obj.g_AttributeResetMask;
  455 + //latest texture coordinate sent
  456 + g_LatestVT = obj.g_LatestVT;
  457 + //latest vertex normal sent
  458 + g_LatestVN = obj.g_LatestVN;
  459 + m_bounds = obj.m_bounds;
  460 +
  461 +
  462 + v_list = obj.v_list;
  463 + vt_list = obj.vt_list;
  464 + vn_list = obj.vn_list;
  465 + primitives = obj.primitives;
  466 +
  467 + points = obj.points;
  468 + lines = obj.lines;
  469 + faces = obj.faces;
  470 +}
  471 +
  472 +//opens an obj file for rendering
  473 +OBJint rtsOBJ::objOpen(const char* filename)
  474 +{
  475 + g_objFile.open(filename);
  476 + return OBJ_OK;
  477 +}
  478 +
  479 +//close the obj file
  480 +OBJint rtsOBJ::objClose()
  481 +{
  482 + //TODO: write obj data
  483 + f_OutputVertices();
  484 + f_OutputTextureCoordinates();
  485 + f_OutputVertexNormals();
  486 + f_OutputPoints();
  487 + f_OutputLines();
  488 + f_OutputFaces();
  489 +
  490 + //close the file
  491 + g_objFile.close();
  492 +
  493 + //delete all of the data from the global object
  494 + f_ClearAll();
  495 + return OBJ_OK;
  496 +}
  497 +
  498 +OBJint rtsOBJ::objBegin(OBJint mode)
  499 +{
  500 + //make sure that we aren't currently rendering
  501 + if(g_CurrentMode != OBJ_NONE)
  502 + return OBJ_ERROR;
  503 + //make sure that the given mode is valid
  504 + if(mode < OBJ_POINTS || mode > OBJ_POLYGON)
  505 + return OBJ_ERROR;
  506 +
  507 + //otherwise, go ahead and set the mode
  508 + g_CurrentMode = mode;
  509 + //set the number of vertices to zero
  510 + g_NumVertices = 0;
  511 +
  512 + //reset the current state primitive state
  513 + current_primitive_mask = 0x0;
  514 +
  515 + return OBJ_OK;
  516 +}
  517 +
  518 +OBJint rtsOBJ::objEnd()
  519 +{
  520 + OBJint error = OBJ_OK;
  521 + //check to make sure the number of rendered vertices is valid for the current mode
  522 + switch(g_CurrentMode)
  523 + {
  524 + case OBJ_NONE:
  525 + //can't quit if we haven't started
  526 + error = OBJ_ERROR;
  527 + break;
  528 + case OBJ_LINES:
  529 + //if less than two vertices or an odd number of vertices
  530 + if(g_NumVertices < 2 || g_NumVertices%2 != 0)
  531 + {
  532 + //if there wasn't a vertex at all
  533 + if(g_NumVertices == 0)
  534 + error = OBJ_ERROR;
  535 + //if there was at least one vertex
  536 + else
  537 + {
  538 + //pop the last line off the list
  539 + primitives.pop_back();
  540 + lines.pop_back();
  541 + error = OBJ_ERROR;
  542 + }
  543 + }
  544 + break;
  545 + case OBJ_LINE_STRIP:
  546 + //if less than two vertices
  547 + if(g_NumVertices < 2)
  548 + {
  549 + //if there wasn't a vertex at all
  550 + if(g_NumVertices == 0)
  551 + error = OBJ_ERROR;
  552 + //if there was at least one vertex
  553 + else
  554 + {
  555 + //pop the last line off the list
  556 + primitives.pop_back();
  557 + lines.pop_back();
  558 + error = OBJ_ERROR;
  559 + }
  560 + }
  561 + break;
  562 + case OBJ_LINE_LOOP:
  563 + //if less than three vertices
  564 + if(g_NumVertices < 3)
  565 + {
  566 + //pop the last line off the list
  567 + primitives.pop_back();
  568 + lines.pop_back();
  569 + error = OBJ_ERROR;
  570 + }
  571 + //connect the first and last points
  572 + else
  573 + {
  574 + error = f_TerminateLineLoop();
  575 + }
  576 + break;
  577 + case OBJ_TRIANGLES:
  578 + //if less than three vertices or not a power of three
  579 + if(g_NumVertices < 3 || g_NumVertices%3 !=0)
  580 + {
  581 + primitives.pop_back();
  582 + faces.pop_back();
  583 + error = OBJ_ERROR;
  584 + }
  585 + break;
  586 + case OBJ_TRIANGLE_STRIP:
  587 + //if less than three vertices
  588 + if(g_NumVertices < 3)
  589 + {
  590 + primitives.pop_back();
  591 + faces.pop_back();
  592 + error = OBJ_ERROR;
  593 + }
  594 + break;
  595 + case OBJ_TRIANGLE_FAN:
  596 + //if less than three vertices
  597 + if(g_NumVertices < 3)
  598 + {
  599 + primitives.pop_back();
  600 + faces.pop_back();
  601 + error = OBJ_ERROR;
  602 + }
  603 + break;
  604 + case OBJ_QUADS:
  605 + if(g_NumVertices < 4 || g_NumVertices%4 != 0)
  606 + {
  607 + primitives.pop_back();
  608 + faces.pop_back();
  609 + error = OBJ_ERROR;
  610 + }
  611 + break;
  612 + case OBJ_QUAD_STRIP:
  613 + //has to be at least 4 vertices and an even number
  614 + if(g_NumVertices < 4 || g_NumVertices%2 != 0)
  615 + {
  616 + primitives.pop_back();
  617 + faces.pop_back();
  618 + error = OBJ_ERROR;
  619 + }
  620 + break;
  621 + case OBJ_POLYGON:
  622 + //has to be at least three vertices
  623 + if(g_NumVertices < 3)
  624 + {
  625 + primitives.pop_back();
  626 + faces.pop_back();
  627 + error = OBJ_ERROR;
  628 + }
  629 + break;
  630 + }
  631 +
  632 + //reset the attribute mask
  633 + g_AttributeMask = 0x0;
  634 + //just for closure, reset the attribute reset mask
  635 + g_AttributeResetMask = 0x0;
  636 + //stop rendering
  637 + g_CurrentMode = OBJ_NONE;
  638 + return error;
  639 +}
  640 +
  641 +OBJint rtsOBJ::f_InsertVertexf(float x, float y, float z, float w, unsigned char mask)
  642 +{
  643 + //make sure we're rendering
  644 + if(g_CurrentMode == OBJ_NONE)
  645 + return OBJ_ERROR;
  646 +
  647 + //insert the vertex into the vertex vector
  648 + vertex_position v;
  649 + v.x = x; v.y = y; v.z=z; v.w=w; v.mask = mask;
  650 + v_list.push_back(v);
  651 + f_AdjustExtents(v); //set the bounding box
  652 + //insert texture coordinate and normal if specified for this primitive
  653 + if((current_primitive_mask & OBJ_VT) && (vt_changed))
  654 + vt_list.push_back(current_vt);
  655 + if((current_primitive_mask & OBJ_VN) && (vn_changed))
  656 + vn_list.push_back(current_vn);
  657 +
  658 +
  659 + //increment the number of vertices inserted
  660 + g_NumVertices++;
  661 +
  662 + //handle each case of the vertex creation individually
  663 + OBJint error = OBJ_OK;
  664 + switch(g_CurrentMode)
  665 + {
  666 + case OBJ_POINTS:
  667 + error = f_InsertPointVertex();
  668 + break;
  669 + case OBJ_LINES:
  670 + error = f_InsertLineVertex();
  671 + break;
  672 + case OBJ_LINE_LOOP:
  673 + error = f_InsertLineLoopVertex();
  674 + break;
  675 + case OBJ_LINE_STRIP:
  676 + error = f_InsertLineStripVertex();
  677 + break;
  678 + case OBJ_TRIANGLES:
  679 + error = f_InsertTriangleVertex();
  680 + break;
  681 + case OBJ_TRIANGLE_STRIP:
  682 + error = f_InsertTriangleStripVertex();
  683 + break;
  684 + case OBJ_TRIANGLE_FAN:
  685 + error = f_InsertTriangleFanVertex();
  686 + break;
  687 + case OBJ_QUADS:
  688 + error = f_InsertQuadVertex();
  689 + break;
  690 + case OBJ_QUAD_STRIP:
  691 + error = f_InsertQuadStripVertex();
  692 + break;
  693 + case OBJ_POLYGON:
  694 + error = f_InsertPolygonVertex();
  695 + break;
  696 + }
  697 + //set the reset mask to zero
  698 + g_AttributeResetMask = 0x0;
  699 +
  700 + //set the attribute mask to include vertex position
  701 + g_AttributeMask = g_AttributeMask | OBJ_V;
  702 +
  703 + //return the result of the insertion
  704 + return error;
  705 +}
  706 +
  707 +OBJint rtsOBJ::objVertex1f(float x)
  708 +{
  709 + return f_InsertVertexf(x, 0.0, 0.0, 0.0, OBJ_V_X);
  710 +}
  711 +
  712 +OBJint rtsOBJ::objVertex2f(float x, float y)
  713 +{
  714 + return f_InsertVertexf(x, y, 0.0, 0.0, OBJ_V_X | OBJ_V_Y);
  715 +}
  716 +
  717 +OBJint rtsOBJ::objVertex3f(float x, float y, float z)
  718 +{
  719 + return f_InsertVertexf(x, y, z, 0.0, OBJ_V_X | OBJ_V_Y | OBJ_V_Z);
  720 +
  721 +}
  722 +
  723 +OBJint rtsOBJ::objVertex4f(float x, float y, float z, float w)
  724 +{
  725 + return f_InsertVertexf(x, y, z, w, OBJ_V_X | OBJ_V_Y | OBJ_V_Z | OBJ_V_W);
  726 +}
  727 +
  728 +OBJint rtsOBJ::objNormal3f(float i, float j, float k)
  729 +{
  730 + return f_InsertNormalf(i, j, k, OBJ_VN_I | OBJ_VN_J | OBJ_VN_K);
  731 +}
  732 +OBJint rtsOBJ::objNormal2f(float i, float j)
  733 +{
  734 + return f_InsertNormalf(i, j, 0.0, OBJ_VN_I | OBJ_VN_J);
  735 +}
  736 +
  737 +OBJint rtsOBJ::objNormal1f(float i)
  738 +{
  739 + return f_InsertNormalf(i, 0.0, 0.0, OBJ_VN_I);
  740 +}
  741 +
  742 +OBJint rtsOBJ::f_InsertNormalf(float i, float j, float k, unsigned char mask)
  743 +{
  744 + /*DEPRECATED
  745 + //if the mode is not rendering faces, there is an error
  746 + if(g_CurrentMode < OBJ_TRIANGLES)
  747 + return OBJ_ERROR;
  748 + //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written)
  749 + if(!(g_AttributeMask & OBJ_VN))
  750 + {
  751 + //if a vertex has been rendered, then we can't change the attribute, so exit
  752 + if(g_NumVertices > 0)
  753 + return OBJ_ERROR;
  754 + else
  755 + //otherwise, just set the attribute flag
  756 + g_AttributeMask = g_AttributeMask | OBJ_VN;
  757 + }
  758 +
  759 +
  760 + //insert the new normal into the normal list for the file
  761 + vertex_normal new_vn;
  762 + new_vn.i = i; new_vn.j = j; new_vn.k = k;
  763 + new_vn.mask = mask;
  764 + vn_list.push_back(new_vn);
  765 + */
  766 + current_vn.i = i; //set the current texture state to the given coordinates
  767 + current_vn.j = j;
  768 + current_vn.k = k;
  769 + current_vn.mask = mask; //set the mask as appropriate
  770 + vn_changed = true; //the texture coordinate state has changed
  771 + current_primitive_mask = current_primitive_mask | OBJ_VN; //the current primitive now uses texture coordinates (if it didn't previously)
  772 +
  773 + return OBJ_OK;
  774 +}
  775 +
  776 +OBJint rtsOBJ::objTexCoord3f(float u, float v, float w)
  777 +{
  778 + return f_InsertTexCoordf(u, v, w, OBJ_VT_U | OBJ_VT_V | OBJ_VT_W);
  779 +}
  780 +
  781 +OBJint rtsOBJ::objTexCoord2f(float u, float v)
  782 +{
  783 + return f_InsertTexCoordf(u, v, 0.0, OBJ_VT_U | OBJ_VT_V);
  784 +}
  785 +
  786 +OBJint rtsOBJ::objTexCoord1f(float u)
  787 +{
  788 + return f_InsertTexCoordf(u, 0.0, 0.0, OBJ_VT_U);
  789 +}
  790 +
  791 +OBJint rtsOBJ::f_InsertTexCoordf(float u, float v, float w, unsigned char mask)
  792 +{
  793 + /*
  794 + DEPRECATED
  795 + //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written)
  796 + if(!(g_AttributeMask & OBJ_VT))
  797 + {
  798 + //if a vertex has been rendered, then we can't change the attribute, so exit
  799 + if(g_NumVertices > 0)
  800 + return OBJ_ERROR;
  801 + else
  802 + //otherwise, just set the attribute flag
  803 + g_AttributeMask = g_AttributeMask | OBJ_VT;
  804 + }
  805 +
  806 + //insert the new texture coordinate into the list for the file
  807 + vertex_texture new_vt;
  808 + new_vt.u = u; new_vt.v = v; new_vt.w = w;
  809 + new_vt.mask = mask;
  810 + vt_list.push_back(new_vt);
  811 + */
  812 + current_vt.u = u; //set the current texture state to the given coordinates
  813 + current_vt.v = v;
  814 + current_vt.w = w;
  815 + current_vt.mask = mask; //set the mask as appropriate
  816 + vt_changed = true; //the texture coordinate state has changed
  817 + current_primitive_mask = current_primitive_mask | OBJ_VT; //the current primitive now uses texture coordinates (if it didn't previously)
  818 +
  819 + return OBJ_OK;
  820 +}
  821 +
  822 +
  823 +void rtsOBJ::insertVertexPosition(float x, float y, float z, unsigned char mask)
  824 +{
  825 + vertex_position v;
  826 + v.x = x;
  827 + v.y = y;
  828 + v.z = z;
  829 + v.mask = mask;
  830 +
  831 + v_list.push_back(v);
  832 +}
  833 +
  834 +void rtsOBJ::insertLine(unsigned int num_points, unsigned int* pointlist, unsigned int* normallist, unsigned int* texturelist)
  835 +{
  836 + //create the new primitive
  837 + primitive line;
  838 + line.type = OBJ_LINES;
  839 + line.mask = 0;
  840 +
  841 + //set the mask based on the passed data
  842 + if(pointlist != NULL)
  843 + line.mask = line.mask | OBJ_V;
  844 + if(normallist != NULL)
  845 + line.mask = line.mask | OBJ_VN;
  846 + if(texturelist != NULL)
  847 + line.mask = line.mask | OBJ_VT;
  848 +
  849 + //insert the line
  850 + unsigned int v;
  851 + vertex new_vert;
  852 + for(v=0; v<num_points; v++)
  853 + {
  854 + if(pointlist)
  855 + new_vert.v = pointlist[v];
  856 + if(normallist)
  857 + new_vert.vn = normallist[v];
  858 + if(texturelist)
  859 + new_vert.vt = texturelist[v];
  860 + line.p.push_back(new_vert);
  861 + }
  862 + //insert the new primitive into the list
  863 + primitives.push_back(line);
  864 +}
  865 +OBJint rtsOBJ::f_InsertPointVertex()
  866 +{
  867 + //insert the most recent point into the most recent point list
  868 + //if this is the first vertex, create the point list
  869 + if(g_NumVertices == 1)
  870 + {
  871 + primitive new_p; //create the new point
  872 + new_p.type = OBJ_POINTS;
  873 + new_p.mask = current_primitive_mask;
  874 + points.push_back(primitives.size()); //store the primitive id in the points list
  875 + primitives.push_back(new_p);
  876 + }
  877 +
  878 + //find the id of the most recent primitive
  879 + unsigned int p_index = primitives.size() - 1;
  880 + //find the index of the recent point
  881 + vertex p;
  882 + p.v = v_list.size() - 1;
  883 + //insert the indices for texture coordinates and normal if necessary
  884 + if(primitives[p_index].mask & OBJ_VT)
  885 + p.vt = vt_list.size() - 1;
  886 + if(primitives[p_index].mask & OBJ_VN)
  887 + p.vn = vn_list.size() - 1;
  888 +
  889 + //insert the vertex index into the primitive's point list
  890 + primitives[p_index].p.push_back(p);
  891 +
  892 + //push the point into the points list if it is not the only point in the primitive
  893 + if(g_NumVertices > 1)
  894 + points.push_back(p_index);
  895 +
  896 + return OBJ_OK;
  897 +}
  898 +
  899 +OBJint rtsOBJ::f_InsertLineVertex()
  900 +{
  901 + //if this is an odd vertex, create a new line
  902 + if(g_NumVertices%2 == 1)
  903 + {
  904 + f_CreateNewLine();
  905 + }
  906 +
  907 + f_InsertNewLineVertex();
  908 +
  909 + return OBJ_OK;
  910 +}
  911 +OBJint rtsOBJ::f_InsertLineLoopVertex()
  912 +{
  913 + //technically, this is the same as inserting a line strip vertex
  914 + f_InsertLineStripVertex();
  915 + return OBJ_OK;
  916 +}
  917 +
  918 +OBJint rtsOBJ::f_InsertLineStripVertex()
  919 +{
  920 + if(g_NumVertices == 1)
  921 + {
  922 + f_CreateNewLine();
  923 + }
  924 +
  925 + f_InsertNewLineVertex();
  926 +
  927 + return OBJ_OK;
  928 +}
  929 +
  930 +OBJint rtsOBJ::f_InsertTriangleVertex()
  931 +{
  932 + //if this is the first vertex in a triangle, create a new triangle
  933 + if(g_NumVertices%3 == 1)
  934 + {
  935 + f_CreateNewFace();
  936 + }
  937 +
  938 +
  939 + f_InsertNewFaceVertex();
  940 +
  941 + return OBJ_OK;
  942 +}
  943 +OBJint rtsOBJ::f_InsertTriangleStripVertex()
  944 +{
  945 + //in the special case of the first three vertices, just create a triangle
  946 + if(g_NumVertices < 4)
  947 + f_InsertTriangleVertex();
  948 + else
  949 + {
  950 +
  951 + //create a new face for the new triangle
  952 + f_CreateNewFace();
  953 +
  954 + //make sure to get the ordering right:
  955 + // Even vertices provide the previous two vertices "in order": (v2, v3, v4)
  956 + // Odd vertices provide the previous two vertices in reverse order: (v1, v3, v2)
  957 + if(g_NumVertices % 2 == 1)
  958 + {
  959 + f_InsertPreviousFaceVertex(2);
  960 + f_InsertPreviousFaceVertex(1);
  961 + f_InsertNewFaceVertex();
  962 + }
  963 + else
  964 + {
  965 + f_InsertPreviousFaceVertex(1);
  966 + f_InsertNewFaceVertex();
  967 + f_InsertPreviousFaceVertex(2);
  968 + }
  969 + }
  970 +
  971 + return OBJ_OK;
  972 +}
  973 +OBJint rtsOBJ::f_InsertTriangleFanVertex()
  974 +{
  975 + //in the special case of the first three vertices, just create a triangle
  976 + if(g_NumVertices <4)
  977 + f_InsertTriangleVertex();
  978 + else
  979 + {
  980 + //create a new face for the new triangle
  981 + f_CreateNewFace();
  982 + //add the previous vertices to the face
  983 + f_InsertFirstFaceVertex(0);
  984 + f_InsertPreviousFaceVertex(2);
  985 + //insert the current vertex
  986 + f_InsertNewFaceVertex();
  987 + }
  988 +
  989 + return OBJ_OK;
  990 +}
  991 +OBJint rtsOBJ::f_InsertQuadVertex()
  992 +{
  993 + //if this is the first vertex in a quad, create a new quad
  994 + if(g_NumVertices%4 == 1)
  995 + {
  996 + f_CreateNewFace();
  997 + }
  998 +
  999 + f_InsertNewFaceVertex();
  1000 +
  1001 + return OBJ_OK;
  1002 +}
  1003 +OBJint rtsOBJ::f_InsertQuadStripVertex()
  1004 +{
  1005 + //in the case of one of the first four vertices, just create a quad
  1006 + if(g_NumVertices < 5)
  1007 + f_InsertQuadVertex();
  1008 + //if the vertex is odd (it will be the third vertex of a quad)
  1009 + else if(g_NumVertices%2 == 1)
  1010 + {
  1011 + //create a new face for the new quad
  1012 + f_CreateNewFace();
  1013 + //add the previous two vertices
  1014 + f_InsertPreviousFaceVertex(2);
  1015 + f_InsertPreviousFaceVertex(3);
  1016 + //add the current vertex
  1017 + f_InsertNewFaceVertex();
  1018 + }
  1019 + else
  1020 + {
  1021 + //if this is the last vertex of the quad, just add it
  1022 + f_InsertNewFaceVertex();
  1023 +
  1024 + }
  1025 + return OBJ_OK;
  1026 +}
  1027 +OBJint rtsOBJ::f_InsertPolygonVertex()
  1028 +{
  1029 + //if this is the first vertex, create the quad
  1030 + if(g_NumVertices == 1)
  1031 + {
  1032 + f_CreateNewFace();
  1033 + }
  1034 + f_InsertNewFaceVertex();
  1035 +
  1036 + return OBJ_OK;
  1037 +}
  1038 +
  1039 +OBJint rtsOBJ::f_InsertPreviousFaceVertex(unsigned int v_index)
  1040 +{
  1041 + /*Finds the vertex used in the previous face with the given index and
  1042 + inserts it into the current face. This limits the redundancy in the file
  1043 + for re-used vertices (in strips and fans). This also transfers texture
  1044 + and normal information.*/
  1045 +
  1046 + //find the index of the previous face
  1047 + unsigned int prev_f_index = primitives.size() - 2;
  1048 + //find the index of the current face
  1049 + unsigned int f_index = prev_f_index +1;
  1050 + //add the vertex information from the previous face to this face
  1051 + primitives[f_index].p.push_back(primitives[prev_f_index].p[v_index]);
  1052 +
  1053 + return OBJ_OK;
  1054 +}
  1055 +
  1056 +OBJint rtsOBJ::f_InsertFirstFaceVertex(unsigned int v_index)
  1057 +{
  1058 + /*Finds the vertex used in the first face (since the last objBegin())
  1059 + with the given index and inserts it at the end of the current face.
  1060 + This includes texture and normal information.*/
  1061 +
  1062 + //The result depends on the type of face being rendered
  1063 + //So far, this function only applies to triangle fans
  1064 + if(g_CurrentMode != OBJ_TRIANGLE_FAN)
  1065 + return OBJ_ERROR;
  1066 +
  1067 + //calculate the number of faces that have been rendered
  1068 + unsigned int num_faces = g_NumVertices - 2;
  1069 + //find the index of the first face
  1070 + unsigned int first_f_index = primitives.size() - num_faces;
  1071 + //find the index of the current face
  1072 + unsigned int f_index = primitives.size() - 1;
  1073 + //transfer the vertex information from the first face to this one
  1074 + primitives[f_index].p.push_back(primitives[first_f_index].p[v_index]);
  1075 +
  1076 +
  1077 + return OBJ_OK;
  1078 +}
  1079 +
  1080 +OBJint rtsOBJ::f_InsertNewFaceVertex()
  1081 +{
  1082 + /*This inserts information about the current vertex into the current face*/
  1083 + //find the new vertex index
  1084 + vertex p;
  1085 + p.v = v_list.size() -1;
  1086 + p.vt = vt_list.size() - 1;
  1087 + p.vn = vn_list.size() -1;
  1088 + //find the face index
  1089 + unsigned int f_index = primitives.size() -1;
  1090 + //INSERT VERTEX AND ATTRIBUTE DATA
  1091 + //just add the vertex to the face
  1092 + primitives[f_index].p.push_back(p);
  1093 +
  1094 + return OBJ_OK;
  1095 +}
  1096 +
  1097 +OBJint rtsOBJ::f_InsertNewLineVertex()
  1098 +{
  1099 + /*This inserts information about the current vertex into the current line*/
  1100 + //find the new vertex index
  1101 + vertex p;
  1102 + p.v = v_list.size() -1;
  1103 + p.vt = vt_list.size() - 1;
  1104 + //find the line index
  1105 + unsigned int l_index = primitives.size() -1;
  1106 +
  1107 + //ADD VERTEX AND ATTRIBUTE INFORMATION
  1108 + //add the vertex to the line
  1109 + primitives[l_index].p.push_back(p);
  1110 +
  1111 + return OBJ_OK;
  1112 +}
  1113 +
  1114 +OBJint rtsOBJ::f_CreateNewFace()
  1115 +{
  1116 + primitive new_f;
  1117 + new_f.type = OBJ_FACE;
  1118 + new_f.mask = g_AttributeMask;
  1119 + faces.push_back(primitives.size());
  1120 + primitives.push_back(new_f);
  1121 +
  1122 +
  1123 + return OBJ_OK;
  1124 +}
  1125 +
  1126 +OBJint rtsOBJ::f_CreateNewLine()
  1127 +{
  1128 + primitive new_l;
  1129 + new_l.type = OBJ_LINES;
  1130 + new_l.mask = g_AttributeMask;
  1131 + lines.push_back(primitives.size());
  1132 + primitives.push_back(new_l);
  1133 +
  1134 + return OBJ_OK;
  1135 +}
  1136 +
  1137 +
  1138 +OBJint rtsOBJ::f_TerminateLineLoop()
  1139 +{
  1140 + /*This function just terminates the line loop by setting the last vertex
  1141 + to the first vertex.*/
  1142 + if(g_CurrentMode != OBJ_LINE_LOOP)
  1143 + return OBJ_ERROR;
  1144 + //find the index for the current line
  1145 + unsigned int l_index = lines.size() -1;
  1146 + //insert the first vertex as the last vertex
  1147 + primitives[l_index].p.push_back(primitives[l_index].p[0]);
  1148 +
  1149 + return OBJ_OK;
  1150 +}
  1151 +
  1152 +void rtsOBJ::f_OutputVertices()
  1153 +{
  1154 + //get the number of vertices in the object
  1155 + unsigned int v_num = v_list.size();
  1156 + for(unsigned int i=0; i<v_num; i++)
  1157 + {
  1158 + g_objFile<<"v";
  1159 + if(v_list[i].mask & OBJ_V_X)
  1160 + g_objFile<<" "<<v_list[i].x;
  1161 + if(v_list[i].mask & OBJ_V_Y)
  1162 + g_objFile<<" "<<v_list[i].y;
  1163 + if(v_list[i].mask & OBJ_V_Z)
  1164 + g_objFile<<" "<<v_list[i].z;
  1165 + if(v_list[i].mask & OBJ_V_W)
  1166 + g_objFile<<" "<<v_list[i].w;
  1167 + g_objFile<<endl;
  1168 + }
  1169 +
  1170 +}
  1171 +
  1172 +void rtsOBJ::f_OutputVertexNormals()
  1173 +{
  1174 + //get the number of normals in the object
  1175 + unsigned int vn_num = vn_list.size();
  1176 + for(unsigned int i=0; i<vn_num; i++)
  1177 + {
  1178 + g_objFile<<"vn ";
  1179 + if(vn_list[i].mask & OBJ_VN_I)
  1180 + {
  1181 + g_objFile<<vn_list[i].i;
  1182 + if(vn_list[i].mask & OBJ_VN_J)
  1183 + {
  1184 + g_objFile<<" "<<vn_list[i].j;
  1185 + if(vn_list[i].mask & OBJ_VN_K)
  1186 + g_objFile<<" "<<vn_list[i].k;
  1187 + }
  1188 + }
  1189 + g_objFile<<endl;
  1190 + }
  1191 +}
  1192 +
  1193 +void rtsOBJ::f_OutputTextureCoordinates()
  1194 +{
  1195 + //get the number of vertices in the object
  1196 + unsigned int vt_num = vt_list.size();
  1197 + for(unsigned int i=0; i<vt_num; i++)
  1198 + {
  1199 + g_objFile<<"vt ";
  1200 + if(vt_list[i].mask & OBJ_VT_U)
  1201 + {
  1202 + g_objFile<<vt_list[i].u;
  1203 + if(vt_list[i].mask & OBJ_VT_V)
  1204 + {
  1205 + g_objFile<<" "<<vt_list[i].v;
  1206 + if(vt_list[i].mask & OBJ_VT_W)
  1207 + g_objFile<<" "<<vt_list[i].w;
  1208 + }
  1209 + }
  1210 + g_objFile<<endl;
  1211 + }
  1212 +}
  1213 +
  1214 +void rtsOBJ::f_OutputPoints()
  1215 +{
  1216 + /*
  1217 + //get the number of point vectors
  1218 + unsigned int p_num = points.size();
  1219 +
  1220 + //for each point vector, output the points
  1221 + for(unsigned int i=0; i<p_num; i++)
  1222 + {
  1223 + g_objFile<<"p";
  1224 + unsigned int v_num = points[i].p.size();
  1225 + for(unsigned int j=0; j<v_num; j++)
  1226 + {
  1227 + g_objFile<<" "<<points[i].p[j].v+1;
  1228 + }
  1229 + g_objFile<<endl;
  1230 + }
  1231 + */
  1232 +}
  1233 +
  1234 +void rtsOBJ::f_OutputLines()
  1235 +{
  1236 + /*
  1237 + //get the number of line vectors
  1238 + unsigned int l_num = lines.size();
  1239 +
  1240 + //for each line vector, output the associated points
  1241 + for(unsigned int i=0; i<l_num; i++)
  1242 + {
  1243 + g_objFile<<"l";
  1244 + unsigned int v_num = lines[i].p.size();
  1245 + for(unsigned int j=0; j<v_num; j++)
  1246 + {
  1247 + g_objFile<<" "<<lines[i].p[j].v+1;
  1248 + //output texture coordinate if there are any
  1249 + if(lines[i].mask & OBJ_VT)
  1250 + g_objFile<<"/"<<lines[i].p[j].vt+1;
  1251 + }
  1252 + g_objFile<<endl;
  1253 + }
  1254 + */
  1255 +}
  1256 +
  1257 +void rtsOBJ::f_OutputFaces()
  1258 +{
  1259 + /*
  1260 + //get the number of faces
  1261 + unsigned int f_num = faces.size();
  1262 +
  1263 + //for each face, output the associated points
  1264 + for(unsigned int i=0; i<f_num; i++)
  1265 + {
  1266 + g_objFile<<"f";
  1267 + //get the number of face vertices
  1268 + unsigned int v_num = faces[i].p.size();
  1269 + for(unsigned int j=0; j<v_num; j++)
  1270 + {
  1271 + g_objFile<<" "<<faces[i].p[j].v+1;
  1272 + //if there are texture coordinates
  1273 + if(faces[i].mask & OBJ_VT)
  1274 + g_objFile<<"/"<<faces[i].p[j].vt+1;
  1275 + //if there is a normal
  1276 + if(faces[i].mask & OBJ_VN)
  1277 + {
  1278 + //but no texture coordinates, put an extra slash
  1279 + if(!(faces[i].mask & OBJ_VT))
  1280 + g_objFile<<"/";
  1281 + g_objFile<<"/"<<faces[i].p[j].vn+1;
  1282 + }
  1283 +
  1284 + }
  1285 + g_objFile<<endl;
  1286 + }
  1287 + */
  1288 +}
  1289 +
  1290 +void rtsOBJ::f_ClearAll()
  1291 +{
  1292 + rtsOBJ();
  1293 + //clear all data from the global obj function
  1294 + faces.clear();
  1295 + lines.clear();
  1296 + points.clear();
  1297 + v_list.clear();
  1298 + vn_list.clear();
  1299 + vt_list.clear();
  1300 + primitives.clear();
  1301 +}
  1302 +
  1303 +/*GLOBAL FUNCTION DEFINITIONS*/
  1304 +//initialize the OBJ file
  1305 +OBJint objOpen(char* filename)
  1306 +{
  1307 + return g_OBJ.objOpen(filename);
  1308 +}
  1309 +//close the obj file
  1310 +OBJint objClose()
  1311 +{
  1312 + return g_OBJ.objClose();
  1313 +}
  1314 +
  1315 +//start rendering in a certain mode
  1316 +OBJint objBegin(OBJint mode)
  1317 +{
  1318 + return g_OBJ.objBegin(mode);
  1319 +}
  1320 +//stop the current rendering sequence
  1321 +OBJint objEnd(void)
  1322 +{
  1323 + return g_OBJ.objEnd();
  1324 +}
  1325 +//render a vertex to the file
  1326 +OBJint objVertex1f(float x)
  1327 +{
  1328 + return g_OBJ.objVertex1f(x);
  1329 +}
  1330 +
  1331 +OBJint objVertex2f(float x, float y)
  1332 +{
  1333 + return g_OBJ.objVertex2f(x, y);
  1334 +}
  1335 +
  1336 +OBJint objVertex3f(float x, float y, float z)
  1337 +{
  1338 + return g_OBJ.objVertex3f(x, y, z);
  1339 +}
  1340 +
  1341 +OBJint objVertex4f(float x, float y, float z, float w)
  1342 +{
  1343 + return g_OBJ.objVertex4f(x, y, z, w);
  1344 +}
  1345 +//set a normal vector for a vertex
  1346 +OBJint objNormal3f(float i, float j, float k)
  1347 +{
  1348 + return g_OBJ.objNormal3f(i, j, k);
  1349 +}
  1350 +OBJint objNormal2f(float i, float j)
  1351 +{
  1352 + return g_OBJ.objNormal2f(i, j);
  1353 +}
  1354 +OBJint objNormal1f(float i)
  1355 +{
  1356 + return g_OBJ.objNormal1f(i);
  1357 +}
  1358 +//set a texture coordinate for a vertex
  1359 +OBJint objTexCoord3f(float u, float v, float w)
  1360 +{
  1361 + return g_OBJ.objTexCoord3f(u, v, w);
  1362 +}
  1363 +
  1364 +OBJint objTexCoord2f(float u, float v)
  1365 +{
  1366 + return g_OBJ.objTexCoord2f(u,v);
  1367 +}
  1368 +
  1369 +OBJint objTexCoord1f(float u)
  1370 +{
  1371 + return g_OBJ.objTexCoord1f(u);
  1372 +}
  1373 +
  1374 +OBJint rtsOBJ::f_ReadPosition(ifstream &infile)
  1375 +{
  1376 + vertex_position new_vertex;
  1377 + //get each coordinate
  1378 + infile>>new_vertex.x;
  1379 + new_vertex.mask = OBJ_V_X;
  1380 +
  1381 + if(infile.peek() == ' ')
  1382 + {
  1383 + infile>>new_vertex.y;
  1384 + new_vertex.mask = new_vertex.mask | OBJ_V_Y;
  1385 + }
  1386 + if(infile.peek() == ' ')
  1387 + {
  1388 + infile>>new_vertex.z;
  1389 + new_vertex.mask = new_vertex.mask | OBJ_V_Z;
  1390 + }
  1391 + if(infile.peek() == ' ')
  1392 + {
  1393 + infile>>new_vertex.w;
  1394 + new_vertex.mask = new_vertex.mask | OBJ_V_W;
  1395 + }
  1396 + int c = infile.peek();
  1397 + //ignore the rest of the line
  1398 + infile.ignore(1000, '\n');
  1399 + c = infile.peek();
  1400 +
  1401 + //cout<<"vertex read: "<<new_vertex.x<<","<<new_vertex.y<<","<<new_vertex.z<<","<<new_vertex.w<<endl;
  1402 + //insert the vertex into the list
  1403 + v_list.push_back(new_vertex);
  1404 +
  1405 + //adjust the extents of the model
  1406 + f_AdjustExtents(new_vertex);
  1407 +
  1408 + return OBJ_OK;
  1409 +}
  1410 +
  1411 +OBJint rtsOBJ::f_ReadNormal(ifstream &infile)
  1412 +{
  1413 + vertex_normal new_normal;
  1414 + infile>>new_normal.i;
  1415 + new_normal.mask = OBJ_VN_I;
  1416 + //get every other component
  1417 + if(infile.peek() == ' ')
  1418 + {
  1419 + infile>>new_normal.j;
  1420 + new_normal.mask = new_normal.mask | OBJ_VN_J;
  1421 + }
  1422 + if(infile.peek() == ' ')
  1423 + {
  1424 + infile>>new_normal.k;
  1425 + new_normal.mask = new_normal.mask | OBJ_VN_K;
  1426 + }
  1427 + //ignore the rest of the line
  1428 + infile.ignore(1000, '\n');
  1429 + //insert the normal
  1430 + vn_list.push_back(new_normal);
  1431 +
  1432 + return OBJ_OK;
  1433 +}
  1434 +
  1435 +OBJint rtsOBJ::f_ReadTexCoord(ifstream &infile)
  1436 +{
  1437 + vertex_texture new_texcoord;
  1438 + infile>>new_texcoord.u;
  1439 + new_texcoord.mask = OBJ_VT_U;
  1440 + //get every other component
  1441 + if(infile.peek() == ' ')
  1442 + {
  1443 + infile>>new_texcoord.v;
  1444 + new_texcoord.mask = new_texcoord.mask | OBJ_VT_V;
  1445 + }
  1446 + if(infile.peek() == ' ')
  1447 + {
  1448 + infile>>new_texcoord.w;
  1449 + new_texcoord.mask = new_texcoord.mask | OBJ_VT_W;
  1450 + }
  1451 +
  1452 + //ignore the rest of the line
  1453 + infile.ignore(1000, '\n');
  1454 + //insert the texture coordinate
  1455 + vt_list.push_back(new_texcoord);
  1456 +
  1457 + return OBJ_OK;
  1458 +
  1459 +}
  1460 +
  1461 +OBJint rtsOBJ::f_ReadVertex(ifstream &infile, vertex &new_point, unsigned char &mask)
  1462 +{
  1463 + //store the line vertex
  1464 + infile>>new_point.v;
  1465 + new_point.v--;
  1466 + mask = OBJ_V;
  1467 + //new_face.v.push_back(new_v - 1);
  1468 + if(infile.peek() == '/')
  1469 + {
  1470 + infile.get();
  1471 + //if there actually is a texcoord
  1472 + if(infile.peek() != '/')
  1473 + {
  1474 + infile>>new_point.vt; //get the index
  1475 + new_point.vt--;
  1476 + mask = mask | OBJ_VT; //update the mask
  1477 + //new_face.vt.push_back(new_vt - 1);
  1478 + }
  1479 + }
  1480 + //check for a normal
  1481 + if(infile.peek() == '/')
  1482 + {
  1483 + infile.get();
  1484 + infile>>new_point.vn; //get the index
  1485 + new_point.vn--;
  1486 + mask = mask | OBJ_VN; //update the mask
  1487 + }
  1488 +
  1489 + return OBJ_OK;
  1490 +}
  1491 +
  1492 +OBJint rtsOBJ::f_ReadPrimitive(ifstream &infile, primitive_type type)
  1493 +{
  1494 + //create a new point list
  1495 + primitive new_primitive;
  1496 + new_primitive.type = type;
  1497 + //until the end of the line
  1498 + while(infile.peek() != '\n')
  1499 + {
  1500 + //read each point
  1501 + if(infile.peek() == ' ')
  1502 + infile.get();
  1503 + else
  1504 + {
  1505 + vertex new_point;
  1506 + f_ReadVertex(infile, new_point, new_primitive.mask);
  1507 + new_primitive.p.push_back(new_point);
  1508 + }
  1509 + }
  1510 + //ignore the rest of the line
  1511 + infile.ignore(1000, '\n');
  1512 +
  1513 + //push the id of the primitive into the new list
  1514 + //:DEBUG:
  1515 + if(type == OBJ_POINTS)
  1516 + points.push_back(primitives.size());
  1517 + else if(type == OBJ_LINES)
  1518 + lines.push_back(primitives.size());
  1519 + else if(type == OBJ_FACE)
  1520 + faces.push_back(primitives.size());
  1521 +
  1522 + primitives.push_back(new_primitive); //push the new primitive
  1523 +
  1524 + return OBJ_OK;
  1525 +}
  1526 +
  1527 +
  1528 +OBJint rtsOBJ::f_AdjustExtents(vertex_position v)
  1529 +{
  1530 + if(v.x < m_bounds.min.x)
  1531 + m_bounds.min.x = v.x;
  1532 + if(v.y < m_bounds.min.y)
  1533 + m_bounds.min.y = v.y;
  1534 + if(v.z < m_bounds.min.z)
  1535 + m_bounds.min.z = v.z;
  1536 +
  1537 + if(v.x > m_bounds.max.x) m_bounds.max.x = v.x;
  1538 + if(v.y > m_bounds.max.y) m_bounds.max.y = v.y;
  1539 + if(v.z > m_bounds.max.z) m_bounds.max.z = v.z;
  1540 +
  1541 + return OBJ_OK;
  1542 +}
  1543 +
  1544 +OBJint rtsOBJ::f_LoadOBJ(const char* filename)
  1545 +{
  1546 + f_ClearAll();
  1547 + //open the file as a stream
  1548 + ifstream infile;
  1549 + infile.open(filename);
  1550 + if(!infile)
  1551 + exit(1);
  1552 +
  1553 + unsigned int vertices = 0;
  1554 +
  1555 + string token;
  1556 + infile>>token;
  1557 + while(!infile.eof())
  1558 + {
  1559 + //if the token is some vertex property
  1560 + if(token == "v")
  1561 + f_ReadPosition(infile);
  1562 + else if(token == "vn")
  1563 + f_ReadNormal(infile);
  1564 + else if(token == "vt")
  1565 + f_ReadTexCoord(infile);
  1566 + else if(token == "p")
  1567 + f_ReadPrimitive(infile, OBJ_POINTS);
  1568 + else if(token == "l")
  1569 + f_ReadPrimitive(infile, OBJ_LINES);
  1570 + else if(token == "f")
  1571 + f_ReadPrimitive(infile, OBJ_FACE);
  1572 + else
  1573 + infile.ignore(9999, '\n');
  1574 + //vertices++;
  1575 +
  1576 + infile>>token;
  1577 + }
  1578 +
  1579 +}
  1580 +
  1581 +OBJint rtsOBJ::f_LoadSWC(const char* filename)
  1582 +{
  1583 + f_ClearAll();
  1584 + //open the file as a stream
  1585 + ifstream infile;
  1586 + infile.open(filename);
  1587 + if(!infile.is_open())
  1588 + return OBJ_ERROR;
  1589 +
  1590 + vector<vertex_position> swcVertices;
  1591 + float token;
  1592 + objBegin(OBJ_LINES);
  1593 + while(!infile.eof())
  1594 + {
  1595 + vertex_position v;
  1596 + infile>>token; //get the id
  1597 + infile>>token; //get the fiber type
  1598 + infile>>v.x; //get the node position
  1599 + infile>>v.y;
  1600 + infile>>v.z;
  1601 + infile>>token; //get the radius
  1602 + infile>>token; //get the parent
  1603 +
  1604 + //insert the node into the swc vector
  1605 + swcVertices.push_back(v);
  1606 + //now draw the line from the parent to the current node
  1607 + if(token != -1)
  1608 + {
  1609 + unsigned int i = (unsigned int)token - 1;
  1610 + objVertex3f(swcVertices[i].x, swcVertices[i].y, swcVertices[i].z);
  1611 + objVertex3f(v.x, v.y, v.z);
  1612 + }
  1613 + }
  1614 + objEnd();
  1615 +
  1616 +
  1617 + return OBJ_OK;
  1618 +
  1619 +}
  1620 +OBJint rtsOBJ::LoadFile(const char* filename)
  1621 +{
  1622 + string strFilename = filename;
  1623 + int length = strFilename.length();
  1624 + string extension = strFilename.substr(strFilename.length() - 3, 3);
  1625 + if(!extension.compare(string("obj")))
  1626 + return f_LoadOBJ(filename);
  1627 + else if(!extension.compare(string("swc")))
  1628 + return f_LoadSWC(filename);
  1629 + else return f_LoadOBJ(filename);
  1630 +
  1631 +}
  1632 +
  1633 +OBJint rtsOBJ::SaveFile(const char* filename)
  1634 +{
  1635 + //open the file as a stream
  1636 + ofstream outfile;
  1637 + outfile.open(filename);
  1638 + if(!outfile.is_open())
  1639 + return OBJ_ERROR;
  1640 +
  1641 + //output vertex positions
  1642 + vector<vertex_position>::iterator v;
  1643 + for(v=v_list.begin(); v!= v_list.end(); v++)
  1644 + {
  1645 + outfile<<"v";
  1646 + if((*v).mask & OBJ_V_X)
  1647 + {
  1648 + outfile<<' '<<(*v).x;
  1649 + if((*v).mask & OBJ_V_Y)
  1650 + {
  1651 + outfile<<' '<<(*v).y;
  1652 + if((*v).mask & OBJ_V_Z)
  1653 + {
  1654 + outfile<<' '<<(*v).z;
  1655 + if((*v).mask & OBJ_V_W)
  1656 + outfile<<' '<<(*v).w;
  1657 + }
  1658 + }
  1659 + }
  1660 + outfile<<'\n';
  1661 + }
  1662 +
  1663 + //output vertex texture coordinates
  1664 + vector<vertex_texture>::iterator vt;
  1665 + for(vt=vt_list.begin(); vt!= vt_list.end(); vt++)
  1666 + {
  1667 + outfile<<"vt";
  1668 + if((*vt).mask & OBJ_VT_U)
  1669 + {
  1670 + outfile<<' '<<(*vt).u;
  1671 + if((*vt).mask & OBJ_VT_V)
  1672 + {
  1673 + outfile<<' '<<(*vt).v;
  1674 + if((*vt).mask & OBJ_VT_W)
  1675 + outfile<<' '<<(*vt).w;
  1676 + }
  1677 + }
  1678 + outfile<<'\n';
  1679 + }
  1680 +
  1681 + //output vertex normal coordinates
  1682 + vector<vertex_normal>::iterator vn;
  1683 + for(vn=vn_list.begin(); vn!= vn_list.end(); vn++)
  1684 + {
  1685 + outfile<<"vn";
  1686 + if((*vn).mask & OBJ_VN_I)
  1687 + {
  1688 + outfile<<' '<<(*vn).i;
  1689 + if((*vn).mask & OBJ_VN_J)
  1690 + {
  1691 + outfile<<' '<<(*vn).j;
  1692 + if((*vn).mask & OBJ_VN_K)
  1693 + outfile<<' '<<(*vn).k;
  1694 + }
  1695 + }
  1696 + outfile<<'\n';
  1697 + }
  1698 +
  1699 + //output each primitive
  1700 + vector<primitive>::iterator p;
  1701 + vector<vertex>::iterator vert;
  1702 + for(p=primitives.begin(); p!= primitives.end(); p++)
  1703 + {
  1704 + switch((*p).type)
  1705 + {
  1706 + case OBJ_POINTS:
  1707 + outfile<<"p"; //output the points token
  1708 + break;
  1709 + case OBJ_LINES:
  1710 + outfile<<"l"; //output the lines token
  1711 + break;
  1712 + case OBJ_FACE:
  1713 + outfile<<"f"; //output the face token
  1714 + break;
  1715 + }
  1716 +
  1717 + //for each vertex in the list for the primitive
  1718 + for(vert = (*p).p.begin(); vert != (*p).p.end(); vert++)
  1719 + {
  1720 + outfile<<' '<<(*vert).v + 1;
  1721 + if((*p).mask & OBJ_VT)
  1722 + outfile<<'/'<<(*vert).vt + 1;
  1723 + if((*p).mask & OBJ_VN)
  1724 + {
  1725 + if(!((*p).mask & OBJ_VT))
  1726 + outfile<<'/';
  1727 + outfile<<'/'<<(*vert).vn + 1;
  1728 + }
  1729 + }
  1730 + outfile<<'\n';
  1731 +
  1732 + }
  1733 +
  1734 +
  1735 +
  1736 +}
  1737 +
  1738 +//get methods
  1739 +unsigned int rtsOBJ::getNumVertices(){return v_list.size();}
  1740 +unsigned int rtsOBJ::getNumLines(){return lines.size();}
  1741 +unsigned int rtsOBJ::getNumFaces(){return faces.size();}
  1742 +unsigned int rtsOBJ::getNumPointLists(){return points.size();}
  1743 +unsigned int rtsOBJ::getNumTexCoords(){return vt_list.size();}
  1744 +unsigned int rtsOBJ::getNumNormals(){return vn_list.size();}
  1745 +
  1746 +//these functions return the coordinate index as well as the value
  1747 +unsigned int rtsOBJ::getNumFaceVertices(unsigned int face){return primitives[face].p.size();}
  1748 +unsigned int rtsOBJ::getFaceVertex(unsigned int face, unsigned int vertex){return primitives[face].p[vertex].v;}
  1749 +unsigned int rtsOBJ::getFaceNormal(unsigned int face, unsigned int normal){return primitives[face].p[normal].vn;}
  1750 +unsigned int rtsOBJ::getFaceTexCoord(unsigned int face, unsigned int texcoord){return primitives[face].p[texcoord].vt;}
  1751 +unsigned int rtsOBJ::getNumLineVertices(unsigned int line){return primitives[line].p.size();}
  1752 +unsigned int rtsOBJ::getLineVertex(unsigned int line, unsigned int vertex){return primitives[line].p[vertex].v;}
  1753 +unsigned int rtsOBJ::getLineTexCoord(unsigned int line, unsigned int texcoord){return primitives[line].p[texcoord].vt;}
  1754 +point3D<float> rtsOBJ::getVertex3d(unsigned int index)
  1755 +{
  1756 + return point3D<float>(v_list[index].x, v_list[index].y, v_list[index].z);
  1757 +}
  1758 +point3D<float> rtsOBJ::getTexCoord3d(unsigned int index)
  1759 +{
  1760 + return point3D<float>(vt_list[index].u, vt_list[index].v, vt_list[index].w);
  1761 +}
  1762 +point3D<float> rtsOBJ::getNormal3d(unsigned int index)
  1763 +{
  1764 + return point3D<float>(vn_list[index].i, vn_list[index].j, vn_list[index].k);
  1765 +}
  1766 +vertex_position rtsOBJ::getVertex(unsigned int index){return v_list[index];}
  1767 +vertex_texture rtsOBJ::getTexCoord(unsigned int index){return vt_list[index];}
  1768 +vertex_normal rtsOBJ::getNormal(unsigned int index){return vn_list[index];}
  1769 +
  1770 +
  1771 +unsigned int rtsOBJ::getPrimitiveType(unsigned int primitive)
  1772 +{
  1773 + /*
  1774 + switch(primitives[i].type)
  1775 + {
  1776 + case OBJ_POINTS:
  1777 + return OBJ_POINTS;
  1778 + break;
  1779 + case OBJ_LINES:
  1780 + return OBJ_LINES;
  1781 + break;
  1782 + case OBJ_FACE:
  1783 + f_RenderFace(i);
  1784 + break;
  1785 + }*/
  1786 + return 0;
  1787 +}
  1788 +/****************************************************/
  1789 +/*******Iterator Methods*****************************/
  1790 +/****************************************************/
  1791 +
  1792 +rtsOBJ::iterator rtsOBJ::begin()
  1793 +{
  1794 + //create an iterator that will be returned and assign it to this OBJ
  1795 + iterator result;
  1796 + result.obj = this;
  1797 + result.end_object = false;
  1798 + result.end_primitive = false;
  1799 +
  1800 + //if there are no primitives, return the end iterator
  1801 + if(primitives.size() == 0)
  1802 + return end();
  1803 +
  1804 + //start at the beginning of the primitive array
  1805 + result.primitive_index = 0;
  1806 +
  1807 + return result;
  1808 +}
  1809 +
  1810 +rtsOBJ::iterator rtsOBJ::end()
  1811 +{
  1812 + //create an end iterator to return
  1813 + iterator result;
  1814 + result.obj = this;
  1815 + result.end_primitive = true;
  1816 + result.primitive_index = result.obj->primitives.size();
  1817 +
  1818 + return result;
  1819 +}
  1820 +
  1821 +void rtsOBJ::iterator::operator++()
  1822 +{
  1823 + primitive_index++;
  1824 + if(primitive_index >= obj->primitives.size())
  1825 + (*this) = obj->end();
  1826 +
  1827 +}
  1828 +
  1829 +bool rtsOBJ::iterator::operator ==(rtsOBJ::iterator operand)
  1830 +{
  1831 + if(operand.primitive_index == primitive_index)
  1832 + return true;
  1833 + else return false;
  1834 +}
  1835 +
  1836 +bool rtsOBJ::iterator::operator !=(rtsOBJ::iterator operand)
  1837 +{
  1838 + if(operand.primitive_index != primitive_index)
  1839 + return true;
  1840 + else return false;
  1841 +}
  1842 +
  1843 +unsigned int rtsOBJ::iterator::operator*()
  1844 +{
  1845 + return primitive_index;
  1846 +}
  1847 +
  1848 +void rtsOBJ::iterator::print()
  1849 +{
  1850 + cout<<"This is a test"<<endl;
  1851 +}
  1852 +
  1853 +
  1854 +
  1855 +
  1856 +#endif
... ...
rect.h 0 → 100644
  1 +++ a/rect.h
... ...
rts/cuda_callable.h 0 → 100644
  1 +++ a/rts/cuda_callable.h
  1 +#ifndef CUDA_CALLABLE
  2 +
  3 +//define the CUDA_CALLABLE macro (will prefix all members)
  4 +#ifdef __CUDACC__
  5 +#define CUDA_CALLABLE __host__ __device__
  6 +#else
  7 +#define CUDA_CALLABLE
  8 +#endif
  9 +
  10 +#endif
... ...
rts/cuda_handle_error.h 0 → 100644
  1 +++ a/rts/cuda_handle_error.h
  1 +#include <stdio.h>
  2 +#include "cuda_runtime.h"
  3 +#include "device_launch_parameters.h"
  4 +
  5 +#ifndef CUDA_HANDLE_ERROR_H
  6 +#define CUDA_HANDLE_ERROR_H
  7 +
  8 +//handle error macro
  9 +static void HandleError( cudaError_t err, const char *file, int line ) {
  10 + if (err != cudaSuccess) {
  11 + //FILE* outfile = fopen("cudaErrorLog.txt", "w");
  12 + //fprintf(outfile, "%s in %s at line %d\n", cudaGetErrorString( err ), file, line );
  13 + //fclose(outfile);
  14 + printf("%s in %s at line %d\n", cudaGetErrorString( err ), file, line );
  15 + //exit( EXIT_FAILURE );
  16 +
  17 + }
  18 +}
  19 +#define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))
  20 +
  21 +
  22 +
  23 +#endif
... ...
rts/cuda_timer.h 0 → 100644
  1 +++ a/rts/cuda_timer.h
  1 +static cudaEvent_t tStartEvent;
  2 +static cudaEvent_t tStopEvent;
  3 +
  4 +static void gpuStartTimer()
  5 +{
  6 + //set up timing events
  7 + cudaEventCreate(&tStartEvent);
  8 + cudaEventCreate(&tStopEvent);
  9 + cudaEventRecord(tStartEvent, 0);
  10 +}
  11 +
  12 +static float gpuStopTimer()
  13 +{
  14 + cudaEventRecord(tStopEvent, 0);
  15 + cudaEventSynchronize(tStopEvent);
  16 + float elapsedTime;
  17 + cudaEventElapsedTime(&elapsedTime, tStartEvent, tStopEvent);
  18 + cudaEventDestroy(tStartEvent);
  19 + cudaEventDestroy(tStopEvent);
  20 + return elapsedTime;
  21 +}
0 22 \ No newline at end of file
... ...
rts/legendre.h 0 → 100644
  1 +++ a/rts/legendre.h
  1 +#ifndef RTS_LEGENDRE_H
  2 +#define RTS_LEGENDRE_H
  3 +
  4 +#include "rts/cuda_callable.h"
  5 +
  6 +namespace rts{
  7 +
  8 +template <typename T>
  9 +CUDA_CALLABLE void init_legendre(T x, T& P0, T& P1)
  10 +{
  11 + //compute the first two Legendre polynomials
  12 + P0 = 1;
  13 + P1 = x;
  14 +}
  15 +
  16 +template <typename T>
  17 +CUDA_CALLABLE void shift_legendre(int n, T x, T& P0, T& P1)
  18 +{
  19 + //compute the next (order n) Legendre polynomial
  20 + T Pnew = ( (2 * n - 1) * x * P1 - (n-1) * P0 ) / n;
  21 +
  22 + //shift and add the new value to the array
  23 + P0 = P1;
  24 + P1 = Pnew;
  25 +}
  26 +
  27 +template <typename T>
  28 +CUDA_CALLABLE void legendre(int n, T x, T* P)
  29 +{
  30 + P[0] = 1;
  31 +
  32 + if(n >= 1)
  33 + P[1] = x;
  34 +
  35 + for(int i=2; i<=n; i++)
  36 + {
  37 + P[i] = ( (2 * i - 1) * x * P[i-1] - (i-1) * P[i-2] ) / i;
  38 + }
  39 +
  40 +}
  41 +
  42 +}
  43 +
  44 +
  45 +#endif
... ...
rts/material.h 0 → 100644
  1 +++ a/rts/material.h
  1 +#ifndef MATERIALSTRUCT_H
  2 +#define MATERIALSTRUCT_H
  3 +
  4 +#include <vector>
  5 +#include <ostream>
  6 +#include <iostream>
  7 +#include <fstream>
  8 +#include <complex>
  9 +#include <algorithm>
  10 +#include <sstream>
  11 +#include "rts/rtcomplex.h"
  12 +
  13 +#define PI 3.14159
  14 +
  15 +namespace rts{
  16 +
  17 + enum field_type {field_microns, field_wavenumber, field_n, field_k, field_A, field_ignore};
  18 +
  19 + //conversion functions
  20 +
  21 + //convert wavenumber to lambda
  22 + template <class T>
  23 + static T _wn(T inverse_cm)
  24 + {
  25 + return (T)10000.0/inverse_cm;
  26 + }
  27 +
  28 + template <class T>
  29 + static T _2wn(T lambda)
  30 + {
  31 + return (T)10000.0/lambda;
  32 + }
  33 +
  34 + //convert absorbance to k
  35 + template <class T>
  36 + static T _A(T absorbance, T lambda)
  37 + {
  38 + return (absorbance * lambda) / (4 * PI);
  39 + }
  40 + template <class T>
  41 + static T _2A(T k, T lambda)
  42 + {
  43 + return (4 * PI * k)/lambda;
  44 + }
  45 +
  46 + //define the dispersion as a single wavelength/refractive index pair
  47 + template <class T>
  48 + struct refIndex
  49 + {
  50 + //wavelength (in microns)
  51 + T lambda;
  52 + rtcomplex<T> n;
  53 + };
  54 +
  55 + template <class T>
  56 + struct entryType
  57 + {
  58 + //list of value types per entry
  59 + std::vector<field_type> valueList;
  60 +
  61 + entryType(std::string format)
  62 + {
  63 + //location of the end of a parameter
  64 + size_t e;
  65 +
  66 + //string storing a token
  67 + std::string token;
  68 +
  69 + do
  70 + {
  71 + //find the end of the first parameter
  72 + e = format.find_first_of(',');
  73 +
  74 + //get the substring up to the comma
  75 + token = format.substr(0, e);
  76 +
  77 + //turn the token into a val_type
  78 + if(token == "microns")
  79 + valueList.push_back(field_microns);
  80 + else if(token == "wavenumber")
  81 + valueList.push_back(field_wavenumber);
  82 + else if(token == "n")
  83 + valueList.push_back(field_n);
  84 + else if(token == "k")
  85 + valueList.push_back(field_k);
  86 + else if(token == "A")
  87 + valueList.push_back(field_A);
  88 + else
  89 + valueList.push_back(field_ignore);
  90 +
  91 + //remove the first token from the format string
  92 + format = format.substr(e+1, format.length()-1);
  93 + }while(e != std::string::npos);
  94 +
  95 +
  96 +
  97 + }
  98 +
  99 + void addValue(field_type value)
  100 + {
  101 + valueList.push_back(value);
  102 + }
  103 +
  104 + refIndex<T> inputEntry(std::string line, T scaleA = 1.0)
  105 + {
  106 + T val;
  107 + std::stringstream ss(line);
  108 +
  109 + //create a new refractive index
  110 + refIndex<T> newRI;
  111 +
  112 +
  113 + //read the entry from an input string
  114 + for(int i=0; i<valueList.size(); i++)
  115 + {
  116 + //retrieve the value
  117 + ss>>val;
  118 +
  119 + //store the value in the appropriate location
  120 + switch(valueList[i])
  121 + {
  122 + case field_microns:
  123 + newRI.lambda = val;
  124 + break;
  125 + case field_wavenumber:
  126 + newRI.lambda = _wn(val);
  127 + break;
  128 + case field_n:
  129 + newRI.n.real(val);
  130 + break;
  131 + case field_k:
  132 + newRI.n.imag(val);
  133 + break;
  134 + case field_A:
  135 + newRI.n.imag(_A(val * scaleA, newRI.lambda));
  136 + break;
  137 + }
  138 + }
  139 +
  140 + //return the refractive index associated with the entry
  141 + return newRI;
  142 +
  143 + }
  144 +
  145 + std::string outputEntry(refIndex<T> material)
  146 + {
  147 + //std::string result;
  148 + std::stringstream ss;
  149 +
  150 + //for each field in the entry
  151 + for(int i=0; i<valueList.size(); i++)
  152 + {
  153 + if(i > 0)
  154 + ss<<"\t";
  155 + //store the value in the appropriate location
  156 + switch(valueList[i])
  157 + {
  158 + case field_microns:
  159 + ss<<material.lambda;
  160 + break;
  161 + case field_wavenumber:
  162 + ss<<_2wn(material.lambda);
  163 + break;
  164 + case field_n:
  165 + ss<<material.n.real();
  166 + break;
  167 + case field_k:
  168 + ss<<material.n.imag();
  169 + break;
  170 + case field_A:
  171 + ss<<_2A(material.n.imag(), material.lambda);
  172 + break;
  173 + }
  174 +
  175 + }
  176 + return ss.str();
  177 + }
  178 +
  179 +
  180 + };
  181 +
  182 +
  183 + //a material is a list of refractive index values
  184 + template <class T>
  185 + class material
  186 + {
  187 + //dispersion (refractive index as a function of wavelength)
  188 + std::vector< refIndex<T> > dispersion;
  189 +
  190 + //average refractive index (approximately 1.4)
  191 + T n0;
  192 +
  193 + void add(refIndex<T> ri)
  194 + {
  195 + //refIndex<T> converted = convert(ri, measurement);
  196 + dispersion.push_back(ri);
  197 + }
  198 +
  199 + //comparison function for sorting
  200 + static bool compare(refIndex<T> a, refIndex<T> b)
  201 + {
  202 + return (a.lambda < b.lambda);
  203 + }
  204 +
  205 + //comparison function for searching lambda
  206 + static bool findCeiling(refIndex<T> a, refIndex<T> b)
  207 + {
  208 + return (a.lambda > b.lambda);
  209 + }
  210 +
  211 + public:
  212 +
  213 + unsigned int nSamples()
  214 + {
  215 + return dispersion.size();
  216 + }
  217 + material<T> computeN(T _n0, unsigned int n_samples = 0, T pf = 2)
  218 + {
  219 + /* This function computes the real part of the refractive index
  220 + from the imaginary part. The Hilbert transform is required. I
  221 + use an FFT in order to simplify this, so either the FFTW or CUFFT
  222 + packages are required. CUFFT is used if this file is passed through
  223 + a CUDA compiler. Otherwise, FFTW is used if available.
  224 + */
  225 +
  226 + n0 = _n0;
  227 +
  228 + int N;
  229 + if(n_samples)
  230 + N = n_samples;
  231 + else
  232 + N = dispersion.size();
  233 +
  234 +
  235 +#ifdef FFTW_AVAILABLE
  236 + //allocate memory for the FFT
  237 + rtcomplex<T>* Chi2 = (rtcomplex<T>*)fftw_malloc(sizeof(rtcomplex<T>) * N * pf);
  238 + rtcomplex<T>* Chi2FFT = (rtcomplex<T>*)fftw_malloc(sizeof(rtcomplex<T>) * N * pf);
  239 + rtcomplex<T>* Chi1 = (rtcomplex<T>*)fftw_malloc(sizeof(rtcomplex<T>) * N * pf);
  240 +
  241 + //create an FFT plan for the forward and inverse transforms
  242 + fftw_plan planForward, planInverse;
  243 + planForward = fftw_plan_dft_1d(N*pf, (fftw_complex*)Chi2, (fftw_complex*)Chi2FFT, FFTW_FORWARD, FFTW_ESTIMATE);
  244 + planInverse = fftw_plan_dft_1d(N*pf, (fftw_complex*)Chi2FFT, (fftw_complex*)Chi1, FFTW_BACKWARD, FFTW_ESTIMATE);
  245 +
  246 + float k, alpha;
  247 + T chi_temp;
  248 +
  249 + //the spectrum will be re-sampled in uniform values of wavenumber
  250 + T nuMin = _2wn(dispersion.back().lambda);
  251 + T nuMax = _2wn(dispersion.front().lambda);
  252 + T dnu = (nuMax - nuMin)/(N-1);
  253 + T lambda, tlambda;
  254 + for(int i=0; i<N; i++)
  255 + {
  256 + //go from back-to-front (wavenumber is the inverse of wavelength)
  257 + lambda = _wn(nuMax - i * dnu);
  258 +
  259 + //compute the frequency
  260 + k = 2 * PI / (lambda);
  261 +
  262 + //get the absorbance
  263 + alpha = getN(lambda).imag() * (2 * k);
  264 +
  265 + //compute chi2
  266 + Chi2[i] = -alpha * (n0 / k);
  267 + }
  268 +
  269 + //use linear interpolation between the start and end points to pad the spectrum
  270 + //rtcomplex<T> nMin = dispersion.back();
  271 + //rtcomplex<T> nMax = dispersion.front();
  272 + T a;
  273 + for(int i=N; i<N*pf; i++)
  274 + {
  275 + //a = (T)(i-N)/(T)(N*pf - N);
  276 + //Chi2[i] = a * Chi2[0] + ((T)1 - a) * Chi2[N-1];
  277 +
  278 + Chi2[i] = 0.0;//Chi2[N-1];
  279 + }
  280 +
  281 + //perform the FFT
  282 + fftw_execute(planForward);
  283 +
  284 + //perform the Hilbert transform in the Fourier domain
  285 + rtcomplex<T> j(0, 1);
  286 + for(int i=0; i<N*pf; i++)
  287 + {
  288 + //if w = 0, set the DC component to zero
  289 + if(i == 0)
  290 + Chi2FFT[i] *= (T)0.0;
  291 + //if w <0, multiply by i
  292 + else if(i < N*pf/2.0)
  293 + Chi2FFT[i] *= j;
  294 + //if i > N/2, multiply by -i
  295 + else
  296 + Chi2FFT[i] *= -j;
  297 + }
  298 +
  299 + //execute the inverse Fourier transform (completing the Hilbert transform)
  300 + fftw_execute(planInverse);
  301 +
  302 + //divide the Chi1 values by N
  303 + for(int i=0; i<N*pf; i++)
  304 + Chi1[i] /= (T)(N*pf);
  305 +
  306 + //create a new material
  307 + material<T> newM;
  308 + newM.dispersion.clear();
  309 + refIndex<T> ri;
  310 + for(int i=0; i<N; i++)
  311 + {
  312 + ri.lambda = _wn(nuMax - i * dnu);
  313 + ri.n.real(Chi1[i].real() / (2 * n0) + n0);
  314 + ri.n.imag(getN(ri.lambda).imag());
  315 +
  316 + newM.dispersion.push_back(ri);
  317 + }
  318 +
  319 +
  320 + //dispersion[i].n.real(Chi1[i].real() / (2 * n0) + n0);
  321 +
  322 +
  323 + /*//output the Absorbance value
  324 + ofstream outOrig("origN.txt");
  325 + for(int i=0; i<N; i++)
  326 + outOrig<<dispersion[i].lambda<<" "<<dispersion[i].n.real()<<endl;
  327 +
  328 + //output the Chi2 value
  329 + ofstream outChi2("chi2.txt");
  330 + for(int i=0; i<N; i++)
  331 + outChi2<<dispersion[i].lambda<<" "<<Chi2[i].real()<<endl;
  332 +
  333 + //output the Fourier transform
  334 + ofstream outFFT("chi2_FFT.txt");
  335 + for(int i=0; i<N; i++)
  336 + {
  337 + float mag = std::sqrt( std::pow(Chi2FFT[i].real(), 2.0) + std::pow(Chi2FFT[i].imag(), 2.0));
  338 + outFFT<<dispersion[i].lambda<<" "<<mag<<endl;
  339 + }
  340 +
  341 + //output the computed Chi1 value
  342 + ofstream outChi1("chi1.txt");
  343 + for(int i=0; i<N; i++)
  344 + {
  345 + outChi1<<dispersion[i].lambda<<" "<<Chi1[i].real()<<" "<<Chi1[i].imag()<<endl;
  346 + }
  347 +
  348 + ofstream outN("n.txt");
  349 + for(int i=0; i<N; i++)
  350 + outN<<dispersion[i].lambda<<" "<<Chi1[i].real() / (2 * n0) + n0<<endl;*/
  351 +
  352 +
  353 + //de-allocate memory
  354 + fftw_destroy_plan(planForward);
  355 + fftw_destroy_plan(planInverse);
  356 + fftw_free(Chi2);
  357 + fftw_free(Chi2FFT);
  358 + fftw_free(Chi1);
  359 +
  360 + return newM;
  361 +#endif
  362 + return material<T>();
  363 + }
  364 +
  365 + material(T lambda = 1.0, T n = 1.4, T k = 0.0)
  366 + {
  367 + //create a default refractive index
  368 + refIndex<T> def;
  369 + def.lambda = lambda;
  370 + def.n.real(n);
  371 + def.n.imag(k);
  372 + add(def);
  373 +
  374 + //set n0
  375 + n0 = n;
  376 + }
  377 +
  378 + material(std::string filename, std::string format, T scaleA = 1.0)
  379 + {
  380 + fromFile(filename, format);
  381 + }
  382 +
  383 + void fromFile(std::string filename, std::string format, T scaleA = 1.0)
  384 + {
  385 + //clear any previous values
  386 + dispersion.clear();
  387 +
  388 + //load the file into a string
  389 + std::ifstream ifs(filename.c_str());
  390 +
  391 + std::string line;
  392 +
  393 + if(!ifs.is_open())
  394 + {
  395 + std::cout<<"Error: material file not found"<<std::endl;
  396 + exit(1);
  397 + }
  398 +
  399 + //process the file as a string
  400 + std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
  401 + fromStr(instr, format, scaleA);
  402 +
  403 + }
  404 +
  405 + void fromStr(std::string str, std::string format, T scaleA = 1.0)
  406 + {
  407 + //create a string stream to process the input data
  408 + std::stringstream ss(str);
  409 +
  410 + //this string will be read line-by-line (where each line is an entry)
  411 + std::string line;
  412 +
  413 + //create an entry structure (for now just a basic one)
  414 + entryType<T> entry(format);
  415 +
  416 + T lambda, n, k;
  417 + while(!ss.eof())
  418 + {
  419 + //read a line from the string
  420 + getline(ss, line);
  421 +
  422 + //if the line is not a comment, process it
  423 + if(line[0] != '#')
  424 + {
  425 + //load the entry and add it to the dispersion list
  426 + add(entry.inputEntry(line, scaleA));
  427 + }
  428 + //generally have to peek to trigger the eof flag
  429 + ss.peek();
  430 + }
  431 +
  432 + //sort the vector by lambda
  433 + sort(dispersion.begin(), dispersion.end(), &material<T>::compare);
  434 + }
  435 +
  436 + //convert the material to a string
  437 + std::string toStr(std::string format = "microns,n,k")
  438 + {
  439 + std::stringstream ss;
  440 + entryType<T> entry(format);
  441 + for(unsigned int l=0; l<dispersion.size(); l++)
  442 + {
  443 + if(l > 0) ss<<std::endl;
  444 + ss<<entry.outputEntry(dispersion[l]);
  445 + }
  446 +
  447 + return ss.str();
  448 + }
  449 +
  450 + void save(std::string filename, std::string format = "microns,n,k")
  451 + {
  452 + ofstream outfile(filename.c_str());
  453 + outfile<<"#material file saved as [" + format + "]"<<std::endl;
  454 + outfile<<toStr(format)<<std::endl;
  455 +
  456 + }
  457 +
  458 + //convert between wavelength and wavenumber
  459 + /*void nu2lambda(T s = (T)1)
  460 + {
  461 + for(int i=0; i<dispersion.size(); i++)
  462 + dispersion[i].lambda = s/dispersion[i].lambda;
  463 + }
  464 +
  465 + void lambda2nu(T s = (T)1)
  466 + {
  467 + for(int i=0; i<dispersion.size(); i++)
  468 + dispersion[i].lambda = s/dispersion[i].lambda;
  469 + }*/
  470 +
  471 +
  472 + refIndex<T>& operator[](unsigned int i)
  473 + {
  474 + return dispersion[i];
  475 +
  476 + }
  477 +
  478 + rtcomplex<T> getN(T l)
  479 + {
  480 + //declare an iterator
  481 + typename std::vector< refIndex<T> >::iterator it;
  482 +
  483 + refIndex<T> r;
  484 + r.lambda = l;
  485 +
  486 + it = search(dispersion.begin(), dispersion.end(), &r, &r + 1, &material<T>::findCeiling);
  487 +
  488 + //if the wavelength is past the end of the list, return the back
  489 + if(it == dispersion.end())
  490 + return dispersion.back().n;
  491 + //if the wavelength is before the beginning of the list, return the front
  492 + else if(it == dispersion.begin())
  493 + return dispersion.front().n;
  494 + //otherwise interpolate
  495 + else
  496 + {
  497 + T lMax = (*it).lambda;
  498 + T lMin = (*(it - 1)).lambda;
  499 + //std::cout<<lMin<<"----------"<<lMax<<std::endl;
  500 +
  501 + T a = (l - lMin) / (lMax - lMin);
  502 + rtcomplex<T> riMin = (*(it - 1)).n;
  503 + rtcomplex<T> riMax = (*it).n;
  504 + rtcomplex<T> interp;
  505 + interp = rtcomplex<T>(a, 0.0) * riMin + rtcomplex<T>(1.0 - a, 0.0) * riMax;
  506 + return interp;
  507 + }
  508 +
  509 + }
  510 + //interpolate the given lambda value and return the index of refraction
  511 + rtcomplex<T> operator()(T l)
  512 + {
  513 + return getN(l);
  514 + }
  515 +
  516 +
  517 + };
  518 +} //end namespace rts
  519 +
  520 +template <typename T>
  521 +std::ostream& operator<<(std::ostream& os, rts::material<T> m)
  522 +{
  523 + os<<m.toStr();
  524 +
  525 + return os;
  526 +}
  527 +
  528 +
  529 +
  530 +#endif
... ...
rts/point.h 0 → 100644
  1 +++ a/rts/point.h
  1 +#ifndef RTS_POINT_H
  2 +#define RTS_POINT_H
  3 +
  4 +//#include "rts/vector.h"
  5 +#include <string.h>
  6 +
  7 +namespace rts
  8 +{
  9 +
  10 +template <class T, int N>
  11 +struct point
  12 +{
  13 + T p[N];
  14 +
  15 + CUDA_CALLABLE point()
  16 + {
  17 +
  18 + }
  19 +
  20 + //efficiency constructor, makes construction easier for 1D-4D vectors
  21 + CUDA_CALLABLE point(T x, T y = (T)0.0, T z = (T)0.0, T w = (T)0.0)
  22 + {
  23 + if(N >= 1)
  24 + p[0] = x;
  25 + if(N >= 2)
  26 + p[1] = y;
  27 + if(N >= 3)
  28 + p[2] = z;
  29 + if(N >= 4)
  30 + p[3] = w;
  31 + }
  32 +
  33 + //arithmetic operators
  34 + CUDA_CALLABLE rts::point<T, N> operator+(rts::vector<T, N> v)
  35 + {
  36 + rts::point<T, N> r;
  37 +
  38 + //calculate the position of the resulting point
  39 + for(int i=0; i<N; i++)
  40 + r.p[i] = p[i] + v.v[i];
  41 +
  42 + return r;
  43 + }
  44 + CUDA_CALLABLE rts::point<T, N> operator-(rts::vector<T, N> v)
  45 + {
  46 + rts::point<T, N> r;
  47 +
  48 + //calculate the position of the resulting point
  49 + for(int i=0; i<N; i++)
  50 + r.p[i] = p[i] - v.v[i];
  51 +
  52 + return r;
  53 + }
  54 + CUDA_CALLABLE rts::vector<T, N> operator-(rts::point<T, N> rhs)
  55 + {
  56 + rts::vector<T, N> r;
  57 +
  58 + //calculate the position of the resulting point
  59 + for(int i=0; i<N; i++)
  60 + r.v[i] = p[i] - rhs.p[i];
  61 +
  62 + return r;
  63 + }
  64 + CUDA_CALLABLE rts::point<T, N> operator*(T rhs)
  65 + {
  66 + rts::point<T, N> r;
  67 +
  68 + //calculate the position of the resulting point
  69 + for(int i=0; i<N; i++)
  70 + r.p[i] = p[i] * rhs;
  71 +
  72 + return r;
  73 + }
  74 +
  75 + CUDA_CALLABLE point(const T(&data)[N])
  76 + {
  77 + memcpy(p, data, sizeof(T) * N);
  78 + }
  79 +
  80 + std::string toStr()
  81 + {
  82 + std::stringstream ss;
  83 +
  84 + ss<<"(";
  85 + for(int i=0; i<N; i++)
  86 + {
  87 + ss<<p[i];
  88 + if(i != N-1)
  89 + ss<<", ";
  90 + }
  91 + ss<<")";
  92 +
  93 + return ss.str();
  94 + }
  95 +
  96 + //bracket operator
  97 + CUDA_CALLABLE T& operator[](int i)
  98 + {
  99 + return p[i];
  100 + }
  101 +
  102 +};
  103 +
  104 +} //end namespace rts
  105 +
  106 +template <typename T, int N>
  107 +std::ostream& operator<<(std::ostream& os, rts::point<T, N> p)
  108 +{
  109 + os<<p.toStr();
  110 + return os;
  111 +}
  112 +
  113 +//arithmetic
  114 +template <typename T, int N>
  115 +CUDA_CALLABLE rts::point<T, N> operator*(T lhs, rts::point<T, N> rhs)
  116 +{
  117 + rts::point<T, N> r;
  118 +
  119 + return rhs * lhs;
  120 +}
  121 +
  122 +
  123 +
  124 +#endif
... ...
rts/rect.h 0 → 100644
  1 +++ a/rts/rect.h
  1 +#ifndef RTS_RECT_H
  2 +#define RTS_RECT_H
  3 +
  4 +//enable CUDA_CALLABLE macro
  5 +#include "rts/cuda_callable.h"
  6 +#include "rts/vector.h"
  7 +#include "rts/point.h"
  8 +#include <iostream>
  9 +
  10 +namespace rts{
  11 +
  12 +//template for a rectangle class in ND space
  13 +template <class T, int N>
  14 +struct rect
  15 +{
  16 + /*
  17 + C------------------>O
  18 + ^ ^
  19 + | |
  20 + Y |
  21 + | |
  22 + | |
  23 + A---------X-------->B
  24 + */
  25 +
  26 + /*T A[N];
  27 + T B[N];
  28 + T C[N];*/
  29 +
  30 + rts::point<T, N> A;
  31 + rts::vector<T, N> X;
  32 + rts::vector<T, N> Y;
  33 +
  34 +
  35 + CUDA_CALLABLE rect()
  36 + {
  37 +
  38 + }
  39 +
  40 + CUDA_CALLABLE rect(point<T, N> a, point<T, N> b, point<T, N> c)
  41 + {
  42 +
  43 + A = a;
  44 + X = b - a;
  45 + Y = c - a;
  46 +
  47 + }
  48 +
  49 + CUDA_CALLABLE rect(rts::point<T, N> pMin, rts::point<T, N> pMax, rts::vector<T, N> normal)
  50 + {
  51 +
  52 + //assign the corner point
  53 + A = pMin;
  54 +
  55 + //compute the vector from pMin to pMax
  56 + rts::vector<T, 3> v0;
  57 + v0 = pMax - pMin;
  58 +
  59 + //compute the cross product of A and the plane normal
  60 + rts::vector<T, 3> v1;
  61 + v1 = v0.cross(normal);
  62 +
  63 +
  64 + //calculate point B
  65 + rts::point<T, 3> B;
  66 + B = A + v0 * 0.5 + v1 * 0.5;
  67 +
  68 + //calculate point C
  69 + rts::point<T, 3> C;
  70 + C = A + v0 * 0.5 - v1 * 0.5;
  71 +
  72 + //calculate X and Y
  73 + X = B - A;
  74 + Y = C - A;
  75 +
  76 +
  77 +
  78 +
  79 + }
  80 +
  81 + /*CUDA_CALLABLE rect(rts::point<T, N> p, rts::vector<T, N> x, rts::vector<T, N> y, T sx, T sy)
  82 + {
  83 + //This constructor creates a rect given a position, orientation, and size
  84 + // p = center position of the rect
  85 + // x = x-axis for the rectangle
  86 + // y = y-axis for the rectangle
  87 + // sx = size of the rect along the A-B axis
  88 + // sy = size of the rect along the A-C axis
  89 +
  90 + //normalize x and y
  91 + rts::vector<T, N> nx = x.norm();
  92 + rts::vector<T, N> ny = y.norm();
  93 +
  94 + //compute X and Y
  95 + X = sx * x;
  96 + Y = sy * y;
  97 +
  98 + //compute A
  99 + A = p - 0.5 * X - 0.5 * Y;
  100 +
  101 + }*/
  102 +
  103 + CUDA_CALLABLE rts::point<T, N> p(T a, T b)
  104 + {
  105 + rts::point<T, N> result;
  106 + //given the two parameters a, b = [0 1], returns the position in world space
  107 + result = A + X * a + Y * b;
  108 +
  109 + return result;
  110 + }
  111 +
  112 + CUDA_CALLABLE rts::point<T, N> operator()(T a, T b)
  113 + {
  114 + return p(a, b);
  115 + }
  116 +
  117 + std::string toStr()
  118 + {
  119 + std::stringstream ss;
  120 +
  121 + ss<<"A = "<<A<<std::endl;
  122 + ss<<"B = "<<A + X<<std::endl;
  123 + ss<<"C = "<<A + X + Y<<std::endl;
  124 + ss<<"D = "<<A + Y<<std::endl;
  125 +
  126 + return ss.str();
  127 +
  128 + }
  129 +};
  130 +
  131 +} //end namespace rts
  132 +
  133 +template <typename T, int N>
  134 +std::ostream& operator<<(std::ostream& os, rts::rect<T, N> R)
  135 +{
  136 + os<<R.toStr();
  137 + return os;
  138 +}
  139 +
  140 +
  141 +#endif
0 142 \ No newline at end of file
... ...
rts/rtcomplex.h 0 → 100644
  1 +++ a/rts/rtcomplex.h
  1 +/*RTS Complex number class. This class is CUDA compatible,
  2 +and can therefore be used in CUDA code and on CUDA devices.
  3 +*/
  4 +
  5 +#ifndef RTS_COMPLEX
  6 +#define RTS_COMPLEX
  7 +
  8 +#include "cuda_callable.h"
  9 +#include <cmath>
  10 +#include <string>
  11 +#include <sstream>
  12 +#include <iostream>
  13 +
  14 +namespace rts
  15 +{
  16 +
  17 +template <class T>
  18 +struct rtcomplex
  19 +{
  20 + T r, i;
  21 +
  22 + //default constructor
  23 + CUDA_CALLABLE rtcomplex()
  24 + {
  25 + r = 0.0;
  26 + i = 0.0;
  27 + }
  28 +
  29 + //access methods
  30 + T real()
  31 + {
  32 + return r;
  33 + }
  34 +
  35 + T real(T r_val)
  36 + {
  37 + r = r_val;
  38 + return r_val;
  39 + }
  40 +
  41 + T imag()
  42 + {
  43 + return i;
  44 + }
  45 + T imag(T i_val)
  46 + {
  47 + i = i_val;
  48 + return i_val;
  49 + }
  50 +
  51 +
  52 +
  53 +
  54 +
  55 + //constructor when given real and imaginary values
  56 + CUDA_CALLABLE rtcomplex(T r, T i)
  57 + {
  58 + this->r = r;
  59 + this->i = i;
  60 + }
  61 +
  62 + //return the current value multiplied by i
  63 + CUDA_CALLABLE rtcomplex<T> imul()
  64 + {
  65 + rtcomplex<T> result;
  66 + result.r = -i;
  67 + result.i = r;
  68 +
  69 + return result;
  70 + }
  71 +
  72 + //ARITHMETIC OPERATORS--------------------
  73 +
  74 + //binary + operator (returns the result of adding two complex values)
  75 + CUDA_CALLABLE rtcomplex<T> operator+ (const rtcomplex<T> rhs)
  76 + {
  77 + rtcomplex<T> result;
  78 + result.r = r + rhs.r;
  79 + result.i = i + rhs.i;
  80 + return result;
  81 + }
  82 +
  83 + CUDA_CALLABLE rtcomplex<T> operator+ (const T rhs)
  84 + {
  85 + rtcomplex<T> result;
  86 + result.r = r + rhs;
  87 + result.i = i;
  88 + return result;
  89 + }
  90 +
  91 + //binary - operator (returns the result of adding two complex values)
  92 + CUDA_CALLABLE rtcomplex<T> operator- (const rtcomplex<T> rhs)
  93 + {
  94 + rtcomplex<T> result;
  95 + result.r = r - rhs.r;
  96 + result.i = i - rhs.i;
  97 + return result;
  98 + }
  99 +
  100 + //binary - operator (returns the result of adding two complex values)
  101 + CUDA_CALLABLE rtcomplex<T> operator- (const T rhs)
  102 + {
  103 + rtcomplex<T> result;
  104 + result.r = r - rhs;
  105 + result.i = i;
  106 + return result;
  107 + }
  108 +
  109 + //binary MULTIPLICATION operators (returns the result of multiplying complex values)
  110 + CUDA_CALLABLE rtcomplex<T> operator* (const rtcomplex<T> rhs)
  111 + {
  112 + rtcomplex<T> result;
  113 + result.r = r * rhs.r - i * rhs.i;
  114 + result.i = r * rhs.i + i * rhs.r;
  115 + return result;
  116 + }
  117 + CUDA_CALLABLE rtcomplex<T> operator* (const T rhs)
  118 + {
  119 + return rtcomplex<T>(r * rhs, i * rhs);
  120 + }
  121 +
  122 + //binary DIVISION operators (returns the result of dividing complex values)
  123 + CUDA_CALLABLE rtcomplex<T> operator/ (const rtcomplex<T> rhs)
  124 + {
  125 + rtcomplex<T> result;
  126 + T denom = rhs.r * rhs.r + rhs.i * rhs.i;
  127 + result.r = (r * rhs.r + i * rhs.i) / denom;
  128 + result.i = (- r * rhs.i + i * rhs.r) / denom;
  129 +
  130 + return result;
  131 + }
  132 + CUDA_CALLABLE rtcomplex<T> operator/ (const T rhs)
  133 + {
  134 + return rtcomplex<T>(r / rhs, i / rhs);
  135 + }
  136 +
  137 + //ASSIGNMENT operators-----------------------------------
  138 + CUDA_CALLABLE rtcomplex<T> & operator=(const rtcomplex<T> &rhs)
  139 + {
  140 + //check for self-assignment
  141 + if(this != &rhs)
  142 + {
  143 + this->r = rhs.r;
  144 + this->i = rhs.i;
  145 + }
  146 + return *this;
  147 + }
  148 + CUDA_CALLABLE rtcomplex<T> & operator=(const T &rhs)
  149 + {
  150 + this->r = rhs;
  151 + this->i = 0;
  152 +
  153 + return *this;
  154 + }
  155 +
  156 + //arithmetic assignment operators
  157 + CUDA_CALLABLE rtcomplex<T> operator+=(const rtcomplex<T> &rhs)
  158 + {
  159 + *this = *this + rhs;
  160 + return *this;
  161 + }
  162 + CUDA_CALLABLE rtcomplex<T> operator+=(const T &rhs)
  163 + {
  164 + *this = *this + rhs;
  165 + return *this;
  166 + }
  167 +
  168 + CUDA_CALLABLE rtcomplex<T> operator*=(const rtcomplex<T> &rhs)
  169 + {
  170 + *this = *this * rhs;
  171 + return *this;
  172 + }
  173 + CUDA_CALLABLE rtcomplex<T> operator*=(const T &rhs)
  174 + {
  175 + *this = *this * rhs;
  176 + return *this;
  177 + }
  178 + //divide and assign
  179 + CUDA_CALLABLE rtcomplex<T> operator/=(const rtcomplex<T> &rhs)
  180 + {
  181 + *this = *this / rhs;
  182 + return *this;
  183 + }
  184 + CUDA_CALLABLE rtcomplex<T> operator/=(const T &rhs)
  185 + {
  186 + *this = *this / rhs;
  187 + return *this;
  188 + }
  189 +
  190 + //absolute value operator (returns the absolute value of the complex number)
  191 + CUDA_CALLABLE T abs()
  192 + {
  193 + return std::sqrt(r * r + i * i);
  194 + }
  195 +
  196 + CUDA_CALLABLE rtcomplex<T> log()
  197 + {
  198 + rtcomplex<T> result;
  199 + result.r = std::log(std::sqrt(r * r + i * i));
  200 + result.i = std::atan2(i, r);
  201 +
  202 +
  203 + return result;
  204 + }
  205 +
  206 + CUDA_CALLABLE rtcomplex<T> exp()
  207 + {
  208 + rtcomplex<T> result;
  209 +
  210 + T e_r = std::exp(r);
  211 + result.r = e_r * std::cos(i);
  212 + result.i = e_r * std::sin(i);
  213 +
  214 + return result;
  215 + }
  216 +
  217 + /*CUDA_CALLABLE complex<T> pow(int y)
  218 + {
  219 +
  220 + return pow((double)y);
  221 + }*/
  222 +
  223 + CUDA_CALLABLE rtcomplex<T> pow(T y)
  224 + {
  225 + rtcomplex<T> result;
  226 +
  227 + result = log() * y;
  228 +
  229 + return result.exp();
  230 + }
  231 +
  232 + CUDA_CALLABLE rtcomplex<T> sqrt()
  233 + {
  234 + rtcomplex<T> result;
  235 +
  236 + //convert to polar coordinates
  237 + T a = std::sqrt(r*r + i*i);
  238 + T theta = std::atan2(i, r);
  239 +
  240 + //find the square root
  241 + T a_p = std::sqrt(a);
  242 + T theta_p = theta/2.0;
  243 +
  244 + //convert back to cartesian coordinates
  245 + result.r = a_p * std::cos(theta_p);
  246 + result.i = a_p * std::sin(theta_p);
  247 +
  248 + return result;
  249 + }
  250 +
  251 + std::string toStr()
  252 + {
  253 + std::stringstream ss;
  254 + ss<<"("<<r<<","<<i<<")";
  255 +
  256 + return ss.str();
  257 + }
  258 +
  259 + //COMPARISON operators
  260 + CUDA_CALLABLE bool operator==(rtcomplex<T> rhs)
  261 + {
  262 + if(r == rhs.r && i == rhs.i)
  263 + return true;
  264 + return false;
  265 + }
  266 +
  267 + CUDA_CALLABLE bool operator==(T rhs)
  268 + {
  269 + if(r == rhs && i == (T)0.0)
  270 + return true;
  271 + return false;
  272 + }
  273 +
  274 + /*//FRIEND functions
  275 + //unary minus operator (for negating the complex number)
  276 + template<class A> CUDA_CALLABLE friend complex<A> operator-(const complex<A> &rhs);
  277 +
  278 + //multiplication by T values when the complex number isn't on the left hand side
  279 + template<class A> CUDA_CALLABLE friend complex<A> operator*(const A a, const complex<A> b);
  280 +
  281 + //division by T values when the complex number isn't on the left hand side
  282 + template<class A> CUDA_CALLABLE friend complex<A> operator/(const A a, const complex<A> b);
  283 +
  284 + //POW function
  285 + //template<class A> CUDA_CALLABLE friend complex<A> pow(const complex<A> x, T y);
  286 + template<class A> CUDA_CALLABLE friend complex<A> pow(const complex<A> x, int y);
  287 +
  288 + //log function
  289 + template<class A> CUDA_CALLABLE friend complex<A> log(complex<A> x);
  290 +
  291 + //exp function
  292 + template<class A> CUDA_CALLABLE friend complex<A> exp(complex<A> x);
  293 +
  294 + //sqrt function
  295 + template<class A> CUDA_CALLABLE friend complex<A> sqrt(complex<A> x);
  296 +
  297 + //trigonometric functions
  298 + template<class A> CUDA_CALLABLE friend complex<A> sin(complex<A> x);
  299 +
  300 + template<class A> CUDA_CALLABLE friend complex<A> cos(complex<A> x);*/
  301 +
  302 +};
  303 +
  304 +//addition
  305 +template<typename T>
  306 +CUDA_CALLABLE static rtcomplex<T> operator+(const double a, const rtcomplex<T> b)
  307 +{
  308 + return rtcomplex<T>(a + b.r, b.i);
  309 +}
  310 +
  311 +//subtraction with a real value
  312 +template<typename T>
  313 +CUDA_CALLABLE static rtcomplex<T> operator-(const double a, const rtcomplex<T> b)
  314 +{
  315 + return rtcomplex<T>(a - b.r, -b.i);
  316 +}
  317 +
  318 +//minus sign
  319 +template<typename T>
  320 +CUDA_CALLABLE static rtcomplex<T> operator-(const rtcomplex<T> &rhs)
  321 +{
  322 + return rtcomplex<T>(-rhs.r, -rhs.i);
  323 +}
  324 +
  325 +//multiply a T value by a complex value
  326 +template<typename T>
  327 +CUDA_CALLABLE static rtcomplex<T> operator*(const double a, const rtcomplex<T> b)
  328 +{
  329 + return rtcomplex<T>(a * b.r, a * b.i);
  330 +}
  331 +
  332 +//divide a T value by a complex value
  333 +template<typename T>
  334 +CUDA_CALLABLE static rtcomplex<T> operator/(const double a, const rtcomplex<T> b)
  335 +{
  336 + //return complex<T>(a * b.r, a * b.i);
  337 + rtcomplex<T> result;
  338 +
  339 + T denom = b.r * b.r + b.i * b.i;
  340 +
  341 + result.r = (a * b.r) / denom;
  342 + result.i = -(a * b.i) / denom;
  343 +
  344 + return result;
  345 +}
  346 +
  347 +//POW function
  348 +/*template<typename T>
  349 +CUDA_CALLABLE static complex<T> pow(complex<T> x, int y)
  350 +{
  351 + return x.pow(y);
  352 +}*/
  353 +
  354 +template<typename T>
  355 +CUDA_CALLABLE static rtcomplex<T> pow(rtcomplex<T> x, T y)
  356 +{
  357 + return x.pow(y);
  358 +}
  359 +
  360 +//log function
  361 +template<typename T>
  362 +CUDA_CALLABLE static rtcomplex<T> log(rtcomplex<T> x)
  363 +{
  364 + return x.log();
  365 +}
  366 +
  367 +//exp function
  368 +template<typename T>
  369 +CUDA_CALLABLE static rtcomplex<T> exp(rtcomplex<T> x)
  370 +{
  371 + return x.exp();
  372 +}
  373 +
  374 +//sqrt function
  375 +template<typename T>
  376 +CUDA_CALLABLE static rtcomplex<T> sqrt(rtcomplex<T> x)
  377 +{
  378 + return x.sqrt();
  379 +}
  380 +
  381 +
  382 +template <typename T>
  383 +CUDA_CALLABLE static T abs(rtcomplex<T> a)
  384 +{
  385 + return a.abs();
  386 +}
  387 +
  388 +template <typename T>
  389 +CUDA_CALLABLE static T real(rtcomplex<T> a)
  390 +{
  391 + return a.r;
  392 +}
  393 +
  394 +template <typename T>
  395 +CUDA_CALLABLE static T imag(rtcomplex<T> a)
  396 +{
  397 + return a.i;
  398 +}
  399 +
  400 +//trigonometric functions
  401 +template<class A>
  402 +CUDA_CALLABLE rtcomplex<A> sin(const rtcomplex<A> x)
  403 +{
  404 + rtcomplex<A> result;
  405 + result.r = std::sin(x.r) * std::cosh(x.i);
  406 + result.i = std::cos(x.r) * std::sinh(x.i);
  407 +
  408 + return result;
  409 +}
  410 +
  411 +template<class A>
  412 +CUDA_CALLABLE rtcomplex<A> cos(const rtcomplex<A> x)
  413 +{
  414 + rtcomplex<A> result;
  415 + result.r = std::cos(x.r) * std::cosh(x.i);
  416 + result.i = -(std::sin(x.r) * std::sinh(x.i));
  417 +
  418 + return result;
  419 +}
  420 +
  421 +
  422 +
  423 +} //end RTS namespace
  424 +
  425 +template<class A>
  426 +std::ostream& operator<<(std::ostream& os, rts::rtcomplex<A> x)
  427 +{
  428 + os<<x.toStr();
  429 + return os;
  430 +}
  431 +
  432 +
  433 +
  434 +#endif
... ...
rts/sbessel.h 0 → 100644
  1 +++ a/rts/sbessel.h
  1 +#ifndef RTS_SBESSEL_H
  2 +#define RTS_SBESSEL_H
  3 +#include <math.h>
  4 +
  5 +
  6 +namespace rts{
  7 +
  8 +#define RTS_BESSEL_CONVERGENCE_FLOAT 0.00045
  9 +
  10 +template <typename T>
  11 +CUDA_CALLABLE void sbesselj(int n, rtcomplex<T> x, rtcomplex<T>* j)
  12 +{
  13 + //compute the first bessel function
  14 + if(n >= 0)
  15 + j[0] = sin(x) / x;
  16 +
  17 + //compute the second bessel function
  18 + if(n >= 1)
  19 + j[1] = j[0] / x - cos(x) / x;
  20 +
  21 + //use the recurrence relation to compute the rest
  22 + for(int i = 2; i <= n; i++)
  23 + {
  24 + j[i] = ( (2 * i - 1) / x ) * j[i-1] - j[i-2];
  25 + }
  26 +
  27 + //if x = 0, deal with the degenerate case
  28 + /*if( isnan(j[0].r) )
  29 + {
  30 + j[0] = (T)1.0;
  31 + for(int i = 1; i<=n; i++)
  32 + j[i] = (T)0.0;
  33 + }*/
  34 +}
  35 +
  36 +template <typename T>
  37 +CUDA_CALLABLE void sbessely(int n, rtcomplex<T> x, rtcomplex<T>* y)
  38 +{
  39 + //compute the first bessel function
  40 + if(n >= 0)
  41 + y[0] = -cos(x) / x;
  42 +
  43 + //compute the second bessel function
  44 + if(n >= 1)
  45 + y[1] = y[0] / x - sin(x) / x;
  46 +
  47 + //use the recurrence relation to compute the rest
  48 + for(int i = 2; i <= n; i++)
  49 + {
  50 + y[i] = ( (2 * i - 1) / x ) * y[i-1] - y[i-2];
  51 + }
  52 +
  53 +}
  54 +
  55 +//spherical Hankel functions of the first kind
  56 +template <typename T>
  57 +CUDA_CALLABLE void sbesselh1(int n, rtcomplex<T> x, rtcomplex<T>* h)
  58 +{
  59 + //compute j_0 and j_1
  60 + rtcomplex<T> j[2];
  61 + sbesselj(1, x, j);
  62 +
  63 + //compute y_0 and y_1
  64 + rtcomplex<T> y[2];
  65 + sbessely(1, x, y);
  66 +
  67 + //compute the first-order Hhankel function
  68 + if(n >= 0)
  69 + h[0] = j[0] + y[0].imul();
  70 +
  71 + //compute the second bessel function
  72 + if(n >= 1)
  73 + h[1] = j[1] + y[1].imul();
  74 +
  75 + //use the recurrence relation to compute the rest
  76 + for(int i = 2; i <= n; i++)
  77 + {
  78 + h[i] = ( (2 * i - 1) / x ) * h[i-1] - h[i-2];
  79 + }
  80 +}
  81 +
  82 +template <typename T>
  83 +CUDA_CALLABLE void init_sbesselj(T x, T* j)
  84 +{
  85 + /*if(x < EPSILON_FLOAT)
  86 + {
  87 + j[0] = (T)1;
  88 + j[1] = (T)0;
  89 + return;
  90 + }*/
  91 +
  92 + //compute the first 2 bessel functions
  93 + j[0] = std::sin(x) / x;
  94 +
  95 + j[1] = j[0] / x - std::cos(x) / x;
  96 +
  97 + //deal with the degenerate case of x = 0
  98 + /*if(isnan(j[0]))
  99 + {
  100 + j[0] = (T)1;
  101 + j[1] = (T)0;
  102 + }*/
  103 +
  104 +}
  105 +
  106 +template <typename T>
  107 +CUDA_CALLABLE void shift_sbesselj(int n, T x, T* j)//, T stability = 1.4)
  108 +{
  109 +
  110 + /*if(x < EPSILON_FLOAT)
  111 + {
  112 + j[0] = j[1];
  113 + j[1] = (T)0;
  114 + return;
  115 + }*/
  116 +
  117 + T jnew;
  118 +
  119 + //compute the next (order n) Bessel function
  120 + jnew = ((2 * n - 1) * j[1])/x - j[0];
  121 +
  122 + //if(n > stability*x)
  123 + if(n > x)
  124 + if(jnew < RTS_BESSEL_CONVERGENCE_FLOAT)
  125 + jnew = (T)0;
  126 +
  127 + //deal with the degenerate case of x = 0
  128 + //if(isnan(jnew))
  129 + // jnew = (T)0;
  130 +
  131 + //shift and add the new value to the array
  132 + j[0] = j[1];
  133 + j[1] = jnew;
  134 +}
  135 +
  136 +
  137 +
  138 +} //end namespace rts
  139 +
  140 +
  141 +
  142 +#endif
... ...
rts/vector.h 0 → 100644
  1 +++ a/rts/vector.h
  1 +#ifndef RTS_VECTOR_H
  2 +#define RTS_VECTOR_H
  3 +
  4 +#include <iostream>
  5 +//#include "rts/point.h"
  6 +
  7 +namespace rts
  8 +{
  9 +
  10 +
  11 +
  12 +template <class T, int N>
  13 +struct vector
  14 +{
  15 + T v[N];
  16 +
  17 + CUDA_CALLABLE vector()
  18 + {
  19 + //memset(v, 0, sizeof(T) * N);
  20 + }
  21 +
  22 + //efficiency constructor, makes construction easier for 1D-4D vectors
  23 + CUDA_CALLABLE vector(T x, T y = (T)0.0, T z = (T)0.0, T w = (T)0.0)
  24 + {
  25 + if(N >= 1)
  26 + v[0] = x;
  27 + if(N >= 2)
  28 + v[1] = y;
  29 + if(N >= 3)
  30 + v[2] = z;
  31 + if(N >= 4)
  32 + v[3] = w;
  33 + }
  34 +
  35 + CUDA_CALLABLE vector(const T(&data)[N])
  36 + {
  37 + memcpy(v, data, sizeof(T) * N);
  38 + }
  39 +
  40 + CUDA_CALLABLE T len()
  41 + {
  42 + //compute and return the vector length
  43 + T sum_sq = (T)0;
  44 + for(int i=0; i<N; i++)
  45 + {
  46 + sum_sq += v[i] * v[i];
  47 + }
  48 + return std::sqrt(sum_sq);
  49 +
  50 + }
  51 +
  52 + CUDA_CALLABLE vector<T, N> cart2sph()
  53 + {
  54 + //convert the vector from cartesian to spherical coordinates
  55 + //x, y, z -> r, theta, phi
  56 +
  57 + vector<T, N> sph;
  58 + sph[0] = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  59 + sph[1] = std::atan2(v[1], v[0]);
  60 + sph[2] = std::acos(v[2] / sph[0]);
  61 +
  62 + return sph;
  63 + }
  64 +
  65 + CUDA_CALLABLE vector<T, N> sph2cart()
  66 + {
  67 + //convert the vector from cartesian to spherical coordinates
  68 + //r, theta, phi -> x, y, z
  69 +
  70 + vector<T, N> cart;
  71 + cart[0] = v[0] * std::cos(v[1]) * std::sin(v[2]);
  72 + cart[1] = v[0] * std::sin(v[1]) * std::sin(v[2]);
  73 + cart[2] = v[0] * std::cos(v[2]);
  74 +
  75 + return cart;
  76 + }
  77 +
  78 + CUDA_CALLABLE vector<T, N> norm()
  79 + {
  80 + //compute and return the vector norm
  81 + vector<T, N> result;
  82 +
  83 + //compute the vector length
  84 + T l = len();
  85 +
  86 + //normalize
  87 + for(int i=0; i<N; i++)
  88 + {
  89 + result.v[i] = v[i] / l;
  90 + }
  91 +
  92 + return result;
  93 + }
  94 +
  95 + CUDA_CALLABLE vector<T, 3> cross(vector<T, 3> rhs)
  96 + {
  97 + vector<T, 3> result;
  98 +
  99 + //compute the cross product (only valid for 3D vectors)
  100 + result[0] = v[1] * rhs[2] - v[2] * rhs[1];
  101 + result[1] = v[2] * rhs[0] - v[0] * rhs[2];
  102 + result[2] = v[0] * rhs[1] - v[1] * rhs[0];
  103 +
  104 + return result;
  105 + }
  106 +
  107 + CUDA_CALLABLE T dot(vector<T, N> rhs)
  108 + {
  109 + T result = (T)0;
  110 +
  111 + for(int i=0; i<N; i++)
  112 + result += v[i] * rhs.v[i];
  113 +
  114 + return result;
  115 +
  116 + }
  117 +
  118 + //arithmetic
  119 + CUDA_CALLABLE vector<T, N> operator+(vector<T, N> rhs)
  120 + {
  121 + vector<T, N> result;
  122 +
  123 + for(int i=0; i<N; i++)
  124 + result.v[i] = v[i] + rhs.v[i];
  125 +
  126 + return result;
  127 + }
  128 + CUDA_CALLABLE vector<T, N> operator-(vector<T, N> rhs)
  129 + {
  130 + vector<T, N> result;
  131 +
  132 + for(int i=0; i<N; i++)
  133 + result.v[i] = v[i] - rhs.v[i];
  134 +
  135 + return result;
  136 + }
  137 + CUDA_CALLABLE vector<T, N> operator*(T rhs)
  138 + {
  139 + vector<T, N> result;
  140 +
  141 + for(int i=0; i<N; i++)
  142 + result.v[i] = v[i] * rhs;
  143 +
  144 + return result;
  145 + }
  146 + CUDA_CALLABLE vector<T, N> operator/(T rhs)
  147 + {
  148 + vector<T, N> result;
  149 +
  150 + for(int i=0; i<N; i++)
  151 + result.v[i] = v[i] / rhs;
  152 +
  153 + return result;
  154 + }
  155 +
  156 + std::string toStr()
  157 + {
  158 + std::stringstream ss;
  159 +
  160 + ss<<"[";
  161 + for(int i=0; i<N; i++)
  162 + {
  163 + ss<<v[i];
  164 + if(i != N-1)
  165 + ss<<", ";
  166 + }
  167 + ss<<"]";
  168 +
  169 + return ss.str();
  170 + }
  171 +
  172 + //bracket operator
  173 + CUDA_CALLABLE T& operator[](int i)
  174 + {
  175 + return v[i];
  176 + }
  177 +
  178 +};
  179 +
  180 +
  181 +} //end namespace rts
  182 +
  183 +template <typename T, int N>
  184 +std::ostream& operator<<(std::ostream& os, rts::vector<T, N> v)
  185 +{
  186 + os<<v.toStr();
  187 + return os;
  188 +}
  189 +
  190 +//arithmetic operators
  191 +template <typename T, int N>
  192 +CUDA_CALLABLE rts::vector<T, N> operator-(rts::vector<T, N> v)
  193 +{
  194 + rts::vector<T, N> r;
  195 +
  196 + //negate the vector
  197 + for(int i=0; i<N; i++)
  198 + r.v[i] = -v.v[i];
  199 +
  200 + return r;
  201 +}
  202 +
  203 +template <typename T, int N>
  204 +CUDA_CALLABLE rts::vector<T, N> operator*(T lhs, rts::vector<T, N> rhs)
  205 +{
  206 + rts::vector<T, N> r;
  207 +
  208 + return rhs * lhs;
  209 +}
  210 +
  211 +#endif
... ...
rtsCamera.h 0 → 100755
  1 +++ a/rtsCamera.h
  1 +#include "rtsVector3d.h"
  2 +#include "rtsPoint3d.h"
  3 +#include "rtsQuaternion.h"
  4 +
  5 +#ifndef RTS_CAMERA_H
  6 +#define RTS_CAMERA_H
  7 +
  8 +class rtsCamera
  9 +{
  10 + vector3D<float> d; //direction that the camera is pointing
  11 + point3D<float> p; //position of the camera
  12 + vector3D<float> up; //"up" direction
  13 + float focus; //focal length of the camera
  14 + float fov;
  15 +
  16 + //private function makes sure that the up vector is orthogonal to the direction vector and both are normalized
  17 + void stabalize()
  18 + {
  19 + vector3D<float> side = up.X(d);
  20 + up = d.X(side);
  21 + up.Normalize();
  22 + d.Normalize();
  23 + }
  24 +
  25 +public:
  26 + void setPosition(point3D<float> pos)
  27 + {
  28 + p = pos;
  29 + }
  30 + void setPosition(float x, float y, float z){setPosition(point3D<float>(x, y, z));}
  31 +
  32 + void setFocalDistance(float distance){focus = distance;}
  33 + void setFOV(float field_of_view){fov = field_of_view;}
  34 +
  35 + void LookAt(point3D<float> pos)
  36 + {
  37 + //find the new direction
  38 + d = pos - p;
  39 +
  40 + //find the distance from the look-at point to the current position
  41 + focus = d.Length();
  42 +
  43 + //stabalize the camera
  44 + stabalize();
  45 + }
  46 + void LookAt(float px, float py, float pz){LookAt(point3D<float>(px, py, pz));}
  47 + void LookAt(point3D<float> pos, vector3D<float> new_up){up = new_up; LookAt(pos);}
  48 + void LookAt(float px, float py, float pz, float ux, float uy, float uz){LookAt(point3D<float>(px, py, pz), vector3D<float>(ux, uy, uz));}
  49 + void LookAtDolly(float lx, float ly, float lz)
  50 + {
  51 + //find the current focus point
  52 + point3D<float> f = p + focus*d;
  53 + vector3D<float> T = point3D<float>(lx, ly, lz) - f;
  54 + p = p + T;
  55 + }
  56 +
  57 + void Dolly(vector3D<float> direction)
  58 + {
  59 + p = p+direction;
  60 + }
  61 + void Dolly(float x, float y, float z){Dolly(vector3D<float>(x, y, z));}
  62 + void Push(float delta)
  63 + {
  64 + if(delta > focus)
  65 + delta = focus;
  66 +
  67 + focus -= delta;
  68 +
  69 + Dolly(d*delta);
  70 + }
  71 +
  72 + void Pan(float theta_x, float theta_y, float theta_z)
  73 + {
  74 + //x rotation is around the up axis
  75 + rtsQuaternion<float> qx;
  76 + qx.CreateRotation(theta_x, up.x, up.y, up.z);
  77 +
  78 + //y rotation is around the side axis
  79 + vector3D<float> side = up.X(d);
  80 + rtsQuaternion<float> qy;
  81 + qy.CreateRotation(theta_y, side.x, side.y, side.z);
  82 +
  83 + //z rotation is around the direction vector
  84 + rtsQuaternion<float> qz;
  85 + qz.CreateRotation(theta_z, d.x, d.y, d.z);
  86 +
  87 + //combine the rotations in x, y, z order
  88 + rtsQuaternion<float> final = qz*qy*qx;
  89 +
  90 + //get the rotation matrix
  91 + matrix4x4<float> rot_matrix = final.toMatrix();
  92 +
  93 + //apply the rotation
  94 + d = rot_matrix*d;
  95 + up = rot_matrix*up;
  96 +
  97 + //stabalize the camera
  98 + stabalize();
  99 +
  100 + }
  101 + void Pan(float theta_x){Pan(theta_x, 0, 0);}
  102 + void Tilt(float theta_y){Pan(0, theta_y, 0);}
  103 + void Twist(float theta_z){Pan(0, 0, theta_z);}
  104 +
  105 + void Zoom(float delta)
  106 + {
  107 + fov -= delta;
  108 + if(fov < 0.5)
  109 + fov = 0.5;
  110 + if(fov > 180)
  111 + fov = 180;
  112 + }
  113 +
  114 + void OrbitFocus(float theta_x, float theta_y)
  115 + {
  116 + //find the focal point
  117 + point3D<float> focal_point = p + focus*d;
  118 +
  119 + //center the coordinate system on the focal point
  120 + point3D<float> centered = p - (focal_point - point3D<float>(0, 0, 0));
  121 +
  122 + //create the x rotation (around the up vector)
  123 + rtsQuaternion<float> qx;
  124 + qx.CreateRotation(theta_x, up.x, up.y, up.z);
  125 + centered = qx.toMatrix()*centered;
  126 +
  127 + //get a side vector for theta_y rotation
  128 + vector3D<float> side = up.X((point3D<float>(0, 0, 0) - centered).Normalize());
  129 +
  130 + rtsQuaternion<float> qy;
  131 + qy.CreateRotation(theta_y, side.x, side.y, side.z);
  132 + centered = qy.toMatrix()*centered;
  133 +
  134 + //perform the rotation on the centered camera position
  135 + //centered = final.toMatrix()*centered;
  136 +
  137 + //re-position the camera
  138 + p = centered + (focal_point - point3D<float>(0, 0, 0));
  139 +
  140 + //make sure we are looking at the focal point
  141 + LookAt(focal_point);
  142 +
  143 + //stabalize the camera
  144 + stabalize();
  145 +
  146 + }
  147 +
  148 + void Slide(float u, float v)
  149 + {
  150 + vector3D<float> V = up.Normalize();
  151 + vector3D<float> U = up.X(d).Normalize();
  152 +
  153 + p = p + (V * v) + (U * u);
  154 + }
  155 +
  156 + //accessor methods
  157 + point3D<float> getPosition(){return p;}
  158 + vector3D<float> getUp(){return up;}
  159 + vector3D<float> getDirection(){return d;}
  160 + point3D<float> getLookAt(){return p + focus*d;}
  161 + float getFOV(){return fov;}
  162 +
  163 + //output the camera settings
  164 + const void print(ostream& output)
  165 + {
  166 + output<<"Position: "<<p<<endl;
  167 +
  168 + }
  169 + friend ostream& operator<<(ostream& out, const rtsCamera& c)
  170 + {
  171 + out<<"Position: "<<c.p<<endl;
  172 + out<<"Direction: "<<c.d<<endl;
  173 + out<<"Up: "<<c.up<<endl;
  174 + out<<"Focal Distance: "<<c.focus<<endl;
  175 + return out;
  176 + }
  177 +
  178 + //constructor
  179 + rtsCamera()
  180 + {
  181 + p = point3D<float>(0, 0, 0);
  182 + d = vector3D<float>(0, 0, 1);
  183 + up = vector3D<float>(0, 1, 0);
  184 + focus = 1;
  185 +
  186 + }
  187 +};
  188 +
  189 +
  190 +
  191 +#endif
0 192 \ No newline at end of file
... ...
rtsCameraController.cpp 0 → 100755
  1 +++ a/rtsCameraController.cpp
  1 +#include "rtsCameraController.h"
  2 +#include <math.h>
  3 +rtsCamera::rtsCamera()
  4 +{
  5 + m_camera_state.position = point3D<float>(10, 10, 10);
  6 + m_camera_state.lookat = point3D<float>(0, 0, 0);
  7 + m_camera_state.up = vector3D<float>(0, 1, 0);
  8 + m_camera_state.pers_view_angle = 60;
  9 + m_camera_state.near_plane = 1;
  10 + m_camera_state.far_plane = 100;
  11 +}
  12 +
  13 +rtsCamera::~rtsCamera()
  14 +{
  15 +
  16 +}
  17 +
  18 +rtsCamera::rtsCamera(rtsCameraState initial_state)
  19 +{
  20 + m_camera_state = initial_state;
  21 +
  22 + //make sure that the view and lookat vectors are orthogonal
  23 + vector3D<float> lookat = m_camera_state.lookat - m_camera_state.position;
  24 + vector3D<float> up = m_camera_state.up;
  25 + vector3D<float> side = lookat.X(up);
  26 + up = side.X(lookat);
  27 + up.Normalize();
  28 + m_camera_state.up = up;
  29 +}
  30 +
  31 +rtsCameraState rtsCamera::getState()
  32 +{
  33 + return m_camera_state;
  34 +}
  35 +
  36 +vector3D<float> rtsCamera::getViewVector()
  37 +{
  38 + vector3D<float> result = m_camera_state.lookat - m_camera_state.position;
  39 + result.Normalize();
  40 + return result;
  41 +}
  42 +
  43 +vector3D<float> rtsCamera::getUpVector()
  44 +{
  45 + return m_camera_state.up;
  46 +}
  47 +
  48 +point3D<float> rtsCamera::getPosition()
  49 +{
  50 + return m_camera_state.position;
  51 +}
  52 +
  53 +void rtsCamera::setState(rtsCameraState camera_state)
  54 +{
  55 + m_camera_state = camera_state;
  56 +
  57 + //re-orthogonalize the vectors
  58 + vector3D<float> view = m_camera_state.lookat - m_camera_state.position;
  59 + vector3D<float> side = view.X(m_camera_state.up);
  60 + m_camera_state.up = side.X(view);
  61 + m_camera_state.up.Normalize();
  62 +}
  63 +
  64 +void rtsCamera::LookAt(point3D<float> point)
  65 +{
  66 + //looks at a point
  67 +
  68 + //find the new view vector
  69 + vector3D<float> view = point - m_camera_state.position;
  70 +
  71 + //normalize the view vector
  72 + view.Normalize();
  73 +
  74 + //prepare a new side vector and up vector
  75 + vector3D<float> side;
  76 + vector3D<float> up;
  77 +
  78 + //get the up vector
  79 + //if the new viewvector is at 0 or 180 degrees to the up vector
  80 + float cos_angle = view*m_camera_state.up;
  81 + if(cos_angle == 1.0f || cos_angle == -1.0f)
  82 + {
  83 + //re-calculate the up vector
  84 + up = m_camera_state.up.X(m_camera_state.lookat - m_camera_state.position);
  85 + }
  86 + else
  87 + {
  88 + //otherwise, just get the current up vector
  89 + up = m_camera_state.up;
  90 + }
  91 +
  92 +
  93 + //correct the up vector based on the new view vector
  94 + side = up.X(view);
  95 + up = view.X(side);
  96 + up.Normalize();
  97 +
  98 + //change the camera state
  99 + m_camera_state.up = up;
  100 + m_camera_state.lookat = point;
  101 +}
  102 +
  103 +void rtsCamera::Position(point3D<float> p)
  104 +{
  105 + m_camera_state.position = p;
  106 +}
  107 +
  108 +void rtsCamera::Up(vector3D<float> up)
  109 +{
  110 + m_camera_state.up = up;
  111 +}
  112 +
  113 +void rtsCamera::DollyPosition(point3D<float> p)
  114 +{
  115 + vector3D<float> adjustment = p-m_camera_state.position;
  116 + m_camera_state.position = p;
  117 + m_camera_state.lookat = m_camera_state.lookat + adjustment;
  118 +}
  119 +
  120 +point3D<float> rtsCamera::getLookAtPoint()
  121 +{
  122 + return m_camera_state.lookat;
  123 +}
  124 +
  125 +
  126 +
  127 +void rtsCamera::Pan(double x, double y)
  128 +{
  129 + //first calculate the lookat and side vectors
  130 + vector3D<float> lookatvector=m_camera_state.lookat - m_camera_state.position;
  131 + vector3D<float> sidevector = lookatvector.X(m_camera_state.up);
  132 + sidevector.Normalize();
  133 +
  134 + m_camera_state.position=m_camera_state.position+sidevector*x;
  135 + m_camera_state.lookat=m_camera_state.lookat+sidevector*x;
  136 +
  137 + vector3D<float> upvector = lookatvector.X(sidevector);
  138 + upvector.Normalize();
  139 + m_camera_state.position=m_camera_state.position+upvector*y;
  140 + m_camera_state.lookat=m_camera_state.lookat+upvector*y;
  141 +}
  142 +
  143 +void rtsCamera::RotateUpDown(double degrees)
  144 +{
  145 + //first calculate the lookat and side vectors
  146 + vector3D<float> lookatvector=m_camera_state.lookat-m_camera_state.position;
  147 + vector3D<float> sidevector = lookatvector.X(m_camera_state.up);
  148 + m_camera_state.up=sidevector.X(lookatvector);
  149 + m_camera_state.up.Normalize();
  150 + sidevector.Normalize();
  151 +
  152 + //translate the look-at point to the origin (and the camera with it)
  153 + point3D<float> origin = point3D<float>(0.0, 0.0, 0.0);
  154 + vector3D<float> translateCamera = origin-m_camera_state.lookat;
  155 +
  156 + point3D<float> translatedCamera=m_camera_state.position+translateCamera;
  157 +
  158 + //the next step is to rotate the side vector so that it lines up with the z axis
  159 + double a=sidevector.x;
  160 + double b=sidevector.y;
  161 + double c=sidevector.z;
  162 +
  163 + double d=sqrt(b*b + c*c);
  164 +
  165 + //error correction for when we are already looking down the z-axis
  166 + if(d==0)
  167 + return;
  168 +
  169 + vector3D<float> XZplane = vector3D<float>(translatedCamera.x,
  170 + (translatedCamera.y*c/d - translatedCamera.z*b/d),
  171 + (translatedCamera.y*b/d + translatedCamera.z*c/d));
  172 +
  173 + vector3D<float> Zaxis = vector3D<float>(XZplane.x*d - XZplane.z*a,
  174 + XZplane.y,
  175 + XZplane.x*a + XZplane.z*d);
  176 +
  177 + vector3D<float> rotated = vector3D<float>(Zaxis.x*cos(TORADIANS(degrees)) - Zaxis.y*sin(TORADIANS(degrees)),
  178 + Zaxis.x*sin(TORADIANS(degrees)) + Zaxis.y*cos(TORADIANS(degrees)),
  179 + Zaxis.z);
  180 +
  181 + vector3D<float> XZout = vector3D<float>( rotated.x*(d/(a*a + d*d)) + rotated.z*(a/(a*a + d*d)),
  182 + rotated.y,
  183 + rotated.x*(-a/(a*a+d*d)) + rotated.z*(d/(a*a + d*d)));
  184 +
  185 + vector3D<float> result = vector3D<float>( XZout.x,
  186 + XZout.y*(c*d/(b*b + c*c)) + XZout.z*(b*d/(b*b + c*c)),
  187 + XZout.y*(-b*d/(b*b + c*c)) + XZout.z*(c*d/(b*b + c*c)));
  188 +
  189 + result=result-translateCamera;
  190 +
  191 + m_camera_state.position.x=result.x;
  192 + m_camera_state.position.y=result.y;
  193 + m_camera_state.position.z=result.z;
  194 +
  195 +}
  196 +
  197 +void rtsCamera::Yaw(double degrees)
  198 +{
  199 + //basically, we have to rotate the look-at point around the up vector
  200 + //first, translate the look-at point so that the camera is at the origin
  201 + point3D<float> origin(0.0, 0.0, 0.0);
  202 + point3D<float> temp_lookat = m_camera_state.lookat - (m_camera_state.position - origin);
  203 +
  204 + //create a rotation matrix to rotate the lookat point around the up vector
  205 + float x=m_camera_state.up.x;
  206 + float y=m_camera_state.up.y;
  207 + float z=m_camera_state.up.z;
  208 + float c=cos(TORADIANS(-degrees));
  209 + float s=sin(TORADIANS(-degrees));
  210 + float t=1.0 - cos(TORADIANS(-degrees));
  211 + float m00 = t*x*x + c;
  212 + float m01 = t*x*y + s*z;
  213 + float m02 = t*x*z - s*y;
  214 + float m03 = 0;
  215 + float m10 = t*x*y - s*z;
  216 + float m11 = t*y*y + c;
  217 + float m12 = t*y*z + s*x;
  218 + float m13 = 0;
  219 + float m20 = t*x*z + s*y;
  220 + float m21 = t*y*z - s*x;
  221 + float m22 = t*z*z + c;
  222 + float m23 = 0;
  223 + float m30 = 0;
  224 + float m31 = 0;
  225 + float m32 = 0;
  226 + float m33 = 1;
  227 + matrix4x4<float> rotation(m00, m01, m02, m03,
  228 + m10, m11, m12, m13,
  229 + m20, m21, m22, m23,
  230 + m30, m31, m32, m33);
  231 + point3D<float> result = rotation*temp_lookat + (m_camera_state.position - origin);
  232 + m_camera_state.lookat = result;
  233 +}
  234 +
  235 +void rtsCamera::Pitch(double degrees)
  236 +{
  237 + //basically, we have to rotate the look-at point and up vector around the side vector
  238 + //first, translate the look-at point so that the camera is at the origin
  239 + point3D<float> origin(0.0, 0.0, 0.0);
  240 +
  241 + //find all three necessary vectors
  242 + vector3D<float> temp_lookat = m_camera_state.lookat - m_camera_state.position;
  243 + double lookat_length = temp_lookat.Length();
  244 + vector3D<float> temp_up = m_camera_state.up;
  245 + vector3D<float> temp_side = temp_lookat.X(temp_up);
  246 + temp_lookat.Normalize();
  247 + temp_up.Normalize();
  248 + temp_side.Normalize();
  249 +
  250 +
  251 + //create a rotation matrix to rotate around the side vector
  252 + float x=temp_side.x;
  253 + float y=temp_side.y;
  254 + float z=temp_side.z;
  255 + float c=cos(TORADIANS(degrees));
  256 + float s=sin(TORADIANS(degrees));
  257 + float t=1.0 - cos(TORADIANS(degrees));
  258 + float m00 = t*x*x + c;
  259 + float m01 = t*x*y + s*z;
  260 + float m02 = t*x*z - s*y;
  261 + float m03 = 0;
  262 + float m10 = t*x*y - s*z;
  263 + float m11 = t*y*y + c;
  264 + float m12 = t*y*z + s*x;
  265 + float m13 = 0;
  266 + float m20 = t*x*z + s*y;
  267 + float m21 = t*y*z - s*x;
  268 + float m22 = t*z*z + c;
  269 + float m23 = 0;
  270 + float m30 = 0;
  271 + float m31 = 0;
  272 + float m32 = 0;
  273 + float m33 = 1;
  274 + matrix4x4<float> rotation(m00, m01, m02, m03,
  275 + m10, m11, m12, m13,
  276 + m20, m21, m22, m23,
  277 + m30, m31, m32, m33);
  278 +
  279 + //rotate the up and look-at vectors around the side vector
  280 + vector3D<float> result_lookat = rotation*temp_lookat;
  281 + vector3D<float> result_up = rotation*temp_up;
  282 + result_lookat.Normalize();
  283 + result_up.Normalize();
  284 +
  285 + m_camera_state.lookat = m_camera_state.position + result_lookat * lookat_length;
  286 + m_camera_state.up = result_up;
  287 +}
  288 +
  289 +
  290 +void rtsCamera::RotateLeftRight(double degrees)
  291 +//this function rotates the camera around the up vector (which always points along hte positive
  292 +//Y world axis).
  293 +{
  294 + //translate the look-at point to the origin (and the camera with it)
  295 + point3D<float> origin = point3D<float>(0.0, 0.0, 0.0);
  296 + vector3D<float> translateCamera = origin-m_camera_state.lookat;
  297 +
  298 + point3D<float> translatedCamera=m_camera_state.position+translateCamera;
  299 +
  300 +
  301 + //perform the rotation around the look-at point
  302 + //using the y-axis as the rotation axis
  303 + point3D<float> newcamera;
  304 + newcamera.x=translatedCamera.x*cos(TORADIANS(degrees)) - translatedCamera.z*sin(TORADIANS(degrees));
  305 + newcamera.z=translatedCamera.x*sin(TORADIANS(degrees)) + translatedCamera.z*cos(TORADIANS(degrees));
  306 + newcamera.y=translatedCamera.y;
  307 +
  308 + vector3D<float> newup;
  309 + newup.x=m_camera_state.up.x*cos(TORADIANS(degrees)) - m_camera_state.up.z*sin(TORADIANS(degrees));
  310 + newup.z=m_camera_state.up.x*sin(TORADIANS(degrees)) + m_camera_state.up.z*cos(TORADIANS(degrees));
  311 + newup.y=m_camera_state.up.y;
  312 +
  313 + //translate the lookat point back to it's original position (along with the camera)
  314 + newcamera=newcamera-translateCamera;
  315 +
  316 + m_camera_state.position.x=newcamera.x;
  317 + m_camera_state.position.y=newcamera.y;
  318 + m_camera_state.position.z=newcamera.z;
  319 +
  320 + m_camera_state.up.x=newup.x;
  321 + m_camera_state.up.y=newup.y;
  322 + m_camera_state.up.z=newup.z;
  323 + m_camera_state.up.Normalize();
  324 +
  325 +}
  326 +
  327 +void rtsCamera::Forward(double distance)
  328 +{
  329 + //calculate the lookat vector (direction of travel)
  330 + vector3D<float> old_lookat=m_camera_state.lookat-m_camera_state.position;
  331 + old_lookat.Normalize();
  332 +
  333 + //calculate the new position of the camera
  334 + point3D<float> new_position = m_camera_state.position+old_lookat*distance;
  335 + //now calculate the new lookat vector
  336 + vector3D<float> new_lookat=m_camera_state.lookat-new_position;
  337 + //find the length of the new lookat vector
  338 + /*double newlength=lookatvector.length();
  339 + //if the length is 0 or the camera flipped
  340 + if((newlength <= 0.0))
  341 + {
  342 + //recalculate the lookat vector using the old position
  343 + lookatvector=m_camera_state.lookat-m_camera_state.position;
  344 + lookatvector.Normalize();
  345 + //adjust the lookat point appropriately
  346 + m_camera_state.lookat = new_position + lookatvector;
  347 + }*/
  348 + //move the camera to the new position
  349 + m_camera_state.position = new_position;
  350 +}
  351 +
  352 +void rtsCamera::ScaleForward(double factor, double min, double max)
  353 +{
  354 + /*This function moves the camera forward, scaling the magnitude
  355 + of the motion by the length of the view vector. Basically, the closer
  356 + the camera is to the lookat point, the slower the camera moves.*/
  357 +
  358 + //calculate the lookat vector (direction of travel)
  359 + vector3D<float> lookatvector=m_camera_state.lookat-m_camera_state.position;
  360 + //find the length of the view vector
  361 + double length = lookatvector.Length();
  362 + //normalize
  363 + lookatvector.Normalize();
  364 +
  365 + //prevent motion if the bounds would be passed
  366 + double new_distance = length - (factor*length);
  367 + if(new_distance < min || new_distance > max)
  368 + factor = 0;
  369 + //move the camera
  370 + m_camera_state.position=m_camera_state.position+lookatvector*factor*length;
  371 + lookatvector=m_camera_state.lookat-m_camera_state.position;
  372 + /*double newlength=lookatvector.length();
  373 + if((newlength < 2))
  374 + {
  375 + lookatvector.Normalize();
  376 + m_camera_state.lookat = m_camera_state.position + lookatvector*2;
  377 + }*/
  378 +
  379 +
  380 +}
  381 +
  382 +void rtsCamera::DollyLeftRight(double distance)
  383 +{
  384 + //calculate the side vector vector (direction of travel)
  385 + vector3D<float> lookatvector=m_camera_state.lookat-m_camera_state.position;
  386 + vector3D<float> side = lookatvector.X(m_camera_state.up);
  387 + side.Normalize();
  388 +
  389 + m_camera_state.position=m_camera_state.position+side*distance;
  390 + m_camera_state.lookat = m_camera_state.lookat + side*distance;
  391 + //lookatvector=m_camera_state.lookat-m_camera_state.position;
  392 +}
  393 +
  394 +void rtsCamera::DollyUpDown(double distance)
  395 +{
  396 + //move along the up vector
  397 + m_camera_state.up.Normalize();
  398 +
  399 + m_camera_state.position=m_camera_state.position+m_camera_state.up*distance;
  400 + m_camera_state.lookat = m_camera_state.lookat + m_camera_state.up*distance;
  401 + //lookatvector=m_camera_state.lookat-m_camera_state.position;
  402 +}
  403 +
  404 +void rtsCamera::Zoom(double angle)
  405 +{
  406 + m_camera_state.pers_view_angle += angle;
  407 +}
0 408 \ No newline at end of file
... ...
rtsCameraController.h 0 → 100755
  1 +++ a/rtsCameraController.h
  1 +#include "rtsLinearAlgebra.h"
  2 +
  3 +#ifndef _RTSMATH_H
  4 +#define _RTSMATH_H
  5 +
  6 +#define CAMERA_UP -1
  7 +#define CAMERA_DOWN 1
  8 +#define CAMERA_LEFT -1
  9 +#define CAMERA_RIGHT 1
  10 +
  11 +struct rtsCameraState
  12 +{
  13 + point3D<float> position;
  14 + point3D<float> lookat;
  15 + vector3D<float> up;
  16 + float pers_view_angle;
  17 + float ortho_width;
  18 + float ortho_height;
  19 + float near_plane;
  20 + float far_plane;
  21 +};
  22 +
  23 +class rtsCamera
  24 +{
  25 + //members
  26 + rtsCameraState m_camera_state;
  27 +
  28 +public:
  29 +
  30 + //methods
  31 + void RotateUpDown(double degrees);
  32 + void RotateLeftRight(double degrees);
  33 + void Pan(double x, double y);
  34 + void Yaw(double degrees);
  35 + void Pitch(double degrees);
  36 + void Forward(double distance);
  37 + void ScaleForward(double factor, double min = 0, double max = 999999);
  38 + void DollyLeftRight(double distance);
  39 + void DollyUpDown(double distance);
  40 + void Zoom(double angle);
  41 + void LookAt(point3D<float> point);
  42 + void Position(point3D<float> point);
  43 + void Up(vector3D<float> up);
  44 + void DollyPosition(point3D<float> point); //moves the camera but keeps the current orientation
  45 +
  46 + //get methods
  47 + rtsCameraState getState();
  48 + vector3D<float> getViewVector();
  49 + vector3D<float> getUpVector();
  50 + point3D<float> getPosition();
  51 + point3D<float> getLookAtPoint();
  52 + double getViewAngle(){return m_camera_state.pers_view_angle;}
  53 + double getNearPlane(){return m_camera_state.near_plane;}
  54 + double getFarPlane(){return m_camera_state.far_plane;}
  55 + double getOrthoWidth(){return m_camera_state.ortho_width;}
  56 + double getOrthoHeight(){return m_camera_state.ortho_height;}
  57 +
  58 + //set methods
  59 + void setState(rtsCameraState camera_state);
  60 +
  61 + //initialization methods
  62 + //int SetPosition(double x, double y, double z);
  63 + //int OrthogonalCamera(double width, double height, double near, double far);
  64 + //int LookAt(double x, double y, double z); //looks at a point in space
  65 + //int SetUpVector(double x, double y, double z);
  66 + /*int InitializePerspectiveCamera(double position_x, double position_y, double position_z,
  67 + double lookat_x, double lookat_y, double lookat_z,
  68 + double up_x, double up_y, double up_z,
  69 + double angle, double near_dist, double far_dist);*/
  70 + //int InitializeCamera(); //initializes a camera to defaults
  71 +
  72 + rtsCamera();
  73 + rtsCamera(rtsCameraState initial_state);
  74 + ~rtsCamera();
  75 +};
  76 +
  77 +#endif
0 78 \ No newline at end of file
... ...
rtsConstants.h 0 → 100755
  1 +++ a/rtsConstants.h
  1 +#define RTS_OK 0
  2 +#define RTS_ERROR 99
  3 +
  4 +
  5 +#define RTS_EMPTY 1 //an element can't be deleted if it contains no data
  6 +#define RTS_INVALID_ID 2 //an object with this identifier does not exist
  7 +#define RTS_INVALID_CONSTANT 3 //an invalid constant passed as a parameter
  8 +
  9 +//objects
  10 +#define RTS_END_OBJECT 4 //reached the end of an object's elements
  11 +
  12 +//utility constants
  13 +#define RTS_NULL 0
  14 +
  15 +#define RTS_NO_INTERSECTION 1 //there is no intersection in intersection calculations
0 16 \ No newline at end of file
... ...
rtsCubeSampler.cpp 0 → 100755
  1 +++ a/rtsCubeSampler.cpp
  1 +#include "rtsCubeSampler.h"
  2 +
  3 +vector<vector3D> rtsCubeSampler::Evaluate()
  4 +{
  5 + /*This function evaluates the cube with the given parameters and returns
  6 + a vector of sample normalized sample vectors.*/
  7 +
  8 + //find a valid up vector
  9 + vector3D u(0.0, 1.0, 0.0);
  10 + //calculate the side vector
  11 + vector3D s = u.cross(m_main_vector);
  12 + //orthogonalize the up vector
  13 + u = m_main_vector.cross(s);
  14 + //normalize all three vectors
  15 + m_main_vector.normalize();
  16 + u.normalize();
  17 + s.normalize();
  18 +
  19 + //create a vector representing each side of the cube
  20 + vector3D sides[6];
  21 + sides[0] = m_main_vector;
  22 + sides[1] = (m_main_vector)*(-1);
  23 + sides[2] = u;
  24 + sides[3] = u*(-1);
  25 + sides[4] = s;
  26 + sides[5] = s*(-1);
  27 +
  28 + //calculate the step size along the basis vectors for a side
  29 + double step = 1.0/((double)m_squared_samples_per_side);
  30 +
  31 + //evaluate the cube, storing the result in an STL vector
  32 + vector<vector3D> result;
  33 + for(int k=0; k<6; k++)
  34 + for(int i=0; i<m_squared_samples_per_side; i++)
  35 + for(int j=0; j<m_squared_samples_per_side; j++)
  36 + {
  37 + //find the indices for the vectors representing the edges of the current side
  38 + unsigned int u_vector_index = (k+2)%6;
  39 + unsigned int v_vector_index = (k+4)%6;
  40 + //get two basis vectors for the side
  41 + vector3D u = sides[u_vector_index];
  42 + vector3D v = sides[v_vector_index];
  43 +
  44 + //calculate a vector
  45 + vector3D adjustment = (u*2*(i*step+0.5*step) - u) + (v*2*(j*step + 0.5*step) - v);
  46 + vector3D final_vector = sides[k] + adjustment;
  47 + final_vector.normalize();
  48 + //test the angle and eliminate the vector if it is too large
  49 + double cosine_angle = final_vector*m_main_vector;
  50 + if(cosine_angle >= cos(TORADIANS(max_angle)))
  51 + result.push_back(final_vector);
  52 + }
  53 +
  54 + //return the vector of results
  55 + return result;
  56 +}
0 57 \ No newline at end of file
... ...
rtsCubeSampler.h 0 → 100755
  1 +++ a/rtsCubeSampler.h
  1 +/*This class returns a series of normalized vectors that sample the surface of a cube*/
  2 +/*TODO:
  3 +-)Implement random sampling
  4 +-)Allow the user to provide a total number of samples
  5 +
  6 +*/
  7 +#ifndef RTSCUBESAMPLER_H
  8 +#define RTSCUBESAMPLER_H
  9 +
  10 +#include <vector>
  11 +#include "rtsMath.h"
  12 +
  13 +using namespace std;
  14 +
  15 +//definitions for sample types
  16 +#define RTS_RANDOM_UNIFORM 0x00001001
  17 +#define RTS_RANDOM_GAUSSIAN 0x00001002
  18 +#define RTS_REGULAR 0x00001003
  19 +
  20 +class rtsCubeSampler
  21 +{
  22 +public:
  23 +
  24 + unsigned int m_sample_type;
  25 + unsigned int m_squared_samples_per_side;
  26 + double max_angle;
  27 + vector3D m_main_vector;
  28 +
  29 + vector<vector3D> Evaluate();
  30 +};
  31 +
  32 +#endif
0 33 \ No newline at end of file
... ...
rtsDTGrid1D.h 0 → 100755
  1 +++ a/rtsDTGrid1D.h
  1 +#ifndef _RTS_DTGRID1D_H
  2 +#define _RTS_DTGRID1D_H
  3 +
  4 +#include <vector>
  5 +#include <iostream>
  6 +using namespace std;
  7 +
  8 +struct ConnectedComponent
  9 +{
  10 + int toValue;
  11 + int coordMin;
  12 + int coordMax;
  13 +};
  14 +
  15 +
  16 +
  17 +
  18 +template<typename T>
  19 +class rtsDTGrid1D
  20 +{
  21 +
  22 +private:
  23 + //main arrays
  24 + vector<T> value;
  25 + vector<ConnectedComponent> conn;
  26 +
  27 + //variables to keep track of insertion
  28 + int max_coord;
  29 + bool insertion_started;
  30 + bool randomIndex(int &v, int &c, int x1);
  31 +
  32 +
  33 +public:
  34 + T background;
  35 + rtsDTGrid1D<T>()
  36 + {
  37 + insertion_started = false;
  38 + max_coord = 0;
  39 + }
  40 + int getMaxX1(){return max_coord;}
  41 +
  42 + T random(int x1);
  43 + T& back();
  44 + bool push(int x1, T value);
  45 + void insert(rtsDTGrid1D<T> toInsert);
  46 + void getBounds(int &min_x1, int &max_x1);
  47 + void dilate(int H);
  48 + template<typename P> rtsDTGrid1D<P> getStorage()
  49 + {
  50 + //create the resulting grid
  51 + rtsDTGrid1D<P> result;
  52 + //create an iterator to run over the existing grid
  53 + P* new_value = (P*)calloc(1, sizeof(P));
  54 + for(iterator i = begin(); i!=end(); i.increment())
  55 + {
  56 + result.push(i.X1(), *new_value);
  57 + }
  58 + return result;
  59 +
  60 + }
  61 + void operator=(T rhs);
  62 + void print();
  63 +
  64 + //iterator
  65 + class iterator;
  66 + friend class iterator;
  67 + class stencil_iterator;
  68 + iterator randomIterator(int x1);
  69 + iterator begin();
  70 + iterator end();
  71 + iterator before();
  72 + iterator after();
  73 +
  74 +};
  75 +
  76 +/***************ITERATOR*************************/
  77 +template<typename T>
  78 +class rtsDTGrid1D<T>::iterator
  79 +{
  80 + friend class rtsDTGrid1D;
  81 +
  82 +
  83 +protected:
  84 + rtsDTGrid1D<T>* parent;
  85 + int iv;
  86 + int ic;
  87 + int x1;
  88 +
  89 +public:
  90 + T Value(){return parent->value[iv];}
  91 + int X1(){return x1;}
  92 + void SetValue(T val){parent->value[iv] = val;}
  93 +
  94 + iterator(){parent = NULL;}
  95 +
  96 + void p()
  97 + {
  98 + //increment the current coordinate and value
  99 + x1++;
  100 + iv++;
  101 + //if we are outside of the current connected component
  102 + if(x1 > parent->conn[ic].coordMax)
  103 + {
  104 + //if this is the last connected component, set the iterator to END and return
  105 + if(ic == parent->conn.size() - 1)
  106 + {
  107 + (*this) = parent->after();
  108 + return;
  109 + }
  110 + //otherwise move to the next connected component and update the coordinate
  111 + ic++;
  112 + x1 = parent->conn[ic].coordMin;
  113 + }
  114 + }
  115 + void n()
  116 + {
  117 + //increment the current coordinate and value
  118 + x1--;
  119 + iv--;
  120 + //if we are outside of the current connected component
  121 + if(x1 < parent->conn[ic].coordMin)
  122 + {
  123 + //if this is the last connected component, set the iterator to END and return
  124 + if(ic <= 0)
  125 + {
  126 + (*this) = parent->before();
  127 + return;
  128 + }
  129 + //otherwise move to the next connected component and update the coordinate
  130 + ic--;
  131 + x1 = parent->conn[ic].coordMax;
  132 + }
  133 +
  134 +
  135 + }
  136 + //boolean operators for comparing iterators
  137 + bool operator==(iterator &rhs)
  138 + {
  139 + if(parent == rhs.parent && iv == rhs.iv)
  140 + return true;
  141 + //if(x1 == rhs.x1)
  142 + // return true;
  143 + return false;
  144 + }
  145 + bool operator!=(iterator &rhs){return !((*this) == rhs);}
  146 + bool operator<(iterator &rhs)
  147 + {
  148 + if(parent == rhs.parent && iv == rhs.iv)
  149 + return true;
  150 + //if the parents are the same, test value indices
  151 + //if(parent == rhs.parent && iv < rhs.iv)
  152 + // return true;
  153 + //otherwise test coordinates
  154 + //if(parent != rhs.parent && x1 < rhs.x1)
  155 + // return true;
  156 + return false;
  157 + }
  158 + bool operator<=(iterator &rhs)
  159 + {
  160 + if(parent == rhs.parent && iv <= rhs.iv)
  161 + return true;
  162 + //if(x1 <= rhs.x1)
  163 + // return true;
  164 + return false;
  165 + }
  166 + void operator++(){p();}
  167 + void operator--(){n();}
  168 +
  169 + void increment_until(int pos)
  170 + {
  171 + while(x1 < pos && (*this) != parent->after())
  172 + {
  173 + p();
  174 + }
  175 + }
  176 +};
  177 +
  178 +
  179 +/************STENCIL ITERATOR********************/
  180 +template<typename T>
  181 +class rtsDTGrid1D<T>::stencil_iterator : public iterator
  182 +{
  183 +private:
  184 + //list of iterators that make up the template
  185 + vector<iterator> iterator_list;
  186 + //iterator positions (relative to the position of the stencil iterator)
  187 + vector<int> position_list;
  188 + //list containing the values for each position in the stencil
  189 + vector<T> value_list;
  190 +
  191 + void refresh_iterators();
  192 + void set_values();
  193 + void increment_all();
  194 +
  195 +public:
  196 + typename rtsDTGrid1D<T>::stencil_iterator operator=(const iterator rhs);
  197 + void addPosition(int p);
  198 + void operator++(){p();}
  199 + void p();
  200 + T getValue(int id){return value_list[id];}
  201 + bool exists(int id);
  202 +
  203 +};
  204 +
  205 +template<typename T>
  206 +void rtsDTGrid1D<T>::stencil_iterator::increment_all()
  207 +{
  208 + //run through each iterator and increment to the correct position
  209 + int i;
  210 + int dest;
  211 + for(i=0; i<iterator_list.size(); i++)
  212 + {
  213 + //determine the appropriate position for the iterator
  214 + dest = x1 + position_list[i];
  215 + //iterate until that position is reached
  216 + iterator_list[i].increment_until(dest);
  217 + set_values();
  218 + }
  219 +
  220 +}
  221 +
  222 +template<typename T>
  223 +void rtsDTGrid1D<T>::stencil_iterator::p()
  224 +{
  225 + //increment the current position
  226 + rtsDTGrid1D<T>::iterator::p();
  227 +
  228 + increment_all();
  229 +}
  230 +
  231 +template<typename T>
  232 +void rtsDTGrid1D<T>::stencil_iterator::refresh_iterators()
  233 +{
  234 + //make sure that the iterator position has been set
  235 + if(parent == NULL)
  236 + {
  237 + cout<<"Iterator location not set."<<endl;
  238 + return;
  239 + }
  240 +
  241 + //initialize all of the other iterators
  242 + int i;
  243 + for(i=0; i<iterator_list.size(); i++)
  244 + {
  245 + //for each iterator, set the iterator to the beginning of the grid
  246 + iterator_list[i] = parent->begin();
  247 + }
  248 + increment_all();
  249 + //set the values for all of the iterators
  250 + set_values();
  251 +}
  252 +
  253 +template<typename T>
  254 +void rtsDTGrid1D<T>::stencil_iterator::set_values()
  255 +{
  256 + int i;
  257 + int dest;
  258 + for(i=0; i<iterator_list.size(); i++)
  259 + {
  260 + //determine the appropriate position for the iterator
  261 + dest = x1 + position_list[i];
  262 + //now add the value to the value list
  263 + if(iterator_list[i].X1() == dest)
  264 + value_list[i] = iterator_list[i].Value();
  265 + else
  266 + value_list[i] = parent->background;
  267 + }
  268 +
  269 +
  270 +}
  271 +
  272 +template<typename T>
  273 +typename rtsDTGrid1D<T>::stencil_iterator rtsDTGrid1D<T>::stencil_iterator::operator=(const iterator rhs)
  274 +{
  275 + parent = rhs.parent;
  276 + iv = rhs.iv;
  277 + ic = rhs.ic;
  278 + x1 = rhs.x1;
  279 +
  280 + refresh_iterators();
  281 +
  282 + return (*this);
  283 +}
  284 +
  285 +template<typename T>
  286 +void rtsDTGrid1D<T>::stencil_iterator::addPosition(int p)
  287 +{
  288 + position_list.push_back(p);
  289 + rtsDTGrid1D<T>::iterator new_iter;
  290 + /*If the parent variable is valid (the current iterator is assigned to
  291 + a grid), assign the position just added to the same grid.
  292 + If the parent isn't set, all iterators are assigned to the appropriate grid
  293 + later on when the operator= is used to assign the grid to the stencil.
  294 + */
  295 + if(parent != NULL)
  296 + {
  297 + new_iter = parent->begin();
  298 + refresh_iterators();
  299 + }
  300 +
  301 + iterator_list.push_back(new_iter);
  302 + value_list.resize(value_list.size() + 1);
  303 +}
  304 +
  305 +template<typename T>
  306 +bool rtsDTGrid1D<T>::stencil_iterator::exists(int id)
  307 +{
  308 + //returns true if the iterator defined by id points to an actual grid node
  309 +
  310 + //determine the appropriate position for the iterator
  311 + int dest = x1 + position_list[id];
  312 +
  313 + if(iterator_list[id].X1() == dest)
  314 + return true;
  315 + else
  316 + return false;
  317 +
  318 +}
  319 +
  320 +
  321 +/**************ITERATOR METHODS IN DT GRID*******************/
  322 +template<typename T>
  323 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::begin()
  324 +{
  325 + //if the grid is empty, return after()
  326 + if(value.size() == 0)
  327 + return after();
  328 +
  329 + iterator result;
  330 + result.parent = this;
  331 + result.ic = 0;
  332 + result.iv = 0;
  333 + result.x1 = conn[0].coordMin;
  334 + return result;
  335 +}
  336 +template<typename T>
  337 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::before()
  338 +{
  339 + //if the grid is empty, return after()
  340 + if(value.size() == 0)
  341 + return after();
  342 +
  343 + iterator result;
  344 + result.parent = this;
  345 + result.ic = 0;
  346 + result.iv = -1;
  347 + //result.x1 = conn[0].coordMin;
  348 + return result;
  349 +}
  350 +
  351 +template<typename T>
  352 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::end()
  353 +{
  354 + //if the grid is empty, return after()
  355 + if(value.size() == 0)
  356 + return after();
  357 +
  358 + iterator result;
  359 + result.parent = this;
  360 + result.ic = conn.size() - 1;
  361 + result.iv = value.size() - 1;
  362 + result.x1 = conn[result.ic].coordMax;
  363 + return result;
  364 +}
  365 +template<typename T>
  366 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::after()
  367 +{
  368 + iterator result;
  369 + result.parent = this;
  370 + result.ic = conn.size() - 1;
  371 + result.iv = value.size();
  372 + //result.x1 = conn[result.ic].coordMax;
  373 + return result;
  374 +}
  375 +
  376 +
  377 +
  378 +
  379 +template<typename T>
  380 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::randomIterator(int x1)
  381 +{
  382 + //if the grid is empty return a "after" iterator
  383 + if(value.size() == 0)
  384 + return after();
  385 +
  386 + rtsDTGrid1D<T>::iterator result;
  387 + result.parent = this;
  388 + int v_i, c_i;
  389 +
  390 + //if the value exists in the grid, create the iterator and return
  391 + if(randomIndex(v_i, c_i, x1))
  392 + {
  393 + result.iv = v_i;
  394 + result.ic = c_i;
  395 + int offset = v_i - conn[c_i].toValue;
  396 + result.x1 = conn[c_i].coordMin + offset;
  397 + }
  398 + //if the value doesn't exist
  399 + else
  400 + {
  401 + //if the value lies before the current column
  402 + if(x1 < conn[c_i].coordMin)
  403 + {
  404 + result.ic = c_i;
  405 +
  406 + }
  407 + else
  408 + {
  409 + //if this is the last connected component
  410 + if(c_i >= conn.size() - 1)
  411 + return after();
  412 + else
  413 + {
  414 + c_i++;
  415 + result.ic = c_i;
  416 + }
  417 + }
  418 + result.iv = conn[c_i].toValue;
  419 + result.x1 = conn[c_i].coordMin;
  420 + }
  421 + return result;
  422 +
  423 +}
  424 +template<typename T>
  425 +void rtsDTGrid1D<T>::print()
  426 +{
  427 + rtsDTGrid1D<T>::iterator i;
  428 + i = begin();
  429 + while(i != after())
  430 + {
  431 + cout<<i.X1()<<":"<<i.Value()<<endl;
  432 + i++;
  433 + }
  434 +
  435 +
  436 +}
  437 +
  438 +/**************DT GRID**************************/
  439 +template<typename T>
  440 +bool rtsDTGrid1D<T>::push(int x1, T v)
  441 +{
  442 + //test to make sure the insertion is happening in the right order
  443 + if(insertion_started && x1 <= max_coord)
  444 + {
  445 + cout<<"Out-of-order insertion in D = 1: X1 = "<<x1<<endl;
  446 + return false;
  447 + }
  448 +
  449 +
  450 + //run this code if we have to start a new connected component. This happens when:
  451 + //(a) We insert the first value into the grid
  452 + //(b) There is empty space between the last insertion and this one
  453 + if(insertion_started == false || x1 > (max_coord + 1))
  454 + {
  455 + //start a new connected component
  456 + ConnectedComponent new_conn;
  457 + new_conn.toValue = value.size();
  458 + new_conn.coordMin = x1;
  459 + new_conn.coordMax = x1;
  460 + conn.push_back(new_conn);
  461 + insertion_started = true;
  462 + }
  463 +
  464 + //insert the value into the grid:
  465 + //(a) Insert the value at the end of the coord array
  466 + //(b) Increment the coordMax value of the current connected component
  467 + //(c) Change the maximum inserted coordinate to the new value
  468 + value.push_back(v);
  469 + conn[conn.size() - 1].coordMax = x1;
  470 + //change max_coord to the new coordinate
  471 + max_coord = x1;
  472 + return true;
  473 +}
  474 +
  475 +template<typename T>
  476 +void rtsDTGrid1D<T>::insert(rtsDTGrid1D<T> toInsert)
  477 +{
  478 + //create source and destination iterators
  479 + rtsDTGrid1D<T>::iterator source = toInsert.begin();
  480 + rtsDTGrid1D<T>::iterator dest = begin();
  481 +
  482 + while(source != toInsert.after())
  483 + {
  484 + //move the destination iterator to the current source position
  485 + dest.increment_until(source.X1());
  486 + //if the position exists in dest
  487 + if(dest.X1() == source.X1())
  488 + dest.SetValue(source.Value());
  489 + source++;
  490 + }
  491 +
  492 +}
  493 +
  494 +template<typename T>
  495 +void rtsDTGrid1D<T>::getBounds(int &min_x1, int &max_x1)
  496 +{
  497 + //return an empty bounding volume if the grid is empty
  498 + if(value.size() == 0)
  499 + {
  500 + min_x1 = 0;
  501 + max_x1 = 0;
  502 + return;
  503 + }
  504 +
  505 + //get the minimum and maximum coordinates
  506 + min_x1 = conn[0].coordMin;
  507 + max_x1 = conn.back().coordMax;
  508 +}
  509 +template<typename T>
  510 +void rtsDTGrid1D<T>::dilate(int H)
  511 +{
  512 + //this function creates a new DT grid dilated by H and copies
  513 + //the original grid into the new grid
  514 +
  515 + //create a new grid
  516 + rtsDTGrid1D<T> new_grid;
  517 +
  518 + //determine the dilated values for the first connected component
  519 + int numValues = 0;
  520 + int start = conn[0].coordMin - H;
  521 + int end = conn[0].coordMax + H;
  522 +
  523 + //run through each remaining connected component
  524 + for(int i=1; i<conn.size(); i++)
  525 + {
  526 + //if the new component and the i'th ones overlap, combine them
  527 + //cout<<conn[i].coordMin - H<<endl;
  528 + if(conn[i].coordMin - H <= end)
  529 + end = conn[i].coordMax + H;
  530 + else
  531 + {
  532 + //store the dilated connected component
  533 + ConnectedComponent cc;
  534 + cc.coordMin = start;
  535 + cc.coordMax = end;
  536 + cc.toValue = numValues;
  537 + numValues += end - start + 1;
  538 + new_grid.conn.push_back(cc);
  539 +
  540 + //start a new dilated connected component
  541 + start = conn[i].coordMin - H;
  542 + end = conn[i].coordMax + H;
  543 + }
  544 + }
  545 + //add the last dilated connected component
  546 + ConnectedComponent cc;
  547 + cc.coordMin = start;
  548 + cc.coordMax = end;
  549 + cc.toValue = numValues;
  550 + numValues += end - start + 1;
  551 + new_grid.conn.push_back(cc);
  552 + //allocate space in the value array, fill it with the background value
  553 + new_grid.value.resize(numValues, background);
  554 +
  555 + //insert this grid into the new one
  556 + new_grid.insert(*this);
  557 +
  558 + //copy the new grid to this grid
  559 + conn = new_grid.conn;
  560 + value = new_grid.value;
  561 +}
  562 +
  563 +template<typename T>
  564 +bool rtsDTGrid1D<T>::randomIndex(int &v, int &c, int x1)
  565 +{
  566 + //if the grid is empty return false
  567 + if(value.size() == 0)
  568 + return false;
  569 +
  570 + int low = 0;
  571 + int high = conn.size()-1;
  572 + int mid;
  573 + do
  574 + {
  575 + mid = low + (high - low)/2;
  576 + if(x1 > conn[mid].coordMax)
  577 + low = mid + 1;
  578 + //else if(x1 < conn[mid].coordMin)
  579 + else if(x1 < conn[mid].coordMin)
  580 + high = mid - 1;
  581 + else break;
  582 + }
  583 + while(low <= high);
  584 +
  585 + //at this point, mid is either at the appropriate connected component,
  586 + //or x1 is not in the grid
  587 + int offset = x1 - conn[mid].coordMin;
  588 + v = conn[mid].toValue + offset;
  589 + c = mid;
  590 + if(x1 >= conn[mid].coordMin && x1 <= conn[mid].coordMax)
  591 + {
  592 + return true;
  593 + }
  594 + else
  595 + {
  596 + return false;
  597 + }
  598 +}
  599 +
  600 +template<typename T>
  601 +void rtsDTGrid1D<T>::operator=(T rhs)
  602 +{
  603 + for(int i=0; i<value.size(); i++)
  604 + value[i] = rhs;
  605 +}
  606 +template<typename T>
  607 +T& rtsDTGrid1D<T>::back()
  608 +{
  609 + return value[value.size()-1];
  610 +}
  611 +
  612 +template<typename T>
  613 +T rtsDTGrid1D<T>::random(int x1)
  614 +{
  615 + int v_i, c_i;
  616 +
  617 + if(randomIndex(v_i, c_i, x1))
  618 + return value[v_i];
  619 + else
  620 + return background;
  621 +}
  622 +
  623 +
  624 +#endif
... ...
rtsDTGrid1D_v1.h 0 → 100755
  1 +++ a/rtsDTGrid1D_v1.h
  1 +
  2 +#include <vector>
  3 +#include <iostream>
  4 +using namespace std;
  5 +
  6 +#ifndef _RTS_DTGRID1D_H
  7 +#define _RTS_DTGRID1D_H
  8 +
  9 +struct ConnectedComponent
  10 +{
  11 + int toValue;
  12 + int coordMin;
  13 + int coordMax;
  14 +};
  15 +
  16 +
  17 +
  18 +
  19 +template<typename T>
  20 +class rtsDTGrid1D
  21 +{
  22 +
  23 +private:
  24 + //main arrays
  25 + vector<T> value;
  26 + vector<ConnectedComponent> conn;
  27 +
  28 + //variables to keep track of insertion
  29 + int max_coord;
  30 + bool insertion_started;
  31 + bool randomIndex(int &v, int &c, int x1);
  32 +
  33 +
  34 +public:
  35 + T background;
  36 + rtsDTGrid1D<T>()
  37 + {
  38 + insertion_started = false;
  39 + max_coord = 0;
  40 + }
  41 + int getMaxX1(){return max_coord;}
  42 +
  43 + T random(int x1);
  44 + T& back();
  45 + bool push(int x1, T value);
  46 + void insert(rtsDTGrid1D<T> toInsert);
  47 + void getBounds(int &min_x1, int &max_x1);
  48 + void dilate(int H);
  49 + template<typename P> rtsDTGrid1D<P> getStorage()
  50 + {
  51 + //create the resulting grid
  52 + rtsDTGrid1D<P> result;
  53 + //create an iterator to run over the existing grid
  54 + P* new_value = (P*)calloc(1, sizeof(P));
  55 + for(iterator i = begin(); i!=end(); i.increment())
  56 + {
  57 + result.push(i.X1(), *new_value);
  58 + }
  59 + return result;
  60 +
  61 + }
  62 + void operator=(T rhs);
  63 + void print();
  64 +
  65 + //iterator
  66 + class iterator;
  67 + friend class iterator;
  68 + class stencil_iterator;
  69 + iterator randomIterator(int x1);
  70 + iterator begin();
  71 + iterator end();
  72 + iterator before();
  73 + iterator after();
  74 +
  75 +};
  76 +
  77 +/***************ITERATOR*************************/
  78 +template<typename T>
  79 +class rtsDTGrid1D<T>::iterator
  80 +{
  81 + friend class rtsDTGrid1D;
  82 +
  83 +
  84 +protected:
  85 + rtsDTGrid1D<T>* parent;
  86 + int iv;
  87 + int ic;
  88 + int x1;
  89 +
  90 +public:
  91 + T Value(){return parent->value[iv];}
  92 + int X1(){return x1;}
  93 + void SetValue(T val){parent->value[iv] = val;}
  94 +
  95 + iterator(){parent = NULL;}
  96 +
  97 + void increment()
  98 + {
  99 + //increment the current coordinate and value
  100 + x1++;
  101 + iv++;
  102 + //if we are outside of the current connected component
  103 + if(x1 > parent->conn[ic].coordMax)
  104 + {
  105 + //if this is the last connected component, set the iterator to END and return
  106 + if(ic == parent->conn.size() - 1)
  107 + {
  108 + (*this) = parent->after();
  109 + return;
  110 + }
  111 + //otherwise move to the next connected component and update the coordinate
  112 + ic++;
  113 + x1 = parent->conn[ic].coordMin;
  114 + }
  115 + }
  116 +
  117 + //boolean operators for comparing iterators
  118 + bool operator==(iterator rhs)
  119 + {
  120 + if(parent == rhs.parent && iv == rhs.iv)
  121 + return true;
  122 + return false;
  123 + }
  124 + bool operator!=(iterator rhs){return !((*this) == rhs);}
  125 + friend bool operator<(iterator &left, iterator &right)
  126 + {
  127 + if(left.iv < right.iv)
  128 + return true;
  129 + return false;
  130 + }
  131 + friend bool operator<=(iterator &left, iterator &right)
  132 + {
  133 + if(left.iv <= right.iv)
  134 + return true;
  135 + return false;
  136 + }
  137 + void operator++(){increment();}
  138 +
  139 + void increment_until(int pos)
  140 + {
  141 + while(x1 < pos && (*this) != parent->after())
  142 + {
  143 + p();
  144 + }
  145 + }
  146 +};
  147 +
  148 +
  149 +/************STENCIL ITERATOR********************/
  150 +template<typename T>
  151 +class rtsDTGrid1D<T>::stencil_iterator : public iterator
  152 +{
  153 +private:
  154 + //list of iterators that make up the template
  155 + vector<iterator> iterator_list;
  156 + //iterator positions (relative to the position of the stencil iterator)
  157 + vector<int> position_list;
  158 + //list containing the values for each position in the stencil
  159 + vector<T> value_list;
  160 +
  161 + void refresh_iterators();
  162 + void set_values();
  163 + void increment_all();
  164 +
  165 +public:
  166 + typename rtsDTGrid1D<T>::stencil_iterator operator=(const iterator rhs);
  167 + void addPosition(int p);
  168 + void operator++(){p();}
  169 + void p();
  170 + T getValue(int id){return value_list[id];}
  171 + bool exists(int id);
  172 +
  173 +};
  174 +
  175 +template<typename T>
  176 +void rtsDTGrid1D<T>::stencil_iterator::increment_all()
  177 +{
  178 + //run through each iterator and increment to the correct position
  179 + int i;
  180 + int dest;
  181 + for(i=0; i<iterator_list.size(); i++)
  182 + {
  183 + //determine the appropriate position for the iterator
  184 + dest = x1 + position_list[i];
  185 + //iterate until that position is reached
  186 + iterator_list[i].increment_until(dest);
  187 + set_values();
  188 + }
  189 +
  190 +}
  191 +
  192 +template<typename T>
  193 +void rtsDTGrid1D<T>::stencil_iterator::increment()
  194 +{
  195 + //increment the current position
  196 + rtsDTGrid1D<T>::iterator::increment();
  197 +
  198 + increment_all();
  199 +}
  200 +
  201 +template<typename T>
  202 +void rtsDTGrid1D<T>::stencil_iterator::refresh_iterators()
  203 +{
  204 + //make sure that the iterator position has been set
  205 + if(parent == NULL)
  206 + {
  207 + cout<<"Iterator location not set."<<endl;
  208 + return;
  209 + }
  210 +
  211 + //initialize all of the other iterators
  212 + int i;
  213 + for(i=0; i<iterator_list.size(); i++)
  214 + {
  215 + //for each iterator, set the iterator to the beginning of the grid
  216 + iterator_list[i] = parent->begin();
  217 + }
  218 + increment_all();
  219 + //set the values for all of the iterators
  220 + set_values();
  221 +}
  222 +
  223 +template<typename T>
  224 +void rtsDTGrid1D<T>::stencil_iterator::set_values()
  225 +{
  226 + int i;
  227 + int dest;
  228 + for(i=0; i<iterator_list.size(); i++)
  229 + {
  230 + //determine the appropriate position for the iterator
  231 + dest = x1 + position_list[i];
  232 + //now add the value to the value list
  233 + if(iterator_list[i].X1() == dest)
  234 + value_list[i] = iterator_list[i].Value();
  235 + else
  236 + value_list[i] = parent->background;
  237 + }
  238 +
  239 +
  240 +}
  241 +
  242 +template<typename T>
  243 +typename rtsDTGrid1D<T>::stencil_iterator rtsDTGrid1D<T>::stencil_iterator::operator=(const iterator rhs)
  244 +{
  245 + parent = rhs.parent;
  246 + iv = rhs.iv;
  247 + ic = rhs.ic;
  248 + x1 = rhs.x1;
  249 +
  250 + refresh_iterators();
  251 +
  252 + return (*this);
  253 +}
  254 +
  255 +template<typename T>
  256 +void rtsDTGrid1D<T>::stencil_iterator::addPosition(int p)
  257 +{
  258 + position_list.push_back(p);
  259 + rtsDTGrid1D<T>::iterator new_iter;
  260 + /*If the parent variable is valid (the current iterator is assigned to
  261 + a grid), assign the position just added to the same grid.
  262 + If the parent isn't set, all iterators are assigned to the appropriate grid
  263 + later on when the operator= is used to assign the grid to the stencil.
  264 + */
  265 + if(parent != NULL)
  266 + {
  267 + new_iter = parent->begin();
  268 + refresh_iterators();
  269 + }
  270 +
  271 + iterator_list.push_back(new_iter);
  272 + value_list.resize(value_list.size() + 1);
  273 +}
  274 +
  275 +template<typename T>
  276 +bool rtsDTGrid1D<T>::stencil_iterator::exists(int id)
  277 +{
  278 + //returns true if the iterator defined by id points to an actual grid node
  279 +
  280 + //determine the appropriate position for the iterator
  281 + int dest = x1 + position_list[id];
  282 +
  283 + if(iterator_list[id].X1() == dest)
  284 + return true;
  285 + else
  286 + return false;
  287 +
  288 +}
  289 +
  290 +
  291 +/**************ITERATOR METHODS IN DT GRID*******************/
  292 +template<typename T>
  293 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::begin()
  294 +{
  295 + //if the grid is empty, return after()
  296 + if(value.size() == 0)
  297 + return after();
  298 +
  299 + iterator result;
  300 + result.parent = this;
  301 + result.ic = 0;
  302 + result.iv = 0;
  303 + result.x1 = conn[0].coordMin;
  304 + return result;
  305 +}
  306 +template<typename T>
  307 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::before()
  308 +{
  309 + //if the grid is empty, return after()
  310 + if(value.size() == 0)
  311 + return after();
  312 +
  313 + iterator result;
  314 + result.parent = this;
  315 + result.ic = 0;
  316 + result.iv = -1;
  317 + //result.x1 = conn[0].coordMin;
  318 + return result;
  319 +}
  320 +
  321 +template<typename T>
  322 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::end()
  323 +{
  324 + //if the grid is empty, return after()
  325 + if(value.size() == 0)
  326 + return after();
  327 +
  328 + iterator result;
  329 + result.parent = this;
  330 + result.ic = conn.size() - 1;
  331 + result.iv = value.size() - 1;
  332 + result.x1 = conn[result.ic].coordMax;
  333 + return result;
  334 +}
  335 +template<typename T>
  336 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::after()
  337 +{
  338 + iterator result;
  339 + result.parent = this;
  340 + result.ic = conn.size() - 1;
  341 + result.iv = value.size();
  342 + //result.x1 = conn[result.ic].coordMax;
  343 + return result;
  344 +}
  345 +
  346 +
  347 +
  348 +
  349 +template<typename T>
  350 +typename rtsDTGrid1D<T>::iterator rtsDTGrid1D<T>::randomIterator(int x1)
  351 +{
  352 + //if the grid is empty return a "after" iterator
  353 + if(value.size() == 0)
  354 + return after();
  355 +
  356 + rtsDTGrid1D<T>::iterator result;
  357 + result.parent = this;
  358 + int v_i, c_i;
  359 +
  360 + //if the value exists in the grid, create the iterator and return
  361 + if(randomIndex(v_i, c_i, x1))
  362 + {
  363 + result.iv = v_i;
  364 + result.ic = c_i;
  365 + int offset = v_i - conn[c_i].toValue;
  366 + result.x1 = conn[c_i].coordMin + offset;
  367 + }
  368 + //if the value doesn't exist
  369 + else
  370 + {
  371 + //if the value lies before the current column
  372 + if(x1 < conn[c_i].coordMin)
  373 + {
  374 + result.ic = c_i;
  375 +
  376 + }
  377 + else
  378 + {
  379 + //if this is the last connected component
  380 + if(c_i >= conn.size() - 1)
  381 + return after();
  382 + else
  383 + {
  384 + c_i++;
  385 + result.ic = c_i;
  386 + }
  387 + }
  388 + result.iv = conn[c_i].toValue;
  389 + result.x1 = conn[c_i].coordMin;
  390 + }
  391 + return result;
  392 +
  393 +}
  394 +template<typename T>
  395 +void rtsDTGrid1D<T>::print()
  396 +{
  397 + rtsDTGrid1D<T>::iterator i;
  398 + i = begin();
  399 + while(i != after())
  400 + {
  401 + cout<<i.X1()<<":"<<i.Value()<<endl;
  402 + i++;
  403 + }
  404 +
  405 +
  406 +}
  407 +
  408 +/**************DT GRID**************************/
  409 +template<typename T>
  410 +bool rtsDTGrid1D<T>::push(int x1, T v)
  411 +{
  412 + //test to make sure the insertion is happening in the right order
  413 + if(insertion_started && x1 <= max_coord)
  414 + {
  415 + cout<<"Out-of-order insertion in D = 1: X1 = "<<x1<<endl;
  416 + return false;
  417 + }
  418 +
  419 +
  420 + //run this code if we have to start a new connected component. This happens when:
  421 + //(a) We insert the first value into the grid
  422 + //(b) There is empty space between the last insertion and this one
  423 + if(insertion_started == false || x1 > (max_coord + 1))
  424 + {
  425 + //start a new connected component
  426 + ConnectedComponent new_conn;
  427 + new_conn.toValue = value.size();
  428 + new_conn.coordMin = x1;
  429 + new_conn.coordMax = x1;
  430 + conn.push_back(new_conn);
  431 + insertion_started = true;
  432 + }
  433 +
  434 + //insert the value into the grid:
  435 + //(a) Insert the value at the end of the coord array
  436 + //(b) Increment the coordMax value of the current connected component
  437 + //(c) Change the maximum inserted coordinate to the new value
  438 + value.push_back(v);
  439 + conn[conn.size() - 1].coordMax = x1;
  440 + //change max_coord to the new coordinate
  441 + max_coord = x1;
  442 + return true;
  443 +}
  444 +
  445 +template<typename T>
  446 +void rtsDTGrid1D<T>::insert(rtsDTGrid1D<T> toInsert)
  447 +{
  448 + //create source and destination iterators
  449 + rtsDTGrid1D<T>::iterator source = toInsert.begin();
  450 + rtsDTGrid1D<T>::iterator dest = begin();
  451 +
  452 + while(source != toInsert.after())
  453 + {
  454 + //move the destination iterator to the current source position
  455 + dest.increment_until(source.X1());
  456 + //if the position exists in dest
  457 + if(dest.X1() == source.X1())
  458 + dest.SetValue(source.Value());
  459 + source++;
  460 + }
  461 +
  462 +}
  463 +
  464 +template<typename T>
  465 +void rtsDTGrid1D<T>::getBounds(int &min_x1, int &max_x1)
  466 +{
  467 + //return an empty bounding volume if the grid is empty
  468 + if(value.size() == 0)
  469 + {
  470 + min_x1 = 0;
  471 + max_x1 = 0;
  472 + return;
  473 + }
  474 +
  475 + //get the minimum and maximum coordinates
  476 + min_x1 = conn[0].coordMin;
  477 + max_x1 = conn.back().coordMax;
  478 +}
  479 +template<typename T>
  480 +void rtsDTGrid1D<T>::dilate(int H)
  481 +{
  482 + //this function creates a new DT grid dilated by H and copies
  483 + //the original grid into the new grid
  484 +
  485 + //create a new grid
  486 + rtsDTGrid1D<T> new_grid;
  487 +
  488 + //determine the dilated values for the first connected component
  489 + int numValues = 0;
  490 + int start = conn[0].coordMin - H;
  491 + int end = conn[0].coordMax + H;
  492 +
  493 + //run through each remaining connected component
  494 + for(int i=1; i<conn.size(); i++)
  495 + {
  496 + //if the new component and the i'th ones overlap, combine them
  497 + //cout<<conn[i].coordMin - H<<endl;
  498 + if(conn[i].coordMin - H <= end)
  499 + end = conn[i].coordMax + H;
  500 + else
  501 + {
  502 + //store the dilated connected component
  503 + ConnectedComponent cc;
  504 + cc.coordMin = start;
  505 + cc.coordMax = end;
  506 + cc.toValue = numValues;
  507 + numValues += end - start + 1;
  508 + new_grid.conn.push_back(cc);
  509 +
  510 + //start a new dilated connected component
  511 + start = conn[i].coordMin - H;
  512 + end = conn[i].coordMax + H;
  513 + }
  514 + }
  515 + //add the last dilated connected component
  516 + ConnectedComponent cc;
  517 + cc.coordMin = start;
  518 + cc.coordMax = end;
  519 + cc.toValue = numValues;
  520 + numValues += end - start + 1;
  521 + new_grid.conn.push_back(cc);
  522 + //allocate space in the value array, fill it with the background value
  523 + new_grid.value.resize(numValues, background);
  524 +
  525 + //insert this grid into the new one
  526 + new_grid.insert(*this);
  527 +
  528 + //copy the new grid to this grid
  529 + conn = new_grid.conn;
  530 + value = new_grid.value;
  531 +}
  532 +
  533 +template<typename T>
  534 +bool rtsDTGrid1D<T>::randomIndex(int &v, int &c, int x1)
  535 +{
  536 + //if the grid is empty return false
  537 + if(value.size() == 0)
  538 + return false;
  539 +
  540 + int low = 0;
  541 + int high = conn.size()-1;
  542 + int mid;
  543 + do
  544 + {
  545 + mid = low + (high - low)/2;
  546 + if(x1 > conn[mid].coordMax)
  547 + low = mid + 1;
  548 + //else if(x1 < conn[mid].coordMin)
  549 + else if(x1 < conn[mid].coordMin)
  550 + high = mid - 1;
  551 + else break;
  552 + }
  553 + while(low <= high);
  554 +
  555 + //at this point, mid is either at the appropriate connected component,
  556 + //or x1 is not in the grid
  557 + int offset = x1 - conn[mid].coordMin;
  558 + v = conn[mid].toValue + offset;
  559 + c = mid;
  560 + if(x1 >= conn[mid].coordMin && x1 <= conn[mid].coordMax)
  561 + {
  562 + return true;
  563 + }
  564 + else
  565 + {
  566 + return false;
  567 + }
  568 +}
  569 +
  570 +template<typename T>
  571 +void rtsDTGrid1D<T>::operator=(T rhs)
  572 +{
  573 + for(int i=0; i<value.size(); i++)
  574 + value[i] = rhs;
  575 +}
  576 +template<typename T>
  577 +T& rtsDTGrid1D<T>::back()
  578 +{
  579 + return value[value.size()-1];
  580 +}
  581 +
  582 +template<typename T>
  583 +T rtsDTGrid1D<T>::random(int x1)
  584 +{
  585 + int v_i, c_i;
  586 +
  587 + if(randomIndex(v_i, c_i, x1))
  588 + return value[v_i];
  589 + else
  590 + return background;
  591 +}
  592 +
  593 +
  594 +#endif
... ...
rtsDTGrid2D.h 0 → 100755
  1 +++ a/rtsDTGrid2D.h
  1 +
  2 +#ifndef _RTS_DTGRID2D_H
  3 +#define _RTS_DTGRID2D_H
  4 +
  5 +#include <vector>
  6 +#include <iostream>
  7 +using namespace std;
  8 +
  9 +#include "rtsDTGrid1D.h"
  10 +
  11 +
  12 +
  13 +struct IndexPair
  14 +{
  15 + //int toValue;
  16 + int toConn;
  17 + int numConn;
  18 +};
  19 +
  20 +
  21 +struct Coord2D
  22 +{
  23 + int x1;
  24 + int x2;
  25 +};
  26 +
  27 +#include <list>
  28 +using namespace std;
  29 +
  30 +class ColumnUnion
  31 +{
  32 +private:
  33 + list<IndexPair> Q;
  34 + vector<ConnectedComponent>* toConn;
  35 +
  36 +public:
  37 + void InsertColumn(IndexPair col)
  38 + {
  39 + Q.push_back(col);
  40 + }
  41 + void RemoveColumn()
  42 + {
  43 + Q.pop_front();
  44 + }
  45 + vector<ConnectedComponent> MergeColumns(vector<ConnectedComponent> *Pc,
  46 + vector<ConnectedComponent> *n,
  47 + int H)
  48 + {
  49 + int i_Pc = 0;
  50 + int i_n = 0;
  51 + int smallest_column;
  52 + ConnectedComponent smallest_cc;
  53 + vector<ConnectedComponent> result;
  54 +
  55 + //iterate while there are remaining connected components in each column
  56 + while(i_Pc < Pc->size() || i_n < n->size())
  57 + {
  58 + //find the smallest coordMin value at the two index locations
  59 +
  60 + //if the index is at the end of the primary array
  61 + if(i_Pc == Pc->size())
  62 + {
  63 + smallest_cc = n->at(i_n);
  64 + smallest_cc.coordMin -= H;
  65 + smallest_cc.coordMax += H;
  66 + i_n++;
  67 + }
  68 + //if n is at the end of the array
  69 + else if(i_n == n->size())
  70 + {
  71 + smallest_cc = Pc->at(i_Pc);
  72 + i_Pc++;
  73 + }
  74 + else if(n->at(i_n).coordMin - H < Pc->at(i_Pc).coordMin)
  75 + {
  76 + smallest_cc = n->at(i_n);
  77 + smallest_cc.coordMin -= H;
  78 + smallest_cc.coordMax += H;
  79 + i_n++;
  80 + }
  81 + else
  82 + {
  83 + smallest_cc = Pc->at(i_Pc);
  84 + i_Pc++;
  85 + }
  86 +
  87 + //merge the connected component into result
  88 + //if the result array is empty or the last connected component doesn't overlap with smallest_cc
  89 + if(result.size() == 0 || result.back().coordMax + 1 < smallest_cc.coordMin)
  90 + result.push_back(smallest_cc);
  91 + else if(result.back().coordMax < smallest_cc.coordMax)
  92 + result.back().coordMax = smallest_cc.coordMax;
  93 + }
  94 + return result;
  95 +
  96 + }
  97 +
  98 + vector<ConnectedComponent> ComputeUnion(int H)
  99 + {
  100 + //create a vector to store the result
  101 + vector<ConnectedComponent> result;
  102 +
  103 + //for each column in the list, merge it with the result vector
  104 + list<IndexPair>::iterator i;
  105 + vector<ConnectedComponent>::iterator start;
  106 + vector<ConnectedComponent>::iterator end;
  107 + for(i = Q.begin(); i != Q.end(); i++)
  108 + {
  109 + start = toConn->begin() + (*i).toConn;
  110 + end = start + (*i).numConn;
  111 + vector<ConnectedComponent> column(start, end);
  112 + result = MergeColumns(&result, &column, H);
  113 + }
  114 +
  115 + //output result
  116 + //for(int i=0; i<result.size(); i++)
  117 + // cout<<i<<": "<<result[i].coordMin<<"--"<<result[i].coordMax<<endl;
  118 +
  119 + return result;
  120 + }
  121 + void ConnectToGrid(vector<ConnectedComponent> *cc_list)
  122 + {
  123 + toConn = cc_list;
  124 + }
  125 +};
  126 +
  127 +
  128 +/*vector<ConnectedComponent> ColumnUnion::MergeColumns(vector<ConnectedComponent> *Pc, vector<ConnectedComponent> *n, int H)
  129 +{
  130 + int i_Pc = 0;
  131 + int i_n = 0;
  132 + int smallest_column;
  133 + ConnectedComponent smallest_cc;
  134 + vector<ConnectedComponent> result;
  135 +
  136 + //iterate while there are remaining connected components in each column
  137 + while(i_Pc < Pc->size() || i_n < n->size())
  138 + {
  139 + //find the smallest coordMin value at the two index locations
  140 +
  141 + //if the index is at the end of the primary array
  142 + if(i_Pc == Pc->size())
  143 + {
  144 + smallest_cc = n->at(i_n);
  145 + smallest_cc.coordMin -= H;
  146 + smallest_cc.coordMax += H;
  147 + i_n++;
  148 + }
  149 + //if n is at the end of the array
  150 + else if(i_n == n->size())
  151 + {
  152 + smallest_cc = Pc->at(i_Pc);
  153 + i_Pc++;
  154 + }
  155 + else if(n->at(i_n).coordMin - H < Pc->at(i_Pc).coordMin)
  156 + {
  157 + smallest_cc = n->at(i_n);
  158 + smallest_cc.coordMin -= H;
  159 + smallest_cc.coordMax += H;
  160 + i_n++;
  161 + }
  162 + else
  163 + {
  164 + smallest_cc = Pc->at(i_Pc);
  165 + i_Pc++;
  166 + }
  167 +
  168 + //merge the connected component into result
  169 + //if the result array is empty or the last connected component doesn't overlap with smallest_cc
  170 + if(result.size() == 0 || result.back().coordMax + 1 < smallest_cc.coordMin)
  171 + result.push_back(smallest_cc);
  172 + else if(result.back().coordMax < smallest_cc.coordMax)
  173 + result.back().coordMax = smallest_cc.coordMax;
  174 + }
  175 + return result;
  176 +}*/
  177 +
  178 +/*vector<ConnectedComponent> ColumnUnion::ComputeUnion(int H)
  179 +{
  180 +
  181 + //create a vector to store the result
  182 + vector<ConnectedComponent> result;
  183 +
  184 + //for each column in the list, merge it with the result vector
  185 + list<IndexPair>::iterator i;
  186 + vector<ConnectedComponent>::iterator start;
  187 + vector<ConnectedComponent>::iterator end;
  188 + for(i = Q.begin(); i != Q.end(); i++)
  189 + {
  190 + start = toConn->begin() + (*i).toConn;
  191 + end = start + (*i).numConn;
  192 + vector<ConnectedComponent> column(start, end);
  193 + result = MergeColumns(&result, &column, H);
  194 + }
  195 +
  196 + //output result
  197 + //for(int i=0; i<result.size(); i++)
  198 + // cout<<i<<": "<<result[i].coordMin<<"--"<<result[i].coordMax<<endl;
  199 +
  200 + return result;
  201 +}
  202 +*/
  203 +
  204 +
  205 +template<typename T>
  206 +class rtsDTGrid2D
  207 +{
  208 +private:
  209 + //main arrays
  210 + vector<T> value;
  211 + vector<ConnectedComponent> conn;
  212 + rtsDTGrid1D<IndexPair> proj1D;
  213 + bool randomIndex(rtsDTGrid1D<IndexPair>::iterator &iter1D, int &v_i, int &c_i, int x1, int x2);
  214 +
  215 +
  216 +
  217 + //variables to keep track of insertion
  218 + int max_coord;
  219 + bool grid_insertion_started;
  220 + bool column_insertion_started;
  221 +
  222 +
  223 +public:
  224 + rtsDTGrid2D<T>()
  225 + {
  226 + grid_insertion_started = false;
  227 + column_insertion_started = false;
  228 + proj1D.background.toConn = -1;
  229 + max_coord = 0;
  230 + }
  231 +
  232 + bool push(int x1, int x2, T v);
  233 + T random(int x1, int x2);
  234 + T& back();
  235 + T background;
  236 + void print();
  237 +
  238 + friend class ColumnUnion;
  239 + void dilate(int H);
  240 + void insert(rtsDTGrid2D<T> toInsert);
  241 + void operator=(T rhs);
  242 + void getBounds(int &min_x1, int &min_x2, int &max_x1, int &max_x2);
  243 +
  244 + void dumpValue();
  245 + void dumpConn();
  246 +
  247 + //iterator
  248 + class iterator;
  249 + friend class iterator;
  250 + class stencil_iterator;
  251 + iterator randomIterator(int x1, int x2);
  252 + iterator begin();
  253 + iterator before();
  254 + iterator end();
  255 + iterator after();
  256 +
  257 + //other types of iteration
  258 + iterator begin_pn();
  259 + iterator end_pn();
  260 + iterator begin_np();
  261 + iterator end_np();
  262 +};
  263 +
  264 +/**********ITERATOR***********************/
  265 +template<typename T>
  266 +class rtsDTGrid2D<T>::iterator
  267 +{
  268 + friend class rtsDTGrid2D;
  269 + rtsDTGrid2D<T>* parent;
  270 + rtsDTGrid1D<IndexPair>::iterator loc1D;
  271 + int iv;
  272 + int ic;
  273 + int x2;
  274 +
  275 +public:
  276 +
  277 +
  278 + T Value(){return parent->value[iv];}
  279 + int X1(){return loc1D.X1();}
  280 + int X2(){return x2;}
  281 + iterator(){parent = NULL;}
  282 + void SetValue(T value){parent->value[iv] = value;}
  283 +
  284 +
  285 + void pp()
  286 + {
  287 + //increment the value
  288 + iv++;
  289 + //if this exceeds the length of the value array, we are at the end of the grid
  290 + if(iv == parent->value.size())
  291 + {
  292 + (*this) = parent->after();
  293 + return;
  294 + }
  295 +
  296 + //increment the current coordinate
  297 + x2++;
  298 + //if we are outside of the current connected component
  299 + if(x2 > parent->conn[ic].coordMax)
  300 + {
  301 + //move to the next connected component
  302 + ic++;
  303 + //if this is the last connected component in the column
  304 + if(ic == loc1D.Value().toConn + loc1D.Value().numConn)
  305 + loc1D++;
  306 + //if there are no more connected components
  307 + if(ic == parent->conn.size())
  308 + {
  309 + //we're at the end, return end
  310 + (*this) = parent->end();
  311 + return;
  312 + }
  313 + x2 = parent->conn[ic].coordMin;
  314 + }
  315 + }
  316 +
  317 + void nn()
  318 + {
  319 + //decrement the value
  320 + iv--;
  321 + //if this is less than 0, we are at the beginning of the grid
  322 + if(iv < 0)
  323 + {
  324 + (*this) = parent->before();
  325 + return;
  326 + }
  327 +
  328 + //decrement the current coordinate
  329 + x2--;
  330 + //if we are outside of the current connected component
  331 + if(x2 < parent->conn[ic].coordMin)
  332 + {
  333 + //move to the previous connected component
  334 + ic--;
  335 + //if this is the first connected component in the column
  336 + if(ic < loc1D.Value().toConn)
  337 + loc1D--;
  338 + //if there are no more connected components
  339 + if(ic < 0)
  340 + {
  341 + //we're at the beginning, return begin
  342 + (*this) = parent->before();
  343 + return;
  344 + }
  345 + x2 = parent->conn[ic].coordMax;
  346 + }
  347 +
  348 + }
  349 +
  350 + void pn()
  351 + {
  352 + //for the most part we will be going backwards through the array
  353 + //so first decrement iv
  354 + iv--;
  355 + x2--;
  356 + //if iv is less than the current connected component
  357 + if(iv < parent->conn[ic].toValue)
  358 + {
  359 + //go to the previous connected component
  360 + ic--;
  361 + //if we are before the first connected component in the column
  362 + if(ic < loc1D.Value().toConn)
  363 + {
  364 + //increment the 1D iterator
  365 + loc1D++;
  366 + //reset ic to the last component of the new column
  367 + ic = loc1D.Value().toConn + loc1D.Value().numConn - 1;
  368 + //find the new value identifier
  369 + iv = parent->conn[ic].toValue + (parent->conn[ic].coordMax - parent->conn[ic].coordMin);
  370 + }
  371 + //compute the currect coordinate
  372 + x2 = parent->conn[ic].coordMax;
  373 + }
  374 + }
  375 +
  376 + void np()
  377 + {
  378 + //for the most part we will be going forward through the grid
  379 + //increment iv
  380 + iv++;
  381 + x2++;
  382 +
  383 + //if we are outside of the current connected component
  384 + if(x2 > parent->conn[ic].coordMax)
  385 + {
  386 + //move to the next connected component
  387 + ic++;
  388 + //if this is the last connected component in the column
  389 + if(ic == loc1D.Value().toConn + loc1D.Value().numConn)
  390 + {
  391 + loc1D--;
  392 + ic = loc1D.Value().toConn;
  393 + iv = parent->conn[ic].toValue;
  394 + }
  395 +
  396 + x2 = parent->conn[ic].coordMin;
  397 + }
  398 +
  399 + }
  400 +
  401 + //boolean operators for comparing iterators
  402 + bool operator==(iterator &rhs)
  403 + {
  404 + if(parent == rhs.parent && iv == rhs.iv)
  405 + return true;
  406 + //if(loc1D == rhs.loc1D && x2 == rhs.x2)
  407 + // return true;
  408 + return false;
  409 + }
  410 + bool operator!=(iterator &rhs){return !((*this) == rhs);}
  411 +
  412 + bool operator<(iterator &rhs)
  413 + {
  414 + if(parent == rhs.parent && iv < rhs.iv)
  415 + return true;
  416 + //if(loc1D < rhs.loc1D)
  417 + // return true;
  418 + //else if(loc1D == rhs.loc1D && x2 < rhs.x2)
  419 + // return true;
  420 + return false;
  421 + }
  422 + bool operator<=(iterator &rhs)
  423 + {
  424 + if(parent == rhs.parent && iv <= rhs.iv)
  425 + return true;
  426 + //if(loc1D <= rhs.loc1D)
  427 + // return true;
  428 + //else if(loc1D == rhs.loc1D && x2 <= rhs.x2)
  429 + // return true;
  430 + return false;
  431 + }
  432 + void operator++(){pp();}
  433 + void operator--(){nn();}
  434 + void increment_until(int p1, int p2)
  435 + {
  436 + while((*this) != parent->end())
  437 + {
  438 + if(X1() > p1)
  439 + return;
  440 + else if(X1() == p1 && X2() >= p2)
  441 + return;
  442 +
  443 + pp();
  444 + }
  445 + }
  446 +};
  447 +
  448 +/********STENCIL ITERATOR*****************/
  449 +template<typename T>
  450 +class rtsDTGrid2D<T>::stencil_iterator : public iterator
  451 +{
  452 +private:
  453 + //list of iterators that make up the template
  454 + vector<iterator> iterator_list;
  455 + //iterator positions (relative to the position of the stencil iterator)
  456 + vector<Coord2D> position_list;
  457 + //list containing the values for each position in the stencil
  458 + vector<T> value_list;
  459 +
  460 + void refresh_iterators();
  461 + void set_values();
  462 + void increment_all();
  463 +
  464 +public:
  465 + typename rtsDTGrid2D<T>::stencil_iterator operator=(const iterator rhs);
  466 + void addPosition(int p1, int p2);
  467 + void increment();
  468 + void operator++()
  469 + {
  470 + increment();
  471 + }
  472 + T getValue(int id){return value_list[id];}
  473 + bool exists(int id);
  474 +
  475 +};
  476 +
  477 +template<typename T>
  478 +void rtsDTGrid2D<T>::stencil_iterator::increment_all()
  479 +{
  480 + //run through each iterator and increment to the correct position
  481 + int i;
  482 + Coord2D dest;
  483 + for(i=0; i<iterator_list.size(); i++)
  484 + {
  485 + //determine the appropriate position for the iterator
  486 + dest.x1 = X1() + position_list[i].x1;
  487 + dest.x2 = X2() + position_list[i].x2;
  488 + //iterate until that position is reached
  489 + iterator_list[i].increment_until(dest.x1, dest.x2);
  490 + }
  491 + set_values();
  492 +
  493 +}
  494 +
  495 +template<typename T>
  496 +void rtsDTGrid2D<T>::stencil_iterator::increment()
  497 +{
  498 + //increment the current position
  499 + rtsDTGrid2D<T>::iterator::pp();
  500 +
  501 + increment_all();
  502 +}
  503 +
  504 +template<typename T>
  505 +void rtsDTGrid2D<T>::stencil_iterator::refresh_iterators()
  506 +{
  507 + //make sure that the iterator position has been set
  508 + if(parent == NULL)
  509 + {
  510 + cout<<"Iterator location not set."<<endl;
  511 + return;
  512 + }
  513 +
  514 + //initialize all of the other iterators
  515 + int i;
  516 + for(i=0; i<iterator_list.size(); i++)
  517 + {
  518 + //for each iterator, set the iterator to the beginning of the grid
  519 + //iterator_list[i] = parent->begin();
  520 + iterator_list[i] = parent->randomIterator(X1() + position_list[i].x1,
  521 + X2() + position_list[i].x2);
  522 + }
  523 + //increment_all();
  524 + //set the values for all of the iterators
  525 + set_values();
  526 +}
  527 +
  528 +template<typename T>
  529 +void rtsDTGrid2D<T>::stencil_iterator::set_values()
  530 +{
  531 + int i;
  532 + Coord2D dest;
  533 + for(i=0; i<iterator_list.size(); i++)
  534 + {
  535 + //determine the appropriate position for the iterator
  536 + dest.x1 = X1() + position_list[i].x1;
  537 + dest.x2 = X2() + position_list[i].x2;
  538 + //now add the value to the value list
  539 + if(iterator_list[i].X1() == dest.x1 && iterator_list[i].X2() == dest.x2)
  540 + value_list[i] = iterator_list[i].Value();
  541 + else
  542 + value_list[i] = parent->background;
  543 + }
  544 +
  545 +
  546 +}
  547 +
  548 +template<typename T>
  549 +typename rtsDTGrid2D<T>::stencil_iterator rtsDTGrid2D<T>::stencil_iterator::operator=(const iterator rhs)
  550 +{
  551 + parent = rhs.parent;
  552 + loc1D = rhs.loc1D;
  553 + iv = rhs.iv;
  554 + ic = rhs.ic;
  555 + x2 = rhs.x2;
  556 +
  557 + refresh_iterators();
  558 +
  559 + return (*this);
  560 +}
  561 +
  562 +template<typename T>
  563 +void rtsDTGrid2D<T>::stencil_iterator::addPosition(int p1, int p2)
  564 +{
  565 + //add a position to the position list and add a new iterator to the iterator list
  566 + Coord2D p;
  567 + p.x1 = p1;
  568 + p.x2 = p2;
  569 + position_list.push_back(p);
  570 + rtsDTGrid2D<T>::iterator new_iter;
  571 +
  572 +
  573 + iterator_list.push_back(new_iter);
  574 + T empty;
  575 + value_list.push_back(empty);
  576 +}
  577 +
  578 +template<typename T>
  579 +bool rtsDTGrid2D<T>::stencil_iterator::exists(int id)
  580 +{
  581 + int i;
  582 + Coord2D dest;
  583 +
  584 + //determine the appropriate position for the iterator
  585 + dest.x1 = X1() + position_list[id].x1;
  586 + dest.x2 = X2() + position_list[id].x2;
  587 + //now add the value to the value list
  588 + if(iterator_list[id].X1() == dest.x1 && iterator_list[id].X2() == dest.x2)
  589 + return true;
  590 + else
  591 + return false;
  592 +
  593 +}
  594 +
  595 +/**************ITERATOR METHODS IN DT GRID*******************/
  596 +template<typename T>
  597 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::begin()
  598 +{
  599 + //if the grid is empty, return an iterator to "after"
  600 + if(value.size() == 0)
  601 + return after();
  602 +
  603 + iterator result;
  604 + result.parent = this;
  605 + result.ic = 0;
  606 + result.iv = 0;
  607 + result.x2 = conn[0].coordMin;
  608 + result.loc1D = proj1D.begin();
  609 +
  610 + return result;
  611 +}
  612 +template<typename T>
  613 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::before()
  614 +{
  615 + if(value.size() == 0)
  616 + return after();
  617 +
  618 + iterator result;
  619 + result.parent = this;
  620 + result.ic = 0;
  621 + result.iv = -1;
  622 + //result.x2 = conn[0].coordMin;
  623 + result.loc1D = proj1D.before();
  624 +
  625 + return result;
  626 +}
  627 +
  628 +template<typename T>
  629 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::end()
  630 +{
  631 + //if the grid is empty, return after()
  632 + if(value.size() == 0)
  633 + return after();
  634 + iterator result;
  635 + result.parent = this;
  636 + result.ic = conn.size() - 1;
  637 + result.iv = value.size() - 1;
  638 + result.x2 = conn[result.ic].coordMax;
  639 + result.loc1D = proj1D.end();
  640 + return result;
  641 +}
  642 +
  643 +template<typename T>
  644 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::randomIterator(int x1, int x2)
  645 +{
  646 + rtsDTGrid2D<T>::iterator result;
  647 + result.parent = this;
  648 +
  649 + //perform the random search
  650 + int v_i, c_i;
  651 + rtsDTGrid1D<IndexPair>::iterator iter1D;
  652 +
  653 + //if the value exists in the grid, create the iterator and return
  654 + if(randomIndex(iter1D, v_i, c_i, x1, x2))
  655 + {
  656 + result.loc1D = iter1D;
  657 + result.iv = v_i;
  658 + result.ic = c_i;
  659 + int offset = v_i - conn[c_i].toValue;
  660 + result.x2 = conn[c_i].coordMin + offset;
  661 + }
  662 + //if the value doesn't exist
  663 + else
  664 + {
  665 + //if the 1D iterator is at the end of the grid, return after()
  666 + if(iter1D == proj1D.after())
  667 + return after();
  668 +
  669 + //if the value lies before the current column
  670 + if(x1 < iter1D.X1() || (x1 == iter1D.X1() && x2 < conn[c_i].coordMin) )
  671 + {
  672 + result.ic = c_i;
  673 + }
  674 + //else if the value lies after the current column
  675 + else
  676 + {
  677 + //increment the 1D iterator
  678 + iter1D++;
  679 + //if this is the last connected component
  680 + if(c_i >= conn.size() - 1)
  681 + return after();
  682 + else
  683 + {
  684 + c_i++;
  685 + result.ic = c_i;
  686 + }
  687 + }
  688 +
  689 +
  690 + result.loc1D = iter1D;
  691 + result.iv = conn[c_i].toValue;
  692 + result.x2 = conn[c_i].coordMin;
  693 + }
  694 + return result;
  695 +
  696 +
  697 +}
  698 +template<typename T>
  699 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::after()
  700 +{
  701 + iterator result;
  702 + result.parent = this;
  703 + result.ic = conn.size() - 1;
  704 + result.iv = value.size();
  705 + //result.x2 = conn[result.ic].coordMax;
  706 + result.loc1D = proj1D.after();
  707 + return result;
  708 +}
  709 +template<typename T>
  710 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::begin_pn()
  711 +{
  712 + if(value.size() == 0)
  713 + return after();
  714 +
  715 + iterator result;
  716 + result.parent = this;
  717 + result.loc1D = proj1D.begin();
  718 + result.ic = result.loc1D.Value().toConn + result.loc1D.Value().numConn - 1;
  719 + result.iv = conn[result.ic].toValue + (conn[result.ic].coordMax - conn[result.ic].coordMin);
  720 + result.x2 = conn[result.ic].coordMax;
  721 +
  722 + return result;
  723 +}
  724 +template<typename T>
  725 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::begin_np()
  726 +{
  727 + //this is the opposite corner of pn
  728 + return end_pn();
  729 +}
  730 +template<typename T>
  731 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::end_pn()
  732 +{
  733 + if(value.size() == 0)
  734 + return after();
  735 + iterator result;
  736 + result.parent = this;
  737 + result.loc1D = proj1D.end();
  738 + result.ic = result.loc1D.Value().toConn;
  739 + result.iv = conn[result.ic].toValue;
  740 + result.x2 = conn[result.ic].coordMin;
  741 +
  742 + return result;
  743 +}
  744 +template<typename T>
  745 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::end_np()
  746 +{
  747 + //this is the opposite corner of pn
  748 + return begin_pn();
  749 +}
  750 +
  751 +template<typename T>
  752 +void rtsDTGrid2D<T>::print()
  753 +{
  754 + rtsDTGrid2D<T>::iterator i;
  755 + i = begin();
  756 + while(i!=end())
  757 + {
  758 + cout<<i.X1()<<","<<i.X2()<<":"<<i.Value()<<endl;
  759 + i.increment();
  760 + }
  761 +
  762 +
  763 +}
  764 +
  765 +/**************DT GRID**************************/
  766 +template<typename T>
  767 +bool rtsDTGrid2D<T>::push(int x1, int x2, T v)
  768 +{
  769 + //run this code if we have to start a new column in X1. This happens when:
  770 + //(a) we have just inserted the first value into the grid
  771 + //(b) the value of x1 is greater than the last value of x1
  772 + if(grid_insertion_started == false || x1 != proj1D.getMaxX1())
  773 + {
  774 + //assume that a new column is being created
  775 + //create the column in proj1D
  776 + IndexPair newPair;
  777 + newPair.toConn = conn.size();
  778 + //newPair.toValue = value.size();
  779 + newPair.numConn = 0;
  780 +
  781 + //if this insertion throws an error, the value was inserted incorrectly
  782 + //the error will get thrown by DTGrid1D, so just return
  783 + if(!proj1D.push(x1, newPair))
  784 + {
  785 + cout<<"Out-of-order insertion in D = 2: X1 = "<<x1<<" X2 = "<<x2<<endl;
  786 + return false;
  787 + }
  788 +
  789 + column_insertion_started = false;
  790 + grid_insertion_started = true;
  791 + }
  792 + //If there is no new column, we still have to check to make sure the value is inserted
  793 + //in the correct order in X2:
  794 + else
  795 + {
  796 + if(column_insertion_started && x2 <= max_coord)
  797 + {
  798 + cout<<"Out-of-order insertion in D = 2: X1 = "<<x1<<" X2 = "<<x2<<endl;
  799 + return false;
  800 + }
  801 + }
  802 +
  803 +
  804 + //run this code if we have to start a new connected component. This happens when:
  805 + //(a) We insert the first value into the column
  806 + //(b) There is empty space between the last insertion and this one
  807 + if(column_insertion_started == false || x2 > (max_coord + 1))
  808 + {
  809 + //start a new connected component
  810 + ConnectedComponent new_conn;
  811 + new_conn.toValue = value.size();
  812 + new_conn.coordMin = x2;
  813 + new_conn.coordMax = x2;
  814 + conn.push_back(new_conn);
  815 + //increment the number of connected components for the column in X1
  816 + proj1D.back().numConn++;
  817 + column_insertion_started = true;
  818 + }
  819 +
  820 + //insert the value into the grid:
  821 + //(a) Insert the value at the end of the coord array
  822 + //(b) Increment the coordMax value of the current connected component
  823 + //(c) Change the maximum inserted coordinate to the new value
  824 + value.push_back(v);
  825 + conn[conn.size() - 1].coordMax = x2;
  826 + //change max_coord to the new coordinate
  827 + max_coord = x2;
  828 + return true;
  829 +}
  830 +
  831 +template<typename T>
  832 +bool rtsDTGrid2D<T>::randomIndex(rtsDTGrid1D<IndexPair>::iterator &iter1D, int &v_i, int &c_i, int x1, int x2)
  833 +{
  834 + //search along the first dimension
  835 + //get an iterator
  836 + iter1D = proj1D.randomIterator(x1);
  837 +
  838 + //if the after() iterator is returned, exit
  839 + if(iter1D == proj1D.after())
  840 + {
  841 + c_i = conn.size();
  842 + v_i = value.size();
  843 + return false;
  844 + }
  845 +
  846 + IndexPair i = iter1D.Value();
  847 +
  848 + //if the 1D column does not exist
  849 + if(iter1D.X1() != x1)
  850 + {
  851 + //get the appropriate values from the 1D iterator
  852 + //(which points to the next valid column)
  853 + c_i = i.toConn;
  854 + v_i = conn[c_i].toValue;
  855 + return false;
  856 + }
  857 +
  858 +
  859 + int high, low, mid;
  860 + low = i.toConn;
  861 + high = i.toConn + i.numConn - 1;
  862 +
  863 + do
  864 + {
  865 + mid = low + (high - low)/2;
  866 + if(x2 > conn[mid].coordMax)
  867 + low = mid + 1;
  868 + else if(x2 < conn[mid].coordMin)
  869 + high = mid - 1;
  870 + else break;
  871 + }
  872 + while(low <= high);
  873 +
  874 + //at this point, mid is either at the appropriate connected component,
  875 + //or x2 is not in the grid
  876 + if(x2 >= conn[mid].coordMin && x2 <= conn[mid].coordMax)
  877 + {
  878 + int offset = x2 - conn[mid].coordMin;
  879 + c_i = mid;
  880 + v_i = conn[mid].toValue + offset;
  881 + return true;
  882 + }
  883 + else
  884 + {
  885 + c_i = mid;
  886 + v_i = conn[c_i].toValue;
  887 + return false;
  888 + }
  889 +}
  890 +
  891 +template<typename T>
  892 +T rtsDTGrid2D<T>::random(int x1, int x2)
  893 +{
  894 + int v_i, c_i;
  895 + rtsDTGrid1D<IndexPair>::iterator iter1D;
  896 + if(randomIndex(iter1D, v_i, c_i, x1, x2))
  897 + return value[v_i];
  898 + else
  899 + return background;
  900 +}
  901 +
  902 +template<typename T>
  903 +T& rtsDTGrid2D<T>::back()
  904 +{
  905 + return value[value.size()-1];
  906 +}
  907 +
  908 +template<typename T>
  909 +void rtsDTGrid2D<T>::dilate(int H)
  910 +{
  911 + //if the grid is empty, return unchanged
  912 + if(value.size() == 0)
  913 + return;
  914 +
  915 + ColumnUnion CUqueue;
  916 + CUqueue.ConnectToGrid(&conn);
  917 +
  918 +
  919 + //dilate the N-1 DT-Grid constituent
  920 + rtsDTGrid1D<IndexPair> dilated_proj1D = proj1D;
  921 +
  922 + //an empty pair has a number of connected components equal to zero
  923 + //this should not happen in reality and can therefore be used to check for new columns
  924 + IndexPair empty_pair;
  925 + empty_pair.numConn = 0;
  926 +
  927 + //set the background node to the empty node and dilate the 1D projection
  928 + dilated_proj1D.background = empty_pair;
  929 + dilated_proj1D.dilate(H);
  930 +
  931 + //create a new DT Grid that will replace this one
  932 + rtsDTGrid2D<T> new_grid;
  933 + new_grid.proj1D = dilated_proj1D;
  934 + new_grid.proj1D.background.toConn = -1;
  935 +
  936 + //create iteratorDilate that iterates along the dilated N-1 grid
  937 + rtsDTGrid1D<IndexPair>::stencil_iterator iteratorDilate;
  938 + iteratorDilate.addPosition(-H);
  939 + iteratorDilate.addPosition(H);
  940 +
  941 + //create an iterator to set the new proj1D values
  942 + rtsDTGrid1D<IndexPair>::iterator iteratorNew;
  943 +
  944 +
  945 + //variables for each iteration
  946 + IndexPair new_pair;
  947 + vector<ConnectedComponent>::iterator ccIterator;
  948 + unsigned int numValues = 0;
  949 + for(iteratorNew = new_grid.proj1D.begin(),
  950 + iteratorDilate = dilated_proj1D.begin();
  951 + iteratorDilate != dilated_proj1D.after();
  952 + iteratorNew++,
  953 + iteratorDilate++)
  954 + {
  955 + //cout<<"1D position: "<<iteratorNew.X1()<<endl;
  956 + //if a column is entering the stencil
  957 + if(iteratorDilate.getValue(1).numConn)
  958 + CUqueue.InsertColumn(iteratorDilate.getValue(1));
  959 +
  960 + //compute the union of all columns in the queue
  961 + vector<ConnectedComponent> result = CUqueue.ComputeUnion(H);
  962 +
  963 + //compute the new IndexPair representing the column
  964 + new_pair.toConn = new_grid.conn.size();
  965 + new_pair.numConn = result.size();
  966 + //store the index pair
  967 + iteratorNew.SetValue(new_pair);
  968 +
  969 + //insert each of the connected components
  970 + for(ccIterator = result.begin(); ccIterator!=result.end(); ccIterator++)
  971 + {
  972 + new_grid.conn.push_back(*ccIterator);
  973 + new_grid.conn.back().toValue = numValues;
  974 + numValues += (*ccIterator).coordMax - (*ccIterator).coordMin + 1;
  975 + }
  976 +
  977 + //if a column is leaving the stencil
  978 + if(iteratorDilate.getValue(0).numConn)
  979 + CUqueue.RemoveColumn();
  980 + }
  981 +
  982 + //allocate space for the new value array
  983 + new_grid.value.resize(numValues, background);
  984 +
  985 + //copy the data from this grid into the new grid
  986 + new_grid.insert(*this);
  987 +
  988 + //replace this grid with the new grid
  989 + conn = new_grid.conn;
  990 + value = new_grid.value;
  991 + proj1D = new_grid.proj1D;
  992 +
  993 +
  994 +}
  995 +
  996 +template<typename T>
  997 +void rtsDTGrid2D<T>::insert(rtsDTGrid2D<T> toInsert)
  998 +{
  999 + //create source and destination iterators
  1000 + rtsDTGrid2D<T>::iterator source = toInsert.begin();
  1001 + rtsDTGrid2D<T>::iterator dest = begin();
  1002 +
  1003 + for(source = toInsert.begin(); source != toInsert.after(); source++)
  1004 + {
  1005 + //move the destination iterator to the current source position
  1006 + dest.increment_until(source.X1(), source.X2());
  1007 + //cout<<"source: "<<source.X1()<<" "<<source.X2()<<": "<<source.Value()<<endl;
  1008 + //cout<<"dest: "<<dest.X1()<<" "<<dest.X2()<<": "<<dest.Value()<<endl;
  1009 + //if the position exists in dest
  1010 + if(dest.X1() == source.X1() && dest.X2() == source.X2())
  1011 + dest.SetValue(source.Value());
  1012 + //cout<<"dest: "<<dest.X1()<<" "<<dest.X2()<<": "<<dest.Value()<<endl;
  1013 + }
  1014 +
  1015 +}
  1016 +
  1017 +template<typename T>
  1018 +void rtsDTGrid2D<T>::getBounds(int &min_x1, int &min_x2, int &max_x1, int &max_x2)
  1019 +{
  1020 + //if the grid is empty, return an empty bounding volume
  1021 + if(value.size() == 0)
  1022 + {
  1023 + min_x1 = min_x2 = max_x1 = max_x2 = 0;
  1024 + return;
  1025 + }
  1026 +
  1027 + //get the min and max values for the 1D grid (x1 coordinate)
  1028 + proj1D.getBounds(min_x1, max_x1);
  1029 +
  1030 + //initialize the min and max values
  1031 + min_x2 = conn[0].coordMin;
  1032 + max_x2 = conn.back().coordMax;
  1033 +
  1034 + //iterate through all columns finding the smallest and largest coordinate values
  1035 + rtsDTGrid1D<IndexPair>::iterator i;
  1036 + IndexPair col;
  1037 + for(i=proj1D.begin(); i!=proj1D.after(); i++)
  1038 + {
  1039 + col = i.Value();
  1040 + if(conn[col.toConn].coordMin < min_x2)
  1041 + min_x2 = conn[col.toConn].coordMin;
  1042 + if(conn[col.toConn + col.numConn - 1].coordMax > max_x2)
  1043 + max_x2 = conn[col.toConn + col.numConn - 1].coordMax;
  1044 + }
  1045 +
  1046 +
  1047 +}
  1048 +template<typename T>
  1049 +void rtsDTGrid2D<T>::operator =(T rhs)
  1050 +{
  1051 + for(int i=0; i<value.size(); i++)
  1052 + value[i] = rhs;
  1053 +}
  1054 +
  1055 +
  1056 +template<typename T>
  1057 +void rtsDTGrid2D<T>::dumpValue()
  1058 +{
  1059 + for(int i=0; i<value.size(); i++)
  1060 + cout<<value[i]<<endl;
  1061 +}
  1062 +
  1063 +template<typename T>
  1064 +void rtsDTGrid2D<T>::dumpConn()
  1065 +{
  1066 + for(int i=0; i<conn.size(); i++)
  1067 + cout<<conn[i].toValue<<","<<conn[i].coordMin<<","<<conn[i].coordMax<<endl;
  1068 +
  1069 +
  1070 +}
  1071 +
  1072 +#endif
0 1073 \ No newline at end of file
... ...
rtsDTGrid2D_v1.h 0 → 100755
  1 +++ a/rtsDTGrid2D_v1.h
  1 +
  2 +#include <vector>
  3 +#include <iostream>
  4 +using namespace std;
  5 +
  6 +#include "rtsDTGrid1D.h"
  7 +
  8 +#ifndef _RTS_DTGRID2D_H
  9 +#define _RTS_DTGRID2D_H
  10 +
  11 +struct IndexPair
  12 +{
  13 + //int toValue;
  14 + int toConn;
  15 + int numConn;
  16 +};
  17 +
  18 +#include "ColumnUnion.h"
  19 +
  20 +struct Coord2D
  21 +{
  22 + int x1;
  23 + int x2;
  24 +};
  25 +
  26 +
  27 +
  28 +template<typename T>
  29 +class rtsDTGrid2D
  30 +{
  31 +private:
  32 + //main arrays
  33 + vector<T> value;
  34 + vector<ConnectedComponent> conn;
  35 + rtsDTGrid1D<IndexPair> proj1D;
  36 + bool randomIndex(rtsDTGrid1D<IndexPair>::iterator &iter1D, int &v_i, int &c_i, int x1, int x2);
  37 +
  38 +
  39 +
  40 + //variables to keep track of insertion
  41 + int max_coord;
  42 + bool grid_insertion_started;
  43 + bool column_insertion_started;
  44 +
  45 +
  46 +public:
  47 + rtsDTGrid2D<T>()
  48 + {
  49 + grid_insertion_started = false;
  50 + column_insertion_started = false;
  51 + proj1D.background.toConn = -1;
  52 + max_coord = 0;
  53 + }
  54 +
  55 + bool push(int x1, int x2, T v);
  56 + T random(int x1, int x2);
  57 + T& back();
  58 + T background;
  59 + void print();
  60 +
  61 + friend class ColumnUnion;
  62 + void dilate(int H);
  63 + void insert(rtsDTGrid2D<T> toInsert);
  64 + void operator=(T rhs);
  65 + void getBounds(int &min_x1, int &min_x2, int &max_x1, int &max_x2);
  66 +
  67 + void dumpValue();
  68 + void dumpConn();
  69 +
  70 + //iterator
  71 + class iterator;
  72 + friend class iterator;
  73 + class stencil_iterator;
  74 + iterator randomIterator(int x1, int x2);
  75 + iterator begin();
  76 + iterator before();
  77 + iterator end();
  78 + iterator after();
  79 +};
  80 +
  81 +/**********ITERATOR***********************/
  82 +template<typename T>
  83 +class rtsDTGrid2D<T>::iterator
  84 +{
  85 + friend class rtsDTGrid2D;
  86 + rtsDTGrid2D<T>* parent;
  87 + rtsDTGrid1D<IndexPair>::iterator loc1D;
  88 + int iv;
  89 + int ic;
  90 + int x2;
  91 +
  92 +public:
  93 +
  94 +
  95 + T Value(){return parent->value[iv];}
  96 + int X1(){return loc1D.X1();}
  97 + int X2(){return x2;}
  98 + iterator(){parent = NULL;}
  99 + void SetValue(T value){parent->value[iv] = value;}
  100 +
  101 +
  102 + void increment()
  103 + {
  104 + //increment the value
  105 + iv++;
  106 + //if this exceeds the length of the value array, we are at the end of the grid
  107 + if(iv == parent->value.size())
  108 + {
  109 + (*this) = parent->after();
  110 + return;
  111 + }
  112 +
  113 + //increment the current coordinate
  114 + x2++;
  115 + //if we are outside of the current connected component
  116 + if(x2 > parent->conn[ic].coordMax)
  117 + {
  118 + //move to the next connected component
  119 + ic++;
  120 + //if this is the last connected component in the column
  121 + if(ic == loc1D.Value().toConn + loc1D.Value().numConn)
  122 + loc1D++;
  123 + //if there are no more connected components
  124 + if(ic == parent->conn.size())
  125 + {
  126 + //we're at the end, return end
  127 + (*this) = parent->end();
  128 + return;
  129 + }
  130 + x2 = parent->conn[ic].coordMin;
  131 + }
  132 + }
  133 +
  134 +
  135 + //boolean operators for comparing iterators
  136 + bool operator==(iterator rhs)
  137 + {
  138 + if(parent == rhs.parent && iv == rhs.iv)
  139 + return true;
  140 + return false;
  141 + }
  142 + bool operator!=(iterator rhs){return !((*this) == rhs);}
  143 +
  144 + friend bool operator<(iterator &left, iterator &right)
  145 + {
  146 + if(left.iv < right.iv)
  147 + return true;
  148 + return false;
  149 + }
  150 + friend bool operator<=(iterator &left, iterator &right)
  151 + {
  152 + if(left.iv <= right.iv)
  153 + return true;
  154 + return false;
  155 + }
  156 + void operator++(){increment();}
  157 + void increment_until(int p1, int p2)
  158 + {
  159 + while((*this) != parent->end())
  160 + {
  161 + if(X1() > p1)
  162 + return;
  163 + else if(X1() == p1 && X2() >= p2)
  164 + return;
  165 +
  166 + increment();
  167 + }
  168 + }
  169 +};
  170 +
  171 +/********STENCIL ITERATOR*****************/
  172 +template<typename T>
  173 +class rtsDTGrid2D<T>::stencil_iterator : public iterator
  174 +{
  175 +private:
  176 + //list of iterators that make up the template
  177 + vector<iterator> iterator_list;
  178 + //iterator positions (relative to the position of the stencil iterator)
  179 + vector<Coord2D> position_list;
  180 + //list containing the values for each position in the stencil
  181 + vector<T> value_list;
  182 +
  183 + void refresh_iterators();
  184 + void set_values();
  185 + void increment_all();
  186 +
  187 +public:
  188 + typename rtsDTGrid2D<T>::stencil_iterator operator=(const iterator rhs);
  189 + void addPosition(int p1, int p2);
  190 + void increment();
  191 + void operator++()
  192 + {
  193 + increment();
  194 + }
  195 + T getValue(int id){return value_list[id];}
  196 + bool exists(int id);
  197 +
  198 +};
  199 +
  200 +template<typename T>
  201 +void rtsDTGrid2D<T>::stencil_iterator::increment_all()
  202 +{
  203 + //run through each iterator and increment to the correct position
  204 + int i;
  205 + Coord2D dest;
  206 + for(i=0; i<iterator_list.size(); i++)
  207 + {
  208 + //determine the appropriate position for the iterator
  209 + dest.x1 = X1() + position_list[i].x1;
  210 + dest.x2 = X2() + position_list[i].x2;
  211 + //iterate until that position is reached
  212 + iterator_list[i].increment_until(dest.x1, dest.x2);
  213 + }
  214 + set_values();
  215 +
  216 +}
  217 +
  218 +template<typename T>
  219 +void rtsDTGrid2D<T>::stencil_iterator::increment()
  220 +{
  221 + //increment the current position
  222 + rtsDTGrid2D<T>::iterator::increment();
  223 +
  224 + increment_all();
  225 +}
  226 +
  227 +template<typename T>
  228 +void rtsDTGrid2D<T>::stencil_iterator::refresh_iterators()
  229 +{
  230 + //make sure that the iterator position has been set
  231 + if(parent == NULL)
  232 + {
  233 + cout<<"Iterator location not set."<<endl;
  234 + return;
  235 + }
  236 +
  237 + //initialize all of the other iterators
  238 + int i;
  239 + for(i=0; i<iterator_list.size(); i++)
  240 + {
  241 + //for each iterator, set the iterator to the beginning of the grid
  242 + //iterator_list[i] = parent->begin();
  243 + iterator_list[i] = parent->randomIterator(X1() + position_list[i].x1,
  244 + X2() + position_list[i].x2);
  245 + }
  246 + //increment_all();
  247 + //set the values for all of the iterators
  248 + set_values();
  249 +}
  250 +
  251 +template<typename T>
  252 +void rtsDTGrid2D<T>::stencil_iterator::set_values()
  253 +{
  254 + int i;
  255 + Coord2D dest;
  256 + for(i=0; i<iterator_list.size(); i++)
  257 + {
  258 + //determine the appropriate position for the iterator
  259 + dest.x1 = X1() + position_list[i].x1;
  260 + dest.x2 = X2() + position_list[i].x2;
  261 + //now add the value to the value list
  262 + if(iterator_list[i].X1() == dest.x1 && iterator_list[i].X2() == dest.x2)
  263 + value_list[i] = iterator_list[i].Value();
  264 + else
  265 + value_list[i] = parent->background;
  266 + }
  267 +
  268 +
  269 +}
  270 +
  271 +template<typename T>
  272 +typename rtsDTGrid2D<T>::stencil_iterator rtsDTGrid2D<T>::stencil_iterator::operator=(const iterator rhs)
  273 +{
  274 + parent = rhs.parent;
  275 + loc1D = rhs.loc1D;
  276 + iv = rhs.iv;
  277 + ic = rhs.ic;
  278 + x2 = rhs.x2;
  279 +
  280 + refresh_iterators();
  281 +
  282 + return (*this);
  283 +}
  284 +
  285 +template<typename T>
  286 +void rtsDTGrid2D<T>::stencil_iterator::addPosition(int p1, int p2)
  287 +{
  288 + //add a position to the position list and add a new iterator to the iterator list
  289 + Coord2D p;
  290 + p.x1 = p1;
  291 + p.x2 = p2;
  292 + position_list.push_back(p);
  293 + rtsDTGrid2D<T>::iterator new_iter;
  294 +
  295 +
  296 + iterator_list.push_back(new_iter);
  297 + T empty;
  298 + value_list.push_back(empty);
  299 +}
  300 +
  301 +template<typename T>
  302 +bool rtsDTGrid2D<T>::stencil_iterator::exists(int id)
  303 +{
  304 + int i;
  305 + Coord2D dest;
  306 +
  307 + //determine the appropriate position for the iterator
  308 + dest.x1 = X1() + position_list[id].x1;
  309 + dest.x2 = X2() + position_list[id].x2;
  310 + //now add the value to the value list
  311 + if(iterator_list[id].X1() == dest.x1 && iterator_list[id].X2() == dest.x2)
  312 + return true;
  313 + else
  314 + return false;
  315 +
  316 +}
  317 +
  318 +/**************ITERATOR METHODS IN DT GRID*******************/
  319 +template<typename T>
  320 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::begin()
  321 +{
  322 + //if the grid is empty, return an iterator to "after"
  323 + if(value.size() == 0)
  324 + return after();
  325 +
  326 + iterator result;
  327 + result.parent = this;
  328 + result.ic = 0;
  329 + result.iv = 0;
  330 + result.x2 = conn[0].coordMin;
  331 + result.loc1D = proj1D.begin();
  332 +
  333 + return result;
  334 +}
  335 +template<typename T>
  336 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::before()
  337 +{
  338 + if(value.size() == 0)
  339 + return after();
  340 +
  341 + iterator result;
  342 + result.parent = this;
  343 + result.ic = 0;
  344 + result.iv = -1;
  345 + //result.x2 = conn[0].coordMin;
  346 + result.loc1D = proj1D.before();
  347 +
  348 + return result;
  349 +}
  350 +
  351 +template<typename T>
  352 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::end()
  353 +{
  354 + //if the grid is empty, return after()
  355 + if(value.size() == 0)
  356 + return after();
  357 + iterator result;
  358 + result.parent = this;
  359 + result.ic = conn.size() - 1;
  360 + result.iv = value.size() - 1;
  361 + result.x2 = conn[result.ic].coordMax;
  362 + result.loc1D = proj1D.end();
  363 + return result;
  364 +}
  365 +
  366 +template<typename T>
  367 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::randomIterator(int x1, int x2)
  368 +{
  369 + rtsDTGrid2D<T>::iterator result;
  370 + result.parent = this;
  371 +
  372 + //perform the random search
  373 + int v_i, c_i;
  374 + rtsDTGrid1D<IndexPair>::iterator iter1D;
  375 +
  376 + //if the value exists in the grid, create the iterator and return
  377 + if(randomIndex(iter1D, v_i, c_i, x1, x2))
  378 + {
  379 + result.loc1D = iter1D;
  380 + result.iv = v_i;
  381 + result.ic = c_i;
  382 + int offset = v_i - conn[c_i].toValue;
  383 + result.x2 = conn[c_i].coordMin + offset;
  384 + }
  385 + //if the value doesn't exist
  386 + else
  387 + {
  388 + //if the 1D iterator is at the end of the grid, return after()
  389 + if(iter1D == proj1D.after())
  390 + return after();
  391 +
  392 + //if the value lies before the current column
  393 + if(x1 < iter1D.X1() || (x1 == iter1D.X1() && x2 < conn[c_i].coordMin) )
  394 + {
  395 + result.ic = c_i;
  396 + }
  397 + //else if the value lies after the current column
  398 + else
  399 + {
  400 + //increment the 1D iterator
  401 + iter1D++;
  402 + //if this is the last connected component
  403 + if(c_i >= conn.size() - 1)
  404 + return after();
  405 + else
  406 + {
  407 + c_i++;
  408 + result.ic = c_i;
  409 + }
  410 + }
  411 +
  412 +
  413 + result.loc1D = iter1D;
  414 + result.iv = conn[c_i].toValue;
  415 + result.x2 = conn[c_i].coordMin;
  416 + }
  417 + return result;
  418 +
  419 +
  420 +}
  421 +template<typename T>
  422 +typename rtsDTGrid2D<T>::iterator rtsDTGrid2D<T>::after()
  423 +{
  424 + iterator result;
  425 + result.parent = this;
  426 + result.ic = conn.size() - 1;
  427 + result.iv = value.size();
  428 + //result.x2 = conn[result.ic].coordMax;
  429 + result.loc1D = proj1D.after();
  430 + return result;
  431 +}
  432 +
  433 +/**************DT GRID**************************/
  434 +template<typename T>
  435 +bool rtsDTGrid2D<T>::push(int x1, int x2, T v)
  436 +{
  437 + //run this code if we have to start a new column in X1. This happens when:
  438 + //(a) we have just inserted the first value into the grid
  439 + //(b) the value of x1 is greater than the last value of x1
  440 + if(grid_insertion_started == false || x1 != proj1D.getMaxX1())
  441 + {
  442 + //assume that a new column is being created
  443 + //create the column in proj1D
  444 + IndexPair newPair;
  445 + newPair.toConn = conn.size();
  446 + //newPair.toValue = value.size();
  447 + newPair.numConn = 0;
  448 +
  449 + //if this insertion throws an error, the value was inserted incorrectly
  450 + //the error will get thrown by DTGrid1D, so just return
  451 + if(!proj1D.push(x1, newPair))
  452 + {
  453 + cout<<"Out-of-order insertion in D = 2: X1 = "<<x1<<" X2 = "<<x2<<endl;
  454 + return false;
  455 + }
  456 +
  457 + column_insertion_started = false;
  458 + grid_insertion_started = true;
  459 + }
  460 + //If there is no new column, we still have to check to make sure the value is inserted
  461 + //in the correct order in X2:
  462 + else
  463 + {
  464 + if(column_insertion_started && x2 <= max_coord)
  465 + {
  466 + cout<<"Out-of-order insertion in D = 2: X1 = "<<x1<<" X2 = "<<x2<<endl;
  467 + return false;
  468 + }
  469 + }
  470 +
  471 +
  472 + //run this code if we have to start a new connected component. This happens when:
  473 + //(a) We insert the first value into the column
  474 + //(b) There is empty space between the last insertion and this one
  475 + if(column_insertion_started == false || x2 > (max_coord + 1))
  476 + {
  477 + //start a new connected component
  478 + ConnectedComponent new_conn;
  479 + new_conn.toValue = value.size();
  480 + new_conn.coordMin = x2;
  481 + new_conn.coordMax = x2;
  482 + conn.push_back(new_conn);
  483 + //increment the number of connected components for the column in X1
  484 + proj1D.back().numConn++;
  485 + column_insertion_started = true;
  486 + }
  487 +
  488 + //insert the value into the grid:
  489 + //(a) Insert the value at the end of the coord array
  490 + //(b) Increment the coordMax value of the current connected component
  491 + //(c) Change the maximum inserted coordinate to the new value
  492 + value.push_back(v);
  493 + conn[conn.size() - 1].coordMax = x2;
  494 + //change max_coord to the new coordinate
  495 + max_coord = x2;
  496 + return true;
  497 +}
  498 +
  499 +template<typename T>
  500 +bool rtsDTGrid2D<T>::randomIndex(rtsDTGrid1D<IndexPair>::iterator &iter1D, int &v_i, int &c_i, int x1, int x2)
  501 +{
  502 + //search along the first dimension
  503 + //get an iterator
  504 + iter1D = proj1D.randomIterator(x1);
  505 +
  506 + //if the after() iterator is returned, exit
  507 + if(iter1D == proj1D.after())
  508 + {
  509 + c_i = conn.size();
  510 + v_i = value.size();
  511 + return false;
  512 + }
  513 +
  514 + IndexPair i = iter1D.Value();
  515 +
  516 + //if the 1D column does not exist
  517 + if(iter1D.X1() != x1)
  518 + {
  519 + //get the appropriate values from the 1D iterator
  520 + //(which points to the next valid column)
  521 + c_i = i.toConn;
  522 + v_i = conn[c_i].toValue;
  523 + return false;
  524 + }
  525 +
  526 +
  527 + int high, low, mid;
  528 + low = i.toConn;
  529 + high = i.toConn + i.numConn - 1;
  530 +
  531 + do
  532 + {
  533 + mid = low + (high - low)/2;
  534 + if(x2 > conn[mid].coordMax)
  535 + low = mid + 1;
  536 + else if(x2 < conn[mid].coordMin)
  537 + high = mid - 1;
  538 + else break;
  539 + }
  540 + while(low <= high);
  541 +
  542 + //at this point, mid is either at the appropriate connected component,
  543 + //or x2 is not in the grid
  544 + if(x2 >= conn[mid].coordMin && x2 <= conn[mid].coordMax)
  545 + {
  546 + int offset = x2 - conn[mid].coordMin;
  547 + c_i = mid;
  548 + v_i = conn[mid].toValue + offset;
  549 + return true;
  550 + }
  551 + else
  552 + {
  553 + c_i = mid;
  554 + v_i = conn[c_i].toValue;
  555 + return false;
  556 + }
  557 +}
  558 +
  559 +template<typename T>
  560 +T rtsDTGrid2D<T>::random(int x1, int x2)
  561 +{
  562 + int v_i, c_i;
  563 + rtsDTGrid1D<IndexPair>::iterator iter1D;
  564 + if(randomIndex(iter1D, v_i, c_i, x1, x2))
  565 + return value[v_i];
  566 + else
  567 + return background;
  568 +}
  569 +
  570 +template<typename T>
  571 +T& rtsDTGrid2D<T>::back()
  572 +{
  573 + return value[value.size()-1];
  574 +}
  575 +
  576 +template<typename T>
  577 +void rtsDTGrid2D<T>::dilate(int H)
  578 +{
  579 + //if the grid is empty, return unchanged
  580 + if(value.size() == 0)
  581 + return;
  582 +
  583 + ColumnUnion CUqueue;
  584 + CUqueue.ConnectToGrid(&conn);
  585 +
  586 +
  587 + //dilate the N-1 DT-Grid constituent
  588 + rtsDTGrid1D<IndexPair> dilated_proj1D = proj1D;
  589 +
  590 + //an empty pair has a number of connected components equal to zero
  591 + //this should not happen in reality and can therefore be used to check for new columns
  592 + IndexPair empty_pair;
  593 + empty_pair.numConn = 0;
  594 +
  595 + //set the background node to the empty node and dilate the 1D projection
  596 + dilated_proj1D.background = empty_pair;
  597 + dilated_proj1D.dilate(H);
  598 +
  599 + //create a new DT Grid that will replace this one
  600 + rtsDTGrid2D<T> new_grid;
  601 + new_grid.proj1D = dilated_proj1D;
  602 + new_grid.proj1D.background.toConn = -1;
  603 +
  604 + //create iteratorDilate that iterates along the dilated N-1 grid
  605 + rtsDTGrid1D<IndexPair>::stencil_iterator iteratorDilate;
  606 + iteratorDilate.addPosition(-H);
  607 + iteratorDilate.addPosition(H);
  608 +
  609 + //create an iterator to set the new proj1D values
  610 + rtsDTGrid1D<IndexPair>::iterator iteratorNew;
  611 +
  612 +
  613 + //variables for each iteration
  614 + IndexPair new_pair;
  615 + vector<ConnectedComponent>::iterator ccIterator;
  616 + unsigned int numValues = 0;
  617 + for(iteratorNew = new_grid.proj1D.begin(),
  618 + iteratorDilate = dilated_proj1D.begin();
  619 + iteratorDilate != dilated_proj1D.after();
  620 + iteratorNew++,
  621 + iteratorDilate++)
  622 + {
  623 + //cout<<"1D position: "<<iteratorNew.X1()<<endl;
  624 + //if a column is entering the stencil
  625 + if(iteratorDilate.getValue(1).numConn)
  626 + CUqueue.InsertColumn(iteratorDilate.getValue(1));
  627 +
  628 + //compute the union of all columns in the queue
  629 + vector<ConnectedComponent> result = CUqueue.ComputeUnion(H);
  630 +
  631 + //compute the new IndexPair representing the column
  632 + new_pair.toConn = new_grid.conn.size();
  633 + new_pair.numConn = result.size();
  634 + //store the index pair
  635 + iteratorNew.SetValue(new_pair);
  636 +
  637 + //insert each of the connected components
  638 + for(ccIterator = result.begin(); ccIterator!=result.end(); ccIterator++)
  639 + {
  640 + new_grid.conn.push_back(*ccIterator);
  641 + new_grid.conn.back().toValue = numValues;
  642 + numValues += (*ccIterator).coordMax - (*ccIterator).coordMin + 1;
  643 + }
  644 +
  645 + //if a column is leaving the stencil
  646 + if(iteratorDilate.getValue(0).numConn)
  647 + CUqueue.RemoveColumn();
  648 + }
  649 +
  650 + //allocate space for the new value array
  651 + new_grid.value.resize(numValues, background);
  652 +
  653 + //copy the data from this grid into the new grid
  654 + new_grid.insert(*this);
  655 +
  656 + //replace this grid with the new grid
  657 + conn = new_grid.conn;
  658 + value = new_grid.value;
  659 + proj1D = new_grid.proj1D;
  660 +
  661 +
  662 +}
  663 +
  664 +template<typename T>
  665 +void rtsDTGrid2D<T>::insert(rtsDTGrid2D<T> toInsert)
  666 +{
  667 + //create source and destination iterators
  668 + rtsDTGrid2D<T>::iterator source = toInsert.begin();
  669 + rtsDTGrid2D<T>::iterator dest = begin();
  670 +
  671 + for(source = toInsert.begin(); source != toInsert.after(); source++)
  672 + {
  673 + //move the destination iterator to the current source position
  674 + dest.increment_until(source.X1(), source.X2());
  675 + //cout<<"source: "<<source.X1()<<" "<<source.X2()<<": "<<source.Value()<<endl;
  676 + //cout<<"dest: "<<dest.X1()<<" "<<dest.X2()<<": "<<dest.Value()<<endl;
  677 + //if the position exists in dest
  678 + if(dest.X1() == source.X1() && dest.X2() == source.X2())
  679 + dest.SetValue(source.Value());
  680 + //cout<<"dest: "<<dest.X1()<<" "<<dest.X2()<<": "<<dest.Value()<<endl;
  681 + }
  682 +
  683 +}
  684 +
  685 +template<typename T>
  686 +void rtsDTGrid2D<T>::getBounds(int &min_x1, int &min_x2, int &max_x1, int &max_x2)
  687 +{
  688 + //if the grid is empty, return an empty bounding volume
  689 + if(value.size() == 0)
  690 + {
  691 + min_x1 = min_x2 = max_x1 = max_x2 = 0;
  692 + return;
  693 + }
  694 +
  695 + //get the min and max values for the 1D grid (x1 coordinate)
  696 + proj1D.getBounds(min_x1, max_x1);
  697 +
  698 + //initialize the min and max values
  699 + min_x2 = conn[0].coordMin;
  700 + max_x2 = conn.back().coordMax;
  701 +
  702 + //iterate through all columns finding the smallest and largest coordinate values
  703 + rtsDTGrid1D<IndexPair>::iterator i;
  704 + IndexPair col;
  705 + for(i=proj1D.begin(); i!=proj1D.after(); i++)
  706 + {
  707 + col = i.Value();
  708 + if(conn[col.toConn].coordMin < min_x2)
  709 + min_x2 = conn[col.toConn].coordMin;
  710 + if(conn[col.toConn + col.numConn - 1].coordMax > max_x2)
  711 + max_x2 = conn[col.toConn + col.numConn - 1].coordMax;
  712 + }
  713 +
  714 +
  715 +}
  716 +template<typename T>
  717 +void rtsDTGrid2D<T>::operator =(T rhs)
  718 +{
  719 + for(int i=0; i<value.size(); i++)
  720 + value[i] = rhs;
  721 +}
  722 +
  723 +
  724 +template<typename T>
  725 +void rtsDTGrid2D<T>::dumpValue()
  726 +{
  727 + for(int i=0; i<value.size(); i++)
  728 + cout<<value[i]<<endl;
  729 +}
  730 +
  731 +template<typename T>
  732 +void rtsDTGrid2D<T>::dumpConn()
  733 +{
  734 + for(int i=0; i<conn.size(); i++)
  735 + cout<<conn[i].toValue<<","<<conn[i].coordMin<<","<<conn[i].coordMax<<endl;
  736 +
  737 +
  738 +}
  739 +
  740 +#endif
0 741 \ No newline at end of file
... ...
rtsDTGrid3D.h 0 → 100755
  1 +++ a/rtsDTGrid3D.h
  1 +#ifndef RTS_DTGRID_3D_H
  2 +#define RTS_DTGRID_3D_H
  3 +
  4 +#include <vector>
  5 +#include <iostream>
  6 +using namespace std;
  7 +
  8 +#include "rtsDTGrid2D.h"
  9 +
  10 +struct Coord3D
  11 +{
  12 + int x1;
  13 + int x2;
  14 + int x3;
  15 +
  16 + bool operator==(Coord3D &rhs)
  17 + {
  18 + if( (x1 == rhs.x1) && (x2 == rhs.x2) && (x3 == rhs.x3) )
  19 + return true;
  20 + return false;
  21 + }
  22 +
  23 + bool operator<(Coord3D &rhs)
  24 + {
  25 + if(x1 < rhs.x1)
  26 + return true;
  27 + else if( (x1 == rhs.x1) && (x2 < rhs.x2) )
  28 + return true;
  29 + else if( (x1 == rhs.x1) && (x2 == rhs.x2) && (x3 < rhs.x3) )
  30 + return true;
  31 + return false;
  32 +
  33 + }
  34 +
  35 +};
  36 +
  37 +
  38 +
  39 +
  40 +/**************DT GRID**************************/
  41 +template<typename T>
  42 +class rtsDTGrid3D
  43 +{
  44 +private:
  45 + //main arrays
  46 + vector<T> value;
  47 + vector<ConnectedComponent> conn;
  48 + rtsDTGrid2D<IndexPair> proj2D;
  49 + Coord2D current_column;
  50 + bool randomIndex(rtsDTGrid2D<IndexPair>::iterator &iter2D, int &v_i, int &c_i, int x1, int x2, int x3);
  51 +
  52 +
  53 +
  54 + //variables to keep track of insertion
  55 + int max_coord;
  56 + bool grid_insertion_started;
  57 + bool column_insertion_started;
  58 +
  59 +
  60 +public:
  61 + rtsDTGrid3D<T>()
  62 + {
  63 + grid_insertion_started = false;
  64 + column_insertion_started = false;
  65 + proj2D.background.toConn = -1;
  66 + max_coord = 0;
  67 + }
  68 +
  69 + bool push(int x1, int x2, int x3, T v);
  70 + T random(int x1, int x2, int x3);
  71 + T background;
  72 +
  73 +
  74 + T& back();
  75 +
  76 + void print();
  77 + void operator=(T rhs);
  78 + void getBounds(int &min_x1, int &min_x2, int &min_x3, int &max_x1, int &max_x2, int &max_x3);
  79 + int getNumNodes(){return value.size();}
  80 + void insert(rtsDTGrid3D<T> toInsert);
  81 +
  82 + //arithmetic
  83 + rtsDTGrid3D<T> operator+(rtsDTGrid3D<T> &rhs);
  84 + rtsDTGrid3D<T> operator-(rtsDTGrid3D<T> &rhs);
  85 +
  86 +
  87 + //dilation
  88 + friend class ColumnUnion;
  89 + void dilate(int H);
  90 +
  91 + /*
  92 +
  93 +
  94 +
  95 +
  96 +
  97 + //other types of iteration
  98 + iterator begin_pn();
  99 + iterator end_pn();
  100 + iterator begin_np();
  101 + iterator end_np();
  102 + */
  103 +
  104 + //iterator
  105 + class iterator;
  106 + friend class iterator;
  107 + class stencil_iterator;
  108 + //iterator randomIterator(int x1, int x2);
  109 + iterator begin();
  110 + iterator before();
  111 + iterator end();
  112 + iterator after();
  113 +
  114 + //other types of iteration
  115 + iterator begin_ppn();
  116 + iterator begin_nnp();
  117 + iterator begin_pnp();
  118 + iterator begin_npn();
  119 + iterator begin_pnn();
  120 + iterator begin_npp();
  121 +
  122 +
  123 + iterator end_ppn(){return begin_nnp();}
  124 + iterator end_nnp(){return begin_ppn();}
  125 + iterator end_pnp(){return begin_npn();}
  126 + iterator end_npn(){return begin_pnp();}
  127 + iterator end_pnn(){return begin_npp();}
  128 + iterator end_npp(){return begin_pnn();}
  129 +};
  130 +
  131 +
  132 +/**********ITERATOR***********************/
  133 +template<typename T>
  134 +class rtsDTGrid3D<T>::iterator
  135 +{
  136 + friend class rtsDTGrid3D;
  137 + rtsDTGrid3D<T>* parent;
  138 + rtsDTGrid2D<IndexPair>::iterator loc2D;
  139 + int iv;
  140 + int ic;
  141 + int x3;
  142 +
  143 +public:
  144 +
  145 +
  146 + T Value(){return parent->value[iv];}
  147 + int X1(){return loc2D.X1();}
  148 + int X2(){return loc2D.X2();}
  149 + int X3(){return x3;}
  150 + Coord3D Coord()
  151 + {
  152 + Coord3D result;
  153 + result.x1 = X1();
  154 + result.x2 = X2();
  155 + result.x3 = X3();
  156 + return result;
  157 + }
  158 + iterator(){parent = NULL;}
  159 + void SetValue(T value){parent->value[iv] = value;}
  160 +
  161 +
  162 + void ppp()
  163 + {
  164 + //increment the value
  165 + iv++;
  166 + //if this exceeds the length of the value array, we are at the end of the grid
  167 + if(iv == parent->value.size())
  168 + {
  169 + (*this) = parent->after();
  170 + return;
  171 + }
  172 +
  173 + //increment the current coordinate
  174 + x3++;
  175 + //if we are outside of the current connected component
  176 + if(x3 > parent->conn[ic].coordMax)
  177 + {
  178 + //move to the next connected component
  179 + ic++;
  180 + //if this is the last connected component in the column
  181 + if(ic == loc2D.Value().toConn + loc2D.Value().numConn)
  182 + loc2D++;
  183 + //if there are no more connected components
  184 + if(ic == parent->conn.size())
  185 + {
  186 + //we're at the end, return end
  187 + (*this) = parent->end();
  188 + return;
  189 + }
  190 + x3 = parent->conn[ic].coordMin;
  191 + }
  192 + }
  193 + void ppn()
  194 + {
  195 + //decrement the value
  196 + iv--;
  197 +
  198 + //decrement the current coordinate
  199 + x3--;
  200 + //if we are outside of the current connected component
  201 + if(x3 < parent->conn[ic].coordMin)
  202 + {
  203 + //move to the previous connected component
  204 + ic--;
  205 + //if this is before the first connected component in the column
  206 + if(ic < loc2D.Value().toConn)
  207 + {
  208 + //increment to the next column
  209 + loc2D++;
  210 + //set the connected component to the last one in the column
  211 + ic = loc2D.Value().toConn + loc2D.Value().numConn - 1;
  212 + int num_values = parent->conn[ic].coordMax - parent->conn[ic].coordMin + 1;
  213 + iv = parent->conn[ic].toValue + num_values - 1;
  214 + }
  215 +
  216 + x3 = parent->conn[ic].coordMax;
  217 + }
  218 +
  219 +
  220 + }
  221 +
  222 + void nnp()
  223 + {
  224 + //increment the value
  225 + iv++;
  226 +
  227 + //increment the current coordinate
  228 + x3++;
  229 + //if we are outside of the current connected component
  230 + if(x3 > parent->conn[ic].coordMax)
  231 + {
  232 + //move to the next connected component
  233 + ic++;
  234 + //if this is after the last connected component in the column
  235 + if(ic == loc2D.Value().toConn + loc2D.Value().numConn)
  236 + {
  237 + //decrement to the previous column
  238 + loc2D--;
  239 + //set the connected component to the first one in the column
  240 + ic = loc2D.Value().toConn;
  241 + iv = parent->conn[ic].toValue;
  242 + }
  243 +
  244 + x3 = parent->conn[ic].coordMin;
  245 + }
  246 +
  247 +
  248 + }
  249 +
  250 +
  251 + void nnn()
  252 + {
  253 + //decrement the value
  254 + iv--;
  255 + //if this is less than 0, we are at the beginning of the grid
  256 + if(iv < 0)
  257 + {
  258 + (*this) = parent->before();
  259 + return;
  260 + }
  261 +
  262 + //decrement the current coordinate
  263 + x3--;
  264 + //if we are outside of the current connected component
  265 + if(x3 < parent->conn[ic].coordMin)
  266 + {
  267 + //move to the previous connected component
  268 + ic--;
  269 + //if this is the first connected component in the column
  270 + if(ic < loc2D.Value().toConn)
  271 + loc2D--;
  272 + //if there are no more connected components
  273 + if(ic < 0)
  274 + {
  275 + //we're at the beginning, return begin
  276 + (*this) = parent->before();
  277 + return;
  278 + }
  279 + x3 = parent->conn[ic].coordMax;
  280 + }
  281 +
  282 + }
  283 +
  284 + void pnp()
  285 + {
  286 + //increment the value
  287 + iv++;
  288 +
  289 + //increment the current coordinate
  290 + x3++;
  291 + //if we are outside of the current connected component
  292 + if(x3 > parent->conn[ic].coordMax)
  293 + {
  294 + //move to the next connected component
  295 + ic++;
  296 + //if this is after the last connected component in the column
  297 + if(ic == loc2D.Value().toConn + loc2D.Value().numConn)
  298 + {
  299 + //decrement to the previous column
  300 + loc2D.pn();
  301 + //set the connected component to the first one in the column
  302 + ic = loc2D.Value().toConn;
  303 + iv = parent->conn[ic].toValue;
  304 + }
  305 +
  306 + x3 = parent->conn[ic].coordMin;
  307 + }
  308 +
  309 +
  310 + }
  311 + void npn()
  312 + {
  313 + //decrement the value
  314 + iv--;
  315 +
  316 + //decrement the current coordinate
  317 + x3--;
  318 + //if we are outside of the current connected component
  319 + if(x3 < parent->conn[ic].coordMin)
  320 + {
  321 + //move to the previous connected component
  322 + ic--;
  323 + //if this is before the first connected component in the column
  324 + if(ic < loc2D.Value().toConn)
  325 + {
  326 + //increment to the next column
  327 + loc2D.np();
  328 + //set the connected component to the last one in the column
  329 + ic = loc2D.Value().toConn + loc2D.Value().numConn - 1;
  330 + int num_values = parent->conn[ic].coordMax - parent->conn[ic].coordMin + 1;
  331 + iv = parent->conn[ic].toValue + num_values - 1;
  332 + }
  333 +
  334 + x3 = parent->conn[ic].coordMax;
  335 + }
  336 +
  337 +
  338 + }
  339 + void pnn()
  340 + {
  341 + //decrement the value
  342 + iv--;
  343 +
  344 + //decrement the current coordinate
  345 + x3--;
  346 + //if we are outside of the current connected component
  347 + if(x3 < parent->conn[ic].coordMin)
  348 + {
  349 + //move to the previous connected component
  350 + ic--;
  351 + //if this is before the first connected component in the column
  352 + if(ic < loc2D.Value().toConn)
  353 + {
  354 + //increment to the next column
  355 + loc2D.pn();
  356 + //set the connected component to the last one in the column
  357 + ic = loc2D.Value().toConn + loc2D.Value().numConn - 1;
  358 + int num_values = parent->conn[ic].coordMax - parent->conn[ic].coordMin + 1;
  359 + iv = parent->conn[ic].toValue + num_values - 1;
  360 + }
  361 +
  362 + x3 = parent->conn[ic].coordMax;
  363 + }
  364 +
  365 +
  366 + }
  367 + void npp()
  368 + {
  369 + //increment the value
  370 + iv++;
  371 +
  372 + //increment the current coordinate
  373 + x3++;
  374 + //if we are outside of the current connected component
  375 + if(x3 > parent->conn[ic].coordMax)
  376 + {
  377 + //move to the next connected component
  378 + ic++;
  379 + //if this is after the last connected component in the column
  380 + if(ic == loc2D.Value().toConn + loc2D.Value().numConn)
  381 + {
  382 + //decrement to the previous column
  383 + loc2D.np();
  384 + //set the connected component to the first one in the column
  385 + ic = loc2D.Value().toConn;
  386 + iv = parent->conn[ic].toValue;
  387 + }
  388 +
  389 + x3 = parent->conn[ic].coordMin;
  390 + }
  391 +
  392 +
  393 + }
  394 +
  395 + /*
  396 + void pn()
  397 + {
  398 + //for the most part we will be going backwards through the array
  399 + //so first decrement iv
  400 + iv--;
  401 + x2--;
  402 + //if iv is less than the current connected component
  403 + if(iv < parent->conn[ic].toValue)
  404 + {
  405 + //go to the previous connected component
  406 + ic--;
  407 + //if we are before the first connected component in the column
  408 + if(ic < loc1D.Value().toConn)
  409 + {
  410 + //increment the 1D iterator
  411 + loc1D++;
  412 + //reset ic to the last component of the new column
  413 + ic = loc1D.Value().toConn + loc1D.Value().numConn - 1;
  414 + //find the new value identifier
  415 + iv = parent->conn[ic].toValue + (parent->conn[ic].coordMax - parent->conn[ic].coordMin);
  416 + }
  417 + //compute the currect coordinate
  418 + x2 = parent->conn[ic].coordMax;
  419 + }
  420 + }
  421 +
  422 + void np()
  423 + {
  424 + //for the most part we will be going forward through the grid
  425 + //increment iv
  426 + iv++;
  427 + x2++;
  428 +
  429 + //if we are outside of the current connected component
  430 + if(x2 > parent->conn[ic].coordMax)
  431 + {
  432 + //move to the next connected component
  433 + ic++;
  434 + //if this is the last connected component in the column
  435 + if(ic == loc1D.Value().toConn + loc1D.Value().numConn)
  436 + {
  437 + loc1D--;
  438 + ic = loc1D.Value().toConn;
  439 + iv = parent->conn[ic].toValue;
  440 + }
  441 +
  442 + x2 = parent->conn[ic].coordMin;
  443 + }
  444 +
  445 + }
  446 +
  447 +
  448 +
  449 +
  450 + friend bool operator<(iterator &left, iterator &right)
  451 + {
  452 + if(left.iv < right.iv)
  453 + return true;
  454 + return false;
  455 + }
  456 + friend bool operator<=(iterator &left, iterator &right)
  457 + {
  458 + if(left.iv <= right.iv)
  459 + return true;
  460 + return false;
  461 + }
  462 +
  463 + */
  464 +
  465 + void increment_until(int p1, int p2, int p3)
  466 + {
  467 + while((*this) != parent->end())
  468 + {
  469 + if(X1() > p1)
  470 + return;
  471 + if(X1() == p1 && X2() > p2)
  472 + return;
  473 + else if(X1() == p1 && X2() == p2 && X3() >= p3)
  474 + return;
  475 +
  476 + ppp();
  477 + }
  478 + }
  479 + void operator++(){ppp();}
  480 + void operator--(){nnn();}
  481 +
  482 + //boolean operators for comparing iterators
  483 + bool operator==(iterator &rhs)
  484 + {
  485 + if(parent == rhs.parent && iv == rhs.iv)
  486 + return true;
  487 +
  488 + //if(loc2D == rhs.loc2D && x3 == rhs.x3)
  489 + // return true;
  490 + return false;
  491 + }
  492 + bool operator!=(iterator &rhs){return !((*this) == rhs);}
  493 + bool operator<(iterator rhs)
  494 + {
  495 + if(parent == rhs.parent && iv < rhs.iv)
  496 + return true;
  497 + //if(loc2D < rhs.loc2D && x3 < rhs.x3)
  498 + // return true;
  499 + return false;
  500 +
  501 + }
  502 +};
  503 +
  504 +/**************ITERATOR METHODS IN DT GRID*******************/
  505 +template<typename T>
  506 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin()
  507 +{
  508 + //if the grid is empty, return an iterator to "after"
  509 + if(value.size() == 0)
  510 + return after();
  511 +
  512 + iterator result;
  513 + result.parent = this;
  514 + result.ic = 0;
  515 + result.iv = 0;
  516 + result.x3 = conn[0].coordMin;
  517 + result.loc2D = proj2D.begin();
  518 +
  519 + return result;
  520 +}
  521 +template<typename T>
  522 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::end()
  523 +{
  524 + //if the grid is empty, return after()
  525 + if(value.size() == 0)
  526 + return after();
  527 + iterator result;
  528 + result.parent = this;
  529 + result.ic = conn.size() - 1;
  530 + result.iv = value.size() - 1;
  531 + result.x3 = conn[result.ic].coordMax;
  532 + result.loc2D = proj2D.end();
  533 + return result;
  534 +}
  535 +template<typename T>
  536 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::after()
  537 +{
  538 + iterator result;
  539 + result.parent = this;
  540 + result.ic = conn.size() - 1;
  541 + result.iv = value.size();
  542 + //result.x2 = conn[result.ic].coordMax;
  543 + result.loc2D = proj2D.after();
  544 + return result;
  545 +}
  546 +
  547 +
  548 +template<typename T>
  549 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::before()
  550 +{
  551 + if(value.size() == 0)
  552 + return after();
  553 +
  554 + iterator result;
  555 + result.parent = this;
  556 + result.ic = 0;
  557 + result.iv = -1;
  558 + //result.x2 = conn[0].coordMin;
  559 + result.loc2D = proj2D.before();
  560 +
  561 + return result;
  562 +}
  563 +
  564 +template<typename T>
  565 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin_ppn()
  566 +{
  567 + //if the grid is empty, return an iterator to "after"
  568 + if(value.size() == 0)
  569 + return after();
  570 +
  571 + iterator result;
  572 + result.parent = this;
  573 + result.loc2D = proj2D.begin();
  574 + //find the index of the last connected component in the first column
  575 + int last_conn = result.loc2D.Value().toConn + result.loc2D.Value().numConn - 1;
  576 + result.ic = last_conn;
  577 + result.iv = conn[last_conn].toValue + conn[last_conn].coordMax - conn[last_conn].coordMin;
  578 + result.x3 = conn[last_conn].coordMax;
  579 +
  580 +
  581 + return result;
  582 +}
  583 +
  584 +template<typename T>
  585 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin_nnp()
  586 +{
  587 + //if the grid is empty, return an iterator to "after"
  588 + if(value.size() == 0)
  589 + return after();
  590 +
  591 + iterator result;
  592 + result.parent = this;
  593 + result.loc2D = proj2D.end();
  594 + //find the index of the first connected component in the last column
  595 + int first_conn = result.loc2D.Value().toConn;
  596 + result.ic = first_conn;
  597 + result.iv = conn[first_conn].toValue;
  598 + result.x3 = conn[first_conn].coordMin;
  599 +
  600 +
  601 + return result;
  602 +}
  603 +template<typename T>
  604 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin_pnp()
  605 +{
  606 + //if the grid is empty, return an iterator to "after"
  607 + if(value.size() == 0)
  608 + return after();
  609 +
  610 + iterator result;
  611 + result.parent = this;
  612 + result.loc2D = proj2D.begin_pn();
  613 + //find the index of the first connected component in the column
  614 + int first_conn = result.loc2D.Value().toConn;
  615 + result.ic = first_conn;
  616 + result.iv = conn[first_conn].toValue;
  617 + result.x3 = conn[first_conn].coordMin;
  618 +
  619 +
  620 + return result;
  621 +}
  622 +template<typename T>
  623 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin_npn()
  624 +{
  625 + //if the grid is empty, return an iterator to "after"
  626 + if(value.size() == 0)
  627 + return after();
  628 +
  629 + iterator result;
  630 + result.parent = this;
  631 + result.loc2D = proj2D.begin_np();
  632 + //find the index of the last connected component in the column
  633 + int last_conn = result.loc2D.Value().toConn + result.loc2D.Value().numConn - 1;
  634 + result.ic = last_conn;
  635 + result.iv = conn[last_conn].toValue + conn[last_conn].coordMax - conn[last_conn].coordMin;
  636 + result.x3 = conn[last_conn].coordMax;
  637 +
  638 +
  639 + return result;
  640 +}
  641 +template<typename T>
  642 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin_pnn()
  643 +{
  644 + //if the grid is empty, return an iterator to "after"
  645 + if(value.size() == 0)
  646 + return after();
  647 +
  648 + iterator result;
  649 + result.parent = this;
  650 + result.loc2D = proj2D.begin_pn();
  651 + //find the index of the last connected component in the column
  652 + int last_conn = result.loc2D.Value().toConn + result.loc2D.Value().numConn - 1;
  653 + result.ic = last_conn;
  654 + result.iv = conn[last_conn].toValue + conn[last_conn].coordMax - conn[last_conn].coordMin;
  655 + result.x3 = conn[last_conn].coordMax;
  656 +
  657 +
  658 + return result;
  659 +}
  660 +template<typename T>
  661 +typename rtsDTGrid3D<T>::iterator rtsDTGrid3D<T>::begin_npp()
  662 +{
  663 + //if the grid is empty, return an iterator to "after"
  664 + if(value.size() == 0)
  665 + return after();
  666 +
  667 + iterator result;
  668 + result.parent = this;
  669 + result.loc2D = proj2D.begin_np();
  670 + //find the index of the first connected component in the column
  671 + int first_conn = result.loc2D.Value().toConn;
  672 + result.ic = first_conn;
  673 + result.iv = conn[first_conn].toValue;
  674 + result.x3 = conn[first_conn].coordMin;
  675 +
  676 +
  677 + return result;
  678 +}
  679 +/**************DT GRID METHODS**************************/
  680 +template<typename T>
  681 +bool rtsDTGrid3D<T>::push(int x1, int x2, int x3, T v)
  682 +{
  683 + //run this code if we have to start a new column. This happens when:
  684 + //(a) we have just inserted the first value into the grid
  685 + //(b) the insertion takes place in a different column
  686 + if(grid_insertion_started == false || x1 != current_column.x1 || x2 != current_column.x2)
  687 + {
  688 + //assume that a new column is being created
  689 + //create the column in proj1D
  690 + IndexPair newPair;
  691 + newPair.toConn = conn.size();
  692 + //newPair.toValue = value.size();
  693 + newPair.numConn = 0;
  694 +
  695 + //if this insertion throws an error, the value was inserted incorrectly
  696 + //the error will get thrown by DTGrid2D, so just return
  697 + if(!proj2D.push(x1, x2, newPair))
  698 + {
  699 + cout<<"Out-of-order insertion in D = 3: X1 = "<<x1<<" X2 = "<<x2<<" X3 = "<<x3<<endl;
  700 + return false;
  701 + }
  702 +
  703 + column_insertion_started = false;
  704 + grid_insertion_started = true;
  705 + }
  706 + //If there is no new column, we still have to check to make sure the value is inserted
  707 + //in the correct order in X3:
  708 + else
  709 + {
  710 + if(column_insertion_started && x3 <= max_coord)
  711 + {
  712 + cout<<"Out-of-order insertion in D = 3: X1 = "<<x1<<" X2 = "<<x2<<" X3 = "<<x3<<endl;
  713 + return false;
  714 + }
  715 + }
  716 +
  717 +
  718 + //run this code if we have to start a new connected component. This happens when:
  719 + //(a) We insert the first value into the column
  720 + //(b) There is empty space between the last insertion and this one
  721 + if(column_insertion_started == false || x3 > (max_coord + 1))
  722 + {
  723 + //start a new connected component
  724 + ConnectedComponent new_conn;
  725 + new_conn.toValue = value.size();
  726 + new_conn.coordMin = x3;
  727 + new_conn.coordMax = x3;
  728 + conn.push_back(new_conn);
  729 + //increment the number of connected components for the column in X1
  730 + proj2D.back().numConn++;
  731 + column_insertion_started = true;
  732 + }
  733 +
  734 + //insert the value into the grid:
  735 + //(a) Insert the value at the end of the coord array
  736 + //(b) Increment the coordMax value of the current connected component
  737 + //(c) Change the maximum inserted coordinate to the new value
  738 + value.push_back(v);
  739 + conn[conn.size() - 1].coordMax = x3;
  740 + //change max_coord to the new coordinate
  741 + max_coord = x3;
  742 + //set the current column
  743 + current_column.x1 = x1;
  744 + current_column.x2 = x2;
  745 + return true;
  746 +}
  747 +
  748 +
  749 +template<typename T>
  750 +bool rtsDTGrid3D<T>::randomIndex(rtsDTGrid2D<IndexPair>::iterator &iter2D, int &v_i, int &c_i, int x1, int x2, int x3)
  751 +{
  752 + //search along the 2nd dimension
  753 + //get an iterator
  754 + iter2D = proj2D.randomIterator(x1, x2);
  755 +
  756 + //if the after() iterator is returned, exit
  757 + if(iter2D == proj2D.after())
  758 + {
  759 + c_i = conn.size();
  760 + v_i = value.size();
  761 + return false;
  762 + }
  763 +
  764 + IndexPair i = iter2D.Value();
  765 +
  766 + //if the column does not exist
  767 + if(iter2D.X1() != x1 || iter2D.X2() != x2)
  768 + {
  769 + //get the appropriate values from the 2D iterator
  770 + //(which points to the next valid column)
  771 + c_i = i.toConn;
  772 + v_i = conn[c_i].toValue;
  773 + return false;
  774 + }
  775 +
  776 + //otherwise perform the binary search within the column
  777 + int high, low, mid;
  778 + low = i.toConn;
  779 + high = i.toConn + i.numConn - 1;
  780 +
  781 + do
  782 + {
  783 + mid = low + (high - low)/2;
  784 + if(x3 > conn[mid].coordMax)
  785 + low = mid + 1;
  786 + else if(x3 < conn[mid].coordMin)
  787 + high = mid - 1;
  788 + else break;
  789 + }
  790 + while(low <= high);
  791 +
  792 + //at this point, mid is either at the appropriate connected component,
  793 + //or x2 is not in the grid
  794 + if(x3 >= conn[mid].coordMin && x3 <= conn[mid].coordMax)
  795 + {
  796 + int offset = x3 - conn[mid].coordMin;
  797 + c_i = mid;
  798 + v_i = conn[mid].toValue + offset;
  799 + return true;
  800 + }
  801 + else
  802 + {
  803 + c_i = mid;
  804 + v_i = conn[c_i].toValue;
  805 + return false;
  806 + }
  807 +}
  808 +
  809 +template<typename T>
  810 +T rtsDTGrid3D<T>::random(int x1, int x2, int x3)
  811 +{
  812 + int v_i, c_i;
  813 + rtsDTGrid2D<IndexPair>::iterator iter2D;
  814 + if(randomIndex(iter2D, v_i, c_i, x1, x2, x3))
  815 + return value[v_i];
  816 + else
  817 + return background;
  818 +}
  819 +
  820 +
  821 +
  822 +template<typename T>
  823 +T& rtsDTGrid3D<T>::back()
  824 +{
  825 + return value[value.size()-1];
  826 +}
  827 +template<typename T>
  828 +void rtsDTGrid3D<T>::print()
  829 +{
  830 + rtsDTGrid3D<T>::iterator i;
  831 + for(i = begin(); i != after(); i++)
  832 + {
  833 + cout<<i.X1()<<","<<i.X2()<<","<<i.X3()<<":"<<i.Value()<<endl;
  834 + }
  835 +
  836 +
  837 +}
  838 +template<typename T>
  839 +void rtsDTGrid3D<T>::operator =(T rhs)
  840 +{
  841 + for(int i=0; i<value.size(); i++)
  842 + value[i] = rhs;
  843 +}
  844 +
  845 +template<typename T>
  846 +void rtsDTGrid3D<T>::getBounds(int &min_x1, int &min_x2, int &min_x3, int &max_x1, int &max_x2, int &max_x3)
  847 +{
  848 + //if the grid is empty, return an empty bounding volume
  849 + if(value.size() == 0)
  850 + {
  851 + min_x1 = min_x2 = min_x3 = max_x1 = max_x2 = max_x3 = 0;
  852 + return;
  853 + }
  854 +
  855 + //get the min and max values for the 1D grid (x1 coordinate)
  856 + proj2D.getBounds(min_x1, min_x2, max_x1, max_x2);
  857 +
  858 + //initialize the min and max values
  859 + min_x3 = conn[0].coordMin;
  860 + max_x3 = conn.back().coordMax;
  861 +
  862 + //iterate through all columns finding the smallest and largest coordinate values
  863 + rtsDTGrid2D<IndexPair>::iterator i;
  864 + IndexPair col;
  865 + for(i=proj2D.begin(); i!=proj2D.after(); i++)
  866 + {
  867 + col = i.Value();
  868 + if(conn[col.toConn].coordMin < min_x3)
  869 + min_x3 = conn[col.toConn].coordMin;
  870 + if(conn[col.toConn + col.numConn - 1].coordMax > max_x3)
  871 + max_x3 = conn[col.toConn + col.numConn - 1].coordMax;
  872 + }
  873 +
  874 +
  875 +}
  876 +template<typename T>
  877 +void rtsDTGrid3D<T>::insert(rtsDTGrid3D<T> toInsert)
  878 +{
  879 + //create source and destination iterators
  880 + rtsDTGrid3D<T>::iterator source = toInsert.begin();
  881 + rtsDTGrid3D<T>::iterator dest = begin();
  882 +
  883 + for(source = toInsert.begin(); source != toInsert.after(); source++)
  884 + {
  885 + //move the destination iterator to the current source position
  886 + dest.increment_until(source.X1(), source.X2(), source.X3());
  887 + //cout<<"source: "<<source.X1()<<" "<<source.X2()<<": "<<source.Value()<<endl;
  888 + //cout<<"dest: "<<dest.X1()<<" "<<dest.X2()<<": "<<dest.Value()<<endl;
  889 + //if the position exists in dest
  890 + if(dest.X1() == source.X1() && dest.X2() == source.X2() && dest.X3() == source.X3())
  891 + dest.SetValue(source.Value());
  892 + //cout<<"dest: "<<dest.X1()<<" "<<dest.X2()<<": "<<dest.Value()<<endl;
  893 + }
  894 +
  895 +}
  896 +
  897 +template<typename T>
  898 +void rtsDTGrid3D<T>::dilate(int H)
  899 +{
  900 + //if the grid is empty, return unchanged
  901 + if(value.size() == 0)
  902 + return;
  903 +
  904 + ColumnUnion CUqueue;
  905 + CUqueue.ConnectToGrid(&conn);
  906 +
  907 +
  908 + //dilate the N-1 DT-Grid constituent
  909 + rtsDTGrid2D<IndexPair> dilated_proj2D = proj2D;
  910 +
  911 + //an empty pair has a number of connected components equal to zero
  912 + //this should not happen in reality and can therefore be used to check for new columns
  913 + IndexPair empty_pair;
  914 + empty_pair.numConn = 0;
  915 +
  916 + //set the background node to the empty node and dilate the 2D projection
  917 + dilated_proj2D.background = empty_pair;
  918 + dilated_proj2D.dilate(H);
  919 +
  920 + //create a new DT Grid that will replace this one
  921 + rtsDTGrid3D<T> new_grid;
  922 + new_grid.proj2D = dilated_proj2D;
  923 + new_grid.proj2D.background.toConn = -1;
  924 +
  925 + //create iteratorDilate that iterates along the dilated N-1 grid
  926 + rtsDTGrid2D<IndexPair>::stencil_iterator iteratorDilate;
  927 +
  928 + //create the template entrance nodes
  929 + int n;
  930 + for(n=-H; n<=H; n++)
  931 + iteratorDilate.addPosition(n, H);
  932 + //create the template exit nodes
  933 + for(n=-H; n<=H; n++)
  934 + iteratorDilate.addPosition(n, -H);
  935 +
  936 + //create an iterator to set the new proj2D values
  937 + rtsDTGrid2D<IndexPair>::iterator iteratorNew;
  938 +
  939 +
  940 + //variables for each iteration
  941 + IndexPair new_pair;
  942 + vector<ConnectedComponent>::iterator ccIterator;
  943 + unsigned int numValues = 0;
  944 + for(iteratorNew = new_grid.proj2D.begin(),
  945 + iteratorDilate = dilated_proj2D.begin();
  946 + iteratorDilate != dilated_proj2D.after();
  947 + iteratorNew++,
  948 + iteratorDilate++)
  949 + {
  950 + //if a column is entering the stencil
  951 + for(n=0; n<=(2*H); n++)
  952 + if(iteratorDilate.getValue(n).numConn)
  953 + CUqueue.InsertColumn(iteratorDilate.getValue(n));
  954 +
  955 + //compute the union of all columns in the queue
  956 + vector<ConnectedComponent> result = CUqueue.ComputeUnion(H);
  957 +
  958 + //compute the new IndexPair representing the column
  959 + new_pair.toConn = new_grid.conn.size();
  960 + new_pair.numConn = result.size();
  961 + //store the index pair
  962 + iteratorNew.SetValue(new_pair);
  963 +
  964 + //insert each of the connected components
  965 + for(ccIterator = result.begin(); ccIterator!=result.end(); ccIterator++)
  966 + {
  967 + new_grid.conn.push_back(*ccIterator);
  968 + new_grid.conn.back().toValue = numValues;
  969 + numValues += (*ccIterator).coordMax - (*ccIterator).coordMin + 1;
  970 + }
  971 +
  972 + //if a column is leaving the stencil
  973 + for(n=(2*H + 1); n<=(4*H + 1); n++)
  974 + if(iteratorDilate.getValue(n).numConn)
  975 + CUqueue.RemoveColumn();
  976 + }
  977 +
  978 + //allocate space for the new value array
  979 + new_grid.value.resize(numValues, background);
  980 +
  981 + //copy the data from this grid into the new grid
  982 + new_grid.insert(*this);
  983 +
  984 + //replace this grid with the new grid
  985 + conn = new_grid.conn;
  986 + value = new_grid.value;
  987 + proj2D = new_grid.proj2D;
  988 +
  989 +
  990 +}
  991 +
  992 +
  993 +
  994 +/***************ARITHMETIC********************************/
  995 +template<typename T>
  996 +rtsDTGrid3D<T> rtsDTGrid3D<T>::operator+(rtsDTGrid3D<T> &rhs)
  997 +{
  998 + rtsDTGrid3D<T> result;
  999 +
  1000 + //create an iterator for each DT Grid
  1001 + rtsDTGrid3D<T>::iterator left = begin();
  1002 + rtsDTGrid3D<T>::iterator right = rhs.begin();
  1003 +
  1004 + //iterate both until one iterator has hit after()
  1005 + while(left != after() && right != rhs.after())
  1006 + {
  1007 + //if the iterators are at the same coordinate
  1008 + if(left.Coord() == right.Coord())
  1009 + {
  1010 + //insert their sum into the new grid
  1011 + result.push(left.X1(), left.X2(), left.X3(), left.Value() + right.Value());
  1012 + //increment both
  1013 + left++; right++;
  1014 + }
  1015 + //add the lowest (lexicographically) value to the background, insert the result, and increment
  1016 + else if( (left.Coord() < right.Coord()) )
  1017 + {
  1018 + result.push(left.X1(), left.X2(), left.X3(), left.Value() + rhs.background);
  1019 + left++;
  1020 + }
  1021 + else if( (right.Coord() < left.Coord()) )
  1022 + {
  1023 + result.push(right.X1(), right.X2(), right.X3(), right.Value() + background);
  1024 + right++;
  1025 + }
  1026 + }
  1027 +
  1028 + //if the left iterator hasn't finished, iterate to finish it off
  1029 + while(left != after())
  1030 + {
  1031 + result.push(left.X1(), left.X2(), left.X3(), left.Value() + rhs.background);
  1032 + left++;
  1033 + }
  1034 +
  1035 + while(right != rhs.after())
  1036 + {
  1037 + result.push(right.X1(), right.X2(), right.X3(), right.Value() + rhs.background);
  1038 + right++;
  1039 + }
  1040 +
  1041 +
  1042 + return result;
  1043 +
  1044 +
  1045 +}
  1046 +
  1047 +template<typename T>
  1048 +rtsDTGrid3D<T> rtsDTGrid3D<T>::operator-(rtsDTGrid3D<T> &rhs)
  1049 +{
  1050 + rtsDTGrid3D<T> result;
  1051 +
  1052 + //create an iterator for each DT Grid
  1053 + rtsDTGrid3D<T>::iterator left = begin();
  1054 + rtsDTGrid3D<T>::iterator right = rhs.begin();
  1055 +
  1056 + //iterate both until one iterator has hit after()
  1057 + while(left != after() && right != rhs.after())
  1058 + {
  1059 + //if the iterators are at the same coordinate
  1060 + if(left.Coord() == right.Coord())
  1061 + {
  1062 + //insert their sum into the new grid
  1063 + result.push(left.X1(), left.X2(), left.X3(), left.Value() - right.Value());
  1064 + //increment both
  1065 + left++; right++;
  1066 + }
  1067 + //add the lowest (lexicographically) value to the background, insert the result, and increment
  1068 + else if( (left.Coord() < right.Coord()) )
  1069 + {
  1070 + result.push(left.X1(), left.X2(), left.X3(), left.Value() - rhs.background);
  1071 + left++;
  1072 + }
  1073 + else if( (right.Coord() < left.Coord()) )
  1074 + {
  1075 + result.push(right.X1(), right.X2(), right.X3(), background - right.Value());
  1076 + right++;
  1077 + }
  1078 + }
  1079 +
  1080 + //if the left iterator hasn't finished, iterate to finish it off
  1081 + while(left != after())
  1082 + {
  1083 + result.push(left.X1(), left.X2(), left.X3(), left.Value() - rhs.background);
  1084 + left++;
  1085 + }
  1086 +
  1087 + while(right != rhs.after())
  1088 + {
  1089 + result.push(right.X1(), right.X2(), right.X3(), background - right.Value());
  1090 + right++;
  1091 + }
  1092 +
  1093 +
  1094 + return result;
  1095 +
  1096 +
  1097 +}
  1098 +#endif
... ...
rtsFilamentNetwork.cpp 0 → 100755
  1 +++ a/rtsFilamentNetwork.cpp
  1 +#include "rtsFilamentNetwork.h"
  2 +
  3 +int rtsFilamentNetwork::LoadFIB(const char* filename)
  4 +{
  5 + return fib_load(filename);
  6 +}
  7 +
  8 +int rtsFilamentNetwork::fib_load(const char* filename)
  9 +{
  10 + //open the input file
  11 + ifstream infile;
  12 + infile.open(filename);
  13 + if(!infile) return 0;
  14 +
  15 + //temporary vector storing points
  16 + vector<point3D<float>> vertices;
  17 + vector<float> radii;
  18 + point3D<float> input;
  19 + point3D<float> max(0.0, 0.0, 0.0); //maximum extents of the points in the file
  20 +
  21 + float r;
  22 +
  23 + int i,j;
  24 + //get all of the nodes from the file
  25 + int num_nodes;
  26 + infile>>num_nodes;
  27 + int id;
  28 + for(i=0; i<num_nodes; i++)
  29 + {
  30 + infile>>id;
  31 + infile>>input.x; infile>>input.y; infile>>input.z; infile>>r;
  32 +
  33 + //update the maximum
  34 + if(input.x > max.x) max.x = input.x;
  35 + if(input.y > max.y) max.y = input.y;
  36 + if(input.z > max.z) max.z = input.z;
  37 +
  38 + vertices.push_back(input);
  39 + radii.push_back(r);
  40 + }
  41 +
  42 + /*Scale the node values based on the maximum value. I do this so that
  43 + every node is between 0 - 1 rather than the original scale. In the long run,
  44 + it should make rendering easier.
  45 + */
  46 + for(i=0; i<num_nodes; i++)
  47 + {
  48 + vertices[i].x = vertices[i].x/max.x;
  49 + vertices[i].y = vertices[i].y/max.y;
  50 + vertices[i].z = vertices[i].z/max.z;
  51 +
  52 + vertices.push_back(input);
  53 + radii.push_back(r);
  54 + }
  55 +
  56 + //get each fiber
  57 + int num_filaments;
  58 + int num_edges;
  59 + infile>>num_filaments;
  60 +
  61 + for(i=0; i<num_filaments; i++)
  62 + {
  63 + network->objBegin(OBJ_LINE_STRIP); //begin the filament
  64 + infile>>num_edges;
  65 + for(j = 1; j<num_edges; j++) //get the index of each edge
  66 + {
  67 + infile>>id; id--;
  68 + network->objVertex3f(vertices[id].x, vertices[id].y, vertices[id].z);
  69 + //this final read is required because of redundancy in the input file
  70 + infile>>id;
  71 + }
  72 + infile>>id; //this final read is also required due to redundancy in the input file
  73 + id--;
  74 + network->objVertex3f(vertices[id].x, vertices[id].y, vertices[id].z);
  75 + infile>>id;
  76 + id--;
  77 + network->objVertex3f(vertices[id].x, vertices[id].y, vertices[id].z);
  78 + network->objEnd();
  79 + }
  80 + return 1;
  81 +}
  82 +
  83 +void rtsFilamentNetwork::PrintProperties()
  84 +{
  85 +
  86 + cout<<"Number of Filaments: "<<network->getNumLines();
  87 +}
  88 +
  89 +void rtsFilamentNetwork::PrintNetwork()
  90 +{
  91 +
  92 +}
0 93 \ No newline at end of file
... ...
rtsFilamentNetwork.h 0 → 100755
  1 +++ a/rtsFilamentNetwork.h
  1 +#ifndef RTSFILAMENTNETWORK_H
  2 +#define RTSFILAMENTNETWORK_H
  3 +
  4 +#include "rtsLinearAlgebra.h"
  5 +#include "objJedi.h"
  6 +#include <vector>
  7 +#include <fstream>
  8 +
  9 +using namespace std;
  10 +
  11 +
  12 +class rtsFilamentNetwork
  13 +{
  14 +protected:
  15 + rtsOBJ* network;
  16 + int fib_load(const char* filename);
  17 +
  18 +public:
  19 + rtsFilamentNetwork(){network = new rtsOBJ();}
  20 +
  21 + virtual int LoadFIB(const char* filename);
  22 + void PrintProperties();
  23 + void PrintNetwork();
  24 +
  25 +};
  26 +
  27 +
  28 +
  29 +#endif
  30 +
  31 +
  32 +
  33 +
  34 +
  35 +
0 36 \ No newline at end of file
... ...
rtsFilename.h 0 → 100755
  1 +++ a/rtsFilename.h
  1 +#include <string>
  2 +
  3 +using namespace std;
  4 +
  5 +#ifndef RTS_FILENAME_H
  6 +#define RTS_FILENAME_H
  7 +
  8 +class rtsFilename
  9 +{
  10 +private:
  11 + string filename;
  12 +
  13 +public:
  14 + string getFilename()
  15 + {
  16 + int pos = filename.find_last_of("/\\");
  17 + string name = filename.substr(pos+1, filename.size());
  18 + return name;
  19 + }
  20 +
  21 + rtsFilename& operator=(const string str)
  22 + {
  23 + filename = str;
  24 + return *this;
  25 + }
  26 + rtsFilename(const string str){filename = str;}
  27 + rtsFilename(){filename = "";}
  28 +
  29 + string getExtension()
  30 + {
  31 + int pos = filename.find_last_of(".");
  32 + string ext = filename.substr(pos+1, filename.size() - pos);
  33 + return ext;
  34 + }
  35 +
  36 + string getDirectory()
  37 + {
  38 + int pos = filename.find_last_of("/\\");
  39 + string directory;
  40 + if(pos != -1)
  41 + directory = filename.substr(0, pos);
  42 + else
  43 + directory = "";
  44 + return directory;
  45 + }
  46 +
  47 + string getPrefix()
  48 + {
  49 + int slash = filename.find_last_of("/\\");
  50 + int dot = filename.find_last_of(".");
  51 +
  52 + string prefix;
  53 + prefix = filename.substr(slash+1, dot - slash - 1);
  54 + return prefix;
  55 +
  56 + }
  57 +
  58 + string getString()
  59 + {
  60 + return filename;
  61 + }
  62 +
  63 +
  64 +
  65 +};
  66 +
  67 +#endif
0 68 \ No newline at end of file
... ...
rtsFunction3D.h 0 → 100755
  1 +++ a/rtsFunction3D.h
  1 +#ifndef RTSFUNCTION3D_H
  2 +#define RTSFUNCTION3D_H
  3 +
  4 +#define DIST_MAX 255
  5 +
  6 +#include "rtsLinearAlgebra.h"
  7 +//#include "rtsDTGrid3D.h"
  8 +#include <fstream>
  9 +//#include <iostream>
  10 +//#include <math.h>
  11 +//#include <queue>
  12 +//#include <algorithm>
  13 +using namespace std;
  14 +
  15 +typedef int indextype;
  16 +
  17 +///This class represents a 3D implicit function as a grid. It provides methods for accessing values, interpolation, and several utilities.
  18 +
  19 +template <class T> class rtsFunction3D
  20 +{
  21 +private:
  22 + //pointer to store the data
  23 + T* m_data;
  24 + //resolution of the data (x, y, z) dimensional extents
  25 + vector3D<indextype> m_resolution;
  26 + T m_boundary; //boundary condition
  27 + point3D<double> m_domain_min; //min and max range values (used for parametric access)
  28 + point3D<double> m_domain_max;
  29 + vector3D<double> m_voxel_size;
  30 +
  31 + //bit-blit function copies 3D data quickly from source to dest
  32 + void blit3D(const T* source,
  33 + indextype s_px, indextype s_py, indextype s_pz,
  34 + indextype s_sx, indextype s_sy, indextype s_sz,
  35 + T* dest,
  36 + indextype d_px, indextype d_py, indextype d_pz,
  37 + indextype d_sx, indextype d_sy, indextype d_sz,
  38 + indextype blit_size_x, indextype blit_size_y, indextype blit_size_z);
  39 +
  40 + void shallow_copy(const rtsFunction3D<T> source, rtsFunction3D<T> &dest);
  41 + inline point3D<double> getParameter(indextype i);
  42 + void initialize_empty(indextype res_x, indextype res_y, indextype res_z);
  43 +
  44 +public:
  45 + //construct an implicit function with a size of 1
  46 + rtsFunction3D(); ///<Create an empty implicit function
  47 + //construct an implicit function of the specified resolution
  48 + rtsFunction3D(indextype res_x, indextype res_y, indextype res_z); ///<Create an implicit function with the specified resolution
  49 + //construct an implicit function from sample data and a specified size
  50 + rtsFunction3D(T* data, indextype res_x, indextype res_y, indextype res_z); ///<Create an implicit function from previous data at the specified resolution
  51 + //shallow-copy constructor, defines all shallow variables
  52 + rtsFunction3D(vector3D<int> resolution, T boundary, point3D<double> min_domain, point3D<double> max_domain);
  53 + //full copy constructor, defines all variables
  54 + rtsFunction3D(T* data, vector3D<int> resolution, T boundary, point3D<double> min_domain, point3D<double> max_domain);
  55 + rtsFunction3D(const rtsFunction3D<T> &original); //copy constructor
  56 + ~rtsFunction3D(); //destructor
  57 + void Init(indextype res_x, indextype res_y, indextype res_z);
  58 +
  59 + //overloaded operators
  60 + rtsFunction3D<T>& operator=(const rtsFunction3D<T>& original); ///<Overloaded operator creates a copy of an implicit function
  61 + rtsFunction3D<T>& operator=(const T constant); ///<Overloaded operator sets all points in an implicit function to the given constant value
  62 + inline T& operator()(indextype x, indextype y, indextype z); ///<Allows access to the sample point indexed by x, y, and z using the parenthesis operator
  63 + inline T operator()(double i, double j, double k); ///<Allows access to the implicit function (based on the domain boundaries) at the position (i, j, k). This class uses linear interpolation.
  64 + rtsFunction3D<T>& operator*=(const T constant); ///<Multiplies the values at all sample points by a constant.
  65 + rtsFunction3D<T>& operator+=(const T constant); ///<Adds a constant to the values at all sample points.
  66 + rtsFunction3D<T>& operator-=(const T constant); ///<Subtracts a constant from the values at all sample points.
  67 + rtsFunction3D<T>& operator/=(const T constant); ///<Divides all values by a constant.
  68 + const rtsFunction3D<T> operator+(const T constant); ///<Adds a constant to an implicit function and returns a new function.
  69 + const rtsFunction3D<T> operator-(const T constant); ///<Subtracts a constant from an implicit function and returns a new function.
  70 + const rtsFunction3D<T> operator*(const T constant); ///<Multiplies an implicit function by a constant and returns a new function.
  71 + const rtsFunction3D<T> operator/(const T constant); ///<Divides an implicit function by a constant and returns a new function.
  72 +
  73 + //casting operator
  74 + //template <class U> friend class rtsFunction3D<U>;
  75 + template <class U> operator rtsFunction3D<U>(); ///<Casts between data types.
  76 +
  77 + //friend classes for overloading "backwards" operations (like 3*function)
  78 + friend rtsFunction3D<T> operator*(const T lhs, rtsFunction3D<T> rhs){return rhs*lhs;} ///<Allows associative multiplication.
  79 + friend rtsFunction3D<T> operator+(const T lhs, rtsFunction3D<T> rhs){return rhs+lhs;} ///<Allows associative addition.
  80 + friend rtsFunction3D<T> operator-(const T lhs, rtsFunction3D<T> rhs) ///<Allows associative subtraction.
  81 + {
  82 + rtsFunction3D<T> result;
  83 + rhs.shallow_copy(rhs, result); //make a copy of all of the shallow variables and allocate memory
  84 + indextype size = rhs.m_resolution.x * rhs.m_resolution.y * rhs.m_resolution.z;
  85 + //iterate and subtract
  86 + for(indextype i=0; i<size; i++)
  87 + result.m_data[i] = lhs - rhs.m_data[i];
  88 +
  89 + return result;
  90 + }
  91 + //friend rtsFunction3D<T> operator/(const T lhs, rtsFunction3D<T> rhs);
  92 +
  93 + //loading/saving data to disk
  94 + void LoadRAW(indextype header_size, indextype data_x, indextype data_y, indextype data_z, const char* filename); ///<Loads RAW data from a file with the specified header size and data size.
  95 + void SaveRAW(const char* filename); ///<Save the data as RAW data to disk.
  96 + void LoadVOL(const char* filename); ///<Load a VOL file from disk.
  97 + void SaveVOL(const char* filename); ///<Save a VOL file to disk.
  98 +
  99 + rtsFunction3D<T> Project2D(); //<Projects the data along the z-axis using a maximum-intensity projection.
  100 +
  101 + //data access methods
  102 + inline T& xyz(indextype x, indextype y, indextype z);
  103 + inline T ijk(double i, double j, double k);
  104 + void Parameterize(double x_min, double x_max, double y_min, double y_max, double z_min, double z_max);
  105 + void setBoundary(T boundary){m_boundary = boundary;}
  106 + T getBoundary(){return m_boundary;}
  107 + T* GetBits();
  108 + indextype DimX(){return m_resolution.x;}
  109 + indextype DimY(){return m_resolution.y;}
  110 + indextype DimZ(){return m_resolution.z;}
  111 + inline point3D<double> getParameter(indextype x, indextype y, indextype z);
  112 + inline point3D<indextype> getNearestIndex(double i, double j, double k);
  113 + inline point3D<double> getFractionalIndex(double i, double j, double k);
  114 + inline point3D<indextype> getNearestIndex(indextype i);
  115 + point3D<double> getMinDomain(){return m_domain_min;}
  116 + point3D<double> getMaxDomain(){return m_domain_max;}
  117 +
  118 + //data input methods
  119 + void Insert(rtsFunction3D<T>* source, indextype x, indextype y, indextype z);
  120 +
  121 + //data massaging
  122 +
  123 + void Scale(T min, T max);
  124 + void Crop(indextype x, indextype y, indextype z, indextype size_x, indextype size_y, indextype size_z);
  125 + void Binary(T threshold, T true_value); ///<Turns the image into a binary image based on a threshold value T. All values below T are set to 0, all values above are set to true_value.
  126 + void Threshold(T min, T value);
  127 + void Threshold(T min, T max, T value);
  128 + void Threshold(T min, T max, T inside, T outside);
  129 + void ClampMax(T max); ///<Clamps the function to the given maximum value.
  130 + void ClampMin(T min);
  131 + T getMin();
  132 + T getMax();
  133 +
  134 + //create new data
  135 + rtsFunction3D<T>* Resample(indextype newres_x, indextype newres_y, indextype newres_z);
  136 +
  137 + //output functions
  138 + void toConsole();
  139 +
  140 +};
  141 +
  142 +template <class T>
  143 +void rtsFunction3D<T>::blit3D(const T* source,
  144 + indextype s_px, indextype s_py, indextype s_pz,
  145 + indextype s_sx, indextype s_sy, indextype s_sz,
  146 + T* dest,
  147 + indextype d_px, indextype d_py, indextype d_pz,
  148 + indextype d_sx, indextype d_sy, indextype d_sz,
  149 + indextype blit_size_x, indextype blit_size_y, indextype blit_size_z)
  150 +{
  151 + indextype ps, pd; //stores the mapping for the source point to the dest point
  152 + //find the maximum points that can be blit to (in case source overlaps the edges of dest)
  153 + blit_size_x = min(blit_size_x, min(s_sx - s_px, d_sx - d_px));
  154 + blit_size_y = min(blit_size_y, min(s_sy - s_py, d_sy - d_py));
  155 + blit_size_z = min(blit_size_z, min(s_sz - s_pz, d_sz - d_pz));
  156 +
  157 + indextype source_z_offset = s_sx * s_sy;
  158 + indextype dest_z_offset = d_sx * d_sy;
  159 +
  160 + indextype z,y;
  161 + for(z=0; z<blit_size_z; z++)
  162 + for(y=0; y<blit_size_y; y++)
  163 + {
  164 + ps = (z + s_pz) * source_z_offset + (y + s_py) * s_sx + s_px;
  165 + pd = (z + d_pz) * dest_z_offset + (y + d_py) * d_sx + d_px;
  166 + memcpy((void*)(&dest[pd]), (void*)(&source[ps]), sizeof(T)*blit_size_x);
  167 + }
  168 +}
  169 +
  170 +template <class T>
  171 +void rtsFunction3D<T>::shallow_copy(const rtsFunction3D<T> source, rtsFunction3D<T> &dest)
  172 +{
  173 + dest = rtsFunction3D<T>(source.m_resolution.x, source.m_resolution.y, source.m_resolution.z);
  174 + dest.m_boundary = source.m_boundary;
  175 + dest.m_domain_max = source.m_domain_max;
  176 + dest.m_domain_min = source.m_domain_max;
  177 + dest.m_voxel_size = source.m_voxel_size;
  178 +}
  179 +
  180 +template <class T>
  181 +rtsFunction3D<T>::rtsFunction3D(vector3D<int> resolution, T boundary, point3D<double> domain_min, point3D<double> domain_max)
  182 +{
  183 + //This function creates an implicit function based on all of the shallow variables
  184 + m_resolution = resolution;
  185 + m_boundary = boundary;
  186 + m_domain_min = domain_min;
  187 + m_domain_max = domain_max;
  188 + m_voxel_size = domain_max - domain_min;
  189 + m_voxel_size.x /= m_resolution.x;
  190 + m_voxel_size.y /= m_resolution.y;
  191 + m_voxel_size.z /= m_resolution.z;
  192 +
  193 + //allocate the data
  194 + m_data = new T[m_resolution.x * m_resolution.y * m_resolution.z];
  195 +}
  196 +
  197 +template <class T>
  198 +rtsFunction3D<T>::rtsFunction3D(T* data, vector3D<int> resolution, T boundary, point3D<double> domain_min, point3D<double> domain_max)
  199 +{
  200 + //This function creates an implicit function based on ALL of the variables
  201 + m_resolution = resolution;
  202 + m_boundary = boundary;
  203 + m_domain_min = domain_min;
  204 + m_domain_max = domain_max;
  205 + m_voxel_size = domain_max - domain_min;
  206 + m_voxel_size.x /= m_resolution.x;
  207 + m_voxel_size.y /= m_resolution.y;
  208 + m_voxel_size.z /= m_resolution.z;
  209 +
  210 + //allocate the data
  211 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  212 + m_data = new T[size];
  213 + memcpy(m_data, data, sizeof(T)*size);
  214 + //for(int i=0; i<size; i++)
  215 + // m_data[i] = data[i];
  216 +}
  217 +
  218 +
  219 +
  220 +template <class T>
  221 +rtsFunction3D<T>::rtsFunction3D()
  222 +{
  223 + m_resolution.x = 1;
  224 + m_resolution.y = 1;
  225 + m_resolution.z = 1;
  226 + m_data = new T[1];
  227 + memset(&m_boundary, 0, sizeof(T)); //initialize boundary condition
  228 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  229 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  230 + m_voxel_size = vector3D<double>(1.0, 1.0, 1.0);
  231 +}
  232 +
  233 +template <class T>
  234 +void rtsFunction3D<T>::initialize_empty(indextype res_x, indextype res_y, indextype res_z)
  235 +{
  236 + m_resolution.x = res_x; //set resolution vector
  237 + m_resolution.y = res_y;
  238 + m_resolution.z = res_z;
  239 + m_data = (T*)calloc(res_x*res_y*res_z, sizeof(T)); //allocate data
  240 +}
  241 +
  242 +template <class T>
  243 +rtsFunction3D<T>::rtsFunction3D(indextype res_x, indextype res_y, indextype res_z)
  244 +{
  245 + initialize_empty(res_x, res_y, res_z);
  246 + memset(&m_boundary, 0, sizeof(T)); //initialize boundary condition
  247 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  248 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  249 +
  250 + m_voxel_size = m_domain_max - m_domain_min;
  251 + m_voxel_size.x /= m_resolution.x;
  252 + m_voxel_size.y /= m_resolution.y;
  253 + m_voxel_size.z /= m_resolution.z;
  254 +}
  255 +
  256 +template <class T>
  257 +void rtsFunction3D<T>::Init(indextype res_x, indextype res_y, indextype res_z)
  258 +{
  259 + initialize_empty(res_x, res_y, res_z);
  260 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  261 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  262 + memset(&m_boundary, 0, sizeof(T)); //initialize boundary condition
  263 +
  264 + m_voxel_size = m_domain_max - m_domain_min;
  265 + m_voxel_size.x /= m_resolution.x;
  266 + m_voxel_size.y /= m_resolution.y;
  267 + m_voxel_size.z /= m_resolution.z;
  268 +}
  269 +
  270 +template <class T>
  271 +rtsFunction3D<T>::rtsFunction3D(T* data, indextype res_x, indextype res_y, indextype res_z)
  272 +{
  273 + m_resolution.x = res_x; //set resolution vector
  274 + m_resolution.y = res_y;
  275 + m_resolution.z = res_z;
  276 + m_data = new T[res_x*res_y*res_z]; //allocate data
  277 + //copy the sample data into the data array
  278 + indextype size = res_x*res_y*res_z;
  279 + for(indextype i=0; i<size; i++)
  280 + m_data[i] = data[i];
  281 + memset(&m_boundary, 0, sizeof(T)); //initialize boundary condition
  282 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  283 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  284 +
  285 + m_voxel_size = domain_max - domain_min;
  286 + m_voxel_size.x /= m_resolution.x;
  287 + m_voxel_size.y /= m_resolution.y;
  288 + m_voxel_size.z /= m_resolution.z;
  289 +}
  290 +
  291 +template <class T>
  292 +rtsFunction3D<T>::rtsFunction3D(const rtsFunction3D<T>& original)
  293 +{
  294 + //copy the shallow variables
  295 + m_resolution = original.m_resolution;
  296 + m_boundary = original.m_boundary;
  297 + m_domain_min = original.m_domain_min;
  298 + m_domain_max = original.m_domain_max;
  299 + m_voxel_size = original.m_voxel_size;
  300 +
  301 + //allocate space for the data
  302 + m_data = new T[m_resolution.x * m_resolution.y * m_resolution.z];
  303 + //copy the data
  304 + blit3D(original.m_data,
  305 + 0, 0, 0,
  306 + m_resolution.x, m_resolution.y, m_resolution.z,
  307 + m_data,
  308 + 0, 0, 0,
  309 + m_resolution.x, m_resolution.y, m_resolution.z,
  310 + m_resolution.x, m_resolution.y, m_resolution.z);
  311 +}
  312 +
  313 +template <class T>
  314 +rtsFunction3D<T>::~rtsFunction3D()
  315 +{
  316 + delete m_data;
  317 +}
  318 +
  319 +template <class T>
  320 +typename rtsFunction3D<T>& rtsFunction3D<T>::operator=(const T rhs)
  321 +{
  322 + indextype size = m_resolution.x*m_resolution.y*m_resolution.z;
  323 + for(int i=0; i<size; i++)
  324 + m_data[i] = rhs;
  325 +
  326 + return *this;
  327 +}
  328 +
  329 +template <class T>
  330 +typename rtsFunction3D<T>& rtsFunction3D<T>::operator=(const rtsFunction3D<T>& rhs)
  331 +{
  332 + //check for self-assignment
  333 + if(this == &rhs)
  334 + return *this;
  335 +
  336 + //deallocate memory
  337 + if(m_data != NULL)
  338 + delete m_data;
  339 +
  340 + //copy the shallow variables
  341 + m_resolution = rhs.m_resolution;
  342 + m_boundary = rhs.m_boundary;
  343 + m_domain_min = rhs.m_domain_min;
  344 + m_domain_max = rhs.m_domain_max;
  345 + m_voxel_size = rhs.m_voxel_size;
  346 +
  347 + //allocate and copy memory
  348 + m_data = new T[m_resolution.x * m_resolution.y * m_resolution.z];
  349 + //copy the data
  350 + blit3D(rhs.m_data,
  351 + 0,0,0,
  352 + m_resolution.x, m_resolution.y, m_resolution.z,
  353 + m_data,
  354 + 0, 0, 0,
  355 + m_resolution.x, m_resolution.y, m_resolution.z,
  356 + m_resolution.x, m_resolution.y, m_resolution.z);
  357 +
  358 + //return the left hand side
  359 + return *this;
  360 +}
  361 +
  362 +template <class T>
  363 +inline T& rtsFunction3D<T>::operator ()(indextype x, indextype y, indextype z)
  364 +{
  365 + return xyz(x, y, z);
  366 +}
  367 +
  368 +template <class T>
  369 +inline T rtsFunction3D<T>::operator()(double i, double j, double k)
  370 +{
  371 + return ijk(i, j, k);
  372 +}
  373 +
  374 +template <class T>
  375 +rtsFunction3D<T>& rtsFunction3D<T>::operator *=(const T constant)
  376 +{
  377 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  378 + for(indextype i = 0; i<size; i++)
  379 + m_data[i] *= constant;
  380 +
  381 + return *this;
  382 +}
  383 +
  384 +template <class T>
  385 +rtsFunction3D<T>& rtsFunction3D<T>::operator +=(const T constant)
  386 +{
  387 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  388 + for(indextype i = 0; i<size; i++)
  389 + m_data[i] += constant;
  390 +
  391 + return *this;
  392 +}
  393 +template <class T>
  394 +rtsFunction3D<T>& rtsFunction3D<T>::operator -=(const T constant)
  395 +{
  396 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  397 + for(indextype i = 0; i<size; i++)
  398 + m_data[i] -= constant;
  399 +
  400 + return *this;
  401 +}
  402 +template <class T>
  403 +rtsFunction3D<T>& rtsFunction3D<T>::operator /=(const T constant)
  404 +{
  405 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  406 + for(indextype i = 0; i<size; i++)
  407 + m_data[i] /= constant;
  408 +
  409 + return *this;
  410 +}
  411 +template <class T>
  412 +const rtsFunction3D<T> rtsFunction3D<T>::operator *(const T constant)
  413 +{
  414 + rtsFunction3D<T> result = (*this);
  415 + result *= constant;
  416 +
  417 + return result;
  418 +}
  419 +
  420 +template <class T>
  421 +const rtsFunction3D<T> rtsFunction3D<T>::operator +(const T constant)
  422 +{
  423 + rtsFunction3D<T> result = (*this);
  424 + result += constant;
  425 +
  426 + return result;
  427 +}
  428 +
  429 +template <class T>
  430 +const rtsFunction3D<T> rtsFunction3D<T>::operator -(const T constant)
  431 +{
  432 + rtsFunction3D<T> result = (*this);
  433 + result -= constant;
  434 +
  435 + return result;
  436 +}
  437 +
  438 +template <class T>
  439 +const rtsFunction3D<T> rtsFunction3D<T>::operator /(const T constant)
  440 +{
  441 + rtsFunction3D<T> result = (*this);
  442 + result /= constant;
  443 +
  444 + return result;
  445 +}
  446 +
  447 +template <class T>
  448 +template <class U>
  449 +rtsFunction3D<T>::operator rtsFunction3D<U>()
  450 +{
  451 + //cast one type to another
  452 + //create the data pointer from the current function
  453 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  454 + U* new_data = new U[size];
  455 + for(int i=0; i<size; i++)
  456 + new_data[i] = m_data[i];
  457 + rtsFunction3D<U> cast_result(new_data, m_resolution, m_boundary, m_domain_min, m_domain_max);
  458 +
  459 + return cast_result;
  460 +}
  461 +
  462 +template <class T>
  463 +inline T& rtsFunction3D<T>::xyz(indextype x, indextype y, indextype z)
  464 +{
  465 + if(x<0 || y<0 || z<0 || x>=m_resolution.x || y>=m_resolution.y || z>=m_resolution.z)
  466 + return m_boundary;
  467 + //return m_data[(z * m_resolution.x * m_resolution.y) + (y * m_resolution.x) + x];
  468 + return m_data[x + m_resolution.x * (y + z * m_resolution.y)];
  469 +
  470 +}
  471 +
  472 +template <class T>
  473 +inline point3D<indextype> rtsFunction3D<T>::getNearestIndex(indextype i)
  474 +{
  475 + point3D<indextype> result;
  476 + result.z = i/(m_resolution.x*m_resolution.y);
  477 + indextype mod = i%(m_resolution.x*m_resolution.y);
  478 + result.y = mod/m_resolution.x;
  479 + result.x = mod%m_resolution.x;
  480 +
  481 + return result;
  482 +
  483 +}
  484 +
  485 +template <class T>
  486 +void rtsFunction3D<T>::LoadRAW(indextype header_size, indextype size_x,
  487 + indextype size_y, indextype size_z, const char *filename)
  488 +{
  489 + //set the data size
  490 + m_resolution = vector3D<indextype>(size_x, size_y, size_z);
  491 + //delete any previous data
  492 + if(m_data != NULL)
  493 + {
  494 + delete m_data;
  495 + m_data = NULL;
  496 + }
  497 +
  498 + ifstream infile(filename, ios::in | ios::binary);
  499 +
  500 + //load the header
  501 + unsigned char* header = new unsigned char[header_size];
  502 + infile.read((char*)header, header_size);
  503 +
  504 + //load the actual data
  505 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  506 + //m_data = (T*)malloc(size*sizeof(T));
  507 + initialize_empty(m_resolution.x, m_resolution.y, m_resolution.z);
  508 + infile.read((char*)m_data, size*sizeof(T));
  509 +
  510 + //calculate min and maxes
  511 + infile.close();
  512 +}
  513 +
  514 +template <class T>
  515 +void rtsFunction3D<T>::LoadVOL(const char *filename)
  516 +{
  517 + ifstream infile(filename, ios::in | ios::binary); //create the files stream
  518 + if(!infile)
  519 + return;
  520 +
  521 + indextype size_x, size_y, size_z; //create variables to store the size of the data set
  522 + //load the dimensions of the data set
  523 + infile.read((char*)&size_x, sizeof(int)); //load the file header
  524 + infile.read((char*)&size_y, sizeof(int));
  525 + infile.read((char*)&size_z, sizeof(int));
  526 +
  527 + //close the file
  528 + infile.close();
  529 + //load the raw data
  530 + LoadRAW(12, size_x, size_y, size_z, filename);
  531 +}
  532 +
  533 +template <class T>
  534 +void rtsFunction3D<T>::SaveVOL(const char *filename)
  535 +{
  536 + ofstream outfile(filename, ios::out | ios::binary); //create the binary file stream
  537 +
  538 + //write the volume size to the file
  539 + vector3D<int> vol_size = m_resolution;
  540 + outfile.write((char*)&vol_size.x, sizeof(int));
  541 + outfile.write((char*)&vol_size.y, sizeof(int));
  542 + outfile.write((char*)&vol_size.z, sizeof(int));
  543 +
  544 + outfile.write((char*)m_data, sizeof(T)*vol_size.x*vol_size.y*vol_size.z);
  545 +}
  546 +
  547 +template <class T>
  548 +void rtsFunction3D<T>::SaveRAW(const char *filename)
  549 +{
  550 + ofstream outfile(filename, ios::out | ios::binary); //create the binary file stream
  551 +
  552 + //write the volume data
  553 + outfile.write((char*)m_data, sizeof(T)*m_resolution.x*m_resolution.y*m_resolution.z);
  554 +}
  555 +
  556 +template <class T>
  557 +inline T rtsFunction3D<T>::ijk(double i, double j, double k)
  558 +{
  559 + /*This function determines the value at the specified parametric points
  560 + defined by the m_domain_min and m_domain_max parameter values.*/
  561 +
  562 + //if the parameter is outside the range, return the boundary value
  563 + if(i<m_domain_min.x || j<m_domain_min.y || k<m_domain_min.z ||
  564 + i>m_domain_max.x || j>m_domain_max.y || k>m_domain_max.z)
  565 + return m_boundary;
  566 +
  567 + point3D<double> index = getFractionalIndex(i, j, k);
  568 +
  569 + //cout<<index.x<<","<<index.y<<","<<index.z<<endl;
  570 +
  571 + //interpolate the values
  572 + int f_x = (int)floor(index.x); //calculate floor and ceiling values
  573 + int f_y = (int)floor(index.y);
  574 + int f_z = (int)floor(index.z);
  575 + int c_x = (int)ceil(index.x);
  576 + int c_y = (int)ceil(index.y);
  577 + int c_z = (int)ceil(index.z);
  578 +
  579 + double x_d = index.x - f_x; //find the point within the voxel
  580 + double y_d = index.y - f_y;
  581 + double z_d = index.z - f_z;
  582 +
  583 + T i_1 = xyz(f_x, f_y, f_z)*(1.0 - z_d) + xyz(f_x, f_y, c_z)*(z_d); //interpolate along z
  584 + T i_2 = xyz(f_x, c_y, f_z)*(1.0 - z_d) + xyz(f_x, c_y, c_z)*(z_d);
  585 + T j_1 = xyz(c_x, f_y, f_z)*(1.0 - z_d) + xyz(c_x, f_y, c_z)*(z_d);
  586 + T j_2 = xyz(c_x, c_y, f_z)*(1.0 - z_d) + xyz(c_x, c_y, c_z)*(z_d);
  587 +
  588 + T w_1 = i_1*(1.0 - y_d) + i_2*(y_d);
  589 + T w_2 = j_1*(1.0 - y_d) + j_2*(y_d);
  590 +
  591 + return w_1*(1.0 - x_d) + w_2*(x_d);
  592 +}
  593 +
  594 +
  595 +template <class T>
  596 +void rtsFunction3D<T>::Parameterize(double x_min, double x_max, double y_min, double y_max, double z_min, double z_max)
  597 +{
  598 + m_domain_min = point3D<double>(x_min, y_min, z_min);
  599 + m_domain_max = point3D<double>(x_max, y_max, z_max);
  600 + m_voxel_size = m_domain_max - m_domain_min;
  601 + m_voxel_size.x /= m_resolution.x;
  602 + m_voxel_size.y /= m_resolution.y;
  603 + m_voxel_size.z /= m_resolution.z;
  604 +}
  605 +
  606 +template <class T>
  607 +inline point3D<double> rtsFunction3D<T>::getParameter(indextype x, indextype y, indextype z)
  608 +{
  609 + //get the value between 0 and 1
  610 + point3D<double> normalized((double)x / (double)(m_resolution.x) + (1.0/(m_resolution.x*2.0)),
  611 + (double)y / (double)(m_resolution.y) + (1.0/(m_resolution.y*2.0)),
  612 + (double)z/(double)(m_resolution.z) + (1.0/(m_resolution.z*2.0)));
  613 +
  614 + point3D<double> result(normalized.x * (m_domain_max.x - m_domain_min.x) + m_domain_min.x,
  615 + normalized.y * (m_domain_max.y - m_domain_min.y) + m_domain_min.y,
  616 + normalized.z * (m_domain_max.z - m_domain_min.z) + m_domain_min.z);
  617 +
  618 + return result;
  619 +}
  620 +
  621 +template <class T>
  622 +inline point3D<indextype> rtsFunction3D<T>::getNearestIndex(double i, double j, double k)
  623 +{
  624 + //this function returns the index of the voxel containing the specified parameter point
  625 + point3D<double> normalized((i - m_domain_min.x)/(m_domain_max.x-m_domain_min.x),
  626 + (j - m_domain_min.y)/(m_domain_max.y-m_domain_min.y),
  627 + (k - m_domain_min.z)/(m_domain_max.z-m_domain_min.z));
  628 +
  629 + point3D<indextype> result((normalized.x - (1.0/(m_resolution.x*2.0)))*(double)m_resolution.x+0.5,
  630 + (normalized.y - (1.0/(m_resolution.y*2.0)))*(double)m_resolution.y+0.5,
  631 + (normalized.z - (1.0/(m_resolution.z*2.0)))*(double)m_resolution.z+0.5);
  632 +
  633 + return result;
  634 +}
  635 +
  636 +template <class T>
  637 +inline point3D<double> rtsFunction3D<T>::getFractionalIndex(double i, double j, double k)
  638 +{
  639 + //this function returns the index of the voxel containing the specified parameter point
  640 + point3D<double> normalized((i - m_domain_min.x)/(m_domain_max.x-m_domain_min.x),
  641 + (j - m_domain_min.y)/(m_domain_max.y-m_domain_min.y),
  642 + (k - m_domain_min.z)/(m_domain_max.z-m_domain_min.z));
  643 +
  644 + point3D<double> result((normalized.x - (1.0/(m_resolution.x*2.0)))*(double)m_resolution.x,
  645 + (normalized.y - (1.0/(m_resolution.y*2.0)))*(double)m_resolution.y,
  646 + (normalized.z - (1.0/(m_resolution.z*2.0)))*(double)m_resolution.z);
  647 + return result;
  648 +}
  649 +
  650 +
  651 +template <class T>
  652 +T* rtsFunction3D<T>::GetBits()
  653 +{
  654 + /*Returns bit data in lexocographical order (possibly for 3D texture mapping)*/
  655 + return m_data;
  656 +}
  657 +
  658 +template <class T>
  659 +rtsFunction3D<T>* rtsFunction3D<T>::Resample(indextype newres_x, indextype newres_y, indextype newres_z)
  660 +{
  661 + /*This function resamples the current function at the specified resolution.
  662 + No convolution is done for reducing he resolution.
  663 + */
  664 +
  665 + rtsFunction3D<T>* result = new rtsFunction3D<T>(vector3D<indextype>(newres_x, newres_y, newres_z),
  666 + m_boundary, m_domain_min, m_domain_max);
  667 +
  668 + //run through the entire resolution of the new function, sampling the current function
  669 + int x, y, z;
  670 + point3D<double> parametric;
  671 + for(x = 0; x<newres_x; x++)
  672 + for(y=0; y<newres_y; y++)
  673 + for(z=0; z<newres_z; z++)
  674 + {
  675 + //compute the parametric point for the sample point
  676 + parametric = result->getParameter(x, y, z);
  677 + (*result)(x, y, z) = ijk(parametric.x, parametric.y, parametric.z);
  678 + }
  679 +
  680 + return result;
  681 +}
  682 +
  683 +template <class T>
  684 +void rtsFunction3D<T>::Scale(T new_min, T new_max)
  685 +{
  686 + /*This function scales all values of the implicit function to within a specified range
  687 + */
  688 +
  689 + //find the minimum and maximum values in this function
  690 + indextype data_size = m_resolution.x * m_resolution.y * m_resolution.z;
  691 + T min = m_data[0];
  692 + T max = m_data[0];
  693 + for(indextype i=0; i<data_size; i++)
  694 + {
  695 + if(m_data[i] < min)
  696 + min = m_data[i];
  697 + if(m_data[i] > max)
  698 + max = m_data[i];
  699 + }
  700 +
  701 + //scale all values to the specified range
  702 + T current_range = max - min;
  703 + T new_range = new_max - new_min;
  704 + for(indextype i=0; i<data_size; i++)
  705 + m_data[i] = ((m_data[i] - min)/current_range)*(new_range) + new_min;
  706 +}
  707 +
  708 +template <class T>
  709 +void rtsFunction3D<T>::Crop(indextype x, indextype y, indextype z,
  710 + indextype size_x, indextype size_y, indextype size_z)
  711 +{
  712 + /*This function crops the implicit function at the specified nodes
  713 + */
  714 + //create a pointer for the new data
  715 + T* new_data = new T[size_x*size_y*size_z];
  716 +
  717 + //blit from the old data to the new data
  718 + blit3D(m_data,
  719 + x, y, z,
  720 + m_resolution.x, m_resolution.y, m_resolution.z,
  721 + new_data,
  722 + 0, 0, 0,
  723 + size_x, size_y, size_z,
  724 + size_x, size_y, size_z);
  725 +
  726 + //change the shallow variables
  727 + vector3D<indextype> new_resolution = vector3D<indextype>(size_x, size_y, size_z);
  728 + vector3D<double> voxel_size = getParameter(0,0,0) - getParameter(1,1,1);
  729 + point3D<double> new_domain_min = getParameter(x, y, z) - 0.5*voxel_size;
  730 + point3D<double> new_domain_max = getParameter(size_x-1, size_y - 1, size_z-1) + 0.5*voxel_size;
  731 + //copy new shallow variables
  732 + m_resolution = new_resolution;
  733 + m_domain_min = new_domain_min;
  734 + m_domain_max = new_domain_max;
  735 +
  736 + //copy data
  737 + delete m_data;
  738 + m_data = new_data;
  739 +
  740 +}
  741 +
  742 +template <class T>
  743 +void rtsFunction3D<T>::Threshold(T min, T value)
  744 +{
  745 + /*This function sets all values between min and max to value.
  746 + */
  747 + int x, y, z;
  748 + T test_value;
  749 + for(x=0; x<m_resolution.x; x++)
  750 + for(y=0; y<m_resolution.y; y++)
  751 + for(z=0; z<m_resolution.z; z++)
  752 + {
  753 + test_value = xyz(x, y, z);
  754 + if(test_value >= min)
  755 + xyz(x, y, z) = value;
  756 + }
  757 +}
  758 +
  759 +template <class T>
  760 +void rtsFunction3D<T>::Threshold(T min, T max, T value)
  761 +{
  762 + /*This function sets all values between min and max to value.
  763 + */
  764 + int x, y, z;
  765 + T test_value;
  766 + for(x=0; x<m_resolution.x; x++)
  767 + for(y=0; y<m_resolution.y; y++)
  768 + for(z=0; z<m_resolution.z; z++)
  769 + {
  770 + test_value = xyz(x, y, z);
  771 + if(test_value >= min && test_value <= max)
  772 + xyz(x, y, z) = value;
  773 + }
  774 +}
  775 +
  776 +template <class T>
  777 +void rtsFunction3D<T>::Threshold(T min, T max, T inside, T outside)
  778 +{
  779 + /*This function sets all values between min and max to value.
  780 + */
  781 + int x, y, z;
  782 + T test_value;
  783 + for(x=0; x<m_resolution.x; x++)
  784 + for(y=0; y<m_resolution.y; y++)
  785 + for(z=0; z<m_resolution.z; z++)
  786 + {
  787 + test_value = xyz(x, y, z);
  788 + if(test_value >= min && test_value <= max)
  789 + xyz(x, y, z) = inside;
  790 + else
  791 + xyz(x, y, z) = outside;
  792 + }
  793 +}
  794 +
  795 +template <class T>
  796 +void rtsFunction3D<T>::Insert(rtsFunction3D<T>* source, indextype x, indextype y, indextype z)
  797 +{
  798 + blit3D(source->m_data, 0, 0, 0, source->m_resolution.x, source->m_resolution.y, source->m_resolution.z,
  799 + m_data, x, y, z, m_resolution.x, m_resolution.y, m_resolution.z,
  800 + source->m_resolution.x, source->m_resolution.y, source->m_resolution.z);
  801 +}
  802 +
  803 +
  804 +
  805 +
  806 +template <class T>
  807 +void rtsFunction3D<T>::Binary(T threshold, T true_value)
  808 +{
  809 + /**
  810 + This function converts an implicit function into a binary or characteristic function describing the solid represented by the level
  811 + set at isovalue "threshold". All values below threshold are set to zero while all values above threshold are set to the specified
  812 + "true_value". In order to use this function, the data type T must be able to be set to 0.
  813 + **/
  814 + int max_index = m_resolution.x * m_resolution.y * m_resolution.z; //find the size of the data array
  815 + int i;
  816 + for(i=0; i<max_index; i++)
  817 + if(m_data[i] >= threshold)
  818 + m_data[i] = true_value;
  819 + else
  820 + m_data[i] = 0;
  821 +}
  822 +
  823 +
  824 +
  825 +template <class T>
  826 +void rtsFunction3D<T>::ClampMax(T max)
  827 +{
  828 + int i;
  829 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  830 + for(i=0; i<elements; i++)
  831 + if(m_data[i] > max)
  832 + m_data[i] = max;
  833 +}
  834 +
  835 +template <class T>
  836 +void rtsFunction3D<T>::ClampMin(T min)
  837 +{
  838 + int i;
  839 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  840 + for(i=0; i<elements; i++)
  841 + if(m_data[i] < min)
  842 + m_data[i] = min;
  843 +}
  844 +
  845 +template <class T>
  846 +T rtsFunction3D<T>::getMin()
  847 +{
  848 + int i;
  849 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  850 + T current = m_data[0];
  851 + for(i=1; i<elements; i++)
  852 + if(m_data[i] < current)
  853 + current = m_data[i];
  854 + return current;
  855 +}
  856 +
  857 +template <class T>
  858 +T rtsFunction3D<T>::getMax()
  859 +{
  860 + int i;
  861 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  862 + T current = m_data[0];
  863 + for(i=1; i<elements; i++)
  864 + if(m_data[i] > current)
  865 + current = m_data[i];
  866 + return current;
  867 +}
  868 +
  869 +
  870 +template <class T>
  871 +void rtsFunction3D<T>::toConsole()
  872 +{
  873 + cout<<endl;
  874 + int x, y, z;
  875 + for(z=0; z<m_resolution.z; z++)
  876 + {
  877 + for(y=0; y<m_resolution.y; y++)
  878 + {
  879 + for(x=0; x<m_resolution.x; x++)
  880 + {
  881 + cout.width(7);
  882 + cout.precision(3);
  883 + cout<<(double)xyz(x, y, z);
  884 + }
  885 + cout<<endl;
  886 + }
  887 + cout<<"-----------------------------"<<endl;
  888 + }
  889 +
  890 +}
  891 +
  892 +template <class T>
  893 +rtsFunction3D<T> rtsFunction3D<T>::Project2D()
  894 +{
  895 + /**
  896 + This function projects the entire 3D function onto a 2D function along the z-axis.
  897 + **/
  898 + rtsFunction3D<T> result(m_resolution.x, m_resolution.y, 1);
  899 + result = 0;
  900 +
  901 + indextype x, y, z;
  902 + for(x = 0; x<m_resolution.x; x++)
  903 + for(y=0; y<m_resolution.y; y++)
  904 + for(z=0; z<m_resolution.z; z++)
  905 + {
  906 + if(result(x, y, 0) < xyz(x, y, z))
  907 + result(x, y, 0) = xyz(x, y, z);
  908 + }
  909 + return result;
  910 +}
  911 +
  912 +
  913 +#endif
0 914 \ No newline at end of file
... ...
rtsGUIConsole.h 0 → 100755
  1 +++ a/rtsGUIConsole.h
  1 +#ifndef __GUICON_H__
  2 +#define __GUICON_H__
  3 +
  4 +//void RedirectIOToConsole(int Xpos = 0, int Ypos = 0, int Width = 700, int Height = 400);
  5 +
  6 +#ifdef WIN32
  7 +#include <windows.h>
  8 +#include <stdio.h>
  9 +#include <fcntl.h>
  10 +#include <io.h>
  11 +#include <iostream>
  12 +#include <fstream>
  13 +
  14 +#ifndef _USE_OLD_IOSTREAMS
  15 +
  16 +using namespace std;
  17 +#endif
  18 +
  19 +// maximum mumber of lines the output console should have
  20 +
  21 +static const WORD MAX_CONSOLE_LINES = 500;
  22 +//#ifdef _DEBUG
  23 +
  24 +void RedirectIOToConsole(int Xpos = 0, int Ypos = 0, int Width = 700, int Height = 400)
  25 +{
  26 + int hConHandle;
  27 + long lStdHandle;
  28 + CONSOLE_SCREEN_BUFFER_INFO coninfo;
  29 + FILE *fp;
  30 + // allocate a console for this app
  31 + AllocConsole();
  32 + // set the screen buffer to be big enough to let us scroll text
  33 + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
  34 + coninfo.dwSize.Y = MAX_CONSOLE_LINES;
  35 + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
  36 + coninfo.dwSize);
  37 + // redirect unbuffered STDOUT to the console
  38 + lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
  39 + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  40 + fp = _fdopen( hConHandle, "w" );
  41 + *stdout = *fp;
  42 + setvbuf( stdout, NULL, _IONBF, 0 );
  43 + // redirect unbuffered STDIN to the console
  44 + lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
  45 + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  46 + fp = _fdopen( hConHandle, "r" );
  47 + *stdin = *fp;
  48 + setvbuf( stdin, NULL, _IONBF, 0 );
  49 +
  50 + // redirect unbuffered STDERR to the console
  51 + lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
  52 + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  53 + fp = _fdopen( hConHandle, "w" );
  54 + *stderr = *fp;
  55 + setvbuf( stderr, NULL, _IONBF, 0 );
  56 +
  57 + // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
  58 + // point to console as well
  59 + ios::sync_with_stdio();
  60 + //position
  61 + MoveWindow(GetConsoleWindow(), Xpos, Ypos, Width, Height, true);
  62 +}
  63 +
  64 +#else
  65 +void RedirectIOToConsole(int Xpos = 0, int Ypos = 0, int Width = 700, int Height = 400)
  66 +{
  67 +}
  68 +#endif
  69 +
  70 +#endif
  71 +
  72 +/* End of File */
0 73 \ No newline at end of file
... ...
rtsGraph.h 0 → 100755
  1 +++ a/rtsGraph.h
  1 +#ifndef RTS_GRAPH_H
  2 +#define RTS_GRAPH_H
  3 +
  4 +#include <list>
  5 +#include <algorithm>
  6 +
  7 +using namespace std;
  8 +
  9 +template<typename T>
  10 +class rtsGraph
  11 +{
  12 + unsigned int current_id;
  13 +public:
  14 + class rtsGraphNode;
  15 + typedef typename list<rtsGraphNode>::iterator rtsGraphNodePtr;
  16 +
  17 + class rtsGraphNode
  18 + {
  19 + public:
  20 + list<rtsGraphNodePtr> ConnectionList;
  21 + unsigned int ID;
  22 + T Data;
  23 + };
  24 +
  25 + list<rtsGraphNode> NodeList;
  26 +
  27 + rtsGraphNodePtr addNode(T data)
  28 + {
  29 + //Adds a node to the graph. This node is unconnected by default.
  30 +
  31 + //create the new node
  32 + rtsGraphNode new_node;
  33 + //set the data to the data provided
  34 + new_node.Data = data;
  35 + //set the id
  36 + new_node.ID = current_id++;
  37 +
  38 + //add the node to the node list
  39 + NodeList.push_back(new_node);
  40 + rtsGraphNodePtr result = NodeList.end();
  41 + result--;
  42 + return result;
  43 + }
  44 + bool cmpPtr(const rtsGraphNodePtr a, const rtsGraphNodePtr b)
  45 + {
  46 + return (*a).ID < (*b).ID;
  47 + }
  48 +
  49 + void addConnection(rtsGraphNodePtr n0, rtsGraphNodePtr n1)
  50 + {
  51 + //adds a connection between two nodes
  52 + //connect n0 to n1
  53 + (*n0).ConnectionList.push_back(n1);
  54 + (*n1).ConnectionList.push_back(n0);
  55 +
  56 + }
  57 +
  58 + void removeNode(rtsGraphNodePtr n)
  59 + {
  60 +
  61 + typename list<rtsGraphNodePtr>::iterator i;
  62 + typename list<rtsGraphNodePtr>::iterator j;
  63 + typename list<rtsGraphNodePtr>::iterator temp;
  64 + rtsGraphNodePtr m;
  65 + rtsGraphNodePtr k;
  66 + /*Remove all of the connections TO n*/
  67 +
  68 + //for each node m connected to n
  69 + for(i = (*n).ConnectionList.begin(); i != (*n).ConnectionList.end(); i++)
  70 + {
  71 + m = (*i);
  72 + //for each node k connected to m
  73 + j = (*m).ConnectionList.begin();
  74 + while(j != (*m).ConnectionList.end())
  75 + {
  76 + k = (*j);
  77 + //if k is the same as n, remove it
  78 + if(k == n)
  79 + {
  80 + temp = j;
  81 + j++;
  82 + (*m).ConnectionList.erase(temp);
  83 + }
  84 + else
  85 + j++;
  86 +
  87 + }
  88 + }
  89 +
  90 + /*Add all connections to neighboring nodes*/
  91 +
  92 + //for each node m connected to n
  93 + for(i = (*n).ConnectionList.begin(); i != (*n).ConnectionList.end(); i++)
  94 + {
  95 + m = (*i);
  96 + //for each node k connected to n
  97 + for(j = (*n).ConnectionList.begin(); j != (*n).ConnectionList.end(); j++)
  98 + {
  99 + k = (*j);
  100 + if(k != m)
  101 + (*m).ConnectionList.push_back(k);
  102 +
  103 + }
  104 + //(*m).ConnectionList.sort(&rtsGraph<T>::cmpPtr);
  105 + //sort((*m).ConnectionList.begin(), (*m).ConnectionList.end(), rtsGraph<T>::cmpPtr);
  106 + (*m).ConnectionList.unique();
  107 + }
  108 +
  109 +
  110 +
  111 +
  112 +
  113 +
  114 +
  115 + }
  116 +
  117 +
  118 + void PrintGraph()
  119 + {
  120 + rtsGraphNodePtr i;
  121 + typename list<rtsGraphNodePtr>::iterator c;
  122 + for(i = NodeList.begin(); i != NodeList.end(); i++)
  123 + {
  124 + cout<<(*i).Data<<": ";
  125 + for(c = (*i).ConnectionList.begin(); c != (*i).ConnectionList.end(); c++)
  126 + {
  127 + if(c != (*i).ConnectionList.begin())
  128 + cout<<"--";
  129 + cout<<(*(*c)).Data;
  130 + }
  131 + cout<<endl;
  132 +
  133 + }
  134 +
  135 + }
  136 +
  137 +
  138 +
  139 +
  140 +};
  141 +
  142 +#endif
0 143 \ No newline at end of file
... ...
rtsImage.h 0 → 100755
  1 +++ a/rtsImage.h
  1 +#include "rtsFunction3D.h"
  2 +#include "cimg/cimg.h"
  3 +#include <string>
  4 +#include <sstream>
  5 +#include <iomanip>
  6 +
  7 +using namespace std;
  8 +using namespace cimg_library;
  9 +
  10 +
  11 +///This file contains a series of functions useful for loading images into other structures. These function use the CImg header file.
  12 +
  13 +void rts_cimgLoadImage(rtsFunction3D<unsigned char>& result, const char* filename) ///<This function loads an image and store it in an Implicit3D object.
  14 +{
  15 + CImg<unsigned char> image(filename), visu(500,400,1,3,0);
  16 +
  17 + result = rtsFunction3D<unsigned char>(image.width, image.height, 1);
  18 + unsigned int x, y;
  19 + for(x=0; x<image.width; x++)
  20 + for(y=0; y<image.height; y++)
  21 + {
  22 + result(x, y, 0) = image(x, y);
  23 + }
  24 +}
  25 +
  26 +void rts_cimgSaveImage(rtsFunction3D<unsigned char>& result, int z, const char* filename)
  27 +{
  28 + CImg<unsigned char> image(result.DimX(), result.DimY());
  29 + unsigned int x, y;
  30 + for(x=0; x<image.width; x++)
  31 + for(y=0; y<image.height; y++)
  32 + image(x, y) = result(x, y, z);
  33 +
  34 + image.save(filename);
  35 +}
  36 +
  37 +void rts_cimgLoadImageSequence(rtsFunction3D<unsigned char>& result, const char* filename, unsigned int min, unsigned int max, unsigned int color = 0)
  38 +{
  39 + /**
  40 + This function loads a sequence of images into a 3D implicit function. The filename is passed using the '?' wild
  41 + card. The wild cards are then replaced with the given min through max values in order to construct the names
  42 + for the image files to be loaded. The files are then loaded and placed in sequential order along the z-axis
  43 + of the implicit function.
  44 + **/
  45 + string sequence_name = filename; //turn the filename into a string
  46 + unsigned int wild_card_begin = sequence_name.find_first_of('?'); //find the start and end indices of the wild card
  47 + unsigned int wild_card_end = sequence_name.find_last_of('?');
  48 +
  49 + unsigned int max_number_length = wild_card_end - wild_card_begin + 1; //find the maximum number of characters in the image number
  50 + unsigned int max_number = (unsigned int)pow((double)10, (double)max_number_length) - 1; //find the maximum possible number
  51 +
  52 + //make sure that the data is given correctly
  53 + if(max < min) return;
  54 + if(max > max_number) max = max_number;
  55 +
  56 + //create an array of file names
  57 + int num_images = max - min + 1; //compute the number of images
  58 + bool implicit_created = false;
  59 + for(int i=0; i<num_images; i++)
  60 + {
  61 + ostringstream format_stream; //create a stream for number formatting
  62 + format_stream.fill('0'); //the frame name will be right justified with proceeding zeroes
  63 + format_stream<<setw(max_number_length); //specify the length of the frame name (based on the wild cards)
  64 + format_stream<<i+min; //put the number in the stream, convert it to a string
  65 + string frame_name = format_stream.str();
  66 +
  67 + string file_name = sequence_name; //create the file name for the current frame
  68 + file_name.replace(wild_card_begin, max_number_length, frame_name);
  69 +
  70 + CImg<unsigned char> image(file_name.c_str()); //load the frame
  71 + if(implicit_created == false) //create the implicit function for the first frame
  72 + {
  73 + result = rtsFunction3D<unsigned char>(image.width, image.height, num_images);
  74 + implicit_created = true;
  75 + }
  76 +
  77 + //place the frame in the implicit function
  78 + unsigned int x, y;
  79 + for(x=0; x<image.width; x++)
  80 + for(y=0; y<image.height; y++)
  81 + result(x, y, i) = image(x, y, color);
  82 + }
  83 +}
  84 +
  85 +void rts_cimgSaveImageSequence(rtsFunction3D<unsigned char>& result, const char* filename)
  86 +{
  87 + string sequence_name = filename; //turn the filename into a string
  88 + unsigned int wild_card_begin = sequence_name.find_first_of('?'); //find the start and end indices of the wild card
  89 + unsigned int wild_card_end = sequence_name.find_last_of('?');
  90 +
  91 + unsigned int max_number_length = wild_card_end - wild_card_begin + 1; //find the maximum number of characters in the image number
  92 + unsigned int max_number = (unsigned int)pow((double)10, (double)max_number_length) - 1; //find the maximum possible number
  93 +
  94 + //make sure that the data is given correctly
  95 + unsigned int max = result.DimZ();
  96 + if(max > max_number) max = max_number;
  97 +
  98 + //save each individual file
  99 + int num_images = max; //compute the number of images
  100 + CImg<unsigned char> image(result.DimX(), result.DimY()); //create an image for saving
  101 + for(int i=0; i<num_images; i++) //determine the filename and save the image
  102 + {
  103 + ostringstream format_stream; //create a stream for number formatting
  104 + format_stream.fill('0'); //the frame name will be right justified with proceeding zeroes
  105 + format_stream<<setw(max_number_length); //specify the length of the frame name (based on the wild cards)
  106 + format_stream<<i; //put the number in the stream, convert it to a string
  107 + string frame_name = format_stream.str();
  108 +
  109 + string file_name = sequence_name; //create the file name for the current frame
  110 + file_name.replace(wild_card_begin, max_number_length, frame_name);
  111 +
  112 + //fill the image with the implicit data at the current z coordinate
  113 + unsigned int x, y;
  114 + for(x=0; x<image.width; x++)
  115 + for(y=0; y<image.height; y++)
  116 + image(x, y) = result(x, y, i);
  117 +
  118 + //save the file
  119 + image.save(file_name.c_str());
  120 + }
  121 +
  122 +}
  123 +
  124 +void rts_cimgDisplayFunction3D(rtsFunction3D<unsigned char> source, unsigned int z)
  125 +{
  126 + CImg<unsigned char> image(source.DimX(), source.DimY());
  127 +
  128 + int x, y;
  129 + for(x=0; x<image.width; x++)
  130 + for(y=0; y<image.height; y++)
  131 + image(x, y) = source(x, y, z);
  132 +
  133 + CImgDisplay main_disp(image,"loaded image");
  134 + while (!main_disp.is_closed)
  135 + main_disp.wait();
  136 +}
0 137 \ No newline at end of file
... ...
rtsImplicit3D.h 0 → 100755
  1 +++ a/rtsImplicit3D.h
  1 +#ifndef RTSIMPLICIT3D_H
  2 +#define RTSIMPLICIT3D_H
  3 +
  4 +#define DIST_MAX 255
  5 +
  6 +#include "rtsLinearAlgebra.h"
  7 +#include "rtsDTGrid3D.h"
  8 +#include <fstream>
  9 +#include <iostream>
  10 +#include <math.h>
  11 +#include <queue>
  12 +#include <algorithm>
  13 +using namespace std;
  14 +
  15 +typedef int indextype;
  16 +
  17 +///This class represents a 3D implicit function as a grid. It provides methods for accessing values, interpolation, and several utilities.
  18 +
  19 +template <class T> class rtsImplicit3D
  20 +{
  21 +private:
  22 + //pointer to store the data
  23 + T* m_data;
  24 + //resolution of the data (x, y, z) dimensional extents
  25 + vector3D<indextype> m_resolution;
  26 + T m_boundary; //boundary condition
  27 + point3D<double> m_domain_min; //min and max range values (used for parametric access)
  28 + point3D<double> m_domain_max;
  29 + vector3D<double> m_voxel_size;
  30 +
  31 + //bit-blit function copies 3D data quickly from source to dest
  32 + void blit3D(const T* source,
  33 + indextype s_px, indextype s_py, indextype s_pz,
  34 + indextype s_sx, indextype s_sy, indextype s_sz,
  35 + T* dest,
  36 + indextype d_px, indextype d_py, indextype d_pz,
  37 + indextype d_sx, indextype d_sy, indextype d_sz,
  38 + indextype blit_size_x, indextype blit_size_y, indextype blit_size_z);
  39 +
  40 + void shallow_copy(const rtsImplicit3D<T> source, rtsImplicit3D<T> &dest);
  41 + inline point3D<double> getParameter(indextype i);
  42 +
  43 + inline float isosurface_distance(point3D<double> p0, point3D<double> p1, T isovalue);
  44 + inline float manhattan_distance(rtsImplicit3D<float>* function, point3D<indextype> p, bool sdf = false);
  45 + void compute_distance_function_boundary(T isovalue, rtsImplicit3D<float>* &result, rtsImplicit3D<bool>* &mask, bool sdf = false);
  46 +
  47 +
  48 +public:
  49 + //construct an implicit function with a size of 1
  50 + rtsImplicit3D(); ///<Create an empty implicit function
  51 + //construct an implicit function of the specified resolution
  52 + rtsImplicit3D(indextype res_x, indextype res_y, indextype res_z); ///<Create an implicit function with the specified resolution
  53 + //construct an implicit function from sample data and a specified size
  54 + rtsImplicit3D(T* data, indextype res_x, indextype res_y, indextype res_z); ///<Create an implicit function from previous data at the specified resolution
  55 + //shallow-copy constructor, defines all shallow variables
  56 + rtsImplicit3D(vector3D<int> resolution, T boundary, point3D<double> min_domain, point3D<double> max_domain);
  57 + //full copy constructor, defines all variables
  58 + rtsImplicit3D(T* data, vector3D<int> resolution, T boundary, point3D<double> min_domain, point3D<double> max_domain);
  59 + rtsImplicit3D(const rtsImplicit3D<T> &original); //copy constructor
  60 + ~rtsImplicit3D(); //destructor
  61 +
  62 + //overloaded operators
  63 + rtsImplicit3D<T>& operator=(const rtsImplicit3D<T>& original); ///<Overloaded operator creates a copy of an implicit function
  64 + rtsImplicit3D<T>& operator=(const T constant); ///<Overloaded operator sets all points in an implicit function to the given constant value
  65 + inline T& operator()(indextype x, indextype y, indextype z); ///<Allows access to the sample point indexed by x, y, and z using the parenthesis operator
  66 + inline T operator()(double i, double j, double k); ///<Allows access to the implicit function (based on the domain boundaries) at the position (i, j, k). This class uses linear interpolation.
  67 + rtsImplicit3D<T>& operator*=(const T constant); ///<Multiplies the values at all sample points by a constant.
  68 + rtsImplicit3D<T>& operator+=(const T constant); ///<Adds a constant to the values at all sample points.
  69 + rtsImplicit3D<T>& operator-=(const T constant); ///<Subtracts a constant from the values at all sample points.
  70 + rtsImplicit3D<T>& operator/=(const T constant); ///<Divides all values by a constant.
  71 + const rtsImplicit3D<T> operator+(const T constant); ///<Adds a constant to an implicit function and returns a new function.
  72 + const rtsImplicit3D<T> operator-(const T constant); ///<Subtracts a constant from an implicit function and returns a new function.
  73 + const rtsImplicit3D<T> operator*(const T constant); ///<Multiplies an implicit function by a constant and returns a new function.
  74 + const rtsImplicit3D<T> operator/(const T constant); ///<Divides an implicit function by a constant and returns a new function.
  75 +
  76 + //casting operator
  77 + //template <class U> friend class rtsImplicit3D<U>;
  78 + template <class U> operator rtsImplicit3D<U>(); ///<Casts between data types.
  79 +
  80 + //friend classes for overloading "backwards" operations (like 3*function)
  81 + friend rtsImplicit3D<T> operator*(const T lhs, rtsImplicit3D<T> rhs){return rhs*lhs;} ///<Allows associative multiplication.
  82 + friend rtsImplicit3D<T> operator+(const T lhs, rtsImplicit3D<T> rhs){return rhs+lhs;} ///<Allows associative addition.
  83 + friend rtsImplicit3D<T> operator-(const T lhs, rtsImplicit3D<T> rhs) ///<Allows associative subtraction.
  84 + {
  85 + rtsImplicit3D<T> result;
  86 + rhs.shallow_copy(rhs, result); //make a copy of all of the shallow variables and allocate memory
  87 + indextype size = rhs.m_resolution.x * rhs.m_resolution.y * rhs.m_resolution.z;
  88 + //iterate and subtract
  89 + for(indextype i=0; i<size; i++)
  90 + result.m_data[i] = lhs - rhs.m_data[i];
  91 +
  92 + return result;
  93 + }
  94 + //friend rtsImplicit3D<T> operator/(const T lhs, rtsImplicit3D<T> rhs);
  95 +
  96 + //loading/saving data to disk
  97 + void LoadRAW(indextype header_size, indextype data_x, indextype data_y, indextype data_z, const char* filename); ///<Loads RAW data from a file with the specified header size and data size.
  98 + void SaveRAW(const char* filename); ///<Save the data as RAW data to disk.
  99 + void LoadVOL(const char* filename); ///<Load a VOL file from disk.
  100 + void SaveVOL(const char* filename); ///<Save a VOL file to disk.
  101 +
  102 + //data access methods
  103 + inline T& xyz(indextype x, indextype y, indextype z);
  104 + inline T ijk(double i, double j, double k);
  105 + void Parameterize(double x_min, double x_max, double y_min, double y_max, double z_min, double z_max);
  106 + void setBoundary(T boundary){m_boundary = boundary;}
  107 + T getBoundary(){return m_boundary;}
  108 + T* GetBits();
  109 + indextype DimX(){return m_resolution.x;}
  110 + indextype DimY(){return m_resolution.y;}
  111 + indextype DimZ(){return m_resolution.z;}
  112 + inline point3D<double> getParameter(indextype x, indextype y, indextype z);
  113 + inline point3D<indextype> getNearestIndex(double i, double j, double k);
  114 + inline point3D<double> getFractionalIndex(double i, double j, double k);
  115 + inline point3D<indextype> getNearestIndex(indextype i);
  116 + point3D<double> getMinDomain(){return m_domain_min;}
  117 + point3D<double> getMaxDomain(){return m_domain_max;}
  118 + vector<point3D<indextype>> getEdgeNodes(T isovalue, bool protrusions = true); ///<Returns a vector nodes lying on the edge of an implicit surface.
  119 + rtsImplicit3D<T> Project2D(); //<Projects the data along the z-axis using a maximum-intensity projection.
  120 + unsigned int BackgroundComponents6(indextype x, indextype y, indextype z, T threshold, int n=18); ///<Returns the number of background components 6-connected to the specified node.
  121 + unsigned int Neighbors6(indextype x, indextype y, indextype z, T threshold); //<Returns the number of 6-connected neighbors above threshold.
  122 +
  123 + //data input methods
  124 + void Insert(rtsDTGrid3D<T>* dt_grid, double factor, indextype x, indextype y, indextype z);
  125 + void Insert(rtsImplicit3D<T>* source, indextype x, indextype y, indextype z);
  126 +
  127 + //data massaging
  128 +
  129 + void Scale(T min, T max);
  130 + void Crop(indextype x, indextype y, indextype z, indextype size_x, indextype size_y, indextype size_z);
  131 + void Binary(T threshold, T true_value); ///<Turns the image into a binary image based on a threshold value T. All values below T are set to 0, all values above are set to true_value.
  132 + void Threshold(T min, T value);
  133 + void Threshold(T min, T max, T value);
  134 + void Threshold(T min, T max, T inside, T outside);
  135 + void Erode(T isovalue, T fill_value); ///<Erodes the image around the edges defined by an isovalue.
  136 + unsigned int Thin(T isovalue); ///<Finds the skeleton of the given isosurface using erosion.
  137 + bool TestTopology(T isovalue, unsigned int x, unsigned int y, unsigned int z); ///<Tests if the specified voxel is necessary to the topology of the specified isosurface.
  138 + int Neighbors26(indextype x, indextype y, indextype z, T isovalue); ///<Returns the number of neighbors above the given isovalue.
  139 + void FloodFill26(indextype x, indextype y, indextype z, T new_value); ///<Fills the connected component at (x, y, z) with the new value.
  140 + void FloodFill6(indextype x, indextype y, indextype z, T new_value); ///<Performs a 6-connected flood-fill operation starting at the specified node.
  141 + void MedianFilter(int dist_x, int dist_y, int dist_z, double factor = 0.5); ///<Performs a median filter on the data set.
  142 + void ClampMax(T max); ///<Clamps the function to the given maximum value.
  143 + void ClampMin(T min);
  144 + void ClampMin(T min, T value); ///<Sets all function values below min to value.
  145 +
  146 + //create new data
  147 + rtsImplicit3D<T>* Resample(indextype newres_x, indextype newres_y, indextype newres_z);
  148 + rtsImplicit3D<float>* Isodistance_Manhattan(T isovalue, bool sdf = false);
  149 + rtsImplicit3D<vector3D<T>>* Gradient();
  150 + rtsImplicit3D<float>* EstimateAmbient(T threshold);
  151 + rtsImplicit3D<float>* EstimateAttenuatedAmbient(T surface, T transparent, float attenuation);
  152 +
  153 + //implicit shapes
  154 + //(these functions create some basic implicit shapes just for fun)
  155 + void Sphere(double center_i, double center_j, double center_k, double radius, T in_value);
  156 +
  157 + //output functions
  158 + void toConsole();
  159 +
  160 +};
  161 +
  162 +template <class T>
  163 +void rtsImplicit3D<T>::blit3D(const T* source,
  164 + indextype s_px, indextype s_py, indextype s_pz,
  165 + indextype s_sx, indextype s_sy, indextype s_sz,
  166 + T* dest,
  167 + indextype d_px, indextype d_py, indextype d_pz,
  168 + indextype d_sx, indextype d_sy, indextype d_sz,
  169 + indextype blit_size_x, indextype blit_size_y, indextype blit_size_z)
  170 +{
  171 + indextype ps, pd; //stores the mapping for the source point to the dest point
  172 + //find the maximum points that can be blit to (in case source overlaps the edges of dest)
  173 + blit_size_x = min(blit_size_x, min(s_sx - s_px, d_sx - d_px));
  174 + blit_size_y = min(blit_size_y, min(s_sy - s_py, d_sy - d_py));
  175 + blit_size_z = min(blit_size_z, min(s_sz - s_pz, d_sz - d_pz));
  176 +
  177 + indextype source_z_offset = s_sx * s_sy;
  178 + indextype dest_z_offset = d_sx * d_sy;
  179 +
  180 + indextype z,y;
  181 + for(z=0; z<blit_size_z; z++)
  182 + for(y=0; y<blit_size_y; y++)
  183 + {
  184 + ps = (z + s_pz) * source_z_offset + (y + s_py) * s_sx + s_px;
  185 + pd = (z + d_pz) * dest_z_offset + (y + d_py) * d_sx + d_px;
  186 + memcpy((void*)(&dest[pd]), (void*)(&source[ps]), sizeof(T)*blit_size_x);
  187 + }
  188 +}
  189 +
  190 +template <class T>
  191 +void rtsImplicit3D<T>::shallow_copy(const rtsImplicit3D<T> source, rtsImplicit3D<T> &dest)
  192 +{
  193 + dest = rtsImplicit3D<T>(source.m_resolution.x, source.m_resolution.y, source.m_resolution.z);
  194 + dest.m_boundary = source.m_boundary;
  195 + dest.m_domain_max = source.m_domain_max;
  196 + dest.m_domain_min = source.m_domain_max;
  197 + dest.m_voxel_size = source.m_voxel_size;
  198 +}
  199 +
  200 +template <class T>
  201 +rtsImplicit3D<T>::rtsImplicit3D(vector3D<int> resolution, T boundary, point3D<double> domain_min, point3D<double> domain_max)
  202 +{
  203 + //This function creates an implicit function based on all of the shallow variables
  204 + m_resolution = resolution;
  205 + m_boundary = boundary;
  206 + m_domain_min = domain_min;
  207 + m_domain_max = domain_max;
  208 + m_voxel_size = domain_max - domain_min;
  209 + m_voxel_size.x /= m_resolution.x;
  210 + m_voxel_size.y /= m_resolution.y;
  211 + m_voxel_size.z /= m_resolution.z;
  212 +
  213 + //allocate the data
  214 + m_data = new T[m_resolution.x * m_resolution.y * m_resolution.z];
  215 +}
  216 +
  217 +template <class T>
  218 +rtsImplicit3D<T>::rtsImplicit3D(T* data, vector3D<int> resolution, T boundary, point3D<double> domain_min, point3D<double> domain_max)
  219 +{
  220 + //This function creates an implicit function based on ALL of the variables
  221 + m_resolution = resolution;
  222 + m_boundary = boundary;
  223 + m_domain_min = domain_min;
  224 + m_domain_max = domain_max;
  225 + m_voxel_size = domain_max - domain_min;
  226 + m_voxel_size.x /= m_resolution.x;
  227 + m_voxel_size.y /= m_resolution.y;
  228 + m_voxel_size.z /= m_resolution.z;
  229 +
  230 + //allocate the data
  231 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  232 + m_data = new T[size];
  233 + memcpy(m_data, data, sizeof(T)*size);
  234 + //for(int i=0; i<size; i++)
  235 + // m_data[i] = data[i];
  236 +}
  237 +
  238 +
  239 +
  240 +template <class T>
  241 +rtsImplicit3D<T>::rtsImplicit3D()
  242 +{
  243 + m_resolution.x = 1;
  244 + m_resolution.y = 1;
  245 + m_resolution.z = 1;
  246 + m_data = new T[1];
  247 + //m_boundary = 0; //initialize boundary condition
  248 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  249 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  250 + m_voxel_size = vector3D<double>(1.0, 1.0, 1.0);
  251 +}
  252 +
  253 +template <class T>
  254 +rtsImplicit3D<T>::rtsImplicit3D(indextype res_x, indextype res_y, indextype res_z)
  255 +{
  256 + m_resolution.x = res_x; //set resolution vector
  257 + m_resolution.y = res_y;
  258 + m_resolution.z = res_z;
  259 + m_data = new T[res_x*res_y*res_z]; //allocate data
  260 + memset(&m_boundary, 0, sizeof(T)); //initialize boundary condition
  261 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  262 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  263 +
  264 + m_voxel_size = m_domain_max - m_domain_min;
  265 + m_voxel_size.x /= m_resolution.x;
  266 + m_voxel_size.y /= m_resolution.y;
  267 + m_voxel_size.z /= m_resolution.z;
  268 +}
  269 +
  270 +template <class T>
  271 +rtsImplicit3D<T>::rtsImplicit3D(T* data, indextype res_x, indextype res_y, indextype res_z)
  272 +{
  273 + m_resolution.x = res_x; //set resolution vector
  274 + m_resolution.y = res_y;
  275 + m_resolution.z = res_z;
  276 + m_data = new T[res_x*res_y*res_z]; //allocate data
  277 + //copy the sample data into the data array
  278 + indextype size = res_x*res_y*res_z;
  279 + for(indextype i=0; i<size; i++)
  280 + m_data[i] = data[i];
  281 + m_boundary = 0; //initialize boundary condition
  282 + m_domain_min = point3D<double>(0.0, 0.0, 0.0); //set range parameters
  283 + m_domain_max = point3D<double>(1.0, 1.0, 1.0);
  284 +
  285 + m_voxel_size = domain_max - domain_min;
  286 + m_voxel_size.x /= m_resolution.x;
  287 + m_voxel_size.y /= m_resolution.y;
  288 + m_voxel_size.z /= m_resolution.z;
  289 +}
  290 +
  291 +template <class T>
  292 +rtsImplicit3D<T>::rtsImplicit3D(const rtsImplicit3D<T>& original)
  293 +{
  294 + //copy the shallow variables
  295 + m_resolution = original.m_resolution;
  296 + m_boundary = original.m_boundary;
  297 + m_domain_min = original.m_domain_min;
  298 + m_domain_max = original.m_domain_max;
  299 + m_voxel_size = original.m_voxel_size;
  300 +
  301 + //allocate space for the data
  302 + m_data = new T[m_resolution.x * m_resolution.y * m_resolution.z];
  303 + //copy the data
  304 + blit3D(original.m_data,
  305 + 0, 0, 0,
  306 + m_resolution.x, m_resolution.y, m_resolution.z,
  307 + m_data,
  308 + 0, 0, 0,
  309 + m_resolution.x, m_resolution.y, m_resolution.z,
  310 + m_resolution.x, m_resolution.y, m_resolution.z);
  311 +}
  312 +
  313 +template <class T>
  314 +rtsImplicit3D<T>::~rtsImplicit3D()
  315 +{
  316 + delete m_data;
  317 +}
  318 +
  319 +template <class T>
  320 +typename rtsImplicit3D<T>& rtsImplicit3D<T>::operator=(const T rhs)
  321 +{
  322 + indextype size = m_resolution.x*m_resolution.y*m_resolution.z;
  323 + for(int i=0; i<size; i++)
  324 + m_data[i] = rhs;
  325 +
  326 + return *this;
  327 +}
  328 +
  329 +template <class T>
  330 +typename rtsImplicit3D<T>& rtsImplicit3D<T>::operator=(const rtsImplicit3D<T>& rhs)
  331 +{
  332 + //check for self-assignment
  333 + if(this == &rhs)
  334 + return *this;
  335 +
  336 + //deallocate memory
  337 + if(m_data != NULL)
  338 + delete m_data;
  339 +
  340 + //copy the shallow variables
  341 + m_resolution = rhs.m_resolution;
  342 + m_boundary = rhs.m_boundary;
  343 + m_domain_min = rhs.m_domain_min;
  344 + m_domain_max = rhs.m_domain_max;
  345 + m_voxel_size = rhs.m_voxel_size;
  346 +
  347 + //allocate and copy memory
  348 + m_data = new T[m_resolution.x * m_resolution.y * m_resolution.z];
  349 + //copy the data
  350 + blit3D(rhs.m_data,
  351 + 0,0,0,
  352 + m_resolution.x, m_resolution.y, m_resolution.z,
  353 + m_data,
  354 + 0, 0, 0,
  355 + m_resolution.x, m_resolution.y, m_resolution.z,
  356 + m_resolution.x, m_resolution.y, m_resolution.z);
  357 +
  358 + //return the left hand side
  359 + return *this;
  360 +}
  361 +
  362 +template <class T>
  363 +inline T& rtsImplicit3D<T>::operator ()(indextype x, indextype y, indextype z)
  364 +{
  365 + return xyz(x, y, z);
  366 +}
  367 +
  368 +template <class T>
  369 +inline T rtsImplicit3D<T>::operator()(double i, double j, double k)
  370 +{
  371 + return ijk(i, j, k);
  372 +}
  373 +
  374 +template <class T>
  375 +rtsImplicit3D<T>& rtsImplicit3D<T>::operator *=(const T constant)
  376 +{
  377 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  378 + for(indextype i = 0; i<size; i++)
  379 + m_data[i] *= constant;
  380 +
  381 + return *this;
  382 +}
  383 +
  384 +template <class T>
  385 +rtsImplicit3D<T>& rtsImplicit3D<T>::operator +=(const T constant)
  386 +{
  387 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  388 + for(indextype i = 0; i<size; i++)
  389 + m_data[i] += constant;
  390 +
  391 + return *this;
  392 +}
  393 +template <class T>
  394 +rtsImplicit3D<T>& rtsImplicit3D<T>::operator -=(const T constant)
  395 +{
  396 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  397 + for(indextype i = 0; i<size; i++)
  398 + m_data[i] -= constant;
  399 +
  400 + return *this;
  401 +}
  402 +template <class T>
  403 +rtsImplicit3D<T>& rtsImplicit3D<T>::operator /=(const T constant)
  404 +{
  405 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  406 + for(indextype i = 0; i<size; i++)
  407 + m_data[i] /= constant;
  408 +
  409 + return *this;
  410 +}
  411 +template <class T>
  412 +const rtsImplicit3D<T> rtsImplicit3D<T>::operator *(const T constant)
  413 +{
  414 + rtsImplicit3D<T> result = (*this);
  415 + result *= constant;
  416 +
  417 + return result;
  418 +}
  419 +
  420 +template <class T>
  421 +const rtsImplicit3D<T> rtsImplicit3D<T>::operator +(const T constant)
  422 +{
  423 + rtsImplicit3D<T> result = (*this);
  424 + result += constant;
  425 +
  426 + return result;
  427 +}
  428 +
  429 +template <class T>
  430 +const rtsImplicit3D<T> rtsImplicit3D<T>::operator -(const T constant)
  431 +{
  432 + rtsImplicit3D<T> result = (*this);
  433 + result -= constant;
  434 +
  435 + return result;
  436 +}
  437 +
  438 +template <class T>
  439 +const rtsImplicit3D<T> rtsImplicit3D<T>::operator /(const T constant)
  440 +{
  441 + rtsImplicit3D<T> result = (*this);
  442 + result /= constant;
  443 +
  444 + return result;
  445 +}
  446 +
  447 +template <class T>
  448 +template <class U>
  449 +rtsImplicit3D<T>::operator rtsImplicit3D<U>()
  450 +{
  451 + //cast one type to another
  452 + //create the data pointer from the current function
  453 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  454 + U* new_data = new U[size];
  455 + for(int i=0; i<size; i++)
  456 + new_data[i] = m_data[i];
  457 + rtsImplicit3D<U> cast_result(new_data, m_resolution, m_boundary, m_domain_min, m_domain_max);
  458 +
  459 + return cast_result;
  460 +}
  461 +
  462 +template <class T>
  463 +inline T& rtsImplicit3D<T>::xyz(indextype x, indextype y, indextype z)
  464 +{
  465 + if(x<0 || y<0 || z<0 || x>=m_resolution.x || y>=m_resolution.y || z>=m_resolution.z)
  466 + return m_boundary;
  467 + //return m_data[(z * m_resolution.x * m_resolution.y) + (y * m_resolution.x) + x];
  468 + return m_data[x + m_resolution.x * (y + z * m_resolution.y)];
  469 +
  470 +}
  471 +
  472 +template <class T>
  473 +inline point3D<indextype> rtsImplicit3D<T>::getNearestIndex(indextype i)
  474 +{
  475 + point3D<indextype> result;
  476 + result.z = i/(m_resolution.x*m_resolution.y);
  477 + indextype mod = i%(m_resolution.x*m_resolution.y);
  478 + result.y = mod/m_resolution.x;
  479 + result.x = mod%m_resolution.x;
  480 +
  481 + return result;
  482 +
  483 +}
  484 +
  485 +template <class T>
  486 +void rtsImplicit3D<T>::LoadRAW(indextype header_size, indextype size_x,
  487 + indextype size_y, indextype size_z, const char *filename)
  488 +{
  489 + //set the data size
  490 + m_resolution = vector3D<indextype>(size_x, size_y, size_z);
  491 + //delete any previous data
  492 + if(m_data != NULL)
  493 + delete m_data;
  494 +
  495 + ifstream infile(filename, ios::in | ios::binary);
  496 +
  497 + //load the header
  498 + unsigned char* header = new unsigned char[header_size];
  499 + infile.read((char*)header, header_size);
  500 +
  501 + //load the actual data
  502 + indextype size = m_resolution.x * m_resolution.y * m_resolution.z;
  503 + m_data = new T[size];
  504 + infile.read((char*)m_data, size*sizeof(T));
  505 +
  506 + //calculate min and maxes
  507 + infile.close();
  508 +}
  509 +
  510 +template <class T>
  511 +void rtsImplicit3D<T>::LoadVOL(const char *filename)
  512 +{
  513 + ifstream infile(filename, ios::in | ios::binary); //create the files stream
  514 + if(!infile)
  515 + return;
  516 +
  517 + indextype size_x, size_y, size_z; //create variables to store the size of the data set
  518 + //load the dimensions of the data set
  519 + infile.read((char*)&size_x, sizeof(int)); //load the file header
  520 + infile.read((char*)&size_y, sizeof(int));
  521 + infile.read((char*)&size_z, sizeof(int));
  522 +
  523 + //close the file
  524 + infile.close();
  525 + //load the raw data
  526 + LoadRAW(12, size_x, size_y, size_z, filename);
  527 +}
  528 +
  529 +template <class T>
  530 +void rtsImplicit3D<T>::SaveVOL(const char *filename)
  531 +{
  532 + ofstream outfile(filename, ios::out | ios::binary); //create the binary file stream
  533 +
  534 + //write the volume size to the file
  535 + vector3D<int> vol_size = m_resolution;
  536 + outfile.write((char*)&vol_size.x, sizeof(int));
  537 + outfile.write((char*)&vol_size.y, sizeof(int));
  538 + outfile.write((char*)&vol_size.z, sizeof(int));
  539 +
  540 + outfile.write((char*)m_data, sizeof(char)*vol_size.x*vol_size.y*vol_size.z);
  541 +}
  542 +
  543 +template <class T>
  544 +void rtsImplicit3D<T>::SaveRAW(const char *filename)
  545 +{
  546 + ofstream outfile(filename, ios::out | ios::binary); //create the binary file stream
  547 +
  548 + //write the volume data
  549 + outfile.write((char*)m_data, sizeof(T)*m_resolution.x*m_resolution.y*m_resolution.z);
  550 +}
  551 +
  552 +template <class T>
  553 +inline T rtsImplicit3D<T>::ijk(double i, double j, double k)
  554 +{
  555 + /*This function determines the value at the specified parametric points
  556 + defined by the m_domain_min and m_domain_max parameter values.*/
  557 +
  558 + //if the parameter is outside the range, return the boundary value
  559 + if(i<m_domain_min.x || j<m_domain_min.y || k<m_domain_min.z ||
  560 + i>m_domain_max.x || j>m_domain_max.y || k>m_domain_max.z)
  561 + return m_boundary;
  562 +
  563 + point3D<double> index = getFractionalIndex(i, j, k);
  564 +
  565 + //cout<<index.x<<","<<index.y<<","<<index.z<<endl;
  566 +
  567 + //interpolate the values
  568 + int f_x = (int)floor(index.x); //calculate floor and ceiling values
  569 + int f_y = (int)floor(index.y);
  570 + int f_z = (int)floor(index.z);
  571 + int c_x = (int)ceil(index.x);
  572 + int c_y = (int)ceil(index.y);
  573 + int c_z = (int)ceil(index.z);
  574 +
  575 + double x_d = index.x - f_x; //find the point within the voxel
  576 + double y_d = index.y - f_y;
  577 + double z_d = index.z - f_z;
  578 +
  579 + T i_1 = xyz(f_x, f_y, f_z)*(1.0 - z_d) + xyz(f_x, f_y, c_z)*(z_d); //interpolate along z
  580 + T i_2 = xyz(f_x, c_y, f_z)*(1.0 - z_d) + xyz(f_x, c_y, c_z)*(z_d);
  581 + T j_1 = xyz(c_x, f_y, f_z)*(1.0 - z_d) + xyz(c_x, f_y, c_z)*(z_d);
  582 + T j_2 = xyz(c_x, c_y, f_z)*(1.0 - z_d) + xyz(c_x, c_y, c_z)*(z_d);
  583 +
  584 + T w_1 = i_1*(1.0 - y_d) + i_2*(y_d);
  585 + T w_2 = j_1*(1.0 - y_d) + j_2*(y_d);
  586 +
  587 + return w_1*(1.0 - x_d) + w_2*(x_d);
  588 +}
  589 +
  590 +
  591 +template <class T>
  592 +void rtsImplicit3D<T>::Parameterize(double x_min, double x_max, double y_min, double y_max, double z_min, double z_max)
  593 +{
  594 + m_domain_min = point3D<double>(x_min, y_min, z_min);
  595 + m_domain_max = point3D<double>(x_max, y_max, z_max);
  596 + m_voxel_size = m_domain_max - m_domain_min;
  597 + m_voxel_size.x /= m_resolution.x;
  598 + m_voxel_size.y /= m_resolution.y;
  599 + m_voxel_size.z /= m_resolution.z;
  600 +}
  601 +
  602 +template <class T>
  603 +inline point3D<double> rtsImplicit3D<T>::getParameter(indextype x, indextype y, indextype z)
  604 +{
  605 + //get the value between 0 and 1
  606 + point3D<double> normalized((double)x / (double)(m_resolution.x) + (1.0/(m_resolution.x*2.0)),
  607 + (double)y / (double)(m_resolution.y) + (1.0/(m_resolution.y*2.0)),
  608 + (double)z/(double)(m_resolution.z) + (1.0/(m_resolution.z*2.0)));
  609 +
  610 + point3D<double> result(normalized.x * (m_domain_max.x - m_domain_min.x) + m_domain_min.x,
  611 + normalized.y * (m_domain_max.y - m_domain_min.y) + m_domain_min.y,
  612 + normalized.z * (m_domain_max.z - m_domain_min.z) + m_domain_min.z);
  613 +
  614 + return result;
  615 +}
  616 +
  617 +template <class T>
  618 +inline point3D<indextype> rtsImplicit3D<T>::getNearestIndex(double i, double j, double k)
  619 +{
  620 + //this function returns the index of the voxel containing the specified parameter point
  621 + point3D<double> normalized((i - m_domain_min.x)/(m_domain_max.x-m_domain_min.x),
  622 + (j - m_domain_min.y)/(m_domain_max.y-m_domain_min.y),
  623 + (k - m_domain_min.z)/(m_domain_max.z-m_domain_min.z));
  624 +
  625 + point3D<indextype> result((normalized.x - (1.0/(m_resolution.x*2.0)))*(double)m_resolution.x+0.5,
  626 + (normalized.y - (1.0/(m_resolution.y*2.0)))*(double)m_resolution.y+0.5,
  627 + (normalized.z - (1.0/(m_resolution.z*2.0)))*(double)m_resolution.z+0.5);
  628 +
  629 + return result;
  630 +}
  631 +
  632 +template <class T>
  633 +inline point3D<double> rtsImplicit3D<T>::getFractionalIndex(double i, double j, double k)
  634 +{
  635 + //this function returns the index of the voxel containing the specified parameter point
  636 + point3D<double> normalized((i - m_domain_min.x)/(m_domain_max.x-m_domain_min.x),
  637 + (j - m_domain_min.y)/(m_domain_max.y-m_domain_min.y),
  638 + (k - m_domain_min.z)/(m_domain_max.z-m_domain_min.z));
  639 +
  640 + point3D<double> result((normalized.x - (1.0/(m_resolution.x*2.0)))*(double)m_resolution.x,
  641 + (normalized.y - (1.0/(m_resolution.y*2.0)))*(double)m_resolution.y,
  642 + (normalized.z - (1.0/(m_resolution.z*2.0)))*(double)m_resolution.z);
  643 + return result;
  644 +}
  645 +
  646 +
  647 +template <class T>
  648 +T* rtsImplicit3D<T>::GetBits()
  649 +{
  650 + /*Returns bit data in lexocographical order (possibly for 3D texture mapping)*/
  651 + return m_data;
  652 +}
  653 +
  654 +template <class T>
  655 +rtsImplicit3D<T>* rtsImplicit3D<T>::Resample(indextype newres_x, indextype newres_y, indextype newres_z)
  656 +{
  657 + /*This function resamples the current function at the specified resolution.
  658 + No convolution is done for reducing he resolution.
  659 + */
  660 +
  661 + rtsImplicit3D<T>* result = new rtsImplicit3D<T>(vector3D<indextype>(newres_x, newres_y, newres_z),
  662 + m_boundary, m_domain_min, m_domain_max);
  663 +
  664 + //run through the entire resolution of the new function, sampling the current function
  665 + int x, y, z;
  666 + point3D<double> parametric;
  667 + for(x = 0; x<newres_x; x++)
  668 + for(y=0; y<newres_y; y++)
  669 + for(z=0; z<newres_z; z++)
  670 + {
  671 + //compute the parametric point for the sample point
  672 + parametric = result->getParameter(x, y, z);
  673 + (*result)(x, y, z) = ijk(parametric.x, parametric.y, parametric.z);
  674 + }
  675 +
  676 + return result;
  677 +}
  678 +
  679 +template <class T>
  680 +void rtsImplicit3D<T>::Scale(T new_min, T new_max)
  681 +{
  682 + /*This function scales all values of the implicit function to within a specified range
  683 + */
  684 +
  685 + //find the minimum and maximum values in this function
  686 + indextype data_size = m_resolution.x * m_resolution.y * m_resolution.z;
  687 + T min = m_data[0];
  688 + T max = m_data[0];
  689 + for(indextype i=0; i<data_size; i++)
  690 + {
  691 + if(m_data[i] < min)
  692 + min = m_data[i];
  693 + if(m_data[i] > max)
  694 + max = m_data[i];
  695 + }
  696 +
  697 + //scale all values to the specified range
  698 + T current_range = max - min;
  699 + T new_range = new_max - new_min;
  700 + for(indextype i=0; i<data_size; i++)
  701 + m_data[i] = ((m_data[i] - min)/current_range)*(new_range) + new_min;
  702 +}
  703 +
  704 +template <class T>
  705 +void rtsImplicit3D<T>::Crop(indextype x, indextype y, indextype z,
  706 + indextype size_x, indextype size_y, indextype size_z)
  707 +{
  708 + /*This function crops the implicit function at the specified nodes
  709 + */
  710 + //create a pointer for the new data
  711 + T* new_data = new T[size_x*size_y*size_z];
  712 +
  713 + //blit from the old data to the new data
  714 + blit3D(m_data,
  715 + x, y, z,
  716 + m_resolution.x, m_resolution.y, m_resolution.z,
  717 + new_data,
  718 + 0, 0, 0,
  719 + size_x, size_y, size_z,
  720 + size_x, size_y, size_z);
  721 +
  722 + //change the shallow variables
  723 + vector3D<indextype> new_resolution = vector3D<indextype>(size_x, size_y, size_z);
  724 + vector3D<double> voxel_size = getParameter(0,0,0) - getParameter(1,1,1);
  725 + point3D<double> new_domain_min = getParameter(x, y, z) - 0.5*voxel_size;
  726 + point3D<double> new_domain_max = getParameter(size_x-1, size_y - 1, size_z-1) + 0.5*voxel_size;
  727 + //copy new shallow variables
  728 + m_resolution = new_resolution;
  729 + m_domain_min = new_domain_min;
  730 + m_domain_max = new_domain_max;
  731 +
  732 + //copy data
  733 + delete m_data;
  734 + m_data = new_data;
  735 +
  736 +}
  737 +
  738 +template <class T>
  739 +void rtsImplicit3D<T>::Threshold(T min, T value)
  740 +{
  741 + /*This function sets all values between min and max to value.
  742 + */
  743 + int x, y, z;
  744 + T test_value;
  745 + for(x=0; x<m_resolution.x; x++)
  746 + for(y=0; y<m_resolution.y; y++)
  747 + for(z=0; z<m_resolution.z; z++)
  748 + {
  749 + test_value = xyz(x, y, z);
  750 + if(test_value >= min)
  751 + xyz(x, y, z) = value;
  752 + }
  753 +}
  754 +
  755 +template <class T>
  756 +void rtsImplicit3D<T>::Threshold(T min, T max, T value)
  757 +{
  758 + /*This function sets all values between min and max to value.
  759 + */
  760 + int x, y, z;
  761 + T test_value;
  762 + for(x=0; x<m_resolution.x; x++)
  763 + for(y=0; y<m_resolution.y; y++)
  764 + for(z=0; z<m_resolution.z; z++)
  765 + {
  766 + test_value = xyz(x, y, z);
  767 + if(test_value >= min && test_value <= max)
  768 + xyz(x, y, z) = value;
  769 + }
  770 +}
  771 +
  772 +template <class T>
  773 +void rtsImplicit3D<T>::Threshold(T min, T max, T inside, T outside)
  774 +{
  775 + /*This function sets all values between min and max to value.
  776 + */
  777 + int x, y, z;
  778 + T test_value;
  779 + for(x=0; x<m_resolution.x; x++)
  780 + for(y=0; y<m_resolution.y; y++)
  781 + for(z=0; z<m_resolution.z; z++)
  782 + {
  783 + test_value = xyz(x, y, z);
  784 + if(test_value >= min && test_value <= max)
  785 + xyz(x, y, z) = inside;
  786 + else
  787 + xyz(x, y, z) = outside;
  788 + }
  789 +}
  790 +
  791 +template <class T>
  792 +void rtsImplicit3D<T>::Insert(rtsDTGrid3D<T>* dt_grid, double factor, indextype pos_x, indextype pos_y, indextype pos_z)
  793 +{
  794 +/* This function copies a 3D DT-Grid into the implicit function at the specified position.
  795 +*/
  796 + rtsDTGrid3D<T>::iterator i;
  797 + indextype x, y, z;
  798 + for(i=dt_grid->begin(); i != dt_grid->end(); i.increment()) //for each node in the grid
  799 + {
  800 + x = pos_x + i.getX();
  801 + y = pos_y + i.getY();
  802 + z = pos_z + i.getZ();
  803 + if(x >= 0 || x < m_resolution.x ||
  804 + y >= 0 || y < m_resolution.y ||
  805 + y >= 0 || y < m_resolution.z)
  806 + xyz(x, y, z) = max(i.value* factor, (double)xyz(x, y, z));
  807 + }
  808 +}
  809 +
  810 +template <class T>
  811 +void rtsImplicit3D<T>::Insert(rtsImplicit3D<T>* source, indextype x, indextype y, indextype z)
  812 +{
  813 + blit3D(source->m_data, 0, 0, 0, source->m_resolution.x, source->m_resolution.y, source->m_resolution.z,
  814 + m_data, x, y, z, m_resolution.x, m_resolution.y, m_resolution.z,
  815 + source->m_resolution.x, source->m_resolution.y, source->m_resolution.z);
  816 +}
  817 +
  818 +
  819 +template <class T>
  820 +inline float rtsImplicit3D<T>::manhattan_distance(rtsImplicit3D<float>* function, point3D<indextype> point, bool sdf)
  821 +{
  822 + /*This function updates the manhattan distance from a surface using the manhattan
  823 + distance of its neighboring points.
  824 + */
  825 + indextype x, y, z;
  826 + x=point.x; y=point.y, z=point.z;
  827 + int sign = 1;
  828 + float result = DIST_MAX;
  829 + float near_value; //the value of the neighbor being considered
  830 + float possible_value;
  831 + if(x!=0)
  832 + {
  833 + near_value = (*function)(x-1, y, z);
  834 + if(!sdf)
  835 + result = min(result, near_value + (float)m_voxel_size.x);
  836 + else
  837 + {
  838 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  839 + possible_value = sign*(fabs(near_value) + m_voxel_size.x);
  840 + if(fabs(possible_value) < fabs(result))
  841 + result = possible_value;
  842 + }
  843 +
  844 + }
  845 + if(x!=function->DimX()-1)
  846 + {
  847 + near_value = (*function)(x+1, y, z);
  848 + if(!sdf)
  849 + result = min(result, near_value + (float)m_voxel_size.x);
  850 + else
  851 + {
  852 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  853 + possible_value = sign*(fabs(near_value) + m_voxel_size.x);
  854 + if(fabs(possible_value) < fabs(result))
  855 + result = possible_value;
  856 + }
  857 + }
  858 + if(y!=0)
  859 + {
  860 + near_value = (*function)(x, y-1, z);
  861 + if(!sdf)
  862 + result = min(result, near_value + (float)m_voxel_size.y);
  863 + else
  864 + {
  865 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  866 + possible_value = sign*(fabs(near_value) + m_voxel_size.y);
  867 + if(fabs(possible_value) < fabs(result))
  868 + result = possible_value;
  869 + }
  870 + }
  871 + if(y!=function->DimY()-1)
  872 + {
  873 + near_value = (*function)(x, y+1, z);
  874 + if(!sdf)
  875 + result = min(result, near_value + (float)m_voxel_size.y);
  876 + else
  877 + {
  878 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  879 + possible_value = sign*(fabs(near_value) + m_voxel_size.y);
  880 + if(fabs(possible_value) < fabs(result))
  881 + result = possible_value;
  882 + }
  883 + }
  884 + if(z!=0)
  885 + {
  886 + near_value = (*function)(x, y, z-1);
  887 + if(!sdf)
  888 + result = min(result, near_value + (float)m_voxel_size.z);
  889 + else
  890 + {
  891 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  892 + possible_value = sign*(fabs(near_value) + m_voxel_size.z);
  893 + if(fabs(possible_value) < fabs(result))
  894 + result = possible_value;
  895 + }
  896 + }
  897 + if(z!=function->DimZ()-1)
  898 + {
  899 + near_value = (*function)(x, y, z+1);
  900 + if(!sdf)
  901 + result = min(result, near_value + (float)m_voxel_size.z);
  902 + else
  903 + {
  904 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  905 + possible_value = sign*(fabs(near_value) + m_voxel_size.z);
  906 + if(fabs(possible_value) < fabs(result))
  907 + result = possible_value;
  908 + }
  909 + }
  910 + return result;
  911 +}
  912 +
  913 +template <class T>
  914 +inline float rtsImplicit3D<T>::isosurface_distance(point3D<double> p0, point3D<double> p1, T isovalue)
  915 +{
  916 + /*This function computes the distance from p0 to the surface, given two points p0 and p1
  917 + on either side of the surface. isovalue specifies
  918 + the value at the surface. Right now, this function returns a float. I'll have to think
  919 + of something better to do in the future.
  920 + */
  921 +
  922 + //compute the normalized position of the surface between p0 and p1
  923 + float val0 = ijk(p0.x, p0.y, p0.z);
  924 + float val1 = ijk(p1.x, p1.y, p1.z);
  925 + float isovalue_norm_pos = (isovalue - val0) / (val1 - val0);
  926 + //compute the actual position of the surface
  927 + point3D<double> s_pos = p0 + isovalue_norm_pos * (p1 - p0);
  928 + //compute the distance from p0 to the surface
  929 + float result = (s_pos - p0).Length();
  930 + //cout<<"distance: "<<result<<endl;
  931 + return result;
  932 +}
  933 +
  934 +template <class T>
  935 +void rtsImplicit3D<T>::compute_distance_function_boundary(T isovalue,
  936 + rtsImplicit3D<float>* &result,
  937 + rtsImplicit3D<bool>* &mask, bool sdf)
  938 +{
  939 + /*This function creates an initial signed distance function from a threshold image.
  940 + All voxels adjacent to the surface specified by the threshold are initialized with a
  941 + distance value. Low values are inside, high values are outside.
  942 + */
  943 + //current and neighboring voxel flags (false = inside, true = outside)
  944 + bool c, x_p, x_n, y_p, y_n, z_p, z_n;
  945 + float d_xp, d_xn, d_yp, d_yn, d_zp, d_zn;
  946 + float in_out = 1;
  947 +
  948 + //boundary condition function and the mask
  949 + result = new rtsImplicit3D<float>(m_resolution.x, m_resolution.y, m_resolution.z);
  950 + //get the parameterization
  951 + result->Parameterize(m_domain_min.x, m_domain_max.x, m_domain_min.y, m_domain_max.y, m_domain_min.z, m_domain_max.z);
  952 + (*result) = DIST_MAX;
  953 + result->setBoundary(DIST_MAX);
  954 + //create a mask
  955 + mask = new rtsImplicit3D<bool>(m_resolution.x, m_resolution.y, m_resolution.z);
  956 + (*mask) = false;
  957 +
  958 + cout<<"done making boundary condition function"<<endl;
  959 + //for each voxel
  960 + int x, y, z;
  961 + for(x=0; x<m_resolution.x; x++)
  962 + for(y=0; y<m_resolution.y; y++)
  963 + for(z=0; z<m_resolution.z; z++)
  964 + {
  965 + //reset flags
  966 + c=x_p=x_n=y_p=y_n=z_p=z_n=true;
  967 + in_out = 1.0;
  968 + //look at the current voxel
  969 + if(xyz(x, y, z) < isovalue)
  970 + c=false;
  971 + else c=true;
  972 + //if the voxel is outside the domain, assume that it is equal to the current voxel
  973 + if(x-1 < 0) x_n = c; //X
  974 + else if(xyz(x-1, y, z) < isovalue) x_n = false;
  975 + if(x+1 >= m_resolution.x) x_p = c;
  976 + else if(xyz(x+1, y, z) < isovalue) x_p = false;
  977 + if(y-1 < 0) y_n = c; //Y
  978 + else if(xyz(x, y-1, z) < isovalue) y_n = false;
  979 + if(y+1 >= m_resolution.y) y_p = c;
  980 + else if(xyz(x, y+1, z) < isovalue) y_p = false;
  981 + if(z-1 < 0) z_n = c; //Z
  982 + else if(xyz(x, y, z-1) < isovalue) z_n = false;
  983 + if(z+1 >= m_resolution.z) z_p = c;
  984 + else if(xyz(x, y, z+1) < isovalue) z_p = false;
  985 +
  986 + //set the distance from the isosurface
  987 + if(c == false && sdf)
  988 + in_out = -1.0;
  989 + if(x_n != c)
  990 + (*result)(x, y, z) = min((*result)(x,y,z),
  991 + isosurface_distance(getParameter(x, y, z),
  992 + getParameter(x-1, y, z),
  993 + isovalue) * in_out);
  994 + if(x_p != c)
  995 + (*result)(x, y, z) = min((*result)(x,y,z),
  996 + isosurface_distance(getParameter(x, y, z),
  997 + getParameter(x+1, y, z),
  998 + isovalue) * in_out);
  999 + if(y_n != c)
  1000 + (*result)(x, y, z) = min((*result)(x,y,z),
  1001 + isosurface_distance(getParameter(x, y, z),
  1002 + getParameter(x, y-1, z),
  1003 + isovalue) * in_out);
  1004 + if(y_p != c)
  1005 + (*result)(x, y, z) = min((*result)(x,y,z),
  1006 + isosurface_distance(getParameter(x, y, z),
  1007 + getParameter(x, y+1, z),
  1008 + isovalue) * in_out);
  1009 + if(z_n != c)
  1010 + (*result)(x, y, z) = min((*result)(x,y,z),
  1011 + isosurface_distance(getParameter(x, y, z-1),
  1012 + getParameter(x, y, z),
  1013 + isovalue) * in_out);
  1014 + if(z_p != c)
  1015 + (*result)(x, y, z) = min((*result)(x,y,z),
  1016 + isosurface_distance(getParameter(x, y, z),
  1017 + getParameter(x, y, z+1),
  1018 + isovalue) * in_out);
  1019 +
  1020 + //set the mask to 1 if the voxel is on an edge node
  1021 + if(x_n != c || x_p != c || y_n != c || y_p != c || z_n != c || z_p != c)
  1022 + (*mask)(x, y, z) = true;
  1023 + }
  1024 +
  1025 +
  1026 + //if a line between the two voxels crosses the surface
  1027 + //find the distance between the voxel center and the surface
  1028 +
  1029 +
  1030 + cout<<"done computing boundary conditions"<<endl;
  1031 +}
  1032 +
  1033 +template <class T>
  1034 +rtsImplicit3D<float>* rtsImplicit3D<T>::EstimateAmbient(T threshold)
  1035 +{
  1036 + rtsImplicit3D<float>* result = new rtsImplicit3D<float>(m_resolution.x, m_resolution.y, m_resolution.z); //create a new implicit function
  1037 + (*result) = 0.0f;
  1038 + rtsImplicit3D<float>* temp = new rtsImplicit3D<float>(m_resolution.x, m_resolution.y, m_resolution.z); //temp buffer for current lighting iteration
  1039 + (*temp) = 0.0f;
  1040 + temp->setBoundary(1.0);
  1041 +
  1042 + cout<<"first iteration..."<<endl;
  1043 + int x,y,z;
  1044 + float ambient;
  1045 +
  1046 + for(x=0; x<m_resolution.x; x++)
  1047 + for(y=0; y<m_resolution.y; y++)
  1048 + for(z=0; z<m_resolution.z; z++)
  1049 + {
  1050 + ambient = 0.0;
  1051 + if(xyz(x-1, y, z) < threshold)
  1052 + ambient += (*temp)(x-1, y, z);
  1053 + if(xyz(x, y-1, z) < threshold)
  1054 + ambient += (*temp)(x, y-1, z);
  1055 + if(xyz(x, y-1, z) < threshold)
  1056 + ambient += (*temp)(x, y, z-1);
  1057 +
  1058 + (*temp)(x, y, z) += ambient/3.0;
  1059 + (*result)(x, y, z) += ambient/3.0;
  1060 + if(ambient > 3.0)
  1061 + cout<<"error"<<endl;
  1062 + }
  1063 + (*temp) = 0.0f;
  1064 + temp->setBoundary(1.0);
  1065 + cout<<"done."<<endl;
  1066 +
  1067 + cout<<"second iteration..."<<endl;
  1068 + for(x=0; x<m_resolution.x; x++)
  1069 + for(y=0; y<m_resolution.y; y++)
  1070 + for(z=m_resolution.z-1; z>=0; z--)
  1071 + {
  1072 + ambient = 0.0;
  1073 + if(xyz(x-1, y, z) < threshold)
  1074 + ambient += (*temp)(x-1, y, z);
  1075 + if(xyz(x, y-1, z) < threshold)
  1076 + ambient += (*temp)(x, y-1, z);
  1077 + if(xyz(x, y, z+1) < threshold)
  1078 + ambient += (*temp)(x, y, z+1);
  1079 +
  1080 + (*temp)(x, y, z) += ambient/3.0;
  1081 + (*result)(x, y, z) += ambient/3.0;
  1082 + if(ambient > 3.0)
  1083 + cout<<"error"<<endl;
  1084 + }
  1085 + (*temp) = 0.0f;
  1086 + temp->setBoundary(1.0);
  1087 + cout<<"done."<<endl;
  1088 +
  1089 + cout<<"third iteration..."<<endl;
  1090 + for(x=0; x<m_resolution.x; x++)
  1091 + for(y=m_resolution.y-1; y>=0; y--)
  1092 + for(z=0; z<m_resolution.z; z++)
  1093 + {
  1094 + ambient = 0.0;
  1095 + if(xyz(x-1, y, z) < threshold)
  1096 + ambient += (*temp)(x-1, y, z);
  1097 + if(xyz(x, y+1, z) < threshold)
  1098 + ambient += (*temp)(x, y+1, z);
  1099 + if(xyz(x, y, z-1) < threshold)
  1100 + ambient += (*temp)(x, y, z-1);
  1101 +
  1102 + (*temp)(x, y, z) += ambient/3.0;
  1103 + (*result)(x, y, z) += ambient/3.0;
  1104 + if(ambient > 3.0)
  1105 + cout<<"error"<<endl;
  1106 + }
  1107 + (*temp) = 0.0f;
  1108 + temp->setBoundary(1.0);
  1109 + cout<<"done."<<endl;
  1110 +
  1111 + cout<<"fourth iteration..."<<endl;
  1112 + for(x=0; x<m_resolution.x; x++)
  1113 + for(y=m_resolution.y-1; y>=0; y--)
  1114 + for(z=m_resolution.z-1; z>=0; z--)
  1115 + {
  1116 + ambient = 0.0;
  1117 + if(xyz(x-1, y, z) < threshold)
  1118 + ambient += (*temp)(x-1, y, z);
  1119 + if(xyz(x, y+1, z) < threshold)
  1120 + ambient += (*temp)(x, y+1, z);
  1121 + if(xyz(x, y, z+1) < threshold)
  1122 + ambient += (*temp)(x, y, z+1);
  1123 +
  1124 + (*temp)(x, y, z) += ambient/3.0;
  1125 + (*result)(x, y, z) += ambient/3.0;
  1126 + if(ambient > 3.0)
  1127 + cout<<"error"<<endl;
  1128 + }
  1129 + (*temp) = 0.0f;
  1130 + temp->setBoundary(1.0);
  1131 + cout<<"done."<<endl;
  1132 +
  1133 + cout<<"fifth iteration..."<<endl;
  1134 + for(x=m_resolution.x-1; x>=0; x--)
  1135 + for(y=0; y<m_resolution.y; y++)
  1136 + for(z=0; z<m_resolution.z; z++)
  1137 + {
  1138 + ambient = 0.0;
  1139 + if(xyz(x+1, y, z) < threshold)
  1140 + ambient += (*temp)(x+1, y, z);
  1141 + if(xyz(x, y-1, z) < threshold)
  1142 + ambient += (*temp)(x, y-1, z);
  1143 + if(xyz(x, y, z-1) < threshold)
  1144 + ambient += (*temp)(x, y, z-1);
  1145 +
  1146 + (*temp)(x, y, z) += ambient/3.0;
  1147 + (*result)(x, y, z) += ambient/3.0;
  1148 + if(ambient > 3.0)
  1149 + cout<<"error"<<endl;
  1150 + }
  1151 + (*temp) = 0.0f;
  1152 + temp->setBoundary(1.0);
  1153 + cout<<"done."<<endl;
  1154 +
  1155 + cout<<"sixth iteration..."<<endl;
  1156 + for(x=m_resolution.x-1; x>=0; x--)
  1157 + for(y=0; y<m_resolution.y; y++)
  1158 + for(z=m_resolution.z-1; z>=0; z--)
  1159 + {
  1160 + ambient = 0.0;
  1161 + if(xyz(x+1, y, z) < threshold)
  1162 + ambient += (*temp)(x+1, y, z);
  1163 + if(xyz(x, y-1, z) < threshold)
  1164 + ambient += (*temp)(x, y-1, z);
  1165 + if(xyz(x, y, z+1) < threshold)
  1166 + ambient += (*temp)(x, y, z+1);
  1167 +
  1168 + (*temp)(x, y, z) += ambient/3.0;
  1169 + (*result)(x, y, z) += ambient/3.0;
  1170 + if(ambient > 3.0)
  1171 + cout<<"error"<<endl;
  1172 + }
  1173 + (*temp) = 0.0f;
  1174 + temp->setBoundary(1.0);
  1175 + cout<<"done."<<endl;
  1176 +
  1177 + cout<<"seventh iteration..."<<endl;
  1178 + for(x=m_resolution.x-1; x>=0; x--)
  1179 + for(y=m_resolution.y-1; y>=0; y--)
  1180 + for(z=0; z<m_resolution.z; z++)
  1181 + {
  1182 + ambient = 0.0;
  1183 + if(xyz(x+1, y, z) < threshold)
  1184 + ambient += (*temp)(x+1, y, z);
  1185 + if(xyz(x, y+1, z) < threshold)
  1186 + ambient += (*temp)(x, y+1, z);
  1187 + if(xyz(x, y, z-1) < threshold)
  1188 + ambient += (*temp)(x, y, z-1);
  1189 +
  1190 + (*temp)(x, y, z) += ambient/3.0;
  1191 + (*result)(x, y, z) += ambient/3.0;
  1192 + if(ambient > 3.0)
  1193 + cout<<"error"<<endl;
  1194 + }
  1195 + (*temp) = 0.0f;
  1196 + temp->setBoundary(1.0);
  1197 + cout<<"done."<<endl;
  1198 +
  1199 + cout<<"eighth iteration..."<<endl;
  1200 + for(x=m_resolution.x-1; x>=0; x--)
  1201 + for(y=m_resolution.y-1; y>=0; y--)
  1202 + for(z=m_resolution.z-1; z>=0; z--)
  1203 + {
  1204 + ambient = 0.0;
  1205 + if(xyz(x+1, y, z) < threshold)
  1206 + ambient += (*temp)(x+1, y, z);
  1207 + if(xyz(x, y+1, z) < threshold)
  1208 + ambient += (*temp)(x, y+1, z);
  1209 + if(xyz(x, y, z+1) < threshold)
  1210 + ambient += (*temp)(x, y, z+1);
  1211 +
  1212 + (*temp)(x, y, z) += ambient/3.0;
  1213 + (*result)(x, y, z) += ambient/3.0;
  1214 + if(ambient > 3.0)
  1215 + cout<<"error"<<endl;
  1216 + }
  1217 + (*temp) = 0.0f;
  1218 + temp->setBoundary(1.0);
  1219 + cout<<"done."<<endl;
  1220 +
  1221 + (*result)/=8.0;
  1222 +
  1223 + return result;
  1224 +}
  1225 +
  1226 +
  1227 +template <class T>
  1228 +rtsImplicit3D<float>* rtsImplicit3D<T>::EstimateAttenuatedAmbient(T threshold, T transparent, float attenuation)
  1229 +{
  1230 + rtsImplicit3D<float>* result = new rtsImplicit3D<float>(m_resolution.x, m_resolution.y, m_resolution.z); //create a new implicit function
  1231 + (*result) = 0.0f;
  1232 + rtsImplicit3D<float>* temp = new rtsImplicit3D<float>(m_resolution.x, m_resolution.y, m_resolution.z); //temp buffer for current lighting iteration
  1233 + (*temp) = 0.0f;
  1234 + temp->setBoundary(1.0);
  1235 +
  1236 + cout<<"first iteration..."<<endl;
  1237 + int x,y,z;
  1238 + float ambient;
  1239 +
  1240 + for(x=0; x<m_resolution.x; x++)
  1241 + for(y=0; y<m_resolution.y; y++)
  1242 + for(z=0; z<m_resolution.z; z++)
  1243 + {
  1244 + ambient = 0.0;
  1245 + if(xyz(x-1, y, z) < threshold)
  1246 + ambient += (*temp)(x-1, y, z)*(1.0 - (xyz(x-1, y, z)/255.0)*attenuation);
  1247 + if(xyz(x, y-1, z) < threshold)
  1248 + ambient += (*temp)(x, y-1, z)*(1.0 - (xyz(x, y-1, z)/255.0)*attenuation);
  1249 + if(xyz(x, y-1, z) < threshold)
  1250 + ambient += (*temp)(x, y, z-1)*(1.0 - (xyz(x, y, z-1)/255.0)*attenuation);
  1251 +
  1252 + (*temp)(x, y, z) += ambient/3.0;
  1253 + (*result)(x, y, z) += min(1.0, ambient/3.0);
  1254 + //if(ambient > 3.0)
  1255 + // cout<<"error"<<endl;
  1256 + }
  1257 + (*temp) = 0.0f;
  1258 + temp->setBoundary(1.0);
  1259 + cout<<"done."<<endl;
  1260 +
  1261 + cout<<"second iteration..."<<endl;
  1262 + for(x=0; x<m_resolution.x; x++)
  1263 + for(y=0; y<m_resolution.y; y++)
  1264 + for(z=m_resolution.z-1; z>=0; z--)
  1265 + {
  1266 + ambient = 0.0;
  1267 + if(xyz(x-1, y, z) < threshold)
  1268 + ambient += (*temp)(x-1, y, z)*(1.0 - (xyz(x-1, y, z)/255.0)*attenuation);
  1269 + if(xyz(x, y-1, z) < threshold)
  1270 + ambient += (*temp)(x, y-1, z)*(1.0 - (xyz(x, y-1, z)/255.0)*attenuation);
  1271 + if(xyz(x, y, z+1) < threshold)
  1272 + ambient += (*temp)(x, y, z+1)*(1.0 - (xyz(x, y, z+1)/255.0)*attenuation);
  1273 +
  1274 + (*temp)(x, y, z) += ambient/3.0;
  1275 + (*result)(x, y, z) += ambient/3.0;
  1276 + if(ambient > 3.0)
  1277 + cout<<"error"<<endl;
  1278 + }
  1279 + (*temp) = 0.0f;
  1280 + temp->setBoundary(1.0);
  1281 + cout<<"done."<<endl;
  1282 +
  1283 + cout<<"third iteration..."<<endl;
  1284 + for(x=0; x<m_resolution.x; x++)
  1285 + for(y=m_resolution.y-1; y>=0; y--)
  1286 + for(z=0; z<m_resolution.z; z++)
  1287 + {
  1288 + ambient = 0.0;
  1289 + if(xyz(x-1, y, z) < threshold)
  1290 + ambient += (*temp)(x-1, y, z)*(1.0 - (xyz(x-1, y, z)/255.0)*attenuation);
  1291 + if(xyz(x, y+1, z) < threshold)
  1292 + ambient += (*temp)(x, y+1, z)*(1.0 - (xyz(x, y+1, z)/255.0)*attenuation);
  1293 + if(xyz(x, y, z-1) < threshold)
  1294 + ambient += (*temp)(x, y, z-1)*(1.0 - (xyz(x, y, z-1)/255.0)*attenuation);
  1295 +
  1296 + (*temp)(x, y, z) += ambient/3.0;
  1297 + (*result)(x, y, z) += ambient/3.0;
  1298 + if(ambient > 3.0)
  1299 + cout<<"error"<<endl;
  1300 + }
  1301 + (*temp) = 0.0f;
  1302 + temp->setBoundary(1.0);
  1303 + cout<<"done."<<endl;
  1304 +
  1305 + cout<<"fourth iteration..."<<endl;
  1306 + for(x=0; x<m_resolution.x; x++)
  1307 + for(y=m_resolution.y-1; y>=0; y--)
  1308 + for(z=m_resolution.z-1; z>=0; z--)
  1309 + {
  1310 + ambient = 0.0;
  1311 + if(xyz(x-1, y, z) < threshold)
  1312 + ambient += (*temp)(x-1, y, z)*(1.0 - (xyz(x-1, y, z)/255.0)*attenuation);
  1313 + if(xyz(x, y+1, z) < threshold)
  1314 + ambient += (*temp)(x, y+1, z)*(1.0 - (xyz(x, y+1, z)/255.0)*attenuation);
  1315 + if(xyz(x, y, z+1) < threshold)
  1316 + ambient += (*temp)(x, y, z+1)*(1.0 - (xyz(x, y, z+1)/255.0)*attenuation);
  1317 +
  1318 + (*temp)(x, y, z) += ambient/3.0;
  1319 + (*result)(x, y, z) += ambient/3.0;
  1320 + if(ambient > 3.0)
  1321 + cout<<"error"<<endl;
  1322 + }
  1323 + (*temp) = 0.0f;
  1324 + temp->setBoundary(1.0);
  1325 + cout<<"done."<<endl;
  1326 +
  1327 + cout<<"fifth iteration..."<<endl;
  1328 + for(x=m_resolution.x-1; x>=0; x--)
  1329 + for(y=0; y<m_resolution.y; y++)
  1330 + for(z=0; z<m_resolution.z; z++)
  1331 + {
  1332 + ambient = 0.0;
  1333 + if(xyz(x+1, y, z) < threshold)
  1334 + ambient += (*temp)(x+1, y, z)*(1.0 - (xyz(x+1, y, z)/255.0)*attenuation);
  1335 + if(xyz(x, y-1, z) < threshold)
  1336 + ambient += (*temp)(x, y-1, z)*(1.0 - (xyz(x, y-1, z)/255.0)*attenuation);
  1337 + if(xyz(x, y, z-1) < threshold)
  1338 + ambient += (*temp)(x, y, z-1)*(1.0 - (xyz(x, y, z-1)/255.0)*attenuation);
  1339 +
  1340 + (*temp)(x, y, z) += ambient/3.0;
  1341 + (*result)(x, y, z) += ambient/3.0;
  1342 + if(ambient > 3.0)
  1343 + cout<<"error"<<endl;
  1344 + }
  1345 + (*temp) = 0.0f;
  1346 + temp->setBoundary(1.0);
  1347 + cout<<"done."<<endl;
  1348 +
  1349 + cout<<"sixth iteration..."<<endl;
  1350 + for(x=m_resolution.x-1; x>=0; x--)
  1351 + for(y=0; y<m_resolution.y; y++)
  1352 + for(z=m_resolution.z-1; z>=0; z--)
  1353 + {
  1354 + ambient = 0.0;
  1355 + if(xyz(x+1, y, z) < threshold)
  1356 + ambient += (*temp)(x+1, y, z)*(1.0 - (xyz(x+1, y, z)/255.0)*attenuation);
  1357 + if(xyz(x, y-1, z) < threshold)
  1358 + ambient += (*temp)(x, y-1, z)*(1.0 - (xyz(x, y-1, z)/255.0)*attenuation);
  1359 + if(xyz(x, y, z+1) < threshold)
  1360 + ambient += (*temp)(x, y, z+1)*(1.0 - (xyz(x, y, z+1)/255.0)*attenuation);
  1361 +
  1362 + (*temp)(x, y, z) += ambient/3.0;
  1363 + (*result)(x, y, z) += ambient/3.0;
  1364 + if(ambient > 3.0)
  1365 + cout<<"error"<<endl;
  1366 + }
  1367 + (*temp) = 0.0f;
  1368 + temp->setBoundary(1.0);
  1369 + cout<<"done."<<endl;
  1370 +
  1371 + cout<<"seventh iteration..."<<endl;
  1372 + for(x=m_resolution.x-1; x>=0; x--)
  1373 + for(y=m_resolution.y-1; y>=0; y--)
  1374 + for(z=0; z<m_resolution.z; z++)
  1375 + {
  1376 + ambient = 0.0;
  1377 + if(xyz(x+1, y, z) < threshold)
  1378 + ambient += (*temp)(x+1, y, z)*(1.0 - (xyz(x+1, y, z)/255.0)*attenuation);
  1379 + if(xyz(x, y+1, z) < threshold)
  1380 + ambient += (*temp)(x, y+1, z)*(1.0 - (xyz(x, y+1, z)/255.0)*attenuation);
  1381 + if(xyz(x, y, z-1) < threshold)
  1382 + ambient += (*temp)(x, y, z-1)*(1.0 - (xyz(x, y, z-1)/255.0)*attenuation);
  1383 +
  1384 + (*temp)(x, y, z) += ambient/3.0;
  1385 + (*result)(x, y, z) += ambient/3.0;
  1386 + if(ambient > 3.0)
  1387 + cout<<"error"<<endl;
  1388 + }
  1389 + (*temp) = 0.0f;
  1390 + temp->setBoundary(1.0);
  1391 + cout<<"done."<<endl;
  1392 +
  1393 + cout<<"eighth iteration..."<<endl;
  1394 + for(x=m_resolution.x-1; x>=0; x--)
  1395 + for(y=m_resolution.y-1; y>=0; y--)
  1396 + for(z=m_resolution.z-1; z>=0; z--)
  1397 + {
  1398 + ambient = 0.0;
  1399 + if(xyz(x+1, y, z) < threshold)
  1400 + ambient += (*temp)(x+1, y, z)*(1.0 - (xyz(x+1, y, z)/255.0)*attenuation);
  1401 + if(xyz(x, y+1, z) < threshold)
  1402 + ambient += (*temp)(x, y+1, z)*(1.0 - (xyz(x, y+1, z)/255.0)*attenuation);
  1403 + if(xyz(x, y, z+1) < threshold)
  1404 + ambient += (*temp)(x, y, z+1)*(1.0 - (xyz(x, y, z+1)/255.0)*attenuation);
  1405 +
  1406 + (*temp)(x, y, z) += ambient/3.0;
  1407 + (*result)(x, y, z) += ambient/3.0;
  1408 + if(ambient > 3.0)
  1409 + cout<<"error"<<endl;
  1410 + }
  1411 + (*temp) = 0.0f;
  1412 + temp->setBoundary(1.0);
  1413 + cout<<"done."<<endl;
  1414 +
  1415 + (*result)/=8.0;
  1416 +
  1417 + return result;
  1418 +}
  1419 +
  1420 +template <class T>
  1421 +rtsImplicit3D<float>* rtsImplicit3D<T>::Isodistance_Manhattan(T isovalue, bool sdf)
  1422 +{
  1423 + rtsImplicit3D<float>* function;
  1424 + rtsImplicit3D<bool>* mask;
  1425 + compute_distance_function_boundary(isovalue, function, mask, sdf);
  1426 +
  1427 + //compute the manhattan distance for the entire function
  1428 + //use fast sweeping to compute the manhattan distance
  1429 + //0:X 0:Y 0:Z
  1430 + cout<<"first iteration..."<<endl;
  1431 + int x,y,z;
  1432 + for(x=0; x<m_resolution.x; x++)
  1433 + for(y=0; y<m_resolution.y; y++)
  1434 + for(z=0; z<m_resolution.z; z++)
  1435 + //if the current point is not a boundary value
  1436 + if(!(*mask)(x, y, z))
  1437 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1438 + cout<<"done."<<endl;
  1439 + cout<<"second iteration..."<<endl;
  1440 + //0:X 0:Y Z:0
  1441 + for(x=0; x<m_resolution.x; x++)
  1442 + for(y=0; y<m_resolution.y; y++)
  1443 + for(z=m_resolution.z-1; z>=0; z--)
  1444 + //if the current point is not a boundary value
  1445 + if(!(*mask)(x, y, z))
  1446 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1447 + cout<<"done."<<endl;
  1448 + cout<<"third iteration..."<<endl;
  1449 + //0:X Y:0 0:Z
  1450 + for(x=0; x<m_resolution.x; x++)
  1451 + for(y=m_resolution.y-1; y>=0; y--)
  1452 + for(z=0; z<m_resolution.z; z++)
  1453 + //if the current point is not a boundary value
  1454 + if(!(*mask)(x, y, z))
  1455 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1456 + cout<<"done."<<endl;
  1457 + cout<<"fourth iteration..."<<endl;
  1458 + //0:X Y:0 Z:0
  1459 + for(x=0; x<m_resolution.x; x++)
  1460 + for(y=m_resolution.y-1; y>=0; y--)
  1461 + for(z=m_resolution.z-1; z>=0; z--)
  1462 + //if the current point is not a boundary value
  1463 + if(!(*mask)(x, y, z))
  1464 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1465 + cout<<"done."<<endl;
  1466 + cout<<"fifth iteration..."<<endl;
  1467 + //X:0 0:Y 0:Z
  1468 + for(x=m_resolution.x-1; x>=0; x--)
  1469 + for(y=0; y<m_resolution.y; y++)
  1470 + for(z=0; z<m_resolution.z; z++)
  1471 + //if the current point is not a boundary value
  1472 + if(!(*mask)(x, y, z))
  1473 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1474 + cout<<"done."<<endl;
  1475 + cout<<"sixth iteration..."<<endl;
  1476 + //X:0 0:Y Z:0
  1477 + for(x=m_resolution.x-1; x>=0; x--)
  1478 + for(y=0; y<m_resolution.y; y++)
  1479 + for(z=m_resolution.z-1; z>=0; z--)
  1480 + //if the current point is not a boundary value
  1481 + if(!(*mask)(x, y, z))
  1482 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1483 + cout<<"done."<<endl;
  1484 + cout<<"seventh iteration..."<<endl;
  1485 + //X:0 Y:0 0:Z
  1486 + for(x=m_resolution.x-1; x>=0; x--)
  1487 + for(y=m_resolution.y-1; y>=0; y--)
  1488 + for(z=0; z<m_resolution.z; z++)
  1489 + //if the current point is not a boundary value
  1490 + if(!(*mask)(x, y, z))
  1491 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1492 + cout<<"done."<<endl;
  1493 + cout<<"eighth iteration..."<<endl;
  1494 + //X:0 Y:0 Z:0
  1495 + for(x=m_resolution.x-1; x>=0; x--)
  1496 + for(y=m_resolution.y-1; y>=0; y--)
  1497 + for(z=m_resolution.z-1; z>=0; z--)
  1498 + //if the current point is not a boundary value
  1499 + if(!(*mask)(x, y, z))
  1500 + (*function)(x,y,z) = manhattan_distance(function, point3D<indextype>(x, y, z), sdf);
  1501 + cout<<"done."<<endl;
  1502 +
  1503 +
  1504 + return function;
  1505 +}
  1506 +
  1507 +//computes the gradient along all three dimensions and returns a vector field
  1508 +template <class T>
  1509 +rtsImplicit3D<vector3D<T>>* rtsImplicit3D<T>::Gradient()
  1510 +{
  1511 + int x, y, z;
  1512 + rtsImplicit3D<vector3D<T>>* result = new rtsImplicit3D<vector3D<T>>(m_resolution.x, m_resolution.y, m_resolution.z);
  1513 + for(x=0; x<m_resolution.x; x++)
  1514 + for(y=0; y<m_resolution.y; y++)
  1515 + for(z=0; z<m_resolution.z; z++)
  1516 + {
  1517 + result->xyz(x, y, z).x = xyz(x-1, y, z) - xyz(x, y, z);
  1518 + result->xyz(x, y, z).y = xyz(x, y-1, z) - xyz(x, y, z);
  1519 + result->xyz(x, y, z).z = xyz(x, y, z-1) - xyz(x, y, z);
  1520 + }
  1521 + return result;
  1522 +}
  1523 +
  1524 +
  1525 +template <class T>
  1526 +int rtsImplicit3D<T>::Neighbors26(indextype x, indextype y, indextype z, T isovalue)
  1527 +{
  1528 + int neighbors = 0;
  1529 + int u,v,w;
  1530 +
  1531 + for(u=-1; u<=1; u++)
  1532 + for(v=-1; v<=1; v++)
  1533 + for(w=-1; w<=1; w++)
  1534 + if(xyz(x+u, y+v, z+w) >= isovalue)
  1535 + neighbors++;
  1536 + if(xyz(x, y, z) > isovalue)
  1537 + neighbors--;
  1538 +
  1539 + return neighbors;
  1540 +}
  1541 +
  1542 +template <class T>
  1543 +unsigned int rtsImplicit3D<T>::Neighbors6(indextype x, indextype y, indextype z, T threshold)
  1544 +{
  1545 +
  1546 + unsigned int neighbors = 0;
  1547 + if(xyz(x+1, y, z) >= threshold)
  1548 + neighbors++;
  1549 + if(xyz(x-1, y, z) >= threshold)
  1550 + neighbors++;
  1551 + if(xyz(x, y+1, z) >= threshold)
  1552 + neighbors++;
  1553 + if(xyz(x, y-1, z) >= threshold)
  1554 + neighbors++;
  1555 + if(xyz(x, y, z+1) >= threshold)
  1556 + neighbors++;
  1557 + if(xyz(x, y, z-1) >= threshold)
  1558 + neighbors++;
  1559 +
  1560 + return neighbors;
  1561 +}
  1562 +
  1563 +template <class T>
  1564 +bool rtsImplicit3D<T>::TestTopology(T isovalue, unsigned int x, unsigned int y, unsigned int z)
  1565 +{
  1566 + if(xyz(x,y,z) < isovalue)
  1567 + return false;
  1568 + //This function returns true if a voxel is necessary, otherwise it returns false
  1569 + unsigned int neighbors = Neighbors(x, y, z, isovalue);
  1570 +
  1571 + if(neighbors == 3)
  1572 + return false;
  1573 + if(neighbors == 0 || neighbors == 1 || neighbors == 4)
  1574 + return true;
  1575 + if(neighbors == 2)
  1576 + {
  1577 + if(xyz(x-1, y, z) >= isovalue && xyz(x+1, y, z) >= isovalue)
  1578 + return true;
  1579 + if(xyz(x, y-1, z) >= isovalue && xyz(x, y+1, z) >= isovalue)
  1580 + return true;
  1581 + return false;
  1582 + }
  1583 +
  1584 +}
  1585 +
  1586 +template <class T>
  1587 +void rtsImplicit3D<T>::FloodFill6(indextype x, indextype y, indextype z, T target_value)
  1588 +{
  1589 + T old_value = xyz(x, y, z); //find the old value (the value being flood-filled)
  1590 + if(target_value == old_value) //if the target value is the same as the old value, nothing to do
  1591 + return;
  1592 +
  1593 + queue<point3D<indextype>> Q; //create a queue for neighboring points
  1594 + point3D<indextype> current(x, y, z); //start with the current point
  1595 + xyz(current.x, current.y, current.z) = target_value;
  1596 + point3D<indextype> next;
  1597 + Q.push(current);
  1598 + indextype u, v, w;
  1599 +
  1600 + while(!Q.empty()) //continue until the queue is empty
  1601 + {
  1602 + current = Q.front(); //get the first element from the queue
  1603 + Q.pop();
  1604 +
  1605 + if(current.x != m_resolution.x - 1)
  1606 + if(xyz(current.x + 1, current.y, current.z) == old_value)
  1607 + {
  1608 + xyz(current.x + 1, current.y, current.z) = target_value;
  1609 + Q.push(point3D<indextype>(current.x + 1, current.y, current.z));
  1610 + }
  1611 + if(current.x != 0)
  1612 + if(xyz(current.x - 1, current.y, current.z) == old_value)
  1613 + {
  1614 + xyz(current.x - 1, current.y, current.z) = target_value;
  1615 + Q.push(point3D<indextype>(current.x - 1, current.y, current.z));
  1616 + }
  1617 + if(current.y != m_resolution.y - 1)
  1618 + if(xyz(current.x, current.y +1, current.z) == old_value)
  1619 + {
  1620 + xyz(current.x, current.y+1, current.z) = target_value;
  1621 + Q.push(point3D<indextype>(current.x, current.y+1, current.z));
  1622 + }
  1623 + if(current.y != 0)
  1624 + if(xyz(current.x, current.y-1, current.z) == old_value)
  1625 + {
  1626 + xyz(current.x, current.y-1, current.z) = target_value;
  1627 + Q.push(point3D<indextype>(current.x, current.y-1, current.z));
  1628 + }
  1629 + if(current.z != m_resolution.z - 1)
  1630 + if(xyz(current.x, current.y, current.z+1) == old_value)
  1631 + {
  1632 + xyz(current.x, current.y, current.z+1) = target_value;
  1633 + Q.push(point3D<indextype>(current.x, current.y, current.z+1));
  1634 + }
  1635 + if(current.z != 0)
  1636 + if(xyz(current.x, current.y, current.z-1) == old_value)
  1637 + {
  1638 + xyz(current.x, current.y, current.z-1) = target_value;
  1639 + Q.push(point3D<indextype>(current.x, current.y, current.z-1));
  1640 + }
  1641 +
  1642 + }
  1643 +
  1644 +}
  1645 +
  1646 +template <class T>
  1647 +void rtsImplicit3D<T>::FloodFill26(int x, int y, int z, T target_value)
  1648 +{
  1649 + T old_value = xyz(x, y, z);
  1650 + if(target_value == old_value)
  1651 + return;
  1652 +
  1653 + queue<point3D<indextype>> Q;
  1654 + point3D<indextype> current(x, y, z);
  1655 + point3D<indextype> next;
  1656 + Q.push(current);
  1657 + indextype u, v, w;
  1658 + while(!Q.empty())
  1659 + {
  1660 + current = Q.front();
  1661 + if(xyz(current.x, current.y, current.z) == old_value)
  1662 + xyz(current.x, current.y, current.z) = target_value;
  1663 + Q.pop();
  1664 + for(u=-1; u<=1; u++)
  1665 + for(v=-1; v<=1; v++)
  1666 + for(w=-1; w<=1; w++)
  1667 + {
  1668 + next.x = current.x + u;
  1669 + next.y = current.y + v;
  1670 + next.z = current.z + w;
  1671 +
  1672 + if(next.x >= 0 && next.x < m_resolution.x &&
  1673 + next.y >= 0 && next.y < m_resolution.y &&
  1674 + next.z >= 0 && next.z < m_resolution.z &&
  1675 + xyz(next.x, next.y, next.z) == old_value)
  1676 + {
  1677 + xyz(next.x, next.y, next.z) = target_value;
  1678 + Q.push(next);
  1679 + }
  1680 + }
  1681 + }
  1682 +
  1683 +
  1684 +}
  1685 +
  1686 +template <class T>
  1687 +void rtsImplicit3D<T>::Binary(T threshold, T true_value)
  1688 +{
  1689 + /**
  1690 + This function converts an implicit function into a binary or characteristic function describing the solid represented by the level
  1691 + set at isovalue "threshold". All values below threshold are set to zero while all values above threshold are set to the specified
  1692 + "true_value". In order to use this function, the data type T must be able to be set to 0.
  1693 + **/
  1694 + int max_index = m_resolution.x * m_resolution.y * m_resolution.z; //find the size of the data array
  1695 + int i;
  1696 + for(i=0; i<max_index; i++)
  1697 + if(m_data[i] >= threshold)
  1698 + m_data[i] = true_value;
  1699 + else
  1700 + m_data[i] = 0;
  1701 +}
  1702 +
  1703 +template <class T>
  1704 +vector<point3D<indextype>> rtsImplicit3D<T>::getEdgeNodes(T isovalue, bool protrusions = true)
  1705 +{
  1706 + vector<point3D<indextype>> result;
  1707 + indextype x, y, z;
  1708 + int neighbors;
  1709 + for(x=0; x<m_resolution.x; x++)
  1710 + for(y=0; y<m_resolution.y; y++)
  1711 + for(z=0; z<m_resolution.z; z++)
  1712 + {
  1713 + if(xyz(x, y, z) >= isovalue)
  1714 + {
  1715 + neighbors = Neighbors26(x, y, z, isovalue);
  1716 + if(protrusions == false && neighbors < 1)
  1717 + continue;
  1718 + if(neighbors < 26)
  1719 + result.push_back(point3D<indextype>(x, y, z));
  1720 + }
  1721 + }
  1722 +
  1723 + return result;
  1724 +
  1725 +}
  1726 +
  1727 +template <class T>
  1728 +unsigned int rtsImplicit3D<T>::BackgroundComponents6(indextype x, indextype y, indextype z, T threshold, int n = 18)
  1729 +{
  1730 + /**
  1731 + This function computes the number of 6-connected background components in the local region of (x, y, z).
  1732 + This computation is performed by testing all 6 possible voxels that can connect to the specified node. If
  1733 + a background node is found, the entire background component associated with that node is filled and the counter
  1734 + is incremented by 1. The value n specifies the connectivity domain for the flood fill.
  1735 + The definition of background components is that specified by He, Kischell, Rioult and Holmes.
  1736 + **/
  1737 +
  1738 + //see if there is at least one BG component
  1739 + if(Neighbors6(x, y, z, threshold) == 6)
  1740 + return 0;
  1741 +
  1742 +
  1743 + //retrieve the local region of the function
  1744 + rtsImplicit3D<T> local(3, 3, 3);
  1745 + point3D<indextype> corner(x-1, y-1, z-1);
  1746 + indextype u, v, w;
  1747 + for(u=0; u<3; u++)
  1748 + for(v=0; v<3; v++)
  1749 + for(w=0; w<3; w++)
  1750 + local(u, v, w) = xyz(corner.x + u, corner.y + v, corner.z + w);
  1751 +
  1752 + //threshold the background to find inside/outside points
  1753 + local.Binary(threshold, 1);
  1754 + //fill points that are not in the connectivity domain
  1755 + if(n == 18)
  1756 + {
  1757 + local(0, 0, 0) = 1;
  1758 + local(0, 0, 2) = 1;
  1759 + local(0, 2, 0) = 1;
  1760 + local(0, 2, 2) = 1;
  1761 + local(2, 0, 0) = 1;
  1762 + local(2, 0, 2) = 1;
  1763 + local(2, 2, 0) = 1;
  1764 + local(2, 2, 2) = 1;
  1765 + }
  1766 + //local.toConsole();
  1767 +
  1768 + //search all 6 possible connected points. If a background node is found, fill the component
  1769 + unsigned int components = 0;
  1770 + if(local(0, 1, 1) == 0)
  1771 + {
  1772 + components++;
  1773 + local.FloodFill6(0, 1, 1, 1);
  1774 + }
  1775 + if(local(2, 1, 1) == 0)
  1776 + {
  1777 + components++;
  1778 + local.FloodFill6(2, 1, 1, 1);
  1779 + }
  1780 + if(local(1, 0, 1) == 0)
  1781 + {
  1782 + components++;
  1783 + local.FloodFill6(1, 0, 1, 1);
  1784 + }
  1785 + if(local(1, 2, 1) == 0)
  1786 + {
  1787 + components++;
  1788 + local.FloodFill6(1, 2, 1, 1);
  1789 + }
  1790 + if(local(1, 1, 0) == 0)
  1791 + {
  1792 + components++;
  1793 + local.FloodFill6(1, 1, 0, 1);
  1794 + }
  1795 + if(local(1, 1, 2) == 0)
  1796 + {
  1797 + components++;
  1798 + local.FloodFill6(1, 1, 2, 1);
  1799 + }
  1800 +
  1801 + return components;
  1802 +}
  1803 +
  1804 +template <class T>
  1805 +rtsImplicit3D<T> rtsImplicit3D<T>::Project2D()
  1806 +{
  1807 + /**
  1808 + This function projects the entire 3D function onto a 2D function along the z-axis.
  1809 + **/
  1810 + rtsImplicit3D<T> result(m_resolution.x, m_resolution.y, 1);
  1811 + result = 0;
  1812 +
  1813 + indextype x, y, z;
  1814 + for(x = 0; x<m_resolution.x; x++)
  1815 + for(y=0; y<m_resolution.y; y++)
  1816 + for(z=0; z<m_resolution.z; z++)
  1817 + {
  1818 + if(result(x, y, 0) < xyz(x, y, z))
  1819 + result(x, y, 0) = xyz(x, y, z);
  1820 + }
  1821 + return result;
  1822 +}
  1823 +
  1824 +template <class T>
  1825 +void rtsImplicit3D<T>::Erode(T isovalue, T fill_value)
  1826 +{
  1827 + vector<point3D<indextype>> border_nodes; //get the border nodes for the image
  1828 + indextype x, y, z;
  1829 + int condition;
  1830 + for(x=0; x<m_resolution.x; x++)
  1831 + for(y=0; y<m_resolution.y; y++)
  1832 + for(z=0; z<m_resolution.z; z++)
  1833 + if(xyz(x, y, z) >= isovalue && BackgroundComponents6(x, y, z, isovalue) == 1)
  1834 + {
  1835 + condition = 0;
  1836 + //now find the border pairs. A border point must meet two of the following conditions to be a border pair.
  1837 + //south border: s(p) is background
  1838 + if(xyz(x, y-1, z) < isovalue)
  1839 + condition++;
  1840 + //north border: n(p) is background, s(p) and s(s(p)) are foreground
  1841 + if(xyz(x, y+1, z) < isovalue && xyz(x, y-1, z) >= isovalue && xyz(x, y-2, z) >= isovalue)
  1842 + condition++;
  1843 + //west border: w(p) is background
  1844 + if(xyz(x-1, y, z) < isovalue)
  1845 + condition++;
  1846 + //east border: e(p) is background, w(p) and w(w(p)) are foreground
  1847 + if(xyz(x+1, y, z) < isovalue && xyz(x-1, y, z) >= isovalue && xyz(x-2, y, z) >= isovalue)
  1848 + condition++;
  1849 + //up border: u(p) is background
  1850 + if(xyz(x, y, z-1) < isovalue)
  1851 + condition++;
  1852 + //down border: d(p) is background, u(p) and u(u(p)) are foreground
  1853 + if(xyz(x, y, z+1) < isovalue && xyz(x, y, z-1) >= isovalue && xyz(x, y, z-2) >= isovalue)
  1854 + condition++;
  1855 +
  1856 + if(condition > 1)
  1857 + border_nodes.push_back(point3D<indextype>(x, y, z));
  1858 + }
  1859 + cout<<"Number of border nodes: "<<border_nodes.size()<<endl;
  1860 +
  1861 + vector<point3D<indextype>>::iterator i;
  1862 + for(i=border_nodes.begin(); i!= border_nodes.end(); i++)
  1863 + xyz((*i).x, (*i).y, (*i).z) = fill_value;
  1864 +
  1865 +
  1866 +}
  1867 +
  1868 +template <class T>
  1869 +void rtsImplicit3D<T>::ClampMax(T max)
  1870 +{
  1871 + int i;
  1872 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  1873 + for(i=0; i<elements; i++)
  1874 + if(m_data[i] > max)
  1875 + m_data[i] = max;
  1876 +}
  1877 +
  1878 +template <class T>
  1879 +void rtsImplicit3D<T>::ClampMin(T min)
  1880 +{
  1881 + int i;
  1882 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  1883 + for(i=0; i<elements; i++)
  1884 + if(m_data[i] < min)
  1885 + m_data[i] = min;
  1886 +}
  1887 +
  1888 +template <class T>
  1889 +void rtsImplicit3D<T>::ClampMin(T min, T value)
  1890 +{
  1891 + int i;
  1892 + int elements = m_resolution.x * m_resolution.y * m_resolution.z;
  1893 + for(i=0; i<elements; i++)
  1894 + if(m_data[i] < min)
  1895 + m_data[i] = value;
  1896 +}
  1897 +
  1898 +template <class T>
  1899 +void rtsImplicit3D<T>::MedianFilter(int dist_x, int dist_y, int dist_z, double factor = 0.5)
  1900 +{
  1901 + rtsImplicit3D<T> result = (*this);
  1902 + indextype x, y, z;
  1903 + indextype min_x, min_y, min_z;
  1904 + indextype max_x, max_y, max_z;
  1905 + indextype u, v, w;
  1906 + vector<T> region;
  1907 + for(x=0; x<m_resolution.x; x++)
  1908 + for(y=0; y<m_resolution.y; y++)
  1909 + for(z=0; z<m_resolution.z; z++)
  1910 + {
  1911 + region.clear();
  1912 + min_x = x - dist_x;
  1913 + min_y = y - dist_y;
  1914 + min_z = z - dist_z;
  1915 + max_x = x + dist_x;
  1916 + max_y = y + dist_y;
  1917 + max_z = z + dist_z;
  1918 +
  1919 + for(u=min_x; u<=max_x; u++)
  1920 + for(v=min_y; v<=max_y; v++)
  1921 + for(w=min_z; w<=max_z; w++)
  1922 + {
  1923 + region.push_back(xyz(u, v, w));
  1924 + }
  1925 + sort(region.begin(), region.end());
  1926 + result(x, y, z) = region[(int)(region.size()*factor)];
  1927 + }
  1928 + (*this) = result;
  1929 +}
  1930 +
  1931 +template <class T>
  1932 +unsigned int rtsImplicit3D<T>::Thin(T isovalue)
  1933 +{
  1934 + /**
  1935 + This function computes the skeleton of an isosurface embedded in the implicit function and
  1936 + described by the "isovalue" parameter.
  1937 + **/
  1938 +
  1939 + vector<point3D<indextype>> border_nodes; //get the border nodes for the image
  1940 + indextype x, y, z;
  1941 + int condition;
  1942 + for(x=0; x<m_resolution.x; x++)
  1943 + for(y=0; y<m_resolution.y; y++)
  1944 + for(z=0; z<m_resolution.z; z++)
  1945 + //find the border nodes
  1946 + if(xyz(x, y, z) >= isovalue && BackgroundComponents6(x, y, z, isovalue) == 1 && Neighbors26(x, y, z, isovalue) != 1)
  1947 + {
  1948 + condition = 0;
  1949 + //now find the border pairs. A border point must meet two of the following conditions to be a border pair.
  1950 + //south border: s(p) is background
  1951 + if(xyz(x, y-1, z) < isovalue)
  1952 + condition++;
  1953 + //north border: n(p) is background, s(p) and s(s(p)) are foreground
  1954 + if(xyz(x, y+1, z) < isovalue && xyz(x, y-1, z) >= isovalue && xyz(x, y-2, z) >= isovalue)
  1955 + condition++;
  1956 + //west border: w(p) is background
  1957 + if(xyz(x-1, y, z) < isovalue)
  1958 + condition++;
  1959 + //east border: e(p) is background, w(p) and w(w(p)) are foreground
  1960 + if(xyz(x+1, y, z) < isovalue && xyz(x-1, y, z) >= isovalue && xyz(x-2, y, z) >= isovalue)
  1961 + condition++;
  1962 + //up border: u(p) is background
  1963 + if(xyz(x, y, z-1) < isovalue)
  1964 + condition++;
  1965 + //down border: d(p) is background, u(p) and u(u(p)) are foreground
  1966 + if(xyz(x, y, z+1) < isovalue && xyz(x, y, z-1) >= isovalue && xyz(x, y, z-2) >= isovalue)
  1967 + condition++;
  1968 +
  1969 + if(condition > 1)
  1970 + border_nodes.push_back(point3D<indextype>(x, y, z));
  1971 + }
  1972 + cout<<"Number of border nodes: "<<border_nodes.size()<<endl;
  1973 +
  1974 + //determine if each edge node can be removed without changing the topology of the model
  1975 + //declare some initial variables
  1976 + rtsImplicit3D<T> local(3, 3, 3); //store the region local to the current voxel
  1977 + int nodes_before, nodes_after; //number of neighboring nodes before and after the filling operation
  1978 + point3D<indextype> fill_start;
  1979 + vector<point3D<indextype>>::iterator i;
  1980 +
  1981 + /*
  1982 + Here we determine if a point can be removed by looking at the number of foreground connected
  1983 + components in the local region. If there is more than one connected component
  1984 + */
  1985 + unsigned int removed = 0;
  1986 + for(i=border_nodes.begin(); i<border_nodes.end(); i++)
  1987 + {
  1988 + //get the local region around the current point
  1989 + for(x=-1; x<=1; x++)
  1990 + for(y=-1; y<=1; y++)
  1991 + for(z=-1; z<=1; z++)
  1992 + local(x+1, y+1, z+1) = xyz((*i).x + x, (*i).y + y, (*i).z + z);
  1993 +
  1994 + //deal with the degenerate case of all four sides being internal
  1995 + //if(local(0, 1, 0) >= isovalue && local(1, 0, 0) >= isovalue && local(1, 2, 0) >= isovalue && local(2, 1, 0) >= isovalue)
  1996 + // continue;
  1997 + local(1, 1, 1) = 0; //remove the center voxel
  1998 + local.Binary(isovalue, 1);
  1999 + nodes_before = local.Neighbors26(1, 1, 1, 1);
  2000 + //if(nodes_before == 1) //prevent reducing ends
  2001 + // continue;
  2002 +
  2003 + //find an interior voxel to fill
  2004 + for(x=0; x<3; x++)
  2005 + for(y=0; y<3; y++)
  2006 + for(z=0; z<3; z++)
  2007 + if(local(x, y, z) > 0)
  2008 + fill_start = point3D<indextype>(x, y, z);
  2009 +
  2010 + //fill the local region
  2011 + local.FloodFill26(fill_start.x, fill_start.y, fill_start.z, 2);
  2012 + //get the number of filled neighbors
  2013 + nodes_after = local.Neighbors26(1, 1, 1, 2);
  2014 + if(nodes_after == nodes_before)
  2015 + {
  2016 + xyz((*i).x, (*i).y, (*i).z) = 0;
  2017 + removed++;
  2018 + //cout<<"removed"<<endl;
  2019 + }
  2020 + //else
  2021 + //{
  2022 + /*for(x=-1; x<=1; x++)
  2023 + for(y=-1; y<=1; y++)
  2024 + for(z=-1; z<=1; z++)
  2025 + local(x+1, y+1, z+1) = xyz((*i).x + x, (*i).y + y, (*i).z + z);
  2026 + local.toConsole();
  2027 + cout<<"not removed: "<<nodes_before<<" "<<nodes_after<<endl;
  2028 + xyz((*i).x, (*i).y, (*i).z) = 100;
  2029 + char c;
  2030 + cin>>c;*/
  2031 + //}
  2032 + }
  2033 + return removed;
  2034 +}
  2035 +
  2036 +/*Shape functions*/
  2037 +/*These functions create implicit shapes in the function.
  2038 +Generally, the shape is based on the parameterization.*/
  2039 +template <class T>
  2040 +void rtsImplicit3D<T>::Sphere(double center_i, double center_j, double center_k, double radius, T in_value)
  2041 +{
  2042 + point3D<double> center(center_i, center_j, center_k);
  2043 + //for each point in the function
  2044 + indextype x, y, z;
  2045 + double radius_squared = radius*radius;
  2046 + vector3D<double> point_to_point;
  2047 + point3D<double> result;
  2048 + double distance_squared;
  2049 +
  2050 + for(x=0; x<m_resolution.x; x++)
  2051 + for(y=0; y<m_resolution.y; y++)
  2052 + for(z=0; z<m_resolution.z; z++)
  2053 + {
  2054 + //get the parameterized value
  2055 + result = getParameter(x, y, z);
  2056 + //find the distance between the center of the sphere and the resulting point
  2057 + //double distance = (result - center).Length();
  2058 + point_to_point = result - center;
  2059 + distance_squared = point_to_point*point_to_point;
  2060 + //if the distance is less than the radius, the point is inside the sphere
  2061 + if(distance_squared < radius_squared)
  2062 + xyz(x, y, z) = in_value;
  2063 + }
  2064 +
  2065 +}
  2066 +
  2067 +
  2068 +template <class T>
  2069 +void rtsImplicit3D<T>::toConsole()
  2070 +{
  2071 + cout<<endl;
  2072 + int x, y, z;
  2073 + for(z=0; z<m_resolution.z; z++)
  2074 + {
  2075 + for(y=0; y<m_resolution.y; y++)
  2076 + {
  2077 + for(x=0; x<m_resolution.x; x++)
  2078 + {
  2079 + cout.width(7);
  2080 + cout.precision(3);
  2081 + cout<<(double)xyz(x, y, z);
  2082 + }
  2083 + cout<<endl;
  2084 + }
  2085 + cout<<"-----------------------------"<<endl;
  2086 + }
  2087 +
  2088 +}
  2089 +
  2090 +
  2091 +#endif
0 2092 \ No newline at end of file
... ...
rtsInputState.h 0 → 100755
  1 +++ a/rtsInputState.h
  1 +#ifndef INPUTSTATE_H
  2 +#define INPUTSTATE_H
  3 +
  4 +class rtsInputState
  5 +{
  6 +private:
  7 + //mouse states
  8 + bool m_left_button;
  9 + bool m_right_button;
  10 + bool m_middle_button;
  11 +
  12 + //keyboard keys
  13 + char* m_keys_pressed;
  14 +
  15 + //mouse position
  16 + int m_mouse_x;
  17 + int m_mouse_y;
  18 +
  19 + //some cool states for general use
  20 + bool m_selection_state;
  21 +
  22 + //modifier keys
  23 + bool m_alt_key;
  24 + bool m_ctrl_key;
  25 + bool m_shift_key;
  26 +
  27 +public:
  28 + void PressLeftButton() {m_left_button = true;}
  29 + void ReleaseLeftButton() {m_left_button = false;}
  30 + void PressMiddleButton() {m_middle_button = true;}
  31 + void ReleaseMiddleButton() {m_middle_button = false;}
  32 + void PressRightButton() {m_right_button = true;}
  33 + void ReleaseRightButton() {m_right_button = false;}
  34 + void SetMousePosition(int x, int y) {m_mouse_x = x; m_mouse_y = y;}
  35 +
  36 +
  37 + bool getRightButton() {return m_right_button;}
  38 + bool getLeftButton() {return m_left_button;}
  39 + bool getMiddleButton() {return m_middle_button;}
  40 + int getMouseX() {return m_mouse_x;}
  41 + int getMouseY() {return m_mouse_y;}
  42 +
  43 + //modifier keys
  44 + bool getShiftState(){return m_shift_key;}
  45 + bool getAltState(){return m_alt_key;}
  46 + bool getCtrlState(){return m_ctrl_key;}
  47 + void setShiftState(bool val){m_shift_key = val;}
  48 + void setCtrlState(bool val){m_ctrl_key = val;}
  49 + void setAltState(bool val){m_alt_key = val;}
  50 +
  51 + //other useful states
  52 + bool getSelectionState(){return m_selection_state;}
  53 + void StartSelection(){m_selection_state = true;}
  54 + void EndSelection(){m_selection_state = false;}
  55 +};
  56 +
  57 +
  58 +
  59 +#endif
0 60 \ No newline at end of file
... ...
rtsLinearAlgebra.h 0 → 100755
  1 +++ a/rtsLinearAlgebra.h
  1 +/** \file
  2 + \brief Used to load common 3D linear algebra classes such as matrices, vectors, and points.
  3 +
  4 +The rtsLinearAlgebra.h file is used to load linear algebra objects commonly used in 3D graphics.
  5 +This includes the 3D versions of the vector, point, and matrix classes.
  6 +*/
  7 +
  8 +#define RTS_PI 3.14159 /**<Defines the value of PI used in RTS algorithms*/
  9 +#define TORADIANS(a) (a)*RTS_PI/180.0 /**<Defines a macro that converts a from degrees to radians*/
  10 +#define TODEGREES(a) (a)*180.0/RTS_PI /**<Defines a macro that converts a from radians to degrees*/
  11 +
  12 +#include <math.h>
  13 +#include "rtsVector3d.h"
  14 +#include "rtsPoint3d.h"
  15 +#include "rtsMatrix4x4.h"
0 16 \ No newline at end of file
... ...
rtsMath.cpp 0 → 100755
  1 +++ a/rtsMath.cpp
  1 +/*These files contain basic structures used frequently in the program and in computer
  2 +graphics in general. For more information, see the header file.
  3 +
  4 +-David Mayerich, 8/20/05*/
  5 +
  6 +#include "rtsMath.h"
  7 +
  8 +//#include<iostream>
  9 +
  10 +//using namespace std;
  11 +
  12 +
  13 +
  14 +point3D::point3D()
  15 +{
  16 + x=0; y=0; z=0;
  17 +}
  18 +
  19 +point3D::point3D(double newx, double newy, double newz)
  20 +{
  21 + x=newx; y=newy; z=newz;
  22 +}
  23 +
  24 +point3D point3D::operator +(vector3D param)
  25 +{
  26 + point3D result;
  27 + result.x=x+param.x;
  28 + result.y=y+param.y;
  29 + result.z=z+param.z;
  30 +
  31 + return result;
  32 +}
  33 +
  34 +point3D point3D::operator -(vector3D param)
  35 +{
  36 + point3D result;
  37 + result.x=x-param.x;
  38 + result.y=y-param.y;
  39 + result.z=z-param.z;
  40 +
  41 + return result;
  42 +}
  43 +
  44 +vector3D point3D::operator -(point3D param)
  45 +{
  46 + vector3D result;
  47 + result.x=x-param.x;
  48 + result.y=y-param.y;
  49 + result.z=z-param.z;
  50 +
  51 + return result;
  52 +}
  53 +
  54 +void point3D::print()
  55 +{
  56 + cout<<x<<","<<y<<","<<z<<endl;
  57 +}
  58 +
  59 +vector3D vector3D::operator+(vector3D param)
  60 +{
  61 + vector3D result;
  62 + result.x=x+param.x;
  63 + result.y=y+param.y;
  64 + result.z=z+param.z;
  65 +
  66 + return result;
  67 +}
  68 +
  69 +vector3D vector3D::operator -(vector3D param)
  70 +{
  71 + vector3D result;
  72 + result.x=x-param.x;
  73 + result.y=y-param.y;
  74 + result.z=z-param.z;
  75 +
  76 + return result;
  77 +}
  78 +double vector3D::operator*(vector3D param)
  79 +{
  80 + return x*param.x + y*param.y + z*param.z;
  81 +}
  82 +
  83 +vector3D::vector3D()
  84 +{
  85 + x=0; y=0; z=0;
  86 +}
  87 +
  88 +vector3D::vector3D(double newx, double newy, double newz)
  89 +{
  90 + x=newx;
  91 + y=newy;
  92 + z=newz;
  93 +}
  94 +
  95 +int vector3D::normalize()
  96 +{
  97 + double length=sqrt(x*x + y*y + z*z);
  98 + if(length == 0)
  99 + {
  100 + x=0.0;
  101 + y=0.0;
  102 + z=0.0;
  103 + }
  104 + else
  105 + {
  106 + x=x/length;
  107 + y=y/length;
  108 + z=z/length;
  109 + }
  110 +
  111 + return 1;
  112 +}
  113 +
  114 +double vector3D::length()
  115 +{
  116 + return sqrt(x*x + y*y + z*z);
  117 +}
  118 +
  119 +vector3D vector3D::cross(vector3D param)
  120 +{
  121 + vector3D result;
  122 + result.x=y*param.z - z*param.y;
  123 + result.y=z*param.x - x*param.z;
  124 + result.z=x*param.y - y*param.x;
  125 +
  126 + return result;
  127 +}
  128 +
  129 +vector3D vector3D::operator *(double param)
  130 +{
  131 + vector3D result;
  132 + result.x=x*param;
  133 + result.y=y*param;
  134 + result.z=z*param;
  135 +
  136 + return result;
  137 +}
  138 +
  139 +void vector3D::print()
  140 +{
  141 + cout<<x<<","<<y<<","<<z<<endl;
  142 +}
  143 +
  144 +matrix4x4::matrix4x4()
  145 +{
  146 + //initialize to the identity matrix
  147 + for(int i=0; i<16; i++)
  148 + matrix[i] = 0.0;
  149 + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0;
  150 +}
  151 +
  152 +matrix4x4::matrix4x4(float m00, float m01, float m02, float m03,
  153 + float m10, float m11, float m12, float m13,
  154 + float m20, float m21, float m22, float m23,
  155 + float m30, float m31, float m32, float m33)
  156 +{
  157 + float new_matrix[16] = {m00, m01, m02, m03,m10, m11, m12, m13, m20, m21, m22, m23,m30, m31, m32, m33};
  158 + for(int i=0; i<16; i++)
  159 + matrix[i] = new_matrix[i];
  160 +}
  161 +
  162 +matrix4x4::matrix4x4(vector3D basis_x, vector3D basis_y, vector3D basis_z)
  163 +{
  164 + //initialize to the identity matrix
  165 + for(int i=0; i<16; i++)
  166 + matrix[i] = 0.0;
  167 + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0;
  168 + //insert the vectors
  169 + matrix[0] = basis_x.x;
  170 + matrix[1] = basis_x.y;
  171 + matrix[2] = basis_x.z;
  172 +
  173 + matrix[4] = basis_y.x;
  174 + matrix[5] = basis_y.y;
  175 + matrix[6] = basis_y.z;
  176 +
  177 + matrix[8] = basis_z.x;
  178 + matrix[9] = basis_z.y;
  179 + matrix[10] = basis_z.z;
  180 +}
  181 +
  182 +double matrix4x4::operator()(unsigned int row, unsigned int col)
  183 +{
  184 + return matrix[row*4 + col];
  185 +}
  186 +
  187 +void matrix4x4::gl_set_matrix(float* gl_matrix)
  188 +{
  189 + //for(int row = 0; row<4; row++)
  190 + // for(int col = 0; col<4; col++)
  191 + // matrix[row*4 + col] = gl_matrix[col*4 + row];
  192 + for(int i=0; i<16; i++)
  193 + matrix[i] = gl_matrix[i];
  194 +}
  195 +
  196 +
  197 +void matrix4x4::gl_get_matrix(float* gl_matrix)
  198 +{
  199 + //for(int row = 0; row<4; row++)
  200 + // for(int col = 0; col<4; col++)
  201 + // gl_matrix[col*4 + row] = matrix[row*4 + col];
  202 + for(int i=0; i<16; i++)
  203 + gl_matrix[i] = matrix[i];
  204 +
  205 +}
  206 +
  207 +matrix4x4 matrix4x4::submatrix(unsigned int start_col, unsigned int start_row, unsigned int end_col, unsigned int end_row)
  208 +{
  209 + matrix4x4 result;
  210 + int col, row;
  211 + for(row = start_row; row<=end_row; row++)
  212 + for(col = start_col; col <= end_col; col++)
  213 + result.matrix[col*4 + row] = matrix[col*4 + row];
  214 + return result;
  215 +
  216 +}
  217 +
  218 +matrix4x4 matrix4x4::transpose()
  219 +{
  220 + matrix4x4 result;
  221 + int col, row;
  222 + for(row = 0; row <4; row++)
  223 + for(col=0; col<4; col++)
  224 + result.matrix[col*4 + row] = matrix[row*4+ col];
  225 + return result;
  226 +}
  227 +
  228 +
  229 +
  230 +vector3D matrix4x4::basis_x()
  231 +{
  232 + vector3D basis(matrix[0], matrix[1], matrix[2]);
  233 + return basis;
  234 +}
  235 +
  236 +vector3D matrix4x4::basis_y()
  237 +{
  238 + vector3D basis(matrix[4], matrix[5], matrix[6]);
  239 + return basis;
  240 +}
  241 +
  242 +vector3D matrix4x4::basis_z()
  243 +{
  244 + vector3D basis(matrix[8], matrix[9], matrix[10]);
  245 + return basis;
  246 +}
  247 +
  248 +
  249 +
  250 +point3D matrix4x4::operator *(point3D param)
  251 +{
  252 + point3D result;
  253 + //result.x = matrix[0][0]*param.x + matrix[1][0]*param.y + matrix[2][0]*param.z + matrix[3][0];
  254 + //result.y = matrix[0][1]*param.x + matrix[1][1]*param.y + matrix[2][1]*param.z + matrix[3][1];
  255 + //result.z = matrix[0][2]*param.x + matrix[1][2]*param.y + matrix[2][2]*param.z + matrix[3][2];
  256 + //float homogeneous = matrix[0][3] + matrix[1][3] + matrix[2][3] + matrix[3][3];
  257 + result.x = matrix[0]*param.x + matrix[4]*param.y + matrix[8]*param.z + matrix[12];
  258 + result.y = matrix[1]*param.x + matrix[5]*param.y + matrix[9]*param.z + matrix[13];
  259 + result.z = matrix[2]*param.x + matrix[6]*param.y + matrix[10]*param.z + matrix[14];
  260 + float homogeneous = matrix[3] + matrix[7] + matrix[11] + matrix[15];
  261 + result.x/=homogeneous;
  262 + result.y/=homogeneous;
  263 + result.z/=homogeneous;
  264 +
  265 + return result;
  266 +}
  267 +
  268 +vector3D matrix4x4::operator*(vector3D param)
  269 +{
  270 + vector3D result;
  271 + result.x = matrix[0]*param.x + matrix[4]*param.y + matrix[8]*param.z;
  272 + result.y = matrix[1]*param.x + matrix[5]*param.y + matrix[9]*param.z;
  273 + result.z = matrix[2]*param.x + matrix[6]*param.y + matrix[10]*param.z;
  274 +
  275 + return result;
  276 +}
  277 +
  278 +void matrix4x4::print()
  279 +{
  280 + for(int row = 0; row<4; row++)
  281 + {
  282 + for(int col = 0; col<4; col++)
  283 + {
  284 + cout<<matrix[col*4 + row]<<" ";
  285 + }
  286 + cout<<endl;
  287 + }
  288 +}
  289 +
  290 +
  291 +RGBA::RGBA(double red, double green, double blue, double ambient)
  292 +{
  293 + r=red;
  294 + g=green;
  295 + b=blue;
  296 + a=ambient;
  297 +}
  298 +
  299 +RGBA::RGBA()
  300 +{
  301 + r=1.0;
  302 + g=1.0;
  303 + b=1.0;
  304 + a=1.0;
  305 +}
  306 +
  307 +int quaternion::normalize()
  308 +{
  309 + double length=sqrt(w*w + x*x + y*y + z*z);
  310 + w=w/length;
  311 + x=x/length;
  312 + y=y/length;
  313 + z=z/length;
  314 +
  315 + return 1;
  316 +}
  317 +
  318 +quaternion quaternion::operator *(quaternion param)
  319 +{
  320 + float A, B, C, D, E, F, G, H;
  321 +
  322 +
  323 + A = (w + x)*(param.w + param.x);
  324 + B = (z - y)*(param.y - param.z);
  325 + C = (w - x)*(param.y + param.z);
  326 + D = (y + z)*(param.w - param.x);
  327 + E = (x + z)*(param.x + param.y);
  328 + F = (x - z)*(param.x - param.y);
  329 + G = (w + y)*(param.w - param.z);
  330 + H = (w - y)*(param.w + param.z);
  331 +
  332 + quaternion result;
  333 + result.w = B + (-E - F + G + H) /2;
  334 + result.x = A - (E + F + G + H)/2;
  335 + result.y = C + (E - F + G - H)/2;
  336 + result.z = D + (E - F - G + H)/2;
  337 +
  338 + return result;
  339 +}
  340 +
  341 +double* quaternion::toMatrix()
  342 +{
  343 +
  344 +
  345 + double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
  346 +
  347 +
  348 + // calculate coefficients
  349 + x2 = x + x; y2 = y + y;
  350 + z2 = z + z;
  351 + xx = x * x2; xy = x * y2; xz = x * z2;
  352 + yy = y * y2; yz = y * z2; zz = z * z2;
  353 + wx = w * x2; wy = w * y2; wz = w * z2;
  354 +
  355 + double m[4][4];
  356 + m[0][0] = 1.0 - (yy + zz); m[1][0] = xy - wz;
  357 + m[2][0] = xz + wy; m[3][0] = 0.0;
  358 +
  359 + m[0][1] = xy + wz; m[1][1] = 1.0 - (xx + zz);
  360 + m[2][1] = yz - wx; m[3][1] = 0.0;
  361 +
  362 +
  363 + m[0][2] = xz - wy; m[1][2] = yz + wx;
  364 + m[2][2] = 1.0 - (xx + yy); m[3][2] = 0.0;
  365 +
  366 +
  367 + m[0][3] = 0; m[1][3] = 0;
  368 + m[2][3] = 0; m[3][3] = 1;
  369 +
  370 + double* orientationmatrix=(double*)m;
  371 + char c;
  372 +
  373 +
  374 + double* result=new double[16];
  375 + double* array=(double*)m;
  376 + for(int i=0; i<16; i++)
  377 + result[i]=array[i];
  378 +
  379 + return result;
  380 +}
  381 +
  382 +quaternion::quaternion()
  383 +{
  384 + w=0.0; x=0.0; y=0.0; z=0.0;
  385 +}
  386 +
  387 +quaternion::quaternion(double c, double i, double j, double k)
  388 +{
  389 + w=c; x=i; y=j; z=k;
  390 +}
  391 +
  392 +ray3D::ray3D(point3D start_point, vector3D dir)
  393 +{
  394 + point=start_point;
  395 + direction=dir;
  396 + direction.normalize();
  397 +}
  398 +
  399 +ray3D::ray3D(point3D pointA, point3D pointB)
  400 +{
  401 + point = pointA;
  402 + direction = pointB - pointA;
  403 + direction.normalize();
  404 +}
  405 +
  406 +ray3D::ray3D()
  407 +{
  408 + point = point3D(0, 0, 0);
  409 + direction = vector3D(0, 0, 1);
  410 +}
  411 +
  412 +int ray3D::intersect(plane3D plane, point3D& intersection_point)
  413 +{
  414 + double NdotD = plane.normal * direction; //determine the angle between the plane normal and the ray direction
  415 + if(NdotD == 0.0) //if they are orthogonal, the ray is parallel to the plane
  416 + return RTS_NO_INTERSECTION;
  417 +
  418 + vector3D E = point - plane.point; //determine the vector from the ray point to the plane point
  419 + double NdotE = plane.normal * E; //find the angle between the plane normal and the above calculated E
  420 + double t = -NdotE/NdotD; //the intersection occurrs at time t
  421 +
  422 + if(t<0)
  423 + return RTS_NO_INTERSECTION;
  424 +
  425 + intersection_point = point + direction*t; //find the intersection point
  426 + return RTS_OK;
  427 +}
  428 +
  429 +
  430 +
  431 +plane3D::plane3D()
  432 +{
  433 + point = point3D(0.0, 0.0, 0.0);
  434 + normal = vector3D(0.0, 0.0, 1.0);
  435 + normal.normalize();
  436 +}
  437 +
  438 +plane3D::plane3D(point3D point_on_plane, vector3D plane_normal)
  439 +{
  440 + point = point_on_plane;
  441 + normal = plane_normal;
  442 + normal.normalize();
  443 +}
  444 +
  445 +
  446 +function2D::function2D(const function2D &copy)
  447 +{
  448 + m_x0 = copy.m_x0;
  449 + m_y0 = copy.m_y0;
  450 + m_x1 = copy.m_x1;
  451 + m_y1 = copy.m_y1;
  452 + m_x_resolution = copy.m_x_resolution;
  453 + m_y_resolution = copy.m_y_resolution;
  454 + m_values = new float[m_x_resolution*m_y_resolution];
  455 +
  456 + for(int i=0; i < m_x_resolution*m_y_resolution; i++)
  457 + m_values[i] = copy.m_values[i];
  458 +}
  459 +function2D& function2D::operator=(const function2D& f)
  460 +{
  461 + if (this != &f) // make sure not same object
  462 + {
  463 + delete m_values;
  464 + m_x0 = f.m_x0;
  465 + m_x1 = f.m_x1;
  466 + m_y0 = f.m_y0;
  467 + m_y1 = f.m_y1;
  468 + m_x_resolution = f.m_x_resolution;
  469 + m_y_resolution = f.m_y_resolution;
  470 + m_values = new float[m_x_resolution*m_y_resolution];
  471 + for(int i=0; i<m_x_resolution * m_y_resolution; i++)
  472 + m_values[i] = f.m_values[i];
  473 + }
  474 + return *this; // Return ref for multiple assignment
  475 +}//end operator=
  476 +
  477 +function2D function2D::operator*(function2D param)
  478 +{
  479 + //this is a quick and dirty multiplication method (mostly for images)
  480 +
  481 + if((m_x_resolution != param.m_x_resolution) || (m_y_resolution != param.m_y_resolution))
  482 + exit(0);
  483 +
  484 + float* a_bits = m_values;
  485 + float* b_bits = param.getBits();
  486 +
  487 + function2D result(m_x0, m_x1, m_y0, m_y1, m_x_resolution, m_y_resolution);
  488 + //result.m_values = new T[m_x_resolution * m_y_resolution];
  489 +
  490 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  491 + result.m_values[i] = a_bits[i]*b_bits[i];
  492 +
  493 + //result.setBits((T*)result_bits);
  494 + return result;
  495 +}
  496 +function2D function2D::operator*(float param)
  497 +{
  498 + function2D result(m_x0, m_x1, m_y0, m_y1, m_x_resolution, m_y_resolution);
  499 + for(int i = 0; i<m_x_resolution*m_y_resolution; i++)
  500 + result.m_values[i] = m_values[i]*param;
  501 +
  502 + return result;
  503 +}
  504 +
  505 +function2D function2D::operator+(function2D param)
  506 +{
  507 + function2D result(m_x0, m_x1, m_y0, m_y1, m_x_resolution, m_y_resolution);
  508 + for(int i=0; i<m_x_resolution * m_y_resolution; i++)
  509 + result.m_values[i] = m_values[i] + param.m_values[i];
  510 + return result;
  511 +}
  512 +
  513 +function2D function2D::operator+(float param)
  514 +{
  515 + function2D result(m_x0, m_x1, m_y0, m_y1, m_x_resolution, m_y_resolution);
  516 + for(int i=0; i<m_x_resolution * m_y_resolution; i++)
  517 + result.m_values[i] = m_values[i] + param;
  518 + return result;
  519 +}
  520 +
  521 +function2D function2D::operator-(function2D param)
  522 +{
  523 + function2D result(m_x0, m_x1, m_y0, m_y1, m_x_resolution, m_y_resolution);
  524 + for(int i=0; i<m_x_resolution * m_y_resolution; i++)
  525 + result.m_values[i] = m_values[i] - param.m_values[i];
  526 + return result;
  527 +}
  528 +
  529 +function2D::function2D(float domain_x0, float domain_x1, float domain_y0, float domain_y1,
  530 + int x_resolution, int y_resolution)
  531 +{
  532 + //set all of the member variables describing the size of the function domain
  533 + m_x0=domain_x0;
  534 + m_y0=domain_y0;
  535 + m_x1=domain_x1;
  536 + m_y1=domain_y1;
  537 +
  538 + m_x_resolution = x_resolution;
  539 + m_y_resolution = y_resolution;
  540 +
  541 + //allocate memory for the function
  542 + m_values = new float[x_resolution * y_resolution];
  543 +}
  544 +
  545 +function2D::function2D()
  546 +{
  547 + m_x0 = 0;
  548 + m_x1 = 0;
  549 + m_y0 = 0;
  550 + m_y1 = 0;
  551 + m_x_resolution = 0;
  552 + m_y_resolution = 0;
  553 + m_values = NULL;
  554 +}
  555 +float function2D::operator ()(float x, float y)
  556 +{
  557 + if(x < m_x0 || x > m_x1)
  558 + return 0.0f;
  559 + if(y < m_y0 || y > m_y1)
  560 + return 0.0f;
  561 +
  562 + float x_size = m_x1 - m_x0;
  563 + float y_size = m_y1 - m_y0;
  564 + float scaled_x = (x-m_x0)/x_size;
  565 + float scaled_y = (y-m_y0)/y_size;
  566 + int x_index = scaled_x * m_x_resolution;
  567 + int y_index = scaled_y * m_y_resolution;
  568 + return m_values[y_index * m_x_resolution + x_index];
  569 +}
  570 +
  571 +float* function2D::getBits()
  572 +{
  573 + return m_values;
  574 +}
  575 +
  576 +void function2D::setBits(unsigned char* bits)
  577 +{
  578 + //copy the given bits to the current function
  579 + //the member m_values can't just be set to bits because the datatypes may be different
  580 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  581 + m_values[i] = bits[i];
  582 +}
  583 +
  584 +void function2D::setBits(float* bits)
  585 +{
  586 + //copy the given bits to the current function
  587 + //the member m_values can't just be set to bits because the datatypes may be different
  588 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  589 + m_values[i] = bits[i];
  590 +}
  591 +
  592 +void function2D::setBits(double* bits)
  593 +{
  594 + //copy the given bits to the current function
  595 + //the member m_values can't just be set to bits because the datatypes may be different
  596 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  597 + m_values[i] = bits[i];
  598 +}
  599 +void function2D::setBits(int* bits)
  600 +{
  601 + //copy the given bits to the current function
  602 + //the member m_values can't just be set to bits because the datatypes may be different
  603 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  604 + m_values[i] = bits[i];
  605 +}
  606 +
  607 +
  608 +
  609 +function2D::~function2D()
  610 +{
  611 + delete m_values;
  612 +}
  613 +
  614 +void function2D::CreateGaussian(float mean_x, float mean_y, float std_dev)
  615 +{
  616 + //this function creates a 2D gaussian with a mean at the center of the image
  617 + //and a standard deviation as specified
  618 + //unsigned char* gaussian = new unsigned char[width*height];
  619 + //create a few variables to store details about the function domain
  620 + float domain_x;
  621 + float domain_y;
  622 + float x_domain_length = m_x1 - m_x0;
  623 + float y_domain_length = m_y1 - m_y0;
  624 + //double high_value = (1.0/(2.0*PI*std_dev*std_dev))*exp(0.0);
  625 + //cucle through all values in the functions resolution
  626 + for(int x = 0; x<m_x_resolution; x++)
  627 + for(int y=0; y<m_y_resolution; y++)
  628 + {
  629 + //find the appropriate domain values associated with the array index
  630 + domain_x = ((x/(double)m_x_resolution)*(x_domain_length))+m_x0;
  631 + domain_y = ((y/(double)m_y_resolution)*(y_domain_length))+m_y0;
  632 + double exponent = exp(-((domain_x-mean_x)*(domain_x-mean_x) + (domain_y-mean_y)*(domain_y-mean_y))/(2.0*std_dev*std_dev));
  633 + m_values[y*m_x_resolution+x] = (1.0/(2.0*RTS_PI*std_dev*std_dev))*exponent;
  634 + }
  635 +}
  636 +
  637 +void function2D::CreateConstant(float value)
  638 +{
  639 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  640 + {
  641 + m_values[i] = value;
  642 + }
  643 +}
  644 +
  645 +void function2D::CreateCircleMask(float center_x, float center_y, float radius)
  646 +{
  647 + float domain_x;
  648 + float domain_y;
  649 + float x_domain_length = m_x1 - m_x0;
  650 + float y_domain_length = m_y1 - m_y0;
  651 +
  652 + //cycle through all values in the functions resolution
  653 + for(int x = 0; x<m_x_resolution; x++)
  654 + for(int y=0; y<m_y_resolution; y++)
  655 + {
  656 + //find the appropriate domain values associated with the array index
  657 + domain_x = ((x/(double)m_x_resolution)*(x_domain_length))+m_x0;
  658 + domain_y = ((y/(double)m_y_resolution)*(y_domain_length))+m_y0;
  659 + //find the distance between the current point and the circle center
  660 + point3D center(center_x, center_y, 0.0);
  661 + point3D current(domain_x, domain_y, 0.0);
  662 + vector3D difference = current - center;
  663 + float distance = difference.length();
  664 +
  665 + //if the pixel is inside the circle, set it to 1.0
  666 + //otherwise, set the pixel to 0.0
  667 + if(distance < radius)
  668 + m_values[y*m_x_resolution+x] = 1.0f;
  669 + else
  670 + m_values[y*m_x_resolution+x] = 0.0f;
  671 + }
  672 +}
  673 +
  674 +void function2D::Scale(float min, float max)
  675 +{
  676 + //this method scales the function so that it exists between the values min and max
  677 +
  678 + //first, find the minimum and maximum values for the function
  679 + int current_min_index = 0;
  680 + int current_max_index = 0;
  681 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  682 + {
  683 + if(m_values[i] < m_values[current_min_index])
  684 + current_min_index = i;
  685 + if(m_values[i] > m_values[current_max_index])
  686 + current_max_index = i;
  687 + }
  688 + //cout<<"current max: "<<m_values[current_max_index]<<endl;
  689 + //cout<<"current min: "<<m_values[current_min_index]<<endl;
  690 + //char c;cin>>c;
  691 + float current_min = m_values[current_min_index];
  692 + float current_max = m_values[current_max_index];
  693 + //now loop through the function again and scale to the appropriate values
  694 + float scaled;
  695 + for(int i=0; i<m_x_resolution * m_y_resolution; i++)
  696 + {
  697 + scaled = ((m_values[i] - current_min) / (current_max - current_min));
  698 + m_values[i] = (scaled *(max-min)) + min;
  699 + }
  700 +}
  701 +
  702 +void function2D::Clip(float min, float max)
  703 +{
  704 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  705 + {
  706 + if(m_values[i] < min)
  707 + m_values[i] = min;
  708 + else if(m_values[i] > max)
  709 + m_values[i] = max;
  710 + }
  711 +}
  712 +
  713 +void function2D::Abs()
  714 +{
  715 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  716 + {
  717 + m_values[i] = fabs(m_values[i]);
  718 + }
  719 +}
  720 +
  721 +float function2D::Integral()
  722 +{
  723 + //this function returns the sum of all values of the function
  724 + float result=0.0f;
  725 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  726 + result+= m_values[i];
  727 + return result;
  728 +}
  729 +
  730 +float function2D::Average()
  731 +{
  732 + //this function returns the average of all of the values of the function
  733 + float result=0.0f;
  734 + for(int i=0; i<m_x_resolution*m_y_resolution; i++)
  735 + result+= m_values[i];
  736 + result = result/(m_x_resolution*m_y_resolution);
  737 + return result;
  738 +}
  739 +
  740 +
  741 +line3D::line3D()
  742 +{
  743 + m_p0 = point3D(0.0, 0.0, 0.0);
  744 + m_p1 = point3D(0.0, 0.0, 0.0);
  745 +}
  746 +
  747 +line3D::line3D(point3D p0, point3D p1)
  748 +{
  749 + m_p0 = p0;
  750 + m_p1 = p1;
  751 +}
  752 +
  753 +point3D line3D::get_point(double pos)
  754 +{
  755 + return m_p0 + (m_p1 - m_p0)*pos;
  756 +}
  757 +
... ...
rtsMath.h 0 → 100755
  1 +++ a/rtsMath.h
  1 +/*These files contain basic structures used frequently in the program and in computer
  2 +graphics in general.
  3 +vector3D - A 3D vector class that contains 3 double values and overloaded methods for
  4 + most vector operations such as euclidean and cross products.
  5 +point3D - A 3D point structure that contains 3 values and overloads functions for
  6 + point-vector arithmetic.
  7 +These two classes are designed to work together and different methods may require operands
  8 +of both types.
  9 +
  10 +RGBA and RGB - Color storage and associated methods, although they are not fully implemented yet
  11 +
  12 +-David Mayerich, 8/20/05*/
  13 +
  14 +#ifndef _RTS_MATH_H
  15 +#define _RTS_MATH_H
  16 +
  17 +#define RTS_PI 3.14159
  18 +#define TORADIANS(a) (a)*RTS_PI/180.0
  19 +#define TODEGREES(a) (a)*180.0/RTS_PI
  20 +
  21 +#include "rtsConstants.h"
  22 +#include <math.h>
  23 +#include <iostream>
  24 +using namespace std;
  25 +
  26 +class vector3D
  27 +{
  28 +public:
  29 + float x;
  30 + float y;
  31 + float z;
  32 +
  33 + vector3D();
  34 + vector3D(double newx, double newy, double newz);
  35 + vector3D operator+(vector3D param);
  36 + vector3D operator-(vector3D param);
  37 + double operator*(vector3D param); //inner product
  38 + vector3D cross(vector3D param);
  39 + vector3D operator*(double param);
  40 +
  41 + int normalize();
  42 + double length();
  43 +
  44 + void print();
  45 +};
  46 +
  47 +
  48 +class point3D
  49 +{
  50 +public:
  51 + float x;
  52 + float y;
  53 + float z;
  54 +
  55 + point3D();
  56 + point3D(double newx, double newy, double newz);
  57 +
  58 + //support for vector arithmetic
  59 + point3D operator+(vector3D param);
  60 + point3D operator-(vector3D param);
  61 +
  62 + vector3D operator-(point3D param);
  63 +
  64 + void print();
  65 +};
  66 +
  67 +class matrix4x4
  68 +{
  69 +
  70 + /*stored as:
  71 + | 0 4 8 12 |
  72 + | |
  73 + | 1 5 9 13 |
  74 + | |
  75 + | 2 6 10 14 |
  76 + | |
  77 + | 3 7 11 15 |
  78 + */
  79 +public:
  80 + float matrix[16];
  81 + matrix4x4();
  82 + matrix4x4(float m00, float m01, float m02, float m03,
  83 + float m10, float m11, float m12, float m13,
  84 + float m20, float m21, float m22, float m23,
  85 + float m30, float m31, float m32, float m33);
  86 + matrix4x4(vector3D basis_x, vector3D basis_y, vector3D basis_z);
  87 + vector3D basis_x();
  88 + vector3D basis_y();
  89 + vector3D basis_z();
  90 + point3D operator*(point3D param);
  91 + vector3D operator*(vector3D param);
  92 + double operator()(unsigned int row, unsigned int col);
  93 + void gl_set_matrix(float* gl_matrix);
  94 + void gl_get_matrix(float* gl_matrix);
  95 + matrix4x4 submatrix(unsigned int start_col, unsigned int start_row, unsigned int end_col, unsigned int end_row);
  96 + matrix4x4 transpose();
  97 + void print();
  98 +};
  99 +
  100 +
  101 +class RGB
  102 +{
  103 +public:
  104 + float r;
  105 + float g;
  106 + float b;
  107 +};
  108 +
  109 +class RGBA
  110 +{
  111 +public:
  112 + float r;
  113 + float g;
  114 + float b;
  115 + float a;
  116 +
  117 + RGBA();
  118 + RGBA(double red, double green, double blue, double ambient);
  119 +};
  120 +
  121 +class quaternion
  122 +{
  123 +public:
  124 + float w;
  125 + float x;
  126 + float y;
  127 + float z;
  128 +
  129 + int normalize();
  130 + quaternion operator*(quaternion param);
  131 + double* toMatrix();
  132 +
  133 + quaternion();
  134 + quaternion(double w, double x, double y, double z);
  135 +
  136 +};
  137 +
  138 +class plane3D
  139 +{
  140 +public:
  141 + point3D point;
  142 + vector3D normal;
  143 +
  144 + plane3D();
  145 + plane3D(point3D point_on_plane, vector3D plane_normal);
  146 +};
  147 +
  148 +class ray3D
  149 +{
  150 +public:
  151 + point3D point;
  152 + vector3D direction;
  153 +
  154 + ray3D();
  155 + ray3D(point3D start_point, vector3D direction);
  156 + ray3D(point3D first_point, point3D second_point);
  157 +
  158 + int intersect(plane3D plane, point3D& intersection_point);
  159 +};
  160 +
  161 +class line3D
  162 +{
  163 +private:
  164 + point3D m_p0;
  165 + point3D m_p1;
  166 +
  167 +public:
  168 + line3D();
  169 + line3D(point3D p0, point3D p1);
  170 +
  171 + point3D get_point(double pos); //returns a point at pos = [0.0, 1.0]
  172 +};
  173 +
  174 +
  175 +//at this point, this template class is only really working with floating point numbers (and doubles)
  176 +#define RTS_UNSIGNED_BYTE 1
  177 +#define RTS_FLOAT 2
  178 +#define RTS_DOUBLE 3
  179 +
  180 +typedef unsigned int rtsBitType;
  181 +
  182 +class function2D
  183 +{
  184 +public:
  185 +
  186 + function2D(float domain_x0, float domain_x1, float domain_y0, float domain_y1, int x_resolution, int y_resolution);
  187 + function2D();
  188 + ~function2D();
  189 + function2D(const function2D &copy); //copy constructor
  190 + function2D& operator=(const function2D& f);
  191 +
  192 + void CreateGaussian(float mean_x, float mean_y, float std_dev);
  193 + void CreateConstant(float value);
  194 + void CreateCircleMask(float center_x, float center_y, float radius);
  195 + void Scale(float min, float max); //scales the function so that the range exists only in the specified bounds
  196 + void Clip(float min, float max); //clips the function so that the range exists only in the specified bounds
  197 + void Abs(); //sets every sample point to the absolute value
  198 + float Integral(); //returns the sum of the function
  199 + float Average();
  200 + float operator ()(float x, float y);
  201 +
  202 + function2D operator*(function2D param);
  203 + function2D operator*(float param);
  204 + function2D operator+(function2D param);
  205 + function2D operator+(float param);
  206 + function2D operator-(function2D param);
  207 +
  208 + float* getBits();
  209 + void setBits(float* bits);
  210 + void setBits(unsigned char* bits);
  211 + void setBits(double* bits);
  212 + void setBits(int* bits);
  213 +
  214 +
  215 +private:
  216 + float m_x0;
  217 + float m_x1;
  218 + float m_y0;
  219 + float m_y1;
  220 + int m_x_resolution;
  221 + int m_y_resolution;
  222 + float* m_values;
  223 +};
  224 +
  225 +
  226 +
  227 +
  228 +
  229 +
  230 +
  231 +
  232 +
  233 +#endif
... ...
rtsMatrix4x4.h 0 → 100755
  1 +++ a/rtsMatrix4x4.h
  1 +#include <iostream>
  2 +#include <iomanip>
  3 +#include <stdio.h>
  4 +#include <string.h>
  5 +
  6 +#include "rtsVector3d.h"
  7 +#include "rtsPoint3d.h"
  8 +
  9 +using namespace std;
  10 +#ifndef RTSMATRIX4X4_H
  11 +#define RTSMATRIX4X4_H
  12 +
  13 +#define RTS_PI 3.14159
  14 +
  15 +///This class represents a 4x4 matrix, which is often used to represent affine transformations on 3D points and vectors.
  16 +
  17 +///
  18 +///This class is designed to work with point3d<T> and vector3d<T>. Data is stored internally in a column-major form which is compatible with OpenGL.
  19 +///
  20 +
  21 +template <class T>
  22 +class matrix4x4
  23 +{
  24 + /*stored as:
  25 + | 0 4 8 12 |
  26 + | |
  27 + | 1 5 9 13 |
  28 + | |
  29 + | 2 6 10 14 |
  30 + | |
  31 + | 3 7 11 15 |
  32 + */
  33 +public:
  34 + T m_matrix[16];
  35 +
  36 + //constructors
  37 + matrix4x4(); ///<Constructor initializes all values to zero.
  38 + matrix4x4(T c0r0, T c0r1, T c0r2, T c0r3,
  39 + T c1r0, T c1r1, T c1r2, T c1r3,
  40 + T c2r0, T c2r1, T c2r2, T c2r3,
  41 + T c3r0, T c3r1, T c3r2, T c3r3); ///<Constructor initializes all values to those specified as parameters. c=column, r=row
  42 +
  43 + //overloaded operators
  44 + T& operator()(int row, int column){return m_matrix[column*4 + row];} ///<Returns the value at the specified position. This function can be used as both m(0, 0) = x and x = m(0, 0)
  45 + vector3D<T> operator*(vector3D<T> rhs); ///<Overloaded arithmetic operator. This function multiplies a vector by the current matrix, returning the transformed vector3D.
  46 + point3D<T> operator*(point3D<T> rhs); ///<Overloaded arithmetic operator. This function multiplies a point by the current matrix, returning the transformed point3D.
  47 + matrix4x4<T> operator*(matrix4x4<T> rhs); ///<Overloaded arithmetic operator. Computes the result of a matrix x matrix multiplication.
  48 +
  49 + //methods
  50 + void SetIdentity(); ///<Sets the current matrix to the identity matrix.
  51 + void SetRotation(T angle, T x, T y, T z); ///<Creates a matrix that represents a rotation of "angle" degrees around the axis given by (x, y, z).
  52 + void SetTranslation(T x, T y, T z); ///<Creates a matrix that represents a translation specified by the vector (x, y, z).
  53 + void SetScale(T x, T y, T z); ///<Creates a matrix that represents a scale along each axis given by the scalars x, y, and z.
  54 +
  55 + //output
  56 + void Print(int width = 7, int precision = 2);///<Sends the current matrix to the standard output.
  57 +
  58 +};
  59 +
  60 +
  61 +template <class T>
  62 +matrix4x4<T>::matrix4x4()
  63 +{
  64 + memset(m_matrix, 0, sizeof(T)*16);
  65 +}
  66 +
  67 +template <class T>
  68 +matrix4x4<T>::matrix4x4(T c0r0, T c0r1, T c0r2, T c0r3,
  69 + T c1r0, T c1r1, T c1r2, T c1r3,
  70 + T c2r0, T c2r1, T c2r2, T c2r3,
  71 + T c3r0, T c3r1, T c3r2, T c3r3)
  72 +{
  73 +
  74 + T new_matrix[16] = {c0r0,c0r1,c0r2,c0r3,c1r0,c1r1,c1r2,c1r3,c2r0,c2r1,c2r2,c2r3,c3r0,c3r1,c3r2,c3r3};
  75 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  76 +}
  77 +
  78 +template <class T>
  79 +vector3D<T> matrix4x4<T>::operator*(vector3D<T> rhs)
  80 +{
  81 + vector3D<T> result;
  82 + result.x = m_matrix[0] * rhs.x + m_matrix[4] * rhs.y + m_matrix[8] * rhs.z;
  83 + result.y = m_matrix[1] * rhs.x + m_matrix[5] * rhs.y + m_matrix[9] * rhs.z;
  84 + result.z = m_matrix[2] * rhs.x + m_matrix[6] * rhs.y + m_matrix[10] * rhs.z;
  85 + return result;
  86 +}
  87 +
  88 +template <class T>
  89 +point3D<T> matrix4x4<T>::operator *(point3D<T> rhs)
  90 +{
  91 + point3D<T> result;
  92 + result.x = m_matrix[0] * rhs.x + m_matrix[4] * rhs.y + m_matrix[8] * rhs.z + m_matrix[12];
  93 + result.y = m_matrix[1] * rhs.x + m_matrix[5] * rhs.y + m_matrix[9] * rhs.z + m_matrix[13];
  94 + result.z = m_matrix[2] * rhs.x + m_matrix[6] * rhs.y + m_matrix[10] * rhs.z + m_matrix[14];
  95 + T w = m_matrix[3] + m_matrix[7] + m_matrix[11] + m_matrix[15];
  96 + result.x/=w;
  97 + result.y/=w;
  98 + result.z/=w;
  99 + return result;
  100 +}
  101 +
  102 +template <class T>
  103 +matrix4x4<T> matrix4x4<T>::operator *(matrix4x4<T> rhs)
  104 +{
  105 + matrix4x4<T> result;
  106 + int i,j,r;
  107 + for(i = 0; i<4; i++)
  108 + for(j = 0; j<4; j++)
  109 + for(r=0; r<4; r++)
  110 + result(i, j) += (*this)(i, r) * rhs(r, j);
  111 +
  112 + return result;
  113 +}
  114 +
  115 +
  116 +
  117 +
  118 +template <class T>
  119 +void matrix4x4<T>::SetIdentity()
  120 +{
  121 + T new_matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
  122 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  123 +}
  124 +
  125 +template <class T>
  126 +void matrix4x4<T>::SetTranslation(T x, T y, T z)
  127 +{
  128 + T new_matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,x,y,z,1};
  129 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  130 +}
  131 +
  132 +template <class T>
  133 +void matrix4x4<T>::SetScale(T x, T y, T z)
  134 +{
  135 + T new_matrix[16] = {x,0,0,0,0,y,0,0,0,0,z,0,0,0,0,1};
  136 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  137 +}
  138 +
  139 +template <class T>
  140 +void matrix4x4<T>::SetRotation(T angle, T x, T y, T z)
  141 +{
  142 + //create the axis of rotation
  143 + vector3D<T> axis(x, y, z);
  144 + T length = axis.Length(); //make sure that it is normalized
  145 + if(length != 1)
  146 + axis.Normalize();
  147 +
  148 + T c = cos(angle*RTS_PI/180.0); //compute the sine and cosine of angle
  149 + T s = sin(angle*RTS_PI/180.0);
  150 +
  151 + //create the matrix
  152 + m_matrix[0] = x*x*(1-c) + c;
  153 + m_matrix[1] = y*x*(1-c) + z*s;
  154 + m_matrix[2] = x*z*(1-c) - y*s;
  155 + m_matrix[4] = x*y*(1-c) - z*s;
  156 + m_matrix[5] = y*y*(1-c) + c;
  157 + m_matrix[6] = y*z*(1-c) + x*s;
  158 + m_matrix[8] = x*z*(1-c) + y*s;
  159 + m_matrix[9] = y*z*(1-c) - x*s;
  160 + m_matrix[10]= z*z*(1-c) + c;
  161 + m_matrix[15]= 1;
  162 +}
  163 +
  164 +
  165 +template <class T>
  166 +void matrix4x4<T>::Print(int width, int precision)
  167 +{
  168 + cout<<setiosflags(ios::fixed);
  169 + cout<<setprecision(precision);
  170 + cout<<setw(width)<<m_matrix[0]
  171 + <<setw(width)<<m_matrix[4]
  172 + <<setw(width)<<m_matrix[8]
  173 + <<setw(width)<<m_matrix[12]<<endl
  174 + <<setw(width)<<m_matrix[1]
  175 + <<setw(width)<<m_matrix[5]
  176 + <<setw(width)<<m_matrix[9]
  177 + <<setw(width)<<m_matrix[13]<<endl
  178 + <<setw(width)<<m_matrix[2]
  179 + <<setw(width)<<m_matrix[6]
  180 + <<setw(width)<<m_matrix[10]
  181 + <<setw(width)<<m_matrix[14]<<endl
  182 + <<setw(width)<<m_matrix[3]
  183 + <<setw(width)<<m_matrix[7]
  184 + <<setw(width)<<m_matrix[11]
  185 + <<setw(width)<<m_matrix[15]<<endl;
  186 +}
  187 +
  188 +
  189 +
  190 +
  191 +
  192 +
  193 +
  194 +
  195 +
  196 +#endif
0 197 \ No newline at end of file
... ...
rtsNetwork.h 0 → 100755
  1 +++ a/rtsNetwork.h
  1 +#include "objJedi.h"
  2 +#include <list>
  3 +#include <vector>
  4 +#include <limits.h>
  5 +#include <fstream>
  6 +
  7 +//itk includes
  8 +#include "../../VesselAnalysis/VesselAnalysis/VOL_to_ITK.h"
  9 +#include "itkDanielssonDistanceMapImageFilter.h"
  10 +#include "itkBinaryThresholdImageFilter.h"
  11 +#include "itkConstNeighborhoodIterator.h"
  12 +#include "itkExpandImageFilter.h"
  13 +#include "itkDiscreteGaussianImageFilter.h"
  14 +#include "itkCastImageFilter.h"
  15 +
  16 +
  17 +/* This code uses the octree library designed by Simon Perreault (http://nomis80.org/code/octree.html)*/
  18 +#include "octree/octree.h"
  19 +
  20 +#define OCTREE_SIZE 1024
  21 +#define BUFFER_ZONE 0
  22 +
  23 +
  24 +using namespace std;
  25 +
  26 +
  27 +
  28 +//definitions for simple structures
  29 +typedef vector<point3D<float>> FilamentType;
  30 +typedef point3D<float> CoordType;
  31 +typedef vector<FilamentType> NetworkType;
  32 +
  33 +struct EdgeType
  34 +{
  35 + unsigned int v0;
  36 + unsigned int v1;
  37 + float avg_radius;
  38 + float min_radius;
  39 + float max_radius;
  40 + float volume;
  41 + float length;
  42 + bool valid;
  43 +};
  44 +
  45 +struct NodeType
  46 +{
  47 + CoordType p;
  48 + vector<unsigned int> edges;
  49 + bool valid;
  50 +};
  51 +
  52 +struct ConnectType //this structures stores the info necessary to combine two fibers
  53 +{
  54 + unsigned int edge0;
  55 + unsigned int edge1;
  56 + unsigned int node0;
  57 + unsigned int node1;
  58 + list<FilamentType>::iterator fiber0;
  59 + list<FilamentType>::iterator fiber1;
  60 +};
  61 +
  62 +struct ConnectableType
  63 +{
  64 + FilamentType fiber;
  65 + bool front;
  66 + bool back;
  67 + unsigned int id;
  68 +};
  69 +
  70 +struct AttributeType
  71 +{
  72 + float TotalFiberLength;
  73 + int NumFibers;
  74 + int NumPoints;
  75 + float TotalVolume;
  76 + int NumDisconnectedFibers;
  77 + int NumBoundaryFibers;
  78 + int NumBifurcations;
  79 +};
  80 +
  81 +struct BranchType
  82 +{
  83 + float angle;
  84 + unsigned int branch_id;
  85 +};
  86 +
  87 +
  88 +class rtsNetwork
  89 +{
  90 +private:
  91 + int id; //used for swc output
  92 + ofstream outfile; //also for swc
  93 + NetworkType network; //list of filaments that make up the network
  94 + vector<NodeType> NodeList; //vector of endpoints
  95 + vector<EdgeType> EdgeList; //vector of vessels as edges
  96 + vector3D<unsigned int> boundary;
  97 + vector3D<float> position;
  98 +
  99 +
  100 + float calcFiberLength(unsigned int f);
  101 + float calcFiberBend(unsigned int f);
  102 + float calcTotalLength();
  103 + bool isBoundaryNode(unsigned int node);
  104 + vector3D<float> calcTrajectory(FilamentType f, bool end);
  105 + bool compareTrajectories(CoordType p0, vector3D<float> v0, CoordType p1, vector3D<float> v1, float distance, float cosine_angle);
  106 + void calcGraph();
  107 + vector<unsigned int> getConnections(unsigned int node);
  108 + CoordType toTissue(CoordType grid_coord);
  109 + FilamentType combineFibers(FilamentType f0, bool endpoint0, FilamentType f1, bool endpoint1);
  110 + bool isConnectable(ConnectableType c0, ConnectableType c1, bool& c0_end, bool& c1_end, float distance, float cosine_angle);
  111 + void traverseGraph(int node, int parent_id);
  112 + void outputFiberToSWC(int edge, int node_from, int parent_id);
  113 +
  114 + vector<BranchType> getFiberAngles(unsigned int fiber);
  115 + void reset();
  116 +
  117 +public:
  118 + //attribute variables
  119 + AttributeType Attributes;
  120 +
  121 + //control variables
  122 + point3D<float> voxel_size;
  123 +
  124 + //cleaning
  125 + int cleanDegenerateEdges(float length);
  126 + int cleanRedundantEdges();
  127 + int cleanBarbs(float length);
  128 +
  129 + //methods
  130 + rtsOBJ LoadOBJModel(const char* filename);
  131 + void AddOBJModel(const char* filename);
  132 + void SaveSWCModel(const char *filename, float root_x, float root_y);
  133 + void SaveSWCModel(const char *filename);
  134 + void Clean(float degenerate_length, float barb_length);
  135 + void CalculateAttributes();
  136 + rtsOBJ Repair(float max_distance, float cos_angle);
  137 + rtsOBJ CreateModel();
  138 + void printFiberStats(unsigned int fiber);
  139 + void ReMesh(float resample_length);
  140 + void SaveAngles(const char* filename);
  141 + void SaveBends(const char* filename);
  142 + void SaveLengths(const char* filename);
  143 + void SaveMathematicaGraph(const char* filename);
  144 + void SaveMathematicaNodeDistances(const char* filename);
  145 + void SetVoxelSize(float dx, float dy, float dz){voxel_size.x = dx; voxel_size.y = dy; voxel_size.z = dz;}
  146 + void RemoveTerminalComponents();
  147 + void RemoveBoundaryComponents();
  148 + void GetRadiusFromVolume(const char* filename, unsigned int threshold, unsigned int range);
  149 + void GetRadiusFromDistanceMap(const char *filename, int range);
  150 + point3D<float> GetFiberRadius(unsigned int fiber);
  151 + void ScaleNetwork(float x, float y, float z);
  152 + void SetOutputPosition(float x, float y, float z);
  153 +
  154 +
  155 +};
  156 +//private
  157 +void rtsNetwork::reset()
  158 +{
  159 + vector<EdgeType>::iterator e;
  160 + for(e=EdgeList.begin(); e!=EdgeList.end(); e++)
  161 + (*e).valid = true;
  162 +
  163 + vector<NodeType>::iterator n;
  164 + for(n=NodeList.begin(); n!=NodeList.end(); n++)
  165 + (*n).valid = true;
  166 +}
  167 +
  168 +float rtsNetwork::calcFiberBend(unsigned int f)
  169 +{
  170 + /*calculates the bend of a fiber.*/
  171 +
  172 + //find the line connecting the two endpoints
  173 + point3D<float> p1 = toTissue(NodeList[EdgeList[f].v0].p);
  174 + point3D<float> p2 = toTissue(NodeList[EdgeList[f].v1].p);
  175 +
  176 + //find the largest distance between the filament and the line between endpoints
  177 + FilamentType::iterator i;
  178 + float max_distance = 0;
  179 + for(i = network[f].begin(); i!= network[f].end(); i++)
  180 + {
  181 + point3D<float> p0 = toTissue((*i));
  182 +
  183 + //find the distance between the current point and the line made by the endpoints
  184 + float d = ((p0 - p1).X(p0-p2).Length())/(p2-p1).Length();
  185 + if(d > max_distance)
  186 + max_distance = d;
  187 + }
  188 + float fiber_length = calcFiberLength(f);
  189 + if(max_distance/fiber_length > 0.5)
  190 + {
  191 + cout<<"Something's wrong."<<endl;
  192 + cout<<max_distance<<"---"<<fiber_length<<endl;
  193 + }
  194 +
  195 + return max_distance/calcFiberLength(f);
  196 +
  197 +}
  198 +int rtsNetwork::cleanRedundantEdges()
  199 +{
  200 +
  201 + //redundant edges are edges with nodes of valence-2
  202 +
  203 + int combined = 0;
  204 +
  205 + //combine all valence-2 fibers
  206 + NetworkType newNetwork;
  207 + unsigned int numNodes = NodeList.size();
  208 + unsigned int n;
  209 + unsigned int e0, e1;
  210 + for(n=0; n<numNodes; n++)
  211 + {
  212 + //if the node is valence-2
  213 + if(getConnections(n).size() == 2)
  214 + {
  215 + //get both edges
  216 + e0 = NodeList[n].edges[0];
  217 + e1 = NodeList[n].edges[1];
  218 +
  219 + //if both edges are valid
  220 + if(EdgeList[e0].valid && EdgeList[e1].valid)
  221 + {
  222 + //combine them
  223 + if(EdgeList[e0].v0 == n)
  224 + {
  225 + if(EdgeList[e1].v0 == n)
  226 + newNetwork.push_back(combineFibers(network[e0], 0, network[e1], 0));
  227 + else
  228 + newNetwork.push_back(combineFibers(network[e0], 0, network[e1], 1));
  229 + }
  230 + else if(EdgeList[e0].v1 == n)
  231 + {
  232 + if(EdgeList[e1].v0 == n)
  233 + newNetwork.push_back(combineFibers(network[e0], 1, network[e1], 0));
  234 + else
  235 + newNetwork.push_back(combineFibers(network[e0], 1, network[e1], 1));
  236 + }
  237 + EdgeList[e0].valid = false;
  238 + EdgeList[e1].valid = false;
  239 + combined++;
  240 + }
  241 +
  242 + }
  243 + }
  244 +
  245 + unsigned int numEdges = network.size();
  246 + unsigned int e;
  247 + for(e=0; e<numEdges; e++)
  248 + {
  249 + if(EdgeList[e].valid)
  250 + newNetwork.push_back(network[e]);
  251 + }
  252 +
  253 + network = newNetwork;
  254 + calcGraph();
  255 + return combined;
  256 +
  257 +
  258 +}
  259 +int rtsNetwork::cleanBarbs(float length)
  260 +{
  261 + int removed = EdgeList.size();
  262 + //removes fibers that are shorter than the specified length
  263 + NetworkType newNetwork;
  264 +
  265 + unsigned int numEdges, e;
  266 + numEdges = EdgeList.size();
  267 + unsigned int numVertices, v;
  268 + float e_length;
  269 +
  270 + for(e=0; e<numEdges; e++)
  271 + {
  272 + //if the fiber is an end fiber (one vertex has valence 1)
  273 + if(getConnections(EdgeList[e].v0).size() ==1 || getConnections(EdgeList[e].v1).size() ==1)
  274 + {
  275 + e_length = calcFiberLength(e);
  276 + //if the fiber is larger than the given length
  277 + if(e_length > length)
  278 + {
  279 + newNetwork.push_back(network[e]);
  280 + removed--;
  281 + }
  282 +
  283 + }
  284 + //if the fiber is not an end fiber
  285 + else
  286 + {
  287 + newNetwork.push_back(network[e]);
  288 + removed--;
  289 + }
  290 +
  291 + }
  292 +
  293 + network.clear();
  294 + network = newNetwork;
  295 + calcGraph();
  296 +
  297 + cout<<"Barbs removed: "<<removed<<endl;
  298 +
  299 + return removed;
  300 +
  301 +}
  302 +
  303 +int rtsNetwork::cleanDegenerateEdges(float length)
  304 +{
  305 + /*This function cleans unnecessary edges with length less than <length>*/
  306 +
  307 + //form lists of degenerate and non-degenerate edges
  308 + int removed = 0;
  309 +
  310 + list<ConnectableType> degenerate;
  311 + list<ConnectableType> complete;
  312 +
  313 + //iterate through each fiber and put it in the appropriate list
  314 + int numFibers = network.size();
  315 + int f;
  316 + ConnectableType c;
  317 + for(f=0; f<numFibers; f++)
  318 + {
  319 + c.fiber = network[f];
  320 + c.id = f;
  321 + if(calcFiberLength(f) <= length)
  322 + degenerate.push_back(c);
  323 + else
  324 + complete.push_back(c);
  325 + }
  326 +
  327 +
  328 + vector<unsigned int> connected_edges;
  329 + vector<unsigned int> shared_vertices;
  330 + int numEdges, numVerts, e, e0, e1, v;
  331 + int connectedEdge;
  332 + //for each degenerate edge
  333 + list<ConnectableType>::iterator i;
  334 + for(i=degenerate.begin(); i!=degenerate.end(); i++)
  335 + {
  336 +/*DEGENERATE CASE 1
  337 +In this case, we remove edges that are parts of very small cycles (ex short edges that
  338 +bridge between a bifurcation, forming a small triangle).
  339 +*/
  340 + //get all of the edges connected to that edge
  341 + connected_edges.clear();
  342 + //add edges connected to v0
  343 + v = EdgeList[(*i).id].v0;
  344 + numEdges = NodeList[v].edges.size();
  345 + for(e=0; e<numEdges; e++)
  346 + {
  347 + connectedEdge = NodeList[v].edges[e];
  348 + if(connectedEdge != (*i).id && EdgeList[connectedEdge].valid)
  349 + connected_edges.push_back(connectedEdge);
  350 + }
  351 + //add edges connected to v1
  352 + v = EdgeList[(*i).id].v1;
  353 + numEdges = NodeList[v].edges.size();
  354 + for(e=0; e<numEdges; e++)
  355 + {
  356 + connectedEdge = NodeList[v].edges[e];
  357 + if(connectedEdge != (*i).id && EdgeList[connectedEdge].valid)
  358 + connected_edges.push_back(connectedEdge);
  359 + }
  360 +
  361 + //find all of the shared vertices
  362 + shared_vertices.clear();
  363 + numEdges = connected_edges.size();
  364 + for(e0=0; e0<numEdges; e0++)
  365 + {
  366 + for(e1 = e0; e1<numEdges; e1++)
  367 + {
  368 + if(e0 != e1)
  369 + {
  370 + if(EdgeList[connected_edges[e0]].v0 == EdgeList[connected_edges[e1]].v0 ||
  371 + EdgeList[connected_edges[e0]].v0 == EdgeList[connected_edges[e1]].v1)
  372 + shared_vertices.push_back(EdgeList[connected_edges[e0]].v0);
  373 + else if(EdgeList[connected_edges[e0]].v1 == EdgeList[connected_edges[e1]].v0 ||
  374 + EdgeList[connected_edges[e0]].v1 == EdgeList[connected_edges[e1]].v1)
  375 + shared_vertices.push_back(EdgeList[connected_edges[e0]].v1);
  376 + }
  377 + }
  378 + }
  379 +
  380 + //are any of these vertices not part of the original edge?
  381 + numVerts = shared_vertices.size();
  382 + bool delete_fiber = false;
  383 + for(v = 0; v<numVerts; v++)
  384 + {
  385 + if(shared_vertices[v] != EdgeList[(*i).id].v0 &&
  386 + shared_vertices[v] != EdgeList[(*i).id].v1)
  387 + {
  388 + if(getConnections(EdgeList[(*i).id].v0).size() ==1 ||
  389 + getConnections(EdgeList[(*i).id].v0).size() ==1)
  390 + cout<<"error "<<(*i).id<<endl;
  391 + delete_fiber = true;
  392 + removed++;
  393 + EdgeList[(*i).id].valid = false;
  394 + }
  395 + }
  396 +/*DEGENERATE CASE 2
  397 +In this case, we remove edges that are equal to each other (ex both ends are connected to the
  398 +same outside fiber).
  399 +*/
  400 +
  401 + //find the number of branches in v0
  402 + int v0 = EdgeList[(*i).id].v0;
  403 + int v1 = EdgeList[(*i).id].v1;
  404 +
  405 + int numV0 = NodeList[v0].edges.size();
  406 + int numV1 = NodeList[v1].edges.size();
  407 +
  408 + //go through each fiber connected to both nodes
  409 + for(int vi=0; vi<numV0; vi++)
  410 + for(int vj=0; vj<numV1; vj++)
  411 + {
  412 + //if there is a match and it isn't the current fiber, delete it
  413 + if(NodeList[v0].edges[vi] == NodeList[v1].edges[vj])
  414 + if(NodeList[v0].edges[vi] != (*i).id && EdgeList[NodeList[v0].edges[vi]].valid)
  415 + {
  416 + delete_fiber = true;
  417 + removed++;
  418 + EdgeList[(*i).id].valid = false;
  419 + }
  420 + }
  421 +
  422 +/*DEGENERATE CASE 3
  423 +Delete fibers that are less than length and have degree-4 connections
  424 +*/
  425 + if(calcFiberLength((*i).id) < length &&
  426 + NodeList[EdgeList[(*i).id].v1].edges.size() >3 &&
  427 + NodeList[EdgeList[(*i).id].v0].edges.size() >3)
  428 + {
  429 + delete_fiber = true;
  430 + removed++;
  431 + EdgeList[(*i).id].valid = false;
  432 + }
  433 +
  434 +
  435 +
  436 +
  437 + if(!delete_fiber)
  438 + complete.push_back((*i));
  439 +
  440 + }
  441 +
  442 + //re-create the network from <complete>
  443 + NetworkType newNetwork;
  444 + for(i = complete.begin(); i!=complete.end(); i++)
  445 + newNetwork.push_back((*i).fiber);
  446 +
  447 + network = newNetwork;
  448 + calcGraph();
  449 +
  450 + return removed;
  451 +
  452 +
  453 +
  454 +
  455 +}
  456 +bool rtsNetwork::isBoundaryNode(unsigned int node)
  457 +{
  458 + CoordType p;
  459 +
  460 + p = NodeList[node].p;
  461 + if(NodeList[node].edges.size() > 1)
  462 + return false;
  463 + if(p.x > BUFFER_ZONE && p.y > BUFFER_ZONE && p.z > BUFFER_ZONE &&
  464 + p.x < boundary.x - BUFFER_ZONE && p.y < boundary.y - BUFFER_ZONE && p.z < boundary.z - BUFFER_ZONE)
  465 + return false;
  466 + else
  467 + return true;
  468 +}
  469 +
  470 +
  471 +bool rtsNetwork::isConnectable(ConnectableType c0, ConnectableType c1, bool& c0_end, bool& c1_end, float distance, float cosine_angle)
  472 +{
  473 + //tests to see if two ConnectableType fibers can be connected. If so, the function
  474 + //returns true as well as the optimal connected endpoints as <c0_end> and <c1_end>.
  475 + //For these parameters, 0 = the first point on the fiber and 1 = the last point.
  476 +
  477 + if(c0.id == 1381 && c1.id == 1407)
  478 + cout<<"here"<<endl;
  479 +
  480 +
  481 + vector3D<float> t0;
  482 + vector3D<float> t1;
  483 + if(c0.front == 0)
  484 + {
  485 + t0 = calcTrajectory(c0.fiber, 0);
  486 + if(c1.front == 0)
  487 + {
  488 + t1 = calcTrajectory(c1.fiber, 0);
  489 + if(compareTrajectories(c0.fiber.front(), t0, c1.fiber.front(), t1, distance, cosine_angle))
  490 + {
  491 + c0_end = 0;
  492 + c1_end = 0;
  493 + return true;
  494 + }
  495 + }
  496 + if(c1.back == 0)
  497 + {
  498 + t1 = calcTrajectory(c1.fiber, 1);
  499 + if(compareTrajectories(c0.fiber.front(), t0, c1.fiber.back(), t1, distance, cosine_angle))
  500 + {
  501 + c0_end = 0;
  502 + c1_end = 1;
  503 + return true;
  504 + }
  505 + }
  506 + }
  507 + if(c0.back == 0)
  508 + {
  509 + t0 = calcTrajectory(c0.fiber, 1);
  510 + if(c1.front == 0)
  511 + {
  512 + t1 = calcTrajectory(c1.fiber, 0);
  513 + if(compareTrajectories(c0.fiber.back(), t0, c1.fiber.front(), t1, distance, cosine_angle))
  514 + {
  515 + c0_end = 1;
  516 + c1_end = 0;
  517 + return true;
  518 + }
  519 + }
  520 + if(c1.back == 0)
  521 + {
  522 + t1 = calcTrajectory(c1.fiber, 1);
  523 + if(compareTrajectories(c0.fiber.back(), t0, c1.fiber.back(), t1, distance, cosine_angle))
  524 + {
  525 + c0_end = 1;
  526 + c1_end = 1;
  527 + return true;
  528 + }
  529 + }
  530 + }
  531 +
  532 +
  533 + return false;
  534 +
  535 +}
  536 +FilamentType rtsNetwork::combineFibers(FilamentType f0, bool endpoint0, FilamentType f1, bool endpoint1)
  537 +{
  538 +
  539 + //create the new filament
  540 + FilamentType newFilament;
  541 + //insert the first filament
  542 + //if the valence-1 vertex is at the beginning
  543 + if(endpoint0 == 0)
  544 + {
  545 + //add the edge backwards
  546 + for(int v=f0.size() - 1; v>=0; v--)
  547 + newFilament.push_back(f0[v]);
  548 + }
  549 + else
  550 + {
  551 + //otherwise we can just copy the filament over
  552 + newFilament = f0;
  553 + }
  554 +
  555 + //insert the second filament
  556 + //if the valence-1 vertex is at the beginning
  557 + if(endpoint1 == 0)
  558 + {
  559 + //add the edge in forwards
  560 + for(int v=0; v<f1.size(); v++)
  561 + newFilament.push_back(f1[v]);
  562 + }
  563 + else
  564 + {
  565 + for(int v=f1.size() - 1; v>=0; v--)
  566 + newFilament.push_back(f1[v]);
  567 + }
  568 +
  569 + return newFilament;
  570 +}
  571 +vector3D<float> rtsNetwork::calcTrajectory(FilamentType f, bool end)
  572 +{
  573 + //calculates the trajectory of a fiber at the given endpoint (0 = first, 1 = last)
  574 +
  575 + CoordType pEndpoint;
  576 + CoordType pPrevpoint;
  577 + if(end == 0)
  578 + {
  579 + pEndpoint = f.front();
  580 + pPrevpoint = f[1];
  581 + //pPrevpoint = f[ceil(f.size()/4.0)];
  582 + }
  583 + else
  584 + {
  585 + pEndpoint = f.back();
  586 + pPrevpoint = f[f.size() - 2];
  587 + //pPrevpoint = f[floor(f.size()*3.0/4.0)];
  588 + }
  589 +
  590 + //pPrevpoint = f[f.size()/2];
  591 +
  592 +
  593 + vector3D<float> result = toTissue(pEndpoint) - toTissue(pPrevpoint);
  594 + result.Normalize();
  595 + return result;
  596 +}
  597 +bool rtsNetwork::compareTrajectories(CoordType p0, vector3D<float> v0, CoordType p1, vector3D<float> v1, float distance, float cosine_angle)
  598 +{
  599 + //determines of two points/trajectory pairs are compatible for connection
  600 + vector3D<float> difference = p1 - p0;
  601 + //test distance
  602 + if(difference.Length() <= distance)
  603 + {
  604 + difference.Normalize();
  605 + if(v0*difference >= cosine_angle && v1*difference <= -cosine_angle)
  606 + return true;
  607 + }
  608 + return false;
  609 +}
  610 +vector<unsigned int> rtsNetwork::getConnections(unsigned int node)
  611 +{
  612 + return NodeList[node].edges;
  613 +
  614 +}
  615 +point3D<float> rtsNetwork::toTissue(CoordType grid_coord)
  616 +{
  617 + //converts a coordinate from the original voxel grid coordinates to tissue-space coordinates
  618 + return CoordType(grid_coord.x * voxel_size.x,
  619 + grid_coord.y * voxel_size.y,
  620 + grid_coord.z * voxel_size.z);
  621 +
  622 + //return grid_coord;
  623 +}
  624 +
  625 +float rtsNetwork::calcFiberLength(unsigned int f)
  626 +{
  627 + //This function calculates the total length of the given fiber
  628 +
  629 + float result = 0.0;
  630 +
  631 + //find the length of each fiber
  632 + int vertNum, v;
  633 +
  634 + vertNum = network[f].size();
  635 + for(v=1; v<vertNum; v++)
  636 + {
  637 + result += (toTissue(network[f][v-1]) - toTissue(network[f][v])).Length();
  638 + }
  639 +
  640 + return result;
  641 +
  642 +}
  643 +
  644 +float rtsNetwork::calcTotalLength()
  645 +{
  646 + float result = 0.0;
  647 +
  648 + //find the length of each fiber
  649 + int numFibers = network.size();
  650 + int f;
  651 +
  652 + for(f = 0; f < numFibers; f++)
  653 + {
  654 + result += calcFiberLength(f);
  655 + }
  656 + return result;
  657 +
  658 +}
  659 +
  660 +rtsOBJ rtsNetwork::LoadOBJModel(const char *filename)
  661 +{
  662 + rtsOBJ model;
  663 + model.LoadFile(filename);
  664 +
  665 + //empty the current network if it isn't already
  666 + network.clear();
  667 +
  668 + //get the number of filaments
  669 + int lineNum = model.getNumLines();
  670 +
  671 + int vertexNum, v, vIndex; //for keeping track of the vertices in each line
  672 +
  673 + for(int l=0; l<lineNum; l++)
  674 + {
  675 + FilamentType fiber; //create a new fiber
  676 + vertexNum = model.getNumLineVertices(l); //get the number of vertices in the line
  677 +
  678 + for(v = 0; v<vertexNum; v++) //convert the line to a fiber
  679 + {
  680 + vIndex = model.getLineVertex(l, v);
  681 + fiber.push_back(model.getVertex3d(vIndex));
  682 + }
  683 + network.push_back(fiber); //store the converted fiber in the network
  684 + }
  685 +
  686 + //calculate the graph components
  687 + calcGraph();
  688 +
  689 + //set the boundary
  690 + AABB bound = model.getBoundingBox();
  691 + boundary.x = ceil(bound.max.x);
  692 + boundary.y = ceil(bound.max.y);
  693 + boundary.z = ceil(bound.max.z);
  694 +
  695 + return model;
  696 +
  697 +}
  698 +
  699 +void rtsNetwork::AddOBJModel(const char *filename)
  700 +{
  701 + rtsOBJ model;
  702 + model.LoadFile(filename);
  703 +
  704 + //get the number of filaments
  705 + int lineNum = model.getNumLines();
  706 +
  707 + int vertexNum, v, vIndex; //for keeping track of the vertices in each line
  708 +
  709 + for(int l=0; l<lineNum; l++)
  710 + {
  711 + FilamentType fiber; //create a new fiber
  712 + vertexNum = model.getNumLineVertices(l); //get the number of vertices in the line
  713 +
  714 + for(v = 0; v<vertexNum; v++) //convert the line to a fiber
  715 + {
  716 + vIndex = model.getLineVertex(l, v);
  717 + fiber.push_back(model.getVertex3d(vIndex));
  718 + }
  719 + network.push_back(fiber); //store the converted fiber in the network
  720 + }
  721 +
  722 + //calculate the graph components
  723 + calcGraph();
  724 +
  725 + /*//set the boundary
  726 + AABB bound = model.getBoundingBox();
  727 + boundary.x = ceil(bound.max.x);
  728 + boundary.y = ceil(bound.max.y);
  729 + boundary.z = ceil(bound.max.z);
  730 + */
  731 +
  732 +}
  733 +
  734 +void rtsNetwork::outputFiberToSWC(int e, int node_from, int parent_id)
  735 +{
  736 + EdgeList[e].valid = false;
  737 + int p;
  738 + point3D<float> outPoint;
  739 + //if we are traversing the fiber front-to-back
  740 + if(EdgeList[e].v0 == node_from)
  741 + {
  742 + if(parent_id == -1)
  743 + {
  744 + p=0;
  745 + outPoint = network[e][p] + position;
  746 + outfile<<id<<" "<<2<<" "<<outPoint.x<<" "<<outPoint.y<<" "<<outPoint.z<<" "<<1.0<<" "<<parent_id<<endl;
  747 + }
  748 + else
  749 + {
  750 + p=1;
  751 + outPoint = network[e][p] + position;
  752 + outfile<<id<<" "<<2<<" "<<outPoint.x<<" "<<outPoint.y<<" "<<outPoint.z<<" "<<1.0<<" "<<parent_id<<endl;
  753 + }
  754 + p++;
  755 + id++;
  756 + for(; p<network[e].size(); p++)
  757 + {
  758 + outPoint = network[e][p] + position;
  759 + outfile<<id<<" "<<2<<" "<<outPoint.x<<" "<<outPoint.y<<" "<<outPoint.z<<" "<<1.0<<" "<<id-1<<endl;
  760 + id++;
  761 + }
  762 + }
  763 + //if we are traversing the fiber back-to-front
  764 + else
  765 + {
  766 + if(parent_id == -1)
  767 + {
  768 + p=network[e].size()-1;
  769 + outPoint = network[e][p] + position;
  770 + outfile<<id<<" "<<2<<" "<<outPoint.x<<" "<<outPoint.y<<" "<<outPoint.z<<" "<<1.0<<" "<<parent_id<<endl;
  771 + }
  772 + else
  773 + {
  774 + p=network[e].size()-2;
  775 + outPoint = network[e][p] + position;
  776 + outfile<<id<<" "<<2<<" "<<outPoint.x<<" "<<outPoint.y<<" "<<outPoint.z<<" "<<1.0<<" "<<parent_id<<endl;
  777 + }
  778 + p--;
  779 + id++;
  780 + for(; p>=0; p--)
  781 + {
  782 + outPoint = network[e][p] + position;
  783 + outfile<<id<<" "<<2<<" "<<outPoint.x<<" "<<outPoint.y<<" "<<outPoint.z<<" "<<1.0<<" "<<id-1<<endl;
  784 + id++;
  785 + }
  786 + }
  787 +
  788 +}
  789 +void rtsNetwork::traverseGraph(int node, int parent_id)
  790 +{
  791 + //if the node is valid
  792 + if(NodeList[node].valid)
  793 + {
  794 + NodeList[node].valid = false;
  795 + int num_edges = NodeList[node].edges.size();
  796 + for(int e = 0; e<num_edges; e++)
  797 + {
  798 + if(EdgeList[NodeList[node].edges[e]].valid)
  799 + {
  800 + outputFiberToSWC(NodeList[node].edges[e], node, parent_id);
  801 + int newNode = EdgeList[NodeList[node].edges[e]].v0;
  802 + if(newNode != node)
  803 + traverseGraph(newNode, id-1);
  804 + else
  805 + traverseGraph(EdgeList[NodeList[node].edges[e]].v1, id-1);
  806 + }
  807 + }
  808 + }
  809 +
  810 +
  811 +}
  812 +
  813 +void rtsNetwork::SetOutputPosition(float x, float y, float z)
  814 +{
  815 + position.x = x;
  816 + position.y = y;
  817 + position.z = z;
  818 +}
  819 +void rtsNetwork::SaveSWCModel(const char *filename, float root_x, float root_y)
  820 +{
  821 + cout<<filename<<endl;
  822 + outfile.open(filename);
  823 + //recursively iterate through the network saving the elements to an SWC file
  824 + int node;
  825 + id = 1;
  826 +
  827 + //set the root seed point
  828 + point3D<float> rootSeed(root_x, root_y, 0);
  829 + float distance = 9999999;
  830 + int closest_node;
  831 +
  832 + //find the closest node to the root seed
  833 + for(node = 0; node != NodeList.size(); node++)
  834 + {
  835 + float length = (NodeList[node].p - rootSeed).Length();
  836 + if(length < distance)
  837 + {
  838 + closest_node = node;
  839 + distance = length;
  840 + cout<<length<<endl;
  841 + }
  842 + }
  843 + traverseGraph(closest_node, -1);
  844 +
  845 + outfile.close();
  846 +
  847 +}
  848 +
  849 +void rtsNetwork::SaveSWCModel(const char* filename)
  850 +{
  851 + cout<<filename<<endl;
  852 + outfile.open(filename);
  853 + //recursively iterate through the network saving the elements to an SWC file
  854 + int node;
  855 + id = 1;
  856 +
  857 + //set the root seed point
  858 +
  859 + //find the closest node to the root seed
  860 + for(node = 0; node != NodeList.size(); node++)
  861 + {
  862 + if(NodeList[node].valid)
  863 + traverseGraph(node, -1);
  864 + }
  865 +
  866 +
  867 + outfile.close();
  868 +}
  869 +
  870 +void rtsNetwork::ScaleNetwork(float x, float y, float z)
  871 +{
  872 +
  873 + NetworkType::iterator f;
  874 + FilamentType::iterator p;
  875 +
  876 + for(f = network.begin(); f!=network.end(); f++)
  877 + for(p = (*f).begin(); p!= (*f).end(); p++)
  878 + {
  879 + (*p).x = (*p).x * x;
  880 + (*p).y = (*p).y * y;
  881 + (*p).z = (*p).z * z;
  882 + }
  883 +
  884 + calcGraph();
  885 +}
  886 +rtsOBJ rtsNetwork::CreateModel()
  887 +{
  888 + rtsOBJ model;
  889 + /*
  890 + NetworkType::iterator f;
  891 + unsigned int numVerts, v;
  892 + for(f=network.begin(); f!=network.end(); f++)
  893 + {
  894 + model.objBegin(OBJ_LINE_STRIP);
  895 +
  896 + numVerts = (*f).size();
  897 + for(v=0; v<numVerts; v++)
  898 + {
  899 + model.objVertex3f((*f)[v].x, (*f)[v].y, (*f)[v].z);
  900 + }
  901 +
  902 + model.objEnd();
  903 + }
  904 + */
  905 +
  906 + //add all of the vertices to the OBJ
  907 + int num_vertices = NodeList.size();
  908 + int v;
  909 + for(v=0; v<num_vertices; v++)
  910 + {
  911 + model.insertVertexPosition(NodeList[v].p.x, NodeList[v].p.y, NodeList[v].p.z);
  912 + }
  913 +
  914 + //for each edge
  915 + int num_edges = EdgeList.size();
  916 + int e;
  917 + unsigned int* buffer = new unsigned int[10000];
  918 +
  919 + for(e=1; e<num_edges-1; e++)
  920 + {
  921 + buffer[0] = EdgeList[e].v0;
  922 +
  923 + //walk along the fiber
  924 + num_vertices = network[e].size()-1;
  925 + for(v=1; v<num_vertices; v++)
  926 + {
  927 + buffer[v] = model.getNumVertices();
  928 + model.insertVertexPosition(network[e][v].x, network[e][v].y, network[e][v].z);
  929 + }
  930 +
  931 + buffer[v] = EdgeList[e].v1;
  932 +
  933 + model.insertLine(v+1, buffer, NULL, NULL);
  934 + }
  935 +
  936 +
  937 + return model;
  938 +
  939 +}
  940 +
  941 +
  942 +
  943 +void rtsNetwork::calcGraph()
  944 +{
  945 + //make sure that all graph information is cleared
  946 + EdgeList.clear();
  947 + NodeList.clear();
  948 +
  949 + //find the maximum extents of the fiber network
  950 + int numFibers = network.size();
  951 + int f;
  952 + float Max = 0;
  953 + float temp;
  954 + for(f=0; f<numFibers; f++)
  955 + {
  956 + temp = max(network[f].front().x,
  957 + max(network[f].front().y,
  958 + max(network[f].front().z,
  959 + max(network[f].back().x,
  960 + max(network[f].back().y,
  961 + network[f].back().z)))));
  962 + if(temp > Max) Max = temp;
  963 + }
  964 +
  965 + //place each point ID inside the octree
  966 + unsigned int id = 0;
  967 + Octree<unsigned int> tree(OCTREE_SIZE);
  968 + tree.setEmptyValue(UINT_MAX);
  969 + unsigned int v0, v1;
  970 +
  971 +
  972 + for(f=0; f<numFibers; f++)
  973 + {
  974 + //get the appropriate id from the tree
  975 + NodeType v0pos, v1pos;
  976 + v0pos.p = network[f].front();
  977 + v1pos.p = network[f].back();
  978 + v0pos.valid = 1;
  979 + v1pos.valid = 1;
  980 + v0 = tree(v0pos.p.x, v0pos.p.y, v0pos.p.z);
  981 + v1 = tree(v1pos.p.x, v1pos.p.y, v1pos.p.z);
  982 +
  983 + //if the id doesn't exist, add it
  984 + if(v0 == UINT_MAX)
  985 + {
  986 + v0 = id; //set the id of the current vertex
  987 + tree(v0pos.p.x, v0pos.p.y, v0pos.p.z) = id; //add the id to the octree
  988 + NodeList.push_back(v0pos); //add the node position to the node list
  989 +
  990 + id++; //increment the id
  991 + }
  992 + if(v1 == UINT_MAX)
  993 + {
  994 + v1 = id; //set the id of the current vertex
  995 + tree(v1pos.p.x, v1pos.p.y, v1pos.p.z) = id; //add the id to the octree
  996 + NodeList.push_back(v1pos); //add the node position to the node list
  997 +
  998 + id++; //increment the id
  999 + }
  1000 +
  1001 + //add the current edge to the edge list
  1002 + EdgeType e;
  1003 + e.v0 = v0;
  1004 + e.v1 = v1;
  1005 + e.valid = 1;
  1006 + e.length = calcFiberLength(f);
  1007 + EdgeList.push_back(e);
  1008 + //add this edge to each point's edge list
  1009 + NodeList[e.v0].edges.push_back(EdgeList.size() - 1);
  1010 + NodeList[e.v1].edges.push_back(EdgeList.size() - 1);
  1011 +
  1012 + //cout<<"Edge: "<<v0<<"--->"<<v1<<" "<<"w = "<<e.w<<endl;
  1013 + }
  1014 +
  1015 + /*Computes a connectivity matrix based on the edge list and vertices in Attributes*/
  1016 +
  1017 + /*
  1018 + //create the matrix and zero it out
  1019 + Array2D<unsigned int> matrix(NodeList.size(), NodeList.size());
  1020 + unsigned int numNodes = NodeList.size();
  1021 + int x, y;
  1022 + for(x=0; x<numNodes; x++)
  1023 + for(y=0; y<numNodes; y++)
  1024 + matrix(x, y) = 0;
  1025 +
  1026 + //iterate through each edge, assigning values to the connectivity matrix
  1027 + vector<EdgeType>::iterator e;
  1028 + for(e = EdgeList.begin(); e!= EdgeList.end(); e++)
  1029 + {
  1030 + matrix((*e).v0, (*e).v1) = 1;
  1031 + matrix((*e).v1, (*e).v0) = 1;
  1032 + }
  1033 +
  1034 + ConnectivityMatrix = matrix;
  1035 + */
  1036 +}
  1037 +
  1038 +vector<BranchType> rtsNetwork::getFiberAngles(unsigned int fiber)
  1039 +{
  1040 + vector<BranchType> result;
  1041 +
  1042 + int b;
  1043 + vector3D<float> currentTrajectory;
  1044 + vector3D<float> branchTrajectory;
  1045 + unsigned int f;
  1046 +
  1047 + unsigned int node = EdgeList[fiber].v0;
  1048 +
  1049 + int numBranches = NodeList[node].edges.size();
  1050 + currentTrajectory = calcTrajectory(network[fiber], 0).Normalize();
  1051 + //currentTrajectory.print();
  1052 + for(b=0; b<numBranches; b++)
  1053 + {
  1054 + f = NodeList[node].edges[b];
  1055 + if(f != fiber && EdgeList[f].valid)
  1056 + {
  1057 + if(EdgeList[f].v0 == node)
  1058 + branchTrajectory = calcTrajectory(network[f], 0).Normalize();
  1059 + else
  1060 + branchTrajectory = calcTrajectory(network[f], 1).Normalize();
  1061 + //branchTrajectory.print();
  1062 + BranchType newBranch;
  1063 + newBranch.angle = acos((branchTrajectory*(-1))*currentTrajectory)*(180.0/3.14159);
  1064 + newBranch.branch_id = f;
  1065 + result.push_back(newBranch);
  1066 + }
  1067 +
  1068 + }
  1069 +
  1070 + node = EdgeList[fiber].v1;
  1071 +
  1072 + numBranches = NodeList[node].edges.size();
  1073 + currentTrajectory = calcTrajectory(network[fiber], 1).Normalize();
  1074 + //currentTrajectory.print();
  1075 + for(b=0; b<numBranches; b++)
  1076 + {
  1077 + f = NodeList[node].edges[b];
  1078 + if(f != fiber && EdgeList[f].valid)
  1079 + {
  1080 + if(EdgeList[f].v0 == node)
  1081 + branchTrajectory = calcTrajectory(network[f], 0).Normalize();
  1082 + else
  1083 + branchTrajectory = calcTrajectory(network[f], 1).Normalize();
  1084 + //branchTrajectory.print();
  1085 + BranchType newBranch;
  1086 + newBranch.angle = acos((branchTrajectory*(-1))*currentTrajectory)*(180.0/3.14159);
  1087 + newBranch.branch_id = f;
  1088 + result.push_back(newBranch);
  1089 + }
  1090 +
  1091 + }
  1092 +
  1093 + //mark the fiber as traversed
  1094 + EdgeList[fiber].valid = false;
  1095 +
  1096 + return result;
  1097 +}
  1098 +//public
  1099 +void rtsNetwork::CalculateAttributes()
  1100 +{
  1101 + Attributes.TotalFiberLength = calcTotalLength();
  1102 + Attributes.NumFibers = network.size();
  1103 +
  1104 + Attributes.NumPoints = 0;
  1105 + Attributes.TotalVolume = 0;
  1106 + Attributes.NumDisconnectedFibers = 0;
  1107 + Attributes.NumBoundaryFibers = 0;
  1108 + int numFibers = network.size();
  1109 + for(int f=0; f<numFibers; f++)
  1110 + {
  1111 + Attributes.NumPoints += network[f].size();
  1112 + Attributes.TotalVolume += EdgeList[f].volume;
  1113 + if(NodeList[EdgeList[f].v0].edges.size() == 1 ||
  1114 + NodeList[EdgeList[f].v1].edges.size() ==1)
  1115 + if(isBoundaryNode(EdgeList[f].v0) || isBoundaryNode(EdgeList[f].v1))
  1116 + Attributes.NumBoundaryFibers++;
  1117 + else
  1118 + Attributes.NumDisconnectedFibers++;
  1119 +
  1120 + }
  1121 +
  1122 + Attributes.NumBifurcations = 0;
  1123 + int numNodes = NodeList.size();
  1124 + for(int n=0; n<numNodes; n++)
  1125 + if(NodeList[n].edges.size() >= 2)
  1126 + Attributes.NumBifurcations++;
  1127 +
  1128 +
  1129 +}
  1130 +
  1131 +
  1132 +
  1133 +
  1134 +
  1135 +rtsOBJ rtsNetwork::Repair(float max_distance, float cos_angle)
  1136 +{
  1137 + /*This function repairs the network by serching a solid angle around each endpoint
  1138 + for a suitable candidate endpoint to connect to.*/
  1139 +
  1140 + cout<<"repairing...."<<endl;
  1141 +
  1142 + rtsOBJ preview;
  1143 +
  1144 + //create the complete and incomplete connectable lists
  1145 + list<ConnectableType> complete;
  1146 + list<ConnectableType> incomplete;
  1147 +
  1148 + cout<<"Finding Valence-1 Fibers..."<<endl;
  1149 + //go through each fiber, adding ones with valence-1 endpoints to <incomplete>
  1150 + int numFibers = network.size();
  1151 + int f;
  1152 + unsigned int v0;
  1153 + unsigned int v1;
  1154 + int numVerts, v;
  1155 + for(f=0; f<numFibers; f++)
  1156 + {
  1157 + ConnectableType c;
  1158 + v0 = EdgeList[f].v0;
  1159 + v1 = EdgeList[f].v1;
  1160 + //test valence and boundary
  1161 + if(NodeList[v0].edges.size() == 1 && !isBoundaryNode(v0))
  1162 + {
  1163 + c.front = false;
  1164 + }
  1165 + else c.front = true;
  1166 +
  1167 + if(NodeList[v1].edges.size() == 1 && !isBoundaryNode(v1))
  1168 + {
  1169 + c.back = false;
  1170 + }
  1171 + else c.back = true;
  1172 +
  1173 + if(c.front == false || c.back == false)
  1174 + {
  1175 + c.fiber = network[f];
  1176 + c.id = f;
  1177 + incomplete.push_back(c);
  1178 + numVerts = c.fiber.size();
  1179 + //preview.objBegin(OBJ_LINE_STRIP);
  1180 + //for(v=0; v<numVerts; v++)
  1181 + // preview.objVertex3f(c.fiber[v].x, c.fiber[v].y, c.fiber[v].z);
  1182 + //preview.objEnd();
  1183 + }
  1184 + else
  1185 + {
  1186 + c.fiber = network[f];
  1187 + c.id = f;
  1188 + complete.push_back(c);
  1189 + }
  1190 +
  1191 + }
  1192 + cout<<"Valence-1 Fibers: "<<incomplete.size()<<endl;
  1193 +
  1194 + //find all of the possible connections
  1195 + list<ConnectableType>::iterator i;
  1196 + list<ConnectableType>::iterator j;
  1197 + list<ConnectableType>::iterator temp;
  1198 + FilamentType newFiber;
  1199 + bool endpoint0, endpoint1;
  1200 +
  1201 + int iIndex, jIndex;
  1202 +
  1203 + iIndex = 0;
  1204 + for(i=incomplete.begin(); i!=incomplete.end(); i++)
  1205 + {
  1206 + jIndex = iIndex;
  1207 + j = i;
  1208 + while(j != incomplete.end() && i != incomplete.end())
  1209 + {
  1210 + if(i!=j)
  1211 + {
  1212 + if(isConnectable((*i), (*j), endpoint0, endpoint1, max_distance, cos_angle))
  1213 + {
  1214 + ConnectableType newConnectable;
  1215 + newConnectable.fiber = combineFibers((*i).fiber, endpoint0, (*j).fiber, endpoint1);
  1216 + //determine the new connectivity
  1217 + if(endpoint0 == 0)
  1218 + newConnectable.front = (*i).back;
  1219 + else
  1220 + newConnectable.front = (*i).front;
  1221 +
  1222 + if(endpoint1 == 0)
  1223 + newConnectable.back = (*j).back;
  1224 + else
  1225 + newConnectable.back = (*j).front;
  1226 +
  1227 + //remove the previous connectables
  1228 + temp = i;
  1229 + i++;
  1230 + iIndex++;
  1231 + incomplete.erase(temp);
  1232 + temp = j;
  1233 + //this is just in case the fibers are next to each otehr
  1234 + if(j == i)
  1235 + {
  1236 + i++;
  1237 + iIndex++;
  1238 + j = i;
  1239 + jIndex = iIndex;
  1240 + }
  1241 + else
  1242 + {
  1243 + j = i;
  1244 + jIndex = iIndex;
  1245 + }
  1246 + incomplete.erase(temp);
  1247 + //insert the new connectable in the proper list
  1248 + if(newConnectable.front == 0 || newConnectable.back == 0)
  1249 + incomplete.push_back(newConnectable);
  1250 + else
  1251 + complete.push_back(newConnectable);
  1252 +
  1253 +
  1254 +
  1255 + //numVerts = newConnectable.fiber.size();
  1256 + //preview.objBegin(OBJ_LINE_STRIP);
  1257 + //for(v=0; v<numVerts; v++)
  1258 + // preview.objVertex3f(newConnectable.fiber[v].x, newConnectable.fiber[v].y, newConnectable.fiber[v].z);
  1259 + //preview.objEnd();
  1260 + }
  1261 + else
  1262 + {
  1263 + j++;
  1264 + jIndex++;
  1265 + }
  1266 +
  1267 + }
  1268 + else
  1269 + {
  1270 + j++;
  1271 + jIndex++;
  1272 + }
  1273 + //cout<<"i: "<<iIndex<<"j: "<<jIndex<<endl;
  1274 + //cout<<"size of incomplete: "<<incomplete.size()<<endl;
  1275 + }
  1276 + iIndex++;
  1277 + }
  1278 +
  1279 + //reconstruct the fiber list
  1280 + vector<FilamentType> newNetwork;
  1281 + for(i=incomplete.begin(); i!=incomplete.end(); i++)
  1282 + newNetwork.push_back((*i).fiber);
  1283 + for(i=complete.begin(); i!=complete.end(); i++)
  1284 + newNetwork.push_back((*i).fiber);
  1285 +
  1286 + network = newNetwork;
  1287 + calcGraph();
  1288 +
  1289 +
  1290 + //build the model to return
  1291 + preview = CreateModel();
  1292 +
  1293 + return preview;
  1294 +
  1295 +}
  1296 +void rtsNetwork::printFiberStats(unsigned int fiber)
  1297 +{
  1298 + /*
  1299 + cout<<"-----------------------------------------------------"<<endl;
  1300 + cout<<"Fiber nodes:"<<endl;
  1301 + int numVerts = network[fiber].size();
  1302 + for(int v=0; v<numVerts; v++)
  1303 + {
  1304 + cout<<network[fiber][v].x<<","<<network[fiber][v].y<<","<<network[fiber][v].z<<endl;
  1305 + }
  1306 + */
  1307 + cout<<"------------------------------------------------------"<<endl;
  1308 + cout<<"Selected node: "<<fiber<<endl;
  1309 +
  1310 +
  1311 + int b;
  1312 + vector3D<float> currentTrajectory;
  1313 + vector3D<float> branchTrajectory;
  1314 + unsigned int f;
  1315 +
  1316 + //get the list of angles
  1317 + vector<BranchType> angles = getFiberAngles(fiber);
  1318 +
  1319 + unsigned int node = EdgeList[fiber].v0;
  1320 + int numBranches = NodeList[node].edges.size()-1;
  1321 + cout<<"V0 Valence: "<<getConnections(node).size()<<endl;
  1322 +
  1323 + for(b=0; b<numBranches; b++)
  1324 + {
  1325 + cout<<" ["<<angles[b].branch_id<<"] "<<angles[b].angle<<(char)248<<endl;
  1326 + }
  1327 +
  1328 +
  1329 + node = EdgeList[fiber].v1;
  1330 + cout<<"V1 Valence: "<<getConnections(node).size()<<endl;
  1331 + numBranches = angles.size();
  1332 + for(; b<numBranches; b++)
  1333 + {
  1334 + cout<<" ["<<angles[b].branch_id<<"] "<<angles[b].angle<<(char)248<<endl;
  1335 + }
  1336 +
  1337 + reset();
  1338 +
  1339 + cout<<"End Points: ["<<NodeList[EdgeList[fiber].v0].p.x<<","
  1340 + <<NodeList[EdgeList[fiber].v0].p.y<<","
  1341 + <<NodeList[EdgeList[fiber].v0].p.z<<"]"
  1342 + <<"["<<NodeList[EdgeList[fiber].v1].p.x<<","
  1343 + <<NodeList[EdgeList[fiber].v1].p.y<<","
  1344 + <<NodeList[EdgeList[fiber].v1].p.z<<"]"<<endl;
  1345 + cout<<"Fiber Length: "<<calcFiberLength(fiber)<<"um"<<endl;
  1346 + cout<<"Average Radius: "<<EdgeList[fiber].avg_radius<<"um"<<endl;
  1347 + cout<<"Min Radius: "<<EdgeList[fiber].min_radius<<"um"<<endl;
  1348 + cout<<"Max Radius: "<<EdgeList[fiber].max_radius<<"um"<<endl;
  1349 + cout<<"Fiber Volume: "<<EdgeList[fiber].volume<<"um^3"<<endl;
  1350 + cout<<"Maximum Bend: "<<calcFiberBend(fiber)<<endl;
  1351 + cout<<"------------------------------------------------------"<<endl;
  1352 +
  1353 + int numVertices = network[fiber].size();
  1354 + //for(int v=0; v<numVertices; v++)
  1355 + // cout<<network[fiber][v].x<<","<<network[fiber][v].y<<","<<network[fiber][v].z<<endl;
  1356 +
  1357 +
  1358 +}
  1359 +void rtsNetwork::Clean(float degenerate_length = 5, float barb_length = 30)
  1360 +{
  1361 + int changes;
  1362 + do
  1363 + {
  1364 + changes = 0;
  1365 + int degen = cleanDegenerateEdges(degenerate_length);
  1366 + cout<<"Degen: "<<degen<<endl;
  1367 + changes += degen;
  1368 +
  1369 + int barbs = cleanBarbs(barb_length);
  1370 + cout<<"Barbs: "<<barbs<<endl;
  1371 + changes += barbs;
  1372 +
  1373 + int redundant = cleanRedundantEdges();
  1374 + cout<<"Redundant: "<<redundant<<endl;
  1375 + changes += redundant;
  1376 +
  1377 + }while(changes != 0);
  1378 +
  1379 +
  1380 +}
  1381 +void rtsNetwork::ReMesh(float resample_length)
  1382 +{
  1383 + //Resample the skeleton at the given frequency
  1384 + NetworkType newNetwork;
  1385 +
  1386 + int numFibers = network.size();
  1387 + int f;
  1388 + int numVerts, v;
  1389 + FilamentType newFiber;
  1390 + vector3D<float> distanceVector;
  1391 + point3D<float> prevPoint;
  1392 + for(f=0; f<numFibers; f++)
  1393 + {
  1394 + newFiber.clear();
  1395 + numVerts = network[f].size();
  1396 + newFiber.push_back(network[f][0]);
  1397 + prevPoint = network[f][0];
  1398 + for(v=1; v<numVerts-1; v++)
  1399 + {
  1400 + distanceVector = toTissue(network[f][v]) - toTissue(prevPoint);
  1401 + if(distanceVector.Length() >= resample_length)
  1402 + {
  1403 + newFiber.push_back(network[f][v]);
  1404 + prevPoint = network[f][v];
  1405 + }
  1406 + }
  1407 +
  1408 + //deal with the last vertex
  1409 + //newFiber.push_back(network[f][v]);
  1410 +
  1411 + distanceVector = toTissue(network[f][v]) - toTissue(prevPoint);
  1412 + if(distanceVector.Length() >= resample_length || newFiber.size() == 1)
  1413 + {
  1414 + newFiber.push_back(network[f][v]);
  1415 + }
  1416 + else
  1417 + {
  1418 + //change the last point
  1419 + newFiber[newFiber.size() - 1] = network[f][v];
  1420 + }
  1421 +
  1422 +
  1423 + //cout<<"old: "<<network[f].size()<<endl;
  1424 + //cout<<"new: "<<newFiber.size()<<endl;
  1425 + newNetwork.push_back(newFiber);
  1426 + }
  1427 +
  1428 + //replace the network
  1429 + //cout<<"old network: "<<network.size()<<endl;
  1430 + //cout<<"new network: "<<newNetwork.size()<<endl;
  1431 + network = newNetwork;
  1432 + calcGraph();
  1433 +
  1434 +}
  1435 +void rtsNetwork::SaveAngles(const char *filename)
  1436 +{
  1437 + ofstream outfile;
  1438 + outfile.open(filename);
  1439 +
  1440 + int errors = 0;
  1441 +
  1442 + //get the list of angles for each fiber
  1443 + unsigned int f;
  1444 + int numFibers = EdgeList.size();
  1445 + for(f=0; f<numFibers; f++)
  1446 + {
  1447 + vector<BranchType> angles = getFiberAngles(f);
  1448 + for(int a=0; a<angles.size(); a++)
  1449 + {
  1450 + outfile<<angles[a].angle<<endl;
  1451 +
  1452 + //print out errors
  1453 + if(angles[a].angle >179 && angles[a].angle < 181)
  1454 + {
  1455 + //cout<<"ERROR"<<endl;
  1456 + //printFiberStats(f);
  1457 + errors++;
  1458 + }
  1459 + if(angles[a].angle >90 && angles[a].angle < 90.01)
  1460 + {
  1461 + //cout<<"ERROR"<<endl;
  1462 + //printFiberStats(f);
  1463 + errors++;
  1464 + }
  1465 + if(angles[a].angle < 0)
  1466 + {
  1467 + //cout<<"ERROR"<<endl;
  1468 + //printFiberStats(f);
  1469 + errors++;
  1470 + }
  1471 + }
  1472 + }
  1473 +
  1474 + cout<<"ERRORS: "<<errors<<endl;
  1475 +
  1476 + outfile.close();
  1477 +
  1478 + reset();
  1479 +
  1480 +}
  1481 +void rtsNetwork::SaveBends(const char *filename)
  1482 +{
  1483 + ofstream outfile;
  1484 + outfile.open(filename);
  1485 +
  1486 + int numFibers = EdgeList.size();
  1487 + for(int f = 0; f<numFibers; f++)
  1488 + if(network[f].size() >2)
  1489 + outfile<<calcFiberBend(f)<<endl;
  1490 +
  1491 + outfile.close();
  1492 +
  1493 +}
  1494 +
  1495 +void rtsNetwork::SaveLengths(const char *filename)
  1496 +{
  1497 + ofstream outfile;
  1498 + outfile.open(filename);
  1499 +
  1500 + int numFibers = EdgeList.size();
  1501 + for(int f = 0; f<numFibers; f++)
  1502 + if(network[f].size() >2)
  1503 + outfile<<calcFiberLength(f)<<endl;
  1504 +
  1505 + outfile.close();
  1506 +}
  1507 +
  1508 +void rtsNetwork::SaveMathematicaGraph(const char* filename)
  1509 +{
  1510 + ofstream outfile;
  1511 + outfile.open(filename);
  1512 +
  1513 + outfile<<"<< Combinatorica`"<<endl;
  1514 + outfile<<"<< GraphUtilities`"<<endl;
  1515 + outfile<<"e = {";
  1516 +
  1517 + int numEdges = EdgeList.size();
  1518 + int e;
  1519 +
  1520 + for(e=0; e<numEdges-1; e++)
  1521 + {
  1522 + outfile<<""<<EdgeList[e].v0+1<<"->"<<EdgeList[e].v1+1<<",";
  1523 + }
  1524 + outfile<<""<<EdgeList[e].v0+1<<"->"<<EdgeList[e].v1+1<<"};";
  1525 +
  1526 + //assign weights
  1527 + outfile<<endl<<"w = {";
  1528 + for(e=0; e<numEdges-1; e++)
  1529 + {
  1530 + outfile<<calcFiberLength(e)<<", ";
  1531 + }
  1532 + outfile<<calcFiberLength(e)<<"};";
  1533 +
  1534 + int numVertices = NodeList.size();
  1535 + int v;
  1536 + outfile<<endl<<"v = {";
  1537 + for(v=0; v<numVertices-1; v++)
  1538 + {
  1539 + //outfile<<"{{"<<NodeList[v].p.x<<","<<NodeList[v].p.y<<"}}, ";
  1540 + outfile<<"{"<<NodeList[v].p.x<<","<<NodeList[v].p.y<<","<<NodeList[v].p.z<<"}, ";
  1541 + }
  1542 + //outfile<<"{{"<<NodeList[v].p.x<<","<<NodeList[v].p.y<<"}}};";
  1543 + outfile<<"{"<<NodeList[v].p.x<<","<<NodeList[v].p.y<<","<<NodeList[v].p.z<<"}};";
  1544 +
  1545 +
  1546 + outfile.close();
  1547 +}
  1548 +
  1549 +void rtsNetwork::SaveMathematicaNodeDistances(const char* filename)
  1550 +{
  1551 + ofstream outfile;
  1552 + outfile.open(filename);
  1553 +
  1554 + //for each node, save the distance between all other nodes
  1555 + int numNodes = NodeList.size();
  1556 + int i, j;
  1557 + vector3D<float> distance;
  1558 + outfile<<"d = {";
  1559 + for(i=0; i<numNodes-1; i++)
  1560 + {
  1561 + outfile<<"{";
  1562 + for(j=0; j<numNodes-1; j++)
  1563 + {
  1564 + distance = toTissue(NodeList[i].p) - toTissue(NodeList[j].p);
  1565 + outfile<<distance.Length()<<",";
  1566 + }
  1567 + distance = toTissue(NodeList[i].p) - toTissue(NodeList[j].p);
  1568 + outfile<<distance.Length()<<"},";
  1569 + }
  1570 + outfile<<"{";
  1571 + for(j=0; j<numNodes-1; j++)
  1572 + {
  1573 + distance = toTissue(NodeList[i].p) - toTissue(NodeList[j].p);
  1574 + outfile<<distance.Length()<<",";
  1575 + }
  1576 + distance = toTissue(NodeList[i].p) - toTissue(NodeList[j].p);
  1577 + outfile<<distance.Length()<<"}};";
  1578 +
  1579 + outfile.close();
  1580 +
  1581 +
  1582 +}
  1583 +void rtsNetwork::RemoveTerminalComponents()
  1584 +{
  1585 + int removed;
  1586 + do{
  1587 + removed = EdgeList.size();
  1588 + //removes fibers that are shorter than the specified length
  1589 + NetworkType newNetwork;
  1590 +
  1591 + unsigned int numEdges, e;
  1592 + numEdges = EdgeList.size();
  1593 + unsigned int numVertices, v;
  1594 +
  1595 + for(e=0; e<numEdges; e++)
  1596 + {
  1597 + //if the fiber is not an end fiber (one vertex has valence 1)
  1598 + if(getConnections(EdgeList[e].v0).size() != 1 && getConnections(EdgeList[e].v1).size() != 1)
  1599 + {
  1600 + newNetwork.push_back(network[e]);
  1601 + removed--;
  1602 +
  1603 + }
  1604 +
  1605 + }
  1606 +
  1607 + network.clear();
  1608 + network = newNetwork;
  1609 +
  1610 + Clean();
  1611 + calcGraph();
  1612 + }while(removed != 0);
  1613 +
  1614 +}
  1615 +
  1616 +void rtsNetwork::RemoveBoundaryComponents()
  1617 +{
  1618 + int removed;
  1619 + do{
  1620 + removed = EdgeList.size();
  1621 + //removes fibers that are shorter than the specified length
  1622 + NetworkType newNetwork;
  1623 +
  1624 + unsigned int numEdges, e;
  1625 + numEdges = EdgeList.size();
  1626 + unsigned int numVertices, v;
  1627 +
  1628 + for(e=0; e<numEdges; e++)
  1629 + {
  1630 + //if the fiber is not an end fiber (one vertex has valence 1)
  1631 + if(getConnections(EdgeList[e].v0).size() != 1 && getConnections(EdgeList[e].v1).size() != 1)
  1632 + {
  1633 + newNetwork.push_back(network[e]);
  1634 + removed--;
  1635 +
  1636 + }
  1637 + //if the fiber is an end fiber
  1638 + else if(!isBoundaryNode(EdgeList[e].v0) && !isBoundaryNode(EdgeList[e].v1))
  1639 + {
  1640 + newNetwork.push_back(network[e]);
  1641 + removed--;
  1642 + }
  1643 +
  1644 +
  1645 + }
  1646 +
  1647 + network.clear();
  1648 + network = newNetwork;
  1649 +
  1650 + Clean();
  1651 + calcGraph();
  1652 + }while(removed != 0);
  1653 +
  1654 +}
  1655 +void rtsNetwork::GetRadiusFromVolume(const char *filename, unsigned int threshold, unsigned int range = 2)
  1656 +{
  1657 + //load the volume image
  1658 + VOLType::Pointer volume = LoadVOL(filename);
  1659 + VOLType::SpacingType spacing;
  1660 + // Note: measurement units (e.g., mm, inches, etc.) are defined by the application.
  1661 + spacing[0] = 0.86; // spacing along X
  1662 + spacing[1] = 1.0; // spacing along Y
  1663 + spacing[2] = 1.4; // spacing along Z
  1664 + volume->SetSpacing(spacing);
  1665 + SaveSlice(volume, 20, "original.bmp");
  1666 + //volume->ReleaseDataFlagOn();
  1667 +
  1668 +/*
  1669 + cout<<"Expanding Image..."<<endl;
  1670 + typedef itk::ExpandImageFilter<VOLType, VOLType> ResizeFilterType;
  1671 + ResizeFilterType::Pointer resizeFilter = ResizeFilterType::New();
  1672 + resizeFilter->SetExpandFactors(resample);
  1673 + resizeFilter->SetInput(volume);
  1674 + resizeFilter->Update();
  1675 + VOLType::Pointer resizedImage = resizeFilter->GetOutput();
  1676 + SaveSlice(resizedImage, 20, "resized.bmp");
  1677 + cout<<"done."<<endl;
  1678 +*/
  1679 +
  1680 + typedef itk::DiscreteGaussianImageFilter<VOLType, FloatType> BlurFilterType;
  1681 + BlurFilterType::Pointer blurFilter = BlurFilterType::New();
  1682 + blurFilter->SetUseImageSpacingOn();
  1683 + float variance[3] = {0.61, 1.5, 0.61};
  1684 + blurFilter->SetVariance(variance);
  1685 + blurFilter->SetMaximumKernelWidth(8);
  1686 + blurFilter->SetInput(volume);
  1687 + try
  1688 + {
  1689 + blurFilter->Update();
  1690 + }
  1691 + catch(itk::ExceptionObject & exp)
  1692 + {
  1693 + std::cout<<exp<<std::endl;
  1694 + }
  1695 + FloatType::Pointer blurredImage = blurFilter->GetOutput();
  1696 +
  1697 + typedef itk::CastImageFilter<FloatType, VOLType> CastingFilterType;
  1698 + CastingFilterType::Pointer castFilter = CastingFilterType::New();
  1699 + castFilter->SetInput(blurredImage);
  1700 + castFilter->Update();
  1701 + VOLType::Pointer resizedImage = castFilter->GetOutput();
  1702 +
  1703 + SaveSlice(resizedImage, 20, "resized.bmp");
  1704 +
  1705 +
  1706 + //threshold the input image
  1707 + cout<<"Thresholding Volume..."<<endl;
  1708 + typedef itk::BinaryThresholdImageFilter<VOLType, VOLType> ThresholdFilterType;
  1709 + ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
  1710 + thresholdFilter->SetInsideValue(255);
  1711 + thresholdFilter->SetOutsideValue(0);
  1712 + thresholdFilter->SetLowerThreshold(threshold);
  1713 + thresholdFilter->SetUpperThreshold(255);
  1714 + thresholdFilter->SetInput(resizedImage);
  1715 + try
  1716 + {
  1717 + thresholdFilter->Update();
  1718 + }
  1719 + catch(itk::ExceptionObject & exp)
  1720 + {
  1721 + std::cout<<exp<<std::endl;
  1722 + }
  1723 + VOLType::Pointer thresholdImage = thresholdFilter->GetOutput();
  1724 + //volume->ReleaseData();
  1725 + //thresholdFilter->ReleaseDataFlagOn();
  1726 +
  1727 + SaveSlice(thresholdImage, 20, "threshold.bmp");
  1728 +
  1729 + cout<<"done."<<endl;
  1730 +
  1731 +
  1732 + cout<<"Computing Distance Field..."<<endl;
  1733 + //create the distance transform filter
  1734 + typedef itk::DanielssonDistanceMapImageFilter<VOLType, FloatType> DistanceFilterType;
  1735 + DistanceFilterType::Pointer distanceFilter = DistanceFilterType::New();
  1736 + distanceFilter->SetInput(thresholdImage);
  1737 + distanceFilter->UseImageSpacingOn();
  1738 +
  1739 + try
  1740 + {
  1741 + distanceFilter->Update();
  1742 + }
  1743 + catch(itk::ExceptionObject & exp)
  1744 + {
  1745 + std::cout<<exp<<std::endl;
  1746 + }
  1747 + //SaveSlice(distanceFilter->GetOutput(), 20, "distance.bmp");
  1748 + FloatType::Pointer distanceMap = distanceFilter->GetOutput();
  1749 + //SaveFloatRAW(distanceMap, "distanceMap.raw");
  1750 + cout<<"done."<<endl;
  1751 +
  1752 + cout<<"Computing Radii..."<<endl;
  1753 +
  1754 +
  1755 +
  1756 + //create a neighborhood iterator
  1757 + typedef itk::ConstNeighborhoodIterator<FloatType> NeighborhoodIteratorType;
  1758 + NeighborhoodIteratorType::RadiusType radius;
  1759 + radius.Fill(range);
  1760 + NeighborhoodIteratorType i(radius, distanceMap, distanceMap->GetBufferedRegion());
  1761 + vector<NeighborhoodIteratorType::OffsetType> OffsetVector;
  1762 + OffsetVector.resize((range*2+1)*(range*2+1)*(range*2+1));
  1763 + int x, y, z, j;
  1764 + j=0;
  1765 + for(x=-range; x<=range; x++)
  1766 + for(y=-range; y<=range; y++)
  1767 + for(z=-range; z<=range; z++)
  1768 + {
  1769 + OffsetVector[j][0]=x;
  1770 + OffsetVector[j][1]=y;
  1771 + OffsetVector[j][2]=z;
  1772 + //cout<<"offset: "<<OffsetVector[j]<<endl;
  1773 + j++;
  1774 + }
  1775 +
  1776 +
  1777 + int numFibers = network.size();
  1778 + int f, numVertices, v;
  1779 + point3D<float> position;
  1780 + float total_radius, near_radius, total_volume, max_radius, min_radius;
  1781 + FloatType::IndexType pixelIndex;
  1782 + float prev_radius;
  1783 + point3D<float> p0, p1;
  1784 + float height;
  1785 + for(f=0; f<numFibers; f++)
  1786 + {
  1787 + total_radius = 0;
  1788 + total_volume = 0;
  1789 + max_radius = 0;
  1790 + min_radius = 999;
  1791 + numVertices = network[f].size();
  1792 + for(v=0; v<numVertices; v++)
  1793 + {
  1794 + position = network[f][v];
  1795 + //pixelIndex[0] = position.x*resample;
  1796 + //pixelIndex[1] = position.y*resample;
  1797 + //pixelIndex[2] = position.z*resample;
  1798 + pixelIndex[0] = position.x;
  1799 + pixelIndex[1] = position.y;
  1800 + pixelIndex[2] = position.z;
  1801 + i.SetLocation(pixelIndex);
  1802 + near_radius = 0;
  1803 + for(j=0; j<OffsetVector.size(); j++)
  1804 + {
  1805 + near_radius = max(near_radius, (float)i.GetPixel(OffsetVector[j]));
  1806 + //cout<<(float)i.GetPixel(OffsetVector[j])<<endl;
  1807 + //cout<<"j = "<<j<<" "<<i.GetPixel(OffsetVector[j])<<endl;
  1808 + }
  1809 + //cout<<"v = "<<v<<" "<<near_radius<<endl;
  1810 + if(near_radius > max_radius)
  1811 + max_radius = near_radius;
  1812 + if(near_radius < min_radius)
  1813 + min_radius = near_radius;
  1814 + total_radius += near_radius;
  1815 + if(v>0)
  1816 + {
  1817 + //compute the volume of the segment
  1818 + p0 = toTissue(network[f][v-1]);
  1819 + p1 = toTissue(network[f][v]);
  1820 + height = (p1 - p0).Length();
  1821 + total_volume += ((3.14159*height)/3.0)*(prev_radius * prev_radius + near_radius*near_radius + prev_radius*near_radius);
  1822 +
  1823 + }
  1824 + prev_radius = near_radius;
  1825 + }
  1826 + EdgeList[f].avg_radius = total_radius/numVertices;
  1827 + EdgeList[f].min_radius = min_radius;
  1828 + EdgeList[f].max_radius = max_radius;
  1829 + EdgeList[f].volume = total_volume;
  1830 + }
  1831 +
  1832 + cout<<"done."<<endl;
  1833 +
  1834 +}
  1835 +void rtsNetwork::GetRadiusFromDistanceMap(const char *filename, int range = 2)
  1836 +{
  1837 + //load the volume image
  1838 + FloatType::Pointer distanceMap = LoadRAWFloat(filename, 256, 256, 256);
  1839 +
  1840 + //create a neighborhood iterator
  1841 + typedef itk::ConstNeighborhoodIterator<FloatType> NeighborhoodIteratorType;
  1842 + NeighborhoodIteratorType::RadiusType radius;
  1843 + radius.Fill(range);
  1844 + NeighborhoodIteratorType i(radius, distanceMap, distanceMap->GetRequestedRegion());
  1845 + vector<NeighborhoodIteratorType::OffsetType> OffsetVector;
  1846 + OffsetVector.resize((range*2+1)*(range*2+1)*(range*2+1));
  1847 + int x, y, z, j;
  1848 + j=0;
  1849 + for(x=-range; x<=range; x++)
  1850 + for(y=-range; y<=range; y++)
  1851 + for(z=-range; z<=range; z++)
  1852 + {
  1853 + OffsetVector[j][0]=x;
  1854 + OffsetVector[j][1]=y;
  1855 + OffsetVector[j][2]=z;
  1856 + //cout<<"offset: "<<OffsetVector[j]<<endl;
  1857 + j++;
  1858 + }
  1859 +
  1860 +
  1861 +
  1862 + cout<<"Computing Radii..."<<endl;
  1863 + int numFibers = network.size();
  1864 + int f, numVertices, v;
  1865 + point3D<float> position;
  1866 + float total_radius, max_radius;
  1867 + FloatType::IndexType pixelIndex;
  1868 + for(f=0; f<numFibers; f++)
  1869 + {
  1870 + total_radius = 0;
  1871 + numVertices = network[f].size();
  1872 + for(v=0; v<numVertices; v++)
  1873 + {
  1874 + position = network[f][v];
  1875 + pixelIndex[0] = position.x;
  1876 + pixelIndex[1] = position.y;
  1877 + pixelIndex[2] = position.z;
  1878 + i.SetLocation(pixelIndex);
  1879 + max_radius = 0;
  1880 + for(j=0; j<OffsetVector.size(); j++)
  1881 + {
  1882 + max_radius = max(max_radius, (float)i.GetPixel(OffsetVector[j]));
  1883 + //cout<<"j = "<<j<<" "<<i.GetPixel(OffsetVector[j])<<endl;
  1884 + }
  1885 +
  1886 + total_radius += max_radius;
  1887 + }
  1888 + EdgeList[f].avg_radius = total_radius/numVertices;
  1889 + }
  1890 +
  1891 + cout<<"done."<<endl;
  1892 +
  1893 +}
  1894 +
  1895 +point3D<float> rtsNetwork::GetFiberRadius(unsigned int fiber)
  1896 +{
  1897 + point3D<float> result;
  1898 + result.x = EdgeList[fiber].min_radius;
  1899 + result.y = EdgeList[fiber].max_radius;
  1900 + result.z = EdgeList[fiber].avg_radius;
  1901 + return result;
  1902 +}
0 1903 \ No newline at end of file
... ...
rtsOctree.h 0 → 100755
  1 +++ a/rtsOctree.h
  1 +#ifndef RTSOCTREE_H
  2 +#define RTSOCTREE_H
  3 +
  4 +#include "rtspoint3D.h"
  5 +
  6 +template <class T>
  7 +struct octree_node
  8 +{
  9 + unsigned int center;
  10 + T data;
  11 + octree_node* ppp;
  12 + octree_node* ppn;
  13 + octree_node* pnp;
  14 + octree_node* pnn;
  15 + octree_node* npp;
  16 + octree_node* npn;
  17 + octree_node* nnp;
  18 + octree_node* nnn;
  19 + octree_node();
  20 +}
  21 +
  22 +template <class T>
  23 +octree_node::octree_node()
  24 +{
  25 + ppp = NULL;
  26 + ppn = NULL;
  27 + pnp = NULL;
  28 + pnn = NULL;
  29 + npp = NULL;
  30 + npn = NULL;
  31 + nnp = NULL;
  32 + nnn = NULL;
  33 +}
  34 +
  35 +
  36 +template <class T>
  37 +class rtsOctree
  38 +{
  39 +public:
  40 + unsigned int num_leaves;
  41 + point3D<unsigned int> center;
  42 + octree_node* root;
  43 + rtsOctree(unsigned int sizex, unsigned int sizey, unsigned int sizez);
  44 + void Insert(unsigned int x, unsigned int y, unsigned int z, T value);
  45 +
  46 +};
  47 +
  48 +template <class T>
  49 +rtsOctree<T>::rtsOctree(unsigned int sizex, unsigned int sizey, unsigned int sizez)
  50 +{
  51 + center.x = sizex/2;
  52 + center.y = sizey/2;
  53 + center.z = sizez/2;
  54 + root = new octree_node();
  55 + num_leaves = 1;
  56 +}
  57 +
  58 +template <class T>
  59 +void rtsOctree<T>::Insert(unsigned int x, unsigned int y, unsigned int z, T value)
  60 +{
  61 + point3D<unsigned int> current;
  62 + point3D<unsigned int> destination(x, y, z);
  63 + while(!(current == destination))
  64 + {
  65 +
  66 +
  67 +
  68 +
  69 +
  70 +#endif
0 71 \ No newline at end of file
... ...
rtsParser.h 0 → 100755
  1 +++ a/rtsParser.h
  1 +#include<vector>
  2 +#include<fstream>
  3 +
  4 +using namespace std;
  5 +
  6 +//define the parameter data types
  7 +#define RTS_ERROR 0
  8 +#define RTS_OK 1
  9 +
  10 +
  11 +#define RTS_STRING 2
  12 +#define RTS_DOUBLE 3
  13 +
  14 +struct parameter
  15 +{
  16 + //name of the specified parameter
  17 + char* name;
  18 + int ID;
  19 + char* char_value;
  20 + double double_value;
  21 + int type;
  22 + bool set;
  23 +};
  24 +
  25 +class rtsParser
  26 +{
  27 +private:
  28 + vector<parameter> parameters;
  29 + vector<parameter>::iterator p_SearchParams(char* name);
  30 + bool p_SetParameter(char* name, char* value);
  31 + bool p_SetParameter(char* name, double value);
  32 +
  33 +public:
  34 + void AddParameter(char* name, int ID, int type);
  35 + void AddParameter(char* name, int type);
  36 + void OutputParameters();
  37 + void Load(const char* filename);
  38 + int GetDoubleParameter(char* name, double& result);
  39 + int GetStringParameter(char* name, char*& result);
  40 +};
  41 +
  42 +vector<parameter>::iterator rtsParser::p_SearchParams(char *name)
  43 +{
  44 + //search the parameters vector for a name matching the input parameter
  45 +
  46 + vector<parameter>::iterator iter;
  47 +
  48 + //run through the vector
  49 + for(iter = parameters.begin(); iter != parameters.end(); iter++)
  50 + {
  51 + //if the name matches the parameter name, return the iterator
  52 + if(strcmp((*iter).name, name) == 0)
  53 + return iter;
  54 + }
  55 +
  56 + return parameters.end();
  57 +}
  58 +
  59 +bool rtsParser::p_SetParameter(char *name, char *value)
  60 +{
  61 + //sets the character value of a parameter
  62 +
  63 + //first, find the parameter
  64 + vector<parameter>::iterator iter;
  65 + for(iter = parameters.begin(); iter != parameters.end(); iter++)
  66 + {
  67 + //if the parameter is found
  68 + if(strcmp((*iter).name, name) == 0)
  69 + {
  70 + //if the parameter type is wrong, return false
  71 + if((*iter).type != RTS_STRING)
  72 + return false;
  73 + //otherwise, set the parameter value
  74 + (*iter).char_value = value;
  75 + (*iter).set = true;
  76 + return true;
  77 + }
  78 + }
  79 + //if the parameter was not found, return false
  80 + return false;
  81 +}
  82 +
  83 +bool rtsParser::p_SetParameter(char *name, double value)
  84 +{
  85 + //sets the character value of a parameter
  86 +
  87 + //first, find the parameter
  88 + vector<parameter>::iterator iter;
  89 + for(iter = parameters.begin(); iter != parameters.end(); iter++)
  90 + {
  91 + //if the parameter is found
  92 + if(strcmp((*iter).name, name) == 0)
  93 + {
  94 + //if the parameter type is wrong, return false
  95 + if((*iter).type != RTS_DOUBLE)
  96 + return false;
  97 + //otherwise, set the parameter value
  98 + (*iter).double_value = value;
  99 + (*iter).set = true;
  100 + return true;
  101 + }
  102 + }
  103 + //if the parameter was not found, return false
  104 + return false;
  105 +}
  106 +
  107 +void rtsParser::Load(const char* filename)
  108 +{
  109 + //loads a parameter file and fills the list with the parameter values
  110 +
  111 + //create an input stream and load the file
  112 + ifstream infile;
  113 + infile.open(filename);
  114 +
  115 + //create temporary variables to store values
  116 + char param_name[1000];
  117 + vector<parameter>::iterator iter;
  118 +
  119 + //for each line in the parameter file
  120 + while(!infile.eof())
  121 + {
  122 + //get the parameter name token
  123 + infile.get(param_name, 100, ' ');
  124 + //find the proper parameter in the parameter list
  125 + iter = p_SearchParams(param_name);
  126 +
  127 + //test to make sure the parameter was found
  128 + if(iter == parameters.end())
  129 + {
  130 + cout<<"Error, could not find parameter: "<<param_name<<endl;
  131 + exit(1);
  132 + }
  133 +
  134 + //cout<<"infile.get: "<<param_name<<endl;
  135 +
  136 + //get the equal sign
  137 + char equals;
  138 + infile>>equals;
  139 +
  140 + //cout<<"infile>>equals: "<<equals<<endl;
  141 +
  142 +
  143 + //create space for the string
  144 + char* temp_value_string= new char[500];
  145 + infile.get(temp_value_string, 500);
  146 +
  147 + //cout<<"temp_value_string: "<<temp_value_string<<endl;
  148 +
  149 + if((*iter).type == RTS_STRING)
  150 + {
  151 + //remove the quotation marks
  152 + temp_value_string = strchr(temp_value_string, '"');
  153 + if(temp_value_string != NULL)
  154 + {
  155 + temp_value_string++;
  156 + char* end = strrchr(temp_value_string, '"');
  157 + *end = 0;
  158 +
  159 + //set the parameter
  160 + (*iter).char_value = temp_value_string;
  161 + (*iter).set = true;
  162 + }
  163 + else
  164 + {
  165 + cout<<"Error, no quotes in parameter value: "<<(*iter).name<<endl;
  166 + }
  167 + }
  168 + else if((*iter).type == RTS_DOUBLE)
  169 + {
  170 + (*iter).double_value = atof(temp_value_string);
  171 + (*iter).set = true;
  172 + }
  173 +
  174 +
  175 +
  176 +
  177 + //get the final line character
  178 + //char temp[2];
  179 + //infile.get(temp, 2);
  180 + //skip to the next line
  181 + infile.getline(param_name, 1000);
  182 + //}
  183 +
  184 + }
  185 +
  186 +}
  187 +
  188 +int rtsParser::GetDoubleParameter(char* name, double& result)
  189 +{
  190 + //find the appropriate parameter
  191 + vector<parameter>::iterator iter = p_SearchParams(name);
  192 +
  193 + //check for errors
  194 + if(iter == parameters.end())
  195 + {
  196 + cout<<"Error finding parameter: "<<name<<endl;
  197 + return RTS_ERROR;
  198 + }
  199 + else if((*iter).type != RTS_DOUBLE)
  200 + {
  201 + cout<<"Invalid data type for parameter: "<<name<<endl;
  202 + return RTS_ERROR;
  203 + }
  204 + else if(!(*iter).set)
  205 + {
  206 + cout<<"Parameter not set during load: "<<name<<endl;
  207 + return RTS_ERROR;
  208 + }
  209 +
  210 + //return the appropriate value as a reference parameter
  211 + result = (*iter).double_value;
  212 + return RTS_OK;
  213 +}
  214 +
  215 +int rtsParser::GetStringParameter(char* name, char*& result)
  216 +{
  217 + //find the appropriate parameter
  218 + vector<parameter>::iterator iter = p_SearchParams(name);
  219 +
  220 + //check for errors
  221 + if(iter == parameters.end())
  222 + {
  223 + cout<<"Error finding parameter: "<<name<<endl;
  224 + return RTS_ERROR;
  225 + }
  226 + else if((*iter).type != RTS_STRING)
  227 + {
  228 + cout<<"Invalid data type for parameter: "<<name<<endl;
  229 + return RTS_ERROR;
  230 + }
  231 + else if(!(*iter).set)
  232 + {
  233 + cout<<"Parameter not set during load: "<<name<<endl;
  234 + return RTS_ERROR;
  235 + }
  236 +
  237 + //return the appropriate value as a reference parameter
  238 + result = (*iter).char_value;
  239 + return RTS_OK;
  240 +}
  241 +
  242 +void rtsParser::AddParameter(char *name, int ID, int type)
  243 +{
  244 + //this function adds an expected parameter to the parser
  245 +
  246 + //create a new parameter and store the user-defined variables
  247 + parameter new_param;
  248 + new_param.name = name;
  249 + new_param.ID = ID;
  250 + new_param.type = type;
  251 + new_param.set = false;
  252 +
  253 + //add the parameter to the parameter list
  254 + parameters.push_back(new_param);
  255 +}
  256 +
  257 +void rtsParser::AddParameter(char* name, int type)
  258 +{
  259 + AddParameter(name, 0, type);
  260 +}
  261 +
  262 +void rtsParser::OutputParameters()
  263 +{
  264 + vector<parameter>::iterator iter;
  265 + for(iter = parameters.begin(); iter!= parameters.end(); iter++)
  266 + {
  267 + //test to see if the parameter was set by the file
  268 + if((*iter).set)
  269 + {
  270 + cout<<"name: "<<(*iter).name;
  271 +
  272 + if((*iter).type == RTS_DOUBLE)
  273 + cout<<" value: "<<(*iter).double_value<<endl;
  274 + else
  275 + cout<<" value: "<<(*iter).char_value<<endl;
  276 + }
  277 + }
  278 +}
  279 +
... ...
rtsPoint3d.h 0 → 100755
  1 +++ a/rtsPoint3d.h
  1 +#ifndef RTSPOINT3D_H
  2 +#define RTSPOINT3D_H
  3 +#include "rtsVector3d.h"
  4 +
  5 +///This class is used to store information about a 3D point. It is designed to work with the class vector3D<T> for linear algebra operations.
  6 +
  7 +template <class T> class point3D
  8 +{
  9 + //friend class vector3D<T>;
  10 +public:
  11 + //data values
  12 + T x;
  13 + T y;
  14 + T z;
  15 +
  16 + point3D(); ///<Constructor initializes the point at the origin (0,0,0).
  17 + point3D(T new_x, T new_y, T new_z); ///<Constructor initializes the point to the position specified by (new_x, new_y, new_z).
  18 +
  19 + //operators
  20 + bool operator==(point3D<T> param); ///<Overloaded boolean operator. Returns true if the two oparands are at the same position.
  21 + bool operator!=(point3D<T> param); ///<Overloaded boolean operator for !=
  22 + point3D<T> operator+(vector3D<T> param); ///<Overloaded arithmetic oparator. Returns the sum of the current point and a given vector.
  23 + point3D<T> operator-(vector3D<T> param); ///<Overloaded arithmetic operator. Returns the sum of the current point and the negative of a given vector.
  24 + vector3D<T> operator-(point3D<T> param); ///<Overloaded arithmetic operator. Returns the vector representing the space between two points.
  25 +
  26 + //casting operators
  27 + template <class U> operator point3D<U>(); ///<Overloaded casting operator. Allows casting between points of different types.
  28 +
  29 + //output
  30 + friend ostream& operator<<(ostream& os, const point3D<T> &rhs)
  31 + {
  32 + os<<"("<<rhs.x<<","<<rhs.y<<","<<rhs.z<<")";
  33 + return os;
  34 + }
  35 +
  36 + /*point3D<T> & operator=(const point3D<T> & rhs)
  37 + {
  38 + if(this != &rhs)
  39 + {
  40 + x = rhs.x;
  41 + y = rhs.y;
  42 + z = rhs.z;
  43 + }
  44 + return *this;
  45 + }*/
  46 +
  47 + void print();
  48 +};
  49 +
  50 +template <class T>
  51 +template <class U>
  52 +point3D<T>::operator point3D<U>()
  53 +{
  54 + point3D<U> cast_result(x, y, z);
  55 + return cast_result;
  56 +}
  57 +
  58 +template <class T> point3D<T>::point3D()
  59 +{
  60 + x=0;
  61 + y=0;
  62 + z=0;
  63 +}
  64 +
  65 +template <class T> point3D<T>::point3D(T new_x, T new_y, T new_z)
  66 +{
  67 + x=new_x;
  68 + y=new_y;
  69 + z=new_z;
  70 +}
  71 +
  72 +template <class T>
  73 +point3D<T> point3D<T>::operator -(vector3D<T> param)
  74 +{
  75 + point3D<T> result; //create the result
  76 +
  77 + result.x = x-param.x; //perform the computation
  78 + result.y = y-param.y;
  79 + result.z = z-param.z;
  80 +
  81 + return result;
  82 +}
  83 +
  84 +template <class T>
  85 +vector3D<T> point3D<T>::operator -(point3D<T> param)
  86 +{
  87 + vector3D<T> result;
  88 + result.x = x - param.x;
  89 + result.y = y - param.y;
  90 + result.z = z - param.z;
  91 +
  92 + return result;
  93 +}
  94 +
  95 +template <class T>
  96 +point3D<T> point3D<T>::operator+(vector3D<T> param)
  97 +{
  98 + point3D<T> result; //create the result
  99 +
  100 + result.x = x+param.x; //perform the computation
  101 + result.y = y+param.y;
  102 + result.z = z+param.z;
  103 +
  104 + return result;
  105 +}
  106 +
  107 +template <class T>
  108 +bool point3D<T>::operator ==(point3D<T> param)
  109 +{
  110 + if(x == param.x && y == param.y && z == param.z)
  111 + return true;
  112 + else
  113 + return false;
  114 +}
  115 +
  116 +template <class T>
  117 +bool point3D<T>::operator !=(point3D<T> param)
  118 +{
  119 + if(x != param.x || y != param.y || z != param.z)
  120 + return true;
  121 + else
  122 + return false;
  123 +}
  124 +
  125 +
  126 +
  127 +template <class T>
  128 +void point3D<T>::print()
  129 +{
  130 + cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
  131 +}
  132 +
  133 +/*template <class T>
  134 +ostream& point3D<T>::operator<<(ostream& os, point3D<T> &rhs)
  135 +{
  136 + os<<"("<<x<<","<<y<<","<<z<<")";
  137 + return os;
  138 +}
  139 +*/
  140 +
  141 +#endif
... ...
rtsProgressBar.cpp 0 → 100755
  1 +++ a/rtsProgressBar.cpp
  1 +#include <iostream>
  2 +#include <sstream>
  3 +using namespace std;
  4 +
  5 +void rtsProgressBar(int percent)
  6 +{
  7 + stringstream bar;
  8 + static int x = 0;
  9 + string slash[4];
  10 + slash[0] = "\\";
  11 + slash[1] = "-";
  12 + slash[2] = "/";
  13 + slash[3] = "|";
  14 + bar<<"[";
  15 + for(int i=0; i<40; i++)
  16 + {
  17 + if(percent > (float)i/(float)40 *100)
  18 + bar << "*";
  19 + else
  20 + bar << " ";
  21 + }
  22 + bar<<"]";
  23 + cout << "\r"; // carriage return back to beginning of line
  24 + cout << bar.str() << " " << slash[x] << " " << percent << " %"; // print the bars and percentage
  25 + x++; // increment to make the slash appear to rotate
  26 + if(x == 4)
  27 + x = 0; // reset slash animation
  28 +}
0 29 \ No newline at end of file
... ...
rtsQuaternion.h 0 → 100755
  1 +++ a/rtsQuaternion.h
  1 +#include "rtsMatrix4x4.h"
  2 +
  3 +#ifndef RTS_QUATERNION_H
  4 +#define RTS_QUATERNION_H
  5 +
  6 +template<typename T>
  7 +class rtsQuaternion
  8 +{
  9 +public:
  10 + T w;
  11 + T x;
  12 + T y;
  13 + T z;
  14 +
  15 + void normalize();
  16 + void CreateRotation(T theta, T axis_x, T axis_y, T axis_z);
  17 + rtsQuaternion<T> operator*(rtsQuaternion<T> &rhs);
  18 + matrix4x4<T> toMatrix();
  19 +
  20 +
  21 + rtsQuaternion();
  22 + rtsQuaternion(T w, T x, T y, T z);
  23 +
  24 +};
  25 +
  26 +template<typename T>
  27 +void rtsQuaternion<T>::normalize()
  28 +{
  29 + double length=sqrt(w*w + x*x + y*y + z*z);
  30 + w=w/length;
  31 + x=x/length;
  32 + y=y/length;
  33 + z=z/length;
  34 +}
  35 +
  36 +template<typename T>
  37 +void rtsQuaternion<T>::CreateRotation(T theta, T axis_x, T axis_y, T axis_z)
  38 +{
  39 + //assign the given Euler rotation to this quaternion
  40 + w = cos(theta/2.0);
  41 + x = axis_x*sin(theta/2.0);
  42 + y = axis_y*sin(theta/2.0);
  43 + z = axis_z*sin(theta/2.0);
  44 +
  45 +
  46 +}
  47 +
  48 +template<typename T>
  49 +rtsQuaternion<T> rtsQuaternion<T>::operator *(rtsQuaternion<T> &param)
  50 +{
  51 + float A, B, C, D, E, F, G, H;
  52 +
  53 +
  54 + A = (w + x)*(param.w + param.x);
  55 + B = (z - y)*(param.y - param.z);
  56 + C = (w - x)*(param.y + param.z);
  57 + D = (y + z)*(param.w - param.x);
  58 + E = (x + z)*(param.x + param.y);
  59 + F = (x - z)*(param.x - param.y);
  60 + G = (w + y)*(param.w - param.z);
  61 + H = (w - y)*(param.w + param.z);
  62 +
  63 + rtsQuaternion<T> result;
  64 + result.w = B + (-E - F + G + H) /2;
  65 + result.x = A - (E + F + G + H)/2;
  66 + result.y = C + (E - F + G - H)/2;
  67 + result.z = D + (E - F - G + H)/2;
  68 +
  69 + return result;
  70 +}
  71 +
  72 +template<typename T>
  73 +matrix4x4<T> rtsQuaternion<T>::toMatrix()
  74 +{
  75 + matrix4x4<T> result;
  76 +
  77 +
  78 + double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
  79 +
  80 +
  81 + // calculate coefficients
  82 + x2 = x + x; y2 = y + y;
  83 + z2 = z + z;
  84 + xx = x * x2; xy = x * y2; xz = x * z2;
  85 + yy = y * y2; yz = y * z2; zz = z * z2;
  86 + wx = w * x2; wy = w * y2; wz = w * z2;
  87 +
  88 + result(0, 0) = 1.0 - (yy + zz);
  89 + result(0, 1) = xy - wz;
  90 + //m[0][0] = 1.0 - (yy + zz); m[1][0] = xy - wz;
  91 +
  92 + result(0, 2) = xz + wy;
  93 + result(0, 3) = 0.0;
  94 + //m[2][0] = xz + wy; m[3][0] = 0.0;
  95 +
  96 + result(1, 0) = xy + wz;
  97 + result(1, 1) = 1.0 - (xx + zz);
  98 + //m[0][1] = xy + wz; m[1][1] = 1.0 - (xx + zz);
  99 +
  100 + result(1, 2) = yz - wx;
  101 + result(1, 3) = 0.0;
  102 + //m[2][1] = yz - wx; m[3][1] = 0.0;
  103 +
  104 + result(2, 0) = xz - wy;
  105 + result(2, 1) = yz + wx;
  106 + //m[0][2] = xz - wy; m[1][2] = yz + wx;
  107 +
  108 + result(2, 2) = 1.0 - (xx + yy);
  109 + result(3, 2) = 0.0;
  110 + //m[2][2] = 1.0 - (xx + yy); m[3][2] = 0.0;
  111 +
  112 + result(3, 0) = 0.0;
  113 + result(3, 1) = 0.0;
  114 + result(3, 2) = 0.0;
  115 + result(3, 3) = 1.0;
  116 + //m[0][3] = 0; m[1][3] = 0;
  117 + //m[2][3] = 0; m[3][3] = 1;
  118 + /*
  119 + double* orientationmatrix=(double*)m;
  120 + char c;
  121 +
  122 +
  123 + double* result=new double[16];
  124 + double* array=(double*)m;
  125 + for(int i=0; i<16; i++)
  126 + result[i]=array[i];
  127 + */
  128 +
  129 + return result;
  130 +}
  131 +
  132 +template<typename T>
  133 +rtsQuaternion<T>::rtsQuaternion()
  134 +{
  135 + w=0.0; x=0.0; y=0.0; z=0.0;
  136 +}
  137 +
  138 +template<typename T>
  139 +rtsQuaternion<T>::rtsQuaternion(T c, T i, T j, T k)
  140 +{
  141 + w=c; x=i; y=j; z=k;
  142 +}
  143 +
  144 +#endif
... ...
rtsSkeleton.h 0 → 100755
  1 +++ a/rtsSkeleton.h
  1 +#include <vector>
  2 +using namespace std;
  3 +
  4 +#include "rtsPoint3d.h"
  5 +#include "rts_itkVolume.h"
  6 +typedef vector<point3D<double>> filament;
  7 +
  8 +#define BACKGROUND_NODE 0
  9 +#define SKELETON_NODE 255
  10 +#define ENDPOINT_NODE 128
  11 +#define VISITED_NODE 64
  12 +
  13 +class rtsSkeleton
  14 +{
  15 + rts_itkVolume<unsigned char> implicit_skeleton;
  16 + vector<filament> explicit_filaments;
  17 + vector<point3D<unsigned int>> explicit_endpoints;
  18 +
  19 + void ComputeEndPoints();
  20 +
  21 +public:
  22 + void ConstructExplicitSkeleton();
  23 + void SmoothExplicitSkeleton(int iterations);
  24 + void SaveExplicitSkeleton(const char* filename);
  25 +}
  26 +
  27 +void rtsSkeleton::ComputeEndPoints()
  28 +{
  29 + /*This function finds all of the filament end points in the implicit skeleton.
  30 + The end points are stored in the explicit_endpoints vector.
  31 + An end point is defined as a node with (n == 1) or (n > 2) connected components.
  32 + */
  33 +
  34 + unsigned int max_x = implicit_skeleton.DimX();
  35 + unsigned int max_y = implicit_skeleton.DimY();
  36 + unsigned int max_z = implicit_skeleton.DimZ();
  37 + unsigned int conn;
  38 +
  39 + indextype x, y, z;
  40 + for(x=0; x<max_x; x++) //go through each voxel in the data set
  41 + for(y=0; y<max_y; y++)
  42 + for(z=0; z<max_z; z++)
  43 + {
  44 + if(implicit_skeleton.GetPixel(x, y, z) == SKELETON_NODE) //if the voxel is part of the skeleton
  45 + {
  46 + conn = Neighbors26(&implicit_skeleton, x, y, z, 1); //test the number of connected components
  47 + if(conn == 1 || conn > 2) //if the number of connected components meets the
  48 + //criteria, store the node in the explicit_endpoints vector.
  49 + {
  50 + explicit_endpoints.push_back(point3D<unsigned int>(x, y, z));
  51 + }
  52 + }
  53 +
  54 + }
  55 +
  56 + //tag the endpoints in the implicit function
  57 + vector<point3D<unsigned int>>::iterator i;
  58 + for(i=explicit_endpoints.begin(); i!=explicit_endpoints.end(); i++)
  59 + implicit_skeleton.xyz(i->x, i->y, i->z) = ENDPOINT_NODE;
  60 +
  61 + //cout<<"Number of end points: "<<explicit_endpoints.size()<<endl;
  62 +}
  63 +
  64 +void rtsSkeleton::ConstructExplicitSkeleton()
  65 +{
  66 + /*The implicit skeleton is constructed as follows:
  67 + 1) Label all branch nodes.
  68 + 2) For each branch, find the number of fibers connected to that branch.
  69 + a) Create each fiber as a seperate structure and store them in a queue.
  70 + b) Iteratively track each fiber.
  71 + */
  72 + ComputeEndPoints(); //compute the endpoints for the explicit skeleton and
  73 + //label them in the implicit skeleton
  74 +
  75 + //iterate through each end point
  76 + vector<point3D<unsigned int>>::iterator i;
  77 + rtsFunction3D<unsigned char> local;
  78 + unsigned int x, y, z;
  79 + for(i = explicit_endpoints.begin(); i != explicit_endpoints.end(); i++)
  80 + {
  81 + //cout<<"Tracing Filament..."<<endl;
  82 + //i->print();
  83 + local = getLocalRegion(i->x, i->y, i->z);
  84 + local(1, 1, 1) = 0;
  85 + //local.toConsole();
  86 + for(x=0; x<3; x++)
  87 + for(y=0; y<3; y++)
  88 + for(z=0; z<3; z++)
  89 + if(local.xyz(x, y, z) > VISITED_NODE)
  90 + {
  91 + //cout<<(int)local.xyz(x, y, z)<<endl;
  92 + //cout<<(int)implicit_skeleton.xyz(i->x - 1 + x,
  93 + // i->y - 1 + y,
  94 + // i->z - 1 + z)<<endl;
  95 + TraceFilament((*i), point3D<unsigned int>(i->x - 1 + x,
  96 + i->y - 1 + y,
  97 + i->z - 1 + z));
  98 + }
  99 + //since we have tracked all filaments attached to an endpoint
  100 + //set the endpoint as visited
  101 + implicit_skeleton.xyz(i->x, i->y, i->z) = VISITED_NODE;
  102 + }
  103 +
  104 + //cout<<"Tracing complete"<<endl;
  105 +
  106 +
  107 +}
0 108 \ No newline at end of file
... ...
rtsSkeletonizer.h 0 → 100755
  1 +++ a/rtsSkeletonizer.h
  1 +#ifndef RTSSKELETONIZER_H
  2 +#define RTSSKELETONIZER_H
  3 +
  4 +#include "rts_itkVolume.h"
  5 +#include "objJedi.h"
  6 +#include <vector>
  7 +#include <queue>
  8 +
  9 +using namespace std;
  10 +
  11 +typedef vector<point3D<double>> filament;
  12 +typedef unsigned int indextype;
  13 +
  14 +#define BACKGROUND_NODE 0
  15 +#define SKELETON_NODE 255
  16 +#define ENDPOINT_NODE 128
  17 +#define VISITED_NODE 64
  18 +
  19 +class rtsSkeletonizer
  20 +{
  21 +private:
  22 + rts_itkVolume<unsigned char> implicit_skeleton;
  23 + /*Key:
  24 + 0 - background node
  25 + 255 - skeleton node
  26 + 128 - endpoint node
  27 + */
  28 +
  29 + vector<filament> explicit_filaments;
  30 + vector<point3D<unsigned int>> explicit_endpoints;
  31 +
  32 +
  33 +
  34 +public:
  35 + rtsSkeletonizer(rts_itkVolume<unsigned char> input);
  36 + unsigned int BackgroundComponents6(rts_itkVolume<unsigned char>* function,
  37 + indextype x,
  38 + indextype y,
  39 + indextype z,
  40 + unsigned char threshold);
  41 + unsigned int rtsSkeletonizer::Peel(unsigned char isovalue);
  42 + int Neighbors26(rts_itkVolume<unsigned char>* function,
  43 + indextype x,
  44 + indextype y,
  45 + indextype z,
  46 + unsigned char isovalue);
  47 + vector<point3D<unsigned int>> FloodFill6(rts_itkVolume<unsigned char>* function, indextype x, indextype y, indextype z, unsigned char target_value);
  48 + void FloodFill26(rts_itkVolume<unsigned char>* function, int x, int y, int z, unsigned char target_value);
  49 + unsigned int Neighbors6(rts_itkVolume<unsigned char>* function, indextype x, indextype y, indextype z, unsigned char threshold);
  50 + rts_itkVolume<unsigned char> getImplicitResult(){return implicit_skeleton;}
  51 + unsigned int NumConnectedComponents(indextype x, indextype y, indextype z, unsigned char threshold);
  52 +
  53 + void ComputeEndPoints(); //find all of the filament end points
  54 + void TraceFilament(point3D<unsigned int> p0, point3D<unsigned int> p1);
  55 + rts_itkVolume<unsigned char> getLocalRegion(unsigned int x, unsigned int y, unsigned int z);
  56 +
  57 + void ConstructExplicitSkeleton();
  58 + void SmoothExplicitSkeleton(int iterations);
  59 + void SaveExplicitSkeleton(const char* filename);
  60 +
  61 +
  62 +};
  63 +
  64 +void rtsSkeletonizer::SmoothExplicitSkeleton(int iterations)
  65 +{
  66 + /*This function smooths the vessels by repeatedly taking the dual of the skeleton.
  67 + Branch points and end points are constrained to their initial positions.
  68 + */
  69 +
  70 + vector<filament>::iterator f;
  71 + int num_verts, end_vert;
  72 + int v;
  73 + point3D<double> new_vert;
  74 +
  75 + for(int i = 0; i<iterations; i++)
  76 + {
  77 + for(f=explicit_filaments.begin(); f!=explicit_filaments.end(); f++)
  78 + {
  79 + filament new_filament;
  80 +
  81 + //find the number of vertices in the filament
  82 + num_verts = f->size();
  83 + end_vert = num_verts - 1;
  84 +
  85 + //take care of the first vertex
  86 + new_filament.push_back((*f)[0]);
  87 +
  88 + for(v=1; v<end_vert; v++)
  89 + {
  90 + //find the position of the next vertex (midpoint between the last and current vertices)
  91 + new_vert = (*f)[v-1] + ((*f)[v] - (*f)[v-1])*0.5;
  92 + new_filament.push_back(new_vert);
  93 + }
  94 +
  95 + //take care of the last vertex
  96 + new_filament.push_back((*f)[end_vert]);
  97 +
  98 + //delete the old filament and add the new one
  99 + (*f) = new_filament;
  100 + }
  101 + }
  102 +
  103 +}
  104 +
  105 +void rtsSkeletonizer::SaveExplicitSkeleton(const char* filename)
  106 +{
  107 + /*Save the filament file as an OBJ*/
  108 + //create the OBJ object
  109 + rtsOBJ output;
  110 +
  111 + unsigned int num_filaments = explicit_filaments.size();
  112 + //cout<<"Number of filaments: "<<num_filaments<<endl;
  113 + vector<filament>::iterator i;
  114 + filament::iterator f;
  115 + for(i=explicit_filaments.begin(); i!=explicit_filaments.end(); i++)
  116 + {
  117 + output.objBegin(OBJ_LINE_STRIP);
  118 + //cout<<"start filament"<<endl;
  119 + for(f=i->begin(); f!=i->end(); f++)
  120 + {
  121 + output.objVertex3f((*f).x, (*f).y, (*f).z);
  122 + //f->print();
  123 + }
  124 + //cout<<"end filament"<<endl<<endl;
  125 + output.objEnd();
  126 + }
  127 +
  128 + output.SaveFile(filename);
  129 +
  130 +}
  131 +
  132 +rts_itkVolume<unsigned char> rtsSkeletonizer::getLocalRegion(unsigned int x, unsigned int y, unsigned int z)
  133 +{
  134 + rts_itkVolume<unsigned char> local(3, 3, 3);
  135 + point3D<indextype> corner;
  136 + indextype u, v, w;
  137 + corner = point3D<indextype>(x-1, y-1, z-1);
  138 + for(u=0; u<3; u++)
  139 + for(v=0; v<3; v++)
  140 + for(w=0; w<3; w++)
  141 + local.SetPixel(u, v, w, implicit_skeleton.GetPixel(corner.x + u, corner.y + v, corner.z + w));
  142 + return local;
  143 +}
  144 +
  145 +
  146 +void rtsSkeletonizer::TraceFilament(point3D<unsigned int> p0, point3D<unsigned int> p1)
  147 +{
  148 + //create the new filament and start it with the two given points
  149 + filament result;
  150 + result.push_back(p0);
  151 + result.push_back(p1);
  152 +
  153 + //if(p0 == point3D<unsigned int>(156, 433, 254))
  154 + // cout<<"Stop here"<<endl;
  155 +
  156 + //if p1 is an endpoint, go ahead and end the filament right away
  157 + if(implicit_skeleton.GetPixel(p1.x, p1.y, p1.z) == ENDPOINT_NODE)
  158 + {
  159 + explicit_filaments.push_back(result);
  160 + return;
  161 + }
  162 +
  163 + rts_itkVolume<unsigned char> local;
  164 + point3D<unsigned int> current = p1;
  165 + point3D<unsigned int> next;
  166 + point3D<unsigned int> possible_end;
  167 + int x, y, z;
  168 + int c; //possible connections
  169 +
  170 + while(1) //continue tracing until the next endpoint
  171 + {
  172 + c=0;
  173 + local = getLocalRegion(current.x, current.y, current.z);
  174 + //cout<<"Local Region at ("<<current.x<<","<<current.y<<","<<current.z<<")"<<endl;
  175 + //local.toConsole();
  176 + local.SetPixel(1, 1, 1, 0);
  177 + for(x=0; x<3; x++)
  178 + for(y=0; y<3; y++)
  179 + for(z=0; z<3; z++)
  180 + {
  181 + //if the node is a skeleton node, store it as the next point
  182 + if(local(x, y, z) == SKELETON_NODE)
  183 + {
  184 + c++;
  185 + next = current - vector3D<unsigned int>(1, 1, 1) + vector3D<unsigned int>(x, y, z);
  186 + }
  187 + //if it is an endpoint node, check for a termination
  188 + if(local(x, y, z) == ENDPOINT_NODE)
  189 + {
  190 + //if we are not backtracking to the start node
  191 + possible_end = current - vector3D<unsigned int>(1, 1, 1) + vector3D<unsigned int>(x, y, z);
  192 + if(possible_end != p0 || result.size() > 2)
  193 + {
  194 + //terminate the fiber
  195 + result.push_back(current - vector3D<unsigned int>(1, 1, 1) + vector3D<unsigned int>(x, y, z));
  196 + explicit_filaments.push_back(result);
  197 + implicit_skeleton.SetPixel(current.x, current.y, current.z, VISITED_NODE);
  198 + return;
  199 + }
  200 + }
  201 + }
  202 + //return when there is nowhere to go
  203 + if(c == 0)
  204 + return;
  205 + //now we have the next node in the filament, go ahead and label the current
  206 + //one as traversed
  207 + implicit_skeleton.SetPixel(current.x, current.y, current.z, VISITED_NODE);
  208 + //now insert it into the fiber and move to the next node
  209 + result.push_back(next);
  210 + if(current == next)
  211 + {
  212 + //cout<<"I've been waiting for you Obi-Wan"<<endl;
  213 + local = getLocalRegion(current.x, current.y, current.z);
  214 + //cout<<"Local Region at ("<<current.x<<","<<current.y<<","<<current.z<<")"<<endl;
  215 + //local.toConsole();
  216 +
  217 + //cout<<"Number of neighbors: "<<Neighbors26(&implicit_skeleton, current.x, current.y, current.z, 1);
  218 + }
  219 + current = next;
  220 + }
  221 +
  222 +
  223 +}
  224 +
  225 +void rtsSkeletonizer::ConstructExplicitSkeleton()
  226 +{
  227 + /*The implicit skeleton is constructed as follows:
  228 + 1) Label all branch nodes.
  229 + 2) For each branch, find the number of fibers connected to that branch.
  230 + a) Create each fiber as a seperate structure and store them in a queue.
  231 + b) Iteratively track each fiber.
  232 + */
  233 + ComputeEndPoints(); //compute the endpoints for the explicit skeleton and
  234 + //label them in the implicit skeleton
  235 +
  236 + //iterate through each end point
  237 + vector<point3D<unsigned int>>::iterator i;
  238 + rts_itkVolume<unsigned char> local;
  239 + unsigned int x, y, z;
  240 + for(i = explicit_endpoints.begin(); i != explicit_endpoints.end(); i++)
  241 + {
  242 + //cout<<"Tracing Filament..."<<endl;
  243 + //i->print();
  244 + local = getLocalRegion(i->x, i->y, i->z);
  245 + local.SetPixel(1, 1, 1, 0);
  246 + //local.toConsole();
  247 + for(x=0; x<3; x++)
  248 + for(y=0; y<3; y++)
  249 + for(z=0; z<3; z++)
  250 + if(local.GetPixel(x, y, z) > VISITED_NODE)
  251 + {
  252 + //cout<<(int)local.xyz(x, y, z)<<endl;
  253 + //cout<<(int)implicit_skeleton.xyz(i->x - 1 + x,
  254 + // i->y - 1 + y,
  255 + // i->z - 1 + z)<<endl;
  256 + TraceFilament((*i), point3D<unsigned int>(i->x - 1 + x,
  257 + i->y - 1 + y,
  258 + i->z - 1 + z));
  259 + }
  260 + //since we have tracked all filaments attached to an endpoint
  261 + //set the endpoint as visited
  262 + implicit_skeleton.SetPixel(i->x, i->y, i->z, VISITED_NODE);
  263 + }
  264 +
  265 + //cout<<"Tracing complete"<<endl;
  266 +
  267 +
  268 +}
  269 +
  270 +
  271 +rtsSkeletonizer::rtsSkeletonizer(rts_itkVolume<unsigned char> input)
  272 +{
  273 + implicit_skeleton = input;
  274 +}
  275 +
  276 +void rtsSkeletonizer::ComputeEndPoints()
  277 +{
  278 + /*This function finds all of the filament end points in the implicit skeleton.
  279 + The end points are stored in the explicit_endpoints vector.
  280 + An end point is defined as a node with (n == 1) or (n > 2) connected components.
  281 + */
  282 +
  283 + unsigned int max_x = implicit_skeleton.DimX();
  284 + unsigned int max_y = implicit_skeleton.DimY();
  285 + unsigned int max_z = implicit_skeleton.DimZ();
  286 + unsigned int conn;
  287 +
  288 + indextype x, y, z;
  289 + for(x=0; x<max_x; x++) //go through each voxel in the data set
  290 + for(y=0; y<max_y; y++)
  291 + for(z=0; z<max_z; z++)
  292 + {
  293 + if(implicit_skeleton(x, y, z) == SKELETON_NODE) //if the voxel is part of the skeleton
  294 + {
  295 + conn = Neighbors26(&implicit_skeleton, x, y, z, 1); //test the number of connected components
  296 + if(conn == 1 || conn > 2) //if the number of connected components meets the
  297 + //criteria, store the node in the explicit_endpoints vector.
  298 + {
  299 + explicit_endpoints.push_back(point3D<unsigned int>(x, y, z));
  300 + }
  301 + }
  302 +
  303 + }
  304 +
  305 + //tag the endpoints in the implicit function
  306 + vector<point3D<unsigned int>>::iterator i;
  307 + for(i=explicit_endpoints.begin(); i!=explicit_endpoints.end(); i++)
  308 + implicit_skeleton.SetPixel(i->x, i->y, i->z, ENDPOINT_NODE);
  309 +
  310 + //cout<<"Number of end points: "<<explicit_endpoints.size()<<endl;
  311 +}
  312 +
  313 +
  314 +
  315 +unsigned int rtsSkeletonizer::NumConnectedComponents(indextype x, indextype y, indextype z, unsigned char threshold)
  316 +{
  317 + unsigned int result = 0;
  318 +
  319 + rts_itkVolume<unsigned char> local(3, 3, 3);
  320 +
  321 +
  322 + local = getLocalRegion(x, y, z);
  323 +// local.toConsole();
  324 + local.SetPixel(1, 1, 1, 0);
  325 +// local.toConsole();
  326 +
  327 + indextype xi, yi, zi;
  328 + //iterate through each voxel
  329 + for(xi=0; xi<3; xi++)
  330 + for(yi=0; yi<3; yi++)
  331 + for(zi=0; zi<3; zi++)
  332 + if(local(xi, yi, zi) >= threshold)
  333 + {
  334 + FloodFill6(&local, xi, yi, zi, 0);
  335 + result++;
  336 + }
  337 + /*
  338 + if(result == 1 || result > 2)
  339 + {
  340 + cout<<result<<endl;
  341 + local = getLocalRegion(x, y, z);
  342 + local.toConsole();
  343 + }
  344 + */
  345 + return result;
  346 +
  347 +
  348 +}
  349 +
  350 +unsigned int rtsSkeletonizer::BackgroundComponents6(rts_itkVolume<unsigned char>* function,
  351 + indextype x,
  352 + indextype y,
  353 + indextype z,
  354 + unsigned char threshold)
  355 +{
  356 + /**
  357 + This function computes the number of 6-connected background components in the local region of (x, y, z).
  358 + This computation is performed by testing all 6 possible voxels that can connect to the specified node. If
  359 + a background node is found, the entire background component associated with that node is filled and the counter
  360 + is incremented by 1. The value n specifies the connectivity domain for the flood fill.
  361 + The definition of background components is that specified by He, Kischell, Rioult and Holmes.
  362 + **/
  363 +
  364 + //see if there is at least one BG component
  365 + if(Neighbors6(function, x, y, z, threshold) == 6)
  366 + return 0;
  367 +
  368 +
  369 + //retrieve the local region of the function
  370 + rts_itkVolume<unsigned char> local(3, 3, 3);
  371 + point3D<indextype> corner(x-1, y-1, z-1);
  372 + indextype u, v, w;
  373 + for(u=0; u<3; u++)
  374 + for(v=0; v<3; v++)
  375 + for(w=0; w<3; w++)
  376 + local.SetPixel(u, v, w, function->GetPixel(corner.x + u, corner.y + v, corner.z + w));
  377 +
  378 + //threshold the background to find inside/outside points
  379 + local.Binary(threshold, 1);
  380 + //fill points that are not in the connectivity domain
  381 + /*if(n == 18)
  382 + {
  383 + local(0, 0, 0) = 1;
  384 + local(0, 0, 2) = 1;
  385 + local(0, 2, 0) = 1;
  386 + local(0, 2, 2) = 1;
  387 + local(2, 0, 0) = 1;
  388 + local(2, 0, 2) = 1;
  389 + local(2, 2, 0) = 1;
  390 + local(2, 2, 2) = 1;
  391 + }*/
  392 + //local.toConsole();
  393 +
  394 + //search all 6 possible connected points. If a background node is found, fill the component
  395 + unsigned int components = 0;
  396 + if(local(0, 1, 1) == 0)
  397 + {
  398 + components++;
  399 + FloodFill6(&local, 0, 1, 1, 1);
  400 + }
  401 + if(local(2, 1, 1) == 0)
  402 + {
  403 + components++;
  404 + FloodFill6(&local, 2, 1, 1, 1);
  405 + }
  406 + if(local(1, 0, 1) == 0)
  407 + {
  408 + components++;
  409 + FloodFill6(&local, 1, 0, 1, 1);
  410 + }
  411 + if(local(1, 2, 1) == 0)
  412 + {
  413 + components++;
  414 + FloodFill6(&local, 1, 2, 1, 1);
  415 + }
  416 + if(local(1, 1, 0) == 0)
  417 + {
  418 + components++;
  419 + FloodFill6(&local, 1, 1, 0, 1);
  420 + }
  421 + if(local(1, 1, 2) == 0)
  422 + {
  423 + components++;
  424 + FloodFill6(&local, 1, 1, 2, 1);
  425 + }
  426 +
  427 + return components;
  428 +}
  429 +
  430 +unsigned int rtsSkeletonizer::Neighbors6(rts_itkVolume<unsigned char>* function, indextype x, indextype y, indextype z, unsigned char threshold)
  431 +{
  432 +
  433 + unsigned int neighbors = 0;
  434 + if(function->GetPixel(x+1, y, z) >= threshold)
  435 + neighbors++;
  436 + if(function->GetPixel(x-1, y, z) >= threshold)
  437 + neighbors++;
  438 + if(function->GetPixel(x, y+1, z) >= threshold)
  439 + neighbors++;
  440 + if(function->GetPixel(x, y-1, z) >= threshold)
  441 + neighbors++;
  442 + if(function->GetPixel(x, y, z+1) >= threshold)
  443 + neighbors++;
  444 + if(function->GetPixel(x, y, z-1) >= threshold)
  445 + neighbors++;
  446 +
  447 + return neighbors;
  448 +}
  449 +
  450 +int rtsSkeletonizer::Neighbors26(rts_itkVolume<unsigned char>* function,
  451 + indextype x,
  452 + indextype y,
  453 + indextype z,
  454 + unsigned char isovalue)
  455 +{
  456 + int neighbors = 0;
  457 + int u,v,w;
  458 +
  459 + for(u=-1; u<=1; u++)
  460 + for(v=-1; v<=1; v++)
  461 + for(w=-1; w<=1; w++)
  462 + if(function->GetPixel(x+u, y+v, z+w) >= isovalue)
  463 + neighbors++;
  464 + if(function->GetPixel(x, y, z) > isovalue)
  465 + neighbors--;
  466 +
  467 + return neighbors;
  468 +}
  469 +
  470 +unsigned int rtsSkeletonizer::Peel(unsigned char isovalue)
  471 +{
  472 + /**
  473 + Removes one layer of pixels from the specified isosurface.
  474 + **/
  475 +
  476 + unsigned int res_x = implicit_skeleton.DimX();
  477 + unsigned int res_y = implicit_skeleton.DimY();
  478 + unsigned int res_z = implicit_skeleton.DimZ();
  479 + vector<point3D<indextype>> border_nodes; //get the border nodes for the image
  480 + indextype x, y, z;
  481 + int condition;
  482 + for(x=0; x<res_x; x++)
  483 + for(y=0; y<res_y; y++)
  484 + for(z=0; z<res_z; z++)
  485 + //find the border nodes
  486 + if(implicit_skeleton(x, y, z) >= isovalue && BackgroundComponents6(&implicit_skeleton, x, y, z, isovalue) == 1 && Neighbors26(&implicit_skeleton, x, y, z, isovalue) != 1)
  487 + {
  488 + condition = 0;
  489 + //now find the border pairs. A border point must meet two of the following conditions to be a border pair.
  490 + //south border: s(p) is background
  491 + if(implicit_skeleton(x, y-1, z) < isovalue)
  492 + condition++;
  493 + //north border: n(p) is background, s(p) and s(s(p)) are foreground
  494 + if(implicit_skeleton(x, y+1, z) < isovalue && implicit_skeleton(x, y-1, z) >= isovalue && implicit_skeleton(x, y-2, z) >= isovalue)
  495 + condition++;
  496 + //west border: w(p) is background
  497 + if(implicit_skeleton(x-1, y, z) < isovalue)
  498 + condition++;
  499 + //east border: e(p) is background, w(p) and w(w(p)) are foreground
  500 + if(implicit_skeleton(x+1, y, z) < isovalue && implicit_skeleton(x-1, y, z) >= isovalue && implicit_skeleton(x-2, y, z) >= isovalue)
  501 + condition++;
  502 + //up border: u(p) is background
  503 + if(implicit_skeleton(x, y, z-1) < isovalue)
  504 + condition++;
  505 + //down border: d(p) is background, u(p) and u(u(p)) are foreground
  506 + if(implicit_skeleton(x, y, z+1) < isovalue && implicit_skeleton(x, y, z-1) >= isovalue && implicit_skeleton(x, y, z-2) >= isovalue)
  507 + condition++;
  508 +
  509 + if(condition > 1)
  510 + border_nodes.push_back(point3D<indextype>(x, y, z));
  511 + }
  512 + //cout<<"Number of border nodes: "<<border_nodes.size()<<endl;
  513 +
  514 + //determine if each edge node can be removed without changing the topology of the model
  515 + //declare some initial variables
  516 + rts_itkVolume<unsigned char> local(3, 3, 3); //store the region local to the current voxel
  517 + int nodes_before, nodes_after; //number of neighboring nodes before and after the filling operation
  518 + point3D<indextype> fill_start;
  519 + vector<point3D<indextype>>::iterator i;
  520 +
  521 + /*
  522 + Here we determine if a point can be removed by looking at the number of foreground connected
  523 + components in the local region. If there is more than one connected component
  524 + */
  525 + unsigned int removed = 0;
  526 + for(i=border_nodes.begin(); i<border_nodes.end(); i++)
  527 + {
  528 + //get the local region around the current point
  529 + for(x=-1; x<=1; x++)
  530 + for(y=-1; y<=1; y++)
  531 + for(z=-1; z<=1; z++)
  532 + local.SetPixel(x+1, y+1, z+1, implicit_skeleton((*i).x + x, (*i).y + y, (*i).z + z));
  533 +
  534 + local.SetPixel(1, 1, 1, 0); //remove the center voxel
  535 + local.Binary(isovalue, 1);
  536 + nodes_before = Neighbors26(&local, 1, 1, 1, 1);
  537 +
  538 +
  539 + //find an interior voxel to fill
  540 + for(x=0; x<3; x++)
  541 + for(y=0; y<3; y++)
  542 + for(z=0; z<3; z++)
  543 + if(local(x, y, z) > 0)
  544 + fill_start = point3D<indextype>(x, y, z);
  545 +
  546 + //fill the local region
  547 + FloodFill26(&local, fill_start.x, fill_start.y, fill_start.z, 2);
  548 + //get the number of filled neighbors
  549 + nodes_after = Neighbors26(&local, 1, 1, 1, 2);
  550 + if(nodes_after == nodes_before)
  551 + {
  552 + implicit_skeleton.SetPixel((*i).x, (*i).y, (*i).z, 0);
  553 + removed++;
  554 + }
  555 +
  556 + }
  557 + return removed;
  558 +}
  559 +
  560 +vector<point3D<unsigned int>> rtsSkeletonizer::FloodFill6(rts_itkVolume<unsigned char>* function, indextype x, indextype y, indextype z, unsigned char target_value)
  561 +{
  562 + //create a vector containing all of the filled nodes
  563 + vector<point3D<unsigned int>> result;
  564 +
  565 + unsigned char old_value = function->GetPixel(x, y, z); //find the old value (the value being flood-filled)
  566 + if(target_value == old_value) //if the target value is the same as the old value, nothing to do
  567 + return result;
  568 +
  569 + queue<point3D<indextype>> Q; //create a queue for neighboring points
  570 + point3D<indextype> current(x, y, z); //start with the current point
  571 + function->SetPixel(current.x, current.y, current.z, target_value);
  572 + point3D<indextype> next;
  573 + Q.push(current);
  574 + indextype u, v, w;
  575 +
  576 +
  577 + while(!Q.empty()) //continue until the queue is empty
  578 + {
  579 + current = Q.front(); //get the first element from the queue
  580 + Q.pop();
  581 +
  582 + if(current.x != function->DimY() - 1)
  583 + if(function->GetPixel(current.x + 1, current.y, current.z) == old_value)
  584 + {
  585 + function->SetPixel(current.x + 1, current.y, current.z, target_value);
  586 + result.push_back(point3D<unsigned int>(current.x + 1, current.y, current.z));
  587 + Q.push(point3D<indextype>(current.x + 1, current.y, current.z));
  588 + }
  589 + if(current.x != 0)
  590 + if(function->GetPixel(current.x - 1, current.y, current.z) == old_value)
  591 + {
  592 + function->SetPixel(current.x - 1, current.y, current.z, target_value);
  593 + result.push_back(point3D<unsigned int>(current.x - 1, current.y, current.z));
  594 + Q.push(point3D<indextype>(current.x - 1, current.y, current.z));
  595 + }
  596 + if(current.y != function->DimY() - 1)
  597 + if(function->GetPixel(current.x, current.y +1, current.z) == old_value)
  598 + {
  599 + function->SetPixel(current.x, current.y+1, current.z, target_value);
  600 + result.push_back(point3D<unsigned int>(current.x, current.y+1, current.z));
  601 + Q.push(point3D<indextype>(current.x, current.y+1, current.z));
  602 + }
  603 + if(current.y != 0)
  604 + if(function->GetPixel(current.x, current.y-1, current.z) == old_value)
  605 + {
  606 + function->SetPixel(current.x, current.y-1, current.z, target_value);
  607 + result.push_back(point3D<unsigned int>(current.x, current.y-1, current.z));
  608 + Q.push(point3D<indextype>(current.x, current.y-1, current.z));
  609 + }
  610 + if(current.z != function->DimZ() - 1)
  611 + if(function->GetPixel(current.x, current.y, current.z+1) == old_value)
  612 + {
  613 + function->SetPixel(current.x, current.y, current.z+1, target_value);
  614 + result.push_back(point3D<unsigned int>(current.x, current.y, current.z+1));
  615 + Q.push(point3D<indextype>(current.x, current.y, current.z+1));
  616 + }
  617 + if(current.z != 0)
  618 + if(function->GetPixel(current.x, current.y, current.z-1) == old_value)
  619 + {
  620 + function->SetPixel(current.x, current.y, current.z-1, target_value);
  621 + result.push_back(point3D<unsigned int>(current.x, current.y, current.z-1));
  622 + Q.push(point3D<indextype>(current.x, current.y, current.z-1));
  623 + }
  624 +
  625 + }
  626 +
  627 + return result;
  628 +
  629 +}
  630 +
  631 +void rtsSkeletonizer::FloodFill26(rts_itkVolume<unsigned char>* function, int x, int y, int z, unsigned char target_value)
  632 +{
  633 + unsigned char old_value = function->GetPixel(x, y, z);
  634 + if(target_value == old_value)
  635 + return;
  636 +
  637 + queue<point3D<indextype>> Q;
  638 + point3D<indextype> current(x, y, z);
  639 + point3D<indextype> next;
  640 + Q.push(current);
  641 + indextype u, v, w;
  642 + while(!Q.empty())
  643 + {
  644 + current = Q.front();
  645 + if(function->GetPixel(current.x, current.y, current.z) == old_value)
  646 + function->SetPixel(current.x, current.y, current.z, target_value);
  647 + Q.pop();
  648 +
  649 + unsigned int res_x = function->DimX();
  650 + unsigned int res_y = function->DimY();
  651 + unsigned int res_z = function->DimZ();
  652 + for(u=-1; u<=1; u++)
  653 + for(v=-1; v<=1; v++)
  654 + for(w=-1; w<=1; w++)
  655 + {
  656 + next.x = current.x + u;
  657 + next.y = current.y + v;
  658 + next.z = current.z + w;
  659 +
  660 + if(next.x >= 0 && next.x < res_x &&
  661 + next.y >= 0 && next.y < res_y &&
  662 + next.z >= 0 && next.z < res_z &&
  663 + function->GetPixel(next.x, next.y, next.z) == old_value)
  664 + {
  665 + function->SetPixel(next.x, next.y, next.z, target_value);
  666 + Q.push(next);
  667 + }
  668 + }
  669 + }
  670 +
  671 +
  672 +}
  673 +
  674 +
  675 +
  676 +
  677 +
  678 +
  679 +
  680 +#endif
0 681 \ No newline at end of file
... ...
rtsSourceCode.h 0 → 100755
  1 +++ a/rtsSourceCode.h
  1 +#ifndef RTSSOURCECODE_H
  2 +#define RTSSOURCECODE_H
  3 +
  4 +#include <string>
  5 +#include <fstream>
  6 +#include <vector>
  7 +#include <iostream>
  8 +
  9 +using namespace std;
  10 +
  11 +///This class defines generic source code that can be loaded from text files. It is primarily used by the rts_glShaderProgram class for GLSL programming.
  12 +
  13 +class rtsSourceCode
  14 +{
  15 +public:
  16 + vector<string> source; //the actual source code
  17 + void clear() ///<Clears any current source code from the class.
  18 + {
  19 + source.clear();
  20 + }
  21 + void LoadSource(const char* filename) ///<Loads source code from a specified file.
  22 + {
  23 + ifstream infile; //create an input file
  24 + infile.open(filename); //load the specified file
  25 +
  26 + if(!infile.is_open()) //if the file is not open, exit
  27 + {
  28 + return;
  29 + }
  30 + source.clear(); //remove any previous code
  31 +
  32 + while(!infile.eof())
  33 + {
  34 + string current_line;
  35 + getline(infile, current_line);
  36 + current_line += '\n';
  37 + source.push_back(current_line);
  38 + }
  39 + }
  40 + rtsSourceCode(const char* filename) ///<Constructor creates the class and loads source code from the specified file.
  41 + {
  42 + LoadSource(filename);
  43 + }
  44 + rtsSourceCode(){} ///<Constructor creates a blank class.
  45 + rtsSourceCode& operator+=(const rtsSourceCode& rhs)
  46 + {
  47 + int lines = rhs.source.size();
  48 + for(int l=0; l<lines; l++)
  49 + source.push_back(rhs.source[l]);
  50 + return *this;
  51 + }
  52 + rtsSourceCode& operator+=(const string& rhs)
  53 + {
  54 + source.push_back(rhs);
  55 + return *this;
  56 + }
  57 + void ConsoleOut() ///<Sends the source code to the standard output.
  58 + {
  59 + unsigned int lines = source.size();
  60 + for(unsigned int l = 0; l<lines; l++)
  61 + cout<<l<<": "<<source[l];
  62 + }
  63 +};
  64 +
  65 +#endif
0 66 \ No newline at end of file
... ...
rtsUtilities.cpp 0 → 100755
  1 +++ a/rtsUtilities.cpp
  1 +#include "rtsUtilities.h"
  2 +
  3 +char* rtsInt_to_String(int num, int min_chars)
  4 +{
  5 + //returns a null-terminated string representing the passed parameter
  6 +
  7 + //find out if the number is negative
  8 + bool negative = false;
  9 + if(num < 0)
  10 + {
  11 + negative = true;
  12 + num *= -1;
  13 + }
  14 +
  15 + //first, count the number of digits that will be in the string
  16 + int num_digits = 0;
  17 + int dividend = 1;
  18 + while((num/dividend) != 0)
  19 + {
  20 + dividend*=10;
  21 + num_digits++;
  22 + }
  23 +
  24 +
  25 + //calculate the number of characters required by number
  26 +
  27 + int num_chars = 0;
  28 +
  29 + if(negative)
  30 + num_chars = num_digits+1;
  31 + else
  32 + num_chars = num_digits;
  33 +
  34 + //allocate memory for the string (add 1 for the NULL character)
  35 + char* result;
  36 + int total_chars = 0;
  37 + if(num_chars > min_chars)
  38 + total_chars = num_chars;
  39 + else
  40 + total_chars = min_chars;
  41 + result = new char[total_chars + 1];
  42 + //initialize the string to 0's
  43 + for(int i=0; i<total_chars; i++)
  44 + result[i] = '0';
  45 +
  46 + //calculate the starting point for the character string
  47 + int start_char = total_chars - num_digits;
  48 + if(negative)
  49 + result[0] = '-';
  50 +
  51 + //finally, calculate each character and assign it to the string
  52 + dividend = pow(10.0, num_digits-1); //calculate the character from biggest to smallest
  53 + unsigned char digit = 0;
  54 + int i;
  55 + for(i=0; i < num_digits; i++)
  56 + {
  57 + digit = num/dividend;
  58 + num -= digit*dividend;
  59 + dividend /= 10;
  60 + result[start_char + i] = '0' + digit;
  61 + }
  62 +
  63 + result[start_char + i] = NULL;
  64 +
  65 + return result;
  66 +}
  67 +
  68 +char** rtsGetFileList(const char* mask, unsigned int start, unsigned int end)
  69 +{
  70 + //retrieves a list of names based on the supplied mask "?" is a number and the passed integers
  71 +
  72 + //first, find the length of the string
  73 + int length = strlen(mask);
  74 + int num_length = 0;
  75 + int start_index = -1;
  76 + //get the number of number characters in the mask by counting "?"
  77 + for(int i=0; i<length; i++)
  78 + {
  79 + if(mask[i] == '?')
  80 + {
  81 + if(start_index == -1)
  82 + start_index = i;
  83 +
  84 + num_length++;
  85 + }
  86 + }
  87 +
  88 + //allocate space for a list of filenames
  89 + char** result = new char*[end - start + 1];
  90 +
  91 + //now, for each string name
  92 + for(int i=0; i<(end - start) + 1; i++)
  93 + {
  94 + //create a new slot for a filename
  95 + char* filename = new char[length+1];
  96 + //find the string version of the current number
  97 + char* number = rtsInt_to_String(start+i, num_length);
  98 + //now, for each character in the filename
  99 + for(int j=0; j<length; j++)
  100 + {
  101 + //if we are at the mask, output the number
  102 + if(j >= start_index && (j < start_index + num_length))
  103 + {
  104 + filename[j] = number[j - start_index];
  105 + }
  106 + //otherwise output the mask value
  107 + else
  108 + filename[j] = mask[j];
  109 + }
  110 + filename[length] = 0;
  111 + result[i] = filename;
  112 + }
  113 + return result;
  114 +}
  115 +
  116 +
  117 +unsigned char* rtsCalculateDifferenceImage(int length, unsigned char* a, unsigned char* b)
  118 +{
  119 + //calculates the difference between two images and returns the absolute value
  120 + unsigned char* result = new unsigned char[length];
  121 + for(int i=0; i<length; i++)
  122 + result[i] = (unsigned char)(abs((int)a[i]-(int)b[i]));
  123 + return result;
  124 +}
  125 +
  126 +unsigned int rtsSumPixels(int length, unsigned char* pixels)
  127 +{
  128 + //calculates the sum of all pixels in the array
  129 + unsigned int result = 0;
  130 + for(int i=0; i<length; i++)
  131 + result+=(unsigned int)pixels[i];
  132 +
  133 + return result;
  134 +}
  135 +
  136 +unsigned char* rts2DGaussian(int width, int height, double std_dev)
  137 +{
  138 + //this function creates a 2D gaussian with a mean at the center of the image
  139 + //and a standard deviation as specified
  140 + unsigned char* gaussian = new unsigned char[width*height];
  141 + double high_value = (1.0/(2.0*RTS_PI*std_dev*std_dev))*exp(0.0);
  142 + for(int x = 0; x<width; x++)
  143 + for(int y=0; y<height; y++)
  144 + {
  145 + double exponent = exp(-((x-width/2.0)*(x-width/2.0) + (y-height/2.0)*(y-height/2.0))/(2.0*std_dev*std_dev));
  146 + gaussian[y*width+x] = (255.0/high_value)*(1.0/(2.0*RTS_PI*std_dev*std_dev))*exponent;
  147 + }
  148 + return gaussian;
  149 +}
  150 +
  151 +unsigned char* rtsInvertImage(int width, int height, unsigned char* pixels)
  152 +{
  153 + //this function inverts an image
  154 + unsigned char* result = new unsigned char[width*height];
  155 + for(int x = 0; x<width; x++)
  156 + for(int y=0; y<height; y++)
  157 + {
  158 + result[y*width+x] = 255 - pixels[y*width+x];
  159 + }
  160 + return result;
  161 +}
  162 +
  163 +unsigned char* rtsMultiplyImages(int width, int height, unsigned char* pixels_a, unsigned char* pixels_b)
  164 +{
  165 + //this function multiplies one image by another
  166 + unsigned char* result = new unsigned char[width*height];
  167 + for(int x = 0; x<width; x++)
  168 + for(int y=0; y<height; y++)
  169 + {
  170 + result[y*width+x] = (unsigned char)255*((pixels_a[y*width+x]/255.0) * (pixels_b[y*width+x]/255.0));
  171 + }
  172 + return result;
  173 +}
0 174 \ No newline at end of file
... ...
rtsUtilities.h 0 → 100755
  1 +++ a/rtsUtilities.h
  1 +#ifndef RTS_UTILITIES_H
  2 +#define RTS_UTILITIES_H
  3 +
  4 +//#include<stdlib.h>
  5 +#include <math.h>
  6 +#include <iostream>
  7 +#include <string.h>
  8 +#include "rtsMath.h"
  9 +
  10 +using namespace std;
  11 +
  12 +char* rtsInt_to_String(int num, int min_chars);
  13 +char** rtsGetFileList(const char* mask, unsigned int start, unsigned int end);
  14 +unsigned char* rtsCalculateDifferenceImage(int length, unsigned char* a, unsigned char* b);
  15 +unsigned int rtsSumPixels(int length, unsigned char* pixels);
  16 +unsigned char* rts2DGaussian(int width, int height, double std_dev);
  17 +unsigned char* rtsInvertImage(int width, int height, unsigned char* pixels);
  18 +unsigned char* rtsMultiplyImages(int width, int height, unsigned char* pixels_a, unsigned char* pixels_b);
  19 +
  20 +#endif
0 21 \ No newline at end of file
... ...
rtsVector3d.h 0 → 100755
  1 +++ a/rtsVector3d.h
  1 +///This class is used to store information for a 3D vector.
  2 +#include <iostream>
  3 +#include <math.h>
  4 +using namespace std;
  5 +
  6 +#ifndef RTSVECTOR3D_H
  7 +#define RTSVECTOR3D_H
  8 +
  9 +
  10 +template <class T> class vector3D
  11 +{
  12 + //friend class point3D<T>;
  13 +public:
  14 + //data values
  15 + T x;
  16 + T y;
  17 + T z;
  18 +
  19 + vector3D(); ///<Constructor. The resulting vector is initialized to (0,0,0)
  20 + vector3D(T new_x, T new_y, T new_z); ///<Constructor. Initialize the resulting vector to the value specified by (new_x, new_y, new_z)
  21 +
  22 + //operators
  23 + vector3D<T> operator+(vector3D<T> param); ///<Used for vector arithmetic. Allows two vectors with similar types to be added.
  24 + vector3D<T> operator-(vector3D<T> param); ///<Used for vector arithmetic. Allows two vectors with similar types to be subtracted.
  25 + T operator*(vector3D<T> param); ///<Used for vector arithmetic. Computes the inner product of two vectors of the same type.
  26 + vector3D<T> operator*(T param); ///<Used for vector arithmetic. Multiplies a vector by a scalar value of type T.
  27 + vector3D<T> X(vector3D<T> param); ///<Compute the cross product between two vectors
  28 +
  29 + friend vector3D<T> operator*(const T lhs, vector3D<T> rhs){return rhs*lhs;} ///<Allows vectors to be multiplied by scalars in either order
  30 +
  31 + //methods
  32 + vector3D<T> Times(vector3D<T> param); ///<Performs piecewise multiplication between two vectors [ex. (x1*x2, y1*y2, z1*z2)].
  33 + vector3D<T> Normalize(); ///<Returns the normalized version of the vector.
  34 + T Length(); ///<Returns the length of the vector.
  35 +
  36 + //casting operators
  37 + template <class U> operator vector3D<U>(); ///<Casting operator allows explicit casting between vector types.
  38 + //output
  39 + friend ostream& operator<<(ostream& os, const vector3D<T> &rhs)
  40 + {
  41 + os<<"("<<rhs.x<<","<<rhs.y<<","<<rhs.z<<")";
  42 + return os;
  43 + }
  44 + void print();
  45 +};
  46 +
  47 +template <class T>
  48 +template <class U>
  49 +vector3D<T>::operator vector3D<U>()
  50 +{
  51 + vector3D<U> cast_result(x, y, z);
  52 + return cast_result;
  53 +}
  54 +
  55 +template <class T> vector3D<T>::vector3D()
  56 +{
  57 + x=0;
  58 + y=0;
  59 + z=0;
  60 +}
  61 +
  62 +template <class T> vector3D<T>::vector3D(T new_x, T new_y, T new_z)
  63 +{
  64 + x=new_x;
  65 + y=new_y;
  66 + z=new_z;
  67 +}
  68 +
  69 +template <class T>
  70 +vector3D<T> vector3D<T>::operator -(vector3D<T> param)
  71 +{
  72 + vector3D<T> result; //create the result
  73 +
  74 + result.x = x-param.x; //perform the computation
  75 + result.y = y-param.y;
  76 + result.z = z-param.z;
  77 +
  78 + return result;
  79 +}
  80 +
  81 +template <class T>
  82 +vector3D<T> vector3D<T>::operator+(vector3D<T> param)
  83 +{
  84 + vector3D<T> result; //create the result
  85 +
  86 + result.x = x+param.x; //perform the computation
  87 + result.y = y+param.y;
  88 + result.z = z+param.z;
  89 +
  90 + return result;
  91 +}
  92 +
  93 +template <class T>
  94 +vector3D<T> vector3D<T>::Times(vector3D<T> param)
  95 +{
  96 + vector3D<T> result; //create the result
  97 +
  98 + result.x = x*param.x; //perform the computation
  99 + result.y = y*param.y;
  100 + result.z = z*param.z;
  101 +
  102 + return result;
  103 +}
  104 +
  105 +template <class T>
  106 +vector3D<T> vector3D<T>::operator*(T param)
  107 +{
  108 + vector3D<T> result; //create the result
  109 +
  110 + result.x = x*param; //perform the computation
  111 + result.y = y*param;
  112 + result.z = z*param;
  113 +
  114 + return result;
  115 +}
  116 +
  117 +template <class T>
  118 +T vector3D<T>::operator *(vector3D<T> param)
  119 +{
  120 + //This function computes the dot product between two vectors
  121 + return x*param.x + y*param.y + z*param.z;
  122 +}
  123 +
  124 +template <class T>
  125 +vector3D<T> vector3D<T>::X(vector3D<T> param)
  126 +{
  127 + vector3D<T> result;
  128 + result.x=y*param.z - z*param.y;
  129 + result.y=z*param.x - x*param.z;
  130 + result.z=x*param.y - y*param.x;
  131 +
  132 + return result;
  133 +}
  134 +
  135 +template <class T>
  136 +vector3D<T> vector3D<T>::Normalize()
  137 +{
  138 + T length = Length();
  139 + if(length ==0.0)
  140 + {
  141 + x = y = z = 0;
  142 + }
  143 + else
  144 + {
  145 + x/= length;
  146 + y /=length;
  147 + z /=length;
  148 + }
  149 + return *this;
  150 +}
  151 +
  152 +template <class T>
  153 +T vector3D<T>::Length()
  154 +{
  155 + return sqrt(x*x + y*y + z*z);
  156 +}
  157 +
  158 +template <class T>
  159 +void vector3D<T>::print()
  160 +{
  161 + cout<<"["<<x<<","<<y<<","<<z<<"]"<<endl;
  162 +}
  163 +
  164 +#endif
... ...
rtsVolume.cpp 0 → 100755
  1 +++ a/rtsVolume.cpp
  1 +#include "rtsVolume.h"
  2 +
  3 +rtsVolume::rtsVolume()
  4 +{
  5 + m_data = NULL;
  6 + m_size_x = 0;
  7 + m_size_y = 0;
  8 + m_size_z = 0;
  9 +}
  10 +
  11 +rtsVolume::rtsVolume(unsigned int size_x, unsigned int size_y, unsigned int size_z)
  12 +{
  13 + m_size_x = size_x;
  14 + m_size_y = size_y;
  15 + m_size_z = size_z;
  16 +
  17 + //allocate space for the data
  18 + m_data = new unsigned char[m_size_x * m_size_y * m_size_z];
  19 + for(int i=0; i<m_size_x*m_size_y*m_size_z; i++)
  20 + m_data[i] = 0;
  21 +}
  22 +
  23 +rtsVolume::rtsVolume(const unsigned char* data, unsigned int size_x, unsigned int size_y, unsigned int size_z)
  24 +{
  25 + //assign variables
  26 + m_size_x = size_x;
  27 + m_size_y = size_y;
  28 + m_size_z = size_z;
  29 + //allocate data
  30 + m_data = new unsigned char[m_size_x * m_size_y * m_size_z];
  31 + //blit data
  32 + blit3D(data, m_size_x, m_size_y, m_size_z, m_data, 0,0,0,m_size_x, m_size_y, m_size_z);
  33 +
  34 +}
  35 +
  36 +rtsVolume::~rtsVolume()
  37 +{
  38 + delete m_data;
  39 +}
  40 +
  41 +void rtsVolume::open(const char *filename)
  42 +{
  43 + if(m_data != NULL)
  44 + delete m_data;
  45 +
  46 +
  47 + ifstream infile(filename, ios::in | ios::binary);
  48 +
  49 + //load the dimensions of the data set
  50 + infile.read((char*)&m_size_x, sizeof(int));
  51 + infile.read((char*)&m_size_y, sizeof(int));
  52 + infile.read((char*)&m_size_z, sizeof(int));
  53 +
  54 + m_data = new unsigned char[m_size_x*m_size_y*m_size_z];
  55 + infile.read((char*)m_data, m_size_x*m_size_y*m_size_z*sizeof(unsigned char));
  56 +
  57 + //calculate min and maxes
  58 + infile.close();
  59 +}
  60 +
  61 +void rtsVolume::save(const char *filename)
  62 +{
  63 + ofstream outfile(filename, ios::out | ios::binary);
  64 + outfile.write((char*)&m_size_x, sizeof(int));
  65 + outfile.write((char*)&m_size_y, sizeof(int));
  66 + outfile.write((char*)&m_size_z, sizeof(int));
  67 +
  68 + outfile.write((char*)m_data, m_size_x*m_size_y*m_size_z*sizeof(unsigned char));
  69 + outfile.close();
  70 +}
  71 +
  72 +void rtsVolume::resize_canvas(unsigned int size_x, unsigned int size_y, unsigned int size_z)
  73 +{
  74 + //allocate memory for the new size
  75 + unsigned char* temp = m_data;
  76 + m_data = new unsigned char[size_x * size_y * size_z];
  77 +
  78 + //copy the data from old (temp) to new (m_data)
  79 + blit3D(temp, m_size_x, m_size_y, m_size_z, m_data, 0, 0, 0, size_x, size_y, size_z);
  80 +
  81 + //set the size variables
  82 + m_size_x = size_x;
  83 + m_size_y = size_y;
  84 + m_size_z = size_z;
  85 +
  86 +}
  87 +
  88 +void rtsVolume::blacken_border()
  89 +{
  90 + //code to put a black border around the volume
  91 + //create a few volumes for each side of the cube
  92 + rtsVolume front_back(m_size_x, m_size_y, 1);
  93 + rtsVolume left_right(1, m_size_y, m_size_z);
  94 + rtsVolume top_bottom(m_size_x, 1, m_size_z);
  95 +
  96 + //copy these into the current object
  97 + this->insert(front_back, 0, 0, 0);
  98 + this->insert(front_back, 0, 0, m_size_z-1);
  99 + this->insert(left_right, 0, 0, 0);
  100 + this->insert(left_right, m_size_x-1, 0, 0);
  101 + this->insert(top_bottom, 0, 0, 0);
  102 + this->insert(top_bottom, 0, m_size_y-1, 0);
  103 +
  104 +}
  105 +
  106 +void rtsVolume::invert()
  107 +{
  108 + //inverts the data stored in the volume
  109 + unsigned int length = m_size_x*m_size_y*m_size_z;
  110 + for(int i=0; i<length; i++)
  111 + m_data[i] = 255 - m_data[i];
  112 +}
  113 +
  114 +void rtsVolume::blacken(unsigned char threshold)
  115 +{
  116 + unsigned int size = m_size_x*m_size_y*m_size_z;
  117 + for(unsigned int i=0; i<size; i++)
  118 + if(m_data[i] <= threshold)
  119 + m_data[i] = 0;
  120 +}
  121 +
  122 +void rtsVolume::whiten(unsigned char threshold)
  123 +{
  124 + unsigned int size = m_size_x*m_size_y*m_size_z;
  125 + for(unsigned int i=0; i<size; i++)
  126 + if(m_data[i] >= threshold)
  127 + m_data[i] = 255;
  128 +}
  129 +
  130 +void rtsVolume::blit3D(const unsigned char* source,
  131 + unsigned int s_sx, unsigned int s_sy, unsigned int s_sz,
  132 + unsigned char* dest,
  133 + unsigned int d_px, unsigned int d_py, unsigned int d_pz,
  134 + unsigned int d_sx, unsigned int d_sy, unsigned int d_sz)
  135 +{
  136 + unsigned int ps, pd; //stores the mapping for the source point to the dest point
  137 + //find the maximum points that can be blit to (in case source overlaps the edges of dest)
  138 + unsigned int blit_size_x = min(s_sx, d_sx - d_px);
  139 + unsigned int blit_size_y = min(s_sy, d_sy - d_py);
  140 + unsigned int blit_size_z = min(s_sz, d_sz - d_pz);
  141 +
  142 + unsigned int source_z_offset = s_sx * s_sy;
  143 + unsigned int dest_z_offset = d_sx * d_sy;
  144 +
  145 + unsigned int z,y;
  146 + for(z=0; z<blit_size_z; z++)
  147 + for(y=0; y<blit_size_y; y++)
  148 + {
  149 + ps = z * source_z_offset + y * s_sx;
  150 + pd = (z + d_pz) * dest_z_offset + (y + d_py) * d_sx + d_px;
  151 + memcpy((void*)(&dest[pd]), (void*)(&source[ps]), sizeof(unsigned char)*blit_size_x);
  152 + }
  153 +
  154 +
  155 +
  156 +}
  157 +
  158 +inline unsigned char rtsVolume::operator ()(unsigned int x, unsigned int y, unsigned int z)
  159 +{
  160 + return m_data[z * m_size_x * m_size_y + y * m_size_x + z];
  161 +}
  162 +
  163 +rtsVolume& rtsVolume::operator=(const rtsVolume& rhs)
  164 +{
  165 + //check for self-assignment
  166 + if(this == &rhs)
  167 + return *this;
  168 +
  169 + //deallocate memory
  170 + if(m_data != NULL)
  171 + delete m_data;
  172 +
  173 + //copy variables
  174 + m_size_x = rhs.m_size_x;
  175 + m_size_y = rhs.m_size_y;
  176 + m_size_z = rhs.m_size_z;
  177 +
  178 + //allocate and copy memory
  179 + m_data = new unsigned char[m_size_x * m_size_y * m_size_z];
  180 + //copy the data
  181 + blit3D(rhs.m_data, m_size_x, m_size_y, m_size_z,m_data, 0, 0, 0, m_size_x, m_size_y, m_size_z);
  182 +
  183 + //return the left hand side
  184 + return *this;
  185 +}
  186 +
  187 +
  188 +rtsVolume::rtsVolume(const rtsVolume& original)
  189 +{
  190 + //copy the shallow variables
  191 + m_size_x = original.m_size_x;
  192 + m_size_y = original.m_size_y;
  193 + m_size_z = original.m_size_z;
  194 +
  195 + //allocate space for the data
  196 + m_data = new unsigned char[m_size_x * m_size_y * m_size_z];
  197 + //copy the data
  198 + blit3D(original.m_data, m_size_x, m_size_y, m_size_z,m_data, 0, 0, 0, m_size_x, m_size_y, m_size_z);
  199 +}
  200 +
  201 +unsigned char* rtsVolume::get_bits()
  202 +{
  203 + return m_data;
  204 +}
  205 +
  206 +void rtsVolume::insert(rtsVolume source, unsigned int pos_x, unsigned int pos_y, unsigned int pos_z)
  207 +{
  208 + unsigned char* source_bits = source.get_bits();
  209 + blit3D(source_bits, source.get_dimx(), source.get_dimy(), source.get_dimz(),
  210 + m_data, pos_x, pos_y, pos_z, m_size_x, m_size_y, m_size_z);
  211 +}
0 212 \ No newline at end of file
... ...
rtsVolume.h 0 → 100755
  1 +++ a/rtsVolume.h
  1 +#ifndef RTS_VOLUME_H
  2 +#define RTS_VOLUME_H
  3 +
  4 +#include <time.h>
  5 +#include <iostream>
  6 +#include <fstream>
  7 +
  8 +using namespace std;
  9 +
  10 +class rtsVolume
  11 +{
  12 +
  13 +private:
  14 + unsigned char* m_data; //pointer to the volume data
  15 + unsigned int m_size_x; //variables specifying the size of the volume
  16 + unsigned int m_size_y;
  17 + unsigned int m_size_z;
  18 +
  19 + //static function for copying 3D data from one pointer to another
  20 + //this function does not test boundaries so can quite easily crash
  21 + void blit3D(const unsigned char* source,
  22 + unsigned int s_sx, unsigned int s_sy, unsigned int s_sz,
  23 + unsigned char* dest,
  24 + unsigned int d_px, unsigned int d_py, unsigned int d_pz,
  25 + unsigned int d_sx, unsigned int d_sy, unsigned int d_sz);
  26 +
  27 +public:
  28 + rtsVolume();
  29 + //construct a blank volume of a given size
  30 + rtsVolume(unsigned int size_x, unsigned int size_y, unsigned int size_z);
  31 + //construct a volume from specified data
  32 + rtsVolume(const unsigned char* data, unsigned int size_x, unsigned int size_y, unsigned int size_z);
  33 + rtsVolume(const rtsVolume &original); //copy constructor
  34 + ~rtsVolume();
  35 +
  36 + //overloaded operators
  37 + rtsVolume& operator=(const rtsVolume& original);
  38 + inline unsigned char operator()(unsigned int x, unsigned int y, unsigned int z);
  39 +
  40 + //load and save methods
  41 + void open(const char* filename);
  42 + void save(const char* filename);
  43 + /*Allow resizing of the canvas. This resizes the volume without
  44 + resizing the existing data within the volume*/
  45 + void resize_canvas(unsigned int size_x, unsigned int size_y, unsigned int size_z);
  46 + void insert(const rtsVolume source, unsigned int pos_x, unsigned int pos_y, unsigned int pos_z);
  47 + void blacken_border();
  48 + void invert();
  49 + void blacken(unsigned char threshold);
  50 + void whiten(unsigned char threshold);
  51 +
  52 + //get functions
  53 + unsigned char* get_bits();
  54 + unsigned int get_dimx() {return m_size_x;}
  55 + unsigned int get_dimy() {return m_size_y;}
  56 + unsigned int get_dimz() {return m_size_z;}
  57 +
  58 +
  59 +
  60 +};
  61 +
  62 +
  63 +
  64 +#endif
0 65 \ No newline at end of file
... ...
rts_cudaBrewer.h 0 → 100755
  1 +++ a/rts_cudaBrewer.h
  1 +#include "rtsVector3d.h"
  2 +#include "cudaHandleError.h"
  3 +
  4 +#define BREWER_CTRL_PTS 11
  5 +texture<float4, cudaTextureType1D> cudaTexBrewer;
  6 +cudaArray* gpuBrewer;
  7 +
  8 +
  9 +__device__ float4 colorBrewer(float val, float min_range, float max_range, float min_fade = 0.000)
  10 +{
  11 + float t = (val - min_range)/(max_range - min_range)*((float)(BREWER_CTRL_PTS-2)/BREWER_CTRL_PTS);
  12 + float shift = 1.0/BREWER_CTRL_PTS;
  13 + float4 color = tex1D(cudaTexBrewer, t+shift);
  14 + if(t < min_fade)
  15 + color.w = (val - min_range)/(max_range - min_range)/min_fade;
  16 + return color;
  17 +}
  18 +
  19 +
  20 +void rts_cudaInitBrewer()
  21 +{
  22 + //allocate CPU space
  23 + float4 cpuColorMap[BREWER_CTRL_PTS];
  24 +
  25 + //define control points
  26 + cpuColorMap[0] = make_float4(0.192157f, 0.211765f, 0.584314f, 1.0f);
  27 + cpuColorMap[1] = make_float4(0.270588f, 0.458824f, 0.705882f, 1.0f);
  28 + cpuColorMap[2] = make_float4(0.454902f, 0.678431f, 0.819608f, 1.0f);
  29 + cpuColorMap[3] = make_float4(0.670588f, 0.85098f, 0.913725f, 1.0f);
  30 + cpuColorMap[4] = make_float4(0.878431f, 0.952941f, 0.972549f, 1.0f);
  31 + cpuColorMap[5] = make_float4(1.0f, 1.0f, 0.74902f, 1.0f);
  32 + cpuColorMap[6] = make_float4(0.996078f, 0.878431f, 0.564706f, 1.0f);
  33 + cpuColorMap[7] = make_float4(0.992157f, 0.682353f, 0.380392f, 1.0f);
  34 + cpuColorMap[8] = make_float4(0.956863f, 0.427451f, 0.262745f, 1.0f);
  35 + cpuColorMap[9] = make_float4(0.843137f, 0.188235f, 0.152941f, 1.0f);
  36 + cpuColorMap[10] = make_float4(0.647059f, 0.0f, 0.14902f, 1.0f);
  37 +
  38 +
  39 + int width = BREWER_CTRL_PTS;
  40 + int height = 0;
  41 +
  42 +
  43 + // allocate array and copy colormap data
  44 + cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 32, 32, 32, cudaChannelFormatKindFloat);
  45 +
  46 + HANDLE_ERROR(cudaMallocArray(&gpuBrewer, &channelDesc, width, height));
  47 +
  48 + cudaMemcpyToArray(gpuBrewer, 0, 0, cpuColorMap, sizeof(float4)*width, cudaMemcpyHostToDevice);
  49 +
  50 + // set texture parameters
  51 + cudaTexBrewer.addressMode[0] = cudaAddressModeClamp;
  52 + //texBrewer.addressMode[1] = cudaAddressModeClamp;
  53 + cudaTexBrewer.filterMode = cudaFilterModeLinear;
  54 + cudaTexBrewer.normalized = true; // access with normalized texture coordinates
  55 +
  56 + // Bind the array to the texture
  57 + HANDLE_ERROR( cudaBindTextureToArray( cudaTexBrewer, gpuBrewer, channelDesc));
  58 +
  59 +}
... ...
rts_cudaCufftShift.h 0 → 100755
  1 +++ a/rts_cudaCufftShift.h
  1 +#ifndef CUDA_CUFFT_SHIFT_H
  2 +#define CUDA_CUFFT_SHIFT_H
  3 +
  4 +#define BLOCK_SIZE 16
  5 +
  6 +__global__ void devCufftShift(char* gpuSource, int sE, int sX, int sY, int sZ)
  7 +{
  8 + int ix = blockIdx.x * blockDim.x + threadIdx.x;
  9 + int blocks_per_slice = sY/blockDim.y + 1;
  10 + int iy = (blockIdx.y % blocks_per_slice)*blockDim.y + threadIdx.y;
  11 + int iz = blockIdx.y/blocks_per_slice;
  12 +
  13 + if(ix >= sX || iy >= sY || iz >= sZ/2)
  14 + return;
  15 +
  16 + //array index
  17 + int i = iz*sX*sY*sE + iy*sX*sE + ix*sE;
  18 +
  19 + int iSwap = (iz + sZ/2)*sX*sY*sE;
  20 +
  21 + if(iy < sY/2)
  22 + iSwap += (iy + sY/2)*sX*sE;
  23 + else
  24 + iSwap += (iy - sY/2)*sX*sE;
  25 +
  26 + if(ix < sX/2)
  27 + iSwap += (ix + sX/2)*sE;
  28 + else
  29 + iSwap += (ix - sX/2)*sE;
  30 + //iSwap = (iz + sZ/2)*sX*sY*sE + (iy + sY/2)*sX*sE + (ix + sX/2)*sE;
  31 +
  32 + char temp;
  33 + for(int e=0; e<sE; e++)
  34 + {
  35 + temp = gpuSource[i + e];
  36 + gpuSource[i + e] = gpuSource[iSwap + e];
  37 + gpuSource[iSwap + e] = temp;
  38 + }
  39 +
  40 +}
  41 +
  42 +void rts_cudaCufftShift(char* gpuSource, int elementSize, int sX, int sY, int sZ)
  43 +{
  44 + //This function duplicates the Matlab fftshift function, making it easier to apply certain filters in
  45 + //the frequency domain.
  46 +
  47 + //currently only usable for even numbers
  48 + if(sX%2 != 0 || sY%2 != 0 || sZ%2 != 0)
  49 + {
  50 + printf("Error: cudaCufftShift dimensions must be even (for now)\n");
  51 + exit(1);
  52 + }
  53 +
  54 + dim3 block(BLOCK_SIZE, BLOCK_SIZE);
  55 + dim3 grid(sX/block.x + 1, (sY/block.y + 1)* sZ);
  56 +
  57 + //call the kernel
  58 + devCufftShift<<<grid, block>>>(gpuSource, elementSize, sX, sY, sZ);
  59 +
  60 +
  61 +
  62 +}
  63 +
  64 +
  65 +#endif
0 66 \ No newline at end of file
... ...
rts_glBrewer.glsl 0 → 100755
  1 +++ a/rts_glBrewer.glsl
... ...
rts_glBrewer.h 0 → 100755
  1 +++ a/rts_glBrewer.h
  1 +#include "rtsPoint3d.h"
  2 +
  3 +void rts_glBrewerPts(point3D<float>* brewerPts)
  4 +{
  5 + //define control points
  6 + brewerPts[0] = point3D<float>(0.192157f, 0.211765f, 0.584314f);
  7 + brewerPts[1] = point3D<float>(0.270588f, 0.458824f, 0.705882f);
  8 + brewerPts[2] = point3D<float>(0.454902f, 0.678431f, 0.819608f);
  9 + brewerPts[3] = point3D<float>(0.670588f, 0.85098f, 0.913725f);
  10 + brewerPts[4] = point3D<float>(0.878431f, 0.952941f, 0.972549f);
  11 + brewerPts[5] = point3D<float>(1.0f, 1.0f, 0.74902f);
  12 + brewerPts[6] = point3D<float>(0.996078f, 0.878431f, 0.564706f);
  13 + brewerPts[7] = point3D<float>(0.992157f, 0.682353f, 0.380392f);
  14 + brewerPts[8] = point3D<float>(0.956863f, 0.427451f, 0.262745f);
  15 + brewerPts[9] = point3D<float>(0.843137f, 0.188235f, 0.152941f);
  16 + brewerPts[10] = point3D<float>(0.647059f, 0.0f, 0.14902f);
  17 +}
0 18 \ No newline at end of file
... ...
rts_glFilamentNetwork.cpp 0 → 100755
  1 +++ a/rts_glFilamentNetwork.cpp
  1 +#include "rts_glFilamentNetwork.h"
  2 +
  3 +void rts_glFilamentNetwork::glRender()
  4 +{
  5 + ((rts_glOBJ*)network)->glRender();
  6 +}
  7 +
  8 +void rts_glFilamentNetwork::glRenderSelected()
  9 +{
  10 + ((rts_glOBJ*)network)->glRenderSelected();
  11 +}
  12 +
  13 +int rts_glFilamentNetwork::LoadFIB(const char* filename)
  14 +{
  15 + ((rts_glOBJ*)network)->Invalidate();
  16 + return fib_load(filename);
  17 +}
0 18 \ No newline at end of file
... ...
rts_glFilamentNetwork.h 0 → 100755
  1 +++ a/rts_glFilamentNetwork.h
  1 +#ifndef RTS_GLFILAMENTNETWORK_H
  2 +#define RTS_GLFILAMENTNETWORK_H
  3 +
  4 +#include "rtsFilamentNetwork.h"
  5 +#include "rts_glOBJ.h"
  6 +#include <windows.h>
  7 +#include <gl/gl.h>
  8 +#include <gl/glut.h>
  9 +
  10 +class rts_glFilamentNetwork:public rtsFilamentNetwork
  11 +{
  12 +public:
  13 + rts_glFilamentNetwork(){network = new rts_glOBJ();}
  14 + void glRender();
  15 + void glRenderSelected();
  16 +
  17 + int LoadFIB(const char* filename); //overload the parent function to reset the display list
  18 +
  19 + void Pick(unsigned int x, unsigned int y, unsigned int size_x, unsigned int size_y)
  20 + {
  21 + ((rts_glOBJ*)network)->Pick(x, y, size_x, size_y);
  22 + }
  23 +};
  24 +
  25 +
  26 +#endif
0 27 \ No newline at end of file
... ...
rts_glIntegrateTexture.cpp 0 → 100755
  1 +++ a/rts_glIntegrateTexture.cpp
... ...
rts_glIntegrateTexture.h 0 → 100755
  1 +++ a/rts_glIntegrateTexture.h
  1 +/*This class performs integration across a series of rectangular
  2 +texture samples. Basically, this is a downsample using a large box
  3 +filter and can be used to sum the results of multiple calculations
  4 +that are combined in a single texture.*/
  5 +
  6 +#include "rts_glRenderToTexture.h"
  7 +#include "rts_glShaderProgram.h"
  8 +
  9 +#define MEAN 0
  10 +#define SUM 1
  11 +#define MIN 2
  12 +#define MAX 3
  13 +
  14 +
  15 +class rts_glIntegrateTexture
  16 +{
  17 +private:
  18 + int x_sample_size;
  19 + int y_sample_size;
  20 + int x_sample_num;
  21 + int y_sample_num;
  22 +
  23 + rts_glShaderProgram x_pass_mean;
  24 + rts_glShaderProgram y_pass_mean;
  25 +
  26 + rts_glShaderProgram x_pass_min;
  27 + rts_glShaderProgram y_pass_min;
  28 +
  29 + rts_glShaderProgram x_pass_max;
  30 + rts_glShaderProgram y_pass_max;
  31 +
  32 + //this is a two-pass downsample
  33 + rts_glRenderToTexture x_pass;
  34 + rts_glRenderToTexture y_pass;
  35 +
  36 + void initialize_shaders();
  37 + inline void x_pass_enable(int type, rts_glTextureMap texture);
  38 + inline void x_pass_disable(int type);
  39 + inline void y_pass_enable(int type);
  40 + inline void y_pass_disable(int type);
  41 +
  42 +public:
  43 + //initialize the integrator with the number and size of samples
  44 + void Init(int x_size, int y_size,
  45 + int samples_x, int samples_y,
  46 + rts_glTextureMap test);
  47 +
  48 + void Integrate(float* result, rts_glTextureMap texture, int type = MEAN);
  49 + rts_glTextureMap getResultTexture(){return y_pass.GetTexture(0);}
  50 +};
  51 +
  52 +void rts_glIntegrateTexture::initialize_shaders()
  53 +{
  54 + //load and initialize the integration shaders
  55 + x_pass_mean.AttachShader(GL_FRAGMENT_SHADER,
  56 + "x_pass_mean.glsl");
  57 + x_pass_mean.Compile();
  58 + x_pass_mean.Link();
  59 + cout<<"x_pass_mean.glsl"<<endl;
  60 + x_pass_mean.PrintLog();
  61 + //x_pass_program.AttachTextureMap("difference_tex",
  62 + // test);
  63 + x_pass_mean.AttachGlobalUniform("templatesize", &x_sample_size);
  64 +
  65 +
  66 + y_pass_mean.AttachShader(GL_FRAGMENT_SHADER,
  67 + "y_pass_mean.glsl");
  68 + y_pass_mean.Compile();
  69 + y_pass_mean.Link();
  70 + cout<<"y_pass_mean.glsl"<<endl;
  71 + y_pass_mean.PrintLog();
  72 + y_pass_mean.AttachTextureMap("xfunnel_tex",
  73 + x_pass.GetTexture(0));
  74 + y_pass_mean.AttachGlobalUniform("templatesize", &x_sample_size);
  75 +
  76 +}
  77 +
  78 +void rts_glIntegrateTexture::x_pass_enable(int type, rts_glTextureMap texture)
  79 +{
  80 + x_pass_mean.BeginProgram();
  81 + x_pass_mean.AttachTextureMap("difference_tex",
  82 + texture);
  83 + x_pass_mean.UpdateGlobalUniforms();
  84 +}
  85 +
  86 +void rts_glIntegrateTexture::x_pass_disable(int type)
  87 +{
  88 + x_pass_mean.EndProgram();
  89 +}
  90 +
  91 +void rts_glIntegrateTexture::y_pass_enable(int type)
  92 +{
  93 + y_pass_mean.BeginProgram();
  94 + y_pass_mean.UpdateGlobalUniforms();
  95 +}
  96 +
  97 +void rts_glIntegrateTexture::y_pass_disable(int type)
  98 +{
  99 + y_pass_mean.EndProgram();
  100 +}
  101 +
  102 +
  103 +void rts_glIntegrateTexture::Init(int x_size, int y_size,
  104 + int samples_x, int samples_y,
  105 + rts_glTextureMap test)
  106 +{
  107 + //set provate variables
  108 + x_sample_size = x_size;
  109 + y_sample_size = y_size;
  110 + x_sample_num = samples_x;
  111 + y_sample_num = samples_y;
  112 +
  113 + //initialize the integrator texture maps
  114 + x_pass.Init(x_sample_num, y_sample_num*y_sample_size);
  115 + x_pass.AddTexture(GL_TEXTURE_RECTANGLE_ARB, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT);
  116 + y_pass.Init(x_sample_num, y_sample_num);
  117 + y_pass.AddTexture(GL_TEXTURE_RECTANGLE_ARB, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT);
  118 +
  119 + initialize_shaders();
  120 +}
  121 +
  122 +void rts_glIntegrateTexture::Integrate(float* result, rts_glTextureMap texture, int type)
  123 +{
  124 +
  125 + x_pass.BeginRender(0);
  126 + glMatrixMode(GL_PROJECTION);
  127 + glLoadIdentity();
  128 + x_pass.UseMaxViewport();
  129 + gluOrtho2D(0.0, 1.0, 0.0, 1.0);
  130 +
  131 + x_pass_enable(MEAN, texture);
  132 +
  133 + int total_w = x_sample_size * x_sample_num;
  134 + int total_h = y_sample_size * y_sample_num;
  135 +
  136 + //GLint prog;
  137 + //glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
  138 + glBegin(GL_QUADS);
  139 + glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
  140 + glTexCoord2f(total_w, 0.0); glVertex2f(1.0, 0.0);
  141 + glTexCoord2f(total_w, total_h); glVertex2f(1.0, 1.0);
  142 + glTexCoord2f(0.0, total_h); glVertex2f(0.0, 1.0);
  143 + glEnd();
  144 + x_pass_disable(MEAN);
  145 + glFinish();
  146 + x_pass.EndRender();
  147 +
  148 + //funnel along Y
  149 + y_pass.BeginRender(0);
  150 + glMatrixMode(GL_PROJECTION);
  151 + glLoadIdentity();
  152 + y_pass.UseMaxViewport();
  153 + gluOrtho2D(0.0, 1.0, 0.0, 1.0);
  154 +
  155 + //glColor3f(1.0, 0.0, 0.0);
  156 + y_pass_enable(type);
  157 + glBegin(GL_QUADS);
  158 + glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
  159 + glTexCoord2f(x_sample_num, 0.0); glVertex2f(1.0, 0.0);
  160 + glTexCoord2f(x_sample_num, total_h); glVertex2f(1.0, 1.0);
  161 + glTexCoord2f(0.0, total_h); glVertex2f(0.0, 1.0);
  162 + glEnd();
  163 + int fb;
  164 + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb);
  165 + y_pass_disable(type);
  166 + y_pass.EndRender();
  167 +
  168 + y_pass.GetTexture(0).BeginTexture();
  169 + glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GL_FLOAT, result);
  170 + y_pass.GetTexture(0).EndTexture();
  171 +
  172 +}
0 173 \ No newline at end of file
... ...
rts_glOBJ.cpp 0 → 100755
  1 +++ a/rts_glOBJ.cpp
  1 +#include "rts_glOBJ.h"
  2 +#include "gl\glut.h"
  3 +
  4 +OBJint rts_glOBJ::f_RenderTexCoord(vertex_texture &texcoord)
  5 +{
  6 + if(texcoord.mask & OBJ_VT_W)
  7 + glTexCoord3f(texcoord.u, texcoord.v, texcoord.w);
  8 + else if(texcoord.mask & OBJ_VT_V)
  9 + glTexCoord2f(texcoord.u, texcoord.v);
  10 + else
  11 + glTexCoord1f(texcoord.u);
  12 + return OBJ_OK;
  13 +}
  14 +
  15 +OBJint rts_glOBJ::f_RenderNormal(vertex_normal &normal)
  16 +{
  17 + if(normal.mask & OBJ_VN_K)
  18 + glNormal3f(normal.i, normal.j, normal.k);
  19 + else
  20 + return OBJ_ERROR;
  21 +
  22 + return OBJ_OK;
  23 +
  24 +}
  25 +
  26 +OBJint rts_glOBJ::f_RenderVertex(vertex_position &v)
  27 +{
  28 + if(v.mask & OBJ_V_W)
  29 + glVertex4f(v.x, v.y, v.z, v.w);
  30 + else if(v.mask & OBJ_V_Z)
  31 + glVertex3f(v.x, v.y, v.z);
  32 + else if(v.mask & OBJ_V_Y)
  33 + glVertex2f(v.x, v.y);
  34 + else
  35 + //glVertex1f(v.x);
  36 + return OBJ_ERROR;
  37 +
  38 + return OBJ_OK;
  39 +}
  40 +
  41 +inline void rts_glOBJ::f_RenderPointList(unsigned int id)
  42 +{
  43 + glBegin(GL_POINTS);
  44 + unsigned int num_vertices = primitives[id].p.size();
  45 + for(unsigned int v = 0; v<num_vertices; v++)
  46 + {
  47 + f_RenderVertex(v_list[primitives[id].p[v].v]);
  48 + }
  49 + glEnd();
  50 +}
  51 +
  52 +inline void rts_glOBJ::f_RenderLineStrip(unsigned int id)
  53 +{
  54 + //render each line as a line strip
  55 + glBegin(GL_LINE_STRIP);
  56 + unsigned int num_vertices = primitives[id].p.size();
  57 + for(unsigned int v=0; v<num_vertices; v++)
  58 + {
  59 + f_RenderVertex(v_list[primitives[id].p[v].v]);
  60 + }
  61 +
  62 + //end rendering
  63 + glEnd();
  64 +
  65 +}
  66 +
  67 +inline void rts_glOBJ::f_RenderFace(unsigned int id)
  68 +{
  69 + //start the proper render mode
  70 + if(primitives[id].p.size() > 4)
  71 + glBegin(GL_POLYGON);
  72 + else if(primitives[id].p.size() == 4)
  73 + glBegin(GL_QUADS);
  74 + else if(primitives[id].p.size() == 3)
  75 + glBegin(GL_TRIANGLES);
  76 + else
  77 + return;
  78 +
  79 + //now run through each vertex
  80 + unsigned int num_vertices = primitives[id].p.size();
  81 + for(unsigned int v=0; v<num_vertices; v++)
  82 + {
  83 + f_RenderVertex(v_list[primitives[id].p[v].v]);
  84 + }
  85 +
  86 + //end rendering
  87 + glEnd();
  88 +
  89 +}
  90 +
  91 +OBJint rts_glOBJ::f_RenderPrimitive(unsigned int i)
  92 +{
  93 + switch(primitives[i].type)
  94 + {
  95 + case OBJ_POINTS:
  96 + f_RenderPointList(i);
  97 + break;
  98 + case OBJ_LINES:
  99 + f_RenderLineStrip(i);
  100 + break;
  101 + case OBJ_FACE:
  102 + f_RenderFace(i);
  103 + break;
  104 + }
  105 +
  106 + return OBJ_OK;
  107 +
  108 +}
  109 +
  110 +OBJint rts_glOBJ::f_CreateDisplayList()
  111 +{
  112 + /*This function creates a display list representing the OBJ.
  113 + */
  114 +
  115 + //create the display list
  116 + if(glIsList(dl)) //if the list already exists
  117 + glDeleteLists(dl, 1);
  118 + //create a new display list
  119 + dl = glGenLists(1);
  120 +
  121 + //start the list
  122 + glNewList(dl, GL_COMPILE);
  123 +
  124 + //draw the OBJ
  125 + unsigned int prim = primitives.size();
  126 + for(unsigned int i=0; i<prim; i++)
  127 + f_RenderPrimitive(i);
  128 +
  129 + //finish the list
  130 + glEndList();
  131 +
  132 + dl_valid = true; //the display list is now valid
  133 +
  134 + return OBJ_OK;
  135 +}
  136 +
  137 +OBJint rts_glOBJ::glRender()
  138 +{
  139 + //create the display list if necessary
  140 + if(!dl_valid)
  141 + f_CreateDisplayList();
  142 +
  143 + //call the display list
  144 + glCallList(dl);
  145 +
  146 + return OBJ_OK;
  147 +}
  148 +
  149 +OBJint rts_glOBJ::glRenderSelected()
  150 +{
  151 + if(is_selected)
  152 + {
  153 + list<unsigned int>::iterator p;
  154 + for(p = selected_primitives.begin(); p!=selected_primitives.end(); p++)
  155 + f_RenderPrimitive(*p);
  156 + }
  157 + return OBJ_OK;
  158 +}
  159 +
  160 +
  161 +void rts_glOBJ::SelectPrimitive(unsigned int primitive)
  162 +{
  163 + //adds a primitive to the selection list
  164 + selected_primitives.push_back(primitive);
  165 + selected_primitives.unique();
  166 +}
  167 +
  168 +void rts_glOBJ::UnselectPrimitive(unsigned int primitive)
  169 +{
  170 + selected_primitives.remove(primitive);
  171 +}
  172 +
  173 +void rts_glOBJ::SelectMultipleHits(GLuint* buffer, unsigned int num_hits)
  174 +{
  175 + GLuint* hit_entry = buffer;
  176 + GLuint num_names;
  177 + GLuint nearest_name;
  178 + GLuint minZ = 0xffffffff;
  179 +
  180 + //push the hits into the selection buffer
  181 + for(int h=0; h<num_hits; h++)
  182 + {
  183 + num_names = hit_entry[0];
  184 + SelectPrimitive(hit_entry[3]);
  185 +
  186 + hit_entry = hit_entry + 3 + num_names;
  187 + }
  188 +
  189 +}
  190 +
  191 +void rts_glOBJ::UnselectMultipleHits(GLuint* buffer, unsigned int num_hits)
  192 +{
  193 + GLuint* hit_entry = buffer;
  194 + GLuint num_names;
  195 + GLuint nearest_name;
  196 + GLuint minZ = 0xffffffff;
  197 +
  198 + //push the hits into the selection buffer
  199 + for(int h=0; h<num_hits; h++)
  200 + {
  201 + num_names = hit_entry[0];
  202 + UnselectPrimitive(hit_entry[3]);
  203 +
  204 + hit_entry = hit_entry + 3 + num_names;
  205 + }
  206 +
  207 +}
  208 +
  209 +void rts_glOBJ::SelectClosestHit(GLuint* buffer, unsigned int num_hits)
  210 +{
  211 + GLuint* hit_entry = buffer;
  212 + GLuint num_names;
  213 + GLuint nearest_name;
  214 + GLuint minZ = 0xffffffff;
  215 +
  216 + //push the hits into the selection buffer
  217 + for(int h=0; h<num_hits; h++)
  218 + {
  219 + num_names = hit_entry[0];
  220 + if(hit_entry[1] < minZ)
  221 + {
  222 + nearest_name = hit_entry[3];
  223 + minZ = hit_entry[1];
  224 + }
  225 + hit_entry = hit_entry + 3 + num_names;
  226 +
  227 + }
  228 + SelectPrimitive(nearest_name);
  229 +
  230 +}
  231 +
  232 +void rts_glOBJ::UnselectClosestHit(GLuint* buffer, unsigned int num_hits)
  233 +{
  234 + GLuint* hit_entry = buffer;
  235 + GLuint num_names;
  236 + GLuint nearest_name;
  237 + GLuint minZ = 0xffffffff;
  238 +
  239 + //push the hits into the selection buffer
  240 + for(int h=0; h<num_hits; h++)
  241 + {
  242 + num_names = hit_entry[0];
  243 + if(hit_entry[1] < minZ)
  244 + {
  245 + nearest_name = hit_entry[3];
  246 + minZ = hit_entry[1];
  247 + }
  248 + hit_entry = hit_entry + 3 + num_names;
  249 +
  250 + }
  251 + UnselectPrimitive(nearest_name);
  252 +
  253 +}
  254 +
  255 +
  256 +void rts_glOBJ::Pick(unsigned int x, unsigned int y, unsigned int size_x, unsigned int size_y,
  257 + unsigned int picktype)
  258 +{
  259 + //initialize selection buffer properties
  260 + GLuint selectBuf[BUFSIZE];
  261 + GLint hits;
  262 + GLint viewport[4]; //storage space for viewport data
  263 +
  264 + //get the viewport information
  265 + glGetIntegerv(GL_VIEWPORT, viewport);
  266 +
  267 + //set the selection buffer
  268 + glSelectBuffer(BUFSIZE, selectBuf);
  269 +
  270 + //set the render mode to selection
  271 + glRenderMode(GL_SELECT);
  272 +
  273 + //we pick the object with the assumption that the active projection
  274 + //matrix is the one used to display the object in the viewport
  275 +
  276 + //get the current projection matrix
  277 + float projection[16];
  278 + glGetFloatv(GL_PROJECTION_MATRIX, projection);
  279 +
  280 + //save and reset the current projection matrix
  281 + glMatrixMode(GL_PROJECTION);
  282 + glPushMatrix();
  283 + glLoadIdentity();
  284 +
  285 + //set the picking matrix using GLU
  286 + gluPickMatrix(x, viewport[3] - y, size_x, size_y, viewport);
  287 + //multiply in the saved projection matrix
  288 + glMultMatrixf(projection);
  289 +
  290 + //Draw the object with names for each primitive.
  291 +
  292 + int num_prim = primitives.size(); //get the number of primitives
  293 + glInitNames(); //set the name stack to zero
  294 + for(int p = 0; p < num_prim; p++)
  295 + {
  296 + glPushName(p); //push the name on to the stack
  297 + f_RenderPrimitive(p); //render the primitive
  298 + glPopName();
  299 + }
  300 +
  301 + glFinish(); //force the rendering to complete
  302 +
  303 + hits = glRenderMode(GL_RENDER); //find the number of hits
  304 +
  305 + if(hits) //if there is a hit, select the OBJ and the primitive
  306 + {
  307 + is_selected = true; //select the object
  308 +
  309 + //if this is a new selection, clear the list
  310 + if(picktype == RTS_GLOBJ_SINGLE_NEW_SELECTION ||
  311 + picktype == RTS_GLOBJ_MULTI_NEW_SELECTION)
  312 + selected_primitives.clear();
  313 +
  314 + //if this is adding multiple hits to the selection list
  315 + if(picktype == RTS_GLOBJ_MULTI_NEW_SELECTION ||
  316 + picktype == RTS_GLOBJ_MULTI_ADD_SELECTION)
  317 + SelectMultipleHits(selectBuf, hits);
  318 +
  319 + if(picktype == RTS_GLOBJ_SINGLE_NEW_SELECTION ||
  320 + picktype == RTS_GLOBJ_SINGLE_ADD_SELECTION)
  321 + SelectClosestHit(selectBuf, hits);
  322 +
  323 + if(picktype == RTS_GLOBJ_SINGLE_SUB_SELECTION)
  324 + UnselectClosestHit(selectBuf, hits);
  325 +
  326 + if(picktype == RTS_GLOBJ_MULTI_SUB_SELECTION)
  327 + UnselectMultipleHits(selectBuf, hits);
  328 + //SelectPrimitive(processHits(selectBuf, hits), picktype);
  329 + //selected_primitives.clear();
  330 +
  331 + //select the primitive
  332 + //selected_primitives.push_back(processHits(selectBuf, hits));
  333 + }
  334 + else
  335 + is_selected = false;
  336 +
  337 + //restore the previous projection matrix
  338 + glMatrixMode(GL_PROJECTION);
  339 + glPopMatrix();
  340 +
  341 +}
  342 +rts_glOBJ rts_glOBJ::GetSelected()
  343 +{
  344 + //right now this creates duplicate vertices
  345 +
  346 + rts_glOBJ result;
  347 +
  348 + //for each primitive
  349 + list<unsigned int>::iterator p;
  350 + for(p = selected_primitives.begin(); p != selected_primitives.end(); p++)
  351 + {
  352 + primitive selected_prim = primitives[(*p)];
  353 + //create a new primitive
  354 + primitive new_prim;
  355 + new_prim.mask = selected_prim.mask;
  356 + new_prim.type = selected_prim.type;
  357 +
  358 + //for each vertex in the primitive
  359 + int num_vertices = selected_prim.p.size();
  360 + for(int v = 0; v<num_vertices; v++)
  361 + {
  362 + vertex new_vert;
  363 + if(new_prim.mask & OBJ_V) //if the primitive has a vertex coord
  364 + {
  365 + new_vert.v = result.v_list.size();
  366 + new_prim.p.push_back(new_vert);
  367 + result.v_list.push_back(v_list[selected_prim.p[v].v]);
  368 + }
  369 + }
  370 + result.primitives.push_back(new_prim);
  371 + }
  372 +
  373 + return result;
  374 +
  375 +
  376 +}
  377 +
  378 +void rts_glOBJ::ExpandSelection()
  379 +{
  380 + /*
  381 + //create a list of all selected vertices
  382 + list<unsigned int> selected_v;
  383 +
  384 + list<unsigned int>::iterator p; //selected primitive
  385 + vector<vertex>::iterator v; //vertex
  386 +
  387 + //insert all selected vertex indices into selected_v
  388 + for(p = selected_primitives.begin(); p!=selected_primitives.end(); p++)
  389 + {
  390 + for(v=primitives[(*p)].p.begin(); v!=primitives[(*p)].p.end(); v++)
  391 + {
  392 + selected_v.push_back((*v).v);
  393 + }
  394 + }
  395 + selected_v.unique(); //remove redundant entries
  396 +
  397 + //now find all primitives connected to these vertices
  398 + int num_primitives = primitives.size();
  399 + int prim;
  400 + list<unsigned int>::iterator s_v;
  401 + for(prim =0; prim<num_primitives; prim++)
  402 + {
  403 + for(v=primitives[prim].p.begin(); v!=primitives[prim].p.end(); v++)
  404 + {
  405 + for(s_v = selected_v.begin(); s_v!=selected_v.end(); s_v++)
  406 + {
  407 + if((*s_v) == (*v).v)
  408 + {
  409 + selected_primitives.push_back(prim);
  410 + }
  411 + }
  412 + }
  413 + }
  414 + selected_primitives.unique();
  415 +
  416 + */
  417 +
  418 +
  419 + //create the vertex-primitive list
  420 + vector<unsigned int>* vertex_to_prim = new vector<unsigned int>[v_list.size()];
  421 + int num_primitives = primitives.size();
  422 + int p;
  423 + int num_vertices, v;
  424 + int vertex;
  425 + for(p=0; p<num_primitives; p++)
  426 + {
  427 + num_vertices = primitives[p].p.size();
  428 + for(v = 0; v<num_vertices; v++)
  429 + {
  430 + vertex = primitives[p].p[v].v;
  431 + vertex_to_prim[vertex].push_back(p);
  432 + }
  433 + }
  434 +
  435 + //create the list of selected vertices
  436 + list<unsigned int> selected_verts;
  437 + list<unsigned int>::iterator sel;
  438 + for(sel = selected_primitives.begin(); sel != selected_primitives.end(); sel++)
  439 + {
  440 + num_vertices = primitives[(*sel)].p.size();
  441 + for(v=0; v<num_vertices; v++)
  442 + {
  443 + selected_verts.push_back(primitives[(*sel)].p[v].v);
  444 + }
  445 + }
  446 + selected_verts.unique();
  447 +
  448 + //erase the selected array
  449 + selected_primitives.clear();
  450 + list<unsigned int>::iterator s_v;
  451 + for(s_v = selected_verts.begin(); s_v != selected_verts.end(); s_v++)
  452 + {
  453 + num_primitives = vertex_to_prim[(*s_v)].size();
  454 + for(p=0; p<num_primitives; p++)
  455 + selected_primitives.push_back(vertex_to_prim[(*s_v)][p]);
  456 + }
  457 + cout<<"Before: "<<selected_primitives.size()<<endl;
  458 +
  459 + selected_primitives.sort();
  460 + selected_primitives.unique();
  461 + cout<<"After: "<<selected_primitives.size()<<endl;
  462 +
  463 +
  464 +
  465 +}
0 466 \ No newline at end of file
... ...
rts_glOBJ.h 0 → 100755
  1 +++ a/rts_glOBJ.h
  1 +#ifndef RTS_GLOBJ_H
  2 +#define RTS_GLOBJ_H
  3 +
  4 +#include "objJedi.h"
  5 +#include <windows.h>
  6 +#include <gl/gl.h>
  7 +#include <gl/glu.h>
  8 +#include <list>
  9 +
  10 +using namespace std;
  11 +
  12 +#define BUFSIZE 20000
  13 +
  14 +#define OBJ_NOT_SELECTED 0x0000
  15 +#define OBJ_SELECTED 0x0001
  16 +#define OBJ_SELECTED_PRIMITIVES 0x0002
  17 +
  18 +#define RTS_GLOBJ_SINGLE_NEW_SELECTION 0
  19 +#define RTS_GLOBJ_SINGLE_ADD_SELECTION 1
  20 +#define RTS_GLOBJ_SINGLE_SUB_SELECTION 2
  21 +
  22 +#define RTS_GLOBJ_MULTI_NEW_SELECTION 3
  23 +#define RTS_GLOBJ_MULTI_ADD_SELECTION 4
  24 +#define RTS_GLOBJ_MULTI_SUB_SELECTION 5
  25 +
  26 +class rts_glOBJ : public rtsOBJ
  27 +{
  28 +private:
  29 + int is_selected; //the object, or part of the object, is selected
  30 + list<unsigned int> selected_primitives;
  31 +
  32 + //rendering variables
  33 + GLint dl;
  34 + bool dl_valid; //true if the display list is valid
  35 +
  36 + OBJint f_CreateDisplayList();
  37 +
  38 + void f_RenderPointList(unsigned int pointlist);
  39 + void f_RenderLineStrip(unsigned int line);
  40 + void f_RenderFace(unsigned int face);
  41 +
  42 + OBJint f_RenderTexCoord(vertex_texture &texcoord);
  43 + OBJint f_RenderNormal(vertex_normal &normal);
  44 + OBJint f_RenderVertex(vertex_position &v);
  45 + OBJint f_RenderPrimitive(unsigned int id);
  46 +
  47 + void SelectMultipleHits(GLuint* buffer, unsigned int num_hits);
  48 + void SelectClosestHit(GLuint* buffer, unsigned int num_hits);
  49 + void SelectPrimitive(unsigned int primitive);
  50 + void UnselectMultipleHits(GLuint* buffer, unsigned int num_hits);
  51 + void UnselectClosestHit(GLuint* buffer, unsigned int num_hits);
  52 + void UnselectPrimitive(unsigned int primitive);
  53 +
  54 +public:
  55 + //constructors
  56 + //basic
  57 + rts_glOBJ()
  58 + {
  59 + is_selected = false;
  60 + dl_valid = false;
  61 + cout<<selected_primitives.size()<<endl;
  62 + }
  63 + //assignment
  64 + rts_glOBJ& operator=(const rtsOBJ& obj)
  65 + {
  66 + CopyOBJ(obj);
  67 + is_selected = false;
  68 + dl_valid = false;
  69 + return *this;
  70 + }
  71 + //copy
  72 + rts_glOBJ(const rtsOBJ& obj)
  73 + {
  74 + CopyOBJ(obj);
  75 + is_selected = false;
  76 + dl_valid = false;
  77 + //return *this;
  78 + }
  79 +
  80 + OBJint glRender();
  81 + OBJint glRenderSelected();
  82 + void Invalidate(){dl_valid = false;} //invalidate the display list
  83 +
  84 + //return true of the object is currently selected
  85 + int selected(){return is_selected;};
  86 + //unsigned int getSelected(unsigned int i = 0){return selected_primitives[i];}
  87 + void Pick(unsigned int x, unsigned int y, unsigned int size_x, unsigned int size_y, unsigned int picktype = RTS_GLOBJ_SINGLE_NEW_SELECTION);
  88 + rts_glOBJ GetSelected();
  89 + void ExpandSelection();
  90 +
  91 +};
  92 +
  93 +#endif
0 94 \ No newline at end of file
... ...
rts_glRenderToTexture.cpp 0 → 100755
  1 +++ a/rts_glRenderToTexture.cpp
  1 +#include "rts_glRenderToTexture.h"
  2 +
  3 +void rts_glRenderToTexture::Clean()
  4 +{
  5 + //clean up the fbo
  6 + glDeleteFramebuffersEXT(1, &fbo);
  7 + int num_tex = textures.size();
  8 +
  9 + //clean up all textures associated with the fbo
  10 + for(int i=0; i<num_tex; i++)
  11 + textures[i].Clean();
  12 + textures.clear();
  13 +
  14 + fbo = 0;
  15 +}
  16 +
  17 +void rts_glRenderToTexture::Init(int w, int h)
  18 +{
  19 + CHECK_OPENGL_ERROR
  20 + if(fbo != 0)
  21 + Clean();
  22 + CHECK_OPENGL_ERROR
  23 + glGenFramebuffersEXT(1, &fbo); //create the framebuffer object
  24 + CHECK_OPENGL_ERROR
  25 + width = w;
  26 + height = h;
  27 +
  28 +}
  29 +
  30 +void rts_glRenderToTexture::AddTexture(GLenum target,
  31 + GLint internalformat,
  32 + GLenum format,
  33 + GLenum datatype,
  34 + GLint interpolation)
  35 +{
  36 +
  37 + //create the new texture
  38 + rts_glTextureMap new_texture;
  39 + new_texture.Init(NULL,
  40 + target,
  41 + width,
  42 + height,
  43 + 0,
  44 + internalformat,
  45 + format,
  46 + datatype,
  47 + interpolation);
  48 + //push it into the texture vector
  49 + textures.push_back(new_texture);
  50 + cout<<"Texture Name: "<<new_texture.name<<endl;
  51 +
  52 + //bind it to the frame buffer
  53 +
  54 + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
  55 + CHECK_OPENGL_ERROR
  56 + glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
  57 + GL_COLOR_ATTACHMENT0 + textures.size() - 1,
  58 + target,
  59 + new_texture.name,
  60 + 0);
  61 +
  62 + CHECK_OPENGL_ERROR
  63 + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
  64 + CHECK_OPENGL_ERROR
  65 + if(status != GL_FRAMEBUFFER_COMPLETE)
  66 + cout<<"Framebuffer status invalid!"<<endl;
  67 +
  68 + //restore normal rendering
  69 + glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
  70 +
  71 +}
  72 +
  73 +void rts_glRenderToTexture::BeginRender(int texture)
  74 +{
  75 +
  76 + //bind the framebuffer
  77 + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
  78 + glDrawBuffer(GL_COLOR_ATTACHMENT0+texture);
  79 +}
  80 +
  81 +void rts_glRenderToTexture::EndRender()
  82 +{
  83 + //glFinish();
  84 + //bind the screen buffer
  85 + glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
  86 +}
0 87 \ No newline at end of file
... ...
rts_glRenderToTexture.h 0 → 100755
  1 +++ a/rts_glRenderToTexture.h
  1 +#ifndef RTS_GLRENDERTOTEXTURE_H
  2 +#define RTS_GLRENDERTOTEXTURE_H
  3 +//#include <gl/gl.h>
  4 +#include <vector>
  5 +#include "rts_glTextureMap.h"
  6 +
  7 +using namespace std;
  8 +
  9 +class rts_glRenderToTexture
  10 +{
  11 +private:
  12 + bool init;
  13 +
  14 + GLuint fbo; //framebuffer object
  15 + int width; //width and height of the framebuffer
  16 + int height;
  17 + vector<rts_glTextureMap> textures;
  18 +
  19 +public:
  20 + //constructors
  21 + rts_glRenderToTexture(){init = false; fbo = 0;}
  22 + rts_glRenderToTexture(int width, int height){Init(width, height);}
  23 +
  24 + void Init(int width, int height); //initialization
  25 + void Clean();
  26 +
  27 + void AddTexture(GLenum target,
  28 + GLint internalformat = 1,
  29 + GLenum format = GL_LUMINANCE,
  30 + GLenum datatype = GL_UNSIGNED_BYTE,
  31 + GLint interpolation = GL_NEAREST);
  32 + void BeginTexture(int texture){textures[texture].BeginTexture();}
  33 + void EndTexture(int texture){textures[texture].EndTexture();}
  34 + rts_glTextureMap GetTexture(int texture){return textures[texture];}
  35 +
  36 + void BeginRender(int texture);
  37 + void EndRender();
  38 +
  39 + int Width(){return width;}
  40 + int Height(){return height;}
  41 + void UseMaxViewport(){glViewport(0, 0, width, height);}
  42 +
  43 +};
  44 +
  45 +#endif
... ...
rts_glRenderableDTGrid.cpp 0 → 100755
  1 +++ a/rts_glRenderableDTGrid.cpp
  1 +#include "rts_glRenderableDTGrid.h"
  2 +
  3 +
  4 +/*ITERATOR INITIALIZATION*/
  5 +void rts_glRenderableDTGrid::init_iter_ppp()
  6 +{
  7 + m_iterator = begin();
  8 + m_iter_type = PPP;
  9 +}
  10 +void rts_glRenderableDTGrid::init_iter_nnn()
  11 +{
  12 + m_iterator = last();
  13 + m_iter_type = NNN;
  14 +}
  15 +void rts_glRenderableDTGrid::init_iter_ppn()
  16 +{
  17 + m_iterator = begin(); //put the iterator at the beginning of the data set
  18 +
  19 + if(m_iterator.grid->acc.size() > 1) //if there is more than one pcolumn
  20 + {
  21 + m_iterator.loc.iv = m_iterator.grid->proj2D.value[1].to_value - 1;
  22 + m_iterator.loc.z = zCoord[m_iterator.grid->proj2D.value[1].to_coord - 1];
  23 + }
  24 + else
  25 + {
  26 + m_iterator.loc.iv = value.size() - 1;
  27 + m_iterator.loc.z = zCoord.back();
  28 + }
  29 + m_iter_type = PPN;
  30 +}
  31 +
  32 +void rts_glRenderableDTGrid::init_iter_npp()
  33 +{
  34 + //set the 1D iterator location
  35 + m_iterator.Iterator2D.Iterator1D.loc.iv = proj2D.proj1D.value.size()-1; //start at the last 1D p-column
  36 + m_iterator.Iterator2D.Iterator1D.loc.ic = proj2D.proj1D.xCoord.size() - 2;
  37 + m_iterator.Iterator2D.Iterator1D.loc.x = proj2D.proj1D.xCoord[m_iterator.Iterator2D.Iterator1D.loc.ic+1];
  38 + m_iterator.Iterator2D.Iterator1D.value = proj2D.proj1D.value[m_iterator.Iterator2D.Iterator1D.loc.iv];
  39 + m_iterator.Iterator2D.Iterator1D.grid = &(proj2D.proj1D);
  40 +
  41 + //set the 2D iterator location
  42 + m_iterator.Iterator2D.loc.iv = proj2D.proj1D.value[m_iterator.Iterator2D.Iterator1D.loc.iv].to_value;
  43 + m_iterator.Iterator2D.loc.ic = proj2D.proj1D.value[m_iterator.Iterator2D.Iterator1D.loc.iv].to_coord;
  44 + m_iterator.Iterator2D.loc.y = proj2D.yCoord[m_iterator.Iterator2D.loc.ic];
  45 + m_iterator.Iterator2D.value = proj2D.value[m_iterator.Iterator2D.loc.iv];
  46 + m_iterator.Iterator2D.grid = &(proj2D);
  47 +
  48 + //set the 3D iterator location
  49 + m_iterator.loc.iv = proj2D.value[m_iterator.Iterator2D.loc.iv].to_value;
  50 + m_iterator.loc.ic = proj2D.value[m_iterator.Iterator2D.loc.iv].to_coord;
  51 + m_iterator.loc.z = zCoord[m_iterator.loc.ic];
  52 + m_iterator.value = value[m_iterator.loc.iv];
  53 + m_iterator.grid = this;
  54 +
  55 + m_iter_type = NPP;
  56 +}
  57 +
  58 +void rts_glRenderableDTGrid::iter_next_npp()
  59 +{
  60 + //if we are at the end of a p-column
  61 + if(m_iterator.loc.iv == value.size() - 1 || //if we are at the end of the last p-column or
  62 + (m_iterator.Iterator2D.loc.iv != m_iterator.grid->proj2D.value.size() - 1 &&
  63 + m_iterator.loc.iv == proj2D.value[m_iterator.Iterator2D.loc.iv + 1].to_value - 1)) //we are at the end of a p-column
  64 + {
  65 + iter_next_npx(m_iterator.Iterator2D); //increment the 2D iterator
  66 + m_iterator.loc.iv = proj2D.value[m_iterator.Iterator2D.loc.iv].to_value;
  67 + m_iterator.loc.ic = proj2D.value[m_iterator.Iterator2D.loc.iv].to_coord;
  68 + m_iterator.loc.z = zCoord[m_iterator.loc.ic];
  69 + }
  70 + //if we are at the end of a connected component
  71 + else if(m_iterator.loc.z == zCoord[m_iterator.loc.ic+1])
  72 + {
  73 + m_iterator.loc.iv++;
  74 + m_iterator.loc.ic+=2;
  75 + m_iterator.loc.z = zCoord[m_iterator.loc.ic];
  76 + }
  77 + //else if we are in a p-column
  78 + else
  79 + {
  80 + m_iterator.loc.iv++;
  81 + m_iterator.loc.z++;
  82 + }
  83 + m_iterator.value = value[m_iterator.loc.iv];
  84 +}
  85 +
  86 +void rts_glRenderableDTGrid::iter_next_ppn()
  87 +{
  88 + //if we are at the beginning of a p-column
  89 + if(m_iterator.loc.z == zCoord[m_iterator.loc.ic] &&
  90 + m_iterator.loc.ic == proj2D.value[m_iterator.Iterator2D.loc.iv].to_coord)
  91 + {
  92 + m_iterator.Iterator2D.increment(); //move to the next p-column
  93 + if(m_iterator.Iterator2D.loc.iv >= proj2D.value.size()) //return
  94 + return;
  95 + //now update the 3D locator
  96 + if(m_iterator.Iterator2D.loc.iv == proj2D.value.size() - 1) //if this is the last p-column
  97 + {
  98 + m_iterator.loc.iv = value.size() - 1;
  99 + m_iterator.loc.ic = zCoord.size() - 2;
  100 + m_iterator.loc.z = zCoord.back();
  101 + }
  102 + else
  103 + {
  104 + m_iterator.loc.iv = proj2D.value[m_iterator.Iterator2D.loc.iv+1].to_value - 1;
  105 + m_iterator.loc.ic = proj2D.value[m_iterator.Iterator2D.loc.iv+1].to_coord - 2;
  106 + m_iterator.loc.z = zCoord[m_iterator.loc.ic + 1];
  107 + }
  108 + }
  109 + //if we are at the beginning of a connected component
  110 + else if(m_iterator.loc.z == zCoord[m_iterator.loc.ic])
  111 + {
  112 + m_iterator.loc.iv-=1;
  113 + m_iterator.loc.ic-=2;
  114 + m_iterator.loc.z = zCoord[m_iterator.loc.ic + 1];
  115 + }
  116 + //if we're in the middle of a connected component
  117 + else
  118 + {
  119 + m_iterator.loc.iv--;
  120 + m_iterator.loc.z--;
  121 + }
  122 + m_iterator.value = value[m_iterator.loc.iv];
  123 +}
  124 +
  125 +void rts_glRenderableDTGrid::iter_next_npx(rtsDTGrid2D<IndexPair>::iterator &i2d)
  126 +{
  127 + //if we are at the end of a p-column
  128 + if(i2d.loc.iv == i2d.grid->value.size() - 1 || //if this is the last p-column
  129 + (i2d.Iterator1D.loc.iv != i2d.grid->proj1D.value.size() - 1 && //we are not in the last p-column and
  130 + i2d.loc.iv == i2d.grid->proj1D.value[i2d.Iterator1D.loc.iv+1].to_value - 1))
  131 + {
  132 + //if(i2d.Iterator1D.loc.iv == 0) //if it is the first p-column
  133 + // return;
  134 + i2d.Iterator1D.decrement(); //decrement the 1D iterator
  135 + //update the 2D locator
  136 + i2d.loc.iv = i2d.grid->proj1D.value[i2d.Iterator1D.loc.iv].to_value;
  137 + i2d.loc.ic = i2d.grid->proj1D.value[i2d.Iterator1D.loc.iv].to_coord;
  138 + i2d.loc.y = i2d.grid->yCoord[i2d.loc.ic];
  139 + }
  140 + //if we are at the end of a connected component
  141 + else if(i2d.loc.y == i2d.grid->yCoord[i2d.loc.ic+1])
  142 + {
  143 + i2d.loc.iv++;
  144 + i2d.loc.ic+=2;
  145 + i2d.loc.y = i2d.grid->yCoord[i2d.loc.ic];
  146 + }
  147 + else
  148 + {
  149 + i2d.loc.iv++;
  150 + i2d.loc.y++;
  151 + }
  152 + //set value
  153 + i2d.value = i2d.grid->value[i2d.loc.iv];
  154 +}
  155 +
  156 +
  157 +void rts_glRenderableDTGrid::iter_next()
  158 +{
  159 + if(m_iter_type == PPP)
  160 + m_iterator.increment();
  161 + if(m_iter_type == NNN)
  162 + m_iterator.decrement();
  163 + if(m_iter_type == PPN)
  164 + iter_next_ppn();
  165 + if(m_iter_type == NPP)
  166 + iter_next_npp();
  167 +}
  168 +void rts_glRenderableDTGrid::RenderPoints(unsigned int size, float camera_x, float camera_y, float camera_z)
  169 +{
  170 + /*This function renders a single point to the screen for each voxel in the
  171 + DT-Grid.
  172 + */
  173 + //determine which directions to iterate
  174 + if(camera_x > 0)
  175 + {
  176 + if(camera_y > 0)
  177 + {
  178 + if(camera_z > 0)
  179 + {
  180 + //cout<<"+++"<<endl;
  181 + init_iter_ppp();
  182 + }
  183 + else
  184 + {
  185 + //cout<<"++-"<<endl;
  186 + init_iter_ppn();
  187 + }
  188 + }
  189 + else
  190 + {
  191 + if(camera_z > 0)
  192 + {
  193 + //cout<<"+-+"<<endl;
  194 + init_iter_ppp();
  195 + }
  196 + else
  197 + {
  198 + //cout<<"+--"<<endl;
  199 + init_iter_ppp();
  200 + }
  201 + }
  202 + }
  203 + else
  204 + {
  205 + if(camera_y > 0)
  206 + {
  207 + if(camera_z > 0)
  208 + {
  209 + //cout<<"-++"<<endl;
  210 + init_iter_npp();
  211 + }
  212 + else
  213 + {
  214 + //cout<<"-+-"<<endl;
  215 + init_iter_nnn();
  216 + }
  217 + }
  218 + else
  219 + {
  220 + if(camera_z > 0)
  221 + {
  222 + //cout<<"--+"<<endl;
  223 + init_iter_nnn();
  224 + }
  225 + else
  226 + {
  227 + //cout<<"---"<<endl;
  228 + init_iter_nnn();
  229 + }
  230 + }
  231 + }
  232 +
  233 +
  234 + //init_iter_npp();
  235 +
  236 +
  237 + glPointSize(3);
  238 + glDisable(GL_DEPTH_TEST);
  239 + glEnable(GL_BLEND);
  240 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  241 +
  242 +
  243 +
  244 + glBegin(GL_POINTS); //render voxels as points
  245 + unsigned int i;
  246 + unsigned int num_values = value.size();
  247 + for(i=0; i<num_values; i++)
  248 + {
  249 + glColor4f(m_iterator.value.r, m_iterator.value.g, m_iterator.value.b, m_iterator.value.a);
  250 + glVertex3f(m_iterator.getX()/(float)MaxX(), m_iterator.getY()/(float)MaxY(), m_iterator.getZ()/(float)MaxZ());
  251 + //cout<<"("<<m_iterator.getX()<<","<<m_iterator.getY()<<","<<m_iterator.getZ()<<"):"<<m_iterator.value<<endl;
  252 + iter_next();
  253 + }
  254 + //cout<<"---------------------------------------"<<endl;
  255 + i=0;
  256 + glEnd();
  257 +
  258 + glDisable(GL_BLEND);
  259 + glEnable(GL_DEPTH_TEST);
  260 +}
0 261 \ No newline at end of file
... ...
rts_glRenderableDTGrid.h 0 → 100755
  1 +++ a/rts_glRenderableDTGrid.h
  1 +#ifndef RTS_GLRENDERABLEDTGRID_H
  2 +#define RTS_GLRENDERABLEDTGRID_H
  3 +
  4 +#include "gl/glew.h"
  5 +#include "gl/gl.h"
  6 +#include "rtsDTGrid3D.h"
  7 +
  8 +enum IteratorType {PPP, PPN, PNP, PNN, NPP, NPN, NNP, NNN};
  9 +
  10 +struct ValueType
  11 +{
  12 + float r;
  13 + float g;
  14 + float b;
  15 + float a;
  16 +};
  17 +
  18 +
  19 +class rts_glRenderableDTGrid : public rtsDTGrid3D<ValueType>
  20 +{
  21 +private:
  22 + IteratorType m_iter_type;
  23 + rtsDTGrid3D<ValueType>::iterator m_iterator;
  24 + void init_iter_ppp();
  25 + void init_iter_ppn();
  26 + void iter_next_ppn();
  27 + void init_iter_npp();
  28 + void iter_next_npp();
  29 + void init_iter_nnn();
  30 + void iter_next_npx(rtsDTGrid2D<IndexPair>::iterator &i2d);
  31 + void iter_next();
  32 +public:
  33 + void RenderPoints(unsigned int size, float camera_x, float camera_y, float camera_z);
  34 +
  35 +};
  36 +
  37 +
  38 +#endif
0 39 \ No newline at end of file
... ...
rts_glShaderObject.h 0 → 100755
  1 +++ a/rts_glShaderObject.h
  1 +#ifndef RTS_GLSHADERS
  2 +#define RTS_GLSHADERS
  3 +
  4 +#include <GL/glew.h>
  5 +//#include "windows.h"
  6 +#include <GL/gl.h>
  7 +#include "rtsSourceCode.h"
  8 +
  9 +class rts_glShaderObject
  10 +{
  11 +private:
  12 + void init()
  13 + {
  14 + id = 0;
  15 + compiled = false;
  16 + type = GL_FRAGMENT_SHADER;
  17 + }
  18 +public:
  19 + bool compiled;
  20 + GLenum type;
  21 + rtsSourceCode source;
  22 + GLuint id;
  23 + string log;
  24 +
  25 + rts_glShaderObject(GLenum type, const char* filename)
  26 + {
  27 + init(); //initialize the shader
  28 + SetType(type); //set the shader type
  29 + LoadSource(filename); //load the source code
  30 + }
  31 + rts_glShaderObject(GLenum type, rtsSourceCode sourceCode)
  32 + {
  33 + init(); //initialize the shader
  34 + SetType(type); //set the shader type
  35 + source = sourceCode;
  36 + }
  37 + rts_glShaderObject()
  38 + {
  39 + init();
  40 + }
  41 + rts_glShaderObject(GLenum type)
  42 + {
  43 + init();
  44 + SetType(type);
  45 + }
  46 + void LoadSource(const char* filename)
  47 + {
  48 + source = rtsSourceCode(filename); //get the shader source code
  49 +
  50 + }
  51 + void SetType(GLenum type)
  52 + {
  53 + if(id != 0) //if a shader currently exists, delete it
  54 + {
  55 + glDeleteShader(id);
  56 + id = 0;
  57 + }
  58 + type = type;
  59 + id = glCreateShader(type); //create a shader object
  60 + if(id == 0) //if a shader was not created, log an error
  61 + {
  62 + log = "Error getting shader ID from OpenGL";
  63 + return;
  64 + }
  65 + }
  66 + void UploadSource()
  67 + {
  68 + //create the structure for the shader source code
  69 + GLsizei count = source.source.size();
  70 + GLchar** code_string = new GLchar*[count];
  71 + GLint* length = new GLint[count];
  72 + for(int l = 0; l<count; l++) //for each line of code
  73 + {
  74 + length[l] = source.source[l].size();
  75 + code_string[l] = new GLchar[length[l]]; //copy the string into a new structure
  76 + source.source[l].copy(code_string[l], (unsigned int)length[l]);
  77 +
  78 + }
  79 + glShaderSource(id, count, (const GLchar**)code_string, length); //attach the shader source
  80 + }
  81 + void Compile()
  82 + {
  83 + /*
  84 + This function compiles the shader source code, records any errors to a log, and sets the compiled flag.
  85 + */
  86 + //send the source code to the GPU
  87 + UploadSource();
  88 +
  89 + //compile the shader
  90 + glCompileShader(id); //compile the shader
  91 + GLint compile_status;
  92 + glGetShaderiv(id, GL_COMPILE_STATUS, &compile_status); //get the compile status
  93 + if(compile_status != GL_TRUE) //if there was an error
  94 + {
  95 + GLchar buffer[1000]; //create a log buffer
  96 + GLsizei length;
  97 + glGetShaderInfoLog(id, 1000, &length, buffer); //get the log
  98 + log = buffer;
  99 + compiled = false;
  100 + }
  101 + else
  102 + compiled = true;
  103 +
  104 + }
  105 + void PrintLog()
  106 + {
  107 + cout<<log;
  108 + if(log.size() != 0) cout<<endl;
  109 + }
  110 + void Clean(){if(id != 0) glDeleteShader(id);}
  111 +};
  112 +
  113 +
  114 +
  115 +#endif
... ...
rts_glShaderProgram.h 0 → 100755
  1 +++ a/rts_glShaderProgram.h
  1 +#ifndef RTS_GLSHADERPROGRAM_H
  2 +#define RTS_GLSHADERPROGRAM_H
  3 +
  4 +/*********************************************************
  5 +//create a shader program
  6 + rts_glShaderProgram myProgram;
  7 +//initialize
  8 + myProgram.Init();
  9 +//Attach shaders
  10 + myProgram.AttachShader(GL_FRAGMENT_SHADER, "filename.glsl");
  11 +//Compile and link
  12 + myProgram.Compile();
  13 + myProgram.Link();
  14 + myProgram.PrintLog();
  15 +//attach uniform variables
  16 + myProgram.AttachTextureMap("texture", texture);
  17 + myProgram.AttachGlobalUniform("light_intensity", &intensity);
  18 +
  19 +//use the program
  20 + myProgram.BeginProgram();
  21 + //render
  22 + myProgram.EndProgram();
  23 +**********************************************************/
  24 +
  25 +
  26 +#include "rts_glShaderObject.h"
  27 +#include "rts_glShaderUniform.h"
  28 +#include "rts_glTextureMap.h"
  29 +#include <algorithm>
  30 +
  31 +using namespace std;
  32 +
  33 +class rts_glShaderProgram
  34 +{
  35 +private:
  36 + void get_uniforms()
  37 + {
  38 + GLint num_uniforms;
  39 + glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &num_uniforms); //get the number of uniform variables
  40 + GLint max_name_length;
  41 + glGetProgramiv(id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); //get the maximum uniform name length
  42 + GLchar* name_buffer = new GLchar[max_name_length]; //create a buffer to store the name
  43 + GLsizei length; //I'm not using these yet
  44 + GLint size;
  45 + GLenum type; //variable's data type
  46 + GLint location; //GPU location of the variable
  47 + for(int i=0; i<num_uniforms; i++) //create an rts_glShaderUniform structure for each variable
  48 + {
  49 + glGetActiveUniform(id, i, max_name_length, &length, &size, &type, name_buffer); //get the uniform information
  50 + location = glGetUniformLocation(id, name_buffer); //get the GPU location of the variable
  51 + //create the rts_glShaderUniform structure
  52 + rts_glShaderUniform current;
  53 + current.location = location;
  54 + current.name = name_buffer;
  55 + current.type = type;
  56 + current.p_value = NULL;
  57 +
  58 +
  59 + uniform_list.push_back(current);
  60 + }
  61 +
  62 + }
  63 + int get_index(const char* name)
  64 + {
  65 + unsigned int size = uniform_list.size();
  66 + for(unsigned int i=0; i<size; i++)
  67 + {
  68 + if(uniform_list[i].name == name)
  69 + return i;
  70 + }
  71 + return -1;
  72 + }
  73 + string log;
  74 +public:
  75 + GLuint id;
  76 + bool linked;
  77 + vector<rts_glShaderObject> shader_list; //list of opengl shaders
  78 + vector<rts_glShaderUniform> uniform_list; //list of active uniform variables
  79 + vector<rts_glTextureMap> texture_list; //list of texture maps
  80 +
  81 + rts_glShaderProgram()
  82 + {
  83 + linked = false;
  84 + id = 0;
  85 + }
  86 + void AttachShader(rts_glShaderObject shader)
  87 + {
  88 + if(id == 0)
  89 + {
  90 + Init();
  91 + }
  92 + if(shader.id == 0) //if the shader is invalid
  93 + {
  94 + log = "Shader is invalid";
  95 + return;
  96 + }
  97 +
  98 + //attach the shader to the program
  99 + glAttachShader(id, shader.id); //attach the shader to the program in OpenGL
  100 + CHECK_OPENGL_ERROR
  101 + shader_list.push_back(shader); //push the shader onto our list for later access
  102 + }
  103 + //type = GL_FRAGMENT_SHADER or GL_VERTEX_SHADER
  104 + void AttachShader(GLenum type, const char* filename)
  105 + {
  106 + rts_glShaderObject shader(type, filename);
  107 + AttachShader(shader);
  108 + }
  109 + void AttachShader(GLenum type, rtsSourceCode source)
  110 + {
  111 + rts_glShaderObject shader(type, source);
  112 + AttachShader(shader);
  113 + }
  114 + void PrintLog()
  115 + {
  116 + cout<<log;
  117 +
  118 + if(log.size() != 0) cout<<endl;
  119 + }
  120 + void Compile()
  121 + {
  122 + if(shader_list.size() == 0)
  123 + {
  124 + log = "No shaders to compile";
  125 + return;
  126 + }
  127 +
  128 + vector<rts_glShaderObject>::iterator iter;
  129 + for(iter = shader_list.begin(); iter != shader_list.end(); iter++)
  130 + {
  131 + (*iter).Compile();
  132 + //(*iter).PrintLog();
  133 + }
  134 + }
  135 + void Link()
  136 + {
  137 + glLinkProgram(id); //link the current shader program
  138 + GLint link_status; //test to see if the link went alright
  139 + glGetProgramiv(id, GL_LINK_STATUS, &link_status);
  140 + if(link_status != GL_TRUE)
  141 + {
  142 + linked = false;
  143 + }
  144 + else
  145 + linked = true;
  146 +
  147 + GLsizei length;
  148 + GLchar buffer[1000];
  149 + glGetProgramInfoLog(id, 1000, &length, buffer);
  150 + log = buffer;
  151 +
  152 + get_uniforms(); //create the list of active uniform variables
  153 + }
  154 + void BeginProgram()
  155 + {
  156 + CHECK_OPENGL_ERROR
  157 + if(id == 0) //if the program is invalid, return
  158 + {
  159 + log = "Invalid program, cannot use.";
  160 + return;
  161 + }
  162 + if(!linked)
  163 + {
  164 + cout<<"Shader Program used without being linked."<<endl;
  165 + //exit(1);
  166 + }
  167 +
  168 + //set up all of the texture maps
  169 + int num_textures = texture_list.size();
  170 +
  171 + for(int t=0; t<num_textures; t++)
  172 + {
  173 + glActiveTexture(GL_TEXTURE0 + t);
  174 + CHECK_OPENGL_ERROR
  175 + //glEnable(texture_list[t].texture_type);
  176 + //CHECK_OPENGL_ERROR
  177 + glBindTexture(texture_list[t].texture_type, texture_list[t].name);
  178 + CHECK_OPENGL_ERROR
  179 + }
  180 +
  181 + glUseProgram(id);
  182 + CHECK_OPENGL_ERROR
  183 + }
  184 + void EndProgram()
  185 + {
  186 + CHECK_OPENGL_ERROR
  187 + //return standard functionality
  188 + int num_textures = texture_list.size();
  189 +
  190 + //disable all texture units
  191 + for(int t=0; t<num_textures; t++)
  192 + {
  193 + glActiveTexture(GL_TEXTURE0 + t);
  194 + glDisable(texture_list[t].texture_type);
  195 + CHECK_OPENGL_ERROR
  196 + }
  197 + //make sure that the single default texture unit is active
  198 + if(num_textures > 0)
  199 + glActiveTexture(GL_TEXTURE0);
  200 + CHECK_OPENGL_ERROR
  201 +
  202 + //return to OpenGL default shading
  203 + glUseProgram(0);
  204 + CHECK_OPENGL_ERROR
  205 + }
  206 + void PrintUniforms()
  207 + {
  208 + cout<<"Shader Uniforms: "<<endl;
  209 + unsigned int i;
  210 + for(i=0; i<uniform_list.size(); i++)
  211 + {
  212 + cout<<i<<": "<<uniform_list[i].name<<" "<<uniform_list[i].location<<endl;
  213 + }
  214 + }
  215 + void AttachGlobalUniform(unsigned int index, void* param) //attaches a global variable to the indexed uniform parameter
  216 + {
  217 + uniform_list[index].p_value = param;
  218 + }
  219 + void AttachGlobalUniform(const char* name, void* param)
  220 + {
  221 + //find the index of the shader
  222 + int index = get_index(name);
  223 + if(index != -1)
  224 + AttachGlobalUniform(index, param);
  225 + else
  226 + {
  227 + string strError = "Error finding uniform variable: ";
  228 + strError += name;
  229 + cout<<strError<<endl;
  230 + }
  231 + }
  232 + void AttachTextureMap(unsigned int index, rts_glTextureMap texture) //attaches a texture map to the program
  233 + {
  234 + //if there is not a texture map assigned to the variable
  235 + if(uniform_list[index].p_value == NULL)
  236 + {
  237 + uniform_list[index].p_value = new unsigned int[1];
  238 + ((unsigned int*)uniform_list[index].p_value)[0] = texture_list.size(); //set the parameter value to the index of the texture
  239 + texture_list.push_back(texture); //add the texture to the texture list
  240 + }
  241 + //if there is a texture map assigned, replace it
  242 + else
  243 + {
  244 + texture_list[((unsigned int*)(uniform_list[index].p_value))[0]] = texture;
  245 + }
  246 +
  247 + }
  248 + void AttachTextureMap(const char* name, rts_glTextureMap texture)
  249 + {
  250 + int index = get_index(name);
  251 + if(index != -1) //make sure that the uniform index is valid
  252 + AttachTextureMap(index, texture);
  253 + else
  254 + cout<<"Error finding texture index. Try linking."<<endl;
  255 + }
  256 + void UpdateGlobalUniforms() //sends updated uniform information to the GPU
  257 + {
  258 + CHECK_OPENGL_ERROR
  259 + BeginProgram();
  260 + CHECK_OPENGL_ERROR
  261 + unsigned int num = uniform_list.size();
  262 + for(unsigned int i=0; i<num; i++)
  263 + uniform_list[i].submit_to_gpu();
  264 + EndProgram();
  265 + }
  266 + void Init() //Initialize the shader program
  267 + {
  268 + CHECK_OPENGL_ERROR
  269 + if(id != 0)
  270 + Clean();
  271 + id = glCreateProgram();
  272 + if(id == 0)
  273 + log = "Error getting program ID from OpenGL";
  274 + CHECK_OPENGL_ERROR
  275 + }
  276 + void Clean()
  277 + {
  278 + if(id != 0)
  279 + glDeleteProgram(id);
  280 + id = 0;
  281 +
  282 + //these are allocated outside the object and can just be cleared
  283 + uniform_list.clear();
  284 + texture_list.clear();
  285 +
  286 + //delete each shader from OpenGL
  287 + int num_shad = shader_list.size();
  288 + for(int i=0; i<num_shad; i++)
  289 + shader_list[i].Clean();
  290 + //clear the list
  291 + shader_list.clear();
  292 + }
  293 +};
  294 +
  295 +#endif
... ...
rts_glShaderUniform.h 0 → 100755
  1 +++ a/rts_glShaderUniform.h
  1 +#ifndef RTS_GLSHADERUNIFORM_H
  2 +#define RTS_GLSHADERUNIFORM_H
  3 +
  4 +#include "CHECK_OPENGL_ERROR.h"
  5 +#include <GL/glew.h>
  6 +#include <string>
  7 +
  8 +using namespace std;
  9 +
  10 +enum rtsUniformEnum {RTS_FLOAT, RTS_INT, RTS_BOOL, RTS_FLOAT_MATRIX};
  11 +
  12 +///This class stores a single uniform variable for GLSL and is designed to be used by the rts_glShaderProgram class.
  13 +struct rts_glShaderUniform
  14 +{
  15 +public:
  16 + string name; //the name of the variable
  17 + GLint location; //the location in the program
  18 + void* p_value; //pointer to the global data representing the value in main memory
  19 + GLenum type; //variable type (float, int, vec2, etc.)
  20 + //rtsUniformEnum rts_type; //type of variable in rts format
  21 + //unsigned int num; //the number of values required by the variable (1 for float, 2 for vec2, etc.)
  22 + string log;
  23 +
  24 + //void convert_type(GLenum gl_type); //converts the OpenGL data type to something useful for rts
  25 + void submit_to_gpu()
  26 + {
  27 + if(location < 0)
  28 + return;
  29 + if(p_value == NULL)
  30 + {
  31 + cout<<"Error in uniform address: "<<name<<endl;
  32 + return;
  33 + }
  34 +
  35 +
  36 + CHECK_OPENGL_ERROR
  37 + switch(type)
  38 + {
  39 + case GL_FLOAT:
  40 + glUniform1fv(location, 1, (float*)p_value);
  41 + break;
  42 + case GL_FLOAT_VEC2:
  43 + glUniform2fv(location, 1, (float*)p_value);
  44 + break;
  45 + case GL_FLOAT_VEC3:
  46 + glUniform3fv(location, 1, (float*)p_value);
  47 + break;
  48 + case GL_FLOAT_VEC4:
  49 + glUniform4fv(location, 1, (float*)p_value);
  50 + break;
  51 + case GL_INT:
  52 + glUniform1iv(location, 1, (int*)p_value);
  53 + break;
  54 + case GL_INT_VEC2:
  55 + glUniform2iv(location, 1, (int*)p_value);
  56 + break;
  57 + case GL_INT_VEC3:
  58 + glUniform3iv(location, 1, (int*)p_value);
  59 + break;
  60 + case GL_INT_VEC4:
  61 + glUniform4iv(location, 1, (int*)p_value);
  62 + break;
  63 + case GL_BOOL:
  64 + glUniform1iv(location, 1, (int*)p_value);
  65 + break;
  66 + case GL_BOOL_VEC2:
  67 + glUniform2iv(location, 1, (int*)p_value);
  68 + break;
  69 + case GL_BOOL_VEC3:
  70 + glUniform3iv(location, 1, (int*)p_value);
  71 + break;
  72 + case GL_BOOL_VEC4:
  73 + glUniform4iv(location, 1, (int*)p_value);
  74 + break;
  75 + case GL_FLOAT_MAT2:
  76 + glUniformMatrix2fv(location, 1, GL_FALSE, (float*)p_value);
  77 + break;
  78 + case GL_FLOAT_MAT3:
  79 + glUniformMatrix3fv(location, 1, GL_FALSE, (float*)p_value);
  80 + break;
  81 + case GL_FLOAT_MAT4:
  82 + glUniformMatrix4fv(location, 1, GL_FALSE, (float*)p_value);
  83 + break;
  84 + case GL_SAMPLER_1D:
  85 + case GL_SAMPLER_2D:
  86 + case GL_SAMPLER_3D:
  87 + case GL_SAMPLER_CUBE:
  88 + case GL_SAMPLER_1D_SHADOW:
  89 + case GL_SAMPLER_2D_SHADOW:
  90 + default:
  91 + glUniform1iv(location, 1, (int*)p_value);
  92 + break;
  93 + }
  94 + CHECK_OPENGL_ERROR
  95 + }
  96 + rts_glShaderUniform()
  97 + {
  98 + location = -1;
  99 + p_value = NULL;
  100 + }
  101 +};
  102 +
  103 +
  104 +
  105 +#endif
0 106 \ No newline at end of file
... ...
rts_glTextureMap.cpp 0 → 100755
  1 +++ a/rts_glTextureMap.cpp
  1 +#include "rts_glTextureMap.h"
  2 +
  3 +#define RTS_UNKNOWN 0
  4 +
  5 +rts_glTextureMap::rts_glTextureMap()
  6 +{
  7 + name = 0;
  8 +}
  9 +
  10 +void rts_glTextureMap::get_type()
  11 +{
  12 + if(size.y == 0)
  13 + texture_type = GL_TEXTURE_1D;
  14 + else if(size.z == 0)
  15 + texture_type = GL_TEXTURE_2D;
  16 + else
  17 + texture_type = GL_TEXTURE_3D;
  18 +}
  19 +
  20 +void rts_glTextureMap::set_wrapping()
  21 +{
  22 + CHECK_OPENGL_ERROR
  23 + switch(texture_type)
  24 + {
  25 + case GL_TEXTURE_3D:
  26 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_R_EXT, GL_REPEAT);
  27 + case GL_TEXTURE_2D:
  28 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT);
  29 + case GL_TEXTURE_1D:
  30 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT);
  31 + break;
  32 + case GL_TEXTURE_RECTANGLE_ARB:
  33 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP);
  34 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP);
  35 + break;
  36 +
  37 + default:
  38 + break;
  39 + }
  40 + CHECK_OPENGL_ERROR
  41 +}
  42 +
  43 +void rts_glTextureMap::SetBits(GLvoid* bits)
  44 +{
  45 + glEnable(texture_type); //enable the texture map
  46 + CHECK_OPENGL_ERROR
  47 + glBindTexture(texture_type, name);
  48 + CHECK_OPENGL_ERROR
  49 +
  50 + switch(texture_type)
  51 + {
  52 + case GL_TEXTURE_3D:
  53 + glTexImage3D(texture_type, 0, internal_format, size.x, size.y, size.z, 0, pixel_format, data_type, bits);
  54 + break;
  55 + case GL_TEXTURE_2D:
  56 + case GL_TEXTURE_RECTANGLE_ARB:
  57 + glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  58 + break;
  59 + case GL_TEXTURE_1D:
  60 + glTexImage1D(texture_type, 0, internal_format, size.x, 0, pixel_format, data_type, bits);
  61 + break;
  62 + default:
  63 + //glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  64 + break;
  65 + }
  66 + CHECK_OPENGL_ERROR
  67 +}
  68 +
  69 +void* rts_glTextureMap::GetBits(GLenum format, GLenum type)
  70 +{
  71 + //returns the texture data
  72 +
  73 + int components;
  74 + switch(format)
  75 + {
  76 + case GL_RED:
  77 + case GL_GREEN:
  78 + case GL_BLUE:
  79 + case GL_ALPHA:
  80 + case GL_LUMINANCE:
  81 + components = 1;
  82 + break;
  83 + case GL_LUMINANCE_ALPHA:
  84 + components = 2;
  85 + break;
  86 + case GL_RGB:
  87 + case GL_BGR:
  88 + components = 3;
  89 + break;
  90 + case GL_RGBA:
  91 + case GL_BGRA:
  92 + components = 4;
  93 + break;
  94 + }
  95 +
  96 + int type_size;
  97 + switch(type)
  98 + {
  99 + case GL_UNSIGNED_BYTE:
  100 + case GL_BYTE:
  101 + type_size = sizeof(char);
  102 + break;
  103 + case GL_UNSIGNED_SHORT:
  104 + case GL_SHORT:
  105 + type_size = sizeof(short);
  106 + break;
  107 + case GL_UNSIGNED_INT:
  108 + case GL_INT:
  109 + type_size = sizeof(int);
  110 + break;
  111 + case GL_FLOAT:
  112 + type_size = sizeof(float);
  113 + break;
  114 + }
  115 +
  116 + //allocate memory for the texture
  117 + void* result = malloc(components*type_size * size.x * size.y);
  118 +
  119 + BeginTexture();
  120 + glGetTexImage(texture_type, 0, format, type, result);
  121 +
  122 + CHECK_OPENGL_ERROR
  123 + EndTexture();
  124 +
  125 +
  126 + return result;
  127 +
  128 +}
  129 +
  130 +void rts_glTextureMap::ResetBits(GLvoid *bits)
  131 +{
  132 + glEnable(texture_type); //enable the texture map
  133 + CHECK_OPENGL_ERROR
  134 + glBindTexture(texture_type, name);
  135 + CHECK_OPENGL_ERROR
  136 +
  137 + switch(texture_type)
  138 + {
  139 + case GL_TEXTURE_3D:
  140 + //glTexImage3D(texture_type, 0, internal_format, size.x, size.y, size.z, 0, pixel_format, data_type, bits);
  141 + break;
  142 + case GL_TEXTURE_2D:
  143 + case GL_TEXTURE_RECTANGLE_ARB:
  144 + glTexSubImage2D(texture_type, 0, 0, 0, size.x, size.y, pixel_format, data_type, bits);
  145 + CHECK_OPENGL_ERROR
  146 + break;
  147 + case GL_TEXTURE_1D:
  148 + //glTexImage1D(texture_type, 0, internal_format, size.x, 0, pixel_format, data_type, bits);
  149 + break;
  150 + default:
  151 + //glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  152 + break;
  153 + }
  154 + glDisable(texture_type);
  155 + CHECK_OPENGL_ERROR
  156 +}
  157 +
  158 +void rts_glTextureMap::BeginTexture()
  159 +{
  160 + glEnable(texture_type);
  161 + glBindTexture(texture_type, name);
  162 + CHECK_OPENGL_ERROR
  163 +}
  164 +
  165 +void rts_glTextureMap::EndTexture()
  166 +{
  167 + glDisable(texture_type);
  168 + CHECK_OPENGL_ERROR
  169 +}
  170 +
  171 +
  172 +
  173 +void rts_glTextureMap::Init(GLvoid *bits,
  174 + GLenum type,
  175 + GLsizei width,
  176 + GLsizei height,
  177 + GLsizei depth,
  178 + GLint internalformat,
  179 + GLenum format,
  180 + GLenum datatype,
  181 + GLint interpolation)
  182 +{
  183 + if(name != 0)
  184 + glDeleteTextures(1, &name);
  185 + //see if the texture is supported using a proxy
  186 + CHECK_OPENGL_ERROR
  187 + //glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internalformat, width, height, 0, format, datatype, NULL);
  188 + GLint p;
  189 + CHECK_OPENGL_ERROR
  190 + //glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &p);
  191 + //if(p == 0)
  192 + // cout<<"cannot use a texture with these parameters."<<endl;
  193 + CHECK_OPENGL_ERROR
  194 + if(datatype == GL_FLOAT)
  195 + {
  196 + glPixelStorei(GL_PACK_ALIGNMENT, 4);
  197 + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); //I honestly don't know what this does but it fixes problems
  198 + }
  199 + else if(datatype == GL_UNSIGNED_BYTE)
  200 + {
  201 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  202 + //glPixelStorei(GL_PACK_ALIGNMENT, 1);
  203 + }
  204 + else if(datatype == GL_UNSIGNED_SHORT)
  205 + {
  206 + //glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  207 + //glPixelStorei(GL_PACK_ALIGNMENT, 2);
  208 + }
  209 + CHECK_OPENGL_ERROR
  210 + glGenTextures(1, &name); //get the texture name from OpenGL
  211 + cout<<"OpenGL Name: "<<name<<endl;
  212 + CHECK_OPENGL_ERROR
  213 + size = vector3D<GLuint>(width, height, depth); //assign the texture size
  214 + //get_type(); //guess the type based on the size
  215 + texture_type = type; //set the type of texture
  216 + glEnable(texture_type); //enable the texture map
  217 + CHECK_OPENGL_ERROR
  218 + glBindTexture(texture_type, name); //bind the texture for editing
  219 + CHECK_OPENGL_ERROR
  220 + set_wrapping(); //set the texture wrapping parameters
  221 + CHECK_OPENGL_ERROR
  222 + glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpolation); //set filtering
  223 + CHECK_OPENGL_ERROR
  224 + glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpolation);
  225 + CHECK_OPENGL_ERROR
  226 + internal_format = internalformat; //set the number of components per pixel
  227 + pixel_format = format; //set the pixel format
  228 + data_type = datatype; //set the data type
  229 + SetBits(bits); //send the bits to the OpenGL driver
  230 + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //replace the specified vertex color
  231 + CHECK_OPENGL_ERROR
  232 + glDisable(texture_type);
  233 +}
0 234 \ No newline at end of file
... ...
rts_glTextureMap.h 0 → 100755
  1 +++ a/rts_glTextureMap.h
  1 +#ifndef RTS_GLTEXTUREMAP_H
  2 +#define RTS_GLTEXTUREMAP_H
  3 +
  4 +#include <GL/glew.h>
  5 +#include "rtsVector3d.h"
  6 +#include "CHECK_OPENGL_ERROR.h"
  7 +#include <stdlib.h>
  8 +
  9 +///This class stores an OpenGL texture map and is used by rts_glShaderProgram.
  10 +class rts_glTextureMap
  11 +{
  12 +private:
  13 + void get_type() //guesses the texture type based on the size
  14 + {
  15 + if(size.y == 0)
  16 + texture_type = GL_TEXTURE_1D;
  17 + else if(size.z == 0)
  18 + texture_type = GL_TEXTURE_2D;
  19 + else
  20 + texture_type = GL_TEXTURE_3D;
  21 + }
  22 + void set_wrapping() //set the texture wrapping based on the dimensions
  23 + {
  24 + CHECK_OPENGL_ERROR
  25 + switch(texture_type)
  26 + {
  27 + case GL_TEXTURE_3D:
  28 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_R_EXT, GL_REPEAT);
  29 + case GL_TEXTURE_2D:
  30 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
  31 + case GL_TEXTURE_1D:
  32 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT);
  33 + break;
  34 + case GL_TEXTURE_RECTANGLE_ARB:
  35 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  36 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  37 + break;
  38 +
  39 + default:
  40 + break;
  41 + }
  42 + CHECK_OPENGL_ERROR
  43 + }
  44 + //void set_bits(GLvoid* bits);
  45 +public:
  46 + vector3D<GLsizei> size; //vector representing the size of the texture
  47 + GLuint name; //texture name assigned by OpenGL
  48 + GLenum texture_type; //1D, 2D, 3D
  49 + GLint internal_format; //number of components (ex. 4 for RGBA)
  50 + GLenum pixel_format; //type of data (RGBA, LUMINANCE)
  51 + GLenum data_type; //data type of the bits (float, int, etc.)
  52 +
  53 + //constructor
  54 + rts_glTextureMap()
  55 + {
  56 + name = 0;
  57 + }
  58 +
  59 + void BeginTexture()
  60 + {
  61 + glEnable(texture_type);
  62 + glBindTexture(texture_type, name);
  63 + CHECK_OPENGL_ERROR
  64 + }
  65 + void EndTexture()
  66 + {
  67 + glDisable(texture_type);
  68 + CHECK_OPENGL_ERROR
  69 + }
  70 +
  71 + ///Creates an OpenGL texture map. This function requires basic information about the texture map as well as a pointer to the bit data describing the texture.
  72 + void Init(GLvoid *bits,
  73 + GLenum type = GL_TEXTURE_2D,
  74 + GLsizei width = 256,
  75 + GLsizei height = 256,
  76 + GLsizei depth = 0,
  77 + GLint internalformat = 1,
  78 + GLenum format = GL_LUMINANCE,
  79 + GLenum datatype = GL_UNSIGNED_BYTE,
  80 + GLint interpolation = GL_LINEAR)
  81 + {
  82 + CHECK_OPENGL_ERROR
  83 + if(name != 0)
  84 + glDeleteTextures(1, &name);
  85 +
  86 +
  87 + CHECK_OPENGL_ERROR
  88 + if(datatype == GL_FLOAT)
  89 + {
  90 + glPixelStorei(GL_PACK_ALIGNMENT, 4);
  91 + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); //I honestly don't know what this does but it fixes problems
  92 + }
  93 + else if(datatype == GL_UNSIGNED_BYTE)
  94 + {
  95 + //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  96 + //glPixelStorei(GL_PACK_ALIGNMENT, 1);
  97 + }
  98 + else if(datatype == GL_UNSIGNED_SHORT)
  99 + {
  100 + //glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  101 + //glPixelStorei(GL_PACK_ALIGNMENT, 2);
  102 + }
  103 + CHECK_OPENGL_ERROR
  104 + glGenTextures(1, &name); //get the texture name from OpenGL
  105 + //cout<<"OpenGL Name: "<<name<<endl;
  106 + CHECK_OPENGL_ERROR
  107 + size = vector3D<GLuint>(width, height, depth); //assign the texture size
  108 + //get_type(); //guess the type based on the size
  109 + texture_type = type; //set the type of texture
  110 + glEnable(texture_type); //enable the texture map
  111 + CHECK_OPENGL_ERROR
  112 + glBindTexture(texture_type, name); //bind the texture for editing
  113 + CHECK_OPENGL_ERROR
  114 + set_wrapping(); //set the texture wrapping parameters
  115 + CHECK_OPENGL_ERROR
  116 + glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpolation); //set filtering
  117 + CHECK_OPENGL_ERROR
  118 + glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpolation);
  119 + CHECK_OPENGL_ERROR
  120 + internal_format = internalformat; //set the number of components per pixel
  121 + pixel_format = format; //set the pixel format
  122 + data_type = datatype; //set the data type
  123 + SetBits(bits); //send the bits to the OpenGL driver
  124 + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //replace the specified vertex color
  125 + CHECK_OPENGL_ERROR
  126 + glDisable(texture_type);
  127 +
  128 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  129 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  130 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  131 + }
  132 + void Clean()
  133 + {
  134 + if(name != 0)
  135 + {
  136 + glDeleteTextures(1, &name);
  137 + CHECK_OPENGL_ERROR
  138 + name = 0;
  139 + }
  140 + }
  141 + void SetBits(GLvoid *bits)
  142 + {
  143 + glEnable(texture_type); //enable the texture map
  144 + CHECK_OPENGL_ERROR
  145 + glBindTexture(texture_type, name);
  146 + CHECK_OPENGL_ERROR
  147 +
  148 + switch(texture_type)
  149 + {
  150 + case GL_TEXTURE_3D:
  151 + glTexImage3D(texture_type, 0, internal_format, size.x, size.y, size.z, 0, pixel_format, data_type, bits);
  152 + CHECK_OPENGL_ERROR
  153 + break;
  154 + case GL_TEXTURE_2D:
  155 + case GL_TEXTURE_RECTANGLE_ARB:
  156 + glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  157 + CHECK_OPENGL_ERROR
  158 + break;
  159 + case GL_TEXTURE_1D:
  160 + glTexImage1D(texture_type, 0, internal_format, size.x, 0, pixel_format, data_type, bits);
  161 + CHECK_OPENGL_ERROR
  162 + break;
  163 + default:
  164 + //glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  165 + break;
  166 + }
  167 + CHECK_OPENGL_ERROR
  168 + }
  169 + void ResetBits(GLvoid *bits)
  170 + {
  171 + glEnable(texture_type); //enable the texture map
  172 + CHECK_OPENGL_ERROR
  173 + glBindTexture(texture_type, name);
  174 + CHECK_OPENGL_ERROR
  175 +
  176 + switch(texture_type)
  177 + {
  178 + case GL_TEXTURE_3D:
  179 + //glTexImage3D(texture_type, 0, internal_format, size.x, size.y, size.z, 0, pixel_format, data_type, bits);
  180 + break;
  181 + case GL_TEXTURE_2D:
  182 + case GL_TEXTURE_RECTANGLE_ARB:
  183 + glTexSubImage2D(texture_type, 0, 0, 0, size.x, size.y, pixel_format, data_type, bits);
  184 + CHECK_OPENGL_ERROR
  185 + break;
  186 + case GL_TEXTURE_1D:
  187 + //glTexImage1D(texture_type, 0, internal_format, size.x, 0, pixel_format, data_type, bits);
  188 + break;
  189 + default:
  190 + //glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  191 + break;
  192 + }
  193 + glDisable(texture_type);
  194 + CHECK_OPENGL_ERROR
  195 + }
  196 + void* GetBits(GLenum format, GLenum type)
  197 + {
  198 + //returns the texture data
  199 +
  200 + int components;
  201 + switch(format)
  202 + {
  203 + case GL_RED:
  204 + case GL_GREEN:
  205 + case GL_BLUE:
  206 + case GL_ALPHA:
  207 + case GL_LUMINANCE:
  208 + components = 1;
  209 + break;
  210 + case GL_LUMINANCE_ALPHA:
  211 + components = 2;
  212 + break;
  213 + case GL_RGB:
  214 + case GL_BGR:
  215 + components = 3;
  216 + break;
  217 + case GL_RGBA:
  218 + case GL_BGRA:
  219 + components = 4;
  220 + break;
  221 + }
  222 +
  223 + int type_size;
  224 + switch(type)
  225 + {
  226 + case GL_UNSIGNED_BYTE:
  227 + case GL_BYTE:
  228 + type_size = sizeof(char);
  229 + break;
  230 + case GL_UNSIGNED_SHORT:
  231 + case GL_SHORT:
  232 + type_size = sizeof(short);
  233 + break;
  234 + case GL_UNSIGNED_INT:
  235 + case GL_INT:
  236 + type_size = sizeof(int);
  237 + break;
  238 + case GL_FLOAT:
  239 + type_size = sizeof(float);
  240 + break;
  241 + }
  242 +
  243 + //allocate memory for the texture
  244 + void* result = malloc(components*type_size * size.x * size.y);
  245 +
  246 + BeginTexture();
  247 + glGetTexImage(texture_type, 0, format, type, result);
  248 +
  249 + CHECK_OPENGL_ERROR
  250 + EndTexture();
  251 +
  252 +
  253 + return result;
  254 +
  255 + }
  256 +};
  257 +
  258 +#define RTS_UNKNOWN 0
  259 +
  260 +#endif
0 261 \ No newline at end of file
... ...
rts_glTrueEyes.h 0 → 100755
  1 +++ a/rts_glTrueEyes.h
  1 +#include <iostream>
  2 +#include <string>
  3 +
  4 +#include "rtsCamera.h"
  5 +#include "rtsSourceCode.h"
  6 +#include "rts_glShaderProgram.h"
  7 +using namespace std;
  8 +
  9 +#include <gl/glut.h>
  10 +
  11 +class rts_glTrueEyes
  12 +{
  13 + static int glut_window;
  14 +
  15 + static rts_glShaderProgram shader;
  16 + static string source_file;
  17 + static rtsCamera camera;
  18 + static int mouse_x;
  19 + static int mouse_y;
  20 + static float camera_pos[3];
  21 + static float volume_size[3];
  22 + static rts_glTextureMap volume;
  23 +
  24 + static bool zooming;
  25 +
  26 + static void DrawCube()
  27 + {
  28 + float sx = volume_size[0]/2;
  29 + float sy = volume_size[1]/2;
  30 + float sz = volume_size[2]/2;
  31 + float tx = volume_size[0]/2;
  32 + float ty = volume_size[1]/2;
  33 + float tz = volume_size[2]/2;
  34 +
  35 + glBegin(GL_QUADS);
  36 + glTexCoord3f(-tx, -ty, -tz);
  37 + glVertex3f(-sx, -sy, -sz);
  38 + glTexCoord3f(-tx, ty, -tz);
  39 + glVertex3f(-sx, sy, -sz);
  40 + glTexCoord3f(tx, ty, -tz);
  41 + glVertex3f(sx, sy, -sz);
  42 + glTexCoord3f(tx, -ty, -tz);
  43 + glVertex3f(sx, -sy, -sz);
  44 +
  45 + glTexCoord3f(-tx, -ty, tz);
  46 + glVertex3f(-sx, -sy, sz);
  47 + glTexCoord3f(-tx, ty, tz);
  48 + glVertex3f(-sx, sy, sz);
  49 + glTexCoord3f(tx, ty, tz);
  50 + glVertex3f(sx, sy, sz);
  51 + glTexCoord3f(tx, -ty, tz);
  52 + glVertex3f(sx, -sy, sz);
  53 +
  54 + glTexCoord3f(-tx, -ty, -tz);
  55 + glVertex3f(-sx, -sy, -sz);
  56 + glTexCoord3f(-tx, -ty, tz);
  57 + glVertex3f(-sx, -sy, sz);
  58 + glTexCoord3f(tx, -ty, tz);
  59 + glVertex3f(sx, -sy, sz);
  60 + glTexCoord3f(tx, -ty, -tz);
  61 + glVertex3f(sx, -sy, -sz);
  62 +
  63 + glTexCoord3f(-tx, ty, -tz);
  64 + glVertex3f(-sx, sy, -sz);
  65 + glTexCoord3f(-tx, ty, tz);
  66 + glVertex3f(-sx, sy, sz);
  67 + glTexCoord3f(tx, ty, tz);
  68 + glVertex3f(sx, sy, sz);
  69 + glTexCoord3f(tx, ty, -tz);
  70 + glVertex3f(sx, sy, -sz);
  71 +
  72 + glTexCoord3f(-tx, -ty, -tz);
  73 + glVertex3f(-sx, -sy, -sz);
  74 + glTexCoord3f(-tx, -ty, tz);
  75 + glVertex3f(-sx, -sy, sz);
  76 + glTexCoord3f(-tx, ty, tz);
  77 + glVertex3f(-sx, sy, sz);
  78 + glTexCoord3f(-tx, ty, -tz);
  79 + glVertex3f(-sx, sy, -sz);
  80 +
  81 + glTexCoord3f(tx, -ty, -tz);
  82 + glVertex3f(sx, -sy, -sz);
  83 + glTexCoord3f(tx, -ty, tz);
  84 + glVertex3f(sx, -sy, sz);
  85 + glTexCoord3f(tx, ty, tz);
  86 + glVertex3f(sx, sy, sz);
  87 + glTexCoord3f(tx, ty, -tz);
  88 + glVertex3f(sx, sy, -sz);
  89 + glEnd();
  90 + }
  91 +
  92 + static void DisplayFunction()
  93 + {
  94 +
  95 +
  96 + //set up the viewport and projection
  97 + glMatrixMode(GL_PROJECTION);
  98 + glLoadIdentity();
  99 + glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
  100 + float aspect_ratio = (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT);
  101 + gluPerspective(camera.getFOV(), aspect_ratio, 0.01, 10);
  102 +
  103 + //clear the screen
  104 + glClear(GL_COLOR_BUFFER_BIT);
  105 + glClear(GL_DEPTH_BUFFER_BIT);
  106 +
  107 +
  108 + //set up the camera
  109 + glMatrixMode(GL_MODELVIEW);
  110 + glLoadIdentity();
  111 + point3D<float> pos = camera.getPosition();
  112 + vector3D<float> up = camera.getUp();
  113 + gluLookAt(pos.x, pos.y, pos.z, 0, 0, 0, up.x, up.y, up.z);
  114 +
  115 + //draw a cube
  116 + glColor3f(1.0, 0.0, 0.0);
  117 + shader.UpdateGlobalUniforms();
  118 + shader.BeginProgram();
  119 + DrawCube();
  120 + shader.EndProgram();
  121 +
  122 + glutSwapBuffers();
  123 + }
  124 + static void IdleFunction()
  125 + {
  126 + glutPostRedisplay();
  127 + }
  128 +
  129 + static void MouseDrag(int x, int y)
  130 + {
  131 + int dx = x - mouse_x;
  132 + int dy = y - mouse_y;
  133 +
  134 + if(zooming)
  135 + {
  136 + camera.Zoom(dy);
  137 + }
  138 + else
  139 + {
  140 +
  141 + camera.OrbitFocus(-dx*0.01, dy*0.01);
  142 + point3D<float> pos = camera.getPosition();
  143 + camera_pos[0] = pos.x;
  144 + camera_pos[1] = pos.y;
  145 + camera_pos[2] = pos.z;
  146 + }
  147 +
  148 + mouse_x = x;
  149 + mouse_y = y;
  150 +
  151 + glutPostRedisplay();
  152 +
  153 + }
  154 +
  155 + static void MouseMove(int x, int y)
  156 + {
  157 + mouse_x = x;
  158 + mouse_y = y;
  159 +
  160 + }
  161 + static void KeyPress(unsigned char key, int x, int y)
  162 + {
  163 + //reload the shader
  164 + if(key == 'r' || key == 'R')
  165 + {
  166 + UpdateShader();
  167 +
  168 +
  169 + }
  170 +
  171 + }
  172 +
  173 + static void MousePress(int button, int state, int x, int y)
  174 + {
  175 + if(state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON)
  176 + zooming = true;
  177 + else
  178 + zooming = false;
  179 + }
  180 +
  181 + static void UpdateShader()
  182 + {
  183 + //load the source code
  184 + shader.Clean();
  185 + shader.AttachShader(GL_FRAGMENT_SHADER, source_file.c_str());
  186 +
  187 + //compile the shader
  188 + shader.Compile();
  189 + shader.PrintLog();
  190 + shader.Link();
  191 + shader.PrintLog();
  192 +
  193 + if(!shader.linked)
  194 + {
  195 + cout<<"Error linking shader."<<endl;
  196 + std::puts("Press any key to continue...");
  197 + std::getchar();
  198 + UpdateShader();
  199 + }
  200 +
  201 +
  202 + shader.PrintUniforms();
  203 + shader.AttachGlobalUniform("camera", &camera_pos);
  204 + shader.AttachGlobalUniform("volume_size", &volume_size);
  205 + shader.AttachTextureMap("volume", volume);
  206 +
  207 +
  208 + }
  209 +public:
  210 + void Begin();
  211 + void SetShader(string filename);
  212 + void SetVolume(unsigned char* bits, int sx, int sy, int sz, int channels);
  213 + void SetVolumeSize(float x, float y, float z);
  214 + void Initialize();
  215 +
  216 +};
  217 +
  218 +//static variables
  219 +rtsCamera rts_glTrueEyes::camera;
  220 +rts_glShaderProgram rts_glTrueEyes::shader;
  221 +int rts_glTrueEyes::glut_window;
  222 +int rts_glTrueEyes::mouse_x;
  223 +int rts_glTrueEyes::mouse_y;
  224 +float rts_glTrueEyes::camera_pos[3];
  225 +float rts_glTrueEyes::volume_size[3];
  226 +string rts_glTrueEyes::source_file;
  227 +rts_glTextureMap rts_glTrueEyes::volume;
  228 +bool rts_glTrueEyes::zooming;
  229 +
  230 +
  231 +void rts_glTrueEyes::Initialize()
  232 +{
  233 + //initialize OpenGL
  234 + glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  235 +
  236 + //create the GLUT window
  237 + glut_window = glutCreateWindow("True Eyes");
  238 +
  239 + //initialize GLEW
  240 + GLenum err = glewInit();
  241 + if(err != GLEW_OK)
  242 + fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
  243 + if (glewIsSupported("GL_VERSION_2_0"))
  244 + printf("Ready for OpenGL 2.0\n");
  245 + else {
  246 + printf("OpenGL 2.0 not supported\n");
  247 + //exit(1);
  248 + }
  249 +
  250 + //set the function pointers
  251 + glutDisplayFunc(&rts_glTrueEyes::DisplayFunction);
  252 + glutIdleFunc(&rts_glTrueEyes::IdleFunction);
  253 + glutMotionFunc(&rts_glTrueEyes::MouseDrag);
  254 + glutMouseFunc(&rts_glTrueEyes::MousePress);
  255 + glutPassiveMotionFunc(&rts_glTrueEyes::MouseMove);
  256 + glutKeyboardFunc(&rts_glTrueEyes::KeyPress);
  257 +
  258 + //set rendering parameters
  259 + glEnable(GL_DEPTH_TEST);
  260 + glDisable(GL_CULL_FACE);
  261 +
  262 + //set up the camera
  263 + camera.setPosition(0, 0, -1.6);
  264 + camera_pos[0] = 0;
  265 + camera_pos[1] = 0;
  266 + camera_pos[2] = -1.6;
  267 + camera.LookAt(0.0, 0.0, 0.0);
  268 + camera.setFOV(60);
  269 +
  270 + zooming = false;
  271 +
  272 +
  273 +}
  274 +void rts_glTrueEyes::Begin()
  275 +{
  276 + //start rendering
  277 + glutMainLoop();
  278 +}
  279 +
  280 +void rts_glTrueEyes::SetShader(string filename)
  281 +{
  282 + source_file = filename;
  283 + UpdateShader();
  284 +}
  285 +
  286 +void rts_glTrueEyes::SetVolumeSize(float x, float y, float z)
  287 +{
  288 + float max_edge = max(x, max(y, z));
  289 + volume_size[0] = x/max_edge;
  290 + volume_size[1] = y/max_edge;
  291 + volume_size[2] = z/max_edge;
  292 +}
  293 +
  294 +void rts_glTrueEyes::SetVolume(unsigned char* bits, int sx, int sy, int sz, int channels)
  295 +{
  296 + if(channels == 1)
  297 + volume.Init(bits, GL_TEXTURE_3D, sx, sy, sz, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_NEAREST);
  298 + else if(channels == 3)
  299 + volume.Init(bits, GL_TEXTURE_3D, sx, sy, sz, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, GL_NEAREST);
  300 + CHECK_OPENGL_ERROR
  301 +
  302 +
  303 +
  304 +}
0 305 \ No newline at end of file
... ...
rts_glUtilities.h 0 → 100755
  1 +++ a/rts_glUtilities.h
  1 +#ifndef RTS_GLUTILITIES_H
  2 +#define RTS_GLUTILITIES_H
  3 +
  4 +
  5 +#define CHECK_OPENGL_ERROR \
  6 +{ GLenum error; \
  7 + while ( (error = glGetError()) != GL_NO_ERROR) { \
  8 + printf( "OpenGL ERROR: %s\nCHECK POINT: %s (line %d)\n", gluErrorString(error), __FILE__, __LINE__ ); \
  9 + } \
  10 +}
  11 +
  12 +#endif
0 13 \ No newline at end of file
... ...
rts_glVolumeViewer.cpp 0 → 100755
  1 +++ a/rts_glVolumeViewer.cpp
  1 +#include "rts_glVolumeViewer.h"
  2 +#include "PerformanceData.h"
  3 +
  4 +PerformanceData PD;
  5 +
  6 +
  7 +rts_glVolumeViewer::rts_glVolumeViewer()
  8 +{
  9 + m_optimize=false;
  10 + m_min_threshold = 0;
  11 + m_max_threshold = 255;
  12 + m_volume_texture = 0;
  13 + m_p = point3D(0.0, 0.0, 0.0);
  14 + m_texture_size = vector3D(2,2,1);
  15 + m_voxel_size = vector3D(1.0, 1.0, 1.0);
  16 + m_dimensions = vector3D(m_texture_size.x * m_voxel_size.x,
  17 + m_texture_size.y * m_voxel_size.y,
  18 + m_texture_size.z * m_voxel_size.z);
  19 + m_dimensions.normalize();
  20 +
  21 +
  22 + //calculate the radii
  23 + m_inner_radius = 0.5;
  24 + m_outer_radius = (vector3D(1.0, 1.0, 1.0).length())*0.5;
  25 +
  26 + //create the plane display list
  27 + SetNumPlanes(256);
  28 +
  29 + //visualization parameters
  30 + m_alpha_scale = 1.0;
  31 +}
  32 +
  33 +
  34 +rts_glVolumeViewer::rts_glVolumeViewer(rtsVolume volume_data,
  35 + point3D position = point3D(0.0, 0.0, 0.0),
  36 + vector3D voxel_size = vector3D(1.0, 1.0, 1.0))
  37 +{
  38 + m_optimize=false;
  39 + m_volume_texture = 0;
  40 + m_p = position;
  41 + m_min_threshold = 0;
  42 + m_max_threshold = 255;
  43 + m_texture_size = vector3D(volume_data.get_dimx(), volume_data.get_dimy(), volume_data.get_dimz());
  44 + m_voxel_size = vector3D(1.0, 1.0, 1.0);
  45 + m_dimensions = vector3D(m_texture_size.x * m_voxel_size.x,
  46 + m_texture_size.y * m_voxel_size.y,
  47 + m_texture_size.z * m_voxel_size.z);
  48 + m_dimensions.normalize();
  49 +
  50 +
  51 + //store the volume
  52 + PD.StartTimer(COPY_DATA);
  53 + m_source = volume_data;
  54 + PD.EndTimer(COPY_DATA);
  55 +
  56 + //calculate the radii
  57 + //m_inner_radius = max(max(m_dimensions.x, m_dimensions.y), m_dimensions.z) * 0.5;
  58 + //m_outer_radius = (m_dimensions.length())*0.5;
  59 + m_inner_radius = 0.5;
  60 + m_outer_radius = vector3D(1.0, 1.0, 1.0).length()*0.5;
  61 +
  62 +
  63 +
  64 + SetNumPlanes(256);
  65 + CHECK_OPENGL_ERROR
  66 + //enable 3d texture mapping
  67 + glEnable(GL_TEXTURE_3D);
  68 + CHECK_OPENGL_ERROR
  69 +
  70 +
  71 +
  72 +
  73 +
  74 + //3D Texture mapping
  75 + glGenTextures(1, &m_volume_texture);
  76 + CHECK_OPENGL_ERROR
  77 + glBindTexture(GL_TEXTURE_3D, m_volume_texture);
  78 + CHECK_OPENGL_ERROR
  79 +
  80 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  81 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  82 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  83 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  84 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
  85 + CHECK_OPENGL_ERROR
  86 +
  87 + //load the texture data
  88 + m_load_texture();
  89 + CHECK_OPENGL_ERROR
  90 +
  91 + // our texture colors will replace the untextured colors
  92 + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
  93 + glShadeModel(GL_FLAT);
  94 + CHECK_OPENGL_ERROR
  95 +
  96 + glDisable(GL_TEXTURE_3D);
  97 +
  98 + //visualization parameters
  99 + m_alpha_scale = 1.0;
  100 +}
  101 +
  102 +//~rts_glVolumeViewer()
  103 +//{
  104 +
  105 +
  106 +//}
  107 +
  108 +
  109 +void rts_glVolumeViewer::RenderBoundingBox()
  110 +{
  111 +
  112 +
  113 + //create the transformation for the volume
  114 + glMatrixMode(GL_MODELVIEW);
  115 + glPushMatrix();
  116 + glScalef(m_dimensions.x, m_dimensions.y, m_dimensions.z);
  117 + glTranslatef(m_p.x, m_p.y, m_p.z);
  118 + glutWireCube(1.0);
  119 + glPopMatrix();
  120 +}
  121 +
  122 +void rts_glVolumeViewer::m_draw_plane(point3D p, vector3D n, vector3D up)
  123 +{
  124 +
  125 + //calculate the u, v vectors representing the plane
  126 + vector3D v = up.cross(n); v.normalize();
  127 + vector3D u = n.cross(v); u.normalize();
  128 +
  129 + //compute the points that make up the plane
  130 + point3D p0 = p - v*m_outer_radius - u*m_outer_radius;
  131 + point3D p1 = p - v*m_outer_radius + u*m_outer_radius;
  132 + point3D p2 = p + v*m_outer_radius + u*m_outer_radius;
  133 + point3D p3 = p + v*m_outer_radius - u*m_outer_radius;
  134 + //compute texture coordinates
  135 + point3D t0 = point3D(0.5, 0.5, 0.5) + (p0 - m_p);
  136 + point3D t1 = point3D(0.5, 0.5, 0.5) + (p1 - m_p);
  137 + point3D t2 = point3D(0.5, 0.5, 0.5) + (p2 - m_p);
  138 + point3D t3 = point3D(0.5, 0.5, 0.5) + (p3 - m_p);
  139 +
  140 + //enable texture mapping
  141 + //glEnable(GL_TEXTURE_3D);
  142 + glBindTexture(GL_TEXTURE_3D, m_volume_texture);
  143 +
  144 + //enable blending
  145 + glDisable(GL_DEPTH_TEST);
  146 + glEnable(GL_BLEND);
  147 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  148 +
  149 + glColor4f(1.0, 1.0, 1.0, 1.0);
  150 + glBegin(GL_QUADS);
  151 + glTexCoord3f(t0.x, t0.y, t0.z);
  152 + glVertex3f(p0.x, p0.y, p0.z);
  153 + glTexCoord3f(t1.x, t1.y, t1.z);
  154 + glVertex3f(p1.x, p1.y, p1.z);
  155 + glTexCoord3f(t2.x, t2.y, t2.z);
  156 + glVertex3f(p2.x, p2.y, p2.z);
  157 + glTexCoord3f(t3.x, t3.y, t3.z);
  158 + glVertex3f(p3.x, p3.y, p3.z);
  159 + glEnd();
  160 +
  161 + glDisable(GL_TEXTURE_3D);
  162 + glDisable(GL_BLEND);
  163 +
  164 +
  165 +}
  166 +void rts_glVolumeViewer::RenderCameraSlice(point3D eye_point, vector3D camera_up, float slice_number)
  167 +{
  168 + /*Renders a slice of the volume at the specified value (0 = closest
  169 + to the camera while 1 = furthest from the camera). The slice is oriented towards
  170 + the camera position*/
  171 +
  172 + /*//get the vector from the volume to the eye point
  173 + vector3D to_camera = eye_point - m_p;
  174 + //normalize in order to compute the plane normal
  175 + to_camera.normalize();
  176 +
  177 + //draw the camera-oriented plane
  178 + m_draw_plane(m_p, to_camera, camera_up);*/
  179 +
  180 + glMatrixMode(GL_MODELVIEW);
  181 + glPushMatrix();
  182 +
  183 + //calculate the new basis functions
  184 + vector3D to_camera = (eye_point - m_p); to_camera.normalize();
  185 + vector3D side = camera_up.cross(to_camera); side.normalize();
  186 + camera_up = to_camera.cross(side); camera_up.normalize();
  187 + //create the rotation matrix
  188 + matrix4x4 mat_rotate(side, camera_up, to_camera);
  189 + float gl_rotate[16];
  190 + mat_rotate.gl_get_matrix(gl_rotate);
  191 +
  192 + //perform the geometric transformations
  193 + glScalef(m_dimensions.x, m_dimensions.y, m_dimensions.z);
  194 + glTranslatef(m_p.x, m_p.y, m_p.z);
  195 + glMultMatrixf(gl_rotate);
  196 +
  197 +
  198 + //perform the texture transformations
  199 + glMatrixMode(GL_TEXTURE);
  200 + glPushMatrix();
  201 + glLoadIdentity();
  202 + glScalef(m_source.get_dimx()/m_texture_size.x,
  203 + m_source.get_dimy()/m_texture_size.y,
  204 + m_source.get_dimz()/m_texture_size.z);
  205 + glTranslatef(0.5, 0.5, 0.5);
  206 + glMultMatrixf(gl_rotate);
  207 +
  208 +
  209 + //enable texture mapping
  210 + glEnable(GL_TEXTURE_3D);
  211 + glBindTexture(GL_TEXTURE_3D, m_volume_texture);
  212 +
  213 + //enable blending
  214 + //glDisable(GL_DEPTH_TEST);
  215 + glEnable(GL_BLEND);
  216 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  217 +
  218 + //draw the planes
  219 + glColor4f(1.0, 1.0, 1.0, 1.0);
  220 + //PD.StartTimer(RENDER_PLANES);
  221 + //glCallList(m_dl_planes);
  222 + glBegin(GL_QUADS);
  223 + glTexCoord3f(-m_outer_radius, -m_outer_radius, slice_number);
  224 + glVertex3f(-m_outer_radius, -m_outer_radius, slice_number);
  225 + glTexCoord3f(-m_outer_radius, m_outer_radius, slice_number);
  226 + glVertex3f(-m_outer_radius, m_outer_radius, slice_number);
  227 + glTexCoord3f(m_outer_radius, m_outer_radius, slice_number);
  228 + glVertex3f(m_outer_radius, m_outer_radius, slice_number);
  229 + glTexCoord3f(m_outer_radius, -m_outer_radius, slice_number);
  230 + glVertex3f(m_outer_radius, -m_outer_radius, slice_number);
  231 + glEnd();
  232 +
  233 + //glFinish();
  234 + //PD.EndTimer(RENDER_PLANES);
  235 +
  236 + glMatrixMode(GL_MODELVIEW);
  237 + glPopMatrix();
  238 + glMatrixMode(GL_TEXTURE);
  239 + glPopMatrix();
  240 +
  241 + glDisable(GL_TEXTURE_3D);
  242 + glDisable(GL_BLEND);
  243 +
  244 +
  245 +}
  246 +
  247 +void rts_glVolumeViewer::RenderVolume(point3D eye_point, vector3D camera_up)
  248 +{
  249 + if(m_volume_texture == 0)
  250 + return;
  251 +
  252 + glMatrixMode(GL_MODELVIEW);
  253 + glPushMatrix();
  254 +
  255 + //calculate the new basis functions
  256 + vector3D to_camera = (eye_point - m_p); to_camera.normalize();
  257 + vector3D side = camera_up.cross(to_camera); side.normalize();
  258 + camera_up = to_camera.cross(side); camera_up.normalize();
  259 + //create the rotation matrix
  260 + matrix4x4 mat_rotate(side, camera_up, to_camera);
  261 + float gl_rotate[16];
  262 + mat_rotate.gl_get_matrix(gl_rotate);
  263 +
  264 + //perform the geometric transformations
  265 + glScalef(m_dimensions.x, m_dimensions.y, m_dimensions.z);
  266 + glTranslatef(m_p.x, m_p.y, m_p.z);
  267 + glMultMatrixf(gl_rotate);
  268 +
  269 +
  270 + //perform the texture transformations
  271 + glMatrixMode(GL_TEXTURE);
  272 + glPushMatrix();
  273 + glLoadIdentity();
  274 + glScalef(m_source.get_dimx()/m_texture_size.x,
  275 + m_source.get_dimy()/m_texture_size.y,
  276 + m_source.get_dimz()/m_texture_size.z);
  277 + glTranslatef(0.5, 0.5, 0.5);
  278 + glMultMatrixf(gl_rotate);
  279 +
  280 +
  281 + //enable texture mapping
  282 + glEnable(GL_TEXTURE_3D);
  283 + glBindTexture(GL_TEXTURE_3D, m_volume_texture);
  284 +
  285 + //enable blending
  286 + glDisable(GL_DEPTH_TEST);
  287 + //glEnable(GL_DEPTH_TEST);
  288 + glEnable(GL_BLEND);
  289 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  290 +
  291 + //draw the planes
  292 + glColor4f(1.0, 1.0, 1.0, m_alpha_scale);
  293 + PD.StartTimer(RENDER_PLANES);
  294 + glCallList(m_dl_planes);
  295 + glFinish();
  296 + PD.EndTimer(RENDER_PLANES);
  297 +
  298 + glMatrixMode(GL_MODELVIEW);
  299 + glPopMatrix();
  300 + glMatrixMode(GL_TEXTURE);
  301 + glPopMatrix();
  302 +
  303 + glDisable(GL_TEXTURE_3D);
  304 + glDisable(GL_BLEND);
  305 + glEnable(GL_DEPTH_TEST);
  306 +
  307 +
  308 +}
  309 +
  310 +void rts_glVolumeViewer::SetNumPlanes(unsigned int planes)
  311 +{
  312 + //set the number of planes
  313 + m_num_planes = planes;
  314 +
  315 + //create the display list
  316 + m_dl_planes = glGenLists(1);
  317 + glNewList(m_dl_planes, GL_COMPILE);
  318 +
  319 + //the display planes run from (-m_outer_radius, m_outer_radius) in each dimension
  320 + float z_step = 2.0*m_outer_radius/(planes + 1.0);
  321 + glBegin(GL_QUADS);
  322 + for(int z=0; z<planes; z++)
  323 + {
  324 + glTexCoord3f(-m_outer_radius, -m_outer_radius, -m_outer_radius+z*z_step);
  325 + glVertex3f(-m_outer_radius, -m_outer_radius, -m_outer_radius+z*z_step);
  326 + glTexCoord3f(-m_outer_radius, m_outer_radius, -m_outer_radius+z*z_step);
  327 + glVertex3f(-m_outer_radius, m_outer_radius, -m_outer_radius+z*z_step);
  328 + glTexCoord3f(m_outer_radius, m_outer_radius, -m_outer_radius+z*z_step);
  329 + glVertex3f(m_outer_radius, m_outer_radius, -m_outer_radius+z*z_step);
  330 + glTexCoord3f(m_outer_radius, -m_outer_radius, -m_outer_radius+z*z_step);
  331 + glVertex3f(m_outer_radius, -m_outer_radius, -m_outer_radius+z*z_step);
  332 + }
  333 + glEnd();
  334 + glEndList();
  335 +}
  336 +
  337 +void rts_glVolumeViewer::SetSize(float x, float y, float z)
  338 +{
  339 + m_dimensions.x = x;
  340 + m_dimensions.y = y;
  341 + m_dimensions.z = z;
  342 +}
  343 +
  344 +void rts_glVolumeViewer::SetVoxelSize(float x, float y, float z)
  345 +{
  346 + m_voxel_size.x = x;
  347 + m_voxel_size.y = y;
  348 + m_voxel_size.z = z;
  349 + m_dimensions = vector3D(m_voxel_size.x * m_texture_size.x,
  350 + m_voxel_size.y * m_texture_size.y,
  351 + m_voxel_size.z * m_texture_size.z);
  352 + m_dimensions.normalize();
  353 +}
  354 +
  355 +vector3D rts_glVolumeViewer::GetSize()
  356 +{
  357 + return m_dimensions;
  358 +}
  359 +
  360 +vector3D rts_glVolumeViewer::GetVoxelSize()
  361 +{
  362 + return m_voxel_size;
  363 +}
  364 +
  365 +void rts_glVolumeViewer::SetThreshold(unsigned char lower, unsigned char upper)
  366 +{
  367 + //set the new threshold values
  368 + m_min_threshold = lower;
  369 + m_max_threshold = upper;
  370 +
  371 + //reload the texture map
  372 + m_load_texture();
  373 +}
  374 +
  375 +void rts_glVolumeViewer::Optimize(bool flag)
  376 +{
  377 + //TODO Optimization causes a problem with texture sizing
  378 + /*//if the user changed the setting, reload the texture
  379 + if(m_optimize != flag)
  380 + {
  381 + m_optimize = flag;
  382 + m_load_texture();
  383 + }*/
  384 + cout<<"Optimization has been removed due to bugs"<<endl;
  385 +
  386 +
  387 +}
  388 +
  389 +void rts_glVolumeViewer::Invert()
  390 +{
  391 + //this function inverts the original data set
  392 + m_source.invert();
  393 + m_load_texture();
  394 +}
  395 +
  396 +void rts_glVolumeViewer::m_load_texture()
  397 +{
  398 + //duplicate the source data
  399 + PD.StartTimer(LOAD_TEXTURE);
  400 + rtsVolume texture_volume = m_source;
  401 +
  402 + //place a black border around the volume
  403 + PD.StartTimer(BLACKEN_BORDERS);
  404 + texture_volume.blacken_border();
  405 + PD.EndTimer(BLACKEN_BORDERS);
  406 +
  407 + if(m_min_threshold > 0)
  408 + texture_volume.blacken(m_min_threshold);
  409 + if(m_max_threshold < 255)
  410 + texture_volume.whiten(m_max_threshold);
  411 +
  412 +
  413 +
  414 + //if we are optimizing the texture, make the dimensions a power-of-two
  415 + if(m_optimize)
  416 + {
  417 + PD.StartTimer(RESIZE_DATA);
  418 + //find the maximum dimension
  419 + unsigned int max_dimension = max(max(m_source.get_dimx(), m_source.get_dimy()), m_source.get_dimz());
  420 +
  421 + unsigned int new_dimension = 2;
  422 + //calculate the new dimension
  423 + while(new_dimension < max_dimension)
  424 + new_dimension *= 2;
  425 + //resize the texture volume
  426 + texture_volume.resize_canvas(new_dimension, new_dimension, new_dimension);
  427 + PD.EndTimer(RESIZE_DATA);
  428 + }
  429 +
  430 + //apply the new image to the texture
  431 + glBindTexture(GL_TEXTURE_3D, m_volume_texture);
  432 + unsigned int dimx = texture_volume.get_dimx();
  433 + unsigned int dimy = texture_volume.get_dimy();
  434 + unsigned int dimz = texture_volume.get_dimz();
  435 + m_texture_size = vector3D((double)dimx, (double)dimy, (double)dimz);
  436 + unsigned char* bits = texture_volume.get_bits();
  437 + glTexImage3D(GL_TEXTURE_3D, 0, GL_ALPHA8, dimx, dimy, dimz, 0, GL_ALPHA,
  438 + GL_UNSIGNED_BYTE, bits);
  439 +
  440 + PD.EndTimer(LOAD_TEXTURE);
  441 +
  442 +}
  443 +
  444 +
  445 +
  446 +
... ...
rts_glVolumeViewer.h 0 → 100755
  1 +++ a/rts_glVolumeViewer.h
  1 +#ifndef RTS_GLVOLUMEVIEWER_H
  2 +#define RTS_GLVOLUMEVIEWER_H
  3 +
  4 +#include <windows.h>
  5 +#include <gl/glew.h>
  6 +#include <FL/glut.h>
  7 +#include <gl/gl.h>
  8 +//#include <gl/glxext.h>
  9 +#include <gl/glext.h>
  10 +#include <gl/wglext.h>
  11 +//#include <gl/wglext.h>
  12 +#include "rtsMath.h"
  13 +#include "rtsVolume.h"
  14 +#include "rts_glUtilities.h"
  15 +
  16 +class rts_glVolumeViewer
  17 +{
  18 +private:
  19 +
  20 + rtsVolume m_source;
  21 + GLuint m_volume_texture;
  22 + vector3D m_texture_size; //size of the volume being viewed (in voxels)
  23 + vector3D m_voxel_size;
  24 + bool m_optimize; //optimization flag (use more texture space for faster viz)
  25 +
  26 + point3D m_p; //position of the volume (0,0,0) corner in space
  27 + vector3D m_dimensions;
  28 +
  29 + double m_alpha_scale;
  30 + unsigned char m_min_threshold; //min and max thresholds to be displayed
  31 + unsigned char m_max_threshold;
  32 +
  33 + unsigned int m_num_planes;
  34 +
  35 + GLuint m_dl_planes; //planes display list
  36 +
  37 +
  38 + double m_inner_radius; //radius of the inscribed sphere
  39 + double m_outer_radius; //radius of the circumscribed sphere
  40 +
  41 + void m_draw_plane(point3D p, vector3D n, vector3D u); //draws a camera-oriented plane at point with normal n
  42 + void m_load_texture();
  43 +
  44 +
  45 +public:
  46 + rts_glVolumeViewer();
  47 + //rts_glVolumeViewer(rtsVolume volume_data, point3D position);
  48 + rts_glVolumeViewer(rtsVolume volume_data,
  49 + point3D position,
  50 + vector3D voxel_size);
  51 + void SetSize(float x, float y, float z);
  52 + void SetVoxelSize(float x, float y, float z);
  53 + vector3D GetSize();
  54 + vector3D GetVoxelSize();
  55 + void RenderBoundingBox();
  56 + void RenderCameraSlice(point3D eye_point, vector3D camera_up, float slice_number = 0.0);
  57 + void RenderVolume(point3D eye_point, vector3D camera_up);
  58 + void SetAlphaScale(double scale){m_alpha_scale = scale;}
  59 + void SetNumPlanes(unsigned int planes);
  60 + void SetThreshold(unsigned char lower, unsigned char upper);
  61 + void Optimize(bool flag);
  62 + void Invert();
  63 +};
  64 +
  65 +
  66 +
  67 +#endif
0 68 \ No newline at end of file
... ...
rts_glutRenderWindow.h 0 → 100755
  1 +++ a/rts_glutRenderWindow.h
  1 +#include <GL/glew.h>
  2 +#include <GL/glut.h>
  3 +#include "rtsQuaternion.h"
  4 +#include "rtsCamera.h"
  5 +
  6 +float d_angle = 0.05;
  7 +
  8 +rtsCamera rts_glut_camera;
  9 +unsigned int mouse_x;
  10 +unsigned int mouse_y;
  11 +int mouse_button;
  12 +
  13 +
  14 +//user display function pointer
  15 +void (*UserDisplay)(void);
  16 +
  17 +
  18 +
  19 +/*void KeyboardFunction(unsigned char key, int x, int y)
  20 +{
  21 + if(key == 27)
  22 + exit(0);
  23 +
  24 +}*/
  25 +
  26 +/*void SpecialKeys(int key, int x, int y)
  27 +{
  28 + rtsQuaternion<float> new_rotation;
  29 +
  30 + if(key == GLUT_KEY_UP)
  31 + rts_glut_camera.OrbitFocus(0, d_angle);
  32 + if(key == GLUT_KEY_DOWN)
  33 + rts_glut_camera.OrbitFocus(0, -d_angle);
  34 + if(key == GLUT_KEY_LEFT)
  35 + rts_glut_camera.OrbitFocus(d_angle, 0.0);
  36 + if(key == GLUT_KEY_RIGHT)
  37 + rts_glut_camera.OrbitFocus(-d_angle, 0.0);
  38 +}*/
  39 +
  40 +void MouseDrag(int x, int y)
  41 +{
  42 + int dx = x - mouse_x;
  43 + int dy = y - mouse_y;
  44 +
  45 + if(mouse_button == GLUT_LEFT_BUTTON)
  46 + rts_glut_camera.OrbitFocus(-dx*0.01, dy*0.01);
  47 + else if(mouse_button == GLUT_MIDDLE_BUTTON)
  48 + rts_glut_camera.Zoom(dy*rts_glut_camera.getFOV()/60.0);
  49 +
  50 + mouse_x = x;
  51 + mouse_y = y;
  52 +
  53 +}
  54 +
  55 +void MouseMove(int x, int y)
  56 +{
  57 + mouse_x = x;
  58 + mouse_y = y;
  59 +}
  60 +
  61 +void MouseClick(int button, int state, int x, int y)
  62 +{
  63 + if(state == GLUT_DOWN)
  64 + mouse_button = button;
  65 +
  66 +
  67 +}
  68 +
  69 +void IdleFunction()
  70 +{
  71 + glutPostRedisplay();
  72 +}
  73 +
  74 +void RenderCamera()
  75 +{
  76 + //set viewport
  77 + glMatrixMode(GL_PROJECTION);
  78 + glLoadIdentity();
  79 + glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
  80 +
  81 + //compute the aspect ratio
  82 + float aspect_ratio = (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT);
  83 + gluPerspective(rts_glut_camera.getFOV(), aspect_ratio, 0.01, 10.0);
  84 +
  85 + //render the camera
  86 + glMatrixMode(GL_MODELVIEW);
  87 + glLoadIdentity();
  88 +
  89 + point3D<float> camera_position = rts_glut_camera.getPosition();
  90 + vector3D<float> camera_up = rts_glut_camera.getUp();
  91 + gluLookAt(camera_position.x,
  92 + camera_position.y,
  93 + camera_position.z,
  94 + 0.0, 0.0, 0.0,
  95 + camera_up.x,
  96 + camera_up.y,
  97 + camera_up.z);
  98 +}
  99 +
  100 +void rts_glutInitialize(const char* WindowName, int width = 1024, int height = 768)
  101 +{
  102 + char *myargv [1];
  103 + int myargc=1;
  104 + myargv [0]=strdup ("AppName");
  105 + glutInit(&myargc, myargv);
  106 +
  107 + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  108 + glutInitWindowSize(width, height);
  109 + glutInitWindowPosition(200,0);
  110 + glutCreateWindow(WindowName);
  111 +
  112 + //initialize GLEW
  113 + GLenum err = glewInit();
  114 + if(err != GLEW_OK)
  115 + fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
  116 + if (!glewIsSupported("GL_VERSION_2_0"))
  117 + {
  118 + printf("OpenGL 2.0 not supported\n");
  119 + //exit(1);
  120 + }
  121 + glEnable(GL_DEPTH_TEST);
  122 +
  123 + glClearColor(1.0, 1.0, 1.0, 0.0);
  124 +
  125 + rts_glut_camera.setPosition(0.0, 0.0, -1.0);
  126 + rts_glut_camera.setFOV(60);
  127 + rts_glut_camera.LookAt(0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  128 +}
  129 +
  130 +void DisplayFunction()
  131 +{
  132 + RenderCamera();
  133 + UserDisplay();
  134 + glutSwapBuffers();
  135 +}
  136 +
  137 +void rts_glutStart(void (*display_func)(void))
  138 +{
  139 + //glutSpecialFunc(SpecialKeys);
  140 + //glutKeyboardFunc(KeyboardFunction);
  141 + glutDisplayFunc(DisplayFunction);
  142 + glutMotionFunc(MouseDrag);
  143 + glutMouseFunc(MouseClick);
  144 + glutPassiveMotionFunc(MouseMove);
  145 + UserDisplay = display_func;
  146 + glutIdleFunc(IdleFunction);
  147 +
  148 +
  149 +
  150 + //glutReshapeFunc(ReshapeFunction);
  151 + //glutMouseFunc(MouseFunction);
  152 + //glutMotionFunc(MotionFunction);
  153 + glutMainLoop();
  154 +
  155 +}
... ...
rts_itkFunctions.h 0 → 100755
  1 +++ a/rts_itkFunctions.h
  1 +#include "itkImage.h"
  2 +#include "itkImageFileReader.h"
  3 +#include "itkRAWImageIO.h"
  4 +#include "itkImageRegionIteratorWithIndex.h"
  5 +
  6 +typedef itk::Image<unsigned char, 3> VOLType;
  7 +
  8 +VOLType::Pointer rts_itkNewVOL(int x, int y, int z)
  9 +{
  10 + //Create a new image and allocate the desired amount of space
  11 + //typedef itk::Image<T, 3> ImageType;
  12 + VOLType::Pointer result = VOLType::New();
  13 + VOLType::RegionType region;
  14 + VOLType::SizeType size = {x, y, z};
  15 + region.SetSize(size);
  16 + VOLType::IndexType index = {0, 0, 0};
  17 + region.SetIndex(index);
  18 + result->SetRegions(region);
  19 + result->Allocate();
  20 +
  21 + return result;
  22 +
  23 +}
  24 +
  25 +VOLType::Pointer rts_itkLoadVOL(const char* filename, unsigned int max_slices = 512)
  26 +{
  27 + //first load the header information
  28 + ifstream infile(filename, ios::in | ios::binary); //create the files stream
  29 + if(!infile)
  30 + return VOLType::New();
  31 +
  32 + unsigned int size_x, size_y, size_z; //create variables to store the size of the data set
  33 + //load the dimensions of the data set
  34 + infile.read((char*)&size_x, sizeof(int)); //load the file header
  35 + infile.read((char*)&size_y, sizeof(int));
  36 + infile.read((char*)&size_z, sizeof(int));
  37 +
  38 + //close the file
  39 + infile.close();
  40 +
  41 +
  42 + VOLType::Pointer volume;
  43 +
  44 +
  45 + //create the reader
  46 + typedef itk::ImageFileReader<VOLType> ReaderType;
  47 + typedef itk::RawImageIO<unsigned char, 3> RawType;
  48 +
  49 + ReaderType::Pointer reader = ReaderType::New();
  50 + RawType::Pointer rawIO = RawType::New();
  51 +
  52 +
  53 +
  54 + reader->SetImageIO(rawIO);
  55 + reader->SetFileName(filename);
  56 +
  57 + //set the raw IO parameters
  58 + rawIO->SetFileTypeToBinary();
  59 +
  60 +
  61 + //set the format of the RAW file
  62 + rawIO->SetHeaderSize(12);
  63 + rawIO->SetDimensions(0, size_x);
  64 + rawIO->SetDimensions(1, size_y);
  65 +
  66 + if(size_z < max_slices)
  67 + rawIO->SetDimensions(2, size_z);
  68 + else
  69 + rawIO->SetDimensions(2, max_slices);
  70 +
  71 + //read the file
  72 + try
  73 + {
  74 + reader->Update();
  75 + }
  76 + catch(itk::ExceptionObject & exp)
  77 + {
  78 + std::cout<<exp<<std::endl;
  79 + }
  80 +
  81 +
  82 + volume = reader->GetOutput();
  83 +
  84 + return volume;
  85 +}
  86 +VOLType::Pointer rts_itkLoadRAW(const char* filename, unsigned int size_x, unsigned int size_y, unsigned int size_z)
  87 +{
  88 + //first load the header information
  89 + ifstream infile(filename, ios::in | ios::binary); //create the files stream
  90 + if(!infile)
  91 + return VOLType::New();
  92 +
  93 +
  94 +
  95 + //close the file
  96 + infile.close();
  97 +
  98 +
  99 + VOLType::Pointer volume;
  100 +
  101 +
  102 + //create the reader
  103 + typedef itk::ImageFileReader<VOLType> ReaderType;
  104 + typedef itk::RawImageIO<unsigned char, 3> RawType;
  105 +
  106 + ReaderType::Pointer reader = ReaderType::New();
  107 + RawType::Pointer rawIO = RawType::New();
  108 +
  109 +
  110 +
  111 + reader->SetImageIO(rawIO);
  112 + reader->SetFileName(filename);
  113 +
  114 + //set the raw IO parameters
  115 + rawIO->SetFileTypeToBinary();
  116 +
  117 +
  118 + //set the format of the RAW file
  119 + rawIO->SetHeaderSize(0);
  120 + rawIO->SetDimensions(0, size_x);
  121 + rawIO->SetDimensions(1, size_y);
  122 + rawIO->SetDimensions(2, size_z);
  123 +
  124 +
  125 + //read the file
  126 + try
  127 + {
  128 + reader->Update();
  129 + }
  130 + catch(itk::ExceptionObject & exp)
  131 + {
  132 + std::cout<<exp<<std::endl;
  133 + }
  134 +
  135 +
  136 + volume = reader->GetOutput();
  137 +
  138 + return volume;
  139 +}
  140 +void rts_itkSaveVOL(VOLType::Pointer itk_image, const char* filename)
  141 +{
  142 + typedef itk::ImageRegionIteratorWithIndex<VOLType> IteratorType;
  143 + IteratorType i(itk_image, itk_image->GetLargestPossibleRegion());
  144 +
  145 + //create variables for size and position
  146 + VOLType::IndexType index;
  147 + VOLType::SizeType size;
  148 + //get the volume size
  149 + size = itk_image->GetLargestPossibleRegion().GetSize();
  150 + unsigned char* buffer = new unsigned char[size[0]*size[1]*size[2]];
  151 +
  152 + for(i.GoToBegin(); !i.IsAtEnd(); ++i)
  153 + {
  154 + index = i.GetIndex();
  155 + buffer[index[0] + size[0] * (index[1] + index[2] * size[1])] = i.Get();
  156 + }
  157 +
  158 +
  159 + ofstream outfile(filename, ios::out | ios::binary); //create the binary file stream
  160 +
  161 + //write the volume size to the file
  162 + outfile.write((char*)&size[0], sizeof(int));
  163 + outfile.write((char*)&size[1], sizeof(int));
  164 + outfile.write((char*)&size[2], sizeof(int));
  165 +
  166 + outfile.write((char*)buffer, sizeof(char)*size[0]*size[1]*size[2]);
  167 + outfile.close();
  168 +}
0 169 \ No newline at end of file
... ...
rts_itkImage.h 0 → 100755
  1 +++ a/rts_itkImage.h
  1 +#ifndef _RTS_ITK_IMAGE_H
  2 +#define _RTS_ITK_IMAGE_H
  3 +
  4 +#include "itkImage.h"
  5 +#include "itkImageFileReader.h"
  6 +#include "itkImageFileWriter.h"
  7 +#include "itkCastImageFilter.h"
  8 +#include "itkRescaleIntensityImageFilter.h"
  9 +#include "rtsDTGrid2D.h"
  10 +
  11 +#include <string>
  12 +
  13 +using namespace std;
  14 +
  15 +
  16 +
  17 +template<typename T>
  18 +class rts_itkImage
  19 +{
  20 +public:
  21 + typedef itk::Image<T> ITKImageType;
  22 + typedef typename ITKImageType::Pointer ITKPointerType;
  23 + ITKPointerType image_source;
  24 +
  25 +public:
  26 + rts_itkImage();
  27 + rts_itkImage(int res_x, int res_y);
  28 + void Allocate(int res_x, int res_y);
  29 + void LoadImage(string filename);
  30 + void LoadRAW(int header_size, int res_x, int res_y, string filename);
  31 + void SaveImage(string filename);
  32 + void SaveRAW(string filename);
  33 + void CastAndSaveImage(string filename);
  34 + void RescaleImage(T min, T max);
  35 + void InsertDTGrid(rtsDTGrid2D<T>* grid, bool debug = 0);
  36 + T* GetPointer();
  37 + rts_itkImage<T> SubImage(int px, int py, int sx, int sy);
  38 +
  39 + void SetPixel(int x, int y, T value);
  40 + T GetPixel(int x, int y);
  41 +
  42 + //element-wise operators
  43 + rts_itkImage<T> operator+(T rhs);
  44 +
  45 + int DimX(){return image_source->GetLargestPossibleRegion().GetSize()[0];}
  46 + int DimY(){return image_source->GetLargestPossibleRegion().GetSize()[1];}
  47 +
  48 +
  49 +};
  50 +
  51 +template <class T>
  52 +rts_itkImage<T> rts_itkImage<T>::operator+(T rhs)
  53 +{
  54 + rts_itkImage<T> result(DimX(), DimY());
  55 +
  56 + int x, y;
  57 + for(x=0; x<DimX(); x++)
  58 + for(y=0; y<DimY(); y++)
  59 + result.SetPixel(x, y, GetPixel(x, y) + rhs);
  60 +
  61 + return result;
  62 +}
  63 +
  64 +template <typename T>
  65 +void rts_itkImage<T>::SetPixel(int x, int y, T value)
  66 +{
  67 + ITKImageType::IndexType index;
  68 + index[0] = x;
  69 + index[1] = y;
  70 + image_source->SetPixel(index, value);
  71 +}
  72 +
  73 +template <typename T>
  74 +T rts_itkImage<T>::GetPixel(int x, int y)
  75 +{
  76 + ITKImageType::IndexType index;
  77 + index[0] = x;
  78 + index[1] = y;
  79 + return image_source->GetPixel(index);
  80 +}
  81 +
  82 +template <class T>
  83 +rts_itkImage<T>::rts_itkImage()
  84 +{
  85 + if(image_source.IsNotNull())
  86 + image_source = NULL;
  87 + image_source = ITKImageType::New();
  88 +}
  89 +
  90 +template <class T>
  91 +rts_itkImage<T>::rts_itkImage(int res_x, int res_y)
  92 +{
  93 + Allocate(res_x, res_y);
  94 +}
  95 +
  96 +template<typename T>
  97 +void rts_itkImage<T>::Allocate(int res_x, int res_y)
  98 +{
  99 + if(image_source.IsNotNull())
  100 + {
  101 + image_source = NULL;
  102 + }
  103 +
  104 + image_source = ITKImageType::New();
  105 +
  106 + ITKImageType::RegionType region;
  107 + ITKImageType::SizeType size;
  108 + size[0] = res_x;
  109 + size[1] = res_y;
  110 +
  111 + region.SetSize(size);
  112 + image_source->SetRegions(region);
  113 +
  114 + try
  115 + {
  116 + image_source->Allocate();
  117 + }
  118 + catch(itk::ExceptionObject & exp)
  119 + {
  120 + std::cout<<exp<<std::endl;
  121 + }
  122 +
  123 +}
  124 +
  125 +
  126 +template <typename T>
  127 +rts_itkImage<T> rts_itkImage<T>::SubImage(int px, int py, int sx, int sy)
  128 +{
  129 + /*This function returns the sub-volume specified by a corner point and size*/
  130 +
  131 + //first make sure that the sub-volume is contained within the image
  132 + if(px < 0) {sx += px; px = 0;}
  133 + if(py < 0) {sy += py; py = 0;}
  134 + if(px >= DimX()) px = DimX() - 1;
  135 + if(py >= DimY()) py = DimY() - 1;
  136 + if(px + sx > DimX()) sx = DimX() - px - 1;
  137 + if(py + sy > DimY()) sy = DimY() - py - 1;
  138 +
  139 + cout<<px<<","<<py<<","<<sx<<","<<sy<<endl;
  140 +
  141 + //create the resulting volume
  142 + rts_itkImage<T> destination(sx, sy);
  143 +
  144 + //get an iterator for the destination volume
  145 + itk::ImageRegionIterator<ITKImageType> d(destination.image_source, destination.image_source->GetLargestPossibleRegion());
  146 +
  147 + //get an iterator for the source region
  148 + ITKImageType::RegionType region;
  149 + ITKImageType::IndexType index;
  150 + ITKImageType::SizeType size;
  151 + index[0] = px; index[1] = py;
  152 + size[0] = sx; size[1] = sy;
  153 + region.SetIndex(index);
  154 + region.SetSize(size);
  155 + itk::ImageRegionIterator<ITKImageType> s(image_source, region);
  156 +
  157 + //copy the data from source region to destination volume
  158 + for(s.GoToBegin(), d.GoToBegin();
  159 + !s.IsAtEnd();
  160 + s++, d++)
  161 + d.Set(s.Get());
  162 +
  163 + return destination;
  164 +
  165 +}
  166 +
  167 +template<typename T>
  168 +T* rts_itkImage<T>::GetPointer()
  169 +{
  170 + return image_source->GetBufferPointer();
  171 +}
  172 +
  173 +template<typename T>
  174 +void rts_itkImage<T>::LoadImage(string filename)
  175 +{
  176 + typedef itk::ImageFileReader<ITKImageType> ReaderType;
  177 + ReaderType::Pointer reader = ReaderType::New();
  178 + reader->SetFileName(filename.c_str());
  179 + image_source = reader->GetOutput();
  180 +
  181 + try
  182 + {
  183 + reader->Update();
  184 + }
  185 + catch(itk::ExceptionObject & exp)
  186 + {
  187 + std::cout<<exp<<std::endl;
  188 + }
  189 +
  190 +}
  191 +
  192 +template <typename T>
  193 +void rts_itkImage<T>::LoadRAW(int header_size, int size_x,
  194 + int size_y, string filename)
  195 +{
  196 + Allocate(size_x, size_y);
  197 +
  198 +
  199 + ifstream infile(filename.c_str(), ios::out | ios::binary); //create the files stream
  200 + if(!infile)
  201 + return;
  202 + //first read the header
  203 + char* header = new char[header_size];
  204 + infile.read((char*)header, header_size);
  205 +
  206 + //now read the actual data
  207 + infile.read((char*)image_source->GetBufferPointer(), DimX()*DimY()*sizeof(T));
  208 +
  209 + infile.close();
  210 +}
  211 +
  212 +template<typename T>
  213 +void rts_itkImage<T>::SaveImage(string filename)
  214 +{
  215 + typedef itk::ImageFileWriter<ITKImageType> WriterType;
  216 + WriterType::Pointer writer = WriterType::New();
  217 + writer->SetFileName(filename.c_str());
  218 + writer->SetInput(image_source);
  219 +
  220 + try
  221 + {
  222 + writer->Update();
  223 + }
  224 + catch(itk::ExceptionObject & exp)
  225 + {
  226 + std::cout<<exp<<std::endl;
  227 + }
  228 +
  229 +}
  230 +
  231 +template <typename T>
  232 +void rts_itkImage<T>::SaveRAW(string filename)
  233 +{
  234 + ofstream outfile(filename.c_str(), ios::out | ios::binary); //create the files stream
  235 + if(!outfile)
  236 + return;
  237 +
  238 + outfile.write((char*)image_source->GetBufferPointer(), DimX()*DimY()*sizeof(T));
  239 + outfile.close();
  240 +}
  241 +
  242 +template<typename T>
  243 +void rts_itkImage<T>::CastAndSaveImage(string filename)
  244 +{
  245 + //create the destination image
  246 + typedef itk::Image<unsigned char> DestinationType;
  247 + DestinationType::Pointer dest_image = DestinationType::New();
  248 +
  249 + //create the casting filter
  250 + typedef itk::CastImageFilter<ITKImageType, DestinationType> CastFilterType;
  251 + CastFilterType::Pointer castFilter = CastFilterType::New();
  252 + castFilter->SetInput(image_source);
  253 +
  254 +
  255 + //cast the current image
  256 + dest_image = castFilter->GetOutput();
  257 +
  258 + //save the result
  259 + typedef itk::ImageFileWriter<DestinationType> WriterType;
  260 + WriterType::Pointer writer = WriterType::New();
  261 + writer->SetFileName(filename.c_str());
  262 + writer->SetInput(dest_image);
  263 +
  264 + try
  265 + {
  266 + writer->Update();
  267 + }
  268 + catch(itk::ExceptionObject & exp)
  269 + {
  270 + std::cout<<exp<<std::endl;
  271 + }
  272 +}
  273 +
  274 +template<typename T>
  275 +void rts_itkImage<T>::RescaleImage(T min_v, T max_v)
  276 +{
  277 + typedef itk::RescaleIntensityImageFilter<ITKImageType, ITKImageType> RescaleFilter;
  278 + RescaleFilter::Pointer rescaleFilter = RescaleFilter::New();
  279 + rescaleFilter->SetInput(image_source);
  280 + rescaleFilter->SetOutputMinimum(min_v);
  281 + rescaleFilter->SetOutputMaximum(max_v);
  282 + image_source = rescaleFilter->GetOutput();
  283 + rescaleFilter->Update();
  284 +}
  285 +
  286 +template<typename T>
  287 +void rts_itkImage<T>::InsertDTGrid(rtsDTGrid2D<T>* grid, bool debug = false)
  288 +{
  289 + //find the extents of the DT Grid
  290 + int min_x, min_y, max_x, max_y;
  291 + grid->getBounds(min_x, min_y, max_x, max_y);
  292 +
  293 + //allocate the appropriate amount of space
  294 + ITKImageType::RegionType region;
  295 + ITKImageType::SizeType size;
  296 + size[0] = (max_x - min_x) + 1;
  297 + size[1] = (max_y - min_y) + 1;
  298 + region.SetSize(size);
  299 + image_source->SetRegions(region);
  300 +
  301 + try
  302 + {
  303 + image_source->Allocate();
  304 + }
  305 + catch(itk::ExceptionObject & exp)
  306 + {
  307 + std::cout<<exp<<std::endl;
  308 + }
  309 +
  310 + //fill the image with the background color
  311 + image_source->FillBuffer(grid->background);
  312 +
  313 + //copy values from the DT Grid to the image
  314 + ITKImageType::IndexType index; //create an image index
  315 + rtsDTGrid2D<T>::iterator i; //create an iterator
  316 +
  317 + for(i = grid->begin(); i!= grid->after(); i++)
  318 + {
  319 + index[0] = i.X1() - min_x;
  320 + index[1] = i.X2() - min_y;
  321 + image_source->SetPixel(index, i.Value());
  322 +
  323 + //cout<<index[0]<<","<<index[1]<<": "<<i.Value()<<endl;
  324 +
  325 + }
  326 +
  327 +
  328 +
  329 +
  330 +}
  331 +
  332 +
  333 +
  334 +#endif
... ...
rts_itkVolume.h 0 → 100755
  1 +++ a/rts_itkVolume.h
  1 +#ifndef RTS_ITKVOLUME_H
  2 +#define RTS_ITKVOLUME_H
  3 +
  4 +#include <WTypes.h>
  5 +#include "itkImage.h"
  6 +#include "itkImageFileReader.h"
  7 +#include "itkImageFileWriter.h"
  8 +#include "itkRawImageIO.h"
  9 +#include "itkImageRegionIterator.h"
  10 +#include <string>
  11 +#include "rtsFilename.h"
  12 +#include "rtsDTGrid3D.h"
  13 +using namespace std;
  14 +
  15 +#include "itkRescaleIntensityImageFilter.h"
  16 +
  17 +#include "rts_itkImage.h"
  18 +
  19 +void rtsProgressBar(int percent);
  20 +
  21 +template <class T> class rts_itkVolume
  22 +{
  23 +public:
  24 + typedef int uint;
  25 + typedef itk::Image<T, 3> ITKVolumeType;
  26 + typedef typename ITKVolumeType::Pointer PointerType;
  27 + typedef itk::Image<T, 2> ITKSliceType;
  28 +
  29 + //typedef itk::Image<typename T, 3> ITKVolumeType;
  30 +private:
  31 + //pointer to the data
  32 + PointerType imageData;
  33 +
  34 + char* UnicodeToANSI(wchar_t* unicodestr)
  35 + {
  36 + int a = wcslen(unicodestr)+1;
  37 + char *ansistr = new char[a];
  38 + ::WideCharToMultiByte(CP_ACP,
  39 + 0,
  40 + unicodestr,
  41 + -1,
  42 + ansistr,
  43 + a,
  44 + NULL,
  45 + NULL);
  46 + return ansistr;
  47 +
  48 + }
  49 +
  50 + BSTR ANSIToUnicode(const char* ansistr)
  51 + {
  52 + /*On a side note: This BSTR crap isn't the way to go.
  53 + Try to use wchar_t (Unicode) where possible. Already changed it in
  54 + the above function because it was causing a bug.*/
  55 +
  56 + int a = strlen(ansistr);
  57 + BSTR unicodestr = SysAllocStringLen(NULL, a);
  58 + ::MultiByteToWideChar(CP_ACP, 0, ansistr, a, unicodestr, a);
  59 + return unicodestr;
  60 + }
  61 +
  62 +public:
  63 + //construct an implicit function with a size of 1
  64 + rts_itkVolume(); ///<Create an empty implicit function
  65 + //construct an implicit function of the specified resolution
  66 + rts_itkVolume(uint res_x, uint res_y, uint res_z); ///<Create an implicit function with the specified resolution
  67 + void Init(uint res_x, uint res_y, uint res_z);
  68 + void SetSpacing(float voxel_x, float voxel_y, float voxel_z);
  69 + void Clear();
  70 +
  71 +
  72 + //loading/saving data to disk
  73 + void LoadRAW(uint header_size, uint data_x, uint data_y, uint data_z, string filename); ///<Loads RAW data from a file with the specified header size and data size.
  74 + void SaveRAW(string filename); ///<Save the data as RAW data to disk.
  75 + void LoadVOL(string filename); ///<Load a VOL file from disk.
  76 + void SaveVOL(string filename); ///<Save a VOL file to disk.
  77 + void LoadRAV(string filename); ///<Load a VOL file from disk.
  78 + void SaveRAV(string filename); ///<Save a VOL file to disk.
  79 + void LoadStack(string directory, string filename_mask, int max_files = -1);
  80 + void LoadSlice(string filename, int slice);
  81 +
  82 + void InsertSlice(uint z_position, typename ITKSliceType::Pointer slice);
  83 +
  84 +
  85 + //data access methods
  86 + T operator ()(uint x, uint y, uint z);
  87 + PointerType GetITKPointer(){return imageData;}
  88 + T* GetBits(){return imageData->GetBufferPointer();}
  89 + T GetMin();
  90 + T GetMax();
  91 +
  92 + void SetITKPointer(PointerType pointer){imageData = pointer;}
  93 + uint DimX(){return imageData->GetLargestPossibleRegion().GetSize()[0];}
  94 + uint DimY(){return imageData->GetLargestPossibleRegion().GetSize()[1];}
  95 + uint DimZ(){return imageData->GetLargestPossibleRegion().GetSize()[2];}
  96 +
  97 + float VoxelSizeX(){return imageData->GetSpacing()[0];}
  98 + float VoxelSizeY(){return imageData->GetSpacing()[1];}
  99 + float VoxelSizeZ(){return imageData->GetSpacing()[2];}
  100 + void SetPixel(uint x, uint y, uint z, T value);
  101 + void SetSlice(rts_itkImage<T> image, int slice);
  102 + T GetPixel(uint x, uint y, uint z);
  103 + rts_itkImage<T> GetSlice(int slice);
  104 + rts_itkVolume<T> SubVolume(uint px, uint py, uint pz, uint sx, uint sy, uint sz);
  105 +
  106 + //mathematica operations
  107 + T operator=(T rhs);
  108 + rts_itkVolume<T> operator-(T rhs);
  109 + rts_itkVolume<T> operator+(T rhs);
  110 + rts_itkVolume<T> operator-(rts_itkVolume<T> rhs);
  111 +
  112 + void Print(ostream &os);
  113 +
  114 + //simple data processing
  115 + void Rescale(T new_min, T new_max);
  116 + void Binary(T threshold, T true_value); ///<Turns the image into a binary image based on a threshold value T. All values below T are set to 0, all values above are set to true_value.
  117 +
  118 + void InsertDTGrid(rtsDTGrid3D<T>* grid, bool debug = false);
  119 +};
  120 +
  121 +template <class T>
  122 +rts_itkVolume<T> rts_itkVolume<T>::SubVolume(uint px, uint py, uint pz, uint sx, uint sy, uint sz)
  123 +{
  124 + /*This function returns the sub-volume specified by a corner point and size*/
  125 +
  126 + //first make sure that the sub-volume is contained within the image
  127 + if(px < 0) {sx += px; px = 0;}
  128 + if(py < 0) {sy += py; py = 0;}
  129 + if(pz < 0) {sz += pz; pz = 0;}
  130 + if(px >= DimX()) px = DimX() - 1;
  131 + if(py >= DimY()) py = DimY() - 1;
  132 + if(pz >= DimZ()) pz = DimZ() - 1;
  133 + if(px + sx > DimX()) sx = DimX() - px - 1;
  134 + if(py + sy > DimY()) sy = DimY() - py - 1;
  135 + if(pz + sz > DimZ()) sz = DimZ() - pz - 1;
  136 +
  137 + //cout<<px<<","<<py<<","<<pz<<","<<sx<<","<<sy<<","<<sz<<endl;
  138 +
  139 + //create the resulting volume
  140 + rts_itkVolume destination(sx, sy, sz);
  141 +
  142 + //get an iterator for the destination volume
  143 + itk::ImageRegionIterator<ITKVolumeType> d(destination.imageData, destination.imageData->GetLargestPossibleRegion());
  144 +
  145 + //get an iterator for the source region
  146 + ITKVolumeType::RegionType region;
  147 + ITKVolumeType::IndexType index;
  148 + ITKVolumeType::SizeType size;
  149 + index[0] = px; index[1] = py; index[2] = pz;
  150 + size[0] = sx; size[1] = sy; size[2] = sz;
  151 + region.SetIndex(index);
  152 + region.SetSize(size);
  153 + itk::ImageRegionIterator<ITKVolumeType> s(imageData, region);
  154 +
  155 + //copy the data from source region to destination volume
  156 + for(s.GoToBegin(), d.GoToBegin();
  157 + !s.IsAtEnd();
  158 + s++, d++)
  159 + d.Set(s.Get());
  160 +
  161 + return destination;
  162 +
  163 +}
  164 +
  165 +template <class T>
  166 +T rts_itkVolume<T>::operator=(T rhs)
  167 +{
  168 + /*itk::ImageRegionIterator<ITKVolumeType> i(imageData, imageData->GetLargestPossibleRegion());
  169 +
  170 + for(i.GoToBegin(); !i.IsAtEnd(); i++)
  171 + i.Set(rhs);
  172 +*/
  173 + imageData->FillBuffer(rhs);
  174 + return rhs;
  175 +}
  176 +template <class T>
  177 +rts_itkVolume<T> rts_itkVolume<T>::operator-(T rhs)
  178 +{
  179 + rts_itkVolume<T> result(DimX(), DimY(), DimZ());
  180 +
  181 + itk::ImageRegionIterator<ITKVolumeType> w(result.imageData, result.imageData->GetLargestPossibleRegion());
  182 + itk::ImageRegionIterator<ITKVolumeType> r(imageData, imageData->GetLargestPossibleRegion());
  183 +
  184 + for(r.GoToBegin(), w.GoToBegin(); !r.IsAtEnd(); r++, w++)
  185 + w.Set(r.Get() - rhs);
  186 +
  187 + return result;
  188 +}
  189 +
  190 +template <class T>
  191 +rts_itkVolume<T> rts_itkVolume<T>::operator+(T rhs)
  192 +{
  193 + rts_itkVolume<T> result(DimX(), DimY(), DimZ());
  194 +
  195 + itk::ImageRegionIterator<ITKVolumeType> w(result.imageData, result.imageData->GetLargestPossibleRegion());
  196 + itk::ImageRegionIterator<ITKVolumeType> r(imageData, imageData->GetLargestPossibleRegion());
  197 +
  198 + for(r.GoToBegin(), w.GoToBegin(); !r.IsAtEnd(); r++, w++)
  199 + w.Set(r.Get() + rhs);
  200 +
  201 + return result;
  202 +}
  203 +
  204 +template <class T>
  205 +rts_itkVolume<T> rts_itkVolume<T>::operator-(rts_itkVolume<T> rhs)
  206 +{
  207 + rts_itkVolume<T> result(DimX(), DimY(), DimZ());
  208 +
  209 + itk::ImageRegionIterator<ITKVolumeType> w(result.imageData, result.imageData->GetLargestPossibleRegion());
  210 + itk::ImageRegionIterator<ITKVolumeType> r(rhs.imageData, rhs.imageData->GetLargestPossibleRegion());
  211 + itk::ImageRegionIterator<ITKVolumeType> l(imageData, imageData->GetLargestPossibleRegion());
  212 +
  213 + for(r.GoToBegin(), l.GoToBegin(), w.GoToBegin();
  214 + !r.IsAtEnd();
  215 + r++, l++, w++)
  216 + w.Set(l.Get() - r.Get());
  217 +
  218 + return result;
  219 +}
  220 +
  221 +template <class T>
  222 +void rts_itkVolume<T>::Print(ostream &os)
  223 +{
  224 + ITKVolumeType::SizeType size;
  225 + size = imageData->GetLargestPossibleRegion().GetSize();
  226 +
  227 + int x, y, z;
  228 + for(z=0; z<size[2]; z++)
  229 + {
  230 + os<<"z = "<<z<<":"<<endl;
  231 + for(y=0; y<size[1]; y++)
  232 + {
  233 + for(x=0; x<size[0]; x++)
  234 + os<<GetPixel(x, y, z)<<" ";
  235 + os<<endl;
  236 + }
  237 + }
  238 +}
  239 +
  240 +template <class T>
  241 +rts_itkVolume<T>::rts_itkVolume()
  242 +{
  243 + imageData = ITKVolumeType::New();
  244 +}
  245 +
  246 +template <class T>
  247 +rts_itkVolume<T>::rts_itkVolume(uint res_x, uint res_y, uint res_z)
  248 +{
  249 + imageData = ITKVolumeType::New();
  250 +
  251 + itk::Image<T, 3>::RegionType region;
  252 + itk::Image<T, 3>::SizeType size;
  253 + size[0] = res_x;
  254 + size[1] = res_y;
  255 + size[2] = res_z;
  256 +
  257 + region.SetSize(size);
  258 + imageData->SetRegions(region);
  259 +
  260 + try
  261 + {
  262 + imageData->Allocate();
  263 + }
  264 + catch(itk::ExceptionObject & exp)
  265 + {
  266 + std::cout<<exp<<std::endl;
  267 + }
  268 +
  269 +}
  270 +
  271 +template <class T>
  272 +void rts_itkVolume<T>::Init(uint res_x, uint res_y, uint res_z)
  273 +{
  274 + itk::Image<T, 3>::RegionType region;
  275 + itk::Image<T, 3>::SizeType size;
  276 + size[0] = res_x;
  277 + size[1] = res_y;
  278 + size[2] = res_z;
  279 +
  280 + region.SetSize(size);
  281 + imageData->SetRegions(region);
  282 +
  283 +
  284 + try
  285 + {
  286 + imageData->Allocate();
  287 + }
  288 + catch(itk::ExceptionObject & exp)
  289 + {
  290 + std::cout<<exp<<std::endl;
  291 + }
  292 +}
  293 +
  294 +template <class T>
  295 +void rts_itkVolume<T>::SetSpacing(float voxel_x, float voxel_y, float voxel_z)
  296 +{
  297 + float spacing[3];
  298 + spacing[0] = voxel_x; spacing[1]= voxel_y; spacing[2] = voxel_z;
  299 + imageData->SetSpacing(spacing);
  300 +}
  301 +
  302 +
  303 +template <class T>
  304 +inline T rts_itkVolume<T>::GetPixel(uint x, uint y, uint z)
  305 +{
  306 + T result;
  307 + if(x < 0 || x >= DimX() || y < 0 || y >= DimY() || z < 0 || z >= DimZ())
  308 + {
  309 + memset(&result, 0, sizeof(T));
  310 + return result;
  311 + }
  312 +
  313 + itk::Image<T, 3>::IndexType index;
  314 + index[0] = x; index[1] = y; index[2] = z;
  315 + return imageData->GetPixel(index);
  316 +}
  317 +
  318 +template <class T>
  319 +inline T rts_itkVolume<T>::GetMin()
  320 +{
  321 + int ix, iy, iz;
  322 + T currentMin = GetPixel(0, 0, 0);
  323 + T n;
  324 + for(ix=0; ix<DimX(); ix++)
  325 + for(iy=0; iy<DimY(); iy++)
  326 + for(iz=0; iz<DimZ(); iz++)
  327 + {
  328 + n = GetPixel(ix, iy, iz);
  329 + if(n < currentMin)
  330 + currentMin = n;
  331 + }
  332 + return currentMin;
  333 +}
  334 +
  335 +template <class T>
  336 +inline T rts_itkVolume<T>::GetMax()
  337 +{
  338 + int ix, iy, iz;
  339 + T currentMax = GetPixel(0, 0, 0);
  340 + T n;
  341 + for(ix=0; ix<DimX(); ix++)
  342 + for(iy=0; iy<DimY(); iy++)
  343 + for(iz=0; iz<DimZ(); iz++)
  344 + {
  345 + n = GetPixel(ix, iy, iz);
  346 + if(n > currentMax)
  347 + currentMax = n;
  348 + }
  349 + return currentMax;
  350 +}
  351 +
  352 +template <class T>
  353 +inline T rts_itkVolume<T>::operator ()(uint x, uint y, uint z)
  354 +{
  355 + return GetPixel(x, y, z);
  356 +}
  357 +
  358 +
  359 +
  360 +template <class T>
  361 +void rts_itkVolume<T>::LoadRAW(uint header_size, uint size_x,
  362 + uint size_y, uint size_z, string filename)
  363 +{
  364 + ITKVolumeType::RegionType region;
  365 + ITKVolumeType::SizeType size;
  366 + size[0] = size_x;
  367 + size[1] = size_y;
  368 + size[2] = size_z;
  369 + region.SetSize(size);
  370 + imageData->SetRegions(region);
  371 +
  372 + try
  373 + {
  374 + imageData->Allocate();
  375 + }
  376 + catch(itk::ExceptionObject & exp)
  377 + {
  378 + std::cout<<exp<<std::endl;
  379 + }
  380 +
  381 +
  382 + //cout<<imageData<<endl;
  383 +
  384 + ifstream infile(filename.c_str(), ios::out | ios::binary); //create the files stream
  385 + if(!infile)
  386 + return;
  387 + //first read the header
  388 + char* header = new char[header_size];
  389 + infile.read((char*)header, header_size);
  390 +
  391 + //now read the actual data
  392 + infile.read((char*)imageData->GetBufferPointer(), DimX()*DimY()*DimZ()*sizeof(T));
  393 +
  394 + infile.close();
  395 +}
  396 +
  397 +template <class T>
  398 +void rts_itkVolume<T>::LoadRAV(string filename)
  399 +{
  400 +
  401 + //open the file
  402 + ifstream infile(filename.c_str(), ios::out | ios::binary); //create the files stream
  403 + if(!infile)
  404 + return;
  405 +
  406 + //first read the header
  407 + int dimx, dimy, dimz, bytesize;
  408 + infile.read((char*)&dimx, sizeof(int));
  409 + infile.read((char*)&dimy, sizeof(int));
  410 + infile.read((char*)&dimz, sizeof(int));
  411 + infile.read((char*)&bytesize, sizeof(int));
  412 +
  413 + //allocate space for the image
  414 + ITKVolumeType::RegionType region;
  415 + ITKVolumeType::SizeType size;
  416 + size[0] = dimx;
  417 + size[1] = dimy;
  418 + size[2] = dimz;
  419 + region.SetSize(size);
  420 + imageData->SetRegions(region);
  421 + try
  422 + {
  423 + imageData->Allocate();
  424 + }
  425 + catch(itk::ExceptionObject & exp)
  426 + {
  427 + std::cout<<exp<<std::endl;
  428 + }
  429 +
  430 +
  431 + //now read the actual data
  432 + infile.read((char*)imageData->GetBufferPointer(), DimX()*DimY()*DimZ()*sizeof(T));
  433 +
  434 + infile.close();
  435 +}
  436 +
  437 +template <class T>
  438 +void rts_itkVolume<T>::LoadVOL(string filename)
  439 +{
  440 +
  441 + //open the file
  442 + ifstream infile(filename.c_str(), ios::out | ios::binary); //create the files stream
  443 + if(!infile)
  444 + return;
  445 +
  446 + //first read the header
  447 + int dimx, dimy, dimz, bytesize;
  448 + infile.read((char*)&dimx, sizeof(int));
  449 + infile.read((char*)&dimy, sizeof(int));
  450 + infile.read((char*)&dimz, sizeof(int));
  451 +
  452 + //allocate space for the image
  453 + ITKVolumeType::RegionType region;
  454 + ITKVolumeType::SizeType size;
  455 + size[0] = dimx;
  456 + size[1] = dimy;
  457 + size[2] = dimz;
  458 + region.SetSize(size);
  459 + imageData->SetRegions(region);
  460 + try
  461 + {
  462 + imageData->Allocate();
  463 + }
  464 + catch(itk::ExceptionObject & exp)
  465 + {
  466 + std::cout<<exp<<std::endl;
  467 + }
  468 +
  469 +
  470 + //now read the actual data
  471 + infile.read((char*)imageData->GetBufferPointer(), DimX()*DimY()*DimZ()*sizeof(T));
  472 +
  473 + infile.close();
  474 +}
  475 +
  476 +template <class T>
  477 +void rts_itkVolume<T>::LoadStack(string directory, string filename_mask, int max_files = -1)
  478 +{
  479 + /*Load a list of file names based on the user-specified mask*/
  480 + //create the complete mask
  481 + if(directory[directory.size() - 1] != '/')
  482 + directory += '/';
  483 +
  484 + string full_mask = directory;
  485 + full_mask += filename_mask;
  486 +
  487 + //create a temporary vector to store the file names
  488 + vector<rtsFilename> fileList;
  489 + //create a handle for the search
  490 + HANDLE search_handle;
  491 + WIN32_FIND_DATA found_data;
  492 +
  493 + //start the search
  494 + BSTR unicodestr = ANSIToUnicode(full_mask.c_str());
  495 + search_handle = FindFirstFile(unicodestr, &found_data);
  496 + ::SysFreeString(unicodestr);
  497 +
  498 + //if there are no files, return
  499 + if(search_handle == INVALID_HANDLE_VALUE)
  500 + return;
  501 +
  502 + string new_file;
  503 + char* ansistr = UnicodeToANSI(found_data.cFileName);
  504 + //char* ansistr = (char*)found_data.cFileName;
  505 + //save the first filename
  506 + new_file = directory;
  507 + new_file += ansistr;
  508 + fileList.push_back(new_file);
  509 + delete[] ansistr;
  510 +
  511 + //now loop through the rest of the files
  512 + while(FindNextFile(search_handle, &found_data))
  513 + {
  514 + char* ansistr = UnicodeToANSI(found_data.cFileName);
  515 + new_file = directory;
  516 + new_file += ansistr;
  517 + //cout<<new_file<<endl;
  518 + fileList.push_back(new_file);
  519 + delete[] ansistr;
  520 + }
  521 +
  522 +
  523 +
  524 + /*Load the first file in order to get volume information*/
  525 + typedef itk::ImageFileReader<ITKSliceType> ReaderType;
  526 + ReaderType::Pointer reader = ReaderType::New();
  527 + reader->SetFileName(fileList[0].getString());
  528 + ITKSliceType::Pointer image = reader->GetOutput();
  529 +
  530 + try
  531 + {
  532 + reader->Update();
  533 + }
  534 + catch(itk::ExceptionObject & exp)
  535 + {
  536 + std::cout<<exp<<std::endl;
  537 + }
  538 +
  539 + /*Insert each image into the volume*/
  540 + int i;
  541 + cout<<"Files found: "<<fileList.size()<<endl;
  542 + if(max_files == -1)
  543 + max_files = fileList.size();
  544 + else
  545 + max_files = min<int>(fileList.size(), max_files);
  546 + cout<<"Loading: "<<max_files<<endl;
  547 + //set the max number of files based on user input and number of files found
  548 +
  549 + /*Set up the volume based on information from the first file*/
  550 + ITKSliceType::SizeType size = image->GetLargestPossibleRegion().GetSize(); //get the slice size
  551 + ITKVolumeType::SizeType volSize; //compute the volume size
  552 + volSize[0] = size[0];
  553 + volSize[1] = size[1];
  554 + volSize[2] = max_files;
  555 +
  556 + imageData = ITKVolumeType::New(); //create the volume
  557 + ITKVolumeType::RegionType region;
  558 + region.SetSize(volSize);
  559 + imageData->SetRegions(region);
  560 + imageData->Allocate(); //allocate space
  561 +
  562 +
  563 +
  564 + for(i=0; i<max_files; i++)
  565 + {
  566 + reader = ReaderType::New();
  567 + reader->SetFileName(fileList[i].getString());
  568 + ITKSliceType::Pointer slice = reader->GetOutput();
  569 + reader->Update();
  570 + InsertSlice(i, slice);
  571 + //cout<<i+1<<"/"<<fileList.size()<<endl;
  572 + rtsProgressBar((float)(i+1)/(float)max_files*100);
  573 + }
  574 +}
  575 +
  576 +template <class T>
  577 +void rts_itkVolume<T>::LoadSlice(string filename, int slice)
  578 +{
  579 + //load the specified image
  580 + typedef itk::ImageFileReader<ITKSliceType> ReaderType;
  581 + ReaderType::Pointer reader = ReaderType::New();
  582 + reader->SetFileName(filename.c_str());
  583 + ITKSliceType::Pointer image = reader->GetOutput();
  584 +
  585 + try
  586 + {
  587 + reader->Update();
  588 + }
  589 + catch(itk::ExceptionObject & exp)
  590 + {
  591 + std::cout<<exp<<std::endl;
  592 + }
  593 +
  594 + //insert the slice into the volume
  595 + InsertSlice(slice, image);
  596 +
  597 +}
  598 +
  599 +template <class T>
  600 +rts_itkImage<T> rts_itkVolume<T>::GetSlice(int slice)
  601 +{
  602 + //create a new image
  603 + rts_itkImage<T> outSlice(DimX(), DimY());
  604 +
  605 + int x, y;
  606 + for(x=0; x<DimX(); x++)
  607 + for(y=0; y<DimY(); y++)
  608 + {
  609 + outSlice.SetPixel(x, y, GetPixel(x, y, slice));
  610 + }
  611 +
  612 + return outSlice;
  613 +}
  614 +
  615 +template <class T>
  616 +void rts_itkVolume<T>::SetSlice(rts_itkImage<T> image, int slice)
  617 +{
  618 + int x, y;
  619 + for(x=0; x<DimX(); x++)
  620 + for(y=0; y<DimY(); y++)
  621 + {
  622 + SetPixel(x, y, slice, image.GetPixel(x, y));
  623 + }
  624 +}
  625 +
  626 +template <class T>
  627 +void rts_itkVolume<T>::SaveRAV(string filename)
  628 +{
  629 + ofstream outfile(filename.c_str(), ios::out | ios::binary); //create the files stream
  630 + if(!outfile)
  631 + return;
  632 +
  633 + int dimx = DimX();
  634 + int dimy = DimY();
  635 + int dimz = DimZ();
  636 + int bytesize = sizeof(T);
  637 +
  638 + outfile.write((char*)&dimx, sizeof(int));
  639 + outfile.write((char*)&dimy, sizeof(int));
  640 + outfile.write((char*)&dimz, sizeof(int));
  641 + outfile.write((char*)&bytesize, sizeof(int));
  642 +
  643 + outfile.write((char*)imageData->GetBufferPointer(), DimX()*DimY()*DimZ()*sizeof(T));
  644 + outfile.close();
  645 +
  646 +}
  647 +
  648 +template <class T>
  649 +void rts_itkVolume<T>::SaveVOL(string filename)
  650 +{
  651 + ofstream outfile(filename.c_str(), ios::out | ios::binary); //create the files stream
  652 + if(!outfile)
  653 + return;
  654 +
  655 + int dimx = DimX();
  656 + int dimy = DimY();
  657 + int dimz = DimZ();
  658 +
  659 + outfile.write((char*)&dimx, sizeof(int));
  660 + outfile.write((char*)&dimy, sizeof(int));
  661 + outfile.write((char*)&dimz, sizeof(int));
  662 +
  663 + outfile.write((char*)imageData->GetBufferPointer(), DimX()*DimY()*DimZ()*sizeof(T));
  664 + outfile.close();
  665 +
  666 +}
  667 +
  668 +template <class T>
  669 +void rts_itkVolume<T>::InsertSlice(uint z_position, typename ITKSliceType::Pointer slice)
  670 +{
  671 + itk::Image<T>::SizeType size = slice->GetLargestPossibleRegion().GetSize();
  672 + itk::Image<T>::IndexType index;
  673 + int x, y;
  674 + for(x=0; x<size[0]; x++)
  675 + for(y=0; y<size[1]; y++)
  676 + {
  677 + index[0] = x; index[1] = y;
  678 + SetPixel(x, y, z_position, slice->GetPixel(index));
  679 + }
  680 +
  681 +
  682 +
  683 +}
  684 +
  685 +template <class T>
  686 +void rts_itkVolume<T>::SaveRAW(string filename)
  687 +{
  688 + ofstream outfile(filename.c_str(), ios::out | ios::binary); //create the files stream
  689 + if(!outfile)
  690 + return;
  691 +
  692 + outfile.write((char*)imageData->GetBufferPointer(), DimX()*DimY()*DimZ()*sizeof(T));
  693 + outfile.close();
  694 +}
  695 +
  696 +template <class T>
  697 +void rts_itkVolume<T>::SetPixel(uint x, uint y, uint z, T value)
  698 +{
  699 + ITKVolumeType::IndexType index;
  700 + index[0] = x;
  701 + index[1] = y;
  702 + index[2] = z;
  703 + imageData->SetPixel(index, value);
  704 +}
  705 +
  706 +template <class T>
  707 +void rts_itkVolume<T>::Rescale(T new_min, T new_max)
  708 +{
  709 + typedef itk::RescaleIntensityImageFilter<ITKVolumeType, ITKVolumeType> RescaleFilterType;
  710 + RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
  711 + rescaleFilter->SetOutputMinimum(new_min);
  712 + rescaleFilter->SetOutputMaximum(new_max);
  713 + rescaleFilter->SetInput(imageData);
  714 + rescaleFilter->Update();
  715 +
  716 + imageData = rescaleFilter->GetOutput();
  717 +}
  718 +
  719 +template <class T>
  720 +void rts_itkVolume<T>::Binary(T threshold, T true_value)
  721 +{
  722 + /**
  723 + This function converts an implicit function into a binary or characteristic function describing the solid represented by the level
  724 + set at isovalue "threshold". All values below threshold are set to zero while all values above threshold are set to the specified
  725 + "true_value". In order to use this function, the data type T must be able to be set to 0.
  726 + **/
  727 + int max_index = DimX() * DimY() * DimZ(); //find the size of the data array
  728 + int i;
  729 + T* ptrBits = imageData->GetBufferPointer();
  730 + for(i=0; i<max_index; i++)
  731 + if(ptrBits[i] >= threshold)
  732 + ptrBits[i] = true_value;
  733 + else
  734 + ptrBits[i] = 0;
  735 +}
  736 +
  737 +
  738 +template<typename T>
  739 +void rts_itkVolume<T>::InsertDTGrid(rtsDTGrid3D<T>* grid, bool debug = false)
  740 +{
  741 + //find the extents of the DT Grid
  742 + int min_x, min_y, min_z, max_x, max_y, max_z;
  743 + grid->getBounds(min_x, min_y, min_z, max_x, max_y, max_z);
  744 +
  745 + //allocate the appropriate amount of space
  746 + ITKVolumeType::RegionType region;
  747 + ITKVolumeType::SizeType size;
  748 + size[0] = (max_x - min_x) + 1;
  749 + size[1] = (max_y - min_y) + 1;
  750 + size[2] = (max_z - min_z) + 1;
  751 + region.SetSize(size);
  752 + imageData->SetRegions(region);
  753 +
  754 + try
  755 + {
  756 + imageData->Allocate();
  757 + }
  758 + catch(itk::ExceptionObject & exp)
  759 + {
  760 + std::cout<<exp<<std::endl;
  761 + }
  762 +
  763 + //fill the image with the background color
  764 + imageData->FillBuffer(grid->background);
  765 +
  766 + //copy values from the DT Grid to the image
  767 + ITKVolumeType::IndexType index; //create an image index
  768 + rtsDTGrid3D<T>::iterator i; //create an iterator
  769 +
  770 + for(i = grid->begin(); i!= grid->after(); i++)
  771 + {
  772 + index[0] = i.X1() - min_x;
  773 + index[1] = i.X2() - min_y;
  774 + index[2] = i.X3() - min_z;
  775 + imageData->SetPixel(index, i.Value());
  776 +
  777 + //cout<<index[0]<<","<<index[1]<<": "<<i.Value()<<endl;
  778 +
  779 + }
  780 +}
  781 +#endif
0 782 \ No newline at end of file
... ...
rts_old_Camera.cpp 0 → 100755
  1 +++ a/rts_old_Camera.cpp
  1 +#include "rtsCameraController.h"
  2 +#include <math.h>
  3 +rtsCamera::rtsCamera()
  4 +{
  5 + position = point3D<float>(0, 0, 0);
  6 + view_vector = vector3D<float>(0, 0, -1);
  7 + up_vector = vector3D<float>(0, 1, 0);
  8 + lookat_point = point3D<float>(0, 0, -1);
  9 +
  10 + pers_view_angle = 60;
  11 + ortho_width = 1.0;
  12 + ortho_height = 1.0;
  13 +
  14 + near_plane = 1;
  15 + far_plane = 100;
  16 +}
  17 +
  18 +rtsCamera::LookAt(
  19 +
  20 +/*
  21 +rtsCamera::rtsCamera(rtsCameraState initial_state)
  22 +{
  23 + m_camera_state = initial_state;
  24 +
  25 + //make sure that the view and lookat vectors are orthogonal
  26 + vector3D<float> lookat = m_camera_state.lookat - m_camera_state.position;
  27 + vector3D<float> up = m_camera_state.up;
  28 + vector3D<float> side = lookat.X(up);
  29 + up = side.X(lookat);
  30 + up.Normalize();
  31 + m_camera_state.up = up;
  32 +}
  33 +
  34 +rtsCameraState rtsCamera::getState()
  35 +{
  36 + return m_camera_state;
  37 +}
  38 +
  39 +
  40 +
  41 +
  42 +void rtsCamera::setState(rtsCameraState camera_state)
  43 +{
  44 + m_camera_state = camera_state;
  45 +
  46 + //re-orthogonalize the vectors
  47 + vector3D<float> view = m_camera_state.lookat - m_camera_state.position;
  48 + vector3D<float> side = view.X(m_camera_state.up);
  49 + m_camera_state.up = side.X(view);
  50 + m_camera_state.up.Normalize();
  51 +}
  52 +
  53 +void rtsCamera::LookAt(point3D<float> point)
  54 +{
  55 + //looks at a point
  56 +
  57 + //find the new view vector
  58 + vector3D<float> view = point - m_camera_state.position;
  59 +
  60 + //normalize the view vector
  61 + view.Normalize();
  62 +
  63 + //prepare a new side vector and up vector
  64 + vector3D<float> side;
  65 + vector3D<float> up;
  66 +
  67 + //get the up vector
  68 + //if the new viewvector is at 0 or 180 degrees to the up vector
  69 + float cos_angle = view*m_camera_state.up;
  70 + if(cos_angle == 1.0f || cos_angle == -1.0f)
  71 + {
  72 + //re-calculate the up vector
  73 + up = m_camera_state.up.X(m_camera_state.lookat - m_camera_state.position);
  74 + }
  75 + else
  76 + {
  77 + //otherwise, just get the current up vector
  78 + up = m_camera_state.up;
  79 + }
  80 +
  81 +
  82 + //correct the up vector based on the new view vector
  83 + side = up.X(view);
  84 + up = view.X(side);
  85 + up.Normalize();
  86 +
  87 + //change the camera state
  88 + m_camera_state.up = up;
  89 + m_camera_state.lookat = point;
  90 +}
  91 +
  92 +void rtsCamera::Position(point3D<float> p)
  93 +{
  94 + m_camera_state.position = p;
  95 +}
  96 +
  97 +void rtsCamera::Up(vector3D<float> up)
  98 +{
  99 + m_camera_state.up = up;
  100 +}
  101 +
  102 +void rtsCamera::DollyPosition(point3D<float> p)
  103 +{
  104 + vector3D<float> adjustment = p-m_camera_state.position;
  105 + m_camera_state.position = p;
  106 + m_camera_state.lookat = m_camera_state.lookat + adjustment;
  107 +}
  108 +
  109 +point3D<float> rtsCamera::getLookAtPoint()
  110 +{
  111 + return m_camera_state.lookat;
  112 +}
  113 +
  114 +
  115 +
  116 +void rtsCamera::Pan(double x, double y)
  117 +{
  118 + //first calculate the lookat and side vectors
  119 + vector3D<float> lookatvector=m_camera_state.lookat - m_camera_state.position;
  120 + vector3D<float> sidevector = lookatvector.X(m_camera_state.up);
  121 + sidevector.Normalize();
  122 +
  123 + m_camera_state.position=m_camera_state.position+sidevector*x;
  124 + m_camera_state.lookat=m_camera_state.lookat+sidevector*x;
  125 +
  126 + vector3D<float> upvector = lookatvector.X(sidevector);
  127 + upvector.Normalize();
  128 + m_camera_state.position=m_camera_state.position+upvector*y;
  129 + m_camera_state.lookat=m_camera_state.lookat+upvector*y;
  130 +}
  131 +
  132 +void rtsCamera::RotateUpDown(double degrees)
  133 +{
  134 + //first calculate the lookat and side vectors
  135 + vector3D<float> lookatvector=m_camera_state.lookat-m_camera_state.position;
  136 + vector3D<float> sidevector = lookatvector.X(m_camera_state.up);
  137 + m_camera_state.up=sidevector.X(lookatvector);
  138 + m_camera_state.up.Normalize();
  139 + sidevector.Normalize();
  140 +
  141 + //translate the look-at point to the origin (and the camera with it)
  142 + point3D<float> origin = point3D<float>(0.0, 0.0, 0.0);
  143 + vector3D<float> translateCamera = origin-m_camera_state.lookat;
  144 +
  145 + point3D<float> translatedCamera=m_camera_state.position+translateCamera;
  146 +
  147 + //the next step is to rotate the side vector so that it lines up with the z axis
  148 + double a=sidevector.x;
  149 + double b=sidevector.y;
  150 + double c=sidevector.z;
  151 +
  152 + double d=sqrt(b*b + c*c);
  153 +
  154 + //error correction for when we are already looking down the z-axis
  155 + if(d==0)
  156 + return;
  157 +
  158 + vector3D<float> XZplane = vector3D<float>(translatedCamera.x,
  159 + (translatedCamera.y*c/d - translatedCamera.z*b/d),
  160 + (translatedCamera.y*b/d + translatedCamera.z*c/d));
  161 +
  162 + vector3D<float> Zaxis = vector3D<float>(XZplane.x*d - XZplane.z*a,
  163 + XZplane.y,
  164 + XZplane.x*a + XZplane.z*d);
  165 +
  166 + vector3D<float> rotated = vector3D<float>(Zaxis.x*cos(TORADIANS(degrees)) - Zaxis.y*sin(TORADIANS(degrees)),
  167 + Zaxis.x*sin(TORADIANS(degrees)) + Zaxis.y*cos(TORADIANS(degrees)),
  168 + Zaxis.z);
  169 +
  170 + vector3D<float> XZout = vector3D<float>( rotated.x*(d/(a*a + d*d)) + rotated.z*(a/(a*a + d*d)),
  171 + rotated.y,
  172 + rotated.x*(-a/(a*a+d*d)) + rotated.z*(d/(a*a + d*d)));
  173 +
  174 + vector3D<float> result = vector3D<float>( XZout.x,
  175 + XZout.y*(c*d/(b*b + c*c)) + XZout.z*(b*d/(b*b + c*c)),
  176 + XZout.y*(-b*d/(b*b + c*c)) + XZout.z*(c*d/(b*b + c*c)));
  177 +
  178 + result=result-translateCamera;
  179 +
  180 + m_camera_state.position.x=result.x;
  181 + m_camera_state.position.y=result.y;
  182 + m_camera_state.position.z=result.z;
  183 +
  184 +}
  185 +
  186 +void rtsCamera::Yaw(double degrees)
  187 +{
  188 + //basically, we have to rotate the look-at point around the up vector
  189 + //first, translate the look-at point so that the camera is at the origin
  190 + point3D<float> origin(0.0, 0.0, 0.0);
  191 + point3D<float> temp_lookat = m_camera_state.lookat - (m_camera_state.position - origin);
  192 +
  193 + //create a rotation matrix to rotate the lookat point around the up vector
  194 + float x=m_camera_state.up.x;
  195 + float y=m_camera_state.up.y;
  196 + float z=m_camera_state.up.z;
  197 + float c=cos(TORADIANS(-degrees));
  198 + float s=sin(TORADIANS(-degrees));
  199 + float t=1.0 - cos(TORADIANS(-degrees));
  200 + float m00 = t*x*x + c;
  201 + float m01 = t*x*y + s*z;
  202 + float m02 = t*x*z - s*y;
  203 + float m03 = 0;
  204 + float m10 = t*x*y - s*z;
  205 + float m11 = t*y*y + c;
  206 + float m12 = t*y*z + s*x;
  207 + float m13 = 0;
  208 + float m20 = t*x*z + s*y;
  209 + float m21 = t*y*z - s*x;
  210 + float m22 = t*z*z + c;
  211 + float m23 = 0;
  212 + float m30 = 0;
  213 + float m31 = 0;
  214 + float m32 = 0;
  215 + float m33 = 1;
  216 + matrix4x4<float> rotation(m00, m01, m02, m03,
  217 + m10, m11, m12, m13,
  218 + m20, m21, m22, m23,
  219 + m30, m31, m32, m33);
  220 + point3D<float> result = rotation*temp_lookat + (m_camera_state.position - origin);
  221 + m_camera_state.lookat = result;
  222 +}
  223 +
  224 +void rtsCamera::Pitch(double degrees)
  225 +{
  226 + //basically, we have to rotate the look-at point and up vector around the side vector
  227 + //first, translate the look-at point so that the camera is at the origin
  228 + point3D<float> origin(0.0, 0.0, 0.0);
  229 +
  230 + //find all three necessary vectors
  231 + vector3D<float> temp_lookat = m_camera_state.lookat - m_camera_state.position;
  232 + double lookat_length = temp_lookat.Length();
  233 + vector3D<float> temp_up = m_camera_state.up;
  234 + vector3D<float> temp_side = temp_lookat.X(temp_up);
  235 + temp_lookat.Normalize();
  236 + temp_up.Normalize();
  237 + temp_side.Normalize();
  238 +
  239 +
  240 + //create a rotation matrix to rotate around the side vector
  241 + float x=temp_side.x;
  242 + float y=temp_side.y;
  243 + float z=temp_side.z;
  244 + float c=cos(TORADIANS(degrees));
  245 + float s=sin(TORADIANS(degrees));
  246 + float t=1.0 - cos(TORADIANS(degrees));
  247 + float m00 = t*x*x + c;
  248 + float m01 = t*x*y + s*z;
  249 + float m02 = t*x*z - s*y;
  250 + float m03 = 0;
  251 + float m10 = t*x*y - s*z;
  252 + float m11 = t*y*y + c;
  253 + float m12 = t*y*z + s*x;
  254 + float m13 = 0;
  255 + float m20 = t*x*z + s*y;
  256 + float m21 = t*y*z - s*x;
  257 + float m22 = t*z*z + c;
  258 + float m23 = 0;
  259 + float m30 = 0;
  260 + float m31 = 0;
  261 + float m32 = 0;
  262 + float m33 = 1;
  263 + matrix4x4<float> rotation(m00, m01, m02, m03,
  264 + m10, m11, m12, m13,
  265 + m20, m21, m22, m23,
  266 + m30, m31, m32, m33);
  267 +
  268 + //rotate the up and look-at vectors around the side vector
  269 + vector3D<float> result_lookat = rotation*temp_lookat;
  270 + vector3D<float> result_up = rotation*temp_up;
  271 + result_lookat.Normalize();
  272 + result_up.Normalize();
  273 +
  274 + m_camera_state.lookat = m_camera_state.position + result_lookat * lookat_length;
  275 + m_camera_state.up = result_up;
  276 +}
  277 +
  278 +
  279 +void rtsCamera::RotateLeftRight(double degrees)
  280 +//this function rotates the camera around the up vector (which always points along hte positive
  281 +//Y world axis).
  282 +{
  283 + //translate the look-at point to the origin (and the camera with it)
  284 + point3D<float> origin = point3D<float>(0.0, 0.0, 0.0);
  285 + vector3D<float> translateCamera = origin-m_camera_state.lookat;
  286 +
  287 + point3D<float> translatedCamera=m_camera_state.position+translateCamera;
  288 +
  289 +
  290 + //perform the rotation around the look-at point
  291 + //using the y-axis as the rotation axis
  292 + point3D<float> newcamera;
  293 + newcamera.x=translatedCamera.x*cos(TORADIANS(degrees)) - translatedCamera.z*sin(TORADIANS(degrees));
  294 + newcamera.z=translatedCamera.x*sin(TORADIANS(degrees)) + translatedCamera.z*cos(TORADIANS(degrees));
  295 + newcamera.y=translatedCamera.y;
  296 +
  297 + vector3D<float> newup;
  298 + newup.x=m_camera_state.up.x*cos(TORADIANS(degrees)) - m_camera_state.up.z*sin(TORADIANS(degrees));
  299 + newup.z=m_camera_state.up.x*sin(TORADIANS(degrees)) + m_camera_state.up.z*cos(TORADIANS(degrees));
  300 + newup.y=m_camera_state.up.y;
  301 +
  302 + //translate the lookat point back to it's original position (along with the camera)
  303 + newcamera=newcamera-translateCamera;
  304 +
  305 + m_camera_state.position.x=newcamera.x;
  306 + m_camera_state.position.y=newcamera.y;
  307 + m_camera_state.position.z=newcamera.z;
  308 +
  309 + m_camera_state.up.x=newup.x;
  310 + m_camera_state.up.y=newup.y;
  311 + m_camera_state.up.z=newup.z;
  312 + m_camera_state.up.Normalize();
  313 +
  314 +}
  315 +
  316 +void rtsCamera::Forward(double distance)
  317 +{
  318 + //calculate the lookat vector (direction of travel)
  319 + vector3D<float> old_lookat=m_camera_state.lookat-m_camera_state.position;
  320 + old_lookat.Normalize();
  321 +
  322 + //calculate the new position of the camera
  323 + point3D<float> new_position = m_camera_state.position+old_lookat*distance;
  324 + //now calculate the new lookat vector
  325 + vector3D<float> new_lookat=m_camera_state.lookat-new_position;
  326 + //find the length of the new lookat vector
  327 +
  328 + //move the camera to the new position
  329 + m_camera_state.position = new_position;
  330 +}
  331 +
  332 +void rtsCamera::ScaleForward(double factor, double min, double max)
  333 +{
  334 + //This function moves the camera forward, scaling the magnitude
  335 + //of the motion by the length of the view vector. Basically, the closer
  336 + //the camera is to the lookat point, the slower the camera moves.
  337 +
  338 + //calculate the lookat vector (direction of travel)
  339 + vector3D<float> lookatvector=m_camera_state.lookat-m_camera_state.position;
  340 + //find the length of the view vector
  341 + double length = lookatvector.Length();
  342 + //normalize
  343 + lookatvector.Normalize();
  344 +
  345 + //prevent motion if the bounds would be passed
  346 + double new_distance = length - (factor*length);
  347 + if(new_distance < min || new_distance > max)
  348 + factor = 0;
  349 + //move the camera
  350 + m_camera_state.position=m_camera_state.position+lookatvector*factor*length;
  351 + lookatvector=m_camera_state.lookat-m_camera_state.position;
  352 +
  353 +}
  354 +
  355 +void rtsCamera::DollyLeftRight(double distance)
  356 +{
  357 + //calculate the side vector vector (direction of travel)
  358 + vector3D<float> lookatvector=m_camera_state.lookat-m_camera_state.position;
  359 + vector3D<float> side = lookatvector.X(m_camera_state.up);
  360 + side.Normalize();
  361 +
  362 + m_camera_state.position=m_camera_state.position+side*distance;
  363 + m_camera_state.lookat = m_camera_state.lookat + side*distance;
  364 + //lookatvector=m_camera_state.lookat-m_camera_state.position;
  365 +}
  366 +
  367 +void rtsCamera::DollyUpDown(double distance)
  368 +{
  369 + //move along the up vector
  370 + m_camera_state.up.Normalize();
  371 +
  372 + m_camera_state.position=m_camera_state.position+m_camera_state.up*distance;
  373 + m_camera_state.lookat = m_camera_state.lookat + m_camera_state.up*distance;
  374 + //lookatvector=m_camera_state.lookat-m_camera_state.position;
  375 +}
  376 +
  377 +void rtsCamera::Zoom(double angle)
  378 +{
  379 + m_camera_state.pers_view_angle += angle;
  380 +}
  381 +
  382 +*/
0 383 \ No newline at end of file
... ...
rts_old_Camera.h 0 → 100755
  1 +++ a/rts_old_Camera.h
  1 +#include "rtsLinearAlgebra.h"
  2 +
  3 +#ifndef _RTSMATH_H
  4 +#define _RTSMATH_H
  5 +
  6 +#define CAMERA_UP -1
  7 +#define CAMERA_DOWN 1
  8 +#define CAMERA_LEFT -1
  9 +#define CAMERA_RIGHT 1
  10 +
  11 +struct rtsCameraState
  12 +{
  13 + point3D<float> position;
  14 + point3D<float> lookat;
  15 + vector3D<float> up;
  16 + float pers_view_angle;
  17 + float ortho_width;
  18 + float ortho_height;
  19 + float near_plane;
  20 + float far_plane;
  21 +};
  22 +
  23 +class rtsCamera
  24 +{
  25 + //members
  26 + point3D<float> position;
  27 + vector3D<float> view_vector;
  28 + vector3D<float> up_vector;
  29 + point3D<float> lookat_point;
  30 + float pers_view_angle;
  31 + float ortho_width;
  32 + float ortho_height;
  33 + float near_plane;
  34 + float far_plane;
  35 +
  36 +public:
  37 +
  38 +
  39 + //constructors
  40 + rtsCamera();
  41 + ~rtsCamera(){};
  42 +
  43 + //methods
  44 + void LookAt(point3D<float> pos, point3D<float> lookat, vector3D<float> up);
  45 + /*
  46 + void RotateUpDown(double degrees);
  47 + void RotateLeftRight(double degrees);
  48 + void Pan(double x, double y);
  49 + void Yaw(double degrees);
  50 + void Pitch(double degrees);
  51 + void Forward(double distance);
  52 + void ScaleForward(double factor, double min = 0, double max = 999999);
  53 + void DollyLeftRight(double distance);
  54 + void DollyUpDown(double distance);
  55 + void Zoom(double angle);
  56 + void LookAt(point3D<float> point);
  57 + void Position(point3D<float> point);
  58 + void Up(vector3D<float> up);
  59 + void DollyPosition(point3D<float> point); //moves the camera but keeps the current orientation
  60 + */
  61 +
  62 + //get methods
  63 + rtsCameraState getState();
  64 + vector3D<float> getView(){return view_vector;}
  65 + vector3D<float> getUp(){return up_vector;}
  66 + point3D<float> getPosition(){return position;}
  67 + point3D<float> getLookAt(){return lookat_point;}
  68 + double getViewAngle(){return pers_view_angle;}
  69 + double getNearPlane(){return near_plane;}
  70 + double getFarPlane(){return far_plane;}
  71 + double getOrthoWidth(){return ortho_width;}
  72 + double getOrthoHeight(){return ortho_height;}
  73 +
  74 +
  75 +};
  76 +
  77 +#endif
0 78 \ No newline at end of file
... ...
rts_vtkFunctions.h 0 → 100755
  1 +++ a/rts_vtkFunctions.h
  1 +#include "vtkImageData.h"
  2 +#include "rtsVolume.h"
  3 +#include "rtsImplicit3D.h"
  4 +
  5 +/*vtkImageData* rtsVolume2vtkImageData(rtsVolume* inputVolume, int data_type)
  6 +{
  7 + vtkImageData* outputImageData = vtkImageData::New();
  8 + outputImageData->SetScalarType(data_type);
  9 + outputImageData->SetDimensions(inputVolume->get_dimx(), inputVolume->get_dimy(), inputVolume->get_dimz());
  10 + unsigned char* scalar_pointer = (unsigned char*)outputImageData->GetScalarPointer();
  11 + unsigned char* volume_pointer = inputVolume->get_bits();
  12 + unsigned int vol_size = inputVolume->get_dimx()*inputVolume->get_dimy()*inputVolume->get_dimz();
  13 + for(int i=0; i<vol_size; i++)
  14 + {
  15 + scalar_pointer[i] = volume_pointer[i];
  16 + }
  17 +
  18 + return outputImageData;
  19 +}*/
  20 +
  21 +template <class T>
  22 +vtkImageData* rtsImplicit3D2vtkImageData(rtsImplicit3D<T>* in_function, int data_type)
  23 +{
  24 + //create the vtkImageData class for storing a uniform grid
  25 + vtkImageData* outputImageData = vtkImageData::New();
  26 + //set the data type of the scalar field
  27 + outputImageData->SetScalarType(data_type);
  28 + //set the dimensions of the image data based on the function resolution
  29 + outputImageData->SetDimensions(in_function->DimX(), in_function->DimY(), in_function->DimZ());
  30 + //get a pointer to the scalar field data and the function data
  31 + unsigned char* scalar_pointer = (unsigned char*)outputImageData->GetScalarPointer();
  32 + unsigned char* volume_pointer = (unsigned char*)in_function->GetBits();
  33 + unsigned int vol_size;
  34 + switch(data_type)
  35 + {
  36 + case VTK_UNSIGNED_CHAR:
  37 + vol_size = sizeof(char)*in_function->DimX()*in_function->DimY()*in_function->DimZ();
  38 + break;
  39 + case VTK_DOUBLE:
  40 + vol_size = sizeof(double)*in_function->DimX()*in_function->DimY()*in_function->DimZ();
  41 + break;
  42 + default:
  43 + exit(1);
  44 + }
  45 +
  46 + memcpy(scalar_pointer, volume_pointer, vol_size);
  47 +
  48 + //for(int i=0; i<vol_size; i++)
  49 + //{
  50 + // scalar_pointer[i] = volume_pointer[i];
  51 + //}
  52 +
  53 +
  54 + return outputImageData;
  55 +}
0 56 \ No newline at end of file
... ...
rts_winFileDialog.cpp 0 → 100755
  1 +++ a/rts_winFileDialog.cpp
  1 +/*Make sure to not use Unicode characters. Using the Unicode character set does some
  2 +strange stuff unless you change the character pointers to LPWSTR and LPWCHAR
  3 +*/
  4 +
  5 +#include <iostream>
  6 +using namespace std;
  7 +
  8 +
  9 +#pragma comment( lib, "comctl32" )
  10 +
  11 +#include <windows.h>
  12 +#include <commctrl.h>
  13 +#include <commdlg.h>
  14 +#include <rts_winFileDialog.h>
  15 +
  16 +bool rtsOpenFileDialog( char *filename, int filenameSize, const char *filetypes="All Files (*.*)\0*.*;")
  17 +{
  18 + OPENFILENAME *ofn = (OPENFILENAME*)GlobalAlloc(GMEM_FIXED,sizeof(OPENFILENAME));
  19 + ZeroMemory(ofn, sizeof(OPENFILENAME));
  20 + ofn->lStructSize = sizeof(OPENFILENAME);
  21 + ofn->hwndOwner = NULL;
  22 + ofn->lpstrFile = filename;
  23 + cout<<ofn->lpstrFile<<endl;
  24 + ofn->nMaxFile = filenameSize;
  25 + ofn->lpstrFilter = filetypes ? filetypes : "All Files (*.*)\0*.*;";
  26 + ofn->nFilterIndex = 0;
  27 + ofn->lpstrFileTitle = NULL;
  28 + ofn->nMaxFileTitle = 0;
  29 + ofn->lpstrInitialDir = NULL;
  30 + ofn->Flags = OFN_ENABLESIZING | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
  31 +|OFN_EXPLORER | OFN_HIDEREADONLY;
  32 +
  33 + //allow multiple files to be loaded if the user says so
  34 + //if(multi) ofn->Flags = ofn->Flags | OFN_ALLOWMULTISELECT;
  35 +
  36 + BOOL success = GetOpenFileNameA(ofn);
  37 + //DWORD myfoo = CommDlgExtendedError();
  38 + GlobalFree(ofn);
  39 + return success;
  40 +}
  41 +
  42 +bool rtsSaveFileDialog( char *filename, int filenameSize, const char *filetypes="All Files (*.*)\0*.*;" )
  43 +{
  44 + OPENFILENAME *ofn = (OPENFILENAME*)GlobalAlloc(GMEM_FIXED,sizeof(OPENFILENAME));
  45 + ZeroMemory(ofn, sizeof(OPENFILENAME));
  46 + ofn->lStructSize = sizeof(OPENFILENAME);
  47 + ofn->hwndOwner = NULL;
  48 + ofn->lpstrFile = filename;
  49 + ofn->nMaxFile = filenameSize;
  50 + ofn->lpstrFilter = filetypes ? filetypes : "All Files (*.*)\0*.*;";
  51 + ofn->nFilterIndex = 0;
  52 + ofn->lpstrFileTitle = NULL;
  53 + ofn->nMaxFileTitle = 0;
  54 + ofn->lpstrInitialDir = NULL;
  55 + ofn->Flags = OFN_ENABLESIZING | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
  56 +|OFN_EXPLORER | OFN_HIDEREADONLY;
  57 + BOOL success = GetSaveFileNameA(ofn);
  58 + //DWORD myfoo = CommDlgExtendedError();
  59 + GlobalFree(ofn);
  60 + return success;
  61 +}
  62 +
  63 +bool rts_winBrowseFolderDialog(char* title, char* foldername)
  64 +{
  65 + BROWSEINFO* bi = (BROWSEINFO*)GlobalAlloc(GMEM_FIXED,sizeof(BROWSEINFO));
  66 + ZeroMemory(bi, sizeof(BROWSEINFO));
  67 + char directory[MAX_PATH] = "";
  68 +
  69 + bi->pszDisplayName = directory;
  70 + bi->lpszTitle = title;
  71 + bi->pidlRoot = NULL;
  72 + bi->lpfn = NULL;
  73 + bi->ulFlags = 0;
  74 + PIDLIST_ABSOLUTE pID = SHBrowseForFolder(bi);
  75 +
  76 + SHGetPathFromIDList(pID, foldername);
  77 +
  78 + return true;
  79 +
  80 +}
0 81 \ No newline at end of file
... ...
rts_winFileDialog.h 0 → 100755
  1 +++ a/rts_winFileDialog.h
  1 +/*
  2 +1) Make sure to not use Unicode characters. Using the Unicode character set does some
  3 +strange stuff involving LPWSTR and LPWCHAR.
  4 +2) Make sure an empty string is passed:
  5 + char filename[255] = "";
  6 + rtsOpenFileDialog(filename, 255);
  7 +*/
  8 +
  9 +#pragma comment( lib, "comctl32" )
  10 +
  11 +#include <windows.h>
  12 +#include <commctrl.h>
  13 +#include <commdlg.h>
  14 +#include <Shlobj.h>
  15 +
  16 +bool rtsOpenFileDialog( char *filename, int filenameSize, const char *filetypes);
  17 +bool rtsSaveFileDialog( char *filename, int filenameSize, const char *filetypes);
  18 +bool rts_winBrowseFolderDialog( char* title, char* foldername);
... ...
rts_winFiles.h 0 → 100755
  1 +++ a/rts_winFiles.h
  1 +#include "rtsFilename.h"
  2 +
  3 +#include <windows.h>
  4 +#include <vector>
  5 +
  6 +
  7 +vector<rtsFilename> rts_winGetFileList(const char* mask)
  8 +{
  9 + /*This function returns a list of file names based on the mask passed by
  10 + the user. The value returned is the number of rtsFilename elements in the
  11 + file_list parameter.*/
  12 +
  13 + //create a temporary vector to store the file names
  14 + vector<rtsFilename> result;
  15 + //create a handle for the search
  16 + HANDLE search_handle;
  17 + WIN32_FIND_DATA found_data;
  18 +
  19 + //start the search
  20 + search_handle = FindFirstFile((LPCSTR)mask, &found_data);
  21 +
  22 + //loop through the rest of the data
  23 + rtsFilename new_file;
  24 + if(search_handle != INVALID_HANDLE_VALUE)
  25 + {
  26 + //save the first filename
  27 + new_file = found_data.cFileName;
  28 + result.push_back(new_file);
  29 +
  30 + //now loop through the rest of the files
  31 + while(FindNextFile(search_handle, &found_data))
  32 + {
  33 + new_file = found_data.cFileName;
  34 + result.push_back(new_file);
  35 + }
  36 + }
  37 +
  38 + return result;
  39 +}
  40 +
  41 +
... ...
rtsf_LoadTexture.h 0 → 100755
  1 +++ a/rtsf_LoadTexture.h
  1 +#include "cimg/cimg.h"
  2 +#include "rtsFunction3D.h"
  3 +#include "rtspoint3D.h"
  4 +
  5 +using namespace cimg_library;
  6 +
  7 +typedef point3D<unsigned char> RGB;
  8 +
  9 +rtsFunction3D<RGB> rtsf_LoadTexture(const char* filename)
  10 +{
  11 +
  12 + CImg<unsigned char> image(filename);
  13 +
  14 + unsigned int max_x = image.dimx();
  15 + unsigned int max_y = image.dimy();
  16 + unsigned int max_z = image.dimz();
  17 +
  18 + rtsFunction3D<RGB> bits(max_x, max_y, max_z);
  19 +
  20 + unsigned int x, y, z;
  21 + for(x = 0; x<max_x; x++)
  22 + for(y = 0; y<max_y; y++)
  23 + for(z = 0; z<max_z; z++)
  24 + {
  25 + bits.xyz(x, max_y - y, z).x = image(x, y, z, 0);
  26 + bits.xyz(x, max_y - y, z).y = image(x, y, z, 1);
  27 + bits.xyz(x, max_y - y, z).z = image(x, y, z, 2);
  28 + }
  29 +
  30 +
  31 + return bits;
  32 +
  33 +}
  34 +
  35 +rtsFunction3D<unsigned char> rtsf_LoadGrayTexture(const char* filename)
  36 +{
  37 +
  38 + CImg<unsigned char> image(filename);
  39 +
  40 + //CImgDisplay main_disp(image);
  41 + //while(true);
  42 +
  43 + unsigned int dim_x = image.dimx();
  44 + unsigned int dim_y = image.dimy();
  45 + unsigned int dim_z = image.dimz();
  46 +
  47 + rtsFunction3D<unsigned char> bits(dim_x, dim_y, dim_z);
  48 +
  49 +
  50 + float r, g, b;
  51 + float greyscale;
  52 + float max_length = sqrt(3.0f);
  53 +
  54 + unsigned int x, y, z;
  55 + for(x = 0; x<dim_x; x++)
  56 + for(y = 0; y<dim_y; y++)
  57 + for(z = 0; z<dim_z; z++)
  58 + {
  59 + if(image.dimv() == 3)
  60 + {
  61 + r = image(x, y, z, 0)/255.0f;
  62 + g = image(x, y, z, 1)/255.0f;
  63 + b = image(x, y, z, 2)/255.0f;
  64 + greyscale = 0.3*r + 0.59*g + 0.11*b;
  65 + }
  66 + else
  67 + greyscale = image(x, y, z, 0)/255.0f;
  68 +
  69 +
  70 +
  71 + bits.xyz(x, dim_y - y - 1, z) = greyscale * 255;
  72 + }
  73 +
  74 +
  75 + return bits;
  76 +
  77 +}
0 78 \ No newline at end of file
... ...
temp_rtsBoundingVolumes.h 0 → 100755
  1 +++ a/temp_rtsBoundingVolumes.h
  1 +#ifndef RTS_BOUNDING_VOLUMES
  2 +#define RTS_BOUNDING_VOLUMES
  3 +
  4 +#include "rtsLinearAlgebra.h"
  5 +#include <math.h>
  6 +
  7 +template <class T>
  8 +class rtsAABB
  9 +{
  10 +public:
  11 + point3D<T> minimum;
  12 + point3D<T> maximum;
  13 +
  14 + //overloaded operators
  15 + rtsAABB<T> operator+(rtsAABB<T> param);
  16 + rtsAABB<unsigned int> getGridAlignedAABB();
  17 + inline bool isIn(T x, T y, T z);
  18 +};
  19 +
  20 +template <class T>
  21 +class rtsBoundingSphere
  22 +{
  23 +public:
  24 + point3D<T> center;
  25 + T radius;
  26 +
  27 + inline bool isIn(T x, T y, T z);
  28 +};
  29 +
  30 +template <class T>
  31 +class rtsTGC
  32 +{
  33 +public:
  34 + point3D<T> posA;
  35 + point3D<T> posB;
  36 + vector3D<T> normA;
  37 + vector3D<T> normB;
  38 + T radA;
  39 + T radB;
  40 +
  41 + rtsAABB<T> BoundAABB();
  42 +};
  43 +
  44 +template <class T>
  45 +rtsAABB<T> rtsAABB<T>::operator+(rtsAABB<T> param)
  46 +{
  47 +/* This function creates an AABB by finding the minimum bound
  48 + of two other AABBs.
  49 +*/
  50 +
  51 + rtsAABB<T> result;
  52 +
  53 + result.minimum.x = min(minimum.x, param.minimum.x);
  54 + result.minimum.y = min(minimum.y, param.minimum.y);
  55 + result.minimum.z = min(minimum.z, param.minimum.z);
  56 +
  57 + result.maximum.x = max(maximum.x, param.maximum.x);
  58 + result.maximum.y = max(maximum.y, param.maximum.y);
  59 + result.maximum.z = max(maximum.z, param.maximum.z);
  60 + return result;
  61 +}
  62 +
  63 +template <class T>
  64 +inline bool rtsAABB<T>::isIn(T x, T y, T z)
  65 +{
  66 + if(x >= minimum.x && x <= maximum.x &&
  67 + y >= minimum.y && y <= maximum.y &&
  68 + z >= minimum.z && z <= maximum.z)
  69 + return true;
  70 + else
  71 + return false;
  72 +}
  73 +
  74 +template <class T>
  75 +inline bool rtsBoundingSphere<T>::isIn(T x, T y, T z)
  76 +{
  77 + vector3D<T> to_point = center - point3D<T>(x, y, z);
  78 + T length_squared = to_point*to_point;
  79 + if(length_squared < radius*radius)
  80 + return true;
  81 + else
  82 + return false;
  83 +}
  84 +
  85 +template <class T>
  86 +rtsAABB<unsigned int> rtsAABB<T>::getGridAlignedAABB()
  87 +{
  88 +/* This function returns a version of the current AABB that is snapped
  89 + to a grid (ie the floor of the position and the ceiling of the size).
  90 +*/
  91 + rtsAABB<unsigned int> result;
  92 + result.minimum.x = floor(minimum.x);
  93 + result.minimum.y = floor(minimum.y);
  94 + result.minimum.z = floor(minimum.z);
  95 + result.maximum.x = ceil(maximum.x);
  96 + result.maximum.y = ceil(maximum.y);
  97 + result.maximum.z = ceil(maximum.z);
  98 + return result;
  99 +}
  100 +
  101 +template <class T>
  102 +rtsAABB<T> rtsTGC<T>::BoundAABB()
  103 +{
  104 +/* This function returns an axis-aligned bounding box
  105 + that is the minimum bound for the given truncated-generalized cone.
  106 +*/
  107 + //create a vector representing each axis
  108 + vector3D<double> x(1.0, 0.0, 0.0);
  109 + vector3D<double> y(0.0, 1.0, 0.0);
  110 + vector3D<double> z(0.0, 0.0, 1.0);
  111 +
  112 + //store the extents
  113 + point3D<T> a_extents(radA*(1.0 - fabs(normA*x)),
  114 + radA*(1.0 - fabs(normA*y)),
  115 + radA*(1.0 - fabs(normA*z)));
  116 + point3D<T> b_extents(radB*(1.0 - fabs(normB*x)),
  117 + radB*(1.0 - fabs(normB*y)),
  118 + radB*(1.0 - fabs(normB*z)));
  119 +
  120 + //create the AABB
  121 + rtsAABB<T> result;
  122 +
  123 + //calculate the bounding box information
  124 + //calculate bounding box position as the minima of all extents and positions
  125 + result.minimum.x = min(posA.x - a_extents.x, posB.x - b_extents.x);
  126 + result.minimum.y = min(posA.y - a_extents.y, posB.y - b_extents.y);
  127 + result.minimum.z = min(posA.z - a_extents.z, posB.z - b_extents.z);
  128 +
  129 + //now find the size of the block
  130 + result.maximum.x = max(posA.x + a_extents.x, posB.x + b_extents.x);
  131 + result.maximum.y = max(posA.y + a_extents.y, posB.y + b_extents.y);
  132 + result.maximum.z = max(posA.z + a_extents.z, posB.z + b_extents.z);
  133 +
  134 + return result;
  135 +}
  136 +
  137 +
  138 +
  139 +
  140 +
  141 +
  142 +
  143 +
  144 +#endif
0 145 \ No newline at end of file
... ...
temp_rtsSignedDistance.h 0 → 100755
  1 +++ a/temp_rtsSignedDistance.h
  1 +#include "rtsImplicit3D.h"
  2 +#include <iostream>
  3 +using namespace std;
  4 +
  5 +#define DIST_MAX 255
  6 +#define DIST_UNSIGNED 0
  7 +#define DIST_SIGNED 1
  8 +
  9 +float ComputeSurfaceDistance(point3D<float> p0, point3D<float> p1, float val0, float val1, float s)
  10 +{
  11 + /*This function computes the distance from p0 to the surface, given two points p0 and p1
  12 + on either side of the surface (with values v0 and v1 respectively). surface specifies
  13 + the value at the surface.
  14 + */
  15 +
  16 + //compute the normalized position of the surface between p0 and p1
  17 + float s_norm_pos = (s - val0) / (val1 - val0);
  18 + //compute the actual position of the surface
  19 + point3D<float> s_pos = p0 + s_norm_pos * (p1 - p0);
  20 + //compute the distance from p0 to the surface
  21 + float result = (s_pos - p0).Length();
  22 + //cout<<"distance: "<<result<<endl;
  23 + return result;
  24 +}
  25 +
  26 +void CreateBoundaryConditions(rtsImplicit3D<unsigned char>* function, float threshold,
  27 + rtsImplicit3D<float>* &result, rtsImplicit3D<bool>* &mask)
  28 +{
  29 + /*This function creates an initial signed distance function from a threshold image.
  30 + All voxels adjacent to the surface specified by the threshold are initialized with a
  31 + distance value. Low values are inside, high values are outside.
  32 + */
  33 + //current and neighboring voxel flags (false = inside, true = outside)
  34 + bool c, x_p, x_n, y_p, y_n, z_p, z_n;
  35 + float d_xp, d_xn, d_yp, d_yn, d_zp, d_zn;
  36 + float in_out = 1;
  37 +
  38 + //boundary condition function and the mask
  39 + result = new rtsImplicit3D<float>(function->DimX(), function->DimY(), function->DimZ());
  40 + //get the parameterization
  41 + point3D<float> min_domain= function->getMinDomain();
  42 + point3D<float> max_domain = function->getMaxDomain();
  43 + result->Parameterize(min_domain.x, max_domain.x, min_domain.y, max_domain.y, min_domain.z, max_domain.z);
  44 + (*result) = DIST_MAX;
  45 + //create a mask
  46 + mask = new rtsImplicit3D<bool>(function->DimX(), function->DimY(), function->DimZ());
  47 + (*mask) = false;
  48 +
  49 + cout<<"done making boundary condition function"<<endl;
  50 + //for each voxel
  51 + vector3D<int> size(function->DimX(), function->DimY(), function->DimZ()); //get the function size
  52 + int x, y, z;
  53 + for(x=0; x<size.x; x++)
  54 + for(y=0; y<size.y; y++)
  55 + for(z=0; z<size.z; z++)
  56 + {
  57 + //reset flags
  58 + c=x_p=x_n=y_p=y_n=z_p=z_n=true;
  59 + in_out = 1.0;
  60 + //look at the current voxel
  61 + if((*function)(x, y, z) < threshold)
  62 + c=false;
  63 + else c=true;
  64 + //look at each neighboring voxel
  65 + if(x-1 < 0) x_n = c; //X
  66 + else if((*function)(x-1, y, z) < threshold) x_n = false;
  67 + if(x+1 >= size.x) x_p = c;
  68 + else if((*function)(x+1, y, z) < threshold) x_p = false;
  69 + if(y-1 < 0) y_n = c; //Y
  70 + else if((*function)(x, y-1, z) < threshold) y_n = false;
  71 + if(y+1 >= size.y) y_p = c;
  72 + else if((*function)(x, y+1, z) < threshold) y_p = false;
  73 + if(z-1 < 0) z_n = c; //Z
  74 + else if((*function)(x, y, z-1) < threshold) z_n = false;
  75 + if(z+1 >= size.z) z_p = c;
  76 + else if((*function)(x, y, z+1) < threshold) z_p = false;
  77 +
  78 + //set the distance from the isosurface
  79 + if(c == false)
  80 + in_out = -1.0;
  81 + if(x_n != c)
  82 + (*result)(x, y, z) = min((*result)(x,y,z),
  83 + ComputeSurfaceDistance((*function).getParameter(x, y, z),
  84 + (*function).getParameter(x-1, y, z),
  85 + (*function)(x, y, z),
  86 + (*function)(x-1, y, z),
  87 + threshold) * in_out);
  88 + if(x_p != c)
  89 + (*result)(x, y, z) = min((*result)(x,y,z),
  90 + ComputeSurfaceDistance((*function).getParameter(x, y, z),
  91 + (*function).getParameter(x+1, y, z),
  92 + (*function)(x, y, z),
  93 + (*function)(x+1, y, z),
  94 + threshold) * in_out);
  95 + if(y_n != c)
  96 + (*result)(x, y, z) = min((*result)(x,y,z),
  97 + ComputeSurfaceDistance((*function).getParameter(x, y, z),
  98 + (*function).getParameter(x, y-1, z),
  99 + (*function)(x, y, z),
  100 + (*function)(x, y-1, z),
  101 + threshold) * in_out);
  102 + if(y_p != c)
  103 + (*result)(x, y, z) = min((*result)(x,y,z),
  104 + ComputeSurfaceDistance((*function).getParameter(x, y, z),
  105 + (*function).getParameter(x, y+1, z),
  106 + (*function)(x, y, z),
  107 + (*function)(x, y+1, z),
  108 + threshold) * in_out);
  109 + if(z_n != c)
  110 + (*result)(x, y, z) = min((*result)(x,y,z),
  111 + ComputeSurfaceDistance((*function).getParameter(x, y, z-1),
  112 + (*function).getParameter(x, y, z),
  113 + (*function)(x, y, z),
  114 + (*function)(x, y, z-1),
  115 + threshold) * in_out);
  116 + if(z_p != c)
  117 + (*result)(x, y, z) = min((*result)(x,y,z),
  118 + ComputeSurfaceDistance((*function).getParameter(x, y, z),
  119 + (*function).getParameter(x, y, z+1),
  120 + (*function)(x, y, z),
  121 + (*function)(x, y, z+1),
  122 + threshold) * in_out);
  123 +
  124 + //set the mask to 1 if the voxel is on an edge node
  125 + if(x_n != c || x_p != c || y_n != c || y_p != c || z_n != c || z_p != c)
  126 + (*mask)(x, y, z) = true;
  127 + }
  128 +
  129 +
  130 + //if a line between the two voxels crosses the surface
  131 + //find the distance between the voxel center and the surface
  132 +
  133 +
  134 + cout<<"done computing boundary conditions"<<endl;
  135 +}
  136 +
  137 +double ManhattanDistance(rtsImplicit3D<float>* function,
  138 + point3D<indextype> point,
  139 + vector3D<float> voxelsize,
  140 + int type = DIST_UNSIGNED)
  141 +{
  142 + /*This function updates the manhattan distance from a surface using the manhattan
  143 + distance of its neighboring points.
  144 + */
  145 + indextype x, y, z;
  146 + x=point.x; y=point.y, z=point.z;
  147 + int sign = 1;
  148 + float result = DIST_MAX;
  149 + float near_value; //the value of the neighbor being considered
  150 + float possible_value;
  151 + if(x!=0)
  152 + {
  153 + near_value = (*function)(x-1, y, z);
  154 + if(type == DIST_UNSIGNED)
  155 + result = min(result, near_value + voxelsize.x);
  156 + else if(type == DIST_SIGNED)
  157 + {
  158 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  159 + possible_value = sign*(fabs(near_value) + voxelsize.x);
  160 + if(fabs(possible_value) < fabs(result))
  161 + result = possible_value;
  162 + }
  163 +
  164 + }
  165 + if(x!=function->DimX()-1)
  166 + {
  167 + near_value = (*function)(x+1, y, z);
  168 + if(type == DIST_UNSIGNED)
  169 + result = min(result, near_value + voxelsize.x);
  170 + else if(type == DIST_SIGNED)
  171 + {
  172 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  173 + possible_value = sign*(fabs(near_value) + voxelsize.x);
  174 + if(fabs(possible_value) < fabs(result))
  175 + result = possible_value;
  176 + }
  177 + }
  178 + if(y!=0)
  179 + {
  180 + near_value = (*function)(x, y-1, z);
  181 + if(type == DIST_UNSIGNED)
  182 + result = min(result, near_value + voxelsize.y);
  183 + else if(type == DIST_SIGNED)
  184 + {
  185 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  186 + possible_value = sign*(fabs(near_value) + voxelsize.y);
  187 + if(fabs(possible_value) < fabs(result))
  188 + result = possible_value;
  189 + }
  190 + }
  191 + if(y!=function->DimY()-1)
  192 + {
  193 + near_value = (*function)(x, y+1, z);
  194 + if(type == DIST_UNSIGNED)
  195 + result = min(result, near_value + voxelsize.y);
  196 + else if(type == DIST_SIGNED)
  197 + {
  198 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  199 + possible_value = sign*(fabs(near_value) + voxelsize.y);
  200 + if(fabs(possible_value) < fabs(result))
  201 + result = possible_value;
  202 + }
  203 + }
  204 + if(z!=0)
  205 + {
  206 + near_value = (*function)(x, y, z-1);
  207 + if(type == DIST_UNSIGNED)
  208 + result = min(result, near_value + voxelsize.z);
  209 + else if(type == DIST_SIGNED)
  210 + {
  211 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  212 + possible_value = sign*(fabs(near_value) + voxelsize.z);
  213 + if(fabs(possible_value) < fabs(result))
  214 + result = possible_value;
  215 + }
  216 + }
  217 + if(z!=function->DimZ()-1)
  218 + {
  219 + near_value = (*function)(x, y, z+1);
  220 + if(type == DIST_UNSIGNED)
  221 + result = min(result, near_value + voxelsize.z);
  222 + else if(type == DIST_SIGNED)
  223 + {
  224 + if(near_value<0) sign = -1; else sign = 1; //determine if the value is inside or outside
  225 + possible_value = sign*(fabs(near_value) + voxelsize.z);
  226 + if(fabs(possible_value) < fabs(result))
  227 + result = possible_value;
  228 + }
  229 + }
  230 + return result;
  231 +
  232 +}
  233 +void Eikonal_Manhattan(rtsImplicit3D<float>* &function,
  234 + rtsImplicit3D<bool>* mask,
  235 + int type = DIST_UNSIGNED)
  236 +{
  237 + /*This function estimates the Eikonal equation based on the manhattan distance. The
  238 + function constantly increases values outwards from the boundary conditions.
  239 + */
  240 +
  241 + //compute the distance between two voxels
  242 + vector3D<float> voxel_size;
  243 + voxel_size.x = fabs(function->getParameter(0, 0, 0).x - function->getParameter(1, 0, 0).x);
  244 + voxel_size.y = fabs(function->getParameter(0, 0, 0).y - function->getParameter(0, 1, 0).y);
  245 + voxel_size.z = fabs(function->getParameter(0, 0, 0).z - function->getParameter(0, 0, 1).z);
  246 +
  247 + //use fast sweeping to compute the manhattan distance
  248 + //0:X 0:Y 0:Z
  249 + cout<<"first iteration..."<<endl;
  250 + int x,y,z;
  251 + for(x=0; x<function->DimX(); x++)
  252 + for(y=0; y<function->DimY(); y++)
  253 + for(z=0; z<function->DimZ(); z++)
  254 + //if the current point is not a boundary value
  255 + if(!(*mask)(x, y, z))
  256 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  257 + cout<<"done."<<endl;
  258 + cout<<"second iteration..."<<endl;
  259 + //0:X 0:Y Z:0
  260 + for(x=0; x<function->DimX(); x++)
  261 + for(y=0; y<function->DimY(); y++)
  262 + for(z=function->DimZ()-1; z>=0; z--)
  263 + //if the current point is not a boundary value
  264 + if(!(*mask)(x, y, z))
  265 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  266 + cout<<"done."<<endl;
  267 + cout<<"third iteration..."<<endl;
  268 + //0:X Y:0 0:Z
  269 + for(x=0; x<function->DimX(); x++)
  270 + for(y=function->DimY()-1; y>=0; y--)
  271 + for(z=0; z<function->DimZ(); z++)
  272 + //if the current point is not a boundary value
  273 + if(!(*mask)(x, y, z))
  274 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  275 + cout<<"done."<<endl;
  276 + cout<<"fourth iteration..."<<endl;
  277 + //0:X Y:0 Z:0
  278 + for(x=0; x<function->DimX(); x++)
  279 + for(y=function->DimY()-1; y>=0; y--)
  280 + for(z=function->DimZ()-1; z>=0; z--)
  281 + //if the current point is not a boundary value
  282 + if(!(*mask)(x, y, z))
  283 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  284 + cout<<"done."<<endl;
  285 + cout<<"fifth iteration..."<<endl;
  286 + //X:0 0:Y 0:Z
  287 + for(x=function->DimX()-1; x>=0; x--)
  288 + for(y=0; y<function->DimY(); y++)
  289 + for(z=0; z<function->DimZ(); z++)
  290 + //if the current point is not a boundary value
  291 + if(!(*mask)(x, y, z))
  292 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  293 + cout<<"done."<<endl;
  294 + cout<<"sixth iteration..."<<endl;
  295 + //X:0 0:Y Z:0
  296 + for(x=function->DimX()-1; x>=0; x--)
  297 + for(y=0; y<function->DimY(); y++)
  298 + for(z=function->DimZ()-1; z>=0; z--)
  299 + //if the current point is not a boundary value
  300 + if(!(*mask)(x, y, z))
  301 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  302 + cout<<"done."<<endl;
  303 + cout<<"seventh iteration..."<<endl;
  304 + //X:0 Y:0 0:Z
  305 + for(x=function->DimX()-1; x>=0; x--)
  306 + for(y=function->DimY()-1; y>=0; y--)
  307 + for(z=0; z<function->DimZ(); z++)
  308 + //if the current point is not a boundary value
  309 + if(!(*mask)(x, y, z))
  310 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  311 + cout<<"done."<<endl;
  312 + cout<<"eighth iteration..."<<endl;
  313 + //X:0 Y:0 Z:0
  314 + for(x=function->DimX()-1; x>=0; x--)
  315 + for(y=function->DimY()-1; y>=0; y--)
  316 + for(z=function->DimZ()-1; z>=0; z--)
  317 + //if the current point is not a boundary value
  318 + if(!(*mask)(x, y, z))
  319 + (*function)(x,y,z) = ManhattanDistance(function, point3D<indextype>(x, y, z), voxel_size, type);
  320 + cout<<"done."<<endl;
  321 +}
... ...
temp_rts_glFilamentNetwork.cpp 0 → 100755
  1 +++ a/temp_rts_glFilamentNetwork.cpp
  1 +#include "temp_rts_glFilamentNetwork.h"
  2 +
  3 +void rts_glFilamentNetwork::RenderEdges()
  4 +{
  5 + //for each edge
  6 + vector<netEdge*>::iterator i;
  7 + int a, b;
  8 + point3D<double> v_a, v_b;
  9 + glBegin(GL_LINES); //start rendering lines
  10 + for(i=m_edge_list.begin(); i!=m_edge_list.end(); i++)
  11 + {
  12 + v_a = (*i)->vertex_a->position; //get the positions of the two vertex edges
  13 + v_b = (*i)->vertex_b->position;
  14 + glVertex3f(v_a.x, v_a.y, v_a.z); //draw the vertices
  15 + glVertex3f(v_b.x, v_b.y, v_b.z);
  16 + }
  17 + glEnd(); //finish drawing
  18 +}
  19 +
  20 +void rts_glFilamentNetwork::RenderBranches()
  21 +{
  22 + //for each vertex
  23 + vector<netVertex*>::iterator i;
  24 + point3D<double> v;
  25 + glBegin(GL_POINTS);
  26 + for(i=m_vertex_list.begin(); i!=m_vertex_list.end(); i++)
  27 + {
  28 + if((*i)->v_neighbors.size() > 2)
  29 + {
  30 + v = (*i)->position;
  31 + glVertex3f(v.x, v.y, v.z);
  32 + }
  33 + }
  34 + glEnd();
  35 +}
  36 +
  37 +void rts_glFilamentNetwork::RenderFilaments()
  38 +{
  39 + vector<netFilament*>::iterator i;
  40 + int num_edges;
  41 + point3D<double> v_a, v_b;
  42 + int e;
  43 + glBegin(GL_LINES);
  44 + for(i=m_filament_list.begin(); i!=m_filament_list.end(); i++) //for each filament
  45 + {
  46 + num_edges = (*i)->edges.size();
  47 + for(e=0; e<num_edges; e++)
  48 + {
  49 + v_a = (*i)->edges[e]->vertex_a->position;
  50 + v_b = (*i)->edges[e]->vertex_b->position;
  51 + glVertex3f(v_a.x, v_a.y, v_a.z);
  52 + glVertex3f(v_b.x, v_b.y, v_b.z);
  53 + }
  54 + }
  55 + glEnd();
  56 +}
  57 +
  58 +void rts_glFilamentNetwork::RenderSelectedFilaments()
  59 +{
  60 + vector<unsigned int>::iterator f;
  61 + int num_edges;
  62 + point3D<double> v_a, v_b;
  63 + int e;
  64 + glBegin(GL_LINES);
  65 + for(f=m_selected_list.begin(); f!=m_selected_list.end(); f++)
  66 + {
  67 + num_edges = m_filament_list[(*f)]->edges.size();
  68 + for(e=0; e<num_edges; e++)
  69 + {
  70 + v_a = m_filament_list[(*f)]->edges[e]->vertex_a->position;
  71 + v_b = m_filament_list[(*f)]->edges[e]->vertex_b->position;
  72 + glVertex3f(v_a.x, v_a.y, v_a.z);
  73 + glVertex3f(v_b.x, v_b.y, v_b.z);
  74 + }
  75 + }
  76 + glEnd();
  77 +}
  78 +
  79 +void rts_glFilamentNetwork::RenderOrientationColor(double x, double y, double z, double r, double g, double b)
  80 +{
  81 + vector<netFilament*>::iterator i;
  82 + int num_edges;
  83 + point3D<double> v_a, v_b;
  84 +
  85 + //orientation variables
  86 + vector3D<double> orientation;
  87 + double cos_a;
  88 + vector3D<double> A(x, y, z);
  89 + A.Normalize();
  90 +
  91 + int e;
  92 + glBegin(GL_LINES);
  93 + for(i=m_filament_list.begin(); i!=m_filament_list.end(); i++) //for each filament
  94 + {
  95 + //set the color of the filament based on orientation
  96 + v_a = (*i)->vertex_a->position;
  97 + v_b = (*i)->vertex_b->position;
  98 +
  99 +
  100 + num_edges = (*i)->edges.size();
  101 + for(e=0; e<num_edges; e++)
  102 + {
  103 + v_a = (*i)->edges[e]->vertex_a->position;
  104 + v_b = (*i)->edges[e]->vertex_b->position;
  105 +
  106 + //determine color
  107 + orientation = (v_a - v_b).Normalize();
  108 + cos_a = fabs(orientation*A);
  109 + glColor3f(r*cos_a, g*cos_a, b*cos_a);
  110 +
  111 + glVertex3f(v_a.x, v_a.y, v_a.z);
  112 + glVertex3f(v_b.x, v_b.y, v_b.z);
  113 + }
  114 + }
  115 + glEnd();
  116 +}
  117 +
  118 +void rts_glFilamentNetwork::RenderEdgeDistanceColor(float r, float g, float b, float cutoff)
  119 +{
  120 + vector<netEdge*>::iterator e;
  121 + glBegin(GL_LINES);
  122 + point3D<double> p;
  123 + double d;
  124 + double exp = 3;
  125 + for(e=m_edge_list.begin(); e!=m_edge_list.end(); e++)
  126 + {
  127 + d = (*e)->distance;
  128 + if(d<cutoff)
  129 + {
  130 + if(d<0.0) d=0.0;
  131 + if(d>1.0) d=1.0;
  132 +
  133 + glColor3f(pow((1.0-d),exp)*r, pow((1.0-d),exp)*g, pow((1.0-d),exp)*b);
  134 + p = (*e)->vertex_a->position;
  135 + glVertex3f(p.x, p.y, p.z);
  136 + p = (*e)->vertex_b->position;
  137 + glVertex3f(p.x, p.y, p.z);
  138 + }
  139 + }
  140 + glEnd();
  141 +}
  142 +
  143 +void rts_glFilamentNetwork::RenderFilamentDistanceColor(float r, float g, float b, float cutoff)
  144 +{
  145 + vector<netFilament*>::iterator f;
  146 + unsigned int e;
  147 + unsigned int num_edges;
  148 + double d;
  149 + point3D<double> v;
  150 + double exp = 3.0;
  151 + for(f = m_filament_list.begin(); f!=m_filament_list.end(); f++)
  152 + {
  153 + d = (*f)->distance;
  154 + if(d<cutoff)
  155 + {
  156 + if(d>1.0) d=1.0;
  157 + if(d<0.0) d=0.0;
  158 + //cout<<"d: "<<d<<endl;
  159 + num_edges = (*f)->edges.size();
  160 + glColor3f(pow((1.0-d), exp)*r, pow((1.0-d), exp)*g, pow((1.0-d), exp)*b);
  161 + glBegin(GL_LINES);
  162 + for(e=0; e<num_edges; e++)
  163 + {
  164 + v = (*f)->edges[e]->vertex_a->position;
  165 + glVertex3f(v.x, v.y, v.z);
  166 + v = (*f)->edges[e]->vertex_b->position;
  167 + glVertex3f(v.x, v.y, v.z);
  168 + }
  169 + glEnd();
  170 + }
  171 + }
  172 +
  173 +}
  174 +
  175 +
  176 +void rts_glFilamentNetwork::RenderRadiusColor(float min_r, float min_g, float min_b,
  177 + float max_r, float max_g, float max_b,
  178 + float min_radius, float max_radius)
  179 +{
  180 + /*Render each segment with a color based on the radius of the filament
  181 + */
  182 +
  183 + vector<netFilament*>::iterator i;
  184 + int e;
  185 + int num_edges;
  186 + point3D<double> v;
  187 + vector3D<float> color_min(min_r, min_g, min_b);
  188 + vector3D<float> color_max(max_r, max_g, max_b);
  189 + max_radius /= m_data_scale;
  190 + min_radius /= m_data_scale;
  191 + float diff = max_radius - min_radius;
  192 + float p; //parameter value (position between min and max radii)
  193 + vector3D<float> color_p;
  194 +
  195 + for(i=m_filament_list.begin(); i!=m_filament_list.end(); i++)
  196 + {
  197 + glBegin(GL_LINES);
  198 + num_edges = (*i)->edges.size();
  199 + for(e=0; e<num_edges; e++)
  200 + {
  201 + //determine the color
  202 + p = ((*i)->edges[e]->vertex_a->radius - min_radius)/diff;
  203 + //cout<<"p: "<<p<<endl;
  204 + color_p = (1.0 - p)*color_min + (p)*color_max;
  205 + glColor3f(color_p.x, color_p.y, color_p.z);
  206 + //determine the vertex position
  207 + v = (*i)->edges[e]->vertex_a->position;
  208 + glVertex3f(v.x, v.y, v.z);
  209 + //determine the second color
  210 + p = ((*i)->edges[e]->vertex_b->radius - min_radius)/diff;
  211 + color_p = (1.0 - p)*color_min + (p)*color_max;
  212 + glColor3f(color_p.x, color_p.y, color_p.z);
  213 + //determine the vertex position
  214 + v = (*i)->edges[e]->vertex_b->position;
  215 + glVertex3f(v.x, v.y, v.z);
  216 + }
  217 + glEnd();
  218 + }
  219 +}
  220 +
  221 +void rts_glFilamentNetwork::RenderEdgeBoundingBoxes()
  222 +{
  223 + glMatrixMode(GL_MODELVIEW); //switch to the modelview matrix and store it
  224 +
  225 + vector<netEdge*>::iterator e;
  226 + point3D<double> center;
  227 + vector3D<double> size;
  228 + for(e=m_edge_list.begin(); e!=m_edge_list.end(); e++)
  229 + {
  230 + glPushMatrix();
  231 + size = (*e)->bounding_box.maximum - (*e)->bounding_box.minimum;
  232 + center = (*e)->bounding_box.minimum + 0.5*(size);
  233 + glTranslatef(center.x, center.y, center.z);
  234 + glScalef(size.x,
  235 + size.y,
  236 + size.z);
  237 + glutWireCube(1.0);
  238 + glPopMatrix();
  239 + }
  240 +
  241 +}
  242 +
  243 +void rts_glFilamentNetwork::RenderFilamentBoundingBoxes()
  244 +{
  245 + glMatrixMode(GL_MODELVIEW); //switch to the modelview matrix and store it
  246 +
  247 + vector<netFilament*>::iterator f;
  248 + point3D<double> center;
  249 + vector3D<double> size;
  250 + for(f=m_filament_list.begin(); f!=m_filament_list.end(); f++)
  251 + {
  252 + glPushMatrix();
  253 + size = (*f)->bounding_box.maximum - (*f)->bounding_box.minimum;
  254 + center = (*f)->bounding_box.minimum + 0.5*size;
  255 + glTranslatef(center.x, center.y, center.z);
  256 + glScalef(size.x,
  257 + size.y,
  258 + size.z);
  259 + glutWireCube(1.0);
  260 + glPopMatrix();
  261 + }
  262 +}
  263 +
  264 +void rts_glFilamentNetwork::RenderCellSpheres()
  265 +{
  266 + glMatrixMode(GL_MODELVIEW);
  267 +
  268 + vector<netCell*>::iterator c;
  269 + for(c=m_cell_list.begin(); c!=m_cell_list.end(); c++)
  270 + {
  271 + glPushMatrix();
  272 + glTranslatef((*c)->position.x, (*c)->position.y, (*c)->position.z);
  273 + glutSolidSphere((*c)->radius, 10, 10);
  274 + glPopMatrix();
  275 + }
  276 +}
  277 +void rts_glFilamentNetwork::RenderSelectedCells()
  278 +{
  279 + glMatrixMode(GL_MODELVIEW);
  280 +
  281 + vector<unsigned int>::iterator f;
  282 + vector<netCell*>::iterator c;
  283 + for(f = m_selected_list.begin(); f!=m_selected_list.end(); f++)
  284 + {
  285 + for(c=m_filament_list[(*f)]->cells.begin(); c!=m_filament_list[(*f)]->cells.end(); c++)
  286 + {
  287 + glPushMatrix();
  288 + glTranslatef((*c)->position.x, (*c)->position.y, (*c)->position.z);
  289 + glutSolidSphere((*c)->radius, 10, 10);
  290 + glPopMatrix();
  291 + }
  292 + }
  293 +}
  294 +
  295 +void rts_glFilamentNetwork::p_ProcessPickHits(GLuint num_hits, GLuint* buffer,
  296 + unsigned int start_filament, bool append, int max)
  297 +{
  298 + //cout<<"hits "<<start_filament<<" to "<<start_filament+63<<": "<<num_hits<<endl;
  299 + /*This structure is kinda complicated. Extract the selected filaments here and put the indices
  300 + into the selection vector.
  301 + */
  302 + //cout<<"selected filaments:"<<endl;
  303 + if(num_hits > max)
  304 + num_hits = max;
  305 + unsigned int h, n;
  306 + unsigned int num_names;
  307 + unsigned int name;
  308 + GLuint* ptr = buffer; //index into buffer array
  309 + for(h=0; h<num_hits; h++) //for each hit
  310 + {
  311 + num_names = *ptr; //get the number of names in the hit
  312 + ptr+=3; //skip to the names
  313 + for(n=0; n<num_names; n++) //this should really only execute once (since we don't push names)
  314 + {
  315 + name = start_filament + (*ptr);
  316 + if(append) //if we are appending
  317 + {
  318 + if(!p_IsSelected(name))
  319 + m_selected_list.push_back(name);
  320 + }
  321 + else
  322 + m_selected_list.push_back(name);
  323 + //cout<<start_filament+(*ptr)<<endl;
  324 + ptr++;
  325 + }
  326 + }
  327 +
  328 +
  329 +
  330 +}
  331 +
  332 +void rts_glFilamentNetwork::PickFilaments(int x_center, int y_center, int width, int height, bool append, int max)
  333 +{
  334 + if(!append)
  335 + m_selected_list.clear(); //first empty the selected list to start a new selection
  336 + //set up the selection buffer
  337 + GLuint selection_buffer[1000];
  338 + GLuint hits;
  339 +
  340 + glSelectBuffer(1000, selection_buffer);
  341 + glRenderMode(GL_SELECT); //change to selection mode
  342 + glInitNames(); //start naming objects
  343 + glPushName(0);
  344 +
  345 + //set up projection matrix
  346 + //note that the pick matrix has to be multiplied in first, so we have to store the projection
  347 + //matrix and multiply it in afterwards
  348 + glMatrixMode(GL_PROJECTION);
  349 + GLfloat projection_matrix[16];
  350 + glGetFloatv(GL_PROJECTION_MATRIX, projection_matrix); //get the current projection matrix
  351 + glPushMatrix(); //store the projection matrix
  352 + glLoadIdentity(); //start from scratch
  353 + GLint viewport[4];
  354 + glGetIntegerv(GL_VIEWPORT, viewport); //set up the pick matrix
  355 + gluPickMatrix((GLdouble)x_center, (GLdouble)(viewport[3]-y_center), width, height, viewport);
  356 + glMultMatrixf(projection_matrix);
  357 +
  358 +
  359 + //run through each filament
  360 + int num_filaments = m_filament_list.size();
  361 + int num_edges, e, f;
  362 + point3D<double> v_a, v_b;
  363 + int name = 0;
  364 + unsigned int total_hits = 0;
  365 + for(f=0; f<num_filaments; f++) //for each filament
  366 + {
  367 + glLoadName(name); //push a name for the filament
  368 + glBegin(GL_LINES); //begin drawing the filament
  369 + num_edges = m_filament_list[f]->edges.size();
  370 + for(e = 0; e<num_edges; e++)
  371 + {
  372 + //draw each edge
  373 + v_a = m_filament_list[f]->edges[e]->vertex_a->position;
  374 + v_b = m_filament_list[f]->edges[e]->vertex_b->position;
  375 + glVertex3f(v_a.x, v_a.y, v_a.z);
  376 + glVertex3f(v_b.x, v_b.y, v_b.z);
  377 + }
  378 + glEnd();
  379 + name++; //increment the name
  380 + //We have to make sure that the name count doesn't exceed 64
  381 + if(name == 64) //if the name hits 64, check for and store hits, then reset the name
  382 + {
  383 + hits = glRenderMode(GL_RENDER);
  384 + p_ProcessPickHits(hits, selection_buffer, f-63, append, max - total_hits); //process the hits (store selected fibers)
  385 + total_hits += hits;
  386 + if(total_hits >= max) //if we've reached the max, return
  387 + {
  388 + glPopMatrix();
  389 + return;
  390 + }
  391 + name = 0; //reset the selection queue
  392 + glRenderMode(GL_SELECT); //change to selection mode
  393 + glInitNames(); //start naming objects
  394 + glPushName(0); //insert the first name
  395 + }
  396 + }
  397 + glFlush(); //finish rendering
  398 + hits = glRenderMode(GL_RENDER); //switch back to normal mode, get the number of hits
  399 + p_ProcessPickHits(hits, selection_buffer, f/64, append, max - total_hits); //get any left-over hits
  400 + total_hits += hits;
  401 +
  402 + glPopMatrix();
  403 +}
... ...
temp_rts_glFilamentNetwork.h 0 → 100755
  1 +++ a/temp_rts_glFilamentNetwork.h
  1 +#ifndef RTS_GLFILAMENTNETWORK_H
  2 +#define RTS_GLFILAMENTNETWORK_H
  3 +
  4 +#include "temp_rtsFilamentNetwork.h"
  5 +#include <windows.h>
  6 +#include <gl/gl.h>
  7 +#include <gl/glut.h>
  8 +
  9 +class rts_glFilamentNetwork:public rtsFilamentNetwork
  10 +{
  11 +private:
  12 + void p_ProcessPickHits(GLuint num_hits, GLuint* buffer, unsigned int start_filament,
  13 + bool append = false, int max = 1);
  14 +public:
  15 +
  16 + void RenderEdges();
  17 + void RenderBranches();
  18 + void RenderFilaments();
  19 + void RenderOrientationColor(double x, double y, double z, double r, double g, double b);
  20 + void RenderSelectedFilaments();
  21 + void RenderRadiusColor(float min_r, float min_g, float min_b,
  22 + float max_r, float max_g, float max_b,
  23 + float min_radius, float max_radius);
  24 + void RenderEdgeDistanceColor(float r, float g, float b, float cutoff);
  25 + void RenderFilamentDistanceColor(float r, float g, float b, float cutoff);
  26 + void RenderEdgeBoundingBoxes();
  27 + void RenderFilamentBoundingBoxes();
  28 + void RenderCellSpheres();
  29 + void RenderSelectedCells();
  30 +
  31 + //pick filaments based on the current projection
  32 + void PickFilaments(int x_center, int y_center, int width, int height, bool append = false, int max = 1);
  33 +
  34 +};
  35 +
  36 +
  37 +#endif
0 38 \ No newline at end of file
... ...
validate/CMakeLists.txt 0 → 100755
  1 +++ a/validate/CMakeLists.txt
  1 +#Specify the version being used aswell as the language
  2 +cmake_minimum_required(VERSION 2.8)
  3 +#Name your project here
  4 +project(rts-validate)
  5 +
  6 +#set the module directory
  7 +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
  8 +
  9 +#set up CUDA
  10 +find_package(CUDA)
  11 +
  12 +#find OpenGL
  13 +find_package(OpenGL REQUIRED)
  14 +
  15 +#find GLUT
  16 +set(GLUT_ROOT_PATH $ENV{GLUT_ROOT_PATH})
  17 +find_package(GLUT REQUIRED)
  18 +
  19 +#find GLEW
  20 +find_package(GLEW REQUIRED)
  21 +
  22 +#ask the user for the RTS location
  23 +set(RTS_ROOT_PATH $ENV{RTS_ROOT_PATH})
  24 +find_package(RTS REQUIRED)
  25 +
  26 +#set the include directories
  27 +include_directories(
  28 + ${CMAKE_CURRENT_BINARY_DIR}
  29 + ${OPENGL_INCLUDE_DIR}
  30 + ${GLEW_INCLUDE_PATH}
  31 + ${GLUT_INCLUDE_DIR}
  32 + ${RTS_INCLUDE_DIR}
  33 +)
  34 +
  35 +#enable warnings
  36 +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
  37 + add_definitions(-Wall)
  38 +endif()
  39 +
  40 +#Assign source files to the appropriate variables
  41 +file(GLOB SRC_CPP "*.cpp")
  42 +file(GLOB SRC_H "*.h")
  43 +file(GLOB SRC_CU "*.cu")
  44 +
  45 +#create an executable
  46 +cuda_add_executable(rts-validate ${SRC_CPP} ${SRC_H} ${UI_H} ${SRC_CU})
  47 +
  48 +#set the link libraries
  49 +target_link_libraries(rts-validate ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${GLEW_LIBRARY} ${CUDA_cufft_LIBRARY} ${GLUT_glut_LIBRARY})
  50 +
  51 +
  52 +
... ...
validate/FindRTS.cmake 0 → 100755
  1 +++ a/validate/FindRTS.cmake
  1 +# Tries to find the RTS include directory
  2 +
  3 + FIND_PATH( RTS_INCLUDE_DIR NAMES rts_glShaderProgram.h
  4 + PATHS
  5 + ${CMAKE_CURRENT_SOURCE_DIR}/rts
  6 + ${RTS_ROOT_PATH}
  7 +)
  8 +
  9 +IF (RTS_FOUND)
  10 + #The following deprecated settings are for backwards compatibility with CMake1.4
  11 + SET (RTS_INCLUDE_PATH ${RTS_INCLUDE_DIR})
  12 +ENDIF(RTS_FOUND)
  13 +
  14 +FIND_PACKAGE_HANDLE_STANDARD_ARGS(RTS REQUIRED_VARS TRUE RTS_INCLUDE_DIR)
... ...
validate/compare.h 0 → 100644
  1 +++ a/validate/compare.h
  1 +#ifndef RTS_VALIDATE_COMPARE_H
  2 +#define RTS_VALIDATE_COMPARE_H
  3 +
  4 +#define N 5000
  5 +#define epsilon 0.00001
  6 +
  7 +#include <complex>
  8 +#include <iostream>
  9 +#include <stdlib.h>
  10 +#include "rts/complex.h"
  11 +
  12 +template <typename T>
  13 +static void compare(std::complex<T> a, rts::complex<T> b, std::string testName)
  14 +{
  15 + T diffx = std::abs(a.real() - b.r);
  16 + T diffy = std::abs(a.imag() - b.i);
  17 +
  18 + if(diffx > epsilon || diffy > epsilon)
  19 + {
  20 + std::cout<<"Failed "<<testName<<std::endl;
  21 + std::cout<<a<<"------"<<b.toStr()<<std::endl;
  22 + exit(1);
  23 + }
  24 +
  25 +}
  26 +
  27 +#endif
... ...
validate/main.cpp 0 → 100644
  1 +++ a/validate/main.cpp
  1 +void cpuValidateComplex();
  2 +void gpuValidateComplex();
  3 +void cpuValidateBessel();
  4 +void cpuValidateLegendre();
  5 +
  6 +int main()
  7 +{
  8 + //validate the complex number class
  9 + //cpuValidateComplex();
  10 + //gpuValidateComplex();
  11 +
  12 + //validate Bessel functions
  13 + cpuValidateBessel();
  14 +
  15 + //validate the Legendre polynomials
  16 + cpuValidateLegendre();
  17 +
  18 + return 0;
  19 +}
... ...
validate/validate-bessel.cpp 0 → 100644
  1 +++ a/validate/validate-bessel.cpp
  1 +#include <complex>
  2 +#include <iostream>
  3 +#include <stdio.h>
  4 +#include <string.h>
  5 +#include "rts/complex.h"
  6 +#include "rts/sbessel.h"
  7 +
  8 +#include "compare.h"
  9 +
  10 +typedef float precision;
  11 +
  12 +//typedef std::complex<double> ptype;
  13 +typedef rts::complex<precision> ptype;
  14 +
  15 +void cpuValidateBessel()
  16 +{
  17 +
  18 + //order
  19 + precision v = 5;
  20 + precision vm;
  21 +
  22 + //parameter
  23 + precision max_z = 5;
  24 + int nz = 20;
  25 + precision dz = max_z / nz;
  26 +
  27 + //bessel function results (first and second kind)
  28 + int S = sizeof(ptype) * (v + 1);
  29 +
  30 + ptype* jv = (ptype*)malloc(S);
  31 + ptype* yv = (ptype*)malloc(S);
  32 + ptype* hv = (ptype*)malloc(S);
  33 +
  34 +
  35 + std::cout<<"---------j_v(x)-------------"<<std::endl;
  36 + rts::complex<precision> z;
  37 + for(int iz = 0; iz < nz; iz++)
  38 + {
  39 + z = iz * dz;
  40 +
  41 + rts::sbesselj<precision>(v, z, jv);
  42 +
  43 + std::cout<<z.toStr()<<", "<<jv[0].toStr()<<", "<<jv[1].toStr()<<", "<<jv[2].toStr()<<std::endl;
  44 +
  45 + }
  46 +
  47 + std::cout<<"---------y_v(x)-------------"<<std::endl;
  48 + for(int iz = 0; iz < nz; iz++)
  49 + {
  50 + z = iz * dz;
  51 +
  52 + rts::sbessely<precision>(v, z, yv);
  53 +
  54 + std::cout<<z.toStr()<<", "<<yv[0].toStr()<<", "<<yv[1].toStr()<<", "<<yv[2].toStr()<<std::endl;
  55 +
  56 + }
  57 +
  58 + std::cout<<"---------h(1)_v(x)-------------"<<std::endl;
  59 + for(int iz = 0; iz < nz; iz++)
  60 + {
  61 + z = iz * dz;
  62 +
  63 + rts::sbesselh1<precision>(v, z, hv);
  64 +
  65 + std::cout<<z.toStr()<<", "<<hv[0].toStr()<<", "<<hv[1].toStr()<<", "<<hv[2].toStr()<<std::endl;
  66 +
  67 + }
  68 +
  69 +
  70 +
  71 +
  72 +
  73 +
  74 +
  75 +
  76 +}
... ...
validate/validate-complex.cpp 0 → 100644
  1 +++ a/validate/validate-complex.cpp
  1 +#include <complex>
  2 +#include <iostream>
  3 +#include "rts/complex.h"
  4 +
  5 +#include "compare.h"
  6 +
  7 +#define N 5
  8 +#define epsilon 0.000001
  9 +
  10 +template <typename T>
  11 +void validateOperators()
  12 +{
  13 + int precision = sizeof(T) * 8;
  14 + std::stringstream ss;
  15 + ss<<" ("<<precision<<"-bit)";
  16 + std::string bitString = ss.str();
  17 + //validate complex binary functions
  18 + T x0, x1, y0, y1;
  19 + for(int i = 0; i<N; i++)
  20 + {
  21 + //generate a random complex number
  22 + x0 = (double)rand()/(double)RAND_MAX * 2 - 1;
  23 + y0 = (double)rand()/(double)RAND_MAX * 2 - 1;
  24 + x1 = (double)rand()/(double)RAND_MAX * 2 - 1;
  25 + y1 = (double)rand()/(double)RAND_MAX * 2 - 1;
  26 +
  27 + //create an STD and RTS instance of the complex class
  28 + std::complex<T> stdComplex0(x0, y0);
  29 + rts::complex<T> rtsComplex0(x0, y0);
  30 +
  31 + std::complex<T> stdComplex1(x1, y1);
  32 + rts::complex<T> rtsComplex1(x1, y1);
  33 +
  34 + std::complex<T> stdResult;
  35 + rts::complex<T> rtsResult;
  36 +
  37 + //test addition
  38 + stdResult = stdComplex0 + stdComplex1;
  39 + rtsResult = rtsComplex0 + rtsComplex1;
  40 + compare(stdResult, rtsResult, std::string("Binary Addition") + bitString);
  41 + //test addition with real value
  42 + stdResult = stdComplex1.real() + stdComplex0;
  43 + rtsResult = rtsComplex1.r + rtsComplex0;
  44 + compare(stdResult, rtsResult, std::string("Addition with Real Value") + bitString);
  45 +
  46 + //test subtraction
  47 + stdResult = stdComplex0 - stdComplex1;
  48 + rtsResult = rtsComplex0 - rtsComplex1;
  49 + compare(stdResult, rtsResult, std::string("Binary Subtraction") + bitString);
  50 + //test subtraction with real value
  51 + stdResult = stdComplex1.real() - stdComplex0;
  52 + rtsResult = rtsComplex1.r - rtsComplex0;
  53 + compare(stdResult, rtsResult, std::string("Subtraction with Real Value") + bitString);
  54 +
  55 + //test multiplication
  56 + stdResult = stdComplex0 * stdComplex1;
  57 + rtsResult = rtsComplex0 * rtsComplex1;
  58 + compare(stdResult, rtsResult, std::string("Binary Multiplication") + bitString);
  59 + //test multiplication with real value
  60 + stdResult = stdComplex1.real() * stdComplex0;
  61 + rtsResult = rtsComplex1.r * rtsComplex0;
  62 + compare(stdResult, rtsResult, std::string("Multiplication with Real Value") + bitString);
  63 +
  64 + //test division
  65 + stdResult = stdComplex0 / stdComplex1;
  66 + rtsResult = rtsComplex0 / rtsComplex1;
  67 + compare(stdResult, rtsResult, std::string("Binary Division") + bitString);
  68 + //test division with real value
  69 + stdResult = stdComplex1.real() / stdComplex0;
  70 + rtsResult = rtsComplex1.r / rtsComplex0;
  71 + compare(stdResult, rtsResult, std::string("Division with Real Value") + bitString);
  72 +
  73 + //test abs()
  74 + stdResult = abs(stdComplex0);
  75 + rtsResult = abs(rtsComplex0);
  76 + compare(stdResult, rtsResult, std::string("abs()") + bitString);
  77 +
  78 + //test log()
  79 + stdResult = log(stdComplex0);
  80 + rtsResult = log(rtsComplex0);
  81 + compare(stdResult, rtsResult, std::string("log()") + bitString);
  82 +
  83 + //test exp()
  84 + stdResult = exp(stdComplex0);
  85 + rtsResult = exp(rtsComplex0);
  86 + compare(stdResult, rtsResult, std::string("exp()") + bitString);
  87 +
  88 + //test pow()
  89 + stdResult = pow(stdComplex0, (T)2.0);
  90 + rtsResult = pow(rtsComplex0, (T)2.0);
  91 + compare(stdResult, rtsResult, std::string("pow()") + bitString);
  92 +
  93 + //test sqrt()
  94 + stdResult = sqrt(stdComplex0);
  95 + rtsResult = rts::sqrt(rtsComplex0);
  96 + compare(stdResult, rtsResult, std::string("sqrt()") + bitString);
  97 +
  98 + //trigonometric functions
  99 + stdResult = sin(stdComplex0);
  100 + rtsResult = rts::sin(rtsComplex0);
  101 + compare(stdResult, rtsResult, std::string("sin()") + bitString);
  102 +
  103 + //trigonometric functions
  104 + stdResult = cos(stdComplex0);
  105 + rtsResult = rts::cos(rtsComplex0);
  106 + compare(stdResult, rtsResult, std::string("cos()") + bitString);
  107 +
  108 + //ASSIGNMENT OPERATORS
  109 +
  110 + // +=
  111 + stdResult = stdComplex0;
  112 + stdResult += stdComplex1;
  113 + rtsResult = rtsComplex0;
  114 + rtsResult += rtsComplex1;
  115 + compare(stdResult, rtsResult, std::string("operator +=") + bitString);
  116 +
  117 + // *=
  118 + stdResult = stdComplex0;
  119 + stdResult *= stdComplex1;
  120 + rtsResult = rtsComplex0;
  121 + rtsResult *= rtsComplex1;
  122 + compare(stdResult, rtsResult, std::string("operator *=") + bitString);
  123 +
  124 + // /=
  125 + stdResult = stdComplex0;
  126 + stdResult /= stdComplex1;
  127 + rtsResult = rtsComplex0;
  128 + rtsResult /= rtsComplex1;
  129 + compare(stdResult, rtsResult, std::string("operator /=") + bitString);
  130 +
  131 + }
  132 +}
  133 +
  134 +void cpuValidateComplex()
  135 +{
  136 + //validate both floating point and double precision
  137 + validateOperators<float>();
  138 + validateOperators<double>();
  139 +
  140 +}
... ...
validate/validate-complex.cu 0 → 100644
  1 +++ a/validate/validate-complex.cu
  1 +#include <complex>
  2 +#include <iostream>
  3 +#include "rts/complex.h"
  4 +
  5 +#include "compare.h"
  6 +
  7 +
  8 +template<typename T>
  9 +__global__ void add(rts::complex<T> a, rts::complex<T> b, rts::complex<T>* c)
  10 +{
  11 + *c = a + b;
  12 +}
  13 +
  14 +template<typename T>
  15 +__global__ void multiply(rts::complex<T> a, rts::complex<T> b, rts::complex<T>* c)
  16 +{
  17 + *c = a * b;
  18 +}
  19 +
  20 +template<typename T>
  21 +__global__ void multiply(rts::complex<T> a, T b, rts::complex<T>* c)
  22 +{
  23 + *c = a * b;
  24 +}
  25 +
  26 +template<typename T>
  27 +__global__ void divide(rts::complex<T> a, rts::complex<T> b, rts::complex<T>* c)
  28 +{
  29 + *c = a / b;
  30 +}
  31 +
  32 +template<typename T>
  33 +__global__ void log(rts::complex<T> a, rts::complex<T>* c)
  34 +{
  35 + *c = rts::log(a);
  36 +}
  37 +
  38 +template<typename T>
  39 +__global__ void sqrt(rts::complex<T> a, rts::complex<T>* c)
  40 +{
  41 + *c = rts::sqrt(a);
  42 +}
  43 +
  44 +template<typename T>
  45 +__global__ void exp(rts::complex<T> a, rts::complex<T>* c)
  46 +{
  47 + *c = rts::exp(a);
  48 +}
  49 +
  50 +template<typename T>
  51 +__global__ void pow(rts::complex<T> a, rts::complex<T>* c)
  52 +{
  53 + *c = rts::pow(a, (T)2.0);
  54 +}
  55 +
  56 +template<typename T>
  57 +__global__ void sin(rts::complex<T> a, rts::complex<T>* c)
  58 +{
  59 + *c = rts::sin(a);
  60 +}
  61 +
  62 +template<typename T>
  63 +__global__ void cos(rts::complex<T> a, rts::complex<T>* c)
  64 +{
  65 + *c = rts::cos(a);
  66 +}
  67 +
  68 +template <typename T>
  69 +void gpuValidateOperators()
  70 +{
  71 + int precision = sizeof(T) * 8;
  72 + std::stringstream ss;
  73 + ss<<" ("<<precision<<"-bit)";
  74 + std::string bitString = ss.str();
  75 +
  76 + rts::complex<T>* gpuResult;
  77 + cudaMalloc((void**)&gpuResult, sizeof(rts::complex<T>));
  78 +
  79 + //validate complex binary functions
  80 + T x0, x1, y0, y1;
  81 + for(int i = 0; i<N; i++)
  82 + {
  83 + //generate a random complex number
  84 + x0 = (double)rand()/(double)RAND_MAX * 2 - 1;
  85 + y0 = (double)rand()/(double)RAND_MAX * 2 - 1;
  86 + x1 = (double)rand()/(double)RAND_MAX * 2 - 1;
  87 + y1 = (double)rand()/(double)RAND_MAX * 2 - 1;
  88 +
  89 + //create an STD and RTS instance of the complex class
  90 + std::complex<T> stdComplex0(x0, y0);
  91 + rts::complex<T> rtsComplex0(x0, y0);
  92 +
  93 + std::complex<T> stdComplex1(x1, y1);
  94 + rts::complex<T> rtsComplex1(x1, y1);
  95 +
  96 + std::complex<T> stdResult;
  97 + rts::complex<T> rtsResult;
  98 +
  99 +
  100 + //test addition
  101 + stdResult = stdComplex0 + stdComplex1;
  102 + add<<<1, 1>>>(rtsComplex0, rtsComplex1, gpuResult);
  103 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  104 + compare(stdResult, rtsResult, std::string("Binary Addition") + bitString);
  105 + //std::cout<<stdResult<<"------"<<rtsResult.toStr()<<std::endl;
  106 +
  107 + //test multiplication
  108 + stdResult = stdComplex0 * stdComplex1;
  109 + multiply<<<1, 1>>>(rtsComplex0, rtsComplex1, gpuResult);
  110 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  111 + compare(stdResult, rtsResult, std::string("Binary Multiplication") + bitString);
  112 +
  113 + //test multiplication with constant
  114 + stdResult = stdComplex0 * stdComplex1.real();
  115 + multiply<<<1, 1>>>(rtsComplex0, rtsComplex1.r, gpuResult);
  116 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  117 + compare(stdResult, rtsResult, std::string("Multiplication with Real Value") + bitString);
  118 +
  119 + //test division
  120 + stdResult = stdComplex0 / stdComplex1;
  121 + divide<<<1, 1>>>(rtsComplex0, rtsComplex1, gpuResult);
  122 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  123 + compare(stdResult, rtsResult, std::string("Binary Division") + bitString);
  124 +
  125 + //test log()
  126 + stdResult = log(stdComplex0);
  127 + log<<<1, 1>>>(rtsComplex0, gpuResult);
  128 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  129 + compare(stdResult, rtsResult, std::string("log()") + bitString);
  130 +
  131 + //test exp()
  132 + stdResult = exp(stdComplex0);
  133 + exp<<<1, 1>>>(rtsComplex0, gpuResult);
  134 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  135 + compare(stdResult, rtsResult, std::string("exp()") + bitString);
  136 +
  137 + //test pow()
  138 + stdResult = pow(stdComplex0, 2);
  139 + pow<<<1, 1>>>(rtsComplex0, gpuResult);
  140 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  141 + compare(stdResult, rtsResult, std::string("pow()") + bitString);
  142 +
  143 + //test sqrt()
  144 + stdResult = sqrt(stdComplex0);
  145 + sqrt<<<1, 1>>>(rtsComplex0, gpuResult);
  146 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  147 + compare(stdResult, rtsResult, std::string("sqrt()") + bitString);
  148 +
  149 + //trigonometric functions
  150 + stdResult = sin(stdComplex0);
  151 + sin<<<1, 1>>>(rtsComplex0, gpuResult);
  152 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  153 + compare(stdResult, rtsResult, std::string("sin()") + bitString);
  154 +
  155 + //trigonometric functions
  156 + stdResult = cos(stdComplex0);
  157 + cos<<<1, 1>>>(rtsComplex0, gpuResult);
  158 + cudaMemcpy(&rtsResult, gpuResult, sizeof(rts::complex<T>), cudaMemcpyDeviceToHost);
  159 + compare(stdResult, rtsResult, std::string("cos()") + bitString);
  160 +
  161 +
  162 + }
  163 + cudaFree(gpuResult);
  164 +
  165 +}
  166 +
  167 +void gpuValidateComplex()
  168 +{
  169 +
  170 + gpuValidateOperators<float>();
  171 + //gpuValidateOperators<double>();
  172 +}
... ...