李红攀:小程序新增农事记录
This commit is contained in:
156
src/utils/geo.js
Normal file
156
src/utils/geo.js
Normal file
@@ -0,0 +1,156 @@
|
||||
export function isPointInGeoJson(point, geoJson) {
|
||||
if (!point || !isFiniteNumber(point.longitude) || !isFiniteNumber(point.latitude) || !geoJson) {
|
||||
return false
|
||||
}
|
||||
|
||||
const geometries = collectGeometries(geoJson)
|
||||
if (!geometries.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
return geometries.some((geometry) => {
|
||||
if (!geometry || !geometry.type || !geometry.coordinates) {
|
||||
return false
|
||||
}
|
||||
if (geometry.type === 'Polygon') {
|
||||
return isPointInPolygonCoordinates(point, geometry.coordinates)
|
||||
}
|
||||
if (geometry.type === 'MultiPolygon') {
|
||||
return geometry.coordinates.some(polygon => isPointInPolygonCoordinates(point, polygon))
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
export function getGeoJsonPolygonPaths(geoJson) {
|
||||
const geometries = collectGeometries(geoJson)
|
||||
if (!geometries.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
return geometries.flatMap((geometry) => {
|
||||
if (!geometry || !geometry.type || !geometry.coordinates) {
|
||||
return []
|
||||
}
|
||||
if (geometry.type === 'Polygon') {
|
||||
return buildPolygonPaths(geometry.coordinates)
|
||||
}
|
||||
if (geometry.type === 'MultiPolygon') {
|
||||
return geometry.coordinates.flatMap(polygon => buildPolygonPaths(polygon))
|
||||
}
|
||||
return []
|
||||
})
|
||||
}
|
||||
|
||||
function collectGeometries(geoJson) {
|
||||
if (!geoJson || typeof geoJson !== 'object') {
|
||||
return []
|
||||
}
|
||||
|
||||
if (geoJson.type === 'Feature') {
|
||||
return geoJson.geometry ? [geoJson.geometry] : []
|
||||
}
|
||||
|
||||
if (geoJson.type === 'FeatureCollection') {
|
||||
return (geoJson.features || []).flatMap(feature => collectGeometries(feature))
|
||||
}
|
||||
|
||||
if (geoJson.type === 'Polygon' || geoJson.type === 'MultiPolygon') {
|
||||
return [geoJson]
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
function isPointInPolygonCoordinates(point, polygonCoordinates) {
|
||||
if (!Array.isArray(polygonCoordinates) || polygonCoordinates.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
const [outerRing, ...holes] = polygonCoordinates
|
||||
if (!isPointInRing(point, outerRing)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !holes.some(hole => isPointInRing(point, hole))
|
||||
}
|
||||
|
||||
function buildPolygonPaths(polygonCoordinates) {
|
||||
if (!Array.isArray(polygonCoordinates) || polygonCoordinates.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const [outerRing] = polygonCoordinates
|
||||
const points = normalizeRingPoints(outerRing)
|
||||
return points.length >= 3 ? [points] : []
|
||||
}
|
||||
|
||||
function normalizeRingPoints(ring) {
|
||||
if (!Array.isArray(ring)) {
|
||||
return []
|
||||
}
|
||||
|
||||
return ring
|
||||
.filter(isValidCoordinate)
|
||||
.map(coordinate => ({
|
||||
longitude: Number(coordinate[0]),
|
||||
latitude: Number(coordinate[1]),
|
||||
}))
|
||||
}
|
||||
|
||||
function isPointInRing(point, ring) {
|
||||
if (!Array.isArray(ring) || ring.length < 3) {
|
||||
return false
|
||||
}
|
||||
|
||||
const x = Number(point.longitude)
|
||||
const y = Number(point.latitude)
|
||||
let inside = false
|
||||
|
||||
for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {
|
||||
const current = ring[i]
|
||||
const previous = ring[j]
|
||||
if (!isValidCoordinate(current) || !isValidCoordinate(previous)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const xi = Number(current[0])
|
||||
const yi = Number(current[1])
|
||||
const xj = Number(previous[0])
|
||||
const yj = Number(previous[1])
|
||||
|
||||
if (isPointOnSegment(x, y, xi, yi, xj, yj)) {
|
||||
return true
|
||||
}
|
||||
|
||||
const intersects = ((yi > y) !== (yj > y))
|
||||
&& (x <= ((xj - xi) * (y - yi)) / (yj - yi) + xi)
|
||||
|
||||
if (intersects) {
|
||||
inside = !inside
|
||||
}
|
||||
}
|
||||
|
||||
return inside
|
||||
}
|
||||
|
||||
function isPointOnSegment(px, py, x1, y1, x2, y2) {
|
||||
const cross = (px - x1) * (y2 - y1) - (py - y1) * (x2 - x1)
|
||||
if (Math.abs(cross) > 1e-10) {
|
||||
return false
|
||||
}
|
||||
|
||||
const dot = (px - x1) * (px - x2) + (py - y1) * (py - y2)
|
||||
return dot <= 1e-10
|
||||
}
|
||||
|
||||
function isValidCoordinate(coordinate) {
|
||||
return Array.isArray(coordinate)
|
||||
&& coordinate.length >= 2
|
||||
&& isFiniteNumber(coordinate[0])
|
||||
&& isFiniteNumber(coordinate[1])
|
||||
}
|
||||
|
||||
function isFiniteNumber(value) {
|
||||
return Number.isFinite(Number(value))
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export function getEnvBaseUrl() {
|
||||
|
||||
// # 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
|
||||
// TODO @芋艿:这个后续也要调整。
|
||||
const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'http://localhost:48080/admin-api'
|
||||
const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'http://192.168.1.107:48080/admin-api'
|
||||
const VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'http://119.96.62.56:7004/admin-api'
|
||||
const VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'http://localhost:48080/admin-api'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user