Здравствуйте! Какие условия надо задать, чтобы узнать попадает ли точка в заданную область?
Я немного переборщил, но это работает (я верю).
Основная функция:
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
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Всем привет! Для моего проекта нужна функция распознавания голоса, хочу реализовать её на C++, но не понимаю куда копатьНашёл библиотеку CMUSphinx,...
Мне нужно, что бы каждый последующий добавленный текст в textBox имел определённый цвет, по аналогии с консольной версией
Пытаюсь нарисовать квадрат Серпинского (не суть важно) с помощью библиотеки OpenGL в QtПока есть такой код:
Xcode явных ошибок не находит, но показывает вот такие эрроры: