计算面积 - 多边形相关(面积,点的位置)

三角形:海伦公式

S = 1 2 ( x 1 y 2 + x 2 y 3 + x 3 y 1 − x 1 y 3 − x 2 y 1 − x 3 y 2 ) ; S = \frac 12 (x1y2+x2y3+x3y1-x1y3-x2y1-x3y2); S=21(x1y2+x2y3+x3y1x1y3x2y1x3y2);

//三角形面积
double sTriangulation1(vector<double>x, vector<double>y) {
	//海伦公式
	double S =0.5* ((x[0]*y[1] + x[1]*y[2] + x[2]*y[0]) - (x[1]*y[0] + x[2]*y[1] + x[0]*y[2]));
	if (S < 0)
		return -S;
	return S;
}

double sTriangulation2(vector<double>x, vector<double>y) {
     //向量  与原点
	int n = x.size();
	double sum = 0;
	for (int i = 0; i < n; i++) {
		sum += 0.5 * (x[i]*y[(i+1)%n]-x[(i+1)%n]*y[i]);
	}
	if (sum < 0)
		sum = -sum;
	return sum;
}

多边形面积

考虑有凹边形,统一使用 向量 计算面积的方式,有正负
思路 : 向量法 (点数组需要时顺/逆时针排序的)

  • S A B C = 1 2 A B → ∗ B C → S_{ABC} =\frac 1 2\overrightarrow{AB} * \overrightarrow{BC} SABC=21AB BC
  • 以 原点(0,0) 为 第一个点,那么三角学的面积可以写成
    S A B C = S O B C − S O A B − S O A C S_{ABC}=S_{OBC}-S_{OAB}-S_{OAC} SABC=SOBCSOABSOAC
    这里默认 BC是最远的边,但一般不知是哪个边,无法提前确认+ -,故都使用 向量去做
  • S A B C = S O A B + S O B C + S O C A S_{ABC}=S_{OAB}+S_{OBC}+S_{OCA} SABC=SOAB+SOBC+SOCA
    (上一个结束点 是下一个开始点 循环到第一个开始点)
  • 同理 五边形ABCDE有:
    S A B C D E = S O A B + S O B C + S O C D + S O D E + S O E A S_{ABCDE}=S_{OAB}+S_{OBC}+S_{OCD}+S_{ODE}+S_{OEA} SABCDE=SOAB+SOBC+SOCD+SODE+SOEA
    对于一个 S O A B S_{OAB} SOAB的计算公式; 其中 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2)
    S = 1 2 0 A → ∗ 0 B → = 1 2 ( x 1 ∗ y 2 − x 2 ∗ y 1 ) S=\frac 1 2\overrightarrow{0A} * \overrightarrow{0B}=\frac12(x_1*y_2-x_2*y_1) S=210A 0B =21x1y2x2y1

//x={1,0,-1,0},y={0,1,0,-1}; S=2.0
//x={0,1,0},y={0,0,1}; S=0.5


double SumTriangulation(vector<double>x, vector<double>y) {

	//看成任意两边间与原点的面积(有正负)//N个 最后一个是OEA
	int n = x.size();//n个点   有n-1次
	vector<double> sum;
	double s = 0.0;
	for (int i = 0; i < n-1; i++) {
		s= 0.5 * (x[i] * y[i + 1] - x[i + 1]*y[i]);
		sum.push_back(s);
	}
	//最后一个三角形 OEA
	s= 0.5 * (x[n-1] * y[0] - x[0] * y[n-1]);
	sum.push_back(s);
	s = 0;
	//输出看看
	for (int i = 0; i < sum.size(); i++) {
		cout << sum[i] << " ";
		s += sum[i];
	}
	cout <<endl;
	return s;
}

P点是否在多边形内

思路:射线法 (默认时顺/逆时针排序的)

  • 通过p点引出一条 水平右射线
  • 判断射线与 多边形的边的交点和数量,奇数就是在内
  • 特殊边界:
    • 交点刚好是多边形的点,不算
    • 交点在左边,不算
  • 加速判断 P(x,y) 与 边 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_2,y_2) (x1,y1),(x2,y2)
    • y > = m a x ( y 1 , y 2 ) y>=max(y_1,y_2) y>=max(y1,y2), 没有
    • y < = m i n ( y 1 , y 2 ) y<=min(y_1,y_2) y<=min(y1,y2),没有 (这两包含了 交点刚好是边的情况)
    • x > = m a x ( x 1 , x 2 ) x>=max(x_1,x_2) x>=max(x1,x2),没有
    • y 1 = = y 2 y_1==y_2 y1==y2 ,边水平,没有
  • 利用两点式,求出 交点 X
    两点式: y − y 1 X − x 1 = y 2 − y 1 x 2 − x 1 = \frac{y-y_1}{X-x_1}=\frac{y_2-y_1}{x_2-x_1}= Xx1yy1=x2x1y2y1=
    转化为: X = ( y − y 1 ) ∗ ( x 2 − x 1 ) ( y − y 1 ) + x 1 X=\frac{(y-y_1)*(x_2-x_1)}{(y-y_1)}+x_1 X=(yy1)(yy1)(x2x1)+x1
//点在多边面内
//map<pair<int,int>>(x,y)
bool PtInPolygon(vector<double>x, vector<double>y, double px, double py) {

	int n = x.size();
	int count = 0;
	for (int i = 0; i < n; i++) {
		//判断 是否跳过
		if(y[i]==y[(i + 1) % n]) continue;
		if(py>= max(y[i], y[(i + 1) % n])) continue;
		if(py<= min(y[i], y[(i + 1) % n])) continue;
		if(px>= max(x[i], x[(i + 1) % n])) continue;
		
		//两点式
		double X = ((y[(i + 1) % n] - y[i]) * (x[(i + 1) % n])/(py-y[i]) - x[i]) + x[i];

		if (X > px) //还是有出现在左边的情况 去掉
			count++;
	}
	if (count % 2 == 1)
		return true;
	return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值