#include <algorithm>
#include <iostream>
struct point
{
int x, y;
};
inline point operator-(point const & a, point const & b)
{
const point result = {a.x - b.x, a.y - b.y};
return result;
}
inline long squared_distance(point const & a, point const & b)
{
const point d = b - a;
return d.x * d.x + d.y * d.y;
}
point project_to_units(point const & o, point const & e)
{
const int dx = std::abs(e.x - o.x);
const int dy = std::abs(e.y - o.y);
point result = {e.x, e.y};
if (dy < dx) {
result.x = o.x + (e.y - o.y);
} else if (dx < dy) {
result.y = o.y + (e.x - o.x);
}
return result;
}
struct closer_to
{
const point o;
closer_to(point const & p) : o(p) {}
bool operator()(point const & a, point const & b) const
{
return squared_distance(o, a) < squared_distance(o, b);
}
};
point approximate(const point o, const point e)
{
const point points[] = {
{e.x, o.y}, // projection to X
{o.x, e.y}, // projection to Y
project_to_units(o, e) // projection to [(2n+1)*pi / 4] axis
};
return *std::min_element(points, points + 3, closer_to(e));
}
std::ostream & operator<<(std::ostream & os, point const & p)
{
os << "(" << p.x << ", " << p.y << ")";
return os;
}
int main()
{
const point o = {0, 0};
const point points[] = {
{-1, -1}, {1, 3}, {2, 2}, {2, 3}
};
std::cout << "center: " << o << std::endl;
for (std::size_t i = 0; i < sizeof(points)/sizeof(points[0]); ++i) {
const point a = approximate(o, points[i]);
std::cout << "point " << points[i] << ", approx " << a << std::endl;
}
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKc3RydWN0IHBvaW50CnsKICAgIGludCB4LCB5Owp9OwoKaW5saW5lIHBvaW50IG9wZXJhdG9yLShwb2ludCBjb25zdCAmIGEsIHBvaW50IGNvbnN0ICYgYikKewogICAgY29uc3QgcG9pbnQgcmVzdWx0ID0ge2EueCAtIGIueCwgYS55IC0gYi55fTsKICAgIHJldHVybiByZXN1bHQ7Cn0KCmlubGluZSBsb25nIHNxdWFyZWRfZGlzdGFuY2UocG9pbnQgY29uc3QgJiBhLCBwb2ludCBjb25zdCAmIGIpCnsKICAgIGNvbnN0IHBvaW50IGQgPSBiIC0gYTsKICAgIHJldHVybiBkLnggKiBkLnggKyBkLnkgKiBkLnk7Cn0KCnBvaW50IHByb2plY3RfdG9fdW5pdHMocG9pbnQgY29uc3QgJiBvLCBwb2ludCBjb25zdCAmIGUpCnsKICAgIGNvbnN0IGludCBkeCA9IHN0ZDo6YWJzKGUueCAtIG8ueCk7CiAgICBjb25zdCBpbnQgZHkgPSBzdGQ6OmFicyhlLnkgLSBvLnkpOwogICAgcG9pbnQgcmVzdWx0ID0ge2UueCwgZS55fTsKICAgIGlmIChkeSA8IGR4KSB7CiAgICAgICAgcmVzdWx0LnggPSBvLnggKyAoZS55IC0gby55KTsKICAgIH0gZWxzZSBpZiAoZHggPCBkeSkgewogICAgICAgIHJlc3VsdC55ID0gby55ICsgKGUueCAtIG8ueCk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0Owp9CgpzdHJ1Y3QgY2xvc2VyX3RvCnsKICAgIGNvbnN0IHBvaW50IG87CgogICAgY2xvc2VyX3RvKHBvaW50IGNvbnN0ICYgcCkgOiBvKHApIHt9CgogICAgYm9vbCBvcGVyYXRvcigpKHBvaW50IGNvbnN0ICYgYSwgcG9pbnQgY29uc3QgJiBiKSBjb25zdAogICAgewogICAgICAgIHJldHVybiBzcXVhcmVkX2Rpc3RhbmNlKG8sIGEpIDwgc3F1YXJlZF9kaXN0YW5jZShvLCBiKTsKICAgIH0KfTsKCnBvaW50IGFwcHJveGltYXRlKGNvbnN0IHBvaW50IG8sIGNvbnN0IHBvaW50IGUpCnsKICAgIGNvbnN0IHBvaW50IHBvaW50c1tdID0gewogICAgICAgIHtlLngsIG8ueX0sICAgICAgICAgICAgLy8gcHJvamVjdGlvbiB0byBYCiAgICAgICAge28ueCwgZS55fSwgICAgICAgICAgICAvLyBwcm9qZWN0aW9uIHRvIFkKICAgICAgICBwcm9qZWN0X3RvX3VuaXRzKG8sIGUpIC8vIHByb2plY3Rpb24gdG8gWygybisxKSpwaSAvIDRdIGF4aXMKICAgIH07CiAgICByZXR1cm4gKnN0ZDo6bWluX2VsZW1lbnQocG9pbnRzLCBwb2ludHMgKyAzLCBjbG9zZXJfdG8oZSkpOwp9CgoKc3RkOjpvc3RyZWFtICYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0gJiBvcywgcG9pbnQgY29uc3QgJiBwKQp7CiAgICBvcyA8PCAiKCIgPDwgcC54IDw8ICIsICIgPDwgcC55IDw8ICIpIjsKICAgIHJldHVybiBvczsKfQoKaW50IG1haW4oKQp7CiAgICBjb25zdCBwb2ludCBvID0gezAsIDB9OwoKICAgIGNvbnN0IHBvaW50IHBvaW50c1tdID0gewogICAgICAgIHstMSwgLTF9LCB7MSwgM30sIHsyLCAyfSwgezIsIDN9CiAgICB9OwoKICAgIHN0ZDo6Y291dCA8PCAiY2VudGVyOiAiIDw8IG8gPDwgc3RkOjplbmRsOwoKICAgIGZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBzaXplb2YocG9pbnRzKS9zaXplb2YocG9pbnRzWzBdKTsgKytpKSB7CiAgICAgICAgY29uc3QgcG9pbnQgYSA9IGFwcHJveGltYXRlKG8sIHBvaW50c1tpXSk7CiAgICAgICAgc3RkOjpjb3V0IDw8ICJwb2ludCAiIDw8IHBvaW50c1tpXSA8PCAiLCBhcHByb3ggIiA8PCBhIDw8IHN0ZDo6ZW5kbDsKICAgIH0KICAgIHJldHVybiAwOwp9Cgo=
center: (0, 0)
point (-1, -1), approx (-1, -1)
point (1, 3), approx (0, 3)
point (2, 2), approx (2, 2)
point (2, 3), approx (2, 2)