关于 searoute
searoute-ts 是用于海上路线规划的 TypeScript/JavaScript 库,支持坐标和 UN/LOCODE 港口输入。它生成 GeoJSON 航线,并可设置航道限制、船舶吃水条件、备选路线、多段行程和预计航时。
主要功能
- 01海上航程计算与 GeoJSON 输出
- 02限制或指定运河及海峡
- 03按船舶吃水限制运河
- 04备选路线与多段航线
- 05按航速估算航时
- 06坐标与 UN/LOCODE 输入
适用场景
- 01比较港口间航程和预计航时
- 02因运河或海峡受阻而改道
- 03规划适配船舶吃水的航线
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| units | enum | 否 | 返回距离的单位。nauticalmiles | kilometers | miles |
| origin | any | 是 | UN/LOCODE 港口代码字符串,或 [longitude, latitude] 坐标对。 |
| speedKnots | number | 否 | 船舶速度,单位为节;提供此值时,将返回以小时为单位的预计时长。 |
| allowArctic | boolean | 否 | 允许通过被冰封的西北/东北航道(默认禁止)。 |
| destination | any | 是 | |
| restrictions | array | 否 | 路线必须避开的指定海峡。例如,["suez","babelmandeb"] 会在红海中断期间强制改走好望角航线。 |
| includeGeometry | boolean | 否 | 在结果中包含航线 LineString GeoJSON。 |
| maxSnapDistanceKm | number | 否 | 拒绝距离海上航运网络超过此值(km)的输入。 |
| vesselDraftMeters | number | 否 | 船舶吃水深度,单位为米;水深不足以通行的运河会自动避开。 |
详细介绍
searoute-ts
地球上任意两点之间的最短海上航线。 一个用于规划海上航线、计算港口间距离、估算到达时间和可视化航运路线的 TypeScript / JavaScript 库,基于 2025 Eurostat 海事网络构建。
npm install searoute-ts
import { seaRoute } from 'searoute-ts';
const route = seaRoute([121.5, 31.0], [4.4, 51.9]);
// Shanghai → Rotterdam → GeoJSON LineString, ~10,664 nm via Suez Canal
🗺️ 试用交互式演示 — 在地图上点击两个点,即可查看航线,并实时调整所有选项。(源代码)
📏 港口间海上距离 — 常见主要港口航线的距离、航行时间和运河通行情况。
也可直接使用纯 JavaScript — 软件包包含编译后的
.js文件和.d.ts声明文件。名称中的-ts只是为了便于搜索,并非语言要求。
为什么选择 searoute-ts
- 🚢 真实的航运路线,而非穿越欧亚大陆的球面大圆航线。
- 🗺️ 返回 GeoJSON — 可直接用于 Leaflet、Mapbox、deck.gl、MapLibre。
- 🌊 2025 Eurostat marnet,明确标注苏伊士、巴拿马、曼德海峡、 马六甲、直布罗陀、多佛、基尔、科林斯、白令、麦哲伦、西北/东北航道。
- 🚫 运河和海峡限制 — 只需一个选项,即可在红海中断时强制绕行好望角。
- 📦 船舶吃水限制 — 船舶超出运河限值时,自动限制通行巴拿马运河(15.2 m)、苏伊士运河(20.1 m)、基尔运河 (7 m)、科林斯运河(7.3 m)。
- 🛤️ K 条最短备选路线 —
seaRouteAlternatives返回基准路线 以及最多 N 条真实可行的备选路线。 - 🧭 多段航点 — 使用
seaRouteMulti规划港口轮换和行程。 - ⏱️ 根据速度估算到达时间 —
speedKnots→durationHours。 - 🛠️ 现代工具链 — TypeScript 5、ESM + CJS 双构建、包含类型定义、 Node 18+,无对等依赖。
快速示例
基础用法 — 最短航线
import { seaRoute } from 'searoute-ts';
const route = seaRoute([-74.04, 40.69], [-0.13, 51.5]); // NYC → London
// route.properties.length // ≈ 3 362 nm
// route.properties.units // 'nauticalmiles'
包含预计到达时间和单位
seaRoute(shanghai, rotterdam, {
units: 'kilometers',
speedKnots: 22,
});
// → 19 753 km, properties.durationHours ≈ 485 h (≈ 20 days)
红海 / 苏伊士中断 — 强制绕行好望角
seaRoute(shanghai, rotterdam, {
restrictions: ['suez', 'babelmandeb'],
});
// → routes via Cape of Good Hope, ~25 800 km
感知船舶类型 — 超大型集装箱船
seaRoute(shanghai, newYork, {
vesselDraftMeters: 16, // exceeds Panama's 15.2 m TFW
});
// → Panama auto-blocked, route goes via Suez
港口代码(UN/LOCODE)
import 'searoute-ts/ports'; // enables UN/LOCODE strings on the core API
import { seaRoute } from 'searoute-ts';
seaRoute('CNSHA', 'NLRTM'); // Shanghai → Rotterdam
seaRoute('CNSHA', [4.4, 51.9]); // mixing a code and coordinates is fine too
约 1 600 个港口的数据集位于 searoute-ts/ports 子路径下,以保持核心部分精简 — 导入该子路径即可注册解析器。你也可以自行解析代码:
import { lookupPort, resolvePort } from 'searoute-ts/ports';
lookupPort('SGSIN'); // → { code, name: 'Singapore', country, coordinates: [lon, lat] }
resolvePort('SGSIN'); // → [103.85, 1.28]
未知代码会抛出 UnknownPortError。有关数据来源,请参阅下文的港口代码。
从 CDN 加载港口数据集,而非打包到项目中
不想打包约 135 KB 的数据集?可以使用 loadPorts 在运行时获取 —
它相当于 loadNetwork。
该数据集也以原始 dist/ports.json 文件形式提供,因此 jsDelivr/unpkg 可免费提供带版本号的文件:
import { seaRoute, loadPorts } from 'searoute-ts';
// Pin a version for reproducibility, or use @latest to always get the newest.
await loadPorts('https://cdn.jsdelivr.net/npm/searoute-ts@latest/dist/ports.json');
seaRoute('CNSHA', 'NLRTM'); // works — the fetched dataset is now registered
https://cdn.jsdelivr.net/npm/searoute-ts@latest/dist/ports.json # newest
https://cdn.jsdelivr.net/npm/searoute-ts@<version>/dist/ports.json # frozen/immutable
(dist/ports.json 从新增港口代码的版本起随发布包提供 — 为确保可复现性,请固定到该版本或更高版本。)
loadPorts 会注册获取的数据集(因此可以解析字符串代码),并返回该数据集。
它使用全局 fetch(Node ≥18 / 浏览器);传入 { fetch } 可覆盖默认值。
多段航线 / 港口轮换
import { seaRouteMulti } from 'searoute-ts';
seaRouteMulti(
[shanghai, singapore, mumbai, rotterdam],
{ units: 'kilometers', returnPassages: true },
);
// → one concatenated LineString, total length, union of passages
备选航线(Yen 风格的运河排列)
import { seaRouteAlternatives } from 'searoute-ts';
const alts = seaRouteAlternatives(shanghai, rotterdam, { k: 4 });
// baseline 19 753 km via Suez
// no-malacca 20 759 km
// no-suez 25 315 km (via Panama)
// no-suez-no-panama 25 845 km (via Cape of Good Hope)
从 URL 获取网络,而不是将其打包(可选)
默认情况下,网络会随包一起打包,因此 seaRoute 无需任何设置即可离线运行。
如果你不想随包发布约 1 MB 的网络(例如为了缩减浏览器包体积,
或希望使用更新的网络而不升级软件包),可以在运行时获取网络,并通过现有的
network 选项传入:
import { seaRoute, loadNetwork } from 'searoute-ts';
// CORS-enabled, served from GitHub Pages (or point at your own host / a CDN).
const network = await loadNetwork('https://mayurrawte.github.io/searoute-ts/marnet.json');
const route = seaRoute(shanghai, rotterdam, { network });
只有获取操作是异步的,seaRoute 本身仍保持同步。loadNetwork
使用全局 fetch(Node ≥18 和所有浏览器均支持);传入 { fetch } 可使用
自定义实现。此功能完全可选;如果不使用它,一切保持不变。
我应该使用哪种方式?
| 方式 | 用法 | 数据版本 | 支持离线 | 最适合 |
|---|---|---|---|---|
| 随包打包(默认) | seaRoute(a, b) — 不传入 network | 固定为已安装软件包中的版本 | ✅ | 大多数用户;无需配置,结果可确定 |
| 通过 URL 获取最新版本 | loadNetwork('…/marnet.json') | 始终使用托管的最新版本 | ❌ 需要网络 | 无需升级即可使用始终最新的数据 |
| 通过 CDN 固定版本 | loadNetwork('https://cdn.jsdelivr.net/npm/[email protected]/…') | 固定不变(不可变) | ❌ 需要网络 | 可复现的构建 |
为托管的网络指定版本
通过选择 URL 来选择版本:
-
@latest/ 滚动版本 — 上文的 GitHub Pages URL 始终提供当前网络。 使用方便,但网络可能会在你不知情的情况下发生变化。 -
固定且不可变 — 由于该软件包发布在 npm 上,jsDelivr 和 unpkg 会自动提供所有已发布版本,并为每个版本提供不可变的 URL:
https://cdn.jsdelivr.net/npm/searoute-ts@latest/dist/marnet.json # newest https://cdn.jsdelivr.net/npm/searoute-ts@2/dist/marnet.json # newest 2.x https://cdn.jsdelivr.net/npm/[email protected]/dist/marnet.json # frozen固定的 URL 永不变化,因此路由结果可复现。(独立 JSON 的 CDN 路径要等到网络作为单独资源发布后才会随软件包提供 — 参见 issue #10;在此之前,请使用 GitHub Pages URL。)
在生产环境中,建议使用固定的 URL(或直接使用默认的随包打包方式),以免网络更新导致距离发生变化。
更高分辨率的网络(可选)
随包打包的网络是 Eurostat 的 100 km marnet_plus。Eurostat 还
发布了更高的分辨率,可提供更准确的沿海路径规划和更短的跳点,但代价是下载量更大,
首次构建路由图的速度也会略慢。两种适中的分辨率以子路径导出的形式提供,因此只有在导入时才会产生相应开销:
import { DEFAULT_MARNET } from 'searoute-ts/marnet-20km'; // or 'searoute-ts/marnet-50km'
import { seaRoute } from 'searoute-ts';
seaRoute(origin, destination, { network: DEFAULT_MARNET });
与默认的随包网络一样,每个变体只会作为共享的
dist/data/marnet-<res>.cjs 资源发布一次,CJS 和 ESM 构建都会在运行时加载它,因此导入变体不会导致网络在不同构建中重复打包。
| 导入 | 分辨率 | 线段数 | JSON 大小 | gzip 后大小 | 沿海精度 |
|---|---|---|---|---|---|
searoute-ts(默认随包版本) | 100 km | 9,847 | ~1.3 MB | ~0.18 MB | 基准 — 适用于全球路径规划 |
searoute-ts/marnet-50km | 50 km | 15,498 | ~1.9 MB | ~0.27 MB | 精度略有提升 |
searoute-ts/marnet-20km | 20 km | 29,581 | ~3.6 MB | ~0.51 MB | 沿海跳点精细得多 |
通过 loadNetwork(见下文) | 10 km | 48,301 | ~5.9 MB | ~0.84 MB | 精度高 — 下载量较大 |
通过 loadNetwork(见下文) | 5 km | 72,478 | ~9.0 MB | ~1.24 MB | 精度最高 — 下载量最大 |
10 km 和 5 km 网络体积足够大,打包后会占据安装内容的大部分,因此不会
随软件包发布。请使用 scripts/build-marnet.cjs 从 Eurostat 源数据生成它们(脚本头部介绍了
GDAL 转换),托管生成的 JSON,然后使用
loadNetwork
加载它,或直接向 network 选项传入任意 FeatureCollection<LineString>。
输出格式
{
type: 'Feature',
geometry: { type: 'LineString', coordinates: [[lon, lat], ...] },
properties: {
length: number, // in `units`, in-water only
units: 'nauticalmiles' | 'kilometers' | 'miles' | ...,
bbox: [minLon, minLat, maxLon, maxLat],
greatCircleLength: number, // haversine between inputs, same units
detourRatio: number, // routeKm / greatCircleKm
originSnapKm: number, // input → network distance
destinationSnapKm: number,
durationHours?: number, // if `speedKnots` set
passages?: ('suez' | 'panama' | ...)[], // if `returnPassages: true`
ecaKm?: number, // if `emissions` + `searoute-ts/eca` imported
ecaFraction?: number, // ecaKm / length (0–1)
co2eTonnes?: number, // if `emissions` + `vesselClass`/factor
}
}
length 是两个吸附后的网络顶点之间的距离,不包括输入点到网络的路段(originSnapKm、destinationSnapKm,单位始终为 km),即使设置了 appendOriginDestination: true 也是如此;该选项只会将原始点添加到线路中。若要计算门到门的距离,请自行将它们加上:
const { length, originSnapKm, destinationSnapKm } = seaRoute(a, b, { units: 'kilometers' }).properties;
const doorToDoorKm = originSnapKm + length + destinationSnapKm;
对于短于网络分辨率的航段(默认约 100 km,使用 searoute-ts/marnet-20km 时约 20 km),吸附后的顶点可能比输入点更靠近彼此,因此 length 可能小于 greatCircleLength(detourRatio < 1)。如果两个输入点都吸附到同一个顶点,则会抛出 NoRouteError。
完整选项
seaRoute(origin, destination, {
units: 'nauticalmiles', // any Turf unit
restrictions: ['suez', 'babelmandeb'], // block passages (see table below)
via: ['panama'], // require passages (inverse of restrictions)
allowArctic: false, // default — blocks NWP & NEP
vesselDraftMeters: 15, // auto-restrict canals
speedKnots: 22, // → properties.durationHours
appendOriginDestination: false, // prepend/append raw inputs
returnPassages: true, // populate properties.passages
maxSnapDistanceKm: 50, // SnapFailedError if exceeded
network: customMarnet, // BYO FeatureCollection
antimeridian: 'split', // 'unwrap' | 'split' dateline handling
emissions: true, // → properties.ecaKm / co2eTonnes
vesselClass: 'panamax', // CO₂e estimate class
co2eFactorKgPerKm: 225, // override the class factor
glecInflation: 0.15, // +15% distance for CO₂e (GLEC)
});
输入可以是 [lon, lat] 数组、GeoJSON Feature<Point>、裸 Point 对象,或 UN/LOCODE 字符串(例如 'CNSHA';需先导入 searoute-ts/ports)。
反子午线(国际日期变更线)处理
默认情况下,跨越 ±180° 子午线的航线(例如横滨 → 洛杉矶)会被限制在 [-180, 180] 范围内返回,许多地图渲染器会将其绘制成横跨整幅地图的直线。传入 antimeridian 可获取适用于地图的几何数据:
seaRoute(yokohama, la, { antimeridian: 'unwrap' }); // continuous LineString (may exceed ±180)
seaRoute(yokohama, la, { antimeridian: 'split' }); // MultiLineString cut at ±180 (RFC 7946)
'unwrap' 会将经度按 360° 的倍数平移,使线条不会在国际日期变更线处跳变(适用于 MapLibre/Leaflet/Deck.gl)。'split' 会在 ±180° 处切分航线,生成 MultiLineString,并确保所有坐标都在范围内。两种方式都适用于 seaRoute 和 seaRouteMulti;无论采用哪种方式,properties.length 都不会改变。
强制航线经过某条航道(via)
restrictions 会封锁一条航道;via 则会要求经过一条航道,作用正好相反。可用它来比较明确指定的航线,例如“经苏伊士运河”与“经好望角”,或强制亚洲与欧洲之间的航线经太平洋和巴拿马运河:
seaRoute('CNSHA', 'NLRTM', { via: ['suez'] }); // through Suez (the default)
seaRoute('CNSHA', 'NLRTM', { via: ['panama'] }); // across the Pacific + Panama instead
via 接受与 restrictions 相同的航道名称,并按给定顺序经过多条航道。它会通过多航段机制,沿每条航道的位置规划“起点 → 航道 → 终点”航线,因此可以与其他选项组合使用。via 中指定的航道不会被要求本身封锁(via: ['northeast'] 会经过东北航道,无需同时设置 allowArctic)。在 via 和 restrictions 中指定同一条航道会构成矛盾,并抛出 NoRouteError。
排放与 ECA/SECA 报告
设置 emissions: true,即可在 properties 中启用两项粗略估算:
import 'searoute-ts/eca'; // load the ECA/SECA zones (enables ecaKm)
import { seaRoute } from 'searoute-ts';
const r = seaRoute('CNSHA', 'NLRTM', {
emissions: true,
vesselClass: 'panamax', // → co2eTonnes
});
r.properties.ecaKm; // km of the route inside emission-control zones
r.properties.ecaFraction; // that as a fraction of route length (0–1)
r.properties.co2eTonnes; // rough CO₂e estimate for the voyage
ecaKm——航线有多少里程位于 ECA/SECA 排放控制区域(波罗的海、北海、地中海、北美和美国加勒比海地区),这会影响燃料类型和成本。为保持核心精简,这些区域数据位于searoute-ts/eca子路径导出中;导入该模块即可注册这些区域。它们是 IMO MARPOL 附则 VI 区域的边界框近似值,适用于估算,不适用于合规判定。可通过registerEcaZones替换为精度更高的多边形。co2eTonnes——使用“距离 × 船舶类别系数”得出的简化估算值,不是经认证的数据。系数根据具有代表性的燃料消耗量和 IMO HFO CO₂ 转换值透明推算得出(参见VESSEL_CLASSES);可通过co2eFactorKgPerKm覆盖。GLEC 建议将最短路径距离增加约 15 %,以反映实际偏差;请传入glecInflation: 0.15。
可限制的航道
前 12 条在 Eurostat marnet 中原生标记(与要素的 pass 属性完全匹配)。其余 4 条通过边界框检测。
| 名称 | 类型 | 备注 |
|---|---|---|
suez | 原生 | 苏伊士运河 |
panama | 原生 | 巴拿马运河 |
gibraltar | 原生 | 直布罗陀海峡 |
babelmandeb | 原生 | 曼德海峡(别名为 babalmandab) |
malacca | 原生 | 马六甲海峡 |
dover | 原生 | 多佛尔海峡 |
kiel | 原生 | 基尔运河 |
corinth | 原生 | 科林斯运河 |
bering | 原生 | 白令海峡 |
magellan | 原生 | 麦哲伦海峡 |
northwest | 原生 | 西北航道(默认封锁) |
northeast | 原生 | 东北航道(默认封锁) |
bosporus | 边界框 | 博斯普鲁斯海峡 |
ormuz | 边界框 | 霍尔木兹海峡 |
sunda | 边界框 | 巽他海峡 |
cape_horn | 边界框 | 合恩角区域 |
对于许多亚洲 ↔ 欧洲航线,西北航道和东北航道在数学上是最短路径,但一年中大部分时间都被冰封,因此默认封锁。使用 allowArctic: true 可启用。
根据行业距离数据验证
12 条真实世界航线与已发布的 Searoutes / Sea-Distances 数据相差在 ±10% 以内。
| 航线 | searoute-ts | 行业参考值 |
|---|---|---|
| 上海 → 鹿特丹(苏伊士) | 19 753 km | ~19 300 km |
| 新加坡 → 鹿特丹(苏伊士) | 15 630 km | ~15 500 km |
| 孟买 → 鹿特丹(苏伊士) | 11 918 km | ~11 800 km |
| 纽约 → 鹿特丹 | 6 227 km | ~6 200 km |
| 纽约 → 洛杉矶(巴拿马) | 9 154 km | ~9 100 km |
| 横滨 → 洛杉矶 | 9 145 km | ~8 800 km |
| 新加坡 → 洛杉矶(跨太平洋) | 14 364 km | ~14 300 km |
| 卡尔德拉(CL)→ 布兰卡港(AR) | 4 810 km | ~5 180 km |
所有检查均通过测试套件。
错误
SnapFailedError— 输入无法在maxSnapDistanceKm范围内投影到网络上。包含.side: 'origin' | 'destination'和.distanceKm: number。NoRouteError— 捕捉后的起点和终点之间不存在路径(例如,所有可用运河都被封锁)。
API 参考
import {
seaRoute, // single shortest route
seaRouteMulti, // ordered waypoints (multi-leg)
seaRouteAlternatives, // K-shortest alternatives
loadNetwork, // optional: fetch a network from a URL/CDN
CANAL_MAX_DRAFT_M, // { panama: 15.2, suez: 20.1, kiel: 7, corinth: 7.3 }
DEFAULT_MARNET, // bundled FeatureCollection<LineString>
PASSAGE_BBOXES, // passage bbox lookup
clearFinderCache, // drop the PathFinder cache (tests / hot reload)
SnapFailedError,
NoRouteError,
UnknownPortError, // thrown for unresolved UN/LOCODE strings
registerPortResolver, // plug in a custom port dataset
// types
type Passage,
type Antimeridian,
type SeaRouteOptions,
type SeaRouteFeature,
type SeaRouteMultiFeature,
type SeaRouteProperties,
type LoadNetworkOptions,
type MarnetNetwork,
type MarnetProperties,
} from 'searoute-ts';
import {
lookupPort, // UN/LOCODE → { code, name, country, coordinates }
resolvePort, // UN/LOCODE → [lon, lat]
PORTS, // the raw dataset (Record<code, PortRecord>)
PORT_COUNT,
type Port,
type PortRecord,
} from 'searoute-ts/ports';
港口代码(UN/LOCODE)
起点和终点可使用 UN/LOCODE 字符串(例如 'CNSHA')而非坐标指定。港口数据集通过 searoute-ts/ports 子路径导出提供,因此只有在使用时才会产生相应开销——导入该子路径(无论使用其任一导出,还是仅利用其副作用)都会向核心注册解析器,因此 seaRoute('CNSHA', 'NLRTM') 可以正常工作。
- 约 1 600 个海港,以 UN/LOCODE 为键(包含主代码和别名)。
- 来源:marchah/sea-ports(MIT),其数据本身源自 UN/LOCODE。使用
scripts/build-ports.cjs重新生成。 - 坐标为近似值(精度为港口所在城市)——路由引擎无论如何都会将其捕捉到网络上,因此对于距离计算和可视化而言足够准确。
- 未知或格式错误的代码会抛出
UnknownPortError。
在 AI Agent 中使用(MCP)
配套的 Model Context Protocol 服务,
@searoute-ts/mcp(源代码),
可让 AI Agent(Claude Desktop、claude CLI 等)计算真实海上航线,而不是靠猜测——询问“从上海到鹿特丹的海上距离是多少,且避开苏伊士运河?”时,它会直接调用该库。它提供两个工具:sea_route 和 sea_route_alternatives,并接受港口代码('CNSHA')或坐标。
claude mcp add searoute -- npx -y @searoute-ts/mcp
也可以将其添加到任意 MCP 客户端配置中:
{
"mcpServers": {
"searoute": {
"command": "npx",
"args": ["-y", "@searoute-ts/mcp"]
}
}
}
完整的工具参考请参阅服务的 README。
对于铁路路段,可同时添加
@railroute-ts/mcp
(claude mcp add railroute -- npx -y @railroute-ts/mcp)。
多式联运:添加铁路路段(railroute-ts)
海上距离很少能代表整段运输。姊妹库
railroute-ts 可在
OpenStreetMap 铁路网络上规划路线(内置欧洲网络、API 形式相同、GeoJSON
输出相同),因此只需再调用一次,即可获取港口到内陆的报价,或生成类似 GLEC/CountEmissions 的报告:
import 'searoute-ts/ports';
import { seaRoute } from 'searoute-ts';
import { railRoute } from 'railroute-ts';
import { EUROPE_NETWORK } from 'railroute-ts/networks/europe';
const sea = seaRoute('CNSHA', 'NLRTM', { units: 'kilometers', emissions: true, vesselClass: 'panamax' });
const rail = railRoute([4.47, 51.92], [8.92, 44.41], { network: EUROPE_NETWORK, speedKmh: 60 }); // Rotterdam → Genoa
sea.properties.length; // ≈ 19,753 km Shanghai → Rotterdam via Suez
sea.properties.co2eTonnes; // ≈ 4448 t CO₂e (rough, see Emissions above)
rail.properties.length; // ≈ 1,180 km Rotterdam → Genoa via the Gotthard base tunnel
rail.properties.gaugeChanges; // 0 — standard gauge all the way
npm install railroute-ts — 文档和交互式演示。
这两个库都提供 MCP 服务,因此 AI Agent 可以依次调用 sea_route →
rail_route,计算门到门距离(见下文)。
工作原理
图数据、吸附、Dijkstra、限制、反经线修复、吃水逻辑和备选路线的两页深入介绍,请参阅 DOCS.md。
常见问题
此工具可用于导航吗? 不可以。这些路线是适用于可视化以及粗略距离/时长估算的网络路径,不能用于驾驶船舶。
支持天气航线规划吗? 不支持。有关天气感知航线规划,请参阅 VISIR-2。
为什么我的亚洲→欧洲航线会经过白令海峡? 默认情况下不会——西北航道和东北航道处于封锁状态。传入
allowArctic: true 即可启用。
可以使用自己的网络吗? 可以——seaRoute(origin, destination, { network })。
适用于内陆水道或基于 AIS 构建的自定义图。有关更高分辨率的 Eurostat 数据(5/10/20/50 km),请参阅
更高分辨率网络——20 km 和
50 km 版本以子路径导出的形式提供。
它能处理红海/苏伊士危机吗? 可以——传入
restrictions: ['suez', 'babelmandeb'],即可强制航线绕行好望角。
在 1.x 上出现 Cannot find module '…/searoute-ts/dist/lib/utils'? 1.x(截至
1.2.1)在 "main" 下提供了带无扩展名导入的 ESM 构建,因此未经修补的
Node 无法加载。此问题已在 2.0 中修复:请安装 searoute-ts@^2,
因为 ^1 范围不会安装此版本。升级时,请使用具名导入
import { seaRoute }。现在,失败时会抛出 NoRouteError / SnapFailedError,
而不是返回 null;海里长度也缩短了约 24%,因为 1.x 的计算值偏大。请参阅
CHANGELOG 中的 2.0.0 迁移说明。
跨越反经线时的大圆距离正确吗? 正确——marnet 已经过标准化,使太平洋成为连通图,且所有距离在内部都使用 haversine 计算。
包体积有多大? 运行时导入的内容很小:核心代码加上内置的 100 km marnet(约 1.1 MB JSON,仅作为共享的
dist/data/marnet.cjs 资源随包发布一次,由两种构建共同加载,而不是分别内嵌到每种构建中)。
它支持 Tree-shaking,因此只有在导入可选的 searoute-ts/marnet-20km / marnet-50km
网络时才会加载。不过,这些网络确实会增加 npm 压缩包的大小——包含它们时,包的压缩大小约为 1.1 MB/解压后约为 7 MB(每个变体都是单个共享资源,不会在每种构建中重复)。如果需要更精细的网络但又不想增加安装体积,可以自行生成并托管它们,然后改用 loadNetwork。
致谢
- 海上航线网络 — Eurostat searoute v3.5 (EUPL-1.2)。Oak Ridge 国家实验室全球航运航线网络,并结合欧洲 AIS 数据进行增强。
- Dijkstra — Per Liedman 开发的
geojson-path-finder@2。 - 灵感来源于
searoute-py(Apache-2.0)。 - 原始 JS 移植版 — @johnx25bd。
- 地理空间基本工具 — Turf.js。
许可证
MIT © Mayur Rawte
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。