1/** 2 * DIGIPIN Encoder and Decoder Library 3 * Developed by India Post, Department of Posts 4 * Released under an open-source license for public use 5 * 6 * This module contains two main functions: 7 * - getDigiPin(lat, lon): Encodes latitude & longitude into a 10-digit alphanumeric DIGIPIN 8 * - getLatLngFromDigiPin(digiPin): Decodes a DIGIPIN back into its central latitude & longitude 9 */ 10 11const DIGIPIN_GRID = [ 12 ['F', 'C', '9', '8'], 13 ['J', '3', '2', '7'], 14 ['K', '4', '5', '6'], 15 ['L', 'M', 'P', 'T'] 16 ]; 17 18 const BOUNDS = { 19 minLat: 2.5, 20 maxLat: 38.5, 21 minLon: 63.5, 22 maxLon: 99.5 23 }; 24 25 function getDigiPin(lat, lon) { 26 if (lat < BOUNDS.minLat || lat > BOUNDS.maxLat) throw new Error('Latitude out of range'); 27 if (lon < BOUNDS.minLon || lon > BOUNDS.maxLon) throw new Error('Longitude out of range'); 28 29 let minLat = BOUNDS.minLat; 30 let maxLat = BOUNDS.maxLat; 31 let minLon = BOUNDS.minLon; 32 let maxLon = BOUNDS.maxLon; 33 34 let digiPin = ''; 35 36 for (let level = 1; level <= 10; level++) { 37 const latDiv = (maxLat - minLat) / 4; 38 const lonDiv = (maxLon - minLon) / 4; 39 40 // REVERSED row logic (to match original) 41 let row = 3 - Math.floor((lat - minLat) / latDiv); 42 let col = Math.floor((lon - minLon) / lonDiv); 43 44 row = Math.max(0, Math.min(row, 3)); 45 col = Math.max(0, Math.min(col, 3)); 46 47 digiPin += DIGIPIN_GRID[row][col]; 48 49 if (level === 3 || level === 6) digiPin += '-'; 50 51 // Update bounds (reverse logic for row) 52 maxLat = minLat + latDiv * (4 - row); 53 minLat = minLat + latDiv * (3 - row); 54 55 minLon = minLon + lonDiv * col; 56 maxLon = minLon + lonDiv; 57 } 58 59 return digiPin; 60 } 61 62 63 function getLatLngFromDigiPin(digiPin) { 64 const pin = digiPin.replace(/-/g, ''); 65 if (pin.length !== 10) throw new Error('Invalid DIGIPIN'); 66 67 let minLat = BOUNDS.minLat; 68 let maxLat = BOUNDS.maxLat; 69 let minLon = BOUNDS.minLon; 70 let maxLon = BOUNDS.maxLon; 71 72 for (let i = 0; i < 10; i++) { 73 const char = pin[i]; 74 let found = false; 75 let ri = -1, ci = -1; 76 77 // Locate character in DIGIPIN grid 78 for (let r = 0; r < 4; r++) { 79 for (let c = 0; c < 4; c++) { 80 if (DIGIPIN_GRID[r][c] === char) { 81 ri = r; 82 ci = c; 83 found = true; 84 break; 85 } 86 } 87 if (found) break; 88 } 89 90 if (!found) throw new Error('Invalid character in DIGIPIN'); 91 92 const latDiv = (maxLat - minLat) / 4; 93 const lonDiv = (maxLon - minLon) / 4; 94 95 const lat1 = maxLat - latDiv * (ri + 1); 96 const lat2 = maxLat - latDiv * ri; 97 const lon1 = minLon + lonDiv * ci; 98 const lon2 = minLon + lonDiv * (ci + 1); 99 100 // Update bounding box for next level 101 minLat = lat1; 102 maxLat = lat2; 103 minLon = lon1; 104 maxLon = lon2; 105 } 106 107 const centerLat = (minLat + maxLat) / 2; 108 const centerLon = (minLon + maxLon) / 2; 109 110 return { 111 latitude: centerLat.toFixed(6), 112 longitude: centerLon.toFixed(6) 113 }; 114 } 115 116 117 if (typeof module !== 'undefined') module.exports = { getDigiPin, getLatLngFromDigiPin };export { getDigiPin, getLatLngFromDigiPin };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.