UNPKG

@chauffleet/expo-custom-map

Version:

Open source custom map library for Expo/React Native. Use your own tiles without Google Maps, Mapbox, or API keys. Created by ChaufFleet.

234 lines 7.56 kB
"use strict"; // src/utils/mathUtils.ts Object.defineProperty(exports, "__esModule", { value: true }); exports.debounce = exports.throttle = exports.calculateLOD = exports.calculateOptimalZoom = exports.seededRandom = exports.simpleHash = exports.easing = exports.isPointInPolygon = exports.polygonArea = exports.isPointInCircle = exports.isPointInRect = exports.lerpAngle = exports.angleDifference = exports.normalizeAngleDegrees = exports.normalizeAngleRadians = exports.distanceSquared2D = exports.distance2D = exports.isInRange = exports.roundToDecimals = exports.remap = exports.inverseLerp = exports.lerp = exports.clamp = void 0; /** * Clamp une valeur entre un minimum et un maximum */ const clamp = (value, min, max) => { return Math.min(Math.max(value, min), max); }; exports.clamp = clamp; /** * Interpolation linéaire entre deux valeurs */ const lerp = (start, end, progress) => { return start + (end - start) * progress; }; exports.lerp = lerp; /** * Interpolation inverse - trouve le facteur de progression entre deux valeurs */ const inverseLerp = (start, end, value) => { if (start === end) return 0; return (value - start) / (end - start); }; exports.inverseLerp = inverseLerp; /** * Remap une valeur d'une plage à une autre */ const remap = (value, fromMin, fromMax, toMin, toMax) => { const progress = (0, exports.inverseLerp)(fromMin, fromMax, value); return (0, exports.lerp)(toMin, toMax, progress); }; exports.remap = remap; /** * Arrondir à un nombre spécifique de décimales */ const roundToDecimals = (value, decimals) => { const factor = Math.pow(10, decimals); return Math.round(value * factor) / factor; }; exports.roundToDecimals = roundToDecimals; /** * Vérifier si un nombre est dans une plage (inclusif) */ const isInRange = (value, min, max) => { return value >= min && value <= max; }; exports.isInRange = isInRange; /** * Calculer la distance euclidienne entre deux points 2D */ const distance2D = (x1, y1, x2, y2) => { const dx = x2 - x1; const dy = y2 - y1; return Math.sqrt(dx * dx + dy * dy); }; exports.distance2D = distance2D; /** * Calculer la distance euclidienne au carré (plus rapide si on n'a pas besoin de la racine) */ const distanceSquared2D = (x1, y1, x2, y2) => { const dx = x2 - x1; const dy = y2 - y1; return dx * dx + dy * dy; }; exports.distanceSquared2D = distanceSquared2D; /** * Normaliser un angle en radians entre 0 et 2π */ const normalizeAngleRadians = (angle) => { while (angle < 0) angle += 2 * Math.PI; while (angle >= 2 * Math.PI) angle -= 2 * Math.PI; return angle; }; exports.normalizeAngleRadians = normalizeAngleRadians; /** * Normaliser un angle en degrés entre 0 et 360 */ const normalizeAngleDegrees = (angle) => { while (angle < 0) angle += 360; while (angle >= 360) angle -= 360; return angle; }; exports.normalizeAngleDegrees = normalizeAngleDegrees; /** * Calculer la différence entre deux angles (résultat entre -π et π) */ const angleDifference = (angle1, angle2) => { const diff = angle2 - angle1; return Math.atan2(Math.sin(diff), Math.cos(diff)); }; exports.angleDifference = angleDifference; /** * Interpolation d'angle (prend le chemin le plus court) */ const lerpAngle = (start, end, progress) => { const diff = (0, exports.angleDifference)(start, end); return start + diff * progress; }; exports.lerpAngle = lerpAngle; /** * Vérifier si un point est dans un rectangle */ const isPointInRect = (pointX, pointY, rectX, rectY, rectWidth, rectHeight) => { return (pointX >= rectX && pointX <= rectX + rectWidth && pointY >= rectY && pointY <= rectY + rectHeight); }; exports.isPointInRect = isPointInRect; /** * Vérifier si un point est dans un cercle */ const isPointInCircle = (pointX, pointY, circleX, circleY, radius) => { return (0, exports.distanceSquared2D)(pointX, pointY, circleX, circleY) <= radius * radius; }; exports.isPointInCircle = isPointInCircle; /** * Calculer l'aire d'un polygone (formule du lacet) */ const polygonArea = (vertices) => { if (vertices.length < 3) return 0; let area = 0; const n = vertices.length; for (let i = 0; i < n; i++) { const j = (i + 1) % n; area += vertices[i][0] * vertices[j][1]; area -= vertices[j][0] * vertices[i][1]; } return Math.abs(area) / 2; }; exports.polygonArea = polygonArea; /** * Vérifier si un point est dans un polygone (ray casting algorithm) */ const isPointInPolygon = (point, vertices) => { const [x, y] = point; let inside = false; for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) { const [xi, yi] = vertices[i]; const [xj, yj] = vertices[j]; if (((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) { inside = !inside; } } return inside; }; exports.isPointInPolygon = isPointInPolygon; /** * Fonction easing pour les animations */ exports.easing = { linear: (t) => t, easeInQuad: (t) => t * t, easeOutQuad: (t) => t * (2 - t), easeInOutQuad: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t, easeInCubic: (t) => t * t * t, easeOutCubic: (t) => (--t) * t * t + 1, easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1, easeInSine: (t) => 1 - Math.cos(t * Math.PI / 2), easeOutSine: (t) => Math.sin(t * Math.PI / 2), easeInOutSine: (t) => -(Math.cos(Math.PI * t) - 1) / 2, }; /** * Générer un hash simple pour un nombre (utile pour les seeds) */ const simpleHash = (value) => { let hash = Math.abs(Math.floor(value)); hash = ((hash << 5) - hash + hash) & 0xffffffff; return hash; }; exports.simpleHash = simpleHash; /** * Générer un nombre pseudo-aléatoire avec une seed */ const seededRandom = (seed) => { const x = Math.sin(seed) * 10000; return x - Math.floor(x); }; exports.seededRandom = seededRandom; /** * Calculer le facteur de zoom optimal pour afficher une zone */ const calculateOptimalZoom = (bounds, containerSize, maxZoom = 18, padding = 0.1) => { const paddedWidth = containerSize.width * (1 - padding); const paddedHeight = containerSize.height * (1 - padding); const widthZoom = Math.log2(paddedWidth / bounds.width); const heightZoom = Math.log2(paddedHeight / bounds.height); return Math.min(Math.floor(Math.min(widthZoom, heightZoom)), maxZoom); }; exports.calculateOptimalZoom = calculateOptimalZoom; /** * Calculer le niveau de détail (LOD) basé sur la distance */ const calculateLOD = (distance, maxDistance, maxLOD = 5) => { if (distance >= maxDistance) return 0; const normalizedDistance = 1 - (distance / maxDistance); return Math.floor(normalizedDistance * maxLOD); }; exports.calculateLOD = calculateLOD; /** * Throttle pour limiter la fréquence d'exécution d'une fonction */ const throttle = (func, delay) => { let lastCall = 0; return (...args) => { const now = Date.now(); if (now - lastCall >= delay) { lastCall = now; func(...args); } }; }; exports.throttle = throttle; /** * Debounce pour retarder l'exécution d'une fonction */ const debounce = (func, delay) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func(...args), delay); }; }; exports.debounce = debounce; //# sourceMappingURL=mathUtils.js.map