or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-support.mdcore-data-types.mddistance-calculations.mderror-handling.mdgeocoding-services.mdindex.mdrate-limiting.md

distance-calculations.mddocs/

0

# Distance Calculations

1

2

Geopy provides precise distance calculations using geodesic (ellipsoidal earth model) and great-circle (spherical earth model) algorithms with automatic unit conversions and destination point calculations.

3

4

## Capabilities

5

6

### Distance Base Class

7

8

Base class for all distance measurements with automatic unit conversions and arithmetic operations.

9

10

```python { .api }

11

from geopy.distance import Distance

12

13

class Distance:

14

"""

15

Base class for distance measurements with unit conversions.

16

Supports arithmetic operations and destination calculations.

17

"""

18

19

def __init__(self, *args, **kwargs):

20

"""Initialize distance measurement"""

21

22

@property

23

def kilometers(self) -> float:

24

"""Distance in kilometers"""

25

26

@property

27

def km(self) -> float:

28

"""Alias for kilometers"""

29

30

@property

31

def meters(self) -> float:

32

"""Distance in meters"""

33

34

@property

35

def m(self) -> float:

36

"""Alias for meters"""

37

38

@property

39

def miles(self) -> float:

40

"""Distance in miles"""

41

42

@property

43

def mi(self) -> float:

44

"""Alias for miles"""

45

46

@property

47

def feet(self) -> float:

48

"""Distance in feet"""

49

50

@property

51

def ft(self) -> float:

52

"""Alias for feet"""

53

54

@property

55

def nautical(self) -> float:

56

"""Distance in nautical miles"""

57

58

@property

59

def nm(self) -> float:

60

"""Alias for nautical miles"""

61

62

def destination(self, point, bearing, distance=None):

63

"""

64

Calculate destination point from bearing and distance.

65

66

Parameters:

67

- point (Point): Starting point

68

- bearing (float): Bearing in degrees (0-360)

69

- distance (Distance): Distance to travel (uses self if None)

70

71

Returns:

72

Point: Destination point

73

"""

74

75

def __add__(self, other):

76

"""Addition with another distance"""

77

78

def __sub__(self, other):

79

"""Subtraction with another distance"""

80

81

def __mul__(self, scalar):

82

"""Multiplication by scalar"""

83

84

def __truediv__(self, scalar):

85

"""Division by scalar"""

86

87

def __lt__(self, other):

88

"""Less than comparison"""

89

90

def __le__(self, other):

91

"""Less than or equal comparison"""

92

93

def __eq__(self, other):

94

"""Equality comparison"""

95

96

def __ne__(self, other):

97

"""Inequality comparison"""

98

99

def __gt__(self, other):

100

"""Greater than comparison"""

101

102

def __ge__(self, other):

103

"""Greater than or equal comparison"""

104

```

105

106

### Geodesic Distance

107

108

Precise distance calculations using ellipsoidal earth model for maximum accuracy.

109

110

```python { .api }

111

from geopy.distance import geodesic

112

113

class geodesic(Distance):

114

"""

115

Calculate geodesic distance using ellipsoidal earth model.

116

Most accurate distance calculation method.

117

"""

118

119

def __init__(self, point1=None, point2=None, ellipsoid='WGS-84'):

120

"""

121

Initialize geodesic distance calculation.

122

123

Parameters:

124

- point1 (Point): First point

125

- point2 (Point): Second point

126

- ellipsoid (str): Reference ellipsoid name

127

128

Supported ellipsoids:

129

- 'WGS-84' (default) - World Geodetic System 1984

130

- 'GRS-80' - Geodetic Reference System 1980

131

- 'Airy (1830)' - Airy ellipsoid 1830

132

- 'Intl 1924' - International ellipsoid 1924

133

- 'Clarke (1880)' - Clarke ellipsoid 1880

134

- 'GRS-67' - Geodetic Reference System 1967

135

"""

136

137

def measure(self, point1, point2):

138

"""

139

Measure distance between two points.

140

141

Parameters:

142

- point1 (Point): First point

143

- point2 (Point): Second point

144

145

Returns:

146

geodesic: Distance measurement

147

"""

148

149

def destination(self, point, bearing, distance=None):

150

"""

151

Calculate destination point using geodesic calculation.

152

153

Parameters:

154

- point (Point): Starting point

155

- bearing (float): Initial bearing in degrees (0-360)

156

- distance (Distance): Distance to travel

157

158

Returns:

159

Point: Destination point with precise coordinates

160

"""

161

```

