glviewvol

diff src/volume.cc @ 1:cc9e0d8590e2

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 27 Dec 2014 06:32:28 +0200
parents
children 701507c8238f
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/volume.cc	Sat Dec 27 06:32:28 2014 +0200
     1.3 @@ -0,0 +1,198 @@
     1.4 +#include <stdio.h>
     1.5 +#include <string.h>
     1.6 +#include <ctype.h>
     1.7 +#include <errno.h>
     1.8 +#include <math.h>
     1.9 +#include "volume.h"
    1.10 +
    1.11 +static char *strip_space(char *s);
    1.12 +
    1.13 +
    1.14 +Volume::~Volume()
    1.15 +{
    1.16 +}
    1.17 +
    1.18 +int Volume::num_samples(int dim) const
    1.19 +{
    1.20 +	return 0;
    1.21 +}
    1.22 +
    1.23 +void Volume::normalf(float *norm, float x, float y, float z, float delta)
    1.24 +{
    1.25 +	float dx, dy, dz;
    1.26 +	dx = dy = dz = delta;
    1.27 +
    1.28 +	if(num_samples(0) > 0) {
    1.29 +		// discrete volume
    1.30 +		dx /= (float)num_samples(0);
    1.31 +		dy /= (float)num_samples(1);
    1.32 +		dz /= (float)num_samples(2);
    1.33 +	}
    1.34 +
    1.35 +	norm[0] = valuef(x + dx, y, z) - valuef(x - dx, y, z);
    1.36 +	norm[1] = valuef(x, y + dy, z) - valuef(x, y - dy, z);
    1.37 +	norm[2] = valuef(x, y, z + dz) - valuef(x, y, z - dz);
    1.38 +
    1.39 +	float len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]);
    1.40 +	if(len != 0.0) {
    1.41 +		norm[0] /= len;
    1.42 +		norm[1] /= len;
    1.43 +		norm[2] /= len;
    1.44 +	}
    1.45 +}
    1.46 +
    1.47 +void Volume::normali(float *norm, int x, int y, int z)
    1.48 +{
    1.49 +	int sz[3];
    1.50 +
    1.51 +	if((sz[0] = num_samples(0)) <= 0) {
    1.52 +		// if it's a continuous volume, just call normalf
    1.53 +		normalf(norm, x, y, z);
    1.54 +		return;
    1.55 +	}
    1.56 +	sz[1] = num_samples(1);
    1.57 +	sz[2] = num_samples(2);
    1.58 +
    1.59 +	int prevx = x <= 0 ? 0 : x;
    1.60 +	int nextx = x >= sz[0] - 1 ? sz[0] - 1 : x;
    1.61 +	int prevy = y <= 0 ? 0 : y;
    1.62 +	int nexty = y >= sz[1] - 1 ? sz[1] - 1 : y;
    1.63 +	int prevz = z <= 0 ? 0 : z;
    1.64 +	int nextz = z >= sz[2] - 1 ? sz[2] - 1 : z;
    1.65 +
    1.66 +	norm[0] = valuei(nextx, y, z) - valuei(prevx, y, z);
    1.67 +	norm[1] = valuei(x, nexty, z) - valuei(x, prevy, z);
    1.68 +	norm[2] = valuei(x, y, nextz) - valuei(x, y, prevz);
    1.69 +
    1.70 +	float len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]);
    1.71 +	if(len != 0.0) {
    1.72 +		norm[0] /= len;
    1.73 +		norm[1] /= len;
    1.74 +		norm[2] /= len;
    1.75 +	}
    1.76 +}
    1.77 +
    1.78 +// ---- VoxelVolume (discrete) implementation ----
    1.79 +VoxelVolume::VoxelVolume()
    1.80 +{
    1.81 +	size[0] = size[1] = size[2] = 0;
    1.82 +}
    1.83 +
    1.84 +bool VoxelVolume::load(const char *fname)
    1.85 +{
    1.86 +	FILE *fp = fopen(fname, "r");
    1.87 +	if(!fp) {
    1.88 +		fprintf(stderr, "failed to open file: %s: %s\n", fname, strerror(errno));
    1.89 +		return false;
    1.90 +	}
    1.91 +
    1.92 +	char buf[512];
    1.93 +	while(fgets(buf, sizeof buf, fp)) {
    1.94 +		char *line = strip_space(buf);
    1.95 +
    1.96 +		Image img;
    1.97 +		if(!img.load(line)) {
    1.98 +			slices.clear();
    1.99 +			return false;
   1.100 +		}
   1.101 +
   1.102 +		if(slices.empty()) {
   1.103 +			size[0] = img.width;
   1.104 +			size[1] = img.height;
   1.105 +		} else {
   1.106 +			if(img.width != size[0] || img.height != size[1]) {
   1.107 +				fprintf(stderr, "slice %d \"%s\" size mismatch (%dx%d, %dx%d expected)\n",
   1.108 +						(int)slices.size(), line, img.width, img.height, size[0], size[1]);
   1.109 +				slices.clear();
   1.110 +				return false;
   1.111 +			}
   1.112 +		}
   1.113 +
   1.114 +		slices.push_back(img);
   1.115 +		img.pixels = 0;	// otherwise the destructor will free it
   1.116 +	}
   1.117 +
   1.118 +	size[2] = slices.size();
   1.119 +	fclose(fp);
   1.120 +	return true;
   1.121 +}
   1.122 +
   1.123 +int VoxelVolume::num_samples(int dim) const
   1.124 +{
   1.125 +	return size[dim];
   1.126 +}
   1.127 +
   1.128 +static inline int clamp(int x, int low, int high)
   1.129 +{
   1.130 +	return x < low ? low : (x > high ? high : x);
   1.131 +}
   1.132 +
   1.133 +static inline float lookup(int x0, int y0, int x1, int y1, float tx, float ty,
   1.134 +		float *pixels, int width, int height)
   1.135 +{
   1.136 +	float v00, v01, v10, v11;
   1.137 +
   1.138 +	v00 = pixels[y0 * width + x0];
   1.139 +	v01 = pixels[y1 * width + x0];
   1.140 +	v10 = pixels[y0 * width + x1];
   1.141 +	v11 = pixels[y1 * width + x1];
   1.142 +
   1.143 +	float v0 = v00 + (v01 - v00) * ty;
   1.144 +	float v1 = v10 + (v11 - v10) * ty;
   1.145 +
   1.146 +	return v0 + (v1 - v0) * tx;
   1.147 +}
   1.148 +
   1.149 +float VoxelVolume::valuef(float x, float y, float z) const
   1.150 +{
   1.151 +	if(slices.empty()) {
   1.152 +		return 0.0f;
   1.153 +	}
   1.154 +
   1.155 +	float floor_x = floor(x);
   1.156 +	float ceil_x = ceil(x);
   1.157 +	float tx = x - floor_x;
   1.158 +
   1.159 +	float floor_y = floor(y);
   1.160 +	float ceil_y = ceil(y);
   1.161 +	float ty = y - floor_y;
   1.162 +
   1.163 +	float floor_z = floor(z);
   1.164 +	float ceil_z = ceil(z);
   1.165 +	float tz = z - floor_z;
   1.166 +
   1.167 +	int x0 = clamp(floor_x, 0, size[0] - 1);
   1.168 +	int x1 = clamp(ceil_x, 0, size[0] - 1);
   1.169 +
   1.170 +	int y0 = clamp(floor_y, 0, size[1] - 1);
   1.171 +	int y1 = clamp(ceil_y, 0, size[1] - 1);
   1.172 +
   1.173 +	int s0 = clamp(floor_z, 0, size[2] - 1);
   1.174 +	int s1 = clamp(ceil_z, 0, size[2] - 1);
   1.175 +
   1.176 +	float val_s0 = lookup(x0, y0, x1, y1, tx, ty, slices[s0].pixels, size[0], size[1]);
   1.177 +	float val_s1 = lookup(x0, y0, x1, y1, tx, ty, slices[s1].pixels, size[0], size[1]);
   1.178 +
   1.179 +	return val_s0 + (val_s1 - val_s0) * tz;
   1.180 +}
   1.181 +
   1.182 +float VoxelVolume::valuei(int x, int y, int z) const
   1.183 +{
   1.184 +	x = clamp(x, 0, size[0] - 1);
   1.185 +	y = clamp(y, 0, size[1] - 1);
   1.186 +	z = clamp(z, 0, size[2] - 1);
   1.187 +
   1.188 +	return slices[z].pixels[y * size[0] + x];
   1.189 +}
   1.190 +
   1.191 +static char *strip_space(char *s)
   1.192 +{
   1.193 +	while(*s && isspace(*s)) s++;
   1.194 +	if(!*s) return 0;
   1.195 +
   1.196 +	char *end = s + strlen(s) - 1;
   1.197 +	while(end > s && isspace(*end)) end--;
   1.198 +	end[1] = 0;
   1.199 +
   1.200 +	return s;
   1.201 +}