205 lines
6.2 KiB
C++
205 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#include "../../hpr/math.hpp"
|
|
#include "../../hpr/csg.hpp"
|
|
|
|
|
|
namespace hpr::csg
|
|
{
|
|
void prints(scalar point)
|
|
{
|
|
std::cout << point << std::endl;
|
|
}
|
|
class Lattice : public csg::Shape
|
|
{
|
|
|
|
public:
|
|
|
|
enum class System
|
|
{
|
|
Triclinic,
|
|
Monoclinic,
|
|
Orthorhombic,
|
|
Tetragonal,
|
|
Rhombohedral,
|
|
Hexagonal,
|
|
Cubic,
|
|
Unknown
|
|
};
|
|
|
|
enum class Type
|
|
{
|
|
Primitive,
|
|
BaseCentered,
|
|
BodyCentered,
|
|
FaceCentered,
|
|
Unknown
|
|
};
|
|
|
|
protected:
|
|
|
|
vec3 p_lengths;
|
|
vec3 p_angles;
|
|
Type p_type;
|
|
scalar p_radius;
|
|
darray<vec3> p_controlPoints;
|
|
|
|
public:
|
|
|
|
Lattice() = delete;
|
|
|
|
Lattice(const vec3& lengths, const vec3& angles, scalar radius, Type type) :
|
|
csg::Shape {},
|
|
p_lengths {lengths},
|
|
p_angles {angles},
|
|
p_radius {radius},
|
|
p_type {type}
|
|
{
|
|
generateControlPoints();
|
|
darray<csg::Shape> spheres;
|
|
for (const auto& point : controlPoints()) {
|
|
spheres.push(csg::sphere(point, p_radius));
|
|
print(point);
|
|
}
|
|
|
|
p_shape = csg::Compound(spheres).tshape();//csg::fuse({spheres.front()}, spheres.slice(spheres.begin() + 1, spheres.end())).tshape();
|
|
}
|
|
|
|
darray<vec3> controlPoints() const
|
|
{
|
|
return p_controlPoints;
|
|
}
|
|
|
|
vec3 lengths() const
|
|
{
|
|
return p_lengths;
|
|
}
|
|
|
|
vec3 angles() const
|
|
{
|
|
return p_angles;
|
|
}
|
|
|
|
void generateControlPoints()
|
|
{
|
|
if (p_type == Type::Unknown)
|
|
throw std::runtime_error("Unknown type of lattice");
|
|
p_controlPoints.resize(14);
|
|
//
|
|
vec3 ox {1, 0, 0};
|
|
vec3 oy {0, 1, 0};
|
|
vec3 oz {0, 0, 1};
|
|
vec3 ox1 = hpr::rotate(ox, oz, rad(-p_angles[2]));
|
|
p_controlPoints.push(vec3{0, 0, 0});
|
|
p_controlPoints.push(vec3{0, p_lengths[0], 0});
|
|
vec3 t1 = hpr::translate(p_controlPoints.back(), ox1 * p_lengths[1]);
|
|
p_controlPoints.push(t1);
|
|
p_controlPoints.push(hpr::translate(p_controlPoints.front(), ox1 * p_lengths[1]));
|
|
print(t1);
|
|
print(ox1);
|
|
scalar c1 = cos(rad(p_angles[2])), c2 = cos(rad(p_angles[1])), c3 = cos(rad(p_angles[0]));
|
|
scalar D1 = sqrt(det(mat3(
|
|
1, cos(rad(p_angles[2])), cos(rad(p_angles[1])),
|
|
cos(rad(p_angles[2])), 1, cos(rad(p_angles[0])),
|
|
cos(rad(p_angles[1])), cos(rad(p_angles[0])), 1)));
|
|
scalar volume = 1. / 6. * p_lengths[0] * p_lengths[1] * p_lengths[2] *
|
|
D1;
|
|
scalar s1 = sqrt(pow(p_lengths[0], 2) + pow(p_lengths[1], 2) - 2 *
|
|
p_lengths[0] * p_lengths[1] * cos(rad(p_angles[2])));
|
|
scalar s2 = sqrt(pow(p_lengths[1], 2) + pow(p_lengths[2], 2) - 2 *
|
|
p_lengths[1] * p_lengths[2] * cos(rad(p_angles[1])));
|
|
scalar s3 = sqrt(pow(p_lengths[0], 2) + pow(p_lengths[2], 2) - 2 *
|
|
p_lengths[0] * p_lengths[2] * cos(rad(p_angles[0])));
|
|
scalar area = 1. / 2. * p_lengths[0] * p_lengths[1] *
|
|
sqrt(det(mat2{1, cos(rad(p_angles[2])), cos(rad(p_angles[2])), 1}));
|
|
scalar h1 = 3 * volume / area;
|
|
scalar a1 = asin(h1 / p_lengths[2]);
|
|
scalar sh1 = sqrt(pow(p_lengths[2], 2) - pow(h1, 2));
|
|
scalar sh2 = p_lengths[2] * cos(rad(p_angles[0]));
|
|
scalar a2 = acos(sh2 / sh1);
|
|
|
|
vec3 ox2 = hpr::rotate(ox, oy, a1);
|
|
if (!isnan(a2))
|
|
ox2 = hpr::rotate(ox2, oz, a2);
|
|
print(ox2);
|
|
for (auto n = 0; n < 4; ++n)
|
|
p_controlPoints.push(hpr::translate(p_controlPoints[n], ox2 * p_lengths[2]));
|
|
|
|
/*p_controlPoints.push(vec3{p_lengths[0], p_lengths[1], 0});
|
|
p_controlPoints.push(vec3{p_lengths[0], 0, 0});
|
|
|
|
p_controlPoints.push(vec3{0, 0, p_lengths[2]});
|
|
p_controlPoints.push(vec3{0, p_lengths[1], p_lengths[2]});
|
|
p_controlPoints.push(vec3{p_lengths[0], p_lengths[1], p_lengths[2]});
|
|
p_controlPoints.push(vec3{p_lengths[0], 0, p_lengths[2]});
|
|
|
|
// central points on base faces
|
|
if (p_type == Type::BaseCentered || p_type == Type::FaceCentered)
|
|
{
|
|
for (int n = 0; n < 2; ++n)
|
|
{
|
|
vec3 center;
|
|
for (int k = 0; k < 4; ++k)
|
|
center += p_controlPoints[k + 4 * n];
|
|
p_controlPoints.push(center * 0.25);
|
|
}
|
|
}
|
|
|
|
// central point (center of mass)
|
|
if (p_type == Type::BodyCentered)
|
|
{
|
|
vec3 center;
|
|
for (const auto& point : p_controlPoints)
|
|
center += point;
|
|
p_controlPoints.push(center / p_controlPoints.size());
|
|
}
|
|
|
|
// central points on side faces
|
|
if (p_type == Type::FaceCentered)
|
|
{
|
|
for (int n = 0; n < 3; ++n)
|
|
{
|
|
vec3 center;
|
|
for (int k = 0; k < 2; ++k)
|
|
{
|
|
center += p_controlPoints[n + k];
|
|
center += p_controlPoints[n + k + 4];
|
|
}
|
|
p_controlPoints.push(center * 0.25);
|
|
}
|
|
vec3 center;
|
|
for (int n = 0; n < 2; ++n)
|
|
{
|
|
center += p_controlPoints[n * 3];
|
|
center += p_controlPoints[4 + n * 3];
|
|
}
|
|
p_controlPoints.push(center * 0.25);
|
|
}
|
|
|
|
mat4 trans = mat4::identity();
|
|
vec3 ox {1, 0, 0};
|
|
vec3 oy {0, 1, 0};
|
|
vec3 oz {0, 0, 1};
|
|
int n = 0;
|
|
for (auto& point : p_controlPoints)
|
|
{
|
|
if (n == 0 || n == 3)
|
|
{
|
|
++n;
|
|
continue;
|
|
}
|
|
trans.row(3, vec4(point, 0));
|
|
trans = hpr::rotate(trans, oz, -radians(90 - p_angles[2]));
|
|
if (n >= 4 && n <= 7)
|
|
{
|
|
trans = hpr::rotate(trans, ox, -radians(90 - p_angles[1]));
|
|
trans = hpr::rotate(trans, oy, -radians(90 - p_angles[0]));
|
|
}
|
|
point = vec3(trans.row(3)[0], trans.row(3)[1], trans.row(3)[2]);
|
|
++n;
|
|
}*/
|
|
|
|
}
|
|
};
|
|
|
|
} |