The best algorithm for determining whether the point is within a triangle __graphice

Source: Internet
Author: User
Tags abs

For example, three vertices a (Xa,za) B (XB,ZB) C (XC,ZC) are known
and O-point (Xo,zo)
Determine if o point is in triangular ABC in the X-Z plane
I think of a lot of ways, but I'm looking for the quickest and the simplest.

1. Area discrimination Method

If the sum of the Aoc,boc,aob area equals ABC,

A common and easy way to do this is to use this space:if the sum of the area of the triangular Pab,pac and PBC is equal to the area of the triangular ABC, the point P can be judged within the triangular ABC (including three edges) .
The key point of this method is how to calculate the area of the triangle. Luckily, when you know the coordinates of triangle vertices (a,b and C) ((Ax, Ay), (Bx, by) and (Cx, Cy), you can calculate their area:
S = | (AX * by + Bx * Cy + Cx * Zy-ay * bx-by * cx-cy * ax)/2|
The key code is as follows,
The triangle area is computed by the coordinates of the given three vertices.
Point (Java.awt.Point) represents the coordinates of the points.
private static Double Trianglearea (point pos1, point Pos2, point Pos3) {
Double result = Math.Abs (pos1.x * pos2.y + pos2.x * pos3.y + pos3.x * pos1.y
-pos2.x * pos1.y-pos3.x * pos2.y-pos1.x * pos3.y)/2.0D);
return result;
}
Determines whether the point POS is within the specified triangle.
private static Boolean Intriangle (Point pos, point Posa, point PosB,
Point PosC) {
Double Trianglearea = Trianglearea (Posa, PosB, PosC);
Double area = Trianglearea (pos, Posa, PosB);
Area + = Trianglearea (pos, Posa, PosC);
Area + = Trianglearea (pos, PosB, PosC);
Double epsilon = 0.0001; Because of the error in the calculation of floating point numbers, a small enough number is specified to determine whether two areas are equal (approximate).
if (Math.Abs (Trianglearea-area) < epsilon) {
return true;
}
return false;
}


In an open source script it happened to see so few lines, as follows:

