Last active
October 19, 2016 14:08
-
-
Save cactorium/4917a057dc2517640463f4e165d6b826 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Same #includes as last time, nothing new here | |
#include <vector> | |
#include <iostream> | |
// C++ has structs just like C! | |
// This defines a new type of thing, called a Point | |
// so you can make Points, and they'll all have these exact components | |
struct Point { | |
double x, y, z, mass; | |
}; | |
// This is the function declaration! | |
// Also known as a prototype | |
// In C, they're optional | |
// In C++, they're not | |
// From this declaration, we see that the return type is a Point, | |
// the function is called GetCentroid, and it takes in one argument, | |
// which is kind of complicated so I'll break it down in a bit | |
// The TLDR is that this basically means that you can call the function | |
// using a vector of Points as its arguments, and it won't modify your | |
// vector of Points at all, and it'll also avoid making a copy of them, | |
// which is what C/C++ does to most arguments in functions | |
// | |
// The core of it is a std::vector<Point>, a vector of Points, like we | |
// had in the last class, but that's surrounded by two new things, | |
// const and & | |
// const is short for constant | |
// When a variable has this attribute, it means you aren't allowed to modify | |
// the variable, only reading it, and using methods and whatever else that | |
// avoid modifying it | |
// Put it when you can because it helps programmers figure out what your | |
// function does | |
// | |
// The & probably looks kind of familiar if you've programmed in C before, | |
// but here it's pretty different | |
// In C, it means "the address of", for getting a pointer to a variable | |
// Here's it's used like the * in a pointer declaration; it means reference | |
// So here we have a reference to a constant vector of Points | |
// A reference basically the same thing as a pointer, except you get to treat | |
// the variable like a normal variable; you don't need to bother with the dereferencing | |
// stuff | |
// You also can't do any pointer arithmetic, and the pointer's never null, | |
// so it's a little safer | |
// However, unlike pointers, references are basically only used in function declarations | |
// Here they let you avoid copying objects, and also allow you to modify variables | |
// the same way pointers do in C, except safer | |
// They let you avoid copying objects because you can just pass a reference to it | |
// instead of having to make a copy of it like you normally would if you tried | |
// to pass a variable in a function | |
// | |
// By the way, C++ has pointers like C, but generally unlike C, you should avoid | |
// using them like the plague, because there's better, safer, ways in C++ that | |
// we'll get to eventually | |
// | |
// Aaand just like last time, half the lesson's based on a single line of code | |
// I should probably work on not doing that.. | |
Point GetCentroid(const std::vector<Point>& points); | |
// The program starts in main() as most of the time | |
int main() { | |
// Let's make a program that calculates the centroid, or center of mass, | |
// of an unknown number of points | |
// First we ask the user for the number of points they want to input | |
// We initialize an integer variable to store the number of points | |
int numPoints = 0; | |
// Like before std::cout << stuff | |
// prints stuff out to the command line | |
std::cout << "Enter the number of masses: "; | |
// Similarly std::cin >> stuff | |
// takes data from the user input and sticks it in that variable | |
std::cin >> numPoints; | |
// We need a place to store the points, and a vector's a good a choice as any | |
auto points = std::vector<Point>(); | |
// We know the user wants to enter numPoints points, so we loop that many times | |
for (int i = 0; i < numPoints; ++i) { | |
// We make a temporary variable to store the user's input | |
Point tmp; | |
// And then populate it using the data from std::cin | |
std::cout << "Enter a mass: (x y z mass)\n"; | |
std::cin >> tmp.x >> tmp.y >> tmp.z >> tmp.mass; | |
// And add it to the vector; like before, this means "add tmp to points" | |
// | |
// I don't think I covered this well before, but this is a method call | |
// C++ is object oriented, so objects can have methods related to them, | |
// and methods are basically functions that are very closely related to the | |
// objects they're attached to | |
// So this call is something like | |
// "call point's method push_back using tmp as the argument" | |
// Methods can be defined for certain types in C++, we'll probably discuss | |
// that soon | |
// | |
// Anyways, at the end of this loop points will store all the data that the | |
// user entered in what's effectively a big array | |
points.push_back(tmp); | |
} | |
// Here we store the value we get from GetCentroid in centroid and print | |
// out the results | |
auto centroid = GetCentroid(points); | |
std::cout << "Total mass: " << centroid.mass << "\n"; | |
std::cout << "The center of mass is " << centroid.x << | |
", " << centroid.y << | |
", " << centroid.z << "\n"; | |
return 0; | |
} | |
// We declared the function already, above the main() function, but now | |
// we need to define it so we can actually use it | |
Point GetCentroid(const std::vector<Point>& points) { | |
double totalMass = 0.0, totalX = 0.0, totalY = 0.0, totalZ = 0.0; | |
// Following the formula in Wikipedia, the position of the centroid | |
// is the weighted average of the positions of all the points, or put more | |
// simply, the sum of coordinates of each point, multiplied by its individual mass, | |
// with the sum divided by the total mass of all the points | |
// | |
// It turns out we can calculate both the total mass and the sum of point coordinates | |
// in a single pass over the vector of points, so we'll do that | |
for (Point p: points) { | |
totalMass += p.mass; | |
totalX += p.mass*p.x; | |
totalY += p.mass*p.y; | |
totalZ += p.mass*p.z; | |
} | |
// Here we see an example of another new bit of C++ syntax; | |
// Point{.....} is an expression that is defines a new point | |
// This works for any struct, and the fields, the variables inside a struct, | |
// will be initialized in the same order they appear in that expression | |
// So Point{1.0, 2.0, 3.0, 4.0} will have | |
// an x value of 1.0, | |
// a y value of 2.0, | |
// a z value of 3.0, | |
// and a mass value of 4.0 | |
// | |
// Here we pass that into the return statement so that the function | |
// returns the centroid coordinates and total mass | |
return Point{totalX/totalMass, totalY/totalMass, totalZ/totalMass, totalMass}; | |
} | |
// And we're done! | |
// The homework for this week is to come up with a program that does something | |
// else with moments of inertia or something, preferably using vectors in the | |
// process | |
// Good luck! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment