多边形与多边形 位置关系的判断
2016-04-24 14:11
691 查看
C#判断点的位置方法一
public int isLeft(Point
P0, Point P1,Point P2)
{
int abc= ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y));
return abc;
}
private bool PointInFences(Point
pnt1, Point[] fencePnts)
{
int wn = 0,j=0; //wn
计数器 j第二个点指针
for (int i
= 0; i < fencePnts.Length; i++)
{//开始循环
if (i == fencePnts.Length - 1)
j = 0;//如果 循环到最后一点第二个指针指向第一点
else
j = j + 1; //如果不是,则找下一点
if (fencePnts[i].Y < = pnt1.Y) //
如果多边形的点 小于等于 选定点的 Y 坐标
{
if (fencePnts[j].Y > pnt1.Y) //
如果多边形的下一点 大于于 选定点的 Y 坐标
{
if (isLeft(fencePnts[i], fencePnts[j], pnt1) > 0)
{
wn++;
}
}
}
else
{
if (fencePnts[j].Y < = pnt1.Y)
{
if (isLeft(fencePnts[i], fencePnts[j], pnt1) < 0)
{
wn--;
}
}
}
}
if (wn == 0)
return false;
else
return true;
}
C#判断点的位置方法二——c#内置函数:
GraphicsPath myGraphicsPath = new GraphicsPath();
Region myRegion=new Region();
myGraphicsPath.Reset();
Point inputponint = new Point(inputx, inputy);
myGraphicsPath.AddPolygon(points);//points);
myRegion.MakeEmpty();
myRegion.Union(myGraphicsPath);
//返回判断点是否在多边形里
bool myPoint= myRegion.IsVisible(inputponint);
this.lblx.Text = myPoint.ToString();
图形算法:
1,面积法。就是看所有边和目标点组成的三角形面积和是否等于总的多边形面积,如果相等,则在内部。反之在外部。这种方法计算量较大,用到的主要计算是查乘。
2,夹角和法。参见三楼,判断所有边和目标点的夹角和是否为360度。计算量比上面这种方法稍微小点,用到主要是点乘和求模计算。
3,引射线法。就是从该点出发引一条射线,看这条射线和所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部。这是所有方法中计算量最小的方法,在光线追踪算法中有大量的应用。
在C#中的话,有一个Region类,可以直接调用IsVisible判断是否在这个区域内部,我估计内部的实现应该是上面说的第三种方法。主要看你的需求是哪种输入了,如果在C#中,你完全可以用Region类来隐藏内部实现。
C#判断点的位置的另外一种解决方法:
1.已知点point(x,y)和多边形Polygon(x1,y1;x2,y2;….xn,yn;);
2.以point为起点,以无穷远为终点作平行于X轴的直线line(x,y; -∞,y);
3.循环取得(for(i=0;i< n;i++))多边形的每一条边side(xi,yi;xi+1,yi+1),且判断是否平行于X轴,如果平行continue,否则,i++;
4. 同时判断point(x,y)是否在side上,如果是,则返回1(点在多边形上),否则继续下面的判断;
5.判断线side与line是否有交点,如果有则count++,否则,i++。
6.判断交点的总数,如果为奇数则返回0(点在多边形内),偶数则返回2(点在多边形外)。
代码:
const double INFINITY
= 1e10;
const double ESP
= 1e-5;
const int MAX_N
= 1000;
struct Point {
double x, y;
};
struct LineSegment {
Point pt1, pt2;
};
typedef vector< Point> Polygon;
// 计算叉乘 |P0P1| × |P0P2|
double Multiply(Point p1, Point p2, Point p0)
{
return ( (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) );
}
// 判断线段是否包含点point
bool IsOnline(Point point, LineSegment line)
{
return( ( fabs(Multiply(line.pt1, line.pt2, point)) < ESP ) &&
( ( point.x - line.pt1.x ) * ( point.x - line.pt2.x ) < = 0 ) &&
( ( point.y - line.pt1.y ) * ( point.y - line.pt2.y ) < = 0 ) );
}
// 判断线段相交
bool Intersect(LineSegment L1, LineSegment L2)
{
return( (max(L1.pt1.x, L1.pt2.x) >= min(L2.pt1.x, L2.pt2.x)) &&
(max(L2.pt1.x, L2.pt2.x) >= min(L1.pt1.x, L1.pt2.x)) &&
(max(L1.pt1.y, L1.pt2.y) >= min(L2.pt1.y, L2.pt2.y)) &&
(max(L2.pt1.y, L2.pt2.y) >= min(L1.pt1.y, L1.pt2.y)) &&
(Multiply(L2.pt1, L1.pt2, L1.pt1) * Multiply(L1.pt2, L2.pt2, L1.pt1) >= 0) &&
(Multiply(L1.pt1, L2.pt2, L2.pt1) * Multiply(L2.pt2, L1.pt2, L2.pt1) >= 0)
);
}
// 判断点在多边形内
bool InPolygon(const Polygon&
polygon, Point point)
{
int n = polygon.size();
int count = 0;
LineSegment line;
line.pt1 = point;
line.pt2.y = point.y;
line.pt2.x = - INFINITY;
for( int i
= 0; i < n; i++ ) {
// 得到多边形的一条边
LineSegment side;
side.pt1 = polygon[i];
side.pt2 = polygon[(i + 1) % n];
if( IsOnline(point, side) ) {
return1 ;
}
// 如果side平行x轴则不作考虑
if( fabs(side.pt1.y - side.pt2.y) < ESP ) {
continue;
}
if( IsOnline(side.pt1, line) ) {
if( side.pt1.y > side.pt2.y ) count++;
} else if(
IsOnline(side.pt2, line) ) {
if( side.pt2.y > side.pt1.y ) count++;
} else if(
Intersect(line, side) ) {
count++;
}
}
if ( count % 2 == 1 ) {return 0;}
else { return 2;}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
GraphicsPath gp1 = new GraphicsPath();
GraphicsPath gp2 = new GraphicsPath();
gp1.AddPolygon(new Point[] { new Point(100, 0), new Point(150, 100), new Point(200, 0),
new Point(100, 300), new Point(150, 200), new Point(200, 300)});
gp2.AddRectangle(new Rectangle(new Point(0,50),new Size(300,200)));
g.FillPath(Brushes.Green, gp2);
g.FillPath(Brushes.GreenYellow, gp1);
Region region = new Region(gp1);
region.Intersect(gp2); //求长方形和多边形的交集
g.FillRegion(Brushes.Red, region);//用红色填充
}
最近项目需要判断两个图形要素是否相交的问题:
一个图形元素是GraphicsPath 构造的闭合多边形,另一个图形元素是矩形,然后用region.interSect(矩形)来获取两者的交集元素,但明明是有交集的,返回的交集却为空。
可能的原因是构建图形要素的值太小造成的返回结果不准确,创建图形要素的坐标限定在:{x:(-180,180)} {y:(-90,90)}
请问有什么办法可以使下面的交集能够正确返回?
注:下面的两图形元素肯定是有交集的。
public void intersectTestx(PaintEventArgs e)
{
PointF[] pts = new PointF[4];
pts[0] = new PointF(115.116066f, 40.48523f);
pts[1] = new PointF(115.879951f, 40.5706635f);
pts[2] = new PointF(116.040909f, 39.998024f);
pts[3] = new PointF(115.283585f, 39.9120445f);
//构建GraphicsPath对象
GraphicsPath gpTmp1 = new GraphicsPath(System.Drawing.Drawing2D.FillMode.Alternate);
gpTmp1.AddPolygon(pts);
//构建region对象
Region rgnTmp = new Region(gpTmp1);
SolidBrush myBrush1 = new SolidBrush(Color.Black);
e.Graphics.FillRegion(myBrush1, rgnTmp);
//构建矩形对象
RectangleF recOri = new RectangleF(115.67f, 40.27f, 0.29f, 0.36f);
e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(recOri));
//获取矩形对象和region对象的交集
rgnTmp.Intersect(recOri);
// Fill the intersection area of myRegion with blue.
SolidBrush myBrush = new SolidBrush(Color.Blue);
e.Graphics.FillRegion(myBrush, rgnTmp);
}
分不多,请大家见谅!谢谢。
public int isLeft(Point
P0, Point P1,Point P2)
{
int abc= ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y));
return abc;
}
private bool PointInFences(Point
pnt1, Point[] fencePnts)
{
int wn = 0,j=0; //wn
计数器 j第二个点指针
for (int i
= 0; i < fencePnts.Length; i++)
{//开始循环
if (i == fencePnts.Length - 1)
j = 0;//如果 循环到最后一点第二个指针指向第一点
else
j = j + 1; //如果不是,则找下一点
if (fencePnts[i].Y < = pnt1.Y) //
如果多边形的点 小于等于 选定点的 Y 坐标
{
if (fencePnts[j].Y > pnt1.Y) //
如果多边形的下一点 大于于 选定点的 Y 坐标
{
if (isLeft(fencePnts[i], fencePnts[j], pnt1) > 0)
{
wn++;
}
}
}
else
{
if (fencePnts[j].Y < = pnt1.Y)
{
if (isLeft(fencePnts[i], fencePnts[j], pnt1) < 0)
{
wn--;
}
}
}
}
if (wn == 0)
return false;
else
return true;
}
C#判断点的位置方法二——c#内置函数:
GraphicsPath myGraphicsPath = new GraphicsPath();
Region myRegion=new Region();
myGraphicsPath.Reset();
Point inputponint = new Point(inputx, inputy);
myGraphicsPath.AddPolygon(points);//points);
myRegion.MakeEmpty();
myRegion.Union(myGraphicsPath);
//返回判断点是否在多边形里
bool myPoint= myRegion.IsVisible(inputponint);
this.lblx.Text = myPoint.ToString();
图形算法:
1,面积法。就是看所有边和目标点组成的三角形面积和是否等于总的多边形面积,如果相等,则在内部。反之在外部。这种方法计算量较大,用到的主要计算是查乘。
2,夹角和法。参见三楼,判断所有边和目标点的夹角和是否为360度。计算量比上面这种方法稍微小点,用到主要是点乘和求模计算。
3,引射线法。就是从该点出发引一条射线,看这条射线和所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部。这是所有方法中计算量最小的方法,在光线追踪算法中有大量的应用。
在C#中的话,有一个Region类,可以直接调用IsVisible判断是否在这个区域内部,我估计内部的实现应该是上面说的第三种方法。主要看你的需求是哪种输入了,如果在C#中,你完全可以用Region类来隐藏内部实现。
C#判断点的位置的另外一种解决方法:
1.已知点point(x,y)和多边形Polygon(x1,y1;x2,y2;….xn,yn;);
2.以point为起点,以无穷远为终点作平行于X轴的直线line(x,y; -∞,y);
3.循环取得(for(i=0;i< n;i++))多边形的每一条边side(xi,yi;xi+1,yi+1),且判断是否平行于X轴,如果平行continue,否则,i++;
4. 同时判断point(x,y)是否在side上,如果是,则返回1(点在多边形上),否则继续下面的判断;
5.判断线side与line是否有交点,如果有则count++,否则,i++。
6.判断交点的总数,如果为奇数则返回0(点在多边形内),偶数则返回2(点在多边形外)。
代码:
const double INFINITY
= 1e10;
const double ESP
= 1e-5;
const int MAX_N
= 1000;
struct Point {
double x, y;
};
struct LineSegment {
Point pt1, pt2;
};
typedef vector< Point> Polygon;
// 计算叉乘 |P0P1| × |P0P2|
double Multiply(Point p1, Point p2, Point p0)
{
return ( (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) );
}
// 判断线段是否包含点point
bool IsOnline(Point point, LineSegment line)
{
return( ( fabs(Multiply(line.pt1, line.pt2, point)) < ESP ) &&
( ( point.x - line.pt1.x ) * ( point.x - line.pt2.x ) < = 0 ) &&
( ( point.y - line.pt1.y ) * ( point.y - line.pt2.y ) < = 0 ) );
}
// 判断线段相交
bool Intersect(LineSegment L1, LineSegment L2)
{
return( (max(L1.pt1.x, L1.pt2.x) >= min(L2.pt1.x, L2.pt2.x)) &&
(max(L2.pt1.x, L2.pt2.x) >= min(L1.pt1.x, L1.pt2.x)) &&
(max(L1.pt1.y, L1.pt2.y) >= min(L2.pt1.y, L2.pt2.y)) &&
(max(L2.pt1.y, L2.pt2.y) >= min(L1.pt1.y, L1.pt2.y)) &&
(Multiply(L2.pt1, L1.pt2, L1.pt1) * Multiply(L1.pt2, L2.pt2, L1.pt1) >= 0) &&
(Multiply(L1.pt1, L2.pt2, L2.pt1) * Multiply(L2.pt2, L1.pt2, L2.pt1) >= 0)
);
}
// 判断点在多边形内
bool InPolygon(const Polygon&
polygon, Point point)
{
int n = polygon.size();
int count = 0;
LineSegment line;
line.pt1 = point;
line.pt2.y = point.y;
line.pt2.x = - INFINITY;
for( int i
= 0; i < n; i++ ) {
// 得到多边形的一条边
LineSegment side;
side.pt1 = polygon[i];
side.pt2 = polygon[(i + 1) % n];
if( IsOnline(point, side) ) {
return1 ;
}
// 如果side平行x轴则不作考虑
if( fabs(side.pt1.y - side.pt2.y) < ESP ) {
continue;
}
if( IsOnline(side.pt1, line) ) {
if( side.pt1.y > side.pt2.y ) count++;
} else if(
IsOnline(side.pt2, line) ) {
if( side.pt2.y > side.pt1.y ) count++;
} else if(
Intersect(line, side) ) {
count++;
}
}
if ( count % 2 == 1 ) {return 0;}
else { return 2;}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
GraphicsPath gp1 = new GraphicsPath();
GraphicsPath gp2 = new GraphicsPath();
gp1.AddPolygon(new Point[] { new Point(100, 0), new Point(150, 100), new Point(200, 0),
new Point(100, 300), new Point(150, 200), new Point(200, 300)});
gp2.AddRectangle(new Rectangle(new Point(0,50),new Size(300,200)));
g.FillPath(Brushes.Green, gp2);
g.FillPath(Brushes.GreenYellow, gp1);
Region region = new Region(gp1);
region.Intersect(gp2); //求长方形和多边形的交集
g.FillRegion(Brushes.Red, region);//用红色填充
}
最近项目需要判断两个图形要素是否相交的问题:
一个图形元素是GraphicsPath 构造的闭合多边形,另一个图形元素是矩形,然后用region.interSect(矩形)来获取两者的交集元素,但明明是有交集的,返回的交集却为空。
可能的原因是构建图形要素的值太小造成的返回结果不准确,创建图形要素的坐标限定在:{x:(-180,180)} {y:(-90,90)}
请问有什么办法可以使下面的交集能够正确返回?
注:下面的两图形元素肯定是有交集的。
public void intersectTestx(PaintEventArgs e)
{
PointF[] pts = new PointF[4];
pts[0] = new PointF(115.116066f, 40.48523f);
pts[1] = new PointF(115.879951f, 40.5706635f);
pts[2] = new PointF(116.040909f, 39.998024f);
pts[3] = new PointF(115.283585f, 39.9120445f);
//构建GraphicsPath对象
GraphicsPath gpTmp1 = new GraphicsPath(System.Drawing.Drawing2D.FillMode.Alternate);
gpTmp1.AddPolygon(pts);
//构建region对象
Region rgnTmp = new Region(gpTmp1);
SolidBrush myBrush1 = new SolidBrush(Color.Black);
e.Graphics.FillRegion(myBrush1, rgnTmp);
//构建矩形对象
RectangleF recOri = new RectangleF(115.67f, 40.27f, 0.29f, 0.36f);
e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(recOri));
//获取矩形对象和region对象的交集
rgnTmp.Intersect(recOri);
// Fill the intersection area of myRegion with blue.
SolidBrush myBrush = new SolidBrush(Color.Blue);
e.Graphics.FillRegion(myBrush, rgnTmp);
}
分不多,请大家见谅!谢谢。
相关文章推荐
- 用SVN进行团队开发协作生命周期详解
- Mysql批量删除和修改某个前缀的表
- CentOS7 盒盖休眠
- Yeoman(Yo、Grunt、Bower),node.js学习笔记
- 基于FT5x06嵌入式Linux电容触摸屏驱动
- AppInventor读取百度翻译接口(韩语立刻说)
- [麦先生]学习PDO循序渐进使用方式
- 172. Factorial Trailing Zeroes
- Oracle游标详解
- 静态链接与动态链接的异同
- Spark介绍与安装教程(Linux系统)
- 189. Rotate Array
- 《Linux内核分析》 期中总结
- leetcode-206. Reverse Linked List
- HDU 2389 Rain on your Parade (HK二分图)
- poj1804求逆序对数
- Android:使用pagerslidingtabstrip做Tab
- 作为一个程序员我为什么要写博客?
- ionic的路由配置及参数传递
- 利用ContactPicker元件选择手机联系人信息