условия в заданной области

182
06 марта 2018, 04:24

Здравствуйте! Какие условия надо задать, чтобы узнать попадает ли точка в заданную область?

Answer 1

Я немного переборщил, но это работает (я верю).

Основная функция:

auto pointInArea =
        [](const Circle& c, const Square& s, const Point& p)->bool{
            if (!(s.contain(p) || c.contain(p))){
                //точка не содержится ни в квадрате ни в круге
                return false;
            }
            //точка содержится или квадрате или в круге.

            if (!c.contain(p)){
                //точка не содержится в круге => значит содержится в
                //квадрате, и угол проверять не нужно
                return true;
            }
            //точка содержится в круге (и, возможно в квадрате, но это уже
            //не важно, теперь надо проверить угол
            if (c.getCenter() == p){
                //точка совпадает с центром окружности
                return true;
            }
            radian angle = c.calcAngleByCenter(p);
            if (inInterval(0.0, 5.0* M_PI_4, angle)){
                return true;
            }
            return false;
        };

Весь код:

#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
using radian = double;
const double EPS = 1e-9;
//принадлежность числа интервалу, включительно
bool inInterval(double left, double right, double value){
    if (std::fabs(value - left) < EPS){
        return true;
    }
    if (std::fabs(value - right) < EPS){
        return true;
    }
    return (value > left && value < right);
}

class Point{
public:
    Point(double x = 0.0l, double y = 0.0l):
    m_x{x},
    m_y{y}
    {}
    Point(const Point& other):
    m_x{other.m_x},
    m_y{other.m_y}
    {}
    Point& operator=(const Point& other){
        if (this != &other){
            m_x = other.m_x;
            m_y = other.m_y;
        }
        return *this;
    }
    bool operator==(const Point& other) const{
        if (this == &other){
            return true;
        }
        double dx = m_x - other.m_x;
        double dy = m_y - other.m_y;
        return ((std::fabs(dx) < EPS) && (std::fabs(dy) < EPS));
    }
    virtual ~Point(){}
    const double& getX() const{
        return m_x;
    }
    const double& getY() const{
        return m_y;
    }
    double distanceTo(const Point& p) const{
        return distanceTo(p.getX(), p.getY());
    }
    double distanceTo(double x, double y) const{
        double dx = (m_x - x);
        double dy = (m_y - y);
        return std::sqrt(dx*dx + dy*dy);
    }
private:
    double m_x;
    double m_y;
};
class Circle{
public:
    Circle(const Point& center = {}, double radius = 1.0l):
        m_center{center},
        m_radius{radius}
    {}
    Circle(const Circle& other):
        m_center{other.m_center},
        m_radius{other.m_radius}
    {}
    Circle& operator=(const Circle& other){
        if (this != &other){
            m_center = other.m_center;
            m_radius = other.m_radius;
        }
        return *this;
    }
    virtual ~Circle(){}
    const Point& getCenter() const{
        return m_center;
    }
    const double& getRadius() const{
        return m_radius;
    }
    bool contain(const Point& p) const{
        double d = m_center.distanceTo(p);
        if ((std::fabs(d - m_radius) < EPS) || (d < m_radius)){
            return true;
        }
        return false;
    }
    /**
     * @brief Расчёт угла точка относительно центра окружности.
     *
     * Если точка совпадает с центром окружности,
     * возвращается угол 0.
     *
     * @param p точка, для которой выисляется угол
     * @return угол в интервале [0.0; 2.0*M_PI)
     */
    radian calcAngleByCenter(const Point& p) const{
        if (m_center == p){
            //точка совпадает с центром, вернём угол 0
            return 0.0;
        }
        //переносим начало координат в центр круга
        Point movedPoint = Point(p.getX() - m_center.getX(),
                                 p.getY() - m_center.getY());
        //рассмотрим крайние случаи - точка лежит на осях
        //на оси X
        if (std::fabs(movedPoint.getY()) < EPS){
            //слева или справа ?
            if (movedPoint.getX() < 0){
                return M_PI;
            }else{
                return 0.0;
            }
        }
        //на оси Y
        if (std::fabs(movedPoint.getX()) < EPS){
            //снизу или сверху?
            if (movedPoint.getY() < 0){
                //снизу - 3 * PI / 2
                return 3.0 * M_PI_2;
            }else{
                //сверху - PI/2
                return M_PI_2;
            }
        }
        radian ret = std::atan(movedPoint.getX()/movedPoint.getY());
        //так как atan считает угол только в первый и 4-ый сектор [-p/2; p2]
        //обработаем отдельно случаи когда точка во втором или третьем секторе
        int xSign = (movedPoint.getX() < 0.0)? 0 : 1;
        int ySign = (movedPoint.getY() < 0.0)? 0 : 1;
        int sectorMap[2][2] = {
            //отрицательные y       //положительные y
            {       3,                     2},      //отрицательные X
            {       4,                     1}       //положительные X
        };
        switch (sectorMap[xSign][ySign]) {
        case 1:
            break;
        case 2:
            ret = M_PI_2 - ret;
            break;
        case 3:
            ret = 3.0 * M_PI_2 - ret;
            break;
        case 4:
            ret += 2*M_PI;
            break;
        }
        return ret;
    }
private:
    Point m_center;
    double m_radius;
};
class Square{
public:
    Square(const Point& leftTop = {-1, -1}, double sideLength = 2.0):
        m_leftTop{leftTop},
        m_side{sideLength}
    {}
    Square(const Square& other):
        m_leftTop{other.m_leftTop},
        m_side{other.m_side}
    {}
    Square& operator=(const Square& other){
        if (this != &other){
            m_leftTop = other.m_leftTop;
            m_side = other.m_side;
        }
        return *this;
    }
    virtual ~Square(){}
    double left() const{
        return m_leftTop.getX();
    }
    double top() const{
        return m_leftTop.getY();
    }
    double right() const{
        return m_leftTop.getX() + m_side;
    }
    double bottom() const{
        return m_leftTop.getY() - m_side;
    }
    bool contain(const Point& p) const{
        return (inInterval(left(), right(), p.getX()) &&
                inInterval(bottom(), top(), p.getY()));
    }
private:
    Point m_leftTop;
    double m_side;
};
using ExpectedResult = bool;
int main() {
    std::vector<std::pair<Point, ExpectedResult> > testedPoints{
        {{-1, 1}, true},
        {{-1, -1}, true},
        {{1, 1}, true},
        {{1, -1}, false},
        {{-2, 0}, false},
        {{3, 0}, false},
        {{2, 0}, true},
        {{0, 0}, true},
        {{1, 0}, true},
        {{1.1, 0.1}, true},
        {{1.1, -0.1}, false},
        {{0.9, -0.5}, false},
        {{0.9, 0.5}, true},
        {{0.6, -0.98}, true},
        {{0.6, -0.2}, true}
    };
    Circle circle({1,0}, 1);
    Square square({-1, 1}, 2);
    auto pointInArea =
            [](const Circle& c, const Square& s, const Point& p)->bool{
                if (!(s.contain(p) || c.contain(p))){
                    //точка не содержится ни в квадрате ни в круге
                    return false;
                }
                //точка содержится или квадрате или в круге.

                if (!c.contain(p)){
                    //точка не содержится в круге => значит содержится в
                    //квадрате, и угол проверять не нужно
                    return true;
                }
                //точка содержится в круге (и, возможно в квадрате, но это уже
                //не важно, теперь надо проверить угол
                if (c.getCenter() == p){
                    //точка совпадает с центром окружности
                    return true;
                }
                radian angle = c.calcAngleByCenter(p);
                if (inInterval(0.0, 5.0* M_PI_4, angle)){
                    return true;
                }
                return false;
            };
    std::size_t passedPoints = 0;
    for (const auto& element: testedPoints){
        bool calculatedResult = pointInArea(circle, square, element.first);
        std::cout << "Point: " << element.first.getX()
                  << " " << element.first.getY() << "  calculated result: "
                  << calculatedResult << "\t expected result:"
                  << element.second << std::endl;
        if (calculatedResult == element.second){
            passedPoints++;
        }
    }
    std::cout << passedPoints << " points passed" << std::endl;
    std::cout << testedPoints.size() - passedPoints << " points failed" << std::endl;
    return 0;
}

