Removed the passing of the mass through parameters. Now the mass is
determined by the area of the polygon
This commit is contained in:
parent
ce0cf102ba
commit
89e250dcba
@ -3,17 +3,23 @@
|
|||||||
#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},
|
||||||
@ -25,7 +31,8 @@ polygon poly_generate::rectangle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -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
|
||||||
|
24
polygons.cc
24
polygons.cc
@ -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})
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user