Skip to main content

Make road mark from road shapefile.

Project description

roadmark-maker

从 3D 道路 Shapefile 生成沿路排布的立体路名标牌(Wavefront OBJ)或实例化贴图用的 Billboard 位姿(CSV)。核心为 Python(GeoPandas / Shapely / Matplotlib)与 C++(OpenMP、可选 AVX2)混合的 Maplex 风格 避让与网格管线。

构建

chcp 65001 && uv build --wheel --out-dir dist

依赖与构建说明见 pyproject.toml;C++ 求解器声明在 src/roadmark_maker/roadmark_core.hpp,Cython 绑定在 src/roadmark_maker/roadmark_accel.pyx


对外接口与能力

接口 作用 典型下游
generate(...) 完整管线:读 SHP → 采样与排版 → C++ OBB 碰撞解算 → 逐字或整段 挤出网格 → 写 OBJ Cesium、OSG、Blender 等需三角网格的场景
generate_csv(...) generate 共用 _prepare_data(同样的采样、CRS、density / repeat_mode、碰撞),但 不建网格;在引擎内固定 curved_text=False,将每条标注的 整体 位姿(平移 + 旋转)写出为 CSV UE、Cesium 等用 实例化 Quad + 贴图 画路名

二者均在 src/roadmark_maker/__init__.py 中导出;优先加载 roadmark_accel_avx2,不可用时回退 roadmark_accel


核心逻辑(文字从哪来、模型 / CSV 怎么来)

  1. 文字内容:来自 Shapefile 中由 name_field 指定的字段(默认 name),经 strip 后跳过空、nonenan
  2. 字体与字形_FontManager.get_chinese_font_path() 依次尝试常见中文字体;失败则下载 Noto Sans SC 到临时目录。_TextMeshEnginematplotlib.textpath.TextPath 将字符转为多边形,单字symmetric_difference 处理字内孔洞,整段union 合并字间形状;三角化使用 mapbox_earcut,再挤出顶/底与侧墙。
  3. 三维模型(OBJ):对每个未 hidden 的标注,build_tbn_matrix 在弧长 distance 处建立局部 TBN(切线 / 副法线 / 法线) 齐次矩阵;curved_text=True 时按字符沿线的弧长位置逐字建矩阵并变换顶点;curved_text=False 时整段网格用 一个 采样点的矩阵整体放置。separate_objects 控制是否每个标注单独 o object_name
  4. CSVgenerate_csv_prepare_data 之后遍历存活标注,取矩阵的平移 (x,y,z),将 3×3 旋转经 C++ MathUtils.matrix_to_rotations 转为四元数与/或 ZYX 欧拉角,可按 target_crs 再投影;列为 x,y,z + 角度 + name包含逐字几何,适合整条路名一张纹理的实例化。

参数如何控制「分布」与外观

参数 控制点
text_count 若为正整数,在每条线段上 等分弧长 生成该数量的候选(忽略 distance_interval)。
distance_interval 未设 text_count 时,沿弧长每隔约该距离(与当前 CRS 单位一致;UTM 下为米)放一个候选。
add_at_endpoints 为 true 时在弧长 0 与 line_len 处额外各加一个候选。
density 仅当 curved_text=True 时参与 auto_place_labels:档位决定 全局最小间距同组重复最小间距每组最多保留条数全局贪心外层迭代次数(见下表);可用 max_global_iterations 覆盖迭代次数。
repeat_mode / connect_eps name_connected(默认)下按 路名 + 线段端点距离 ≤ eps 并查集合并连通分量,同组共享 max_labels_per_group 配额;feature / name 为其它分组策略。
font_size / letter_spacing 世界空间大致字高与字距;碰撞体宽度用 effective_text_leneffective_char_width_est(自动压缩时变化)。
curved_text True:自动适配线长、全局选点、逐字贴合折线;False:整段文本一块网格、不做 auto_place_labels 筛选。
auto_fit_text / min_font_scale / min_letter_spacing / overflow_strategy curved_text=True 时,apply_autofit 按线长比例缩小字号与字距,仍过长则 truncate 策略下二分保留长度并加
posture flat:法线朝上贴地;billboard:以世界 Z 为参考的立式朝向。
use_utm True:以数据质心经度推算 UTM 带并 to_crs,XY/Z 比例更接近真实米制;False(默认):工作 CRS 为 EPSG:3857
weight_field 碰撞时 权重大者不滑动;权重相同则 文本更长者 作为 yielder 被推动。
separate_objects 仅影响 OBJ 是否分 o 组。