Вывод:

Point: -1 1       calculated result: 1   expected result:1
Point: -1 -1      calculated result: 1   expected result:1
Point: 1 1        calculated result: 1   expected result:1
Point: 1 -1       calculated result: 0   expected result:0
Point: -2 0       calculated result: 0   expected result:0
Point: 3 0        calculated result: 0   expected result:0
Point: 2 0        calculated result: 1   expected result:1
Point: 0 0        calculated result: 1   expected result:1
Point: 1 0        calculated result: 1   expected result:1
Point: 1.1 0.1    calculated result: 1   expected result:1
Point: 1.1 -0.1   calculated result: 0   expected result:0
Point: 0.9 -0.5   calculated result: 0   expected result:0
Point: 0.9 0.5    calculated result: 1   expected result:1
Point: 0.6 -0.98  calculated result: 1   expected result:1
Point: 0.6 -0.2   calculated result: 1   expected result:1
15 points passed
0 points failed
READ ALSO
Распознавание речи на c++

Распознавание речи на c++

Всем привет! Для моего проекта нужна функция распознавания голоса, хочу реализовать её на C++, но не понимаю куда копатьНашёл библиотеку CMUSphinx,...

414
Изменить последующий текст в textBox`е

Изменить последующий текст в textBox`е

Мне нужно, что бы каждый последующий добавленный текст в textBox имел определённый цвет, по аналогии с консольной версией

231
Не удаётся отрисовать фигуру OpenGL

Не удаётся отрисовать фигуру OpenGL

Пытаюсь нарисовать квадрат Серпинского (не суть важно) с помощью библиотеки OpenGL в QtПока есть такой код:

240
Какая проблема в этом коде? [требует правки]

Какая проблема в этом коде? [требует правки]

Xcode явных ошибок не находит, но показывает вот такие эрроры:

206