Skip to content

Instantly share code, notes, and snippets.

@jonasjuni
Last active February 4, 2022 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonasjuni/69c75d928a7eac65c183409f22dc549d to your computer and use it in GitHub Desktop.
Save jonasjuni/69c75d928a7eac65c183409f22dc549d to your computer and use it in GitHub Desktop.
Point in Polygon dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
restorationScopeId: 'app',
home: PolygonPointPage(),
);
}
}
class PolygonPointPage extends StatelessWidget {
const PolygonPointPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: PointInPolygon(),
),
);
}
}
class PointInPolygon extends StatefulWidget {
const PointInPolygon({Key? key}) : super(key: key);
@override
_PointInPolygonState createState() => _PointInPolygonState();
}
class _PointInPolygonState extends State<PointInPolygon> {
final points = const [
Offset(100, 100),
Offset(200, 100),
Offset(200, 200),
Offset(300, 200),
Offset(300, 300),
Offset(100, 300),
Offset(100, 100)
];
var isInside = false;
//Simple algo for simple convex polygons https://en.wikipedia.org/wiki/Convex_polygon
// Based in https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon?page=1&tab=active#tab-top
void _simplePolygon(Offset point, List<Offset> boundary) {
late double minX, minY, maxX, maxY;
// Get max and min coordernates (Can be optimized by using a const value)
for (var i = 0; i < boundary.length; i++) {
if (i == 0) {
minX = maxX = boundary[i].dx;
minY = maxY = boundary[i].dy;
continue;
}
if (boundary[i].dx < minX) {
minX = boundary[i].dx;
}
if (boundary[i].dx > maxX) {
maxX = boundary[i].dx;
}
if (boundary[i].dy < minY) {
minY = boundary[i].dy;
}
if (boundary[i].dy > maxY) {
maxY = boundary[i].dy;
}
}
if (point.dx < minX ||
point.dx > maxX ||
point.dy < minY ||
point.dy > maxY) {
_changePointStatus(false);
} else {
_changePointStatus(true);
}
}
// Winding Number Inclusion Algo https://en.wikipedia.org/wiki/Point_in_polygon
//Credits Dan Sunday in 2001 - https://web.archive.org/web/20130126163405/http://geomalgorithms.com/a03-_inclusion.html
void _windingNumberInclusion(Offset point) {
//the winding number counter
var wn = 0;
double isLeft(Offset p0, Offset p1, Offset p2) {
return ((p1.dx - p0.dx) * (p2.dy - p0.dy) -
(p2.dx - p0.dx) * (p1.dy - p0.dy));
}
for (var i = 0; i < points.length - 1; i++) {
if (points[i].dy <= point.dy) {
if (points[i + 1].dy > point.dy) {
if (isLeft(points[i], points[i + 1], point) > 0) {
++wn; // have a valid up intersect
}
}
} else {
if (points[i + 1].dy <= point.dy) {
if (isLeft(points[i], points[i + 1], point) < 0) {
--wn; // have a valid down intersect
}
}
}
}
if (wn == 0) {
_changePointStatus(false);
} else {
_changePointStatus(true);
}
}
void _gpuFillApoach() {}
void _changePointStatus(bool value) {
if (isInside != value) {
setState(() {
isInside = value;
});
}
}
@override
Widget build(BuildContext context) {
return MouseRegion(
onHover: (event) {
_windingNumberInclusion(event.localPosition);
},
child: Container(
width: 400,
height: 400,
decoration: BoxDecoration(
border: Border.all(),
image: const DecorationImage(
image: NetworkImage('https://i.imgur.com/IViWIkr.png'),
),
),
child: CustomPaint(
painter: PolygonShape(points, isInside ? Colors.green : Colors.amber),
),
),
);
}
}
class PolygonShape extends CustomPainter {
PolygonShape(this.points, this.color);
final List<Offset> points;
final Color color;
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color.withOpacity(0.75);
final path = Path()..addPolygon(points, true);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment