Skip to content
Snippets Groups Projects
GeometryHelpers.cpp 2.83 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "GeometryHelpers.h"
    
    Chao Peng's avatar
    Chao Peng committed
    
    // some utility functions that can be shared
    namespace ref::utils {
    
    typedef ROOT::Math::XYPoint Point;
    
    // check if a square in a ring
    
    inline bool in_ring(const Point &pt, double sx, double sy, double rmin, double rmax, double phmin, double phmax)
    
    Chao Peng's avatar
    Chao Peng committed
    {
        if (pt.r() > rmax || pt.r() < rmin) {
            return false;
        }
    
        // check four corners
        std::vector<Point> pts {
    
            Point(pt.x() - sx/2., pt.y() - sy/2.),
            Point(pt.x() - sx/2., pt.y() + sy/2.),
            Point(pt.x() + sx/2., pt.y() - sy/2.),
            Point(pt.x() + sx/2., pt.y() + sy/2.),
    
    Chao Peng's avatar
    Chao Peng committed
        };
        for (auto &p : pts) {
            if (p.r() > rmax || p.r() < rmin || p.phi() > phmax || p.phi() < phmin) {
                return false;
            }
        }
        return true;
    }
    
    // check if a square is overlapped with the others
    
    inline bool overlap(const Point &pt, double sx, double sy, const std::vector<Point> &pts)
    
    Chao Peng's avatar
    Chao Peng committed
    {
        for (auto &p : pts) {
    
            auto pn = p - pt;
            if ((std::abs(pn.x()) < (1. - 1e-6)*sx) && (std::abs(pn.y()) < (1. - 1e-6)*sy)) {
    
    Chao Peng's avatar
    Chao Peng committed
                return true;
            }
        }
        return false;
    }
    
    // a helper function to recursively fill square in a ring
    
    void add_rectangle(Point p, std::vector<Point> &res, double sx, double sy, double rmin, double rmax, double phmin, double phmax)
    
    Chao Peng's avatar
    Chao Peng committed
    {
        // outside of the ring or overlapping
    
        if (!in_ring(p, sx, sy, rmin, rmax, phmin, phmax) || overlap(p, sx, sy, res)) {
    
    Chao Peng's avatar
    Chao Peng committed
            return;
        }
    
        res.emplace_back(p);
    
        // check adjacent squares
    
        add_rectangle(Point(p.x() + sx, p.y()), res, sx, sy, rmin, rmax, phmin, phmax);
        add_rectangle(Point(p.x() - sx, p.y()), res, sx, sy, rmin, rmax, phmin, phmax);
        add_rectangle(Point(p.x(), p.y() + sy), res, sx, sy, rmin, rmax, phmin, phmax);
        add_rectangle(Point(p.x(), p.y() - sy), res, sx, sy, rmin, rmax, phmin, phmax);
    
    Chao Peng's avatar
    Chao Peng committed
    }
    
    // fill squares
    
    std::vector<Point> fillRectangles(Point ref, double sx, double sy, double rmin, double rmax, double phmin, double phmax)
    
        // convert (0, 2pi) to (-pi, pi)
        if (phmax > M_PI) {
            phmin -= M_PI;
            phmax -= M_PI;
        }
    
    Chao Peng's avatar
    Chao Peng committed
        // start with a seed square and find one in the ring
        // move to center
    
        ref = ref - Point(int(ref.x()/sx)*sx, int(ref.y()/sy)*sy);
    
        auto find_seed = [] (const Point &ref, int n, double sx, double sy, double rmin, double rmax, double phmin, double phmax) {
    
    Chao Peng's avatar
    Chao Peng committed
            for (int ix = -n; ix < n; ++ix) {
                for (int iy = -n; iy < n; ++iy) {
    
                    Point pt(ref.x() + ix*sx, ref.y() + iy*sy);
                    if (in_ring(pt, sx, sy, rmin, rmax, phmin, phmax)) {
    
    Chao Peng's avatar
    Chao Peng committed
                        return pt;
                    }
                }
            }
            return ref;
        };
    
        std::vector<Point> res;
    
        ref = find_seed(ref, int(rmax/sx) + 2, sx, sy, rmin, rmax, phmin, phmax);
        add_rectangle(ref, res, sx, sy, rmin, rmax, phmin, phmax);
    
    Chao Peng's avatar
    Chao Peng committed
        return res;
    }
    
    
    } // ref::utils