计算几何一点点

定义:平面上的三点P1(x1,y1),P2(x2,y2),P3(x3,y3)的面积量:
                  |x1  x2  x3|
    S(P1,P2,P3) = |y1  y2  y3| = (x1-x3)*(y2-y3) - (y1-y3)(x2-x3)
                  |1   1   1 |
当P1P2P3逆时针时S为正的,当P1P2P3顺时针时S为负的。
 
令矢量的起点为A,终点为B,判断的点为C,
   如果S(A,B,C)为正数,则C在矢量AB的左侧;
   如果S(A,B,C)为负数,则C在矢量AB的右侧;
   如果S(A,B,C)为0,则C在直线AB上。

对于有公共端点的线段p0p1和p1p2,通过计算(p2- p0) × (p1 - p0)的符号便可以确定折线段的拐向:

若(p2- p0) × (p1 - p0) > 0,p0p1在p1点拐向右侧后得到p1p2。  

若(p2- p0) × (p1 - p0) < 0,p0p1在p1点拐向左侧后得到p1p2。  

若(p2- p0) × (p1 - p0) = 0, p0 p1 p2 三点 共线
    所以第二种判断方法为:

bool chaji(dia p0,dia p1,dia p2)
{
    if(((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x))<0)//p0  p2 分别表示线段的两端,p1为要判断的点
    {
        return true;
    }
    else
    return false;
}
poj  2318  toy

题意:给出n个板子,分隔成n+1块区域,再给出m个玩具,求在每个区域中有多少玩具。
解题思路: 对于每一个玩具,依次从左到右判断每个玩具是不是在该板子左侧,如果在,则将此位置数量加1,注意最后一块区域,一定要计数。

Calculate the number of toys that land in each bin of a partitioned toy box.
Mom and dad have a problem - their child John never puts his toys away when he is finished playing with them. They gave John a rectangular box to put his toys in, but John is rebellious and obeys his parents by simply throwing his toys into the box. All the toys get mixed up, and it is impossible for John to find his favorite toys.

John's parents came up with the following idea. They put cardboard partitions into the box. Even if John keeps throwing his toys into the box, at least toys that get thrown into different bins stay separated. The following diagram shows a top view of an example toy box.

For this problem, you are asked to determine how many toys fall into each partition as John throws them into the toy box.
Input
The input file contains one or more problems. The first line of a problem consists of six integers, n m x1 y1 x2 y2. The number of cardboard partitions is n (0 < n <= 5000) and the number of toys is m (0 < m <= 5000). The coordinates of the upper-left corner and the lower-right corner of the box are (x1,y1) and (x2,y2), respectively. The following n lines contain two integers per line, Ui Li, indicating that the ends of the i-th cardboard partition is at the coordinates (Ui,y1) and (Li,y2). You may assume that the cardboard partitions do not intersect each other and that they are specified in sorted order from left to right. The next m lines contain two integers per line, Xj Yj specifying where the j-th toy has landed in the box. The order of the toy locations is random. You may assume that no toy will land exactly on a cardboard partition or outside the boundary of the box. The input is terminated by a line consisting of a single 0.
Output
The output for each problem will be one line for each separate bin in the toy box. For each bin, print its bin number, followed by a colon and one space, followed by the number of toys thrown into that bin. Bins are numbered from 0 (the leftmost bin) to n (the rightmost bin). Separate the output of different problems by a single blank line.
Sample Input
5 6 0 10 60 0
3 1
4 3
6 8
10 10
15 30
1 5
2 1
2 8
5 5
40 10
7 9
4 10 0 10 100 0
20 20
40 40
60 60
80 80
 5 10
15 10
25 10
35 10
45 10
55 10
65 10
75 10
85 10
95 10
0
Sample Output
0: 2
1: 1
2: 1
3: 1
4: 0
5: 1

