Restructure project, start importing sc3 code.
This commit is contained in:
181
src/scmp/coord2d.cc
Executable file
181
src/scmp/coord2d.cc
Executable file
@@ -0,0 +1,181 @@
|
||||
//
|
||||
// Project: scccl
|
||||
// File: src/math/geom2d.cpp
|
||||
// Author: Kyle Isom
|
||||
// Date: 2017-06-05
|
||||
// Namespace: math::geom
|
||||
//
|
||||
// geom2d.cpp contains the implementation of 2D geometry in the math::geom
|
||||
// namespace.
|
||||
//
|
||||
// Copyright 2017 Kyle Isom <kyle@imap.cc>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <scccl/math/math.h>
|
||||
#include <scccl/math/geom/coord2d.h>
|
||||
|
||||
|
||||
// coord2d.cpp contains 2D geometric functions and data structures, such as
|
||||
// cartesian and polar coordinates and rotations.
|
||||
|
||||
// TODO: deprecate Point2D in favour of Vector
|
||||
|
||||
namespace scmath {
|
||||
namespace geom {
|
||||
|
||||
|
||||
//
|
||||
// Point2D
|
||||
|
||||
Point2D::Point2D(const Polar2D &pol)
|
||||
: x(std::rint(std::cos(pol.theta) * pol.r)),
|
||||
y(std::rint(std::sin(pol.theta) * pol.r)) {}
|
||||
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& outs, const Point2D& pt)
|
||||
{
|
||||
outs << "(" << std::to_string(pt.x) << ", " << std::to_string(pt.y) << ")";
|
||||
return outs;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
Point2D::ToString()
|
||||
{
|
||||
return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Point2D::ToPolar(Polar2D& pol)
|
||||
{
|
||||
pol.r = std::sqrt((x * x) + (y * y));
|
||||
pol.theta = std::atan2(y, x);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Point2D::Rotate(Point2D& pt, double theta)
|
||||
{
|
||||
Polar2D pol(*this);
|
||||
pol.Rotate(pol, theta);
|
||||
pol.ToPoint(pt);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Point2D::operator==(const Point2D& rhs) const
|
||||
{
|
||||
return (x == rhs.x) && (y == rhs.y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Point2D::Translate(const Point2D& origin, Point2D &translated)
|
||||
{
|
||||
translated.x = origin.x + x;
|
||||
translated.y = origin.y + y;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Point2D>
|
||||
Point2D::Rotate(std::vector<Polar2D> vertices, double theta)
|
||||
{
|
||||
std::vector<Point2D> rotated;
|
||||
|
||||
for (auto v : vertices) {
|
||||
Point2D p;
|
||||
v.RotateAround(*this, p, theta);
|
||||
rotated.push_back(p) ;
|
||||
}
|
||||
|
||||
return rotated;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Point2D::Distance(const Point2D& other)
|
||||
{
|
||||
auto dx = other.x - x;
|
||||
auto dy = other.y - y;
|
||||
return std::sqrt(dx * dx + dy + dy);
|
||||
}
|
||||
|
||||
|
||||
// Polar2D
|
||||
|
||||
Polar2D::Polar2D(const Point2D &pt)
|
||||
: r(std::sqrt((pt.x * pt.x) + (pt.y * pt.y))),
|
||||
theta(std::atan2(pt.y, pt.x)) {}
|
||||
|
||||
|
||||
void
|
||||
Polar2D::ToPoint(Point2D& pt)
|
||||
{
|
||||
pt.y = std::rint(std::sin(theta) * r);
|
||||
pt.x = std::rint(std::cos(theta) * r);
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
Polar2D::ToString()
|
||||
{
|
||||
return "(" + std::to_string(r) + ", " + std::to_string(theta) + ")";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Polar2D::Rotate(Polar2D& rot, double delta)
|
||||
{
|
||||
rot.r = r;
|
||||
rot.theta = RotateRadians(theta, delta);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Polar2D::operator==(const Polar2D& rhs) const
|
||||
{
|
||||
static double eps = 0.0;
|
||||
if (eps == 0.0) {
|
||||
scmath::DefaultEpsilon(eps);
|
||||
}
|
||||
return scmath::WithinTolerance(r, rhs.r, eps) &&
|
||||
scmath::WithinTolerance(theta, rhs.theta, eps);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Polar2D::RotateAround(const Point2D &origin, Point2D &point, double delta)
|
||||
{
|
||||
Polar2D rot;
|
||||
this->Rotate(rot, delta);
|
||||
rot.ToPoint(point);
|
||||
point.Translate(origin, point);
|
||||
}
|
||||
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& outs, const Polar2D& pol)
|
||||
{
|
||||
outs << "(" << pol.r << ", " << pol.theta << ")";
|
||||
return outs;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace geom
|
||||
} // end namespace math
|
||||
128
src/scmp/math.cc
Normal file
128
src/scmp/math.cc
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include <scccl/math/math.h>
|
||||
|
||||
|
||||
namespace scmath {
|
||||
|
||||
|
||||
std::vector<int>
|
||||
Die(int m, int n)
|
||||
{
|
||||
std::uniform_int_distribution<> die(1, n);
|
||||
|
||||
std::random_device rd;
|
||||
std::vector<int> dice;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
dice.push_back(die(rd));
|
||||
}
|
||||
|
||||
return dice;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BestDie(int k, int m, int n)
|
||||
{
|
||||
auto dice = Die(m, n);
|
||||
|
||||
if (k < m) {
|
||||
std::sort(dice.begin(), dice.end(), std::greater<int>());
|
||||
dice.resize(static_cast<size_t>(k));
|
||||
}
|
||||
|
||||
return std::accumulate(dice.begin(), dice.end(), 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DieTotal(int m, int n)
|
||||
{
|
||||
std::uniform_int_distribution<> die(1, n);
|
||||
|
||||
std::random_device rd;
|
||||
int i = 0, total = 0;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
total += die(rd);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
RadiansToDegreesF(float rads)
|
||||
{
|
||||
return rads * (180.0 / M_PI);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
RadiansToDegreesD(double rads)
|
||||
{
|
||||
return rads * (180.0 / M_PI);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
DegreesToRadiansF(float degrees)
|
||||
{
|
||||
return degrees * M_PI / 180.0;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
DegreesToRadiansD(double degrees)
|
||||
{
|
||||
return degrees * M_PI / 180.0;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
RotateRadians(double theta0, double theta1)
|
||||
{
|
||||
auto dtheta = theta0 + theta1;
|
||||
|
||||
if (dtheta > M_PI) {
|
||||
dtheta -= MAX_RADIAN;
|
||||
} else if (dtheta < -M_PI) {
|
||||
dtheta += MAX_RADIAN;
|
||||
}
|
||||
|
||||
if ((dtheta < -M_PI) || (dtheta > M_PI)) {
|
||||
return RotateRadians(dtheta, 0);
|
||||
}
|
||||
|
||||
return dtheta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const double Epsilon_double = 0.0001;
|
||||
const float Epsilon_float = 0.0001;
|
||||
|
||||
|
||||
void
|
||||
DefaultEpsilon(double &epsilon)
|
||||
{
|
||||
epsilon = Epsilon_double;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DefaultEpsilon(float &epsilon)
|
||||
{
|
||||
epsilon = Epsilon_float;
|
||||
}
|
||||
|
||||
|
||||
} // namespace math
|
||||
|
||||
19
src/scmp/motion2d.cc
Normal file
19
src/scmp/motion2d.cc
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <cmath>
|
||||
#include <scccl/phys/basic/motion2d.h>
|
||||
|
||||
namespace scphys {
|
||||
namespace basic {
|
||||
|
||||
|
||||
scmath::geom::Vector2d
|
||||
Acceleration(double speed, double heading)
|
||||
{
|
||||
auto dx = std::cos(heading) * speed;
|
||||
auto dy = std::sin(heading) * speed;
|
||||
|
||||
return scmath::geom::Vector2d({dx, dy});
|
||||
}
|
||||
|
||||
|
||||
} // namespace basic
|
||||
} // namespace phys
|
||||
40
src/scmp/orientation.cc
Normal file
40
src/scmp/orientation.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <scccl/math/geom/vector.h>
|
||||
#include <scccl/math/geom/orientation.h>
|
||||
|
||||
|
||||
namespace scmath {
|
||||
namespace geom {
|
||||
|
||||
|
||||
float
|
||||
Heading2f(Vector2f vec)
|
||||
{
|
||||
return vec.angle(Basis2f[Basis_x]);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
Heading3f(Vector3f vec)
|
||||
{
|
||||
Vector2f vec2f {vec[0], vec[1]};
|
||||
return Heading2f(vec2f);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
Heading2d(Vector2d vec)
|
||||
{
|
||||
return vec.angle(Basis2d[Basis_x]);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
Heading3d(Vector3d vec)
|
||||
{
|
||||
Vector2d vec2d {vec[0], vec[1]};
|
||||
return Heading2d(vec2d);
|
||||
}
|
||||
|
||||
|
||||
} // namespace geom
|
||||
} // namespace math
|
||||
91
src/scmp/quaternion.cc
Normal file
91
src/scmp/quaternion.cc
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <scccl/math/geom/quaternion.h>
|
||||
|
||||
|
||||
namespace scmath {
|
||||
namespace geom {
|
||||
|
||||
|
||||
Quaternionf
|
||||
quaternionf(Vector3f axis, float angle)
|
||||
{
|
||||
return Quaternionf(axis.unitVector() * std::sin(angle / 2.0),
|
||||
std::cos(angle / 2.0));
|
||||
}
|
||||
|
||||
|
||||
Quaterniond
|
||||
quaterniond(Vector3d axis, double angle)
|
||||
{
|
||||
return Quaterniond(axis.unitVector() * std::sin(angle / 2.0),
|
||||
std::cos(angle / 2.0));
|
||||
}
|
||||
|
||||
|
||||
Quaternionf
|
||||
quaternionf_from_euler(Vector3f euler)
|
||||
{
|
||||
float x, y, z, w;
|
||||
euler = euler / 2.0;
|
||||
|
||||
float cos_yaw = std::cos(euler[0]);
|
||||
float cos_pitch = std::cos(euler[1]);
|
||||
float cos_roll = std::cos(euler[2]);
|
||||
float sin_yaw = std::sin(euler[0]);
|
||||
float sin_pitch = std::sin(euler[1]);
|
||||
float sin_roll = std::sin(euler[2]);
|
||||
|
||||
x = (sin_yaw * cos_pitch * cos_roll) + (cos_yaw * sin_pitch * sin_roll);
|
||||
y = (sin_yaw * cos_pitch * sin_roll) - (cos_yaw * sin_pitch * cos_roll);
|
||||
z = (cos_yaw * cos_pitch * sin_roll) + (sin_yaw * sin_pitch * cos_roll);
|
||||
w = (cos_yaw * cos_pitch * cos_roll) - (sin_yaw * sin_pitch * sin_roll);
|
||||
|
||||
return Quaternionf(Vector4f{w, x, y, z});
|
||||
}
|
||||
|
||||
|
||||
Quaterniond
|
||||
quaterniond_from_euler(Vector3d euler)
|
||||
{
|
||||
double x, y, z, w;
|
||||
euler = euler / 2.0;
|
||||
|
||||
double cos_yaw = std::cos(euler[0]);
|
||||
double cos_pitch = std::cos(euler[1]);
|
||||
double cos_roll = std::cos(euler[2]);
|
||||
double sin_yaw = std::sin(euler[0]);
|
||||
double sin_pitch = std::sin(euler[1]);
|
||||
double sin_roll = std::sin(euler[2]);
|
||||
|
||||
x = (sin_yaw * cos_pitch * cos_roll) + (cos_yaw * sin_pitch * sin_roll);
|
||||
y = (sin_yaw * cos_pitch * sin_roll) - (cos_yaw * sin_pitch * cos_roll);
|
||||
z = (cos_yaw * cos_pitch * sin_roll) + (sin_yaw * sin_pitch * cos_roll);
|
||||
w = (cos_yaw * cos_pitch * cos_roll) - (sin_yaw * sin_pitch * sin_roll);
|
||||
|
||||
return Quaterniond(Vector4d{w, x, y, z});
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Quaternion_SelfTest()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Vector3f v {1.0, 0.0, 0.0};
|
||||
Vector3f yAxis {0.0, 1.0, 0.0};
|
||||
float angle = M_PI / 2;
|
||||
|
||||
Quaternionf p = quaternionf(yAxis, angle);
|
||||
Quaternionf q;
|
||||
Vector3f vr {0.0, 0.0, 1.0};
|
||||
|
||||
assert(p.isUnitQuaternion());
|
||||
std::cerr << p.rotate(v) << std::endl;
|
||||
assert(p.rotate(v) == vr);
|
||||
assert(p * q == p);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace geom
|
||||
} // namespace math
|
||||
Reference in New Issue
Block a user