1 #ifndef SLAM_CTOR_CORE_GEOMETRY_PRIMITIVES_H     2 #define SLAM_CTOR_CORE_GEOMETRY_PRIMITIVES_H    12   Point2D(
double x_par = 0, 
double y_par = 0) : 
x(x_par), 
y(y_par) {}
    15     return std::pow(
x - pt.
x, 2) + std::pow(
y - pt.
y, 2);
    33   return stream << 
"(" << pnt.
x << 
", " << pnt.
y << 
")";
    52   bool is_point()
 const { 
return _is_horiz && _is_vert; }
    57   explicit operator bool()
 const { 
return is_valid; }
    66     assert(
false && 
"BUG: Contains is undefined for non-axes-aligned segment");
    71     return x_projection_contains(p) && y_projection_contains(p);
    75     return std::pow(_end.x - _beg.x, 2) + std::pow(_end.y - _beg.y, 2);
    95   return stream << 
"[" << s.
beg() << 
"; " << s.
end() << 
"]";
   100     Bot = 0, Left = 1, Top = 2, Right = 3
   107     return location == Location::Bot || location == Location::Top;
   116   Ray(
double x_s, 
double x_d, 
double y_s, 
double y_d) :
   117     beg{x_s, y_s}, delta{x_d, y_d} {}
   119   explicit Ray(
const Segment2D &s) : beg(s.beg()), delta(s.end() - s.beg()) {}
   125       intersect_horiz_segm(s.
beg().
x, s.
end().
x, s.
beg().
y, loc, consumer);
   129       intersect_vert_segm(s.
beg().
y, s.
end().
y, s.
beg().
x, loc, consumer);
   132     assert(
false && 
"BUG: Unable to intersect non-axes-aligned segment");
   141     double inters_alpha = (y - beg.y) / delta.y;
   142     double inters_x = beg.x + inters_alpha * delta.x;
   143     if (inters_x < st_x || end_x < inters_x) 
   146     consumer.emplace_back(loc, inters_x, y);
   154     double inters_alpha = (x - beg.x) / delta.x;
   155     double inters_y = beg.y + inters_alpha * delta.y;
   156     if (inters_y < st_y || end_y < inters_y) 
   159     consumer.emplace_back(loc, x, inters_y);
   171     : _bot{b}, _top{t}, _left{l}, _right{r} {
   172     assert(_bot <= _top);
   173     assert(_left <= _right);
   178   double bot()
 const { 
return _bot; }
   179   double top()
 const { 
return _top; }
   180   double left()
 const { 
return _left; }
   181   double right()
 const { 
return _right; }
   185   bool is_square()
 const { 
return vside_len() == hside_len(); }
   186   double side()
 const { 
return vside_len(); }
   187   double area()
 const { 
return vside_len() * hside_len(); }
   189     return {left() + hside_len() / 2, bot() + vside_len() / 2};
   192   bool is_line()
 const { 
return (vside_len() == 0) ^ (hside_len() == 0); }
   193   bool is_point()
 const { 
return (vside_len() == 0) && (hside_len() == 0); }
   201     return std::vector<Point2D>{{left(), bot()}, {left(), top()},
   202                                 {right(), bot()}, {right(), top()}};
   206     double half_v = vside_len() / 2, half_h = hside_len() / 2;
   207     return {new_center.
y - half_v, new_center.
y + half_v,
   208             new_center.
x - half_h, new_center.
x + half_h};
   213     auto new_hv = vside_len() / (factor * 2),
   214          new_hh = hside_len() / (factor * 2);
   215     return LVRect{c.y - new_hv, c.y + new_hv,
   216                   c.x - new_hh, c.x + new_hh};
   222     return std::vector<LVRect>{
   223       LVRect{bot(),   c.y, left(), right()},
   224       LVRect{  c.y, top(), left(), right()}
   230     return std::vector<LVRect>{
   231       LVRect{bot(), top(), left(),     c.x},
   232       LVRect{bot(), top(),    c.x, right()}
   238     return std::vector<LVRect>{
   239       LVRect{ bot(),   c.y, left(),     c.x}, 
   240       LVRect{   c.y, top(), left(),     c.x}, 
   241       LVRect{ bot(),   c.y,    c.x, right()}, 
   242       LVRect{   c.y, top(),    c.x, right()}  
   253     return intersect_internal(that, 
false);
   258       return intersect(that).area() / area();
   261       return that.
contains(left(), bot()) ? 1.0 : 0.0;
   264     assert(is_point() && that.
is_point() && 
"TODO: support lwr-lines");
   265     return *
this == that ? 1.0 : 0.0;
   271                                           bool reversed = 
false)
 const {
   276     unsigned contained_corners_nm = 0;
   277     auto cleft = left(), cright = right(), ctop = top(), cbot = bot();
   279     #define PROCESS_CORNER(horz_id, vert_id)                    \   280       if (contains(that.horz_id(), that.vert_id())) {           \   281         ++contained_corners_nm;                                 \   282         c##horz_id = that.horz_id();                            \   283         c##vert_id = that.vert_id();                            \   291     #undef PROCESS_CORNER   294     switch (contained_corners_nm) {
   303     case 1: 
case 2: 
case 4:
   306       assert(0 && 
"Unexpected inclusions number");
   313   double _bot, 
_top, _left, _right;
   318   stream << 
"LVRectangle [t:" << r.
top() << 
", b:" << r.
bot();
   319   return stream << 
", l:" << r.
left() << 
", r:" << r.
right() << 
"]";
   324   static constexpr std::size_t BOT_EDGE_IDX = 0;
   325   static constexpr std::size_t TOP_EDGE_IDX = 1;
   326   static constexpr std::size_t LFT_EDGE_IDX = 2;
   327   static constexpr std::size_t RHT_EDGE_IDX = 3;
   334         Segment2D{{ left(), bot()}, {right(), bot()}}, 
   335         Segment2D{{ left(), top()}, {right(), top()}}, 
   336         Segment2D{{ left(), bot()}, { left(), top()}}, 
   337         Segment2D{{right(), bot()}, {right(), top()}}  
   359     for (
auto &e : edges()) {
   360       if (!e.contains(p)) { 
continue; }
   371     std::copy_if(ray_intrs.begin(), ray_intrs.end(), std::back_inserter(inters),
   386     if (1 < intersections.size() &&
   387         intersections.front() == intersections.back()) {
   388       intersections.pop_back();
   390     auto new_last = std::unique(intersections.begin(), intersections.end());
   391     intersections.erase(new_last, intersections.end());
   392     assert(intersections.size() < 3);
   393     return intersections;
   402   const std::vector<Segment2D> &
edges()
 const { 
return _edges; }
 
bool operator==(const LightWeightRectangle &rhs) const 
 
void intersect(const Segment2D &s, Intersection::Location loc, Intersections &consumer) const 
 
bool contains(double x, double y) const 
 
Intersection(Location loc, double x, double y)
 
#define PROCESS_CORNER(horz_id, vert_id)
 
auto overlap(const LightWeightRectangle &that) const 
 
auto split4_evenly() const 
 
CONSTEXPR bool are_equal(const T &a, const T &b, const T &eps)
 
bool contains(const Point2D &p) const 
 
double dist_sq(const Point2D &pt) const 
 
void intersect_vert_segm(double st_y, double end_y, double x, Intersection::Location loc, Intersections &consumer) const 
 
LVRect move_center(const Point2D &new_center) const 
 
Point2D operator-(const Point2D &p) const 
 
auto intersect(const LightWeightRectangle &that) const 
 
bool x_projection_contains(const Point2D &p) const 
 
Point2D(double x_par=0, double y_par=0)
 
const std::vector< Segment2D > _edges
 
Segment2D find_containing_edge(const Point2D &p) const 
 
LightWeightRectangle(const Point2D &p)
 
Segment2D(const Point2D &begin, const Point2D &end)
 
std::ostream & operator<<(std::ostream &stream, const Point2D &pnt)
 
Rectangle(double b, double t, double l, double r)
 
bool contains_intersection(const Point2D &p) const 
 
bool operator==(const Point2D &that) const 
 
auto shrink(double factor) const 
 
Ray(double x_s, double x_d, double y_s, double y_d)
 
Point2D operator+(const Point2D &p) const 
 
LightWeightRectangle(double b, double t, double l, double r)
 
void intersect_horiz_segm(double st_x, double end_x, double y, Intersection::Location loc, Intersections &consumer) const 
 
Intersections find_intersections(const Segment2D &s) const 
 
Point2D operator*(double scalar) const 
 
const Point2D & end() const 
 
Intersections find_intersections(const Ray &ray) const 
 
std::vector< Intersection > Intersections
 
bool are_ordered(double a, double b, double c)
 
bool contains(const Point2D &p) const 
 
bool y_projection_contains(const Point2D &p) const 
 
const Segment2D & right_edge() const 
 
static Segment2D invalid()
 
const Segment2D & left_edge() const 
 
const Segment2D & bot_edge() const 
 
const std::vector< Segment2D > & edges() const 
 
const Point2D & beg() const 
 
bool has_on_edge_line(const Segment2D &s) const 
 
const Segment2D & top_edge() const 
 
LightWeightRectangle intersect_internal(const LightWeightRectangle &that, bool reversed=false) const