PageSourceSearch

https://z-aki.github.io/javascripts/libs/digipin.js

js z-aki.github.io collected 2026-10-03 10:14:08 UTC 3,261 bytes, 117 lines download raw bytes

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.