已知一个点的坐标,如何判断该点是否在某扇形里面。

AIQ. 2012-06-05 12:02:23
先插图


平均分成8份。从0°开始,每份45°。 如何判断改点在哪个扇形区域里面?(已知点的坐标)。 在线等 急急急·!!!
...全文
1232 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
Athenacle_ 2012-06-05
  • 打赏
  • 举报
回复
哇,,慢了啊,,,

如果用tan算的话,要以圆心做为原点,从而把三角函数值分出正负才能区分象限
Athenacle_ 2012-06-05
  • 打赏
  • 举报
回复
1.判断是否在圆内,带入圆方程就行了

2.不用三角函数,把整个坐标系分为8个等分。分割线分别为坐标轴和函数 y=x 和 y=-x,根据(x,y)的取值范围直接判断就行了

情况1 : x>0 y>0 第一象限, 若x>y,在第一象限的上半部分,否则下半部分
情况2 : x<0 y>0 第二象限,若x>-y,在第二象限的上半部分,否则下半部分
情况3 :x<0 y<0 第三象限。。。。。。
情况4 : x>0 y<0 第四象限。。。。。。


nice_cxf 2012-06-05
  • 打赏
  • 举报
回复
先判断是不是在圆内(x*x+y*y<=r*r),以下按5楼说的即可
CandPointer 2012-06-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

直角坐标系:
tan θ = y/x

即可判断
[/Quote]

或者更简单的

x>0, y>0, x>y, 第1扇形
x>0, y>0, x<y, 第2扇形
x<0, y>0, -x<y, 第3扇形
x<0, y>0, -x>y, 第4扇形
x<0, y<0, x>y, 第5扇形
x<0, y<0, x>y, 第6扇形
x>0, y<0, x<-y, 第7扇形
x>0, y<0, x>-y, 第8扇形

几个 ?: 运算符可搞定
西山小月 2012-06-05
  • 打赏
  • 举报
回复
判断横纵坐标就可以啊
CandPointer 2012-06-05
  • 打赏
  • 举报
回复
直角坐标系:
tan θ = y/x

即可判断
A_Zhao 2012-06-05
  • 打赏
  • 举报
回复
为了解决上述的“信息丢失”问题,我们必须找到一种信息不会丢失的等价变换。

在数学里面,实现这种等价变换的工具已经有了,那就是复数vs复平面(上的点)。

任何平面上的点(不论是用直角坐标系刻画,还是用极坐标系刻画),都等价于复平面上的点。

那么,我们可以把楼主的题目中的自由点A(xA,yA)视为复平面上的点。

根据高斯(C.F.Gauss)的原则,复平面上的点与复数是一一对应的。

即,自由点A(xA,yA)与复数Z=xA+yAi完全等价。

也即,自由点A的纵横坐标值与复数Z的虚实二部(不是任督二脉)完全等价。

从复数Z的虚实二部,变换为复数的模和辐角,这个过程中信息不会丢失。

而复数的模(mod)和辐角(arg)正是解答本题的关键:

(一)将复数Z的模与预设的圆半径比较大小,可以判别自由点是否超越圆周范围。

(二)根据复数Z的辐角,可以判别自由点落在哪个扇区。

进入C++ 解题:

(一)计算复数Z的模,很简单,纵横坐标值的平方和再开平方。

(二)计算复数Z的辐角,要注意,C++的<math.h>提供的atan反正切函数,只能计算出值域为从-PI/2到PI/2的所谓“主值”,这样不足以匹配8个扇区。所幸的是,<math.h>提供了atan2函数,该函数接受两个double参数即点的纵横二坐标值,可以计算出值域为从-PI到PI的全圆周角值。

上述解法,就是我贴在8楼的代码。

以上,仅供参考,呵呵……

A_Zhao 2012-06-05
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

我觉得要判断三次
第一次:判断是否在直线之上 a*x+b>y
第二次:判断是否在另一条直线之下 a*x+b<y
第三次:判断是否在圆内 sqrt(x^2+y^2)<R
[/Quote]

这个……有点麻烦了……

题目中没有“直线”一设,为什么要另外引入“直线”?

“直线”指的是什么?

在本题中,最多只应该有两种直线(如果再另外构造出其他的直线的话,只会令问题更加麻烦):

(1)分割扇区的径向线段所在的直线;

(2)过原点与自由点A(xA,yA)的直线。

所有这些直线,均过原点,所以直线方程y=ax+b中的常数项b恒等于0;