全局迭代优化(auto_place_labels)与 C++ 碰撞

全局阶段(仅 curved_text=True):

  • 对每个要素在「线长能放下估计跨度」的候选里,选弧长最接近 线段中点 的一个作为 锚点
  • 外层循环最多 iterations 次(由 density 决定,或由 max_global_iterations 覆盖);每轮对当前已选集合调用 _fast_resolve_collisions(..., 3, ...),去掉被标为 hidden 的。
  • 在剩余候选中贪心加入下一个:需满足 全局与其它已选中心的平面距离global_min_sepgroup_idrepeat_min_interval、且组内个数小于 max_labels_per_group;得分优先 离已选集合最远
  • 未被选中的候选最终 hidden=True,不再导出。

density 默认档位(font_size 取中位数有效字号参与比例,代码见 _density_profile

档位 global_min_sep repeat_min_interval max_labels_per_group 外层迭代 iterations
very_dense 6×fs 10×fs 5 10
dense 8×fs 14×fs 4 9
moderate 10×fs 18×fs 3 8
sparse 14×fs 26×fs 2 7
very_sparse 18×fs 34×fs 1 6

C++ 碰撞MaplexSolver::resolve_collisions,Python 侧 max_iterations 固定为 3,非用户参数):

  • 根据当前 OBB 最大宽度建 均匀网格,格内两两做 分离轴 SAT(四个轴:两边 OBB 的方向与法向)。
  • 冲突时对 yielder同线级联滑动:步长约 2 * char_width_est,沿切向推进并可能推动后方同线标注;超出 line_lenhidden
  • 固定轮次结束后仍有重叠则 一方直接 hidden(权重与字长规则同上)。

推荐:城市密集路网可先用 moderatedense;希望同一路名少重复、留白大可 sparse / very_sparse。若仍过密,可增大 distance_interval 或设置较小的 text_count,或略减小 font_size

注意generate_csvcurved_text 置为 False,因此 不会 执行上述全局 auto_place_labels 筛选;CSV 与 OBJ(curved_text=True)在「候选数量」上可能不一致。


处理流程图(与实现一致)

flowchart TB
    subgraph API["入口"]
        G["generate() → OBJ"]
        C["generate_csv() → CSV<br/>内部固定 curved_text=False"]
    end

    subgraph S1["1. 数据与坐标系"]
        A[读取 Shapefile<br/>GeoPandas] --> B{name_field 存在?}
        B -->|否| W[警告并返回空结果]
        B -->|是| CRS{use_utm}
        CRS -->|true| U[质心经纬度 → 推算 UTM EPSG]
        CRS -->|false 默认| M[EPSG:3857]
        U --> T[to_crs 工作 CRS]
        M --> T
    end

    subgraph S2["2. 沿几何采样候选 Label"]
        T --> L[拆分 LineString / MultiLineString]
        L --> S[text_count 或 distance_interval<br/>+ 可选端点 add_at_endpoints]
        S --> K[每条记录: text / weight≥1 / line_len / distance 等]
    end

    subgraph S3["3. 曲线模式预处理"]
        K --> CT{curved_text?}
        CT -->|False| SK[跳过 autofit / auto_place]
        CT -->|True| AF{auto_fit_text?}
        AF -->|是| AF2[apply_autofit:<br/>按线长缩放 + truncate …]
        AF -->|否| AP
        AF2 --> AP[auto_place_labels:<br/>锚点 + 全局贪心 + 组约束<br/>每轮子集 _fast_resolve ×3]
        AP --> SK
    end

    subgraph S4["4. 局部坐标架与 C++ 碰撞"]
        SK --> MX[为各候选 build_tbn_matrix<br/>差分弧长得 T; auto_flip 可读性]
        MX --> COL["_fast_resolve_collisions<br/>C++ 网格 + SAT-OBB<br/>固定 max_iterations=3"]
        COL --> MD[distance 变化则 matrix_dirty]
    end

    subgraph S5["5a. OBJ 导出 generate"]
        MD --> OBJ{导出分支}
        OBJ -->|curved_text=True| CV[逐字 TextPath + earcut 挤出<br/>沿线分布弧长]
        OBJ -->|curved_text=False| FL[整段 generate_mesh 一次<br/>单矩阵变换]
        CV --> WOBJ[写 v/f; separate_objects 控制 o 分组]
        FL --> WOBJ
    end

    subgraph S5b["5b. CSV 导出 generate_csv"]
        MD --> CSVM[矩阵平移 + matrix_to_rotations<br/>可选 target_crs 变换]
        CSVM --> WCSV[UTF-8-SIG CSV<br/>x,y,z + 四元数/欧拉 + name]
    end

    G --> A
    C --> A

