#include <iostream>
#include <algorithm>
#include <cmath>
#include <mutex>
#include <vector>
#include <string>
#include <cstdio>
#include <stdexcept>
namespace format_helper
{
template < class Src > inline Src cast (Src v)
{
return v;
}
inline const char *cast (const std::string & v)
{
return v.c_str ();
}
};
template < typename ... Ts >
inline std::string stringfmt (const std::string & fmt, Ts && ... vs)
{
using namespace
format_helper;
char
b;
//not counting the terminating null character.
size_t
required =
std::snprintf (&b, 0, fmt.c_str (), cast (std::forward < Ts > (vs)) ...);
std::string result;
result.resize (required, 0);
std::snprintf (const_cast < char *>(result.data ()), required + 1,
fmt.c_str (), cast (std::forward < Ts > (vs)) ...);
return result;
}
struct Point
{
float
x;
float
y;
float
z;
//this assumed be start
Point
vectorTo (const Point & end) const
{
return
{
end.x - x, end.y - y, end.z - z};
}
float
len () const //magnitude
{
return
std::sqrt (x * x + y * y + z * z);
}
Point &
operator* (float s)
{
x *= s;
y *= s;
z *= s;
return *this;
}
Point & operator+ (float s)
{
x += s;
y += s;
z += s;
return *this;
}
Point & operator- (float s)
{
x -= s;
y -= s;
z -= s;
return *this;
}
Point & operator/ (float s)
{
x /= s;
y /= s;
z /= s;
return *this;
}
Point & normalize ()
{
const float
s = 1.f / len ();
x *= s;
y *= s;
z *= s;
return *this;
}
Point
cross (const Point & rkVector) const
{
return
{
y *
rkVector.
z -
z *
rkVector.
y,
z *
rkVector.
x -
x *
rkVector.
z,
x *
rkVector.
y -
y *
rkVector.
x};
}
friend
std::ostream &
operator << (std::ostream & out, const Point & c);
};
std::ostream & operator << (std::ostream & out, const Point & c)
{
out << "[" << c.x << "; " << c.y << "; " << c.z << "]";
return out;
}
Point
operator + (const Point & a, const Point & b)
{
return
{
a.x + b.x, a.y + b.y, a.z + b.z};
}
//dot product (if a & b are perpendicular, dot product is zero)
float
operator * (const Point & a, const Point & b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
const static Point A
{
0.f, 0.f, 0.f}; //SOL
const static Point B
{
67.5, -119.46875, 24.84375}; //Achenar
const static Point C
{
-33.65625, 72.46875, -20.65625}; //Alioth
float
min (float a, float b, float c)
{
return std::fmin (a, std::fmin (b, c));
}
float
max (float a, float b, float c)
{
return std::fmax (a, std::fmax (b, c));
}
Point
minp (const Point & a, const Point & b, const Point & c)
{
return
{
min (a.x, b.x, c.x), min (a.y, b.y, c.y), min (a.z, b.z, c.z)};
}
Point
maxp (const Point & a, const Point & b, const Point & c)
{
return
{
max (a.x, b.x, c.x), max (a.y, b.y, c.y), max (a.z, b.z, c.z)};
}
Point
fromInt (uint64_t x, uint64_t y, uint64_t z, float step, const Point & start)
{
return
{
x *step + start.x, y * step + start.y, z * step + start.z};
}
static void
hexchar (unsigned char c, unsigned char &hex1, unsigned char &hex2)
{
hex1 = c / 16;
hex2 = c % 16;
hex1 += hex1 <= 9 ? '0' : 'A' - 10;
hex2 += hex2 <= 9 ? '0' : 'A' - 10;
}
std::string urlencode (const std::string & s)
{
std::vector < char >v;
v.reserve (s.size ());
for (const char c:s)
{
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
c == '-' || c == '_' || c == '.' || c == '!' || c == '~' ||
c == '*' || c == '\'' || c == '(' || c == ')')
v.push_back (c);
else if (c == ' ')
v.push_back ('+');
else
{
v.push_back ('%');
unsigned char d1, d2;
hexchar (c, d1, d2);
v.push_back (d1);
v.push_back (d2);
}
}
return std::string (v.cbegin (), v.cend ());
}
std::string createEDSMLink (const Point & point)
{
const auto params
{
stringfmt ("x=%0.4f&y=%0.4f&z=%0.4f&radius=20", point.x, point.y, point.z)};
return stringfmt ("https://www.edsm.net/api-v1/sphere-systems?%s", params);
}
void
findInnerCircleCenter ()
{
//for 3 sources we can get coordinates of the center of the inner circle of the triangle
//http://www.math24.ru/%D0%B4%D0%B2%D1%83%D0%BC%D0%B5%D1%80%D0%BD%D0%B0%D1%8F-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0-%D0%BA%D0%BE%D0%BE%D1%80%D0%B4%D0%B8%D0%BD%D0%B0%D1%82.html
const float a = B.vectorTo (C).len ();
const float b = A.vectorTo (C).len ();
const float c = A.vectorTo (B).len ();
const float summ = a + b + c;
const float x = (a * A.x + b * B.x + c * C.x) / summ;
const float y = (a * A.y + b * B.y + c * C.y) / summ;
const float z = (a * A.z + b * B.z + c * C.z) / summ;
std::cout << createEDSMLink (Point
{
x, y, z}) << std::endl;
}
void
findEquallyRemotePoint ()
{
const auto AB
{
A.vectorTo (B)};
const auto AC
{
A.vectorTo (C)};
const auto normal
{
AB.cross (AC).normalize ()}; //perpendicular to surface ABC
}
//if it would solid methal triangle ABC then...
void
findMassCenter ()
{
//http://www.pm298.ru/reshenie/fha0503.php
const auto summ
{
A + B + C};
const Point M
{
summ.x / 3.f, summ.y / 3.f, summ.z / 3.f};
std::cout << createEDSMLink (M) << std::endl;
}
int
main ()
{
findInnerCircleCenter ();
//findMassCenter();
return 0;
}