Program Listing for File shell.cc¶
↰ Return to documentation for file (src/shell.cc
)
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* The ENVE project *
* *
* Copyright (c) 2020, Davide Stocco and Enrico Bertolazzi. *
* *
* The ENVE project and its components are supplied under the terms of *
* the open source BSD 3-Clause License. The contents of the ENVE *
* project and its components may not be copied or disclosed except in *
* accordance with the terms of the BSD 3-Clause License. *
* *
* URL: https://opensource.org/licenses/BSD-3-Clause *
* *
* Davide Stocco *
* Department of Industrial Engineering *
* University of Trento *
* e-mail: davide.stocco@unitn.it *
* *
* Enrico Bertolazzi *
* Department of Industrial Engineering *
* University of Trento *
* e-mail: enrico.bertolazzi@unitn.it *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include "enve.hh"
using namespace acme;
namespace enve
{
/*\
| _ _ _
| ___| |__ ___| | |
| / __| '_ \ / _ \ | |
| \__ \ | | | __/ | |
| |___/_| |_|\___|_|_|
|
\*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
shell::shell(
size_t size,
real Rx,
real Mx,
real Ry,
real My,
real Ly
)
: m_shape(std::make_shared<shape>(Rx, Mx, Ry, My, Ly)),
m_bbox(std::make_shared<aabb>())
{
this->m_affine.matrix() = IDENTITY_MAT4;
this->resize(size);
this->updateBBox();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::resize(
size_t size
)
{
#define CMD "enve::shell::resize(...): "
ENVE_ASSERT(size > size_t(0),
CMD "negative ribs number detected.");
// Resize the contact point, friction and normal vectors
for (size_t i = 0; i < this->m_candidates.size(); ++i)
{this->m_candidates[i].clear();}
this->m_ribs.clear(); this->m_ribs.reserve(200);
this->m_out.clear(); this->m_out.reserve(200);
this->m_candidates.clear(); this->m_candidates.reserve(200);
this->m_candidates.resize(size);
for (size_t i = 0; i < size; ++i)
{this->m_candidates[i].reserve(200);}
// Locate the disks
real shellWidth = this->m_shape->surfaceWidth();
real ribW = real(2.0) * shellWidth / size;
real ribR, ribA;
real ribY = -shellWidth - ribW / real(2.0);
for (size_t i = 0; i < size; ++i)
{
ribY += ribW;
ribR = this->m_shape->surfaceRadius(ribY);
ribA = this->m_shape->surfaceAngle(ribY);
ENVE_ASSERT(ribR > size_t(0),
CMD "negative rib radius detected.");
ENVE_ASSERT(ribR == ribR,
CMD "NaN rib radius detected.");
ENVE_ASSERT(ribA == ribA,
CMD "NaN rib angle detected.");
this->m_ribs.emplace_back(i, ribR, ribY, ribW, ribA);
}
#undef CMD
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
size_t
shell::size(void)
const
{
return this->m_ribs.size();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*\
| _
| ___| |__ __ _ _ __ ___
| / __| '_ \ / _` | '_ \ / _ \
| \__ \ | | | (_| | |_) | __/
| |___/_| |_|\__,_| .__/ \___|
| |_|
\*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::surfaceMaxRadius(void)
const
{
return this->m_shape->surfaceMaxRadius();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::surfaceMaxWidth(void)
const
{
return this->m_shape->surfaceMaxWidth();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::surfaceWidth(void)
const
{
return this->m_shape->surfaceWidth();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool
shell::checkWidthBound(
real y
)
const
{
return this->m_shape->checkWidthBound(y);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::surfaceRadius(
real y
)
const
{
return this->m_shape->surfaceRadius(y);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::surfaceDerivative(
real y,
real tolerance
)
const
{
return this->m_shape->surfaceDerivative(y, tolerance);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::surfaceAngle(
real y,
real tolerance
)
const
{
return this->m_shape->surfaceAngle(y, tolerance);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::ribRadius(
size_t i
)
const
{
return this->m_ribs[i].radius();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
point
shell::ribCenter(
size_t i
)
const
{
return this->m_ribs[i].center();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::ribWidth(
size_t i
)
const
{
return this->m_ribs[i].width();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
real
shell::ribAngle(
size_t i
)
const
{
return this->m_ribs[i].angle();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*\
| __ __ _
| __ _ / _|/ _(_)_ __ ___
| / _` | |_| |_| | '_ \ / _ \
| | (_| | _| _| | | | | __/
| \__,_|_| |_| |_|_| |_|\___|
|
\*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::translate(
vec3 const & vector
)
{
this->m_affine.translate(vector);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vec3
shell::translation(void)
const
{
return this->m_affine.translation();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::rotate(
real angle,
vec3 const & axis
)
{
this->m_affine.rotate(angleaxis(angle, axis));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mat3
shell::rotation(void)
const
{
return this->m_affine.rotation();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mat3
shell::linear(void)
const
{
return this->m_affine.linear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::transform(
affine const & pose
)
{
this->checkTransformation(pose);
this->m_affine = pose;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
affine const &
shell::transformation(void)
const
{
return this->m_affine;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool
shell::checkTransformation(
mat4 const & pose,
real tolerance
)
const
{
if (std::abs(pose.determinant() - real(1.0)) < tolerance)
{return true;}
else
{return false;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool
shell::checkTransformation(
affine const & pose,
real tolerance
)
const
{
return this->checkTransformation(pose.matrix(), tolerance);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vec3
shell::x(void)
const
{
return this->m_affine.linear().col(0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vec3
shell::y(void)
const
{
return this->m_affine.linear().col(1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vec3
shell::z(void)
const
{
return this->m_affine.linear().col(2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::eulerAngles(
vec3 & angles
)
const
{
angles = this->m_affine.linear().eulerAngles(2, 0, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*\
| _ _
| __ _ __ _| |__ | |__
| / _` |/ _` | '_ \| '_ \
| | (_| | (_| | |_) | |_) |
| \__,_|\__,_|_.__/|_.__/
|
\*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::shared_ptr<aabb>
shell::bbox(void)
const
{
return this->m_bbox;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::updateBBox(void)
{
real radius = this->m_shape->surfaceMaxRadius();
point origin(this->m_affine.translation());
point extrema(radius, radius, radius);
this->m_bbox->min() = origin - extrema;
this->m_bbox->max() = origin + extrema;
this->m_bbox->updateMaxMin();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*\
| _
| ___ ___| |_ _ _ _ __
| / __|/ _ \ __| | | | '_ \
| \__ \ __/ |_| |_| | |_) |
| |___/\___|\__|\__,_| .__/
| |_|
\*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool
shell::setup(
ground::mesh const & ground,
affine const & pose,
std::string const method
)
{
#define CMD "enve::shell::setup(...): "
// Set the new reference frame
this->transform(pose);
this->updateBBox();
// Local intersected triangles vector
triangleground::vecptr local_ground;
local_ground.reserve(200);
ground.intersection(this->m_bbox, local_ground);
// End setup if there are no intersections
if (local_ground.size() < size_t(1))
{
for (size_t i = 0; i < this->size(); ++i)
{this->m_ribs[i].envelop(pose, this->m_out[i]);}
return false;
}
else
{
// Calculate ribs candidates to speed up calculations
if (method == "geometric")
{
this->refineIntersection(
ground,
local_ground,
local_ground.size() > integer(3)
);
}
// Perform intersection on all ribs
bool out = false;
for (size_t i = 0; i < this->size(); ++i)
{out = this->m_ribs[i].envelop(this->m_candidates[i], pose, method, this->m_out[i]) || out;}
return out;
}
#undef CMD
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool
shell::setup(
ground::flat const & ground,
affine const & pose,
std::string const method
)
{
#define CMD "enve::shell::setup(...): "
// Set the new reference frame
this->transform(pose);
this->updateBBox();
// Perform intersection on all ribs
bool out = false;
for (size_t i = 0; i < this->size(); ++i)
{out = this->m_ribs[i].envelop(ground, pose, method, this->m_out[i]);}
return out;
#undef CMD
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*\
| _ _
| ___ ___ _ __ | |_ __ _ ___| |_
| / __/ _ \| '_ \| __/ _` |/ __| __|
| | (_| (_) | | | | || (_| | (__| |_
| \___\___/|_| |_|\__\__,_|\___|\__|
|
\*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactPoint(
point & point
)
const
{
point = (ZEROS_VEC3);
size_t size = this->size();
real volume_sum = 0.0;
this->contactVolume(volume_sum);
if (volume_sum < EPSILON_HIGH)
{
for (size_t i = 0; i < size; ++i)
{point += this->m_out[i].point;}
point /= size;
}
else
{
for (size_t i = 0; i < size; ++i)
{point += this->m_out[i].point*this->m_out[i].volume;}
point /= volume_sum;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactPoint(
size_t i,
point & point
)
const
{
point = this->m_out[i].point;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactPoint(
std::vector<point> & point
)
const
{
size_t size = this->size();
point.resize(size);
for (size_t i = 0; i < size; ++i)
{point[i] = this->m_out[i].point; }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactNormal(
vec3 & normal
)
const
{
normal = ZEROS_VEC3;
size_t size = this->size();
real volume;
this->contactVolume(volume);
if (volume < EPSILON_HIGH)
{
for (size_t i = 0; i < size; ++i)
{normal += this->m_out[i].normal;}
normal /= size;
normal.normalize();
}
else
{
for (size_t i = 0; i < size; ++i)
{normal += this->m_out[i].normal*this->m_out[i].volume;}
normal /= volume;
normal.normalize();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactNormal(
size_t i,
vec3 & normal
)
const
{
normal = this->m_out[i].normal;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactNormal(
std::vector<vec3> & normal
)
const
{
size_t size = this->size();
normal.resize(size);
for (size_t i = 0; i < size; ++i)
{normal[i] = this->m_out[i].normal;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactFriction(
real & friction
)
const
{
friction = 0.0;
size_t size = this->size();
real volume_sum = 0.0;
this->contactVolume(volume_sum);
if (volume_sum < EPSILON_HIGH)
{
for (size_t i = 0; i < size; ++i)
{friction += this->m_out[i].friction;}
friction /= size;
}
else
{
for (size_t i = 0; i < size; ++i)
{friction += this->m_out[i].friction*this->m_out[i].volume;}
friction /= volume_sum;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactFriction(
size_t i,
real & friction
)
const
{
friction = this->m_out[i].friction;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactFriction(
std::vector<real> & friction
)
const
{
size_t size = this->size();
friction.resize(size);
for (size_t i = 0; i < size; ++i)
{friction[i] = this->m_out[i].friction;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactDepth(
real & depth
)
const
{
depth = 0.0;
size_t size = this->size();
real volume_sum = 0.0;
this->contactVolume(volume_sum);
if (volume_sum < EPSILON_HIGH)
{
depth = volume_sum / size;
}
else
{
for (size_t i = 0; i < size; ++i)
{depth += this->m_out[i].depth*this->m_out[i].volume;}
depth /= volume_sum;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactDepth(
size_t i,
real & depth
)
const
{
depth = this->m_out[i].depth;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactDepth(
std::vector<real> & depth
)
const
{
size_t size = this->size();
depth.resize(size);
for (size_t i = 0; i < size; ++i)
{depth[i] = this->m_out[i].depth;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactArea(
real & area
)
const
{
area = 0.0;
for (size_t i = 0; i < this->size(); ++i)
{area += this->m_out[i].friction;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactArea(
size_t i,
real & area
)
const
{
area = this->m_out[i].area;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactArea(
std::vector<real> & area
)
const
{
size_t size = this->size();
area.resize(size);
for (size_t i = 0; i < size; ++i)
{area[i] = this->m_out[i].area;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactVolume(
real & volume
)
const
{
volume = 0.0;
for (size_t i = 0; i < this->size(); ++i)
{volume += this->m_out[i].volume;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactVolume(
size_t i,
real & volume
)
const
{
volume = this->m_out[i].volume;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactVolume(
std::vector<real> & volume
)
const
{
size_t size = this->size();
volume.resize(size);
for (size_t i = 0; i < size; ++i)
{volume[i] = this->m_out[i].volume;}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactPointAffine(
affine & pose
)
const
{
point point;
vec3 normal;
this->contactPoint(point);
this->contactNormal(normal);
vec3 x_vec((this->y().cross(normal)).normalized());
vec3 y_vec((normal.cross(x_vec)).normalized());
pose.matrix()
<< x_vec, y_vec, normal, point,
vec4(0.0, 0.0, 0.0, 1.0).transpose();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactPointAffine(
size_t i,
affine & pose
)
const
{
vec3 x_vec((this->y().cross(this->m_out[i].normal)).normalized());
vec3 y_vec((this->m_out[i].normal.cross(x_vec)).normalized());
pose.matrix()
<< x_vec, y_vec, this->m_out[i].normal, this->m_out[i].point,
vec4(0.0, 0.0, 0.0, 1.0).transpose();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::contactPointAffine(
std::vector<affine> & pose
)
const
{
for (size_t i = 0; i < this->size(); ++i)
{this->contactPointAffine(i, pose[i]);}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::relativeAngles(
vec3 & angles
)
const
{
affine pose;
this->contactPointAffine(pose);
mat3 rotation(pose.linear().transpose() * this->m_affine.linear());
angles = rotation.eulerAngles(2, 0, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::relativeAngles(
size_t i,
vec3 & angles
)
const
{
affine pose;
this->contactPointAffine(i, pose);
mat3 rotation(pose.linear().transpose() * this->m_affine.linear());
angles = rotation.eulerAngles(2, 0, 1);
angles.x() -= this->m_ribs[i].angle();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::relativeAngles(
std::vector<vec3> & angles
)
const
{
for (size_t i = 0; i < this->size(); ++i)
{this->relativeAngles(i, angles[i]);}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::print(
out_stream & os
)
const
{
point cpoint;
this->contactPoint(cpoint);
vec3 normal;
this->contactNormal(normal);
real friction = 0.0;
this->contactFriction(friction);
real depth = 0.0;
this->contactDepth(depth);
real area = 0.0;
this->contactArea(area);
real volume = 0.0;
this->contactVolume(volume);
vec3 relative_angles;
this->relativeAngles(relative_angles);
affine pose;
this->contactPointAffine(pose);
size_t size = this->size();
std::vector<point> point_vec;
this->contactPoint(point_vec);
std::vector<vec3> normal_vec;
this->contactNormal(normal_vec);
std::vector<real> friction_vec(size);
this->contactFriction(friction_vec);
std::vector<real> depth_vec(size);
this->contactDepth(depth_vec);
std::vector<real> area_vec(size);
this->contactArea(area_vec);
std::vector<real> volume_vec(size);
this->contactVolume(volume_vec);
std::vector<affine> pose_vec(size);
this->contactPointAffine(pose_vec);
std::vector<vec3> relative_angles_vec(size);
this->relativeAngles(relative_angles_vec);
vec3 euler_angles;
this->eulerAngles(euler_angles);
os << " ------------ SHELL PRINT ------------" << std::endl
<< std::endl;
this->m_shape->print(os);
os << "Ribs info:" << std::endl;
for (size_t i = 0; i < relative_angles_vec.size(); ++i)
{
os << "Rib " << i << " : C = " << this->m_ribs[i].center()
<< " R = " << this->m_ribs[i].radius() << " m" << std::endl
<< " W = " << this->m_ribs[i].width() << " m" << std::endl
<< " A = " << this->m_ribs[i].angle() << " rad" << std::endl;
}
os << "Contact parameters:" << std::endl
<< "Shell maximum radius" << std::endl
<< "R = " << this->m_shape->surfaceMaxRadius() << " m" << std::endl
<< "Camber angle" << std::endl
<< "Γ = " << euler_angles.y() / PI << "pi rad" << std::endl
<< "Rotation angle" << std::endl
<< "ß = " << euler_angles.z() / PI << "pi rad" << std::endl
<< "Yaw angle" << std::endl
<< "α = " << euler_angles.x() / PI << "pi rad" << std::endl
<< "Contact point (absolute reference frame)" << std::endl
<< "P = " << cpoint.transpose() << std::endl
<< "Contact point (absolute reference frame)" << std::endl;
for (size_t i = 0; i < point_vec.size(); ++i)
{os << "Rib " << i << " - P = " << point_vec[i].transpose() << " m" << std::endl;}
os << "Contact normal (absolute reference frame)" << std::endl
<< "N = " << normal.transpose() << std::endl
<< "Contact normal vector (absolute reference frame)" << std::endl;
for (size_t i = 0; i < normal_vec.size(); ++i)
{os << "Rib " << i << " - N = " << normal_vec[i].transpose() << std::endl;}
os << "Contact point friction" << std::endl
<< "f = " << friction << std::endl
<< "Contact point friction vector" << std::endl;
for (size_t i = 0; i < friction_vec.size(); ++i)
{os << "Rib " << i << " - f = " << friction_vec[i] << std::endl;}
os << "Contact depth (on average point)" << std::endl
<< "d = " << depth << " m" << std::endl
<< "Contact depth vector" << std::endl;
for (size_t i = 0; i < depth_vec.size(); ++i)
{os << "Rib " << i << " - d = " << depth_vec[i] << " m" << std::endl;}
os << "Contact area (total)" << std::endl
<< "A = " << area << " m^2" << std::endl
<< "Contact area vector" << std::endl;
for (size_t i = 0; i < area_vec.size(); ++i)
{os << "Rib " << i << " - A = " << area_vec[i] << " m^2" << std::endl;}
os << "Contact volume (total)" << std::endl
<< "V = " << volume << " m^3" << std::endl
<< "Contact volume vector" << std::endl;
for (size_t i = 0; i < volume_vec.size(); ++i)
{os << "Rib " << i << " - V = " << volume_vec[i] << " m^3" << std::endl;}
os << "Shell reference frame" << std::endl
<< this->m_affine.matrix() << std::endl
<< "Local contact point reference frame" << std::endl
<< pose.matrix() << std::endl
<< "Relative pose angles" << std::endl
<< "[Γ ß α]' = " << relative_angles.transpose() / PI << "pi rad" << std::endl
<< "Ribs relative pose angles" << std::endl;
for (size_t i = 0; i < relative_angles_vec.size(); ++i)
{os << "Rib " << i << " - [Γ ß α]' = " << relative_angles_vec[i].transpose() / PI << "pi rad" << std::endl;}
os << std::endl;
os << " ------------ END ------------" << std::endl
<< std::endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
shell::refineIntersection(
ground::mesh const & ground,
triangleground::vecptr const & local_ground,
bool refine
)
{
size_t size = this->size();
std::vector<real> y(size);
for (size_t i = 0; i < size; ++i)
{
if (!this->m_candidates[i].empty())
{this->m_candidates[i].clear();}
y[i] = this->m_ribs[i].center().y();
}
// Create shell middle plane
plane mid_plane(this->translation(), this->y());
mid_plane.normalize();
// Iterate on triangles
real d0, d1, d2, sum;
for (size_t i = 0; i < local_ground.size(); ++i)
{
// Calculate distance of i-th triangle
d0 = mid_plane.signedDistance(ground[i]->vertex(0));
d1 = mid_plane.signedDistance(ground[i]->vertex(1));
d2 = mid_plane.signedDistance(ground[i]->vertex(2));
// Iterate on ribs
for (size_t j = 0; j < size; ++j)
{
// Workaround for skip advanced ribs refinement
if (!refine)
{
this->m_candidates[j].push_back(ground[i]);
continue;
}
// Calculate sign of j-th rib distance
sum = real((real(0.0) < (d0-y[j])) - ((d0-y[j]) < real(0.0))) +
real((real(0.0) < (d1-y[j])) - ((d1-y[j]) < real(0.0))) +
real((real(0.0) < (d2-y[j])) - ((d2-y[j]) < real(0.0)));
// Fill candidates list
if (real(-3.0) < sum && sum < real(3.0))
{this->m_candidates[j].push_back(ground[i]);}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
} // namespace enve
#endif