162

163

### Great Circle Distance

164

165

Faster distance calculations using spherical earth model with good accuracy for most applications.

166

167

```python { .api }

168

from geopy.distance import great_circle

169

170

class great_circle(Distance):

171

"""

172

Calculate great-circle distance using spherical earth model.

173

Faster but less accurate than geodesic calculations.

174

"""

175

176

def __init__(self, point1=None, point2=None, radius=EARTH_RADIUS):

177

"""

178

Initialize great-circle distance calculation.

179

180

Parameters:

181

- point1 (Point): First point

182

- point2 (Point): Second point

183

- radius (float): Earth radius in kilometers (default: 6371.009)

184

"""

185

186

def measure(self, point1, point2):

187

"""

188

Measure great-circle distance between two points.

189

190

Parameters:

191

- point1 (Point): First point

192

- point2 (Point): Second point

193

194

Returns:

195

great_circle: Distance measurement

196

"""

197

198

def destination(self, point, bearing, distance=None):

199

"""

200

Calculate destination point using great-circle calculation.

201

202

Parameters:

203

- point (Point): Starting point

204

- bearing (float): Bearing in degrees (0-360)

205

- distance (Distance): Distance to travel

206

207

Returns:

208

Point: Destination point

209

"""

210

```

211

212

### Constants and Aliases

213

214

```python { .api }

215

from geopy.distance import EARTH_RADIUS, ELLIPSOIDS, distance

216

217

# Constants

218

EARTH_RADIUS = 6371.009 # Mean earth radius in kilometers

219

220

ELLIPSOIDS = {

221

'WGS-84': (6378137.0, 6356752.314245, 298.257223563),

222

'GRS-80': (6378137.0, 6356752.314140, 298.257222101),

223

'Airy (1830)': (6377563.396, 6356256.909, 299.3249646),

224

'Intl 1924': (6378388.0, 6356911.946, 297.0),

225

'Clarke (1880)': (6378249.145, 6356514.870, 293.465),

226

'GRS-67': (6378160.0, 6356774.719, 298.25)

227

}

228

229

# Default distance algorithm (alias for geodesic)

230

distance = geodesic

231

```

232

233

### Utility Functions

234

235

```python { .api }

236

from geopy.distance import lonlat

237

238

def lonlat(x, y, z=0):

239

"""

240

Convert (longitude, latitude) to Point(latitude, longitude).

241

242

Utility function to handle coordinate order differences.

243

Many APIs return coordinates as [longitude, latitude] but

244

Point expects (latitude, longitude).

245

246

Parameters:

247

- x (float): Longitude

248

- y (float): Latitude

249

- z (float): Altitude (optional)

250

251

Returns:

252

Point: Point(latitude, longitude, altitude)

253

"""

254

```

255

256

## Usage Examples

257

258

### Basic Distance Calculations

259

260

```python

261

from geopy.distance import geodesic, great_circle

262

from geopy.point import Point

263

264

# Define some locations

265

new_york = Point(40.7128, -74.0060)

266

los_angeles = Point(34.0522, -118.2437)

267

london = Point(51.5074, -0.1278)

268

269

# Calculate distances using different algorithms

270

geo_distance = geodesic(new_york, los_angeles)

271

gc_distance = great_circle(new_york, los_angeles)

272

273

print(f"Geodesic distance: {geo_distance.miles:.2f} miles")

274

print(f"Great circle distance: {gc_distance.miles:.2f} miles")

275

print(f"Difference: {abs(geo_distance.miles - gc_distance.miles):.2f} miles")

276

277

# Access different units

278

print(f"Distance in kilometers: {geo_distance.km:.2f}")

279

print(f"Distance in meters: {geo_distance.m:.2f}")

280

print(f"Distance in nautical miles: {geo_distance.nautical:.2f}")

281

print(f"Distance in feet: {geo_distance.feet:.2f}")

282

```

283

284

### Distance Arithmetic

285

286