一次运行只调用 generate generate_csv 之一;上图中 5a / 5b 为两种出口,不会在同一次执行里同时发生。


逻辑关系简图(阶段依赖)

graph LR
    IO[SHP + CRS] --> SP[弧长采样]
    SP --> GF{curved_text?}
    GF -->|是| AP[autofit + 全局选点]
    GF -->|否| MX[建 TBN]
    AP --> MX
    MX --> CPP[C++ 碰撞 3 轮]
    CPP --> OUT{输出}
    OUT -->|generate| MESH[网格 + OBJ]
    OUT -->|generate_csv| TBL[位姿 + CSV]

以上流程与 src/roadmark_maker/roadmark_accel.pyx_RoadMaplexEngine._prepare_dataexport_objexport_csv 的实现顺序一致,便于对照阅读源码。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

roadmark_maker-0.2.8-cp314-cp314-win_amd64.whl (188.2 kB view details)

Uploaded CPython 3.14Windows x86-64

roadmark_maker-0.2.8-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (427.8 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

roadmark_maker-0.2.8-cp313-cp313-win_amd64.whl (184.1 kB view details)

Uploaded CPython 3.13Windows x86-64

roadmark_maker-0.2.8-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (429.5 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

roadmark_maker-0.2.8-cp312-cp312-win_amd64.whl (183.7 kB view details)

Uploaded CPython 3.12Windows x86-64

roadmark_maker-0.2.8-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (429.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

roadmark_maker-0.2.8-cp311-cp311-win_amd64.whl (186.3 kB view details)

Uploaded CPython 3.11Windows x86-64

roadmark_maker-0.2.8-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (437.4 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file roadmark_maker-0.2.8-cp314-cp314-win_amd64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 f646f26624b6f93910e9e939c4ed9a9fbad059c86469aa2e452222e0aff73021
MD5 46a92cbe04e7ccc6919dbb77f5b553c8
BLAKE2b-256 e3bd876da36a5539074ee4f5af1642a462d89dd288ac759502d9971249417efa

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c98ab46f46988722f6537935dd53f78b9158ff88178a0864c06fe1dd909378dc
MD5 273e4b0f992f66180854593d1a7ff25e
BLAKE2b-256 0405be6c703479ed0aeb4d5231ea168ba355a816aff7ac59c7ebbf2319b93707

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 14195588d13ff06f56c68049bdd1ef1f9608c9784f1291e195e68c7ae923c5d3
MD5 755199a25421e12c83f2c6c11fdf7d97
BLAKE2b-256 f82e2fbbe35307e1714aa0b3656d1f957834bbba34fad6444606b9bedd22a309

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3bd92d2e73cdd2197b00ddf0857af8b0f1105ab753529a23b7d811f89c25dea8
MD5 0bd4eb59db3943bc0fd4700f24c80853
BLAKE2b-256 af945d247f8377ea93078e5b8ded3f9c981b15c9c225fecf19cc7312a6deca4f

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 f6f8664749d779110e91cebcde275d932d049ff53984fb13ae7fceba88197e12
MD5 8750757051d496b90bdbbc94a28df6d0
BLAKE2b-256 54628cc49b6e12ace648084a06b1d2a3fc049b4c0a1558bc5673dc46d86d9ad9

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 fa2a0f6a1b4f374050b8c663cd6b6661470d27a5239644529128de807f5c0da7
MD5 0014267a39f5d49d35facb56fd92e7b9
BLAKE2b-256 bc517bd383767e235e9c19bf903e66429f1d2e42ae7280aa039bd12783190c08

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4f684a3a06acdbd9bd95433d7d0e145f81bef61aee864ee11b6f963c735df680
MD5 bea8337eeeb3e460b4458fa4a41c9ac0
BLAKE2b-256 8731cd7560bc5126f9f297c776c0473c0e9c71eb61b21b07b625472d80dfc113

See more details on using hashes here.

File details

Details for the file roadmark_maker-0.2.8-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for roadmark_maker-0.2.8-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b2f2a6b62ed4d76fd952661fd73d153de8a7e695e61e9c77fc5e71a7e6a56bbc
MD5 21fe2b999ec266ecc703cf99fc9a983b
BLAKE2b-256 9a969a30ea3c89e5770419d2d3d84945a21dddee2bc4bfe07577a586682b3701

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page