@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
JavaScript
;
// 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