组合 / 拆分 / 导出
分类代号:C.5 本章共 6 个接口
把多张 DWG 组合成一张、把一张大图按图框 / 图层拆成多张、把图纸导出为 PDF / DXF 或离线瓦片包——这一章就是"图纸经纪人"。
共同特点:这 6 个接口都相对重,后端会真实创建新图档 / 新文件。测试环境请用临时 mapid,不要对生产图做实验。
快速索引
| 序号 | SDK 方法 | URL |
|---|---|---|
| 36 | cmd_compose_new_map / cmdComposeNewMap |
POST /api/v1/map/cmd/composeNewMap/_null/v1 |
| 37 | cmd_split_map / cmdSplitMap |
POST /api/v1/map/cmd/cmdSplitMap/_null/v1 |
| 38 | cmd_export_layout / cmdExportLayout |
POST /api/v1/map/cmd/exportLayout/_null/v1 |
| 39 | cmd_export_pdf / cmdExportPdf |
POST /api/v1/map/cmd/exportPdf/{mapid}/{version} |
| 40 | cmd_export_dxf / cmdExportDxf |
POST /api/v1/map/cmd/exportDxf/{mapid}/{version} |
| 41 | cmd_save_offline_tile_db / cmdSaveOfflineTileDb |
POST /api/v1/map/cmd/saveOfflineTileDb/_null/v1 |
36 · 组合新地图 composeNewMap
把多张已有 DWG(可各自裁剪范围、四参数变换、按图层过滤)拼成一张新图。
⚠️ 参数是后缀编号风格,不是
maps数组:第 1 张图用无后缀键(mapid、clipBounds…),第 2 张起加序号(mapid2、clipBounds2…),总数由count声明。
请求参数
| 字段 | 类型 | 说明 |
|---|---|---|
count |
int | 参与组合的源图数,默认 1 |
mapid{i} / version{i} |
string | 第 i 张源图(i=1 无后缀,i≥2 后缀 2、3…) |
clipBounds{i} |
string | 可选:裁剪范围 [x1,y1,x2,y2] |
selByCrossing{i} |
bool | 裁剪时是否含相交实体(默认 false) |
layers{i} |
string | 可选:参与的图层名 JSON 数组,如 ["0","TEXT"] |
fourParameter{i} |
string | 可选四参数变换 [xOff,yOff,scale,rotRad] |
isInverseFourParamter{i} |
string | "true" 反向应用四参数(注意后端拼写 Paramter) |
layerPrefix{i} / layerSuffix{i} |
string | 输出图层名加前/后缀 |
savefilename{i} |
string | 可选:该源图裁剪中间结果文件名,缺省自动生成 |
purge{i} |
bool | 先对源图 purge 再组合(默认 false) |
isFullExtent{i} |
bool | 裁剪结果范围取全图(默认 false) |
isRenameBlockNameIfExist |
bool | 块名冲突时自动重命名(默认 true) |
subfrom / subdependencies |
string | 协同图元数据的直接来源/依赖(高级) |
响应
成功(实采双图组合):
{ "status": true, "fileid": "p2de970c8c9a", "mapfrom": "…", "mapdependencies": "…" }
fileid是组合产物文件({fileid}.dwg,deleteMapFile可清理)——不是逐图回写数组。mapfrom不是subfrom的回显——是后端合成的源规格串("{mapid}&&{ver}&&{clipbounds}&&0&&…&&1&&"形态);mapdependencies也不回显subdependencies(传了仍返空串)。两字段当只读回执看,别当参数回显校验。count与实际参数不一致(如count=2缺mapid2)→ HTTP 200 + body 级错误{error:"file is not exist, ", status:false},不抛异常——调用方必须自查status。isInverseFourParamter(后端错拼Paramter)端到端可用:fourParameter+isInverseFourParamter:true组合正常出图。
失败(实采:源文件不存在 / count 与实参不符):
{
"error": "file is not exist, ",
"status": false
}
Python
svc.cmd_compose_new_map(
count=2,
mapid="part_a", version="v1",
clipBounds="[0,0,1000,1000]", layers='["0"]',
mapid2="part_b", version2="v1",
fourParameter2="[1000,0,1,0]", # 第二张图平移 1000
)
Node.js
await svc.cmdComposeNewMap({
count: 2,
mapid: 'part_a', version: 'v1', clipBounds: '[0,0,1000,1000]',
mapid2: 'part_b', version2: 'v1', fourParameter2: '[1000,0,1,0]',
});
37 · 拆分子图 cmdSplitMap
按一组 bbox 把一张大图拆成多张小图。
请求参数
| 字段 | 类型 | 说明 |
|---|---|---|
mapid / version |
string | 源图(二选一:fileid 直接给 dwg 文件名) |
fileid |
string | 源 dwg 文件名,省略时用当前打开的图档 |
clipBounds |
array | 必填:bbox 列表 [["x1","y1","x2","y2"], ...],每框出一张子图。元素也接受逗号串形式 ["x1,y1,x2,y2"] |
isFullExtent |
bool | 子图范围取全图(默认 false) |
method |
string | cloneObjects(默认,逐实体克隆)/ cloneDb / cloneMap |
accessKey / secretKey |
string | 访问受保护图时必填 |
响应
成功:{ "fileids": ["a1.dwg", "a2.dwg", ...] }(每个 clipBounds 一个新 fileid;成功时无 status 字段,判失败看 error/status:false)
失败(实采:未给 clipBounds):
{ "error": "clipBounds is empty" }
⚠️ fileids 可能回含源文件名(实采 2026-09-20):clipBounds 覆盖源图数据范围时,拆分出的子图可以直接就是源 dwg——响应为
{"fileids":["<mapid>.dwg"]}。批量deleteMapFile(fileids)清理会把地图底图 dwg 一起删掉(mapfiles/<mapid>.dwg消失,之后 compose/exportLayout 等文件型命令全报file is not exist,但 db 驱动的 openMap/query/渲染不受影响)。清理时务必排除源文件名:fileids.filter(f => f !== mapid + '.dwg')。
38 · 导出布局为 DWG exportLayout
从 DWG 的布局空间(paper space)单独导出一张新 DWG。CAD 里经常一个文件多个布局(A3、A2、首页),这个接口能一次性把某个布局变成独立图档。
请求参数
| 字段 | 类型 | 说明 |
|---|---|---|
mapid / version |
string | 源图(version 缺省取最新版) |
layoutIndex |
int | 布局序号(0 起) |
layoutName |
string | 或直接用布局名(layoutIndex 优先,二者都给时按 index) |
accessKey / secretKey |
string | 访问受保护图时必填 |
新图 mapid 由后端根据请求参数 hash 自动生成(
p前缀),不接受newMapid/newVersion请求参数。
响应(实采:sys_zp/v1, layoutIndex=0)
{
"fileid": "pf68817b9655",
"status": true
}
fileid 指向后端缓存里的新 DWG 文件,可以接着调用 open_map(mapid=...) 打开,或用 exportDxf / exportPdf 进一步出图。
⚠️ 不存在/bogus mapid 是 body 级错误:
{status:false, error:'File access error: "…/mapfiles/<mapid>"'},HTTP 200 不抛异常——调用方须自查status。
Python
res = svc.cmd_export_layout(mapid="sys_zp", version="v1", layoutIndex=0)
assert res["status"]
print(res["fileid"]) # 'pf68817b9655'
39 · 导出 PDF exportPdf
把当前图档通过 ODA PDF 导出器输出为 PDF。参数是 ODA 导出选项,不是 bbox 截图式参数(不支持 bounds/width/height/scale/outName)。
请求参数
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
pageWidth / pageHeight |
number | — | 纸张尺寸(mm),两者都给出才生效 |
pageLeftMargin / pageRightMargin / pageTopMargin / pageBottomMargin |
number | 0 | 页边距(配合 pageWidth/pageHeight) |
bZoomToExtents |
bool | true | 内容缩放到纸张范围 |
bActiveLayout |
bool | true | 只导出当前活动布局;false 导出全部布局 |
bUsePaperFromOptions |
bool | — | 使用图纸自带页面设置 |
geomDPI / colorImagesDPI / bwImagesDPI |
int | — | 几何/彩色图/黑白图 DPI |
isBlackWhiteMode / isGrayMode / isBwModeBlock / isUseGrayPolicy |
bool | false | 黑白/灰度输出 |
bEmbededTTF / bEmbededOptimizedTTF |
bool | false | 嵌入 TTF 字体 |
bTTFAsAGeometry / bSHXAsAGeometry |
bool | true | 字体转几何 |
bSearchableTTF / bSearchableSHX |
bool | — | 文本可搜索 |
bEnableLayersSupport / bIncludeOffLayers |
bool | — | PDF 图层支持 / 含关闭图层 |
bUseHiddenLineAlgo / bUseSimpleGeomOpt |
bool | — | 隐藏线算法 / 几何优化 |
bHyperlinks / bLinearized / bMeasuring / bExtentsBoundingBox |
bool | — | 超链接 / 线性化 / 测量 / extents 边框 |
bEncoded / bASCIIhexEncoded |
bool | — | 内容流编码 |
nSolidHatchExpType / bOtherHatchExpTypekBitmap |
int/bool | — | 填充导出类型 |
title / author / creator / producer |
string | — | PDF 文档元信息 |
pdfPath |
string | 自动 | 输出路径(缺省写入 download 目录、按参数 hash 命名) |
debugLog / stripProxyOnRetry |
bool | false/true | 调试日志 / 重试时剥离代理实体 |
lineWeight |
number | — | 线宽系数 |
图纸内容由 URL 中的
{mapid}/{version}选定的已打开图档决定。⚠️ 同参数重复调用返回不同的
path文件名(download/<hash1>.pdf→download/<hash2>.pdf),但第二次明显更快(565ms→7ms)——后端内部有加速,但不要假设path相同即缓存复用,要复用文件请存好首次返回的path。
响应(实采:sys_zp/v1)
{
"path": "download/d5f939154c.pdf",
"status": true
}
完整下载 URL 是 http://127.0.0.1:27660/{path}?token=<jwt>。
Python
res = svc.cmd_export_pdf(
mapid="sys_zp", version="v1",
pageWidth=297, pageHeight=210,
)
url = svc.base_gateway() + res["path"] + f"?token={svc.token}"
Node.js
const res = await svc.cmdExportPdf({
mapid: 'sys_zp', version: 'v1',
pageWidth: 297, pageHeight: 210,
});
const url = `${svc.baseGateway()}${res.path}?token=${svc.token}`;
40 · 导出 DXF exportDxf
把当前图档整体导出为 DXF 文件(不支持裁剪/选层——导出的是整个 database)。
请求参数
⚠️ cmd 路由对空 JSON body 的 POST 回 HTTP 500 param error,本接口同样适用。SDK 已处理:除 mapid/version 外没有其它参数时
cmdExportDxf/cmdExportPdf改走 GET(GET 不校验),按缺省参数导出;手写 REST 时要么 GET,要么 POST 至少带一个字段(如cadVersion:"*")。
| 字段 | 类型 | 说明 |
|---|---|---|
filename |
string | 输出文件名(自动补 .dxf;缺省用源图名 + _.dxf) |
cadVersion |
string | 目标 CAD 版本:2000/2004/2007/2010/2013/2018;* = 沿用源图版本 |
响应
成功:{ "status": true, "fileid": "xxx.dxf" }(fileid 是后端 mapfiles 目录里的文件名)
失败(实采:当前地图没有可导出图元):
{
"error": "Invalid Symbol Table name",
"status": false
}
Python
res = svc.cmd_export_dxf(
mapid="sys_zp", version="v1",
filename="sys_zp_out", # 实际写 sys_zp_out.dxf
cadVersion="2018",
)
41 · 离线瓦片包 saveOfflineTileDb
把指定地图已有的栅格/矢量瓦片库按 zoom 范围抽成一个新的离线 sqlite 包(offlinetiles/<id>.db)。注意:它复制既有瓦片,不切新瓦片——源图需先生成过瓦片。
请求参数
| 字段 | 类型 | 说明 |
|---|---|---|
mapid / version |
string | 源图 |
layers |
string | 必填:db_source 中的 style 表名(s<hex> 形态,即瓦片 URL /map/tile/{mapid}/{ver}/{sXXX}/… 里的那段),逗号分隔 |
rasterMinZoom / rasterMaxZoom |
int | 栅格瓦片 zoom 区间(max > min 才导栅格) |
vectorMinZoom / vectorMaxZoom |
int | 矢量瓦片 zoom 区间(max > min 才导矢量) |
输出文件名后端自动生成(
_yyyyMMddhhmmss_NNN),不接受outName/bounds/ismvt/minzoom/maxzoom。
响应
成功:{ "status": true, "dbfilename": "<绝对路径>.db" }
失败(实采:缺 layers 或 zoom 区间为空):
{ "error": "param error" }
⚠️
layers的值被原样插进后端 SQL(insert into <layers> select * from db_source.<layers> where zoom_level >= …)。给了不存在的表名时返回的是 HTTP 200 + body 级{ "error": "exec sql error: insert into …" }而非param error——调用方要检查r.error,不能只看status/dbfilename。文档旧示例里的layers="s_default"就是一条 SQL 错误;正确值是真实 style 表名(如s6d04d896e)。
Python
res = svc.cmd_save_offline_tile_db(
mapid="sys_zp", version="v1",
layers="s6d04d896e", # 用瓦片 URL 里的 style 表名(s<hex>),不是 "s_default"
rasterMinZoom=0, rasterMaxZoom=7,
vectorMinZoom=0, vectorMaxZoom=7,
)
组合示例:DWG → PDF 一把梭
# 1. 上传并打开 DWG
up = svc.upload_map("project.dwg")
svc.open_map(
mapid="proj", version="v1",
fileid=up["fileid"], uploadname=up["uploadname"],
mapopenway=vjmap.MapOpenWay.GeomRender,
)
# 2. 导出第 0 号布局(新图 mapid 由后端 hash 生成,看返回 fileid)
lay = svc.cmd_export_layout(mapid="proj", version="v1", layoutIndex=0)
# 3. 打开刚生成的布局图并导 PDF(fileid=12 位 hash,uploadname=<fileid>.dwg)
svc.open_map(mapid="proj_layout0", version="v1",
fileid=lay["fileid"], uploadname=lay["fileid"] + ".dwg",
mapopenway=vjmap.MapOpenWay.GeomRender)
pdf = svc.cmd_export_pdf(mapid="proj_layout0", version="v1",
pageWidth=297, pageHeight=210)
print(svc.base_gateway() + pdf["path"])