Last active
March 19, 2020 15:17
-
-
Save oliverheilig/7031590 to your computer and use it in GitHub Desktop.
PointInsidePolygon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This snippet shows how to check whether a point is | |
// contained in a polygon. Works for all polygons, even for | |
// OGC-invalid ones, corresponding to "fill mode" alternate. | |
// You can use this for geo-fencing or UI hit-testing. | |
using System; | |
using System.Collections.Generic; | |
using JSIL; | |
using JSIL.Meta; | |
public class Program | |
{ | |
public static void Main() | |
{ | |
Console.WriteLine("The red points are outside, " + | |
"the blue points are inside the polygon"); | |
dynamic document = Builtins.Global["document"]; | |
dynamic window = Builtins.Global["window"]; | |
var canvas = document.createElement("canvas"); | |
var ctx = canvas.getContext("2d"); | |
var body = document.getElementsByTagName("body")[0]; | |
body.appendChild(canvas); | |
var polygon = new List<Point> { | |
new Point(20,30), new Point(50, 50), | |
new Point(60, 45), new Point(100, 50), new Point(50, 100) }; | |
DrawPolygon(ctx, polygon, "black", 2); | |
var pointsToCheck = new List<Point> { | |
new Point(60, 70), new Point(80, 60), new Point(60, 20), new Point(80, 80) }; | |
foreach (var point in pointsToCheck) | |
{ | |
var color = (PolyContainsPoint(polygon, point)) ? "blue" : "red"; | |
DrawPoint(ctx, point, color); | |
} | |
} | |
public static void DrawPoint(dynamic ctx, Point p, string color) | |
{ | |
ctx.fillStyle = color; | |
ctx.fillRect(p.X - 2, p.Y - 2, 4, 4); | |
} | |
public static void DrawPolygon(dynamic ctx, IList<Point> lineString, string color, double width) | |
{ | |
ctx.lineWidth = width; | |
ctx.strokeStyle = color; | |
ctx.beginPath(); | |
ctx.moveTo(lineString[0].X, lineString[0].Y); | |
for (int i = 1; i < lineString.Count; i++) | |
ctx.lineTo(lineString[i].X, lineString[i].Y); | |
ctx.lineTo(lineString[0].X, lineString[0].Y); // close polygon | |
ctx.stroke(); | |
} | |
public static bool PolyContainsPoint(List<Point> points, Point p) | |
{ | |
bool inside = false; | |
// An imaginary closing segment is implied, | |
// so begin testing with that. | |
Point v1 = points[points.Count - 1]; | |
foreach (Point v0 in points) | |
{ | |
double d1 = (p.Y - v0.Y) * (v1.X - v0.X); | |
double d2 = (p.X - v0.X) * (v1.Y - v0.Y); | |
if (p.Y < v1.Y) | |
{ | |
// V1 below ray | |
if (v0.Y <= p.Y) | |
{ | |
// V0 on or above ray | |
// Perform intersection test | |
if (d1 > d2) | |
{ | |
inside = !inside; // Toggle state | |
} | |
} | |
} | |
else if (p.Y < v0.Y) | |
{ | |
// V1 is on or above ray, V0 is below ray | |
// Perform intersection test | |
if (d1 < d2) | |
{ | |
inside = !inside; // Toggle state | |
} | |
} | |
v1 = v0; //Store previous endpoint as next startpoint | |
} | |
return inside; | |
} | |
} | |
public class Point | |
{ | |
public Point(double x, double y) | |
{ | |
this.X = x; | |
this.Y = y; | |
} | |
public double X { get; set; } | |
public double Y { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment