Removed the passing of the mass through parameters. Now the mass is

determined by the area of the polygon
This commit is contained in:
Karma Riuk 2023-05-19 16:31:38 +02:00
parent ce0cf102ba
commit 89e250dcba
4 changed files with 93 additions and 70 deletions

View File

@ -3,29 +3,36 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#define MASS_COEF .1
static double to_rad(double angle_in_deg) { static double to_rad(double angle_in_deg) {
static double PI_180 = M_PI / 180; static double PI_180 = M_PI / 180;
return angle_in_deg * PI_180; return angle_in_deg * PI_180;
} }
polygon poly_generate::rectangle( polygon
double width, double height, double mass, std::string label) { poly_generate::rectangle(double width, double height, std::string label) {
assert(width > 0); assert(width > 0);
assert(height > 0); assert(height > 0);
static const double one_over_twelve = 1. / 12; static const double one_over_twelve = 1. / 12;
return polygon{{0, 0},
double mass = MASS_COEF * width * height;
return polygon{
{0, 0},
0, 0,
{{-width / 2, -height / 2}, {{-width / 2, -height / 2},
{-width / 2, height / 2}, {-width / 2, height / 2},
{width / 2, height / 2}, {width / 2, height / 2},
{width / 2, -height / 2}}, {width / 2, -height / 2}},
one_over_twelve * mass * (width * width + height * height), one_over_twelve * mass * (width * width + height * height),
mass, mass,
label}; label};
} }
polygon poly_generate::triangle( polygon poly_generate::triangle(
double side1, double side2, double angle, double mass, std::string label) { double side1, double side2, double angle, std::string label
) {
assert(side1 > 0); assert(side1 > 0);
assert(side2 > 0); assert(side2 > 0);
static const double one_over_36 = 1. / 36; static const double one_over_36 = 1. / 36;
@ -33,16 +40,21 @@ polygon poly_generate::triangle(
base = side1; base = side1;
height = side2 * std::sin(to_rad(angle)); height = side2 * std::sin(to_rad(angle));
vec2d points[] = { vec2d points[] = {
{0, 0}, {side1, 0}, {side2 * std::cos(to_rad(angle)), height}}; {0, 0},
{side1, 0},
{side2 * std::cos(to_rad(angle)), height}};
vec2d barycenter = { vec2d barycenter = {
(points[0].x + points[1].x + points[2].x) / 3, (points[0].x + points[1].x + points[2].x) / 3,
(points[0].y + points[1].y + points[2].y) / 3, (points[0].y + points[1].y + points[2].y) / 3,
}; };
double mass = MASS_COEF * base * height * .5;
for (unsigned int i = 0; i < 3; ++i) for (unsigned int i = 0; i < 3; ++i)
points[i] -= barycenter; points[i] -= barycenter;
return polygon{{0, 0}, return polygon{
{0, 0},
0, 0,
{std::begin(points), std::end(points)}, {std::begin(points), std::end(points)},
one_over_36 * mass * base * std::pow(height, 3), one_over_36 * mass * base * std::pow(height, 3),
@ -50,28 +62,6 @@ polygon poly_generate::triangle(
label}; label};
} }
polygon poly_generate::regular(
double radius, uint n_sides, double mass, std::string label) {
assert(n_sides > 2);
std::vector<vec2d> points;
label += " ";
label += n_sides;
points.reserve(n_sides);
double theta = 2 * M_PI / n_sides;
for (uint i = 0; i < n_sides; i++)
points.push_back({radius * cos(i * theta), radius * sin(i * theta)});
double l = vec2d::norm(points[1] - points[0]);
double sin_, cos_;
sincos(M_PI / n_sides, &sin_, &cos_);
double cot = cos_ / sin_;
double inertia = mass * l * l / 24 * (1 + 3 * cot * cot);
return polygon{{0, 0}, 0, points, inertia, mass, label};
}
static double area_of_triangle(vec2d& a, vec2d& b, vec2d& c) { static double area_of_triangle(vec2d& a, vec2d& b, vec2d& c) {
return std::abs(vec2d::cross(c - a, b - a)) / 2; return std::abs(vec2d::cross(c - a, b - a)) / 2;
} }
@ -80,23 +70,46 @@ static double area_of_poly(std::vector<vec2d>& points, vec2d& centroid) {
double area = 0; double area = 0;
for (int i = 0; i < points.size(); ++i) for (int i = 0; i < points.size(); ++i)
area += area_of_triangle( area += area_of_triangle(
centroid, points[i], points[(i + 1) % points.size()]); centroid,
points[i],
points[(i + 1) % points.size()]
);
return area; return area;
} }
static double intertia_of_polygon_subtriangle(double total_mass, polygon poly_generate::regular(double radius, uint n_sides, std::string label) {
double total_area, assert(n_sides > 2);
vec2d& centroid, std::vector<vec2d> points;
vec2d& p1, points.reserve(n_sides);
vec2d& p2) { double theta = 2 * M_PI / n_sides;
for (uint i = 0; i < n_sides; i++)
points.push_back({radius * cos(i * theta), radius * sin(i * theta)});
vec2d centroid = {0, 0};
double mass = MASS_COEF * area_of_poly(points, centroid);
double l = vec2d::norm(points[1] - points[0]);
double sin_, cos_;
sincos(M_PI / n_sides, &sin_, &cos_);
double cot = cos_ / sin_;
double inertia = mass * l * l / 24 * (1 + 3 * cot * cot);
return polygon{centroid, 0, points, inertia, mass, label};
}
static double intertia_of_polygon_subtriangle(
double total_mass, double total_area, vec2d& centroid, vec2d& p1, vec2d& p2
) {
double partial_area = area_of_triangle(centroid, p1, p2); double partial_area = area_of_triangle(centroid, p1, p2);
double partial_mass = total_mass * partial_area / total_area; double partial_mass = total_mass * partial_area / total_area;
vec2d CA = p1 - centroid; vec2d CA = p1 - centroid;
vec2d AB = p2 - p1; vec2d AB = p2 - p1;
return partial_mass / 2 * return partial_mass / 2
(vec2d::norm2(AB) / 3 + vec2d::dot(AB, CA) + vec2d::norm2(CA)); * (vec2d::norm2(AB) / 3 + vec2d::dot(AB, CA) + vec2d::norm2(CA));
} }
static vec2d centroid(std::vector<vec2d>& points) { static vec2d centroid(std::vector<vec2d>& points) {
@ -107,15 +120,20 @@ static vec2d centroid(std::vector<vec2d>& points) {
return vec2d{x, y} / points.size(); return vec2d{x, y} / points.size();
} }
polygon poly_generate::general( polygon poly_generate::general(std::vector<vec2d> points, std::string label) {
std::vector<vec2d> points, double mass, std::string label) {
double intertia = 0; double intertia = 0;
vec2d c = centroid(points); vec2d c = centroid(points);
double area = area_of_poly(points, c); double area = area_of_poly(points, c);
double mass = MASS_COEF * area;
for (int i = 0; i < points.size(); ++i) for (int i = 0; i < points.size(); ++i)
intertia += intertia_of_polygon_subtriangle( intertia += intertia_of_polygon_subtriangle(
mass, area, c, points[i], points[(i + 1) % points.size()]); mass,
area,
c,
points[i],
points[(i + 1) % points.size()]
);
for (auto& p : points) // set the center of the polygon to it's centroid for (auto& p : points) // set the center of the polygon to it's centroid
p -= c; p -= c;

View File

@ -7,31 +7,21 @@
namespace poly_generate { namespace poly_generate {
polygon rectangle(double width, polygon
double height, rectangle(double width, double height, std::string label = "rectangle");
double mass = 1,
std::string label = "rectangle");
inline polygon square( inline polygon square(double width, std::string label = "square") {
double width, double mass = 1, std::string label = "square") {
assert(width > 0); assert(width > 0);
return rectangle(width, width, mass, label); return rectangle(width, width, label);
}; };
polygon triangle(double side1, polygon triangle(
double side2, double side1, double side2, double angle, std::string label = "triangle"
double angle, );
double mass = 1,
std::string label = "triangle");
polygon regular(double radius, polygon regular(double radius, uint n_sides, std::string label = "regular");
uint n_sides,
double mass = 1,
std::string label = "regular");
polygon general(std::vector<vec2d> points, polygon general(std::vector<vec2d> points, std::string label = "general");
double mass = 1,
std::string label = "general");
}; // namespace poly_generate }; // namespace poly_generate
#endif #endif

View File

@ -22,22 +22,27 @@ void polygons_init_state() {
int wall_thickness = 50; int wall_thickness = 50;
uint n = 0; uint n = 0;
// north wall // north wall
polygons[n++] = poly_generate::rectangle(width, wall_thickness, INFINITY) polygons[n++] = poly_generate::rectangle(width, wall_thickness)
.set_mass(INFINITY)
.set_center({width / 2., -wall_thickness / 2.}); .set_center({width / 2., -wall_thickness / 2.});
// south wall // south wall
polygons[n++] = poly_generate::rectangle(width, wall_thickness, INFINITY) polygons[n++] = poly_generate::rectangle(width, wall_thickness)
.set_mass(INFINITY)
.set_center({width / 2., height + wall_thickness / 2.}); .set_center({width / 2., height + wall_thickness / 2.});
// west wall // west wall
polygons[n++] = poly_generate::rectangle(wall_thickness, height, INFINITY) polygons[n++] = poly_generate::rectangle(wall_thickness, height)
.set_mass(INFINITY)
.set_center({-wall_thickness / 2., height / 2.}); .set_center({-wall_thickness / 2., height / 2.});
// east wall // east wall
polygons[n++] = poly_generate::rectangle(wall_thickness, height, INFINITY) polygons[n++] = poly_generate::rectangle(wall_thickness, height)
.set_mass(INFINITY)
.set_center({width + wall_thickness / 2., height / 2.}); .set_center({width + wall_thickness / 2., height / 2.});
// middle wall // middle wall
polygons[n++] = poly_generate::rectangle(50, height / 2., INFINITY) polygons[n++] = poly_generate::rectangle(50, height / 2.)
.set_mass(INFINITY)
.set_center({25 + width * 1. / 2, height / 2.}) .set_center({25 + width * 1. / 2, height / 2.})
.set_angle(0); .set_angle(30);
polygons[n++] = poly_generate::regular(100, 3) polygons[n++] = poly_generate::regular(100, 3)
.set_center({100, 400}) .set_center({100, 400})
@ -50,15 +55,16 @@ void polygons_init_state() {
.set_speed({-200, -10}); .set_speed({-200, -10});
polygons[n++] = poly_generate::general( polygons[n++] = poly_generate::general(
{{0, 0}, {100, 0}, {100, 100}, {50, 150}, {0, 100}}, {{0, 0}, {100, 0}, {100, 100}, {50, 150}, {0, 100}}
3
) )
.set_center({200, 600}) .set_center({200, 600})
.set_angle(45) .set_angle(45)
.set_speed({10, 0}); .set_speed({10, 0});
polygons[n++] = poly_generate::rectangle(100, 150).set_center({600, 200}); polygons[n++] = poly_generate::rectangle(100, 150).set_center({600, 200});
polygons[n++] = poly_generate::regular(50, 5).set_center({150, 150}); polygons[n++] = poly_generate::regular(50, 5)
.set_center({150, 150})
.set_speed({50, -50});
polygons[n++] = polygons[n++] =
poly_generate::general({{0, 0}, {50, 80}, {0, 160}, {-50, 80}}) poly_generate::general({{0, 0}, {50, 80}, {0, 160}, {-50, 80}})
.set_center({700, 700}) .set_center({700, 700})

View File

@ -71,6 +71,14 @@ class polygon {
polygon& set_mass(double m) { polygon& set_mass(double m) {
mass = m; mass = m;
// TODO: This is pretty shit, but it's good to make stuff work now,
// since the only time we change the mass of an object is the wall,
// otherwise we take the area and the polygon_generator module handles
// that. But what's to be done is to extract the intertia calcualtion to
// a new module so that we can import it here, and recalculate the
// intertia of the polygon if the mass changes.
if (m == INFINITY)
inertia = INFINITY;
return *this; return *this;
} }
@ -102,6 +110,7 @@ class polygon {
os << " angle: " << p.angle << std::endl; os << " angle: " << p.angle << std::endl;
os << " speed: " << p.speed << std::endl; os << " speed: " << p.speed << std::endl;
os << " angular speed: " << p.angular_speed << std::endl; os << " angular speed: " << p.angular_speed << std::endl;
os << " intertia: " << p.inertia << std::endl;
return os; return os;
} }
}; };