function Polygon_contains (point)
{
var i, J, Status=false;

For (i=0, j=this.numpoints-1; i<this.numpoints; j=i++) {
if (((THIS.POINTS[I].Y<=POINT.Y) && (point.y<this.points[j].y)) | | ((THIS.POINTS[J].Y<=POINT.Y) && (POINT.Y<THIS.POINTS[I].Y)) && (Point.x < (this.points[j].x-this.points[i].x) * (POINT.Y-THIS.POINTS[I].Y)/(THIS.POINTS[J].Y-THIS.P OINTS[I].Y) + this.points[i].x)
status =!status;
}
return status;
}

Careful analysis, although simple, can be justified and Plumbline method, but omitted the intersection, counting the number of points in the process.

The main logic is in that if conditional statement

((THIS.POINTS[I].Y<=POINT.Y) && (point.y<this.points[j].y) | | ((THIS.POINTS[J].Y<=POINT.Y) && (POINT.Y<THIS.POINTS[I].Y)) is to judge point points between the horizontal line at the point of crossing and the horizontal line over the J Point (the critical condition is one end closed)

(Point.x < (this.points[j].x-this.points[i].x) * (POINT.Y-THIS.POINTS[I].Y)/(THIS.POINTS[J].Y-THIS.POINTS[I].Y) + this.points[i].x) is to judge the point points in the line of IJ coordinates, note that here the line of IJ without direction. We should add a little bit of code to fit the IJ vertical situation, and it seems to be based on the positive or negative of the slope. Write a function to determine whether the point is on the left side of the line:

private bool Pointleft (CPoint p, CPoint I, CPoint j)
{
if (i.x = = j.x)
{
return p.x < i.x;
}
Double delty = J.Y-I.Y;
Double deltx = j.x-i.x;
if ((Deltx >= 0 & delty > 0) | | (deltx <= 0 && delty < 0))
{
return p.y > Delty/deltx * (p.x-i.x) + i.y;
}
Else
{
Return P.Y < Delty/deltx * (p.x-i.x) + i.y;
}
}

Just start to assume the point outside, not meet this condition, inside and out on the reverse, the final status is true in the polygon.

It is verified that the polygon, inverse, cis-polygon and concave-convex polygon with rings are effective.

Add a little code to verify that the point is on the edge or coincident with a node.



judge the point within the polygon

Author: hyp

Micro Blog: http://weibo.com/hhyypp


0. Foreword

Recently encountered a similar geometric position problem, has not taken time to summarize, this article summed up my common point and polygon position to judge the method and code. Hope to be helpful to everyone.

The polygons referred to in this paper are convex polygons, and some descriptions may be incorrect. 1. Test the Polygon

Before we start, we need to build a good test environment first.

I built a more specific polygon, as follows.

/ \

| |

|_|

From the top vertex clockwise coordinates (screen coordinate system) are: (40,10) (60,30) (60,50) (20,50) (20,30) 2. X-ray discriminant method

Based on the understanding of polygons, we can draw the following conclusions:

If a point is inside the polygon, the ray at any angle must have either an intersection with the polygon or overlap with the polygon boundary.

If a point is outside the polygon, any angle to do the ray or have a intersection with the polygon, there are two intersection points, there is no intersection, or overlap with the polygon boundary.

Using the above conclusion, we can judge the position of the polygon by determining the number of intersections between the point and the polygon.

The first list of matters to note:

The overlap of the boundary lines of the Ray and polygon

L The difference between the rays of the inner and outer points when there is a intersection

For the first note, you can set the radial angle to zero, just to determine whether the Y values of the two adjacent vertices are equal. Then we can judge the X-value position of the point.

For the second note, many articles on the internet say that the intersection after the X-ray points for the odd point in the polygon inside, this is a false view, not only for concave polygon is not established, for convex polygons also do not set up.

For example: A ray from an external point is just passing through a vertex, the number of points is odd, but the point is not inside the polygon.

As to how to distinguish between these two cases, I can think of an imperfect method, the external point of the ray with a polygon intersection, the intersection is definitely a vertex, if the ray up one or move down one bit, either into two points or no intersection. For the sake of safety, of course, the rays are moved as far as possible to the center of the neighboring point. This way you can tell that the ray of the outer point has a intersection with the polygon.

However, this method is not perfect, because with the shift operation, the internal point may be moved out of the external. And if the judgment point is in (60,30) position, the Judgment time first encounters (20,30), then shifts the operation, then the judgment is wrong.

In order to solve these problems, I first scan the point at first whether the points at the vertex, although the impact of a little bit of efficiency, and when the decision point distance polygon a unit, the judgment may be wrong. But as long as it is not required high-precision, this method is very effective.

The code is as follows:

BOOL InsidePolygon1 (POINTD *polygon,int n,pointd PT)
{
int i,j;
BOOL Inside,redo;

Redo = true;
for (i = 0;i < N;++i)
{
if (polygon[i].x = = Pt.x &&//whether at vertex
Polygon[i].y = = Pt.y)
{
Redo = false;
Inside = true;
Break
}
}

while (redo)
{
Redo = false;
Inside = false;
for (i = 0,j = N-1;i < N;j = i++)
{
if ((Polygon[i].y < Pt.y && Pt.y < polygon[j].y) | |
(Polygon[j].y < Pt.y && Pt.y < POLYGON[I].Y))
{
if (pt.x <= polygon[i].x | | pt.x <= polygon[j].x)
{
Double _x = (pt.y-polygon[i].y) * (polygon[j].x-polygon[i].x)/(POLYGON[J].Y-POLYGON[I].Y) +polygon[i].x;
if (Pt.x < _x)//On the left of the line
Inside =!inside;
else if (pt.x = _x)//Online
{
Inside = true;
Break
}
}
}
else if (Pt.y = = polygon[i].y)
{
if (Pt.x < polygon[i].x)//intersections at vertices
{
Polygon[i].y > Polygon[j].y? --pt.y: ++pt.y;
Redo = true;
Break
}
}
else if (polygon[i].y = polygon[j].y &&//On the horizontal boundary line
Pt.y = Polygon[i].y &&
((polygon[i].x < pt.x && pt.x < polygon[j].x) | |
(Polygon[j].x < Pt.x && Pt.x < polygon[i].x)) )
{
Inside = true;
Break
}
}
}

return inside;
}

3. Angle and discriminant method

The angle and discriminant method is the angle of judging the angle of all the neighboring vertices of the polygon and the position relation between the point and the polygon.

If the point is inside the polygon, as long as the point is not on the boundary or the vertex, the angle is 360 degrees.

If on the boundary line, the angle and is 180 degrees.

If the point is outside the polygon, the angle and cannot reach 360 degrees. But the angle and the likelihood will reach 180 degrees, for instance the judgment point in (60,10).

The code is as follows:

Do not judge vertices according to need
BOOL Ispointinline (const POINTD &pt,const pointd &pt1,const pointd)
{
BOOL inside = false;
if (Pt.y = Pt1.y &&
PT1.Y = Pt2.y &&
((pt1.x < pt.x && pt.x < pt2.x) | |
(pt2.x < Pt.x && Pt.x < pt1.x)) )
{
Inside = true;
}
else if (pt.x = pt1.x &&
pt1.x = pt2.x &&
((Pt1.y < Pt.y && Pt.y < pt2.y) | |
(Pt2.y < Pt.y && Pt.y < PT1.Y)) )
{
Inside = true;
}
else if ((Pt1.y < Pt.y && Pt.y < pt2.y) | |
(Pt2.y < Pt.y && Pt.y < PT1.Y)) &&
((pt1.x < pt.x && pt.x < pt2.x) | |
(pt2.x < Pt.x && Pt.x < pt1.x)) )
{
if (0 = (PT.Y-PT1.Y)/(PT2.Y-PT1.Y)-(pt.x-pt1.x)/(pt2.x-pt1.x))
{
Inside = true;
}
}
return inside;
}

BOOL InsidePolygon2 (Pointd *polygon,int n,pointd p)
{
int i,j;
Double angle = 0;
BOOL inside = false;

for (i = 0,j = N-1;i < N;j = i++)
{
if (polygon[i].x = = p.x &&//whether at vertex
Polygon[i].y = = p.y)
{
Inside = true;
Break
}
else if (Ispointinline (P,polygon[i],polygon[j]))//whether on the boundary line
{
Inside = true;
Break
}

Double x1,y1,x2,y2;
x1 = polygon[i].x-p.x;
y1 = polygon[i].y-p.y;
x2 = polygon[j].x-p.x;
y2 = polygon[j].y-p.y;

Double radian = atan2 (y1,x1)-atan2 (Y2,X2);
Radian = ABS (Radian);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.