wx小程序turf.js判断点是否位于该多边形内部
1、当前打卡位置在地理围栏内判断。使用turf.js(地理空间分析库,处理各种地图算法)。
2、wx小程序在使用npm构建后,引用时一直会提示“ 'xxx.js' is not defined, require args”
3、最终使用 "npm install @turf/boolean-point-in-polygon",到新建项目中,也可以直接使用下面代码。以下代码是方法“booleanPointInPolygon”,所以关联的方法,都是从npm下载下来的js中提炼出来的,直接用即可。文件名称命名为“boolean-point-in-polygon.js”
// index.ts
const booleanPointInPolygon = function(point, polygon, options = {}) {
if (!point) {
throw new Error("point is required");
}
if (!polygon) {
throw new Error("polygon is required");
}
const pt = getCoord(point);
const geom = getGeom(polygon);
const type = geom.type;
const bbox = polygon.bbox;
let polys = geom.coordinates;
if (bbox && inBBox(pt, bbox) === false) {
return false;
}
if (type === "Polygon") {
polys = [polys];
}
let result = false;
for (var i = 0; i < polys.length; ++i) {
const polyResult = pointInPolygon(pt, polys[i]);
if (polyResult === 0)
return options.ignoreBoundary ? false : true;
else if (polyResult)
result = true;
}
return result;
}
function feature(geom, properties, options = {}) {
const feat = { type: "Feature" };
if (options.id === 0 || options.id) {
feat.id = options.id;
}
if (options.bbox) {
feat.bbox = options.bbox;
}
feat.properties = properties || {};
feat.geometry = geom;
return feat;
}
const point = function(coordinates, properties, options = {}) {
if (!coordinates) {
throw new Error("coordinates is required");
}
if (!Array.isArray(coordinates)) {
throw new Error("coordinates must be an Array");
}
if (coordinates.length < 2) {
throw new Error("coordinates must be at least 2 numbers long");
}
const geom = {
type: "Point",
coordinates
};
return feature(geom, properties, options);
}
const polygon = function (coordinates, properties, options = {}) {
for (const ring of coordinates) {
if (ring.length < 4) {
console.log("Each LinearRing of a Polygon must have 4 or more Positions.")
throw new Error(
"Each LinearRing of a Polygon must have 4 or more Positions."
);
}
if (ring[ring.length - 1].length !== ring[0].length) {
console.log("First and last Position are not equivalent.")
throw new Error("First and last Position are not equivalent.");
}
for (let j = 0; j < ring[ring.length - 1].length; j++) {
if (ring[ring.length - 1][j] !== ring[0][j]) {
console.log("First and last Position are not equivalent.")
throw new Error("First and last Position are not equivalent.");
}
}
}
const geom = {
type: "Polygon",
coordinates
};
return feature(geom, properties, options);
}
function inBBox(pt, bbox) {
return bbox[0] <= pt[0] && bbox[1] <= pt[1] && bbox[2] >= pt[0] && bbox[3] >= pt[1];
}
function getGeom(geojson) {
if (geojson.type === "Feature") {
return geojson.geometry;
}
return geojson;
}
function getCoord(coord) {
if (!coord) {
throw new Error("coord is required");
}
if (!Array.isArray(coord)) {
if (coord.type === "Feature" && coord.geometry !== null && coord.geometry.type === "Point") {
return [...coord.geometry.coordinates];
}
if (coord.type === "Point") {
return [...coord.coordinates];
}
}
if (Array.isArray(coord) && coord.length >= 2 && !Array.isArray(coord[0]) && !Array.isArray(coord[1])) {
return [...coord];
}
throw new Error("coord must be GeoJSON Point or an Array of numbers");
}
function pointInPolygon(p, polygon) {
var i = 0;
var ii = 0;
var k = 0;
var f = 0;
var u1 = 0;
var v1 = 0;
var u2 = 0;
var v2 = 0;
var currentP = null;
var nextP = null;
var x = p[0];
var y = p[1];
var numContours = polygon.length;
for (i; i < numContours; i++) {
ii = 0;
var contourLen = polygon[i].length - 1;
var contour = polygon[i];
currentP = contour[0];
if (currentP[0] !== contour[contourLen][0] &&
currentP[1] !== contour[contourLen][1]) {
throw new Error('First and last coordinates in a ring must be the same')
}
u1 = currentP[0] - x;
v1 = currentP[1] - y;
for (ii; ii < contourLen; ii++) {
nextP = contour[ii + 1];
v2 = nextP[1] - y;
if ((v1 < 0 && v2 < 0) || (v1 > 0 && v2 > 0)) {
currentP = nextP;
v1 = v2;
u1 = currentP[0] - x;
continue
}
u2 = nextP[0] - p[0];
if (v2 > 0 && v1 <= 0) {
f = (u1 * v2) - (u2 * v1);
if (f > 0) { k = k + 1; }
else if (f === 0) { return 0 }
} else if (v1 > 0 && v2 <= 0) {
f = (u1 * v2) - (u2 * v1);
if (f < 0) { k = k + 1; }
else if (f === 0) { return 0 }
} else if (v2 === 0 && v1 < 0) {
f = (u1 * v2) - (u2 * v1);
if (f === 0) { return 0 }
} else if (v1 === 0 && v2 < 0) {
f = u1 * v2 - u2 * v1;
if (f === 0) { return 0 }
} else if (v1 === 0 && v2 === 0) {
if (u2 <= 0 && u1 >= 0) {
return 0
} else if (u1 <= 0 && u2 >= 0) {
return 0
}
}
currentP = nextP;
v1 = v2;
u1 = u2;
}
}
if (k % 2 === 0) { return false }
return true
}
module.exports = {
booleanPointInPolygon,
point,
polygon
};
4、调用
const polygon = turf.polygon( polygonCoords);
const point = turf.point(pointCoords);
// 使用Turf.js的booleanPointInPolygon方法判断点是否在多边形内
const insidePolygon = turf.booleanPointInPolygon(point, polygon);
console.log('是否在围栏内:' + insidePolygon);
5、参考官方文档
判断点是否在多边形内 | Turf.js中文网