geo-toolkits
Version:
A comprehensive TypeScript library for geospatial operations including geofencing, polygon containment, area calculations, and coordinate processing. Supports GeoJSON, KML, and KMZ file formats with both local file and remote URL loading capabilities.
440 lines (339 loc) β’ 12.9 kB
Markdown
# geo-toolkits
A comprehensive TypeScript library for geospatial data processing, area calculations, and geofencing operations. Supports GeoJSON, KML, and KMZ file formats with both local file and remote URL loading capabilities.
## π Features
- **πΊοΈ Multi-format Support**: Load GeoJSON, KML, and KMZ files
- **π Flexible Loading**: Support for both local files and remote URLs
- **π― Geofencing**: Point-in-polygon detection with hole support
- **π Area Calculations**: Accurate spherical area calculations for Earth surface
- **π Statistical Analysis**: Comprehensive area and geometric statistics
- **π Spatial Queries**: Find closest features and multiple containment checks
- **β‘ Performance Optimized**: Bounding box pre-filtering for fast operations
- **π TypeScript**: Full type safety and IntelliSense support
## π¦ Installation
```bash
npm install geo-toolkits
```
## π Quick Start
```typescript
import { GeoToolKit } from 'geo-toolkits';
const kit = new GeoToolKit();
// Load spatial data
await kit.loadFromFile('./boundaries.geojson');
// or from URL
await kit.loadFromUrl('https://example.com/data.geojson');
// Check if a point is inside any polygon
const result = kit.contains(40.7128, -74.0060); // NYC coordinates
if (result.isInside) {
console.log(`Point is inside feature: ${result.featureIndex}`);
}
// Calculate total area
const totalArea = kit.getArea(); // in square meters
const areaInKm2 = kit.getAreaInUnit('square_kilometers');
// Get bounding box
const bbox = kit.getBoundingBox();
console.log(`Area spans: ${bbox.maxLat - bbox.minLat} degrees latitude`);
```
## π API Reference
### Data Loading
#### `loadFromFile(filePath: string): Promise<void>`
Load spatial data from a local file. Supports GeoJSON (.geojson, .json), KML (.kml), and KMZ (.kmz) formats.
```typescript
await kit.loadFromFile('./data/boundaries.geojson');
await kit.loadFromFile('./data/regions.kml');
await kit.loadFromFile('./data/areas.kmz');
```
#### `loadFromUrl(url: string): Promise<void>`
Load spatial data from a remote URL. Automatically detects file format and handles network timeouts.
```typescript
await kit.loadFromUrl('https://example.com/boundaries.geojson');
await kit.loadFromUrl('https://maps.example.com/regions.kml');
```
#### `isLoaded(): boolean`
Check if spatial data has been successfully loaded.
```typescript
if (kit.isLoaded()) {
console.log('Data is ready for analysis');
}
```
### Dataset Information
#### `getDatasetInfo()`
Get comprehensive information about the loaded dataset.
```typescript
const info = kit.getDatasetInfo();
console.log({
source: info.source,
originalFormat: info.originalFormat, // 'geojson' | 'kml' | 'kmz'
featureCount: info.featureCount,
polygonCount: info.polygonCount,
multiPolygonCount: info.multiPolygonCount,
fileSize: info.fileSize,
loadedAt: info.loadedAt
});
```
### Feature Access
#### `getFeatures(): SpatialFeature[]`
Get all loaded spatial features (Polygons and MultiPolygons only).
```typescript
const features = kit.getFeatures();
features.forEach((feature, index) => {
console.log(`Feature ${index}: ${feature.type}`);
console.log(`Properties:`, feature.properties);
});
```
#### `getPolygons(): PolygonFeature[]`
Get only Polygon features from the dataset.
```typescript
const polygons = kit.getPolygons();
console.log(`Found ${polygons.length} polygon features`);
```
#### `getMultiPolygons(): MultiPolygonFeature[]`
Get only MultiPolygon features from the dataset.
```typescript
const multiPolygons = kit.getMultiPolygons();
console.log(`Found ${multiPolygons.length} multi-polygon features`);
```
### Geofencing Operations
#### `contains(lat: number, lng: number): ContainmentResult`
Check if a coordinate point is contained within any polygon feature. Handles polygons with holes and MultiPolygon features.
```typescript
const result = kit.contains(40.7128, -74.0060);
if (result.isInside) {
console.log(`Point is inside feature ${result.featureIndex}`);
console.log(`Feature properties:`, result.properties);
if (result.geometryType === 'MultiPolygon') {
console.log(`Specific polygon: ${result.polygonIndex}`);
}
}
```
#### `findClosestFeature(lat: number, lng: number)`
Find the closest feature to a given coordinate point.
```typescript
const closest = kit.findClosestFeature(40.7128, -74.0060);
if (closest) {
console.log(`Closest feature: ${closest.featureIndex}`);
console.log(`Distance: ${closest.distance} meters`);
}
```
#### `getAllContainingFeatures(lat: number, lng: number): ContainmentResult[]`
Get all features that contain the given coordinate (useful for overlapping polygons).
```typescript
const allContaining = kit.getAllContainingFeatures(40.7128, -74.0060);
console.log(`Point is contained in ${allContaining.length} features`);
allContaining.forEach(result => {
console.log(`Feature ${result.featureIndex}: ${result.properties.name}`);
});
```
### Geometry Calculations
#### `getBoundingBox(): BoundingBox | null`
Get the overall bounding box that encompasses all features.
```typescript
const bbox = kit.getBoundingBox();
if (bbox) {
console.log(`Latitude range: ${bbox.minLat} to ${bbox.maxLat}`);
console.log(`Longitude range: ${bbox.minLng} to ${bbox.maxLng}`);
}
```
#### `getMidpoint(): MidpointResult | null`
Calculate the geometric center (midpoint) of all features.
```typescript
const center = kit.getMidpoint();
if (center) {
console.log(`Dataset center: ${center.latitude}, ${center.longitude}`);
}
```
#### `isWithinBoundingBox(lat: number, lng: number): boolean`
Quick check if a coordinate is within the overall dataset bounding box.
```typescript
const withinBounds = kit.isWithinBoundingBox(40.7128, -74.0060);
console.log(`Point within dataset bounds: ${withinBounds}`);
```
### Area Calculations
#### `getArea(): number`
Calculate the total area of all features in square meters using spherical geometry.
```typescript
const totalArea = kit.getArea(); // square meters
console.log(`Total area: ${totalArea.toLocaleString()} mΒ²`);
```
#### `getAreaInUnit(unit): number`
Get total area in specific units.
```typescript
const areaKm2 = kit.getAreaInUnit('square_kilometers');
const areaHectares = kit.getAreaInUnit('hectares');
const areaAcres = kit.getAreaInUnit('acres');
console.log(`Area: ${areaKm2.toFixed(2)} kmΒ²`);
console.log(`Area: ${areaHectares.toFixed(2)} hectares`);
console.log(`Area: ${areaAcres.toFixed(2)} acres`);
```
#### `getAreaDetails(): AreaResult`
Get detailed area breakdown for each feature.
```typescript
const details = kit.getAreaDetails();
console.log(`Total area: ${details.totalArea} ${details.unit}`);
details.features.forEach(feature => {
console.log(`Feature ${feature.featureIndex}: ${feature.area} mΒ²`);
// For MultiPolygon features
if (feature.polygonAreas) {
feature.polygonAreas.forEach((polyArea, index) => {
console.log(` Polygon ${index}: ${polyArea} mΒ²`);
});
}
});
```
#### `getFeatureArea(featureIndex: number): number`
Calculate area of a specific feature by index.
```typescript
const feature0Area = kit.getFeatureArea(0);
console.log(`Feature 0 area: ${feature0Area} mΒ²`);
```
#### `getAreaStatistics()`
Get comprehensive area statistics for the dataset.
```typescript
const stats = kit.getAreaStatistics();
console.log({
totalArea: stats.totalArea,
averageArea: stats.averageArea,
largestFeature: stats.largestFeature,
smallestFeature: stats.smallestFeature,
distribution: {
min: stats.areaDistribution.min,
max: stats.areaDistribution.max,
median: stats.areaDistribution.median,
standardDeviation: stats.areaDistribution.stdDev
}
});
```
### Utility Methods
#### `validateCoordinates(lat: number, lng: number): boolean`
Validate if coordinates are within valid ranges.
```typescript
const isValid = kit.validateCoordinates(40.7128, -74.0060);
if (!isValid) {
console.log('Invalid coordinates provided');
}
```
## π― Use Cases
### Real Estate Applications
```typescript
// Load property boundaries
await kit.loadFromFile('./property-boundaries.geojson');
// Check if a house location is within a specific zone
const houseLocation = kit.contains(40.7128, -74.0060);
if (houseLocation.isInside) {
const zone = houseLocation.properties.zoning_type;
console.log(`House is in ${zone} zone`);
}
// Calculate total developable area
const totalArea = kit.getAreaInUnit('acres');
console.log(`Total developable area: ${totalArea} acres`);
```
### Delivery & Logistics
```typescript
// Load delivery zones
await kit.loadFromUrl('https://api.company.com/delivery-zones.geojson');
// Check if delivery address is serviceable
const deliveryLocation = kit.contains(customerLat, customerLng);
if (deliveryLocation.isInside) {
const zone = deliveryLocation.properties.delivery_zone;
const fee = deliveryLocation.properties.delivery_fee;
console.log(`Delivery available in ${zone} for $${fee}`);
} else {
console.log('Sorry, we don\'t deliver to this location');
}
```
### Environmental Monitoring
```typescript
// Load protected areas
await kit.loadFromFile('./protected-areas.geojson');
// Check if coordinates are in protected zone
const location = kit.contains(sensorLat, sensorLng);
if (location.isInside) {
const protectionLevel = location.properties.protection_level;
console.log(`Sensor is in ${protectionLevel} protected area`);
}
// Calculate total protected area
const protectedArea = kit.getAreaInUnit('hectares');
console.log(`Total protected area: ${protectedArea} hectares`);
```
### Urban Planning
```typescript
// Load city districts
await kit.loadFromFile('./city-districts.geojson');
// Analyze district sizes
const areaStats = kit.getAreaStatistics();
console.log(`Largest district: ${areaStats.largestFeature.area / 1000000} kmΒ²`);
console.log(`Average district size: ${areaStats.averageArea / 1000000} kmΒ²`);
// Find which district a new development is in
const development = kit.contains(newDevLat, newDevLng);
if (development.isInside) {
const district = development.properties.district_name;
console.log(`New development is in ${district}`);
}
```
## π§ Advanced Usage
### Working with Multiple Datasets
```typescript
const residentialKit = new GeoToolKit();
const commercialKit = new GeoToolKit();
await residentialKit.loadFromFile('./residential-zones.geojson');
await commercialKit.loadFromFile('./commercial-zones.geojson');
// Check property zoning
const residentialCheck = residentialKit.contains(lat, lng);
const commercialCheck = commercialKit.contains(lat, lng);
if (residentialCheck.isInside) {
console.log('Property is in residential zone');
} else if (commercialCheck.isInside) {
console.log('Property is in commercial zone');
}
```
### Error Handling
```typescript
try {
await kit.loadFromUrl('https://example.com/data.geojson');
const result = kit.contains(lat, lng);
console.log('Geofencing check completed');
} catch (error) {
if (error.code === 'FILE_NOT_FOUND') {
console.log('Data file not found');
} else if (error.code === 'INVALID_COORDINATES') {
console.log('Invalid coordinates provided');
} else {
console.log('An error occurred:', error.message);
}
}
```
## π Supported File Formats
| Format | Extension | Description |
|--------|-----------|-------------|
| GeoJSON | `.geojson`, `.json` | Standard geospatial JSON format |
| KML | `.kml` | Keyhole Markup Language |
| KMZ | `.kmz` | Compressed KML format |
**Note**: Only Polygon and MultiPolygon geometries are supported. Point, LineString, and other geometry types are filtered out during loading.
## π Coordinate System
- **Input**: WGS84 (EPSG:4326) latitude/longitude coordinates
- **Range**: Latitude: -90 to 90, Longitude: -180 to 180
- **Area Calculations**: Uses spherical geometry for accurate Earth surface area calculations
- **Distance Calculations**: Uses Haversine formula for great circle distances
## β‘ Performance
- **Bounding Box Optimization**: Fast pre-filtering eliminates ~90% of expensive polygon checks
- **Spatial Indexing**: Efficient point-in-polygon operations
- **Memory Efficient**: Processes large datasets without excessive memory usage
- **TypeScript**: Zero runtime overhead with full compile-time type checking
## π TypeScript Support
Full TypeScript support with comprehensive type definitions:
```typescript
import {
GeoToolKit,
type ContainmentResult,
type BoundingBox,
type AreaResult
} from 'geo-toolkits';
const kit = new GeoToolKit();
const result: ContainmentResult = kit.contains(40.7128, -74.0060);
const bbox: BoundingBox | null = kit.getBoundingBox();
```
## π License
MIT
## π€ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## π Support
For issues and questions, please visit our [GitHub repository](https://github.com/bolu1/geo-toolkits).