```python

287

from geopy.distance import geodesic

288

289

# Calculate multiple distances

290

ny_to_la = geodesic(new_york, los_angeles)

291

la_to_london = geodesic(los_angeles, london)

292

293

# Arithmetic operations

294

total_distance = ny_to_la + la_to_london

295

half_distance = ny_to_la / 2

296

double_distance = ny_to_la * 2

297

298

print(f"NY to LA: {ny_to_la.miles:.0f} miles")

299

print(f"LA to London: {la_to_london.miles:.0f} miles")

300

print(f"Total journey: {total_distance.miles:.0f} miles")

301

print(f"Half distance: {half_distance.miles:.0f} miles")

302

303

# Distance comparisons

304

if ny_to_la > la_to_london:

305

print("NY to LA is farther than LA to London")

306

else:

307

print("LA to London is farther than NY to LA")

308

309

# Sort locations by distance from reference point

310

reference = Point(41.8781, -87.6298) # Chicago

311

cities = [

312

("New York", new_york),

313

("Los Angeles", los_angeles),

314

("London", london)

315

]

316

317

cities_with_distance = [

318

(name, point, geodesic(reference, point))

319

for name, point in cities

320

]

321

322

# Sort by distance

323

cities_sorted = sorted(cities_with_distance, key=lambda x: x[2].kilometers)

324

325

print("\nCities sorted by distance from Chicago:")

326

for name, point, dist in cities_sorted:

327

print(f"{name}: {dist.miles:.0f} miles")

328

```

329

330

### Destination Point Calculations

331

332

```python

333

from geopy.distance import geodesic

334

from geopy.point import Point

335

336

# Starting point

337

start = Point(40.7128, -74.0060) # New York

338

339

# Calculate destinations at different bearings and distances

340

distance_100km = geodesic(kilometers=100)

341

distance_200mi = geodesic(miles=200)

342

343

# Cardinal directions (0° = North, 90° = East, 180° = South, 270° = West)

344

destinations = {}

345

bearings = [

346

(0, "North"),

347

(90, "East"),

348

(180, "South"),

349

(270, "West"),

350

(45, "Northeast"),

351

(135, "Southeast"),

352

(225, "Southwest"),

353

(315, "Northwest")

354

]

355

356

print("Destinations 100km from New York:")

357

for bearing, direction in bearings:

358

dest = distance_100km.destination(start, bearing)

359

destinations[direction] = dest

360

print(f"{direction} ({bearing}°): {dest.format_decimal()}")

361

362

# Calculate round trip

363

outbound = geodesic(start, destinations["North"])

364

# Bearing back is opposite direction (180° difference)

365

home = outbound.destination(destinations["North"], 180)

366

367

print(f"\nRound trip verification:")

368

print(f"Original: {start.format_decimal()}")

369

print(f"Returned: {home.format_decimal()}")

370

print(f"Difference: {geodesic(start, home).meters:.2f} meters")

371

```

372

373

### Advanced Distance Applications

374

375

```python

376

from geopy.distance import geodesic

377

from geopy.point import Point

378

import math

379

380

def calculate_area_of_triangle(p1, p2, p3):

381

"""Calculate area of triangle using Heron's formula with geodesic distances"""

382

# Calculate side lengths

383

a = geodesic(p2, p3).meters

384

b = geodesic(p1, p3).meters

385

c = geodesic(p1, p2).meters

386

387

# Semi-perimeter

388

s = (a + b + c) / 2

389

390

# Heron's formula

391

area = math.sqrt(s * (s - a) * (s - b) * (s - c))

392

return area # in square meters

393

394

def find_center_point(points):

395

"""Find geographic center (centroid) of multiple points"""

396

if not points:

397

return None

398

399

# Convert to cartesian coordinates for averaging

400

x_total = y_total = z_total = 0

401

402

for point in points:

403

lat_rad = math.radians(point.latitude)

404

lon_rad = math.radians(point.longitude)

405

406

x = math.cos(lat_rad) * math.cos(lon_rad)

407

y = math.cos(lat_rad) * math.sin(lon_rad)

408

z = math.sin(lat_rad)

409

410

x_total += x

411

y_total += y

412

z_total += z

413

414

# Average

415

x_avg = x_total / len(points)

416

y_avg = y_total / len(points)

417

z_avg = z_total / len(points)

418

419

# Convert back to lat/lon

420

hyp = math.sqrt(x_avg**2 + y_avg**2)

421

lat = math.atan2(z_avg, hyp)

422

lon = math.atan2(y_avg, x_avg)

423

424

return Point(math.degrees(lat), math.degrees(lon))

425

426

def create_circle_of_points(center, radius_km, num_points=8):

427

"""Create circle of points around a center at specified radius"""

428

points = []

429

distance_obj = geodesic(kilometers=radius_km)

430

431

for i in range(num_points):

432

bearing = (360 / num_points) * i

433

point = distance_obj.destination(center, bearing)

434

points.append(point)

435

436

return points

437

438

# Example usage

439

triangle_points = [

440

Point(40.7128, -74.0060), # New York

441

Point(41.8781, -87.6298), # Chicago

442

Point(39.7392, -104.9903) # Denver

443

]

444

445

area = calculate_area_of_triangle(*triangle_points)

446

center = find_center_point(triangle_points)

447

circle = create_circle_of_points(center, 500, 12) # 500km radius, 12 points

448

449

print(f"Triangle area: {area/1e6:.2f} square kilometers")

450

print(f"Geographic center: {center.format_decimal()}")

451

print(f"Circle points around center:")

452

for i, point in enumerate(circle):

453

bearing = (360 / len(circle)) * i

454

print(f" {bearing:3.0f}°: {point.format_decimal()}")

455

```

456

457

### Performance Considerations

458

459

```python

460

from geopy.distance import geodesic, great_circle

461

from geopy.point import Point

462

import time

463

464

def benchmark_distance_calculations():

465

"""Compare performance of geodesic vs great-circle calculations"""

466

467

# Test data

468

points = [

469

Point(40.7128, -74.0060), # New York

470

Point(34.0522, -118.2437), # Los Angeles

471

Point(51.5074, -0.1278), # London

472

Point(35.6762, 139.6503), # Tokyo

473

Point(-33.8688, 151.2093), # Sydney

474

]

475

476

num_calculations = 1000

477

478

# Benchmark geodesic

479

start_time = time.time()

480

for _ in range(num_calculations):

481

for i in range(len(points)):

482

for j in range(i+1, len(points)):

483

geodesic(points[i], points[j])

484

geodesic_time = time.time() - start_time

485

486

# Benchmark great circle

487

start_time = time.time()

488

for _ in range(num_calculations):

489

for i in range(len(points)):

490

for j in range(i+1, len(points)):

491

great_circle(points[i], points[j])

492

great_circle_time = time.time() - start_time

493

494

print(f"Geodesic calculations: {geodesic_time:.3f} seconds")

495

print(f"Great circle calculations: {great_circle_time:.3f} seconds")

496

print(f"Speed ratio: {geodesic_time/great_circle_time:.1f}x")

497

498

# Accuracy comparison

499

p1, p2 = points[0], points[1]

500

geo_dist = geodesic(p1, p2)

501

gc_dist = great_circle(p1, p2)

502

503

print(f"\nAccuracy comparison (NY to LA):")

504

print(f"Geodesic: {geo_dist.kilometers:.6f} km")

505

print(f"Great circle: {gc_dist.kilometers:.6f} km")

506

print(f"Difference: {abs(geo_dist.kilometers - gc_dist.kilometers):.6f} km")

507

print(f"Relative error: {abs(geo_dist.kilometers - gc_dist.kilometers)/geo_dist.kilometers*100:.4f}%")

508

509

# Run benchmark

510

benchmark_distance_calculations()

511

```

512

513

### Custom Ellipsoids

514

515

```python

516

from geopy.distance import geodesic, ELLIPSOIDS

517

518

# View available ellipsoids

519

print("Available ellipsoids:")

520

for name, (a, b, f) in ELLIPSOIDS.items():

521

print(f" {name}: a={a}m, b={b}m, f=1/{f:.1f}")

522

523

# Compare distances using different ellipsoids

524

p1 = Point(40.7128, -74.0060) # New York

525

p2 = Point(51.5074, -0.1278) # London

526

527

ellipsoid_results = {}

528

for ellipsoid_name in ELLIPSOIDS.keys():

529

distance = geodesic(p1, p2, ellipsoid=ellipsoid_name)

530

ellipsoid_results[ellipsoid_name] = distance.kilometers

531

532

print(f"\nDistance NY to London using different ellipsoids:")

533

for name, dist in ellipsoid_results.items():

534

print(f" {name}: {dist:.6f} km")

535

536

# Find the range

537

min_dist = min(ellipsoid_results.values())

538

max_dist = max(ellipsoid_results.values())

539

print(f"\nRange: {max_dist - min_dist:.6f} km")

540

print(f"Relative variation: {(max_dist - min_dist)/min_dist*100:.4f}%")

541

```