那么,直线方程的形式为 y=ax。

那么,分割出8个扇区的4条直线的方程为:

y=0

y=x

x=0

y=-x

自由点所在直线的方程为:

y=(yA/xA)*x

四条恒定直线,一条自由直线,能分别出8种情况吗?(忽略重合情况)

四条恒定直线,只能分别出4种情况。不能分别出8种情况。

为什么不能?

因为,原来自由点有两个自由度(xA、yA),现在用直线来表征它,就只剩下一个自由度(直线的斜率即yA/xA)了。

信息丢失了。

信息丢失的结果是什么?

比如说,自由点A取(xA=1,yA=2),表征它的直线是y=2x,夹在y=x和x=0两条直线之间,即第2扇区和第6扇区都符合。

怎么判别,点A到底是落在第2扇区,还是第6扇区?

只能再通过判别xA、yA两值的正负来做。

上面还少了一步,判断y=2x夹在y=x和x=0两条直线之间,这种判断是如何实现的?

直线的斜率。

但是,问题又来了,x=0这条直线的斜率是无穷大。

人脑有无穷大的观念,电脑可没有。

复杂了……

以上,仅供参考。

呵呵……
AIQ. 2012-06-05
  • 打赏
  • 举报
回复
真的没人吗····
AIQ. 2012-06-05
  • 打赏
  • 举报
回复
该点,,打错了
W170532934 2012-06-05
  • 打赏
  • 举报
回复
楼上各位都挺牛
jiandingzhe 2012-06-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

引用 3 楼 的回复:

直角坐标系:
tan θ = y/x

即可判断


或者更简单的

x>0, y>0, x>y, 第1扇形
x>0, y>0, x<y, 第2扇形
x<0, y>0, -x<y, 第3扇形
x<0, y>0, -x>y, 第4扇形
x<0, y<0, x>y, 第5扇形
x<0, y<0, x>y, 第6扇形
x>0, y<0, x<……
[/Quote]
赞一个。不过你没判断半径。
proorck6 2012-06-05
  • 打赏
  • 举报
回复
我觉得要判断三次
第一次:判断是否在直线之上 a*x+b>y
第二次:判断是否在另一条直线之下 a*x+b<y
第三次:判断是否在圆内 sqrt(x^2+y^2)<R

A_Zhao 2012-06-05
  • 打赏
  • 举报
回复
按照楼主的题意,随手写了一段:


#include<iostream>
#include<math.h>

#define PI 3.1415926 //宏定义PI,意图是:一个圆周率的近似值。
using namespace std;

int whichSector(double X, double Y, double R) {

double mod;
mod = sqrt(X * X + Y * Y); //将点(X,Y)视为复平面上的点,与复数一一对应,现求复数的模。

double arg;
arg = atan2(Y, X); //求复数的辐角。

if (mod > R) { //如果复数的模大于预设的半径,则返回0。
return 0;
} else { //根据复数的辐角来判别该点落在那个扇区。
if (arg > (double) (0.0 * PI / 4.0)
&& arg < (double) (1.0 * PI / 4.0)) {
return 1;
}
if (arg > (double) (1.0 * PI / 4.0)
&& arg < (double) (2.0 * PI / 4.0)) {
return 2;
}
if (arg > (double) (2.0 * PI / 4.0)
&& arg < (double) (3.0 * PI / 4.0)) {
return 3;
}
if (arg > (double) (3.0 * PI / 4.0)
&& arg < (double) (4.0 * PI / 4.0)) {
return 4;
}
if (arg > (double) (-4.0 * PI / 4.0)
&& arg < (double) (-3.0 * PI / 4.0)) {
return 5;
}
if (arg > (double) (-3.0 * PI / 4.0)
&& arg < (double) (-2.0 * PI / 4.0)) {
return 6;
}
if (arg > (double) (-2.0 * PI / 4.0)
&& arg < (double) (-1.0 * PI / 4.0)) {
return 7;
}
if (arg > (double) (-1.0 * PI / 4.0)
&& arg < (double) (-0.0 * PI / 4.0)) {
return 8;
}
return 999; //这是几率极低的事件。
}
return 0;
}

int main(void) {
double r, x, y;

cout << "Please tell me the Radius of your Circle:" << endl;
cin >> r;

cout << "Please tell me the value of X of your Point:" << endl;
cin >> x;

cout << "Please tell me the value of Y of your Point:" << endl;
cin >> y;

int w;
w = whichSector(x, y, r);

if (0 == w) {
cout << "Your point is OUT of your Circle!" << endl;
return 0;
} else {
if (999 == w) {
cout
<< "Oops... Your Point is ***critically*** ON a border that belongs to no sector!"
<< endl;

} else {
cout << "Your Point is ON a certain area of the sector #" << w
<< "." << endl;
}
}

return 0;

}


说明:
(1)以上代码,gcc -std=c99 编译OK!
(2)限于平台的计算精度,难以避免地,会出现解答(1,1)点为落在第2扇区等这样的情况。
(3)随手写的,欢迎大虾们修正、完善!

以上,仅供参考。

呵呵……

zhengjiankang 2012-06-05
  • 打赏
  • 举报
回复
好复杂丫。。。
A_Zhao 2012-06-05
  • 打赏
  • 举报
回复
我在上面提到的解法,虽然完全符合数学原理,但在计算机上运算,却有着致命的缺陷。

那就是:复数可以与实数对一一对应,而实数在数轴上是连续分布的。但是,计算机里的数字,都是以离散形态存在的。

那么,用计算机计算实数,不可避免地,将会有误差,而有些误差会造成定性判断的错误。

之前的解法,在上述问题上的风险,还是比较显著的。

于是,我们要寻找一个更加接近离散性判断的方法。

我们观察到,圆周内部区域,被分割为8个扇区。这8个扇区乃辐射对称且全等。

8等于2的3次方,这意味着,8个离散量必然可以用3个二元离散量的有序排列来一一对应。

二元离散量有3个,这意味着我们在题目中,要找到合适的关于自由点的三个自由度。

对于自由点A(x,y),最合适的三个自由度:

(1)x>0 的真值;
(2)y>0 的真值;
(3)x^2>y^2 的真值(为什么是x和y的平方比较,而不用x>y?请思考一下……)。

可以列出如下真值表:


+-------+-------+-------+------+-------+--------+
| x>0 | y>0 |x^2>y^2| Code | dValue| Sector#|
+-------+-------+-------+------+-------+--------+
| 1 | 1 | 1 | 111 | 7 | 1 |
+-------+-------+-------+------+-------+--------+
| 1 | 1 | 0 | 110 | 6 | 2 |
+-------+-------+-------+------+-------+--------+
| 0 | 1 | 0 | 010 | 2 | 3 |
+-------+-------+-------+------+-------+--------+
| 0 | 1 | 1 | 011 | 3 | 4 |
+-------+-------+-------+------+-------+--------+
| 0 | 0 | 1 | 001 | 1 | 5 |
+-------+-------+-------+------+-------+--------+
| 0 | 0 | 0 | 000 | 0 | 6 |
+-------+-------+-------+------+-------+--------+
| 1 | 0 | 0 | 100 | 4 | 7 |
+-------+-------+-------+------+-------+--------+
| 1 | 0 | 1 | 101 | 5 | 8 |
+-------+-------+-------+------+-------+--------+


将三个真值按序排列,得到“Code”(编码),将Code视为一个二进制数,再将其值转化为十进制数值(dValue)。

可以看出,从dValue映射到扇区编号(Sector#),是双射(单射、满射),所以,可以构造一个完美Hash表:


+-------+--------+
| dValue| Sector#|
+-------+--------+
| 0 | 6 |
+-------+--------+
| 1 | 5 |
+-------+--------+
| 2 | 3 |
+-------+--------+
| 3 | 4 |
+-------+--------+
| 4 | 7 |
+-------+--------+
| 5 | 8 |
+-------+--------+
| 6 | 2 |
+-------+--------+
| 7 | 1 |
+-------+--------+


数学模型已经就绪,下面是C++代码:


#include<iostream>

using namespace std;

int main(void) {

int sector[] = { 6, 5, 3, 4, 7, 8, 2, 1 };

double r, x, y;

cout << "Please tell me the Radius of your Circle:" << endl;
cin >> r;

cout << "Please tell me the value of X of your Point:" << endl;
cin >> x;

cout << "Please tell me the value of Y of your Point:" << endl;
cin >> y;

if (x * x + y * y > r * r) {
cout << "Your point is OUT of your Circle!" << endl;
} else {
cout<< "Your Point is ON a certain area of the sector #"
<< sector[(int) (x > 0) * 4 + (int) (y > 0) * 2
+ (int) (x * x > y * y)] << "." << endl;

}

return 0;

}


呵呵,以上,仅供参考……



65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