| | |
| | | return Math.abs(left.lat - right.lat) < 0.000001 && Math.abs(left.lng - right.lng) < 0.000001 |
| | | } |
| | | |
| | | function normalizePolygonPoints (points) { |
| | | if (!Array.isArray(points)) return [] |
| | | const ring = points.filter(point => point && Number.isFinite(point.lng) && Number.isFinite(point.lat)) |
| | | if (ring.length < 2) return ring |
| | | const first = ring[0] |
| | | const last = ring[ring.length - 1] |
| | | if (isSameWktPoint(first, last)) { |
| | | return ring.slice(0, -1) |
| | | } |
| | | return ring |
| | | } |
| | | |
| | | function isSelfIntersectingPolygon (points) { |
| | | const ring = normalizePolygonPoints(points) |
| | | if (ring.length < 4) return false |
| | | const epsilon = 1e-12 |
| | | const orientation = (a, b, c) => { |
| | | const value = (b.lat - a.lat) * (c.lng - b.lng) - (b.lng - a.lng) * (c.lat - b.lat) |
| | | if (Math.abs(value) < epsilon) return 0 |
| | | return value > 0 ? 1 : 2 |
| | | } |
| | | const onSegment = (a, b, c) => |
| | | b.lng <= Math.max(a.lng, c.lng) + epsilon && |
| | | b.lng + epsilon >= Math.min(a.lng, c.lng) && |
| | | b.lat <= Math.max(a.lat, c.lat) + epsilon && |
| | | b.lat + epsilon >= Math.min(a.lat, c.lat) |
| | | const segmentsIntersect = (p1, q1, p2, q2) => { |
| | | const o1 = orientation(p1, q1, p2) |
| | | const o2 = orientation(p1, q1, q2) |
| | | const o3 = orientation(p2, q2, p1) |
| | | const o4 = orientation(p2, q2, q1) |
| | | if (o1 !== o2 && o3 !== o4) return true |
| | | if (o1 === 0 && onSegment(p1, p2, q1)) return true |
| | | if (o2 === 0 && onSegment(p1, q2, q1)) return true |
| | | if (o3 === 0 && onSegment(p2, p1, q2)) return true |
| | | if (o4 === 0 && onSegment(p2, q1, q2)) return true |
| | | return false |
| | | } |
| | | |
| | | const count = ring.length |
| | | for (let i = 0; i < count; i += 1) { |
| | | const p1 = ring[i] |
| | | const q1 = ring[(i + 1) % count] |
| | | for (let j = i + 1; j < count; j += 1) { |
| | | const p2 = ring[j] |
| | | const q2 = ring[(j + 1) % count] |
| | | const isAdjacent = j === i || j === i + 1 || (i === 0 && j === count - 1) |
| | | if (isAdjacent) continue |
| | | if (segmentsIntersect(p1, q1, p2, q2)) return true |
| | | } |
| | | } |
| | | return false |
| | | } |
| | | |
| | | function buildPolygonWktFromPoints (points) { |
| | | if (!Array.isArray(points) || points.length < 3) return null |
| | | const ring = points |
| | |
| | | const val = cartesian3Convert(item, viewer) |
| | | return { ...val, lng: val.longitude, lat: val.latitude } |
| | | }) |
| | | if (currentShapeType.value === 'polygon' && isSelfIntersectingPolygon(pointList)) { |
| | | ElMessage.warning('多边形存在自相交,请调整后再保存') |
| | | if (activeToolMode.value === 'draw') { |
| | | pointList = [] |
| | | activeShapeId.value = null |
| | | clearActiveTool() |
| | | startDraw('polygon') |
| | | } |
| | | return |
| | | } |
| | | const controlPoints = resolveControlPoints(meta, currentShapeType.value) |
| | | if (!activeAreaType.value) { |
| | | const detectAreaType = getDetectAreaTypeKey() |