0: 2
1: 2
2: 2
3: 2
4: 2

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
int m,n;
const int maxn = 5005;
int coun[maxn];
struct dia
{
    int x;
    int y;
}dian[maxn]; // 每个点的横纵坐标
struct lin
{
    dia a;//a  dixia
    dia b;
}line[maxn];//上边  下边
bool chaji(dia p0,dia p1,dia p2)//判断点在直线左侧
{
    if(((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x))<0)
    {
        return true;
    }
    else
    return false;
}
void judge(dia pp)
{
    for(int i = 0; i < n; i++)
    {
       if(chaji(line[i].b,pp,line[i].a)>0)
       {
           coun[i]++;
           return ;
       }
    }
    coun[n]++;
    return ;
}
int main()
{
int c,d,e,f;
while(cin>>n&&n)
{
    memset(coun,0,sizeof(coun));
    cin>>m;
    cin>>c>>d>>e>>f;
    for(int i = 0; i < n; i++)
    {
      cin>>line[i].a.x;
      cin>>line[i].b.x;
      line[i].b.y = f;
      line[i].a.y = d;
    }
     dia pp;
    for(int i = 0; i < m; i++)
    {
        cin>>pp.x>>pp.y;
        judge(pp);
    }
    for(int i = 0; i <= n; i++)
    {
        printf("%d: %d\n",i,coun[i]);
    }
    printf("\n");
}
}
poj   2398(上一道题的进阶)
题意:板子是无序的,最终输出相同玩具区域的个数
稍作改变:
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
int m,n;
const int maxn = 5005;
int coun[maxn];
struct dia
{
    int x;
    int y;
}dian[maxn]; // 每个点的横纵坐标
struct lin
{
    dia a;//a  dixia
    dia b;
}line[maxn];//上边  下边
bool cmp(const lin &u,const lin &v)
{
    if(u.a.x!=v.a.x)
        return u.a.x<v.a.x;
           // return u.a.y<v.a.y;
}
bool chaji(dia p0,dia p1,dia p2)//判断点在直线左侧
{
    if(((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x))<0)
    {
        return true;
    }
    else
    return false;
}
int cnt[5005], ans[5005];

void judge(dia pp)
{
    for(int i = 0; i < n; i++)
    {
       if(chaji(line[i].b,pp,line[i].a)>0)
       {
           coun[i]++;
           return ;
       }
    }
    coun[n]++;
    return ;
}
int main()
{
int c,d,e,f;
while(cin>>n&&n)
{
    memset(coun,0,sizeof(coun));
    memset(ans,0,sizeof(ans));
    cin>>m;
    cin>>c>>d>>e>>f;
    for(int i = 0; i < n; i++)
    {
      cin>>line[i].a.x;
      cin>>line[i].b.x;
      line[i].b.y = f;
      line[i].a.y = d;
    }
   sort(line,line+n,cmp);
     dia pp;
    for(int i = 0; i < m; i++)
    {
        cin>>pp.x>>pp.y;
        judge(pp);
    }
 /*  for(int i = 0; i <= n; i++)
    {
        printf("%d: %d\n",i,coun[i]);
    }*/
            int t = 0;
            for(int i = 0; i <= n; i++)
            {
                ans[coun[i]]++;
            }
            printf("Box\n");
            for(int i = 1; i < n; i++)
            {
                if(ans[i]!=0)
                {
                 printf("%d: %d\n",i,ans[i]);
                }
            }

}
}

判断点在凸多边形内部:
原理:凸多边形内部的点都在凸多边形的边所在的向量的同一侧(前提是计算边所在的向量时采用的是同一个方向,同为顺时针或者同为逆时针),利用叉积求解。
假设四边形四个顶点依次为A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),待判断的点为P(x,y),如果点P在四边形内部,则向量AB * AP(注意:1.这是求叉积;2.AB、AP均为向量,也就等于(x2-x1) * (y-y1)-(y2-y1) * (x-x1))的值与BC*BP、CD * CP、DA * DP的值同号(若有等于零的情况,则表示P在边上,可以根据自己的喜好把它当做是内部或者外部),即四个值同为正或者同为负,则点P在ABCD内部,否则在外部。

private boolean isPointInRect(int x, int y) {
  final Point A = mLBPoint;
  final Point B = mLTPoint;
  final Point C = mRTPoint;
  final Point D = mRBPoint;
  final int a = (B.x - A.x)*(y - A.y) - (B.y - A.y)*(x - A.x);
  final int b = (C.x - B.x)*(y - B.y) - (C.y - B.y)*(x - B.x);
  final int c = (D.x - C.x)*(y - C.y) - (D.y - C.y)*(x - C.x);
  final int d = (A.x - D.x)*(y - D.y) - (A.y - D.y)*(x - D.x);
  if((a > 0 && b > 0 && c > 0 && d > 0) || (a < 0 && b < 0 && c < 0 && d < 0)) {
   return true;
  }
  
//  AB X AP = (b.x - a.x, b.y - a.y) x (p.x - a.x, p.y - a.y) = (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x);
//  BC X BP = (c.x - b.x, c.y - b.y) x (p.x - b.x, p.y - b.y) = (c.x - b.x) * (p.y - b.y) - (c.y - b.y) * (p.x - b.x);
  return false;
 }

https://blog.csdn.net/liangzhaoyang1/article/details/51090370#     判断线段相交

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值