提问人:shanmkha 提问时间:11/2/2023 最后编辑:shanmkha 更新时间:11/3/2023 访问量:44
检测多边形与纬度列表的自交点?
Detect self intersection of a polygon with list of latLng?
问:
我有一个坐标列表来绘制一个完美的多边形,该多边形不应该是自相交和闭合的多边形。我在 shift 中找到了这段代码,但我想要在 dart 中使用它,因为我在 flutter 中实现。
因此,当多边形类似于第一种情况时,代码应返回 --> true
在其他情况下,应返回 --> false。
我尝试了一些代码,但它效果不佳,我尝试了另一种代码,它在某些情况下有效(不确定在哪些情况下)。
因此,下面我更新了最小的可重复示例。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<LatLng> polygonLatLngs = [];
Set<Polygon> _polygons = HashSet<Polygon>();
Set<Marker> _markers = HashSet<Marker>();
LatLng centerCamera = LatLng(13.621975344148467, 79.42180316886122);
double? zoomCamera;
BitmapDescriptor? errorMark;
GoogleMapController? googleMapController;
void _setPolygon() {
final String polygonIdVal = 'polygon_id_$_polygonIdCounter';
_polygons.add(Polygon(
polygonId: PolygonId(polygonIdVal),
points: polygonLatLngs,
strokeWidth: 2,
strokeColor: Colors.blueAccent,
fillColor: Colors.transparent,
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: GoogleMap(
myLocationButtonEnabled: false,
myLocationEnabled: false,
mapType: MapType.normal,
padding: EdgeInsets.only(bottom: 160),
initialCameraPosition: CameraPosition(
target: centerCamera,
zoom: 18,
),
onMapCreated: (GoogleMapController controller) {
googleMapController = controller;
},
gestureRecognizers: Set()
..add(Factory<PanGestureRecognizer>(
() => PanGestureRecognizer())),
onTap: (latLng) {
setState(() {
polygonLatLngs.add(latLng);
_setPolygon();
isIntersecting(polygonLatLngs);
});
},
onCameraMove: (position) {
centerCamera = position.target;
zoomCamera = position.zoom;
},
markers: _markers,
polygons: _polygons,
),
),
);
}
LatLng? intersectionBetweenSegments(LatLng p0, LatLng p1, LatLng p2, LatLng p3){
var denominator = (p3.longitude - p2.longitude) * (p1.latitude - p0.latitude) - (p3.latitude - p2.latitude) * (p1.longitude - p0.longitude);
var ua = (p3.latitude - p2.latitude) * (p0.longitude - p2.longitude) - (p3.longitude - p2.longitude) * (p0.latitude - p2.latitude);
var ub = (p1.latitude - p0.latitude) * (p0.longitude - p2.longitude) - (p0.longitude - p0.longitude) * (p0.latitude - p2.latitude);
if(denominator < 0){
ua = -ua;
ub = -ub;
denominator = -denominator;
}
if (ua >= 0.0 && ua <= denominator && ub >= 0.0 && ub <= denominator && denominator != 0){
print("INTERSECT");
return LatLng(p0.latitude + ua / denominator * (p1.latitude - p0.latitude), p0.longitude + ua / denominator * (p1.longitude - p0.longitude));
}
return null;
}
bool isIntersecting(List<LatLng> polygon) {
LatLng? intersection;
if(polygon.length > 2){
final n = polygon.length - 1;
for(var i =1; i < n; i++){
for(var j=0; j < i-1; j++){
intersection = intersectionBetweenSegments(polygon[i], polygon[i+1], polygon[j], polygon[j+1]);
if (intersection != null){
print("Error: Intersection @$intersection");
placeErrorMarker(intersection);
//alert user about intersection
showDialog(
context: context,
barrierDismissible: false,
builder: ((BuildContext context) {
return DialogBoxForErrorWithCb(
"Error",
"Station boundary should not be overlap",
onPress: () {
//remove last polyline and remove error mark on map
setState(() {
polygonLatLngs.removeLast();
_markers.remove(_markers.firstWhere((Marker marker) => marker.markerId.value == 'error'));
});
popDialog(context);
},
);
}));
return true;
}
}
}
}
return false;
}
void placeErrorMarker(LatLng intersection) {
_markers.add(Marker(
markerId: MarkerId('error'),
position: intersection,
anchor : const Offset(0.5, 0.5),
infoWindow: InfoWindow(
title: 'Overlap Point',
snippet: 'Boundary should not be overlap',
),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
));
Future.delayed(Duration(seconds: 1)).then((value) {
googleMapController?.showMarkerInfoWindow(MarkerId('error'));
});
}
}
非常感谢您的帮助。
答: 暂无答案
评论