I find myself defining classes like:
struct AngleSize {
explicit AngleSize(double radians) : size(radians) {}
double size;
};
This has a bunch of advantages over storing anglesizes as plain doubles.
Advantage 1, it makes it possible to define these 2 distinct constructors:
Vec2::Vec2(double x, double y);
Vec2::Vec2(double length, AngleSize direction);
... the latter one unambigously called as Vec2(1, AngleSize(5));
(though in this case a static factory function like Vec2::fromPolar(1, 5)
might have been just as good?)
Advantage 2, it's more typesafe, the following mistake is caught:
double temperature = air.getTemperature();
Vec2 v(someLength, temperature);
Yet all is not fine.
Disadvantage 1, verbose and unexpected syntax
Vec2::Vec2(double length, AngleSize direction) {
x = length * cos(direction.size);
y = length * sin(direction.size);
}
Ugh, this should really say cos(direction)
yet without allowing an unsafe implicit conversion, I need to verbosely access the actual value.
Disadvantage 2, too many classes for every single thing, where do you draw the line?
struct Direction { // angle between line and horizontal axis
explicit Direction(AngleSize angleSize);
AngleSize angleSize;
};
struct Angle { // defined by "starting and ending angle" unlike AngleSize
Angle(Direction startingDir, Direction endingDir);
Angle(Direction startingDir, AngleSize size);
Angle(Line line1, Line line2);
};
struct PositionedAngle {
// angle defined by two rays. this is getting just silly
PositionedAngle(Ray firstRay, AngleSize angle);
PositionedAngle(Point center, AngleSize fromAngle, AngleSize toAngle);
// and so on, and so forth.
};
// each of those being a legit math concept with
// distinct operations possible on it.
What do you do in such cases, yourself?
Also where can I read about this problem? I think boost
might have something related?
Note that this isn't just about geometry, it's applicable everywhere. Think posix socklen_t...