
# Isochrone Explorer

[![npm version](https://img.shields.io/npm/v/isochrone-explorer)](https://www.npmjs.com/package/isochrone-explorer)
[![npm downloads](https://img.shields.io/npm/dt/isochrone-explorer)](https://www.npmjs.com/package/isochrone-explorer)

A Node.js library for generating isochrones and finding routes using road network data and Dijkstra's algorithm.

This project enables you to:
- Generate **isochrones** to visualize areas reachable within a specified time or distance from a given point.
- Find the **shortest route** between two coordinates using road networks.

Isochrones represent areas accessible from a starting point within a given time or distance, supporting various travel modes (e.g., car, bike, walk, cycle).

## Features

- Fetch road network data via API requests.
- Generate isochrones based on time or distance constraints.
- Calculate shortest paths between two points.
- Support for multiple travel modes: `car`, `bike`, `walk`, and `cycle`.
- Lightweight and dependency-efficient, using only `axios` for HTTP requests.

## Prerequisites

Before getting started, ensure you have:

- **Node.js** (v14 or higher recommended)
- **npm** (v6 or higher)
- Internet access to fetch road network data via the API (no API key required)

## Installation

Install the package via npm:

```bash
npm install isochrone-explorer
```

### Dependencies
- `axios (^1.6.0)`: For making HTTP requests to the API.

## Code Examples

### 1. Generating Isochrones
Generate isochrones to determine areas reachable from a specific location within a given time or distance.

```javascript
const { generateIsochrones } = require('isochrone-explorer');

async function generateIsochroneExample() {
  const locations = [[-122.4194, 37.7749]]; // [lon, lat] for San Francisco
  const distances = [5000]; // 5 km
  const times = [null]; // Use distance instead of time
  const modes = ['car'];

  try {
    const results = await generateIsochrones({ locations, distances, times, modes });
    console.log(results);
    // Output: [{ location: [-122.4194, 37.7749], polygon: [[lon1, lat1], [lon2, lat2], ...] }]
  } catch (error) {
    console.error('Error:', error.message);
  }
}

generateIsochroneExample();
```

**Parameters:**
- `locations`: Array of `[lon, lat]` coordinates.
- `distances`: Array of maximum distances (meters). Use `null` if using time.
- `times`: Array of maximum times (seconds). Use `null` if using distance.
- `modes`: Array of travel modes (`car`, `bike`, `walk`, `cycle`).

**Output:**
- Array of objects with:
  - `location`: Original `[lon, lat]` coordinates.
  - `polygon`: Array of `[lon, lat]` coordinates forming the isochrone boundary.

### 2. Finding Routes
Calculate the shortest path between two coordinates using road networks.

```javascript
const { findRoute } = require('isochrone-explorer');

async function findRouteExample() {
  const startCoord = [-122.4194, 37.7749]; // San Francisco
  const endCoord = [-122.4089, 37.7837]; // Nearby point

  try {
    const path = await findRoute(startCoord, endCoord);
    console.log(path);
    // Output: [[lon1, lat1], [lon2, lat2], ...]
  } catch (error) {
    console.error('Error:', error.message);
  }
}

findRouteExample();
```

**Parameters:**
- `startCoord`: `[lon, lat]` of the starting point.
- `endCoord`: `[lon, lat]` of the destination.

**Output:**
- Array of `[lon, lat]` coordinates representing the shortest path, or an empty array if no path is found.


## Configuration

### Travel Modes
The package supports the following travel modes with default speeds (configurable in `src/constants.js`):

- `car`: 70 km/h
- `bike`: 45 km/h
- `walk`: 5 km/h
- `cycle`: 15 km/h

To customize speeds, modify `src/constants.js`:

```javascript
module.exports = {
  MODE_SPEEDS: {
    car: 80, // Update to 80 km/h
    bike: 50,
    walk: 6,
    cycle: 20,
  },
};
```

## Limitations
- **Data Scope:** Fetches road network data within a 1 km radius of the input coordinates, which may limit results for large isochrones or long routes.
- **Polygon Output:** Isochrone polygons are raw point sets and may require further processing for visualization (e.g., with Leaflet or Google Maps).
- **Performance:** Processing large road network datasets can be slow for extensive areas.
- **API:** Relies on an external API for fetching road network data, which may have rate limits or occasional downtime.

## Integration with Map Libraries
To visualize isochrones or routes, you can integrate the output with mapping libraries like Leaflet or Google Maps.

### Example: Isochrone with Leaflet

```javascript
import React, { useEffect, useState } from 'react';
import { MapContainer, TileLayer, Polygon, Marker } from 'react-leaflet';
import { generateIsochrones } from 'isochrone-explorer';
import 'leaflet/dist/leaflet.css';

const IsochroneLeaflet = () => {
  const [isochrone, setIsochrone] = useState(null);
  const center = [37.7749, -122.4194]; // San Francisco [lat, lon]

  useEffect(() => {
    const fetchIsochrone = async () => {
      const results = await generateIsochrones({
        locations: [[-122.4194, 37.7749]], // [lon, lat]
        distances: [5000], // 5 km
        times: [null],
        modes: ['car'],
      });
      setIsochrone(results[0]?.polygon);
    };
    fetchIsochrone();
  }, []);

  return (
    <MapContainer center={center} zoom={13} style={{ height: '500px', width: '100%' }}>
      <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='© OpenStreetMap contributors'
      />
      {isochrone && (
        <Polygon positions={isochrone.map(coord => [coord[1], coord[0]])} color="blue" fillOpacity={0.4} />
      )}
      <Marker position={center} />
    </MapContainer>
  );
};

export default IsochroneLeaflet;
```

**Note:** Requires `react-leaflet` and `leaflet` packages for visualization.

## Contributing
Contributions are welcome! To contribute:

1. Fork the repository.
2. Create a feature branch (`git checkout -b feature/your-feature`).
3. Commit your changes (`git commit -m 'Add your feature'`).
4. Push to the branch (`git push origin feature/your-feature`).
5. Open a pull request.



## Author
Nihar Ranjan Mohanta
