Tornado-Visualization/datenvisualisierung_sose2024/horizontalslicetocontourlinemapper.cpp

195 lines
9 KiB
C++
Executable file

#include "horizontalslicetocontourlinemapper.h"
#include <iostream>
#include <math.h>
HorizontalSliceToContourLineMapper::HorizontalSliceToContourLineMapper(){
std::cout << "CONTOUR MAPPER CONSTRUCTOR CALLED - creating " << this << std::endl;
magnitude = false;
}
HorizontalSliceToContourLineMapper::~HorizontalSliceToContourLineMapper() {
std::cout << "CONTOUR MAPPER DESTRUCTOR CALLED - deleting " << this << std::endl;
//delete[] isolist;
}
void HorizontalSliceToContourLineMapper::getSlice(float *source, int x, int y, int z, int current_z) {
// Sets up the variables
slice = source;
xs = x;
ys = y;
zs = z;
iz = current_z;
}
void HorizontalSliceToContourLineMapper::newZ(float* newsource, int z) {
// updates the mapper pointer and sets a new z-slice
slice = newsource;
iz = z;
}
void HorizontalSliceToContourLineMapper::setMagnitude(bool value) {
magnitude = value;
}
void HorizontalSliceToContourLineMapper::setIso(float* isos, int nums) {
isolist = new float[nums];
for (int i=0; i<nums; i++) {
isolist[i] = isos[i];
}
numIsos = nums;
}
int HorizontalSliceToContourLineMapper::marchingSquaresNum(float isoline, float v0, float v1,float v2,float v3) {
// The idea is to check which vertices lie above the isoline-value. Each vertex is equal to 2^n
// We do this because we can describe each of the 15 cases uniquely using a 4-bit binary number
char result = 0;
if (isoline<v0) {
result +=1;
} if (isoline<v1) {
result +=2;
} if (isoline<v2) {
result +=4;
} if (isoline<v3) {
result +=8;
}
return result;
}
float HorizontalSliceToContourLineMapper::WindSpeed(float x, float y, float z) {
return sqrt(x*x + y*y + z*z);
}
QVector<QVector3D> HorizontalSliceToContourLineMapper::mapSliceToContourLineSegments() {
QVector<QVector3D> vectors; // We store all of our points in a dynamic array as Vector3Ds
QVector3D vector1; // Vector 1 and 2 will then be connected as a line (using GL_LINES)
QVector3D vector2;
int squareCase = 0; // Initially I used char here, but I swapped it with int, because debugging was hell
float v0, v1, v2, v3, iso; // Initializing values we'll soon be needing
float z_value = float(iz)/(zs-1);
float x_value, y_value;
for (int i = 0; i < numIsos; i++) {
// We loop through all the isolines
//std::cout << "iso: " << isolist[i]; //we check what is in the isolist; a leftover from the debug times
for (int y=0; y< ys-1; y++) {
// Here we loop through all x and y values except for the last one, because we actually loop
// through squares with vertices x, x+1, y and y+1.
for (int x=0; x< xs-1; x++) {
// Watch out! The notation has been taken from the lecture
v3 = slice[3*((y+1)*xs+x)]; //top left
v2 = slice[3*((y+1)*xs+x+1)]; //top right
v1 = slice[3*(y*xs+x+1)]; //botom right
v0 = slice[3*(y*xs+x)]; //bottom left
if (magnitude == true) {
v3 = WindSpeed(slice[3*((y+1)*xs+x)], slice[3*((y+1)*xs+x)+1], slice[3*((y+1)*xs+x)+2]);
v2 = WindSpeed(slice[3*((y+1)*xs+x+1)], slice[3*((y+1)*xs+x+1)+1], slice[3*((y+1)*xs+x+1)+2]);
v1 = WindSpeed(slice[3*(y*xs+x+1)], slice[3*(y*xs+x+1)+1], slice[3*(y*xs+x+1)+2]);
v0 = WindSpeed(slice[3*(y*xs+x)], slice[3*(y*xs+x)+1], slice[3*(y*xs+x)+2]);
}
iso = isolist[i];
squareCase = marchingSquaresNum(iso, v0, v1, v2, v3);
// Viet found the amazing way of reducing the number of cases (before that I used switch x3)
// We use if-instructions because Switch doesn't allow for the or operation
// Lookuptable is nonetheless very mechanical
if (squareCase==1 || squareCase==14) {
x_value = float(x)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0));
vector1 = QVector3D(x_value,y_value,z_value);
x_value = float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0));
y_value = float(y)/(ys-1);
vector2 = QVector3D(x_value, y_value,z_value);
} else if (squareCase==2 || squareCase==13) {
x_value = float(x+1)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
vector1 = QVector3D(x_value,y_value,z_value);
x_value = float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0));
y_value = float(y)/(ys-1);
vector2 = QVector3D(x_value, y_value,z_value);
} else if (squareCase==3 || squareCase==12) {
x_value = float(x)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0));
vector1 = QVector3D(x_value,y_value,z_value);
x_value = float(x+1)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
vector2 = QVector3D(x_value,y_value,z_value);
} else if (squareCase==4 || squareCase==11) {
x_value = float(x+1)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
vector1 = QVector3D(x_value, y_value, z_value);
x_value = float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3));
y_value = float(y+1)/(ys-1);
vector2 = QVector3D(x_value,y_value,z_value);
} else if (squareCase==5) {
//Special case requires checking is the centre is positive
std::cout << 0.25*(v0+v1+v2+v3) << std::endl;
if (0.25*(v0+v1+v2+v3)>iso) {
std::cout << "Gi funkcias!" << std::endl;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
} else {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v3)/((ys-1)*(v2-v3)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
}
} else if (squareCase==10) {
//Special case requires checking is the centre is positive
std::cout << 0.25*(v0+v1+v2+v3) << std::endl;
if (0.25*(v0+v1+v2+v3)>iso) {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v3)/((ys-1)*(v2-v3)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
} else {
std::cout << "Gi funkcias!" << std::endl;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
}
} else if (squareCase==6 || squareCase==9) {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
} else if (squareCase==7 || squareCase==8) {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
} else {
// cases 0 and 15 are the ones where we draw no lines and they belong here
continue;
}
vectors << vector1 << vector2;
}
}
}
return vectors;
}