212 lines
5.8 KiB
C++
212 lines
5.8 KiB
C++
#include <glm/common.hpp>
|
|
#include <glm/ext/matrix_float4x4.hpp>
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/trigonometric.hpp>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <glm/glm.hpp>
|
|
#include <cstdint>
|
|
|
|
#include <utils/utils.hpp>
|
|
#include <coil/segment.hpp>
|
|
#include <coil/coil.hpp>
|
|
|
|
using glm::vec4;
|
|
using glm::vec3;
|
|
using glm::mat4;
|
|
using glm::radians;
|
|
using glm::rotate;
|
|
using glm::sin;
|
|
using glm::cos;
|
|
using glm::translate;
|
|
|
|
using std::endl;
|
|
using std::cout;
|
|
using std::cerr;
|
|
|
|
CoilSegment::CoilSegment(
|
|
Coil* coil,
|
|
uint16_t year,
|
|
uint16_t height,
|
|
int shift,
|
|
uint32_t sliceDetailization
|
|
):
|
|
coil(coil), year(year),
|
|
height(height), shift(shift),
|
|
sliceDetailization(sliceDetailization),
|
|
slicePointsAmount(sliceDetailization + 2),
|
|
//evil shit
|
|
leap(year % 4 == 0? year % 100 == 0? year % 400 == 0 : true : false) {
|
|
init();
|
|
// calculate();
|
|
}
|
|
|
|
void CoilSegment::init () {
|
|
verticesLength = getDaysAmount() * slicePointsAmount * FIELDS_IN_POINT;
|
|
vertices = (float *) malloc(verticesLength * sizeof(float));
|
|
if (vertices == NULL) {
|
|
cerr << "Allocation failed" << endl;
|
|
exit(-1);
|
|
}
|
|
calculate();
|
|
}
|
|
|
|
void CoilSegment::printVertices() {
|
|
for (uint16_t day = 0; day < getDaysAmount(); day ++) {
|
|
cout << "Day " << day << ", " <<
|
|
"x: " << vertices[FIELDS_IN_POINT * day + 0] << ", " <<
|
|
"y: " << vertices[FIELDS_IN_POINT * day + 1] << ", " <<
|
|
"z: " << vertices[FIELDS_IN_POINT * day + 2] << ", " <<
|
|
"r: " << vertices[FIELDS_IN_POINT * day + 3] << ", " <<
|
|
"g: " << vertices[FIELDS_IN_POINT * day + 4] << ", " <<
|
|
"b: " << vertices[FIELDS_IN_POINT * day + 5] << endl;
|
|
}
|
|
}
|
|
|
|
|
|
float *CoilSegment::calculateSlice() {
|
|
uint32_t size = slicePointsAmount * 3 * sizeof(float);
|
|
float *slice = (float *)malloc(size);
|
|
mat4 transform = mat4(1.);
|
|
transform = glm::scale(
|
|
transform,
|
|
vec3(
|
|
coil->getWidth(),
|
|
10,
|
|
1
|
|
)
|
|
);
|
|
// Start of a slice
|
|
slice[0] = cos(0);
|
|
slice[1] = sin(0);
|
|
slice[2] = 0;
|
|
|
|
float degreeByPoint = -180. / (sliceDetailization + 1);
|
|
|
|
for (uint32_t i = 1; i <= sliceDetailization; i ++) {
|
|
uint32_t offset = 3 * i;
|
|
|
|
slice[offset + 0] = round_to_precision(cos(radians(degreeByPoint * i)), 5);
|
|
slice[offset + 1] = round_to_precision(sin(radians(degreeByPoint * i)), 5);
|
|
slice[offset + 2] = 0;
|
|
}
|
|
|
|
// End of a slice
|
|
uint32_t endIndex = (size / sizeof(float) - 3);
|
|
slice[endIndex + 0] = round_to_precision(cos(radians(180.)), 5);
|
|
slice[endIndex + 1] = round_to_precision(sin(radians(180.)), 5);
|
|
slice[endIndex + 2] = 0;
|
|
|
|
return slice;
|
|
}
|
|
|
|
void CoilSegment::constructSegment(float *slice) {
|
|
float degreesPerDay = 360.f / getDaysAmount();
|
|
|
|
for (uint32_t day = 0; day < getDaysAmount(); day ++) {
|
|
float daysDegree = day * degreesPerDay;
|
|
vec3 daysPosition = vec3(
|
|
cos(radians(daysDegree)) * coil->getRadius(),
|
|
height * (float)day/getDaysAmount() + shift * height,
|
|
sin(radians(daysDegree)) * coil->getRadius()
|
|
);
|
|
|
|
mat4 transform = mat4(1.);
|
|
|
|
transform = translate(
|
|
transform,
|
|
daysPosition
|
|
);
|
|
|
|
transform = rotate(
|
|
transform,
|
|
-radians(daysDegree),
|
|
vec3(
|
|
0.0,
|
|
1.0,
|
|
0.0
|
|
)
|
|
);
|
|
|
|
for (uint32_t slicePoint = 0; slicePoint < slicePointsAmount; slicePoint ++) {
|
|
uint32_t slicePointOffset = 3 * slicePoint;
|
|
vec4 point(
|
|
slice[slicePointOffset + 0],
|
|
slice[slicePointOffset + 1],
|
|
slice[slicePointOffset + 2],
|
|
1
|
|
);
|
|
|
|
point = transform * point;
|
|
uint64_t currentPointOffset = day * slicePointsAmount * FIELDS_IN_POINT + slicePointOffset*2;
|
|
vertices[currentPointOffset + 0] = point.x;
|
|
vertices[currentPointOffset + 1] = point.y;
|
|
vertices[currentPointOffset + 2] = point.z;
|
|
|
|
vertices[currentPointOffset + 3] = (float)slicePoint / slicePointsAmount;
|
|
vertices[currentPointOffset + 4] = 0;
|
|
vertices[currentPointOffset + 5] = 0;
|
|
}
|
|
}
|
|
free(slice);
|
|
}
|
|
// Sample layout of 2 slices with 3 points.
|
|
// |x |y |z |r |g |b | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
|
// | point | point | point | point | point | point |
|
|
// | slice | slice |
|
|
//
|
|
void CoilSegment::calculate() {
|
|
float *slice = calculateSlice();
|
|
|
|
constructSegment(slice);
|
|
}
|
|
|
|
float *CoilSegment::getVertices() { return vertices; }
|
|
|
|
uint64_t CoilSegment::getVerticesLength() { return verticesLength; }
|
|
|
|
uint64_t CoilSegment::getVerticesAmount() { return verticesLength / FIELDS_IN_POINT; }
|
|
|
|
uint16_t CoilSegment::getYear() { return year; }
|
|
|
|
void CoilSegment::exportSliceToCSV(float *slice) {
|
|
cout << "Exporting slice to csv" << endl;
|
|
std::ofstream outFile("./slice_export.csv");
|
|
|
|
outFile << "x,y,z" << endl;
|
|
|
|
for (uint32_t i = 0; i < slicePointsAmount; i ++) {
|
|
uint32_t offset = FIELDS_IN_POINT * i;
|
|
outFile
|
|
<< slice[offset + 0] << ","
|
|
<< slice[offset + 1] << ",0" << endl;
|
|
}
|
|
}
|
|
|
|
void CoilSegment::exportSegmentToCsv() {
|
|
cout << "Exporting segment to csv" << endl;
|
|
std::ofstream outFile("./segment_export.csv");
|
|
|
|
outFile << "x,y,z" << endl;
|
|
|
|
for (uint16_t day = 0; day < getDaysAmount(); day ++) {
|
|
uint64_t dayOffset = day * slicePointsAmount * FIELDS_IN_POINT;
|
|
|
|
for (uint32_t point_in_slice = 0; point_in_slice < slicePointsAmount; point_in_slice ++) {
|
|
uint32_t sliceOffset = point_in_slice * FIELDS_IN_POINT;
|
|
outFile << vertices[dayOffset + sliceOffset + 0] << ","
|
|
<< vertices[dayOffset + sliceOffset + 1] << ","
|
|
<< vertices[dayOffset + sliceOffset + 2] << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16_t CoilSegment::getDaysAmount() { return leap? 366 : 365; }
|
|
|
|
bool const CoilSegment::isLeap() { return leap; }
|
|
|
|
uint32_t CoilSegment::getSliceDetailization() { return sliceDetailization; }
|
|
|
|
uint32_t CoilSegment::getSlicePointsAmount() { return sliceDetailization + 2; } |