osmgl 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/osmgl.d.cts CHANGED
@@ -688,6 +688,24 @@ declare class Shader {
688
688
  * Стиль хранится в `styles/*.json` и целиком вшивается в бандл — карта должна
689
689
  * рисоваться без единого сетевого запроса за конфигом.
690
690
  */
691
+ /**
692
+ * Цвет, ВЫВЕДЕННЫЙ ИЗ ЦВЕТА ДРУГОГО СЛОЯ: «как у него, только темнее».
693
+ *
694
+ * Нужен обводке моста. Собственный цвет ей задать нельзя: тем два десятка, каждая красит дороги
695
+ * по-своему, и любой фиксированный хекс на половине из них смотрелся бы чужим. Полупрозрачная
696
+ * затемняющая краска эту задачу решала, но полупрозрачной линии нельзя: капсулы соседних отрезков
697
+ * перекрываются на изломах, и краска ложится дважды — по вершинам идёт цепочка тёмных бусин.
698
+ * (Трафарет «красить пиксель один раз» бусины убирает, но взамен оставляет светлый шов по
699
+ * сглаженному краю первой капсулы — проверено.)
700
+ *
701
+ * Ссылка снимает вопрос: тема красит обводку дороги, а обводка моста едет следом сама.
702
+ */
703
+ interface ColorFrom {
704
+ /** Идентификатор слоя, у которого берём цвет. */
705
+ from: string;
706
+ /** Насколько затемнить, 0..1 (0.25 — четверть). */
707
+ darken?: number;
708
+ }
691
709
  /** Значение, зависящее от зума: число/цвет либо остановки для интерполяции. */
692
710
  type Interpolated<T> = T | {
693
711
  stops: [number, T][];
@@ -827,13 +845,41 @@ interface FillLayerSpec extends LayerBase {
827
845
  }
828
846
  interface LineLayerSpec extends LayerBase {
829
847
  type: 'line';
848
+ /**
849
+ * СЕТЬ, внутри которой порядок отрисовки решают не слои, а уровни пересечения.
850
+ *
851
+ * Все дорожные слои стиля — обводки, полотна, тень моста — помечаются одним именем (`roads`), и
852
+ * рисуются они не подряд, а по уровням: сначала вся сеть уровня −1 (тоннели), потом вся сеть
853
+ * земли, потом вся сеть эстакад. Поэтому мост со своей тенью и обводкой ложится ЦЕЛИКОМ поверх
854
+ * улицы под ним, какого бы класса та ни была, — а не «полотно моста поверх, обводка под».
855
+ *
856
+ * Так же устроено у Яндекса: у каждого дорожного слоя `line-network: "roads"` и
857
+ * `line-z-level: ["get","z_level"]`. Уровень фичи считается по `generators/level`.
858
+ *
859
+ * Сеть рисуется целиком НА МЕСТЕ ПЕРВОГО своего слоя в стиле; порядок внутри уровня — обычный,
860
+ * по порядку слоёв.
861
+ */
862
+ network?: string;
830
863
  paint: MaterialPaint & {
831
- color: Interpolated<string>;
864
+ /** Цвет линии; `{ from, darken }` — «как у такого-то слоя, только темнее» (см. `ColorFrom`). */
865
+ color: Interpolated<string> | ColorFrom;
832
866
  /** Ширина в ЭКРАННЫХ пикселях: линия не толстеет с приближением к камере. */
833
867
  width: Interpolated<number>;
834
868
  opacity?: Interpolated<number>;
835
869
  /** Сдвиг поперёк линии в пикселях — для обочин и параллельных путей. */
836
870
  offset?: Interpolated<number>;
871
+ /**
872
+ * РАЗМЫТИЕ КРАЯ в пикселях: край растягивается на столько вместо обычного полупикселя.
873
+ *
874
+ * Нужно тени моста. У Яндекса тени нет вовсе как отдельной сущности — там на каждый мост
875
+ * рисуется ВОСЕМЬ вложенных контуров (`road-sd-shadow-1…8__bridge`), каждый с прозрачностью
876
+ * 0.03–0.08, и их сумма изображает размытие. Это обход отсутствующего в их движке размытия:
877
+ * восемь слоёв в стиле и восемь вызовов отрисовки на тайл ради градиента.
878
+ *
879
+ * У нас край линии и так вырезает фрагментный шейдер по расстоянию до оси — растянуть переход
880
+ * стоит одного юниформа. Поэтому тень моста здесь ОДИН слой с честным мягким краем.
881
+ */
882
+ blur?: Interpolated<number>;
837
883
  /**
838
884
  * Уровень полотна в МЕТРАХ — для рельефных вариантов карты: дорожка внутри
839
885
  * приподнятого парка должна лежать на нём, а не тонуть под ним. Меняется
@@ -1140,6 +1186,14 @@ interface SurfaceLayerSpec extends LayerBase {
1140
1186
  /** Ширина фаски по горизонтали, метры. 0 — резкий край. */
1141
1187
  bevel?: number;
1142
1188
  /** На сколько фаска опускается, метры. */
1189
+ /**
1190
+ * Насколько широкую щель между кусками СЛИТЬ, метры. По умолчанию — общее значение движка.
1191
+ *
1192
+ * Ноль нужен слоям, куски которых обязаны остаться порознь. Первый такой — зебра перехода: она
1193
+ * набрана отдельными полосами с промежутками около метра, и общая сварка слепила её в сплошную
1194
+ * белую плиту.
1195
+ */
1196
+ weld?: number;
1143
1197
  bevelDrop?: number;
1144
1198
  paint: MaterialPaint & {
1145
1199
  color: Interpolated<string>;
@@ -1341,6 +1395,13 @@ interface LayerPlan {
1341
1395
  maxzoom: number;
1342
1396
  /** Разбить слой на меши по значению свойства (этажи — см. `LayerBase.splitBy`). */
1343
1397
  splitBy?: string;
1398
+ /**
1399
+ * Слой входит в СЕТЬ (`LineLayerSpec.network`): меш бьётся по уровням пересечения.
1400
+ *
1401
+ * Воркеру важно не имя сети, а сам факт: по уровню он раскладывает геометрию, а порядок
1402
+ * расставляет уже рендер.
1403
+ */
1404
+ network?: string;
1344
1405
  /** Скругление углов в метрах — геометрия, поэтому едет в воркер. */
1345
1406
  cornerRadius?: number;
1346
1407
  cornerSegments?: number;
@@ -1350,6 +1411,7 @@ interface LayerPlan {
1350
1411
  elevation?: number;
1351
1412
  base?: number;
1352
1413
  bevel?: number;
1414
+ weld?: number;
1353
1415
  bevelDrop?: number;
1354
1416
  /**
1355
1417
  * Линия ложится НА ПОВЕРХНОСТЬ, по которой идёт (см. `generators/ground`).
@@ -1607,6 +1669,14 @@ interface LoadedResponse {
1607
1669
  * этажи вообще есть в этом здании.
1608
1670
  */
1609
1671
  splits?: Record<string, (string | number)[]>;
1672
+ /**
1673
+ * Уровни пересечения, встретившиеся в этом тайле (см. `generators/level`), по возрастанию.
1674
+ *
1675
+ * Дорожная сеть рисуется НЕ по слоям, а по уровням: сначала всё, что под землёй, потом земля,
1676
+ * потом эстакады. Какие уровни в тайле есть, знает только тот, кто его разобрал, — рендеру
1677
+ * перебирать все возможные значения было бы дороже, чем передать список.
1678
+ */
1679
+ levels?: number[];
1610
1680
  timing: {
1611
1681
  fetchMs: number;
1612
1682
  parseMs: number;
@@ -3706,6 +3776,18 @@ declare class LayerRenderer {
3706
3776
  private applyMaterial;
3707
3777
  private drawFill;
3708
3778
  private drawLine;
3779
+ /**
3780
+ * СЕТЬ ЦЕЛИКОМ, по уровням пересечения (см. `LineLayerSpec.network`).
3781
+ *
3782
+ * Обычный слой рисуется на своём месте в стиле. Сеть так рисовать нельзя: обводка эстакады
3783
+ * должна лежать поверх ПОЛОТНА улицы под ней, а полотно улицы в стиле идёт позже обводок.
3784
+ * Поэтому вся сеть рисуется одним куском на месте своего первого слоя, и снаружи внутрь порядок
3785
+ * такой: уровень (тоннели → земля → эстакады), а внутри уровня — обычный порядок слоёв.
3786
+ *
3787
+ * Какие уровни в кадре есть, считаем по видимым тайлам: в обычном городе это один нулевой, и
3788
+ * тогда всё сводится к прежней отрисовке слой за слоем.
3789
+ */
3790
+ private drawNetwork;
3709
3791
  /**
3710
3792
  * Подсветка выбранного здания.
3711
3793
  *
@@ -4351,6 +4433,19 @@ interface RoundOptions {
4351
4433
  * получилась бы ступенька.
4352
4434
  */
4353
4435
  extent?: number;
4436
+ /**
4437
+ * Насколько дальше квадрата тайла проходит НАСТОЯЩИЙ разрез, единицы тайла.
4438
+ *
4439
+ * Замораживать надо ровно линию разреза, а не квадрат. Пока поверхности резались по квадрату,
4440
+ * это было одно и то же, но теперь они режутся с запасом (`cutMargin`), и геометрия законно живёт
4441
+ * за квадратом. Со старым определением одна и та же вершина у левого тайла оказывалась «за
4442
+ * границей» и не скруглялась, а у правого — внутри и срезалась: контуры расходились, и вдоль
4443
+ * стыка появлялся вырезанный уступ. Замечено на клине газона в центре Душанбе — обе соседние
4444
+ * зелёные области были срезаны по одной вертикали, ровно по границе тайла.
4445
+ *
4446
+ * Ноль — прежнее поведение: разрез идёт по квадрату (так режут здания и заливки).
4447
+ */
4448
+ margin?: number;
4354
4449
  /**
4355
4450
  * Вершины, которые скруглять НЕЛЬЗЯ (по индексу в кольце без замыкающей
4356
4451
  * точки). Ими помечают углы на общем ребре с соседним полигоном: скругление
@@ -4700,9 +4795,47 @@ interface LineMesh {
4700
4795
  vertexCount: number;
4701
4796
  indexCount: number;
4702
4797
  }
4798
+ interface LineOptions {
4799
+ /**
4800
+ * Уровень пересечения (см. `generators/level`): берём только фичи этого уровня.
4801
+ *
4802
+ * `undefined` — уровни не разделяем, слой строится целиком (так живут все слои, кроме дорожной
4803
+ * сети: у реки или границы пересечений без связи не бывает).
4804
+ */
4805
+ level?: number;
4806
+ }
4703
4807
  declare function generateLine(layer: VectorTileLayer, filter: Filter | undefined, maxSegment?: number,
4704
4808
  /** Уровни поверхностей тайла: по ним дорога ложится на то, по чему идёт. Нет — лежит на нуле. */
4705
- ground?: GroundField): LineMesh | null;
4809
+ ground?: GroundField,
4810
+ /** Метров в единице тайла. Ноль — плавный переход ширины на стыках не строится. */
4811
+ metersPerUnit?: number, opts?: LineOptions): LineMesh | null;
4812
+
4813
+ /**
4814
+ * УРОВЕНЬ ПЕРЕСЕЧЕНИЯ — какой из двух дорог быть сверху там, где они пересекаются без связи.
4815
+ *
4816
+ * ЗАЧЕМ. Плоская карта рисуется краской: слои идут в порядке стиля, и внутри слоя порядок фич
4817
+ * произволен. Поэтому эстакада над улицей ничем не отличалась от перекрёстка — обводки сливались,
4818
+ * полотна пересекались, и место читалось как съезд, которого в жизни нет. Ровно этим у Яндекса
4819
+ * занят `line-z-level` (`["get","z_level"]` у КАЖДОГО дорожного слоя, все они в одной сети
4820
+ * `line-network: "roads"`): сеть рисуется не по слоям, а по уровням, и мост со своей тенью и
4821
+ * обводкой целиком ложится поверх того, что под ним.
4822
+ *
4823
+ * ОТКУДА ЧИСЛО. Готового `z_level` в наших тайлах нет, зато есть то, из чего его считают:
4824
+ * `layer` — тег OSM, честный уровень (−1 подземный, 1 над землёй, изредка 2…5);
4825
+ * `brunnel` — «мост / тоннель / брод», он приходит и там, где `layer` не проставлен.
4826
+ * Поэтому берём `layer`, а если его нет — выводим уровень из `brunnel`. Мост без `layer`
4827
+ * (в Душанбе таких большинство) получает 1, тоннель — −1, обычная улица — 0.
4828
+ *
4829
+ * Считается в ВОРКЕРЕ, при тесселяции: по уровню бьётся меш, и рендеру остаётся только порядок.
4830
+ */
4831
+ /**
4832
+ * Дальше этого уровни не разводим. В OSM попадается и `layer=5`, и опечатки в сотни: каждое
4833
+ * значение — это отдельный бакет и отдельный вызов отрисовки, поэтому хвост подрезаем. Пять этажей
4834
+ * развязки — больше, чем бывает на настоящих.
4835
+ */
4836
+ declare const LEVEL_LIMIT = 5;
4837
+ /** Уровень фичи: `layer` из тегов, иначе вывод из `brunnel`. */
4838
+ declare function featureLevel(props: Record<string, unknown>): number;
4706
4839
 
4707
4840
  /**
4708
4841
  * Положение камеры в адресе страницы.
@@ -4802,6 +4935,8 @@ interface SurfaceOptions {
4802
4935
  /** Ширина фаски по горизонтали, метры. 0 — резкий край. */
4803
4936
  bevel?: number;
4804
4937
  /** Насколько фаска опускается по высоте, метры. */
4938
+ /** Насколько широкую щель между кусками слить, метры. Пусто — SURFACE_WELD_METERS. */
4939
+ weld?: number;
4805
4940
  bevelDrop?: number;
4806
4941
  /** Скругление углов в плане, метры. */
4807
4942
  cornerRadius?: number;
@@ -5656,4 +5791,4 @@ declare class Map$1 extends Evented<MapEvents> {
5656
5791
  destroy(): void;
5657
5792
  }
5658
5793
 
5659
- export { type AnimationOptions, AssetLoader, type AssetLoaderOptions, BASE_SOURCE, BUILDING_HEIGHT_SCALE, BUILDING_VERTEX_STRIDE, type BuildingHit, type BuildingsMesh, CITY_STYLE, type CameraOptions, Circle, type CircleOptions, type CoverOptions, DEFAULT_ICONS, DEFAULT_LIGHT, DEFAULT_SHADOWS, DEFAULT_SKY, DEFAULT_STYLE, DepthTarget, type DeviceHints, EARTH_CIRCUMFERENCE, FILL_VERTEX_STRIDE, type Filter, type FitBoundsOptions, type FitViewport, type FogPlanes, GLOBE_MAX_PITCH, GLOBE_ZOOM_MAX, GLOBE_ZOOM_MIN, GLYPH_BORDER, GLYPH_SIZE, GROUND_SCALE, GeomType, type GestureOptions, type Glyph, type GlyphMetric, GlyphSource, GroundArrows, IconSource, IndoorMask, type Interpolated, LINE_VERTEX_STRIDE, type LayerPlan, LayerRenderer, type LightSpec, type LinePlacement, type LngLat, LngLatBounds, type LngLatLike, MAX_LATITUDE, MODEL_VERTEX_STRIDE, Map$1 as Map, type MapEvents, MapObject, type MapObjectOptions, type MapOptions, Marker, type MarkerOptions, Model, ModelLayer, type ModelMesh, type ModelOptions, type ModelPrimitive, ObjectManager, type ObjectPaint, type ObjectPart, type Padding, type PlacedGlyph, type PlacedSymbol, Polygon, type PolygonOptions, Polyline, type PolylineOptions, type PolylineSegment, Popup, type PopupOptions, type Projection, type QualityName, type QualityProfile, RELIEF_STYLE, RUNTIME_FILL_STRIDE, RUNTIME_LINE_STRIDE, RasterSource, type RasterSourceOptions, RasterTile, type RoundOptions, type RuntimeMesh, SDF_EDGE, SDF_PX, SOFT_STYLE, SPLIT_SEP, SURFACE_CUT_BLEED, SURFACE_LEVEL_SCALE, SURFACE_VERTEX_STRIDE, type ScreenPoint$1 as ScreenPoint, SdfAtlas, type ShadowSettings, type SkySpec, Style, type StyleLayerSpec, type StyleSpec, type SymbolHit, SymbolRenderer, THEMES, TILE_SIZE, type ThemeSpec, TileID, Transform, VectorTile, VectorTileFeature, VectorTileLayer, abbreviateStreet, addGround, altitudeFromMercatorZ, applyTheme, arrowLabelOffset, arrowVertices, buildRuntimeFill, buildRuntimeLine, cameraForBounds, circumferenceAtLatitude, clampLat, clampPixelRatio, clipLineToRect, coordinateDigits, coveringTiles, createGround, Map$1 as default, deviceHints, distToSegment, evaluateColor, evaluateNumber, extractFeature, fillFootprint, fogPlanes, footprintOf, formatHash, generateBuildings, generateFill, generateLine, generateSurface, generateSymbols, globeBasis, globeFlatMix, globeRadius, globeToLocal, groundAt, iconRotation, insideFootprint, latFromMercatorY, lngFromMercatorX, lngLatToUnit, matchesFilter, mercatorMetersPerTile, mercatorX, mercatorY, mercatorZFromAltitude, metersPerPixel, metersPerTile, nextQualityDown, parseGlb, parseGlbAsync, parseGlyphs, parseHash, patchUV, pickBuilding, pickFill, pitchIntent, pixelsPerMeter, placeAlongLine, pointInRing, qualityFor, qualityProfile, raySphere, resolveTemplate, roundRing, sdfFromAlpha, shapeText, splitBucketKey, splitByGround, splitPolygons, styleWithTheme, tileOriginMeters, tileUrl, toLngLat, unitToLngLat, worldSize };
5794
+ export { type AnimationOptions, AssetLoader, type AssetLoaderOptions, BASE_SOURCE, BUILDING_HEIGHT_SCALE, BUILDING_VERTEX_STRIDE, type BuildingHit, type BuildingsMesh, CITY_STYLE, type CameraOptions, Circle, type CircleOptions, type CoverOptions, DEFAULT_ICONS, DEFAULT_LIGHT, DEFAULT_SHADOWS, DEFAULT_SKY, DEFAULT_STYLE, DepthTarget, type DeviceHints, EARTH_CIRCUMFERENCE, FILL_VERTEX_STRIDE, type Filter, type FitBoundsOptions, type FitViewport, type FogPlanes, GLOBE_MAX_PITCH, GLOBE_ZOOM_MAX, GLOBE_ZOOM_MIN, GLYPH_BORDER, GLYPH_SIZE, GROUND_SCALE, GeomType, type GestureOptions, type Glyph, type GlyphMetric, GlyphSource, GroundArrows, IconSource, IndoorMask, type Interpolated, LEVEL_LIMIT, LINE_VERTEX_STRIDE, type LayerPlan, LayerRenderer, type LightSpec, type LinePlacement, type LngLat, LngLatBounds, type LngLatLike, MAX_LATITUDE, MODEL_VERTEX_STRIDE, Map$1 as Map, type MapEvents, MapObject, type MapObjectOptions, type MapOptions, Marker, type MarkerOptions, Model, ModelLayer, type ModelMesh, type ModelOptions, type ModelPrimitive, ObjectManager, type ObjectPaint, type ObjectPart, type Padding, type PlacedGlyph, type PlacedSymbol, Polygon, type PolygonOptions, Polyline, type PolylineOptions, type PolylineSegment, Popup, type PopupOptions, type Projection, type QualityName, type QualityProfile, RELIEF_STYLE, RUNTIME_FILL_STRIDE, RUNTIME_LINE_STRIDE, RasterSource, type RasterSourceOptions, RasterTile, type RoundOptions, type RuntimeMesh, SDF_EDGE, SDF_PX, SOFT_STYLE, SPLIT_SEP, SURFACE_CUT_BLEED, SURFACE_LEVEL_SCALE, SURFACE_VERTEX_STRIDE, type ScreenPoint$1 as ScreenPoint, SdfAtlas, type ShadowSettings, type SkySpec, Style, type StyleLayerSpec, type StyleSpec, type SymbolHit, SymbolRenderer, THEMES, TILE_SIZE, type ThemeSpec, TileID, Transform, VectorTile, VectorTileFeature, VectorTileLayer, abbreviateStreet, addGround, altitudeFromMercatorZ, applyTheme, arrowLabelOffset, arrowVertices, buildRuntimeFill, buildRuntimeLine, cameraForBounds, circumferenceAtLatitude, clampLat, clampPixelRatio, clipLineToRect, coordinateDigits, coveringTiles, createGround, Map$1 as default, deviceHints, distToSegment, evaluateColor, evaluateNumber, extractFeature, featureLevel, fillFootprint, fogPlanes, footprintOf, formatHash, generateBuildings, generateFill, generateLine, generateSurface, generateSymbols, globeBasis, globeFlatMix, globeRadius, globeToLocal, groundAt, iconRotation, insideFootprint, latFromMercatorY, lngFromMercatorX, lngLatToUnit, matchesFilter, mercatorMetersPerTile, mercatorX, mercatorY, mercatorZFromAltitude, metersPerPixel, metersPerTile, nextQualityDown, parseGlb, parseGlbAsync, parseGlyphs, parseHash, patchUV, pickBuilding, pickFill, pitchIntent, pixelsPerMeter, placeAlongLine, pointInRing, qualityFor, qualityProfile, raySphere, resolveTemplate, roundRing, sdfFromAlpha, shapeText, splitBucketKey, splitByGround, splitPolygons, styleWithTheme, tileOriginMeters, tileUrl, toLngLat, unitToLngLat, worldSize };
package/dist/osmgl.d.ts CHANGED
@@ -688,6 +688,24 @@ declare class Shader {
688
688
  * Стиль хранится в `styles/*.json` и целиком вшивается в бандл — карта должна
689
689
  * рисоваться без единого сетевого запроса за конфигом.
690
690
  */
691
+ /**
692
+ * Цвет, ВЫВЕДЕННЫЙ ИЗ ЦВЕТА ДРУГОГО СЛОЯ: «как у него, только темнее».
693
+ *
694
+ * Нужен обводке моста. Собственный цвет ей задать нельзя: тем два десятка, каждая красит дороги
695
+ * по-своему, и любой фиксированный хекс на половине из них смотрелся бы чужим. Полупрозрачная
696
+ * затемняющая краска эту задачу решала, но полупрозрачной линии нельзя: капсулы соседних отрезков
697
+ * перекрываются на изломах, и краска ложится дважды — по вершинам идёт цепочка тёмных бусин.
698
+ * (Трафарет «красить пиксель один раз» бусины убирает, но взамен оставляет светлый шов по
699
+ * сглаженному краю первой капсулы — проверено.)
700
+ *
701
+ * Ссылка снимает вопрос: тема красит обводку дороги, а обводка моста едет следом сама.
702
+ */
703
+ interface ColorFrom {
704
+ /** Идентификатор слоя, у которого берём цвет. */
705
+ from: string;
706
+ /** Насколько затемнить, 0..1 (0.25 — четверть). */
707
+ darken?: number;
708
+ }
691
709
  /** Значение, зависящее от зума: число/цвет либо остановки для интерполяции. */
692
710
  type Interpolated<T> = T | {
693
711
  stops: [number, T][];
@@ -827,13 +845,41 @@ interface FillLayerSpec extends LayerBase {
827
845
  }
828
846
  interface LineLayerSpec extends LayerBase {
829
847
  type: 'line';
848
+ /**
849
+ * СЕТЬ, внутри которой порядок отрисовки решают не слои, а уровни пересечения.
850
+ *
851
+ * Все дорожные слои стиля — обводки, полотна, тень моста — помечаются одним именем (`roads`), и
852
+ * рисуются они не подряд, а по уровням: сначала вся сеть уровня −1 (тоннели), потом вся сеть
853
+ * земли, потом вся сеть эстакад. Поэтому мост со своей тенью и обводкой ложится ЦЕЛИКОМ поверх
854
+ * улицы под ним, какого бы класса та ни была, — а не «полотно моста поверх, обводка под».
855
+ *
856
+ * Так же устроено у Яндекса: у каждого дорожного слоя `line-network: "roads"` и
857
+ * `line-z-level: ["get","z_level"]`. Уровень фичи считается по `generators/level`.
858
+ *
859
+ * Сеть рисуется целиком НА МЕСТЕ ПЕРВОГО своего слоя в стиле; порядок внутри уровня — обычный,
860
+ * по порядку слоёв.
861
+ */
862
+ network?: string;
830
863
  paint: MaterialPaint & {
831
- color: Interpolated<string>;
864
+ /** Цвет линии; `{ from, darken }` — «как у такого-то слоя, только темнее» (см. `ColorFrom`). */
865
+ color: Interpolated<string> | ColorFrom;
832
866
  /** Ширина в ЭКРАННЫХ пикселях: линия не толстеет с приближением к камере. */
833
867
  width: Interpolated<number>;
834
868
  opacity?: Interpolated<number>;
835
869
  /** Сдвиг поперёк линии в пикселях — для обочин и параллельных путей. */
836
870
  offset?: Interpolated<number>;
871
+ /**
872
+ * РАЗМЫТИЕ КРАЯ в пикселях: край растягивается на столько вместо обычного полупикселя.
873
+ *
874
+ * Нужно тени моста. У Яндекса тени нет вовсе как отдельной сущности — там на каждый мост
875
+ * рисуется ВОСЕМЬ вложенных контуров (`road-sd-shadow-1…8__bridge`), каждый с прозрачностью
876
+ * 0.03–0.08, и их сумма изображает размытие. Это обход отсутствующего в их движке размытия:
877
+ * восемь слоёв в стиле и восемь вызовов отрисовки на тайл ради градиента.
878
+ *
879
+ * У нас край линии и так вырезает фрагментный шейдер по расстоянию до оси — растянуть переход
880
+ * стоит одного юниформа. Поэтому тень моста здесь ОДИН слой с честным мягким краем.
881
+ */
882
+ blur?: Interpolated<number>;
837
883
  /**
838
884
  * Уровень полотна в МЕТРАХ — для рельефных вариантов карты: дорожка внутри
839
885
  * приподнятого парка должна лежать на нём, а не тонуть под ним. Меняется
@@ -1140,6 +1186,14 @@ interface SurfaceLayerSpec extends LayerBase {
1140
1186
  /** Ширина фаски по горизонтали, метры. 0 — резкий край. */
1141
1187
  bevel?: number;
1142
1188
  /** На сколько фаска опускается, метры. */
1189
+ /**
1190
+ * Насколько широкую щель между кусками СЛИТЬ, метры. По умолчанию — общее значение движка.
1191
+ *
1192
+ * Ноль нужен слоям, куски которых обязаны остаться порознь. Первый такой — зебра перехода: она
1193
+ * набрана отдельными полосами с промежутками около метра, и общая сварка слепила её в сплошную
1194
+ * белую плиту.
1195
+ */
1196
+ weld?: number;
1143
1197
  bevelDrop?: number;
1144
1198
  paint: MaterialPaint & {
1145
1199
  color: Interpolated<string>;
@@ -1341,6 +1395,13 @@ interface LayerPlan {
1341
1395
  maxzoom: number;
1342
1396
  /** Разбить слой на меши по значению свойства (этажи — см. `LayerBase.splitBy`). */
1343
1397
  splitBy?: string;
1398
+ /**
1399
+ * Слой входит в СЕТЬ (`LineLayerSpec.network`): меш бьётся по уровням пересечения.
1400
+ *
1401
+ * Воркеру важно не имя сети, а сам факт: по уровню он раскладывает геометрию, а порядок
1402
+ * расставляет уже рендер.
1403
+ */
1404
+ network?: string;
1344
1405
  /** Скругление углов в метрах — геометрия, поэтому едет в воркер. */
1345
1406
  cornerRadius?: number;
1346
1407
  cornerSegments?: number;
@@ -1350,6 +1411,7 @@ interface LayerPlan {
1350
1411
  elevation?: number;
1351
1412
  base?: number;
1352
1413
  bevel?: number;
1414
+ weld?: number;
1353
1415
  bevelDrop?: number;
1354
1416
  /**
1355
1417
  * Линия ложится НА ПОВЕРХНОСТЬ, по которой идёт (см. `generators/ground`).
@@ -1607,6 +1669,14 @@ interface LoadedResponse {
1607
1669
  * этажи вообще есть в этом здании.
1608
1670
  */
1609
1671
  splits?: Record<string, (string | number)[]>;
1672
+ /**
1673
+ * Уровни пересечения, встретившиеся в этом тайле (см. `generators/level`), по возрастанию.
1674
+ *
1675
+ * Дорожная сеть рисуется НЕ по слоям, а по уровням: сначала всё, что под землёй, потом земля,
1676
+ * потом эстакады. Какие уровни в тайле есть, знает только тот, кто его разобрал, — рендеру
1677
+ * перебирать все возможные значения было бы дороже, чем передать список.
1678
+ */
1679
+ levels?: number[];
1610
1680
  timing: {
1611
1681
  fetchMs: number;
1612
1682
  parseMs: number;
@@ -3706,6 +3776,18 @@ declare class LayerRenderer {
3706
3776
  private applyMaterial;
3707
3777
  private drawFill;
3708
3778
  private drawLine;
3779
+ /**
3780
+ * СЕТЬ ЦЕЛИКОМ, по уровням пересечения (см. `LineLayerSpec.network`).
3781
+ *
3782
+ * Обычный слой рисуется на своём месте в стиле. Сеть так рисовать нельзя: обводка эстакады
3783
+ * должна лежать поверх ПОЛОТНА улицы под ней, а полотно улицы в стиле идёт позже обводок.
3784
+ * Поэтому вся сеть рисуется одним куском на месте своего первого слоя, и снаружи внутрь порядок
3785
+ * такой: уровень (тоннели → земля → эстакады), а внутри уровня — обычный порядок слоёв.
3786
+ *
3787
+ * Какие уровни в кадре есть, считаем по видимым тайлам: в обычном городе это один нулевой, и
3788
+ * тогда всё сводится к прежней отрисовке слой за слоем.
3789
+ */
3790
+ private drawNetwork;
3709
3791
  /**
3710
3792
  * Подсветка выбранного здания.
3711
3793
  *
@@ -4351,6 +4433,19 @@ interface RoundOptions {
4351
4433
  * получилась бы ступенька.
4352
4434
  */
4353
4435
  extent?: number;
4436
+ /**
4437
+ * Насколько дальше квадрата тайла проходит НАСТОЯЩИЙ разрез, единицы тайла.
4438
+ *
4439
+ * Замораживать надо ровно линию разреза, а не квадрат. Пока поверхности резались по квадрату,
4440
+ * это было одно и то же, но теперь они режутся с запасом (`cutMargin`), и геометрия законно живёт
4441
+ * за квадратом. Со старым определением одна и та же вершина у левого тайла оказывалась «за
4442
+ * границей» и не скруглялась, а у правого — внутри и срезалась: контуры расходились, и вдоль
4443
+ * стыка появлялся вырезанный уступ. Замечено на клине газона в центре Душанбе — обе соседние
4444
+ * зелёные области были срезаны по одной вертикали, ровно по границе тайла.
4445
+ *
4446
+ * Ноль — прежнее поведение: разрез идёт по квадрату (так режут здания и заливки).
4447
+ */
4448
+ margin?: number;
4354
4449
  /**
4355
4450
  * Вершины, которые скруглять НЕЛЬЗЯ (по индексу в кольце без замыкающей
4356
4451
  * точки). Ими помечают углы на общем ребре с соседним полигоном: скругление
@@ -4700,9 +4795,47 @@ interface LineMesh {
4700
4795
  vertexCount: number;
4701
4796
  indexCount: number;
4702
4797
  }
4798
+ interface LineOptions {
4799
+ /**
4800
+ * Уровень пересечения (см. `generators/level`): берём только фичи этого уровня.
4801
+ *
4802
+ * `undefined` — уровни не разделяем, слой строится целиком (так живут все слои, кроме дорожной
4803
+ * сети: у реки или границы пересечений без связи не бывает).
4804
+ */
4805
+ level?: number;
4806
+ }
4703
4807
  declare function generateLine(layer: VectorTileLayer, filter: Filter | undefined, maxSegment?: number,
4704
4808
  /** Уровни поверхностей тайла: по ним дорога ложится на то, по чему идёт. Нет — лежит на нуле. */
4705
- ground?: GroundField): LineMesh | null;
4809
+ ground?: GroundField,
4810
+ /** Метров в единице тайла. Ноль — плавный переход ширины на стыках не строится. */
4811
+ metersPerUnit?: number, opts?: LineOptions): LineMesh | null;
4812
+
4813
+ /**
4814
+ * УРОВЕНЬ ПЕРЕСЕЧЕНИЯ — какой из двух дорог быть сверху там, где они пересекаются без связи.
4815
+ *
4816
+ * ЗАЧЕМ. Плоская карта рисуется краской: слои идут в порядке стиля, и внутри слоя порядок фич
4817
+ * произволен. Поэтому эстакада над улицей ничем не отличалась от перекрёстка — обводки сливались,
4818
+ * полотна пересекались, и место читалось как съезд, которого в жизни нет. Ровно этим у Яндекса
4819
+ * занят `line-z-level` (`["get","z_level"]` у КАЖДОГО дорожного слоя, все они в одной сети
4820
+ * `line-network: "roads"`): сеть рисуется не по слоям, а по уровням, и мост со своей тенью и
4821
+ * обводкой целиком ложится поверх того, что под ним.
4822
+ *
4823
+ * ОТКУДА ЧИСЛО. Готового `z_level` в наших тайлах нет, зато есть то, из чего его считают:
4824
+ * `layer` — тег OSM, честный уровень (−1 подземный, 1 над землёй, изредка 2…5);
4825
+ * `brunnel` — «мост / тоннель / брод», он приходит и там, где `layer` не проставлен.
4826
+ * Поэтому берём `layer`, а если его нет — выводим уровень из `brunnel`. Мост без `layer`
4827
+ * (в Душанбе таких большинство) получает 1, тоннель — −1, обычная улица — 0.
4828
+ *
4829
+ * Считается в ВОРКЕРЕ, при тесселяции: по уровню бьётся меш, и рендеру остаётся только порядок.
4830
+ */
4831
+ /**
4832
+ * Дальше этого уровни не разводим. В OSM попадается и `layer=5`, и опечатки в сотни: каждое
4833
+ * значение — это отдельный бакет и отдельный вызов отрисовки, поэтому хвост подрезаем. Пять этажей
4834
+ * развязки — больше, чем бывает на настоящих.
4835
+ */
4836
+ declare const LEVEL_LIMIT = 5;
4837
+ /** Уровень фичи: `layer` из тегов, иначе вывод из `brunnel`. */
4838
+ declare function featureLevel(props: Record<string, unknown>): number;
4706
4839
 
4707
4840
  /**
4708
4841
  * Положение камеры в адресе страницы.
@@ -4802,6 +4935,8 @@ interface SurfaceOptions {
4802
4935
  /** Ширина фаски по горизонтали, метры. 0 — резкий край. */
4803
4936
  bevel?: number;
4804
4937
  /** Насколько фаска опускается по высоте, метры. */
4938
+ /** Насколько широкую щель между кусками слить, метры. Пусто — SURFACE_WELD_METERS. */
4939
+ weld?: number;
4805
4940
  bevelDrop?: number;
4806
4941
  /** Скругление углов в плане, метры. */
4807
4942
  cornerRadius?: number;
@@ -5656,4 +5791,4 @@ declare class Map$1 extends Evented<MapEvents> {
5656
5791
  destroy(): void;
5657
5792
  }
5658
5793
 
5659
- export { type AnimationOptions, AssetLoader, type AssetLoaderOptions, BASE_SOURCE, BUILDING_HEIGHT_SCALE, BUILDING_VERTEX_STRIDE, type BuildingHit, type BuildingsMesh, CITY_STYLE, type CameraOptions, Circle, type CircleOptions, type CoverOptions, DEFAULT_ICONS, DEFAULT_LIGHT, DEFAULT_SHADOWS, DEFAULT_SKY, DEFAULT_STYLE, DepthTarget, type DeviceHints, EARTH_CIRCUMFERENCE, FILL_VERTEX_STRIDE, type Filter, type FitBoundsOptions, type FitViewport, type FogPlanes, GLOBE_MAX_PITCH, GLOBE_ZOOM_MAX, GLOBE_ZOOM_MIN, GLYPH_BORDER, GLYPH_SIZE, GROUND_SCALE, GeomType, type GestureOptions, type Glyph, type GlyphMetric, GlyphSource, GroundArrows, IconSource, IndoorMask, type Interpolated, LINE_VERTEX_STRIDE, type LayerPlan, LayerRenderer, type LightSpec, type LinePlacement, type LngLat, LngLatBounds, type LngLatLike, MAX_LATITUDE, MODEL_VERTEX_STRIDE, Map$1 as Map, type MapEvents, MapObject, type MapObjectOptions, type MapOptions, Marker, type MarkerOptions, Model, ModelLayer, type ModelMesh, type ModelOptions, type ModelPrimitive, ObjectManager, type ObjectPaint, type ObjectPart, type Padding, type PlacedGlyph, type PlacedSymbol, Polygon, type PolygonOptions, Polyline, type PolylineOptions, type PolylineSegment, Popup, type PopupOptions, type Projection, type QualityName, type QualityProfile, RELIEF_STYLE, RUNTIME_FILL_STRIDE, RUNTIME_LINE_STRIDE, RasterSource, type RasterSourceOptions, RasterTile, type RoundOptions, type RuntimeMesh, SDF_EDGE, SDF_PX, SOFT_STYLE, SPLIT_SEP, SURFACE_CUT_BLEED, SURFACE_LEVEL_SCALE, SURFACE_VERTEX_STRIDE, type ScreenPoint$1 as ScreenPoint, SdfAtlas, type ShadowSettings, type SkySpec, Style, type StyleLayerSpec, type StyleSpec, type SymbolHit, SymbolRenderer, THEMES, TILE_SIZE, type ThemeSpec, TileID, Transform, VectorTile, VectorTileFeature, VectorTileLayer, abbreviateStreet, addGround, altitudeFromMercatorZ, applyTheme, arrowLabelOffset, arrowVertices, buildRuntimeFill, buildRuntimeLine, cameraForBounds, circumferenceAtLatitude, clampLat, clampPixelRatio, clipLineToRect, coordinateDigits, coveringTiles, createGround, Map$1 as default, deviceHints, distToSegment, evaluateColor, evaluateNumber, extractFeature, fillFootprint, fogPlanes, footprintOf, formatHash, generateBuildings, generateFill, generateLine, generateSurface, generateSymbols, globeBasis, globeFlatMix, globeRadius, globeToLocal, groundAt, iconRotation, insideFootprint, latFromMercatorY, lngFromMercatorX, lngLatToUnit, matchesFilter, mercatorMetersPerTile, mercatorX, mercatorY, mercatorZFromAltitude, metersPerPixel, metersPerTile, nextQualityDown, parseGlb, parseGlbAsync, parseGlyphs, parseHash, patchUV, pickBuilding, pickFill, pitchIntent, pixelsPerMeter, placeAlongLine, pointInRing, qualityFor, qualityProfile, raySphere, resolveTemplate, roundRing, sdfFromAlpha, shapeText, splitBucketKey, splitByGround, splitPolygons, styleWithTheme, tileOriginMeters, tileUrl, toLngLat, unitToLngLat, worldSize };
5794
+ export { type AnimationOptions, AssetLoader, type AssetLoaderOptions, BASE_SOURCE, BUILDING_HEIGHT_SCALE, BUILDING_VERTEX_STRIDE, type BuildingHit, type BuildingsMesh, CITY_STYLE, type CameraOptions, Circle, type CircleOptions, type CoverOptions, DEFAULT_ICONS, DEFAULT_LIGHT, DEFAULT_SHADOWS, DEFAULT_SKY, DEFAULT_STYLE, DepthTarget, type DeviceHints, EARTH_CIRCUMFERENCE, FILL_VERTEX_STRIDE, type Filter, type FitBoundsOptions, type FitViewport, type FogPlanes, GLOBE_MAX_PITCH, GLOBE_ZOOM_MAX, GLOBE_ZOOM_MIN, GLYPH_BORDER, GLYPH_SIZE, GROUND_SCALE, GeomType, type GestureOptions, type Glyph, type GlyphMetric, GlyphSource, GroundArrows, IconSource, IndoorMask, type Interpolated, LEVEL_LIMIT, LINE_VERTEX_STRIDE, type LayerPlan, LayerRenderer, type LightSpec, type LinePlacement, type LngLat, LngLatBounds, type LngLatLike, MAX_LATITUDE, MODEL_VERTEX_STRIDE, Map$1 as Map, type MapEvents, MapObject, type MapObjectOptions, type MapOptions, Marker, type MarkerOptions, Model, ModelLayer, type ModelMesh, type ModelOptions, type ModelPrimitive, ObjectManager, type ObjectPaint, type ObjectPart, type Padding, type PlacedGlyph, type PlacedSymbol, Polygon, type PolygonOptions, Polyline, type PolylineOptions, type PolylineSegment, Popup, type PopupOptions, type Projection, type QualityName, type QualityProfile, RELIEF_STYLE, RUNTIME_FILL_STRIDE, RUNTIME_LINE_STRIDE, RasterSource, type RasterSourceOptions, RasterTile, type RoundOptions, type RuntimeMesh, SDF_EDGE, SDF_PX, SOFT_STYLE, SPLIT_SEP, SURFACE_CUT_BLEED, SURFACE_LEVEL_SCALE, SURFACE_VERTEX_STRIDE, type ScreenPoint$1 as ScreenPoint, SdfAtlas, type ShadowSettings, type SkySpec, Style, type StyleLayerSpec, type StyleSpec, type SymbolHit, SymbolRenderer, THEMES, TILE_SIZE, type ThemeSpec, TileID, Transform, VectorTile, VectorTileFeature, VectorTileLayer, abbreviateStreet, addGround, altitudeFromMercatorZ, applyTheme, arrowLabelOffset, arrowVertices, buildRuntimeFill, buildRuntimeLine, cameraForBounds, circumferenceAtLatitude, clampLat, clampPixelRatio, clipLineToRect, coordinateDigits, coveringTiles, createGround, Map$1 as default, deviceHints, distToSegment, evaluateColor, evaluateNumber, extractFeature, featureLevel, fillFootprint, fogPlanes, footprintOf, formatHash, generateBuildings, generateFill, generateLine, generateSurface, generateSymbols, globeBasis, globeFlatMix, globeRadius, globeToLocal, groundAt, iconRotation, insideFootprint, latFromMercatorY, lngFromMercatorX, lngLatToUnit, matchesFilter, mercatorMetersPerTile, mercatorX, mercatorY, mercatorZFromAltitude, metersPerPixel, metersPerTile, nextQualityDown, parseGlb, parseGlbAsync, parseGlyphs, parseHash, patchUV, pickBuilding, pickFill, pitchIntent, pixelsPerMeter, placeAlongLine, pointInRing, qualityFor, qualityProfile, raySphere, resolveTemplate, roundRing, sdfFromAlpha, shapeText, splitBucketKey, splitByGround, splitPolygons, styleWithTheme, tileOriginMeters, tileUrl, toLngLat, unitToLngLat, worldSize };