# Map Service REST API

# Introduction

The map service uses REST APIs. Frontend development can use the Service class in the vjmap JS SDK to call the service. To get map metadata, use:

let svc = new vjmap.Service(env.serviceUrl, env.accessToken);
let res = await svc.metadata("sys_zp" /*map id*/, "v1" /*map version, empty for latest*/);
console.log(res)
1
2
3

When this code runs in the browser, F12 Network shows an http request to the map service.

image-20230524140958184

For backend calls, send the same http request.

Test in Postman: image-20230524141331530

The map service REST API returns correct results when called from Postman.

Note: All service calls must use application/json and include the Token header (or token=xxxx query parameter for GET requests) for authentication. To open password-protected maps without a password prompt, add secretKey or accessKey in the request header. (This is not repeated in examples below; remember to add Token in practice.)

# Common Service APIs

(For brevity, only relative URLs are shown. E.g. https://vjmap.com/server/api/v1/map/cmd/metadata/sys_zp/v1 is abbreviated as /api/v1/map/cmd/metadata/sys_zp/v1)

# Upload Drawing

Service URL /api/v1/map/uploads
Request Type Post
Request Parameter Parameter Description Parameter Example
fileToUpload File binary content

# Create or Open Drawing

Service URL /api/v1/map/openmap/{mapid}
Request Type Get or Post
Request Parameter Parameter Description Parameter Example
version Map version
layer Style
geom Open with geometry render mode true
fileid File unique ID. Pass fileid when opening map for first time cfbe8dc085fb
imageLeft Image top-left x. Valid when opening image type for first time undefined
imageTop Image top-left y. Valid when opening image type for first time
imageResolution Image resolution. Valid when opening image type for first time
uploadname Upload filename zp.dwg
mapfrom Map source (for collaborative drawings)
mapdependencies Map dependencies (for collaborative drawings)
subfrom Map source for sub-items (for collaborative drawings)
subdependencies Map dependencies for sub-items (for collaborative drawings)
stylename Style layer name
layeron Layer indices to turn on, e.g. [0,1,3]
layeroff Layer indices to turn off, e.g. [2,4]
clipbounds Map clip bounds, e.g. [x1,y1,x2,y2]
bkcolor Background color 0
lineweight Line weight, e.g. [1,1,1,1,0]
expression Style expression
secretKey Set when encrypting map on first creation
accessKey Access key when map has password

Note: When setting a password on first upload, set secretKey. Compute as: MD5(MD5(MD5(MD5(password)))), take first 16 chars.

Node.js backend upload and create/open example


// app.js
const fs = require('fs')
const FormData = require('form-data')
const axios = require('axios')
const prompt = require('prompt');

(async ()=>{
    const defaultServiceUrl = 'https://vjmap.com/server/api/v1';
    const defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MiwiVXNlcm5hbWUiOiJhZG1pbjEiLCJOaWNrTmFtZSI6ImFkbWluMSIsIkF1dGhvcml0eUlkIjoiYWRtaW4iLCJCdWZmZXJUaW1lIjo4NjQwMCwiZXhwIjo0ODEzMjY3NjM3LCJpc3MiOiJ2am1hcCIsIm5iZiI6MTY1OTY2NjYzN30.cDXCH2ElTzU2sQU36SNHWoTYTAc4wEkVIXmBAIzWh6M';

    let formData = new FormData();
    let { filepath } =  await prompt.get('filepath'); // Enter file path to upload
    if (!filepath) return;
    let file = fs.createReadStream(filepath)   
    formData.append('fileToUpload', file);
    
    let len = await new Promise((resolve, reject) => {
      return formData.getLength((err, length) => (err ? reject(err) : resolve(length)));
    });
    let res = await axios({
        url: `${defaultServiceUrl}/map/uploads?token=${defaultAccessToken}`,
        method: 'POST',
        data: formData,
        headers: {
          ...formData.getHeaders(),
          'Content-Length': len,  
        },
    });
    /*
    {
        fileid: 'c036d8ca23eb',
        mapid: 'c036d8ca23eb', // mapid is suggested; if previously uploaded/opened, use that mapid
        uploadname: 'base1.dwg'
    }
    */
    console.log(res.data);

    // Upload sends file to server. On first open, pass fileid to openMap and assign mapid. Afterwards open by mapid.
    let { mapid } =  await prompt.get('mapid'); // Enter mapid
    if (!mapid) {
        // If no mapid, use default from upload response
        mapid = res.data.mapid;
    }
    let url = `${defaultServiceUrl}/map/openmap/${res.data.mapid}?version=&layer=&geom=true&fileid=${res.data.fileid}&uploadname=${res.data.uploadname}&mapfrom=&mapdependencies=&subfrom=&subdependencies=&stylename=&layeron=&layeroff=&clipbounds=&bkcolor=0&lineweight=&expression=`;
    // To set password, e.g. 123456
    //  MD5 four times, strMd5 is MD5 helper, implement as needed
    // let secretKey =  strMd5(strMd5(strMd5(strMd5("123456")))).substr(0, 16);
    // url += "&secretKey=" + secretKey
    let result = await axios({
        url: url,
        method: 'GET',
        headers: {
          token: defaultAccessToken,  
        },
    });
    console.log(result)
})();


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

To create drawings from parameters in the backend, generate a JSON object from the entity objects, serialize to string (or base64), and pass as fileid. Node.js parameter-based drawing creation:

const axios = require("axios");


(async () => {
  const defaultServiceUrl = "https://vjmap.com/server/api/v1";
  const defaultAccessToken =
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MiwiVXNlcm5hbWUiOiJhZG1pbjEiLCJOaWNrTmFtZSI6ImFkbWluMSIsIkF1dGhvcml0eUlkIjoiYWRtaW4iLCJCdWZmZXJUaW1lIjo4NjQwMCwiZXhwIjo0ODEzMjY3NjM3LCJpc3MiOiJ2am1hcCIsIm5iZiI6MTY1OTY2NjYzN30.cDXCH2ElTzU2sQU36SNHWoTYTAc4wEkVIXmBAIzWh6M";

  let doc = {};
  let entitys = [];
  // See official docs https://vjmap.com/doc/Class_DbDocument.html for parameters
  entitys.push({
    typename: "DbLine",
    start: [14, 0],
    end: [14, 15],
    colorIndex: 1,
  });
  entitys.push({
    typename: "DbCircle",
    center: [14, 7.5],
    radius: 1.83,
    color: 0xff0000,
  });
  entitys.push({
    typename: "DbText",
    position: [14, 16],
    contents: "Basketball court diagram",
    colorIndex: 1,
    horizontalMode: 4,
    height: 1,
  });
  doc.entitys = entitys;

  // Base64 encoding also works but not recommended; JSON string is fine
  //var bytes = new Buffer(JSON.stringify(doc));
  //var base64 = "data:application/dwg;base64," + bytes.toString('base64')// let fileid = base64;

    let fileid = JSON.stringify(doc);
  // Upload sends file to server. On first open, pass fileid to openMap and assign mapid. Afterwards open by mapid.
  let mapid = "mybackendmap"
  let url = `${defaultServiceUrl}/map/updatemap/${mapid}`;
  let data = {
    fileid: fileid,
    clipbounds: '',
    bkcolor: 0,
    geom: true,
    uploadname: ""
  }
  // To set password (e.g. 123456): MD5 four times; implement strMd5 as needed
  // let secretKey =  strMd5(strMd5(strMd5(strMd5("123456")))).substr(0, 16);
  // url += "&secretKey=" + secretKey
  let result = await axios({
    url: url,
    method: "POST",
    headers: {
      token: defaultAccessToken,
    },
    data
  });
  console.log(result);
})();


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

Result:

image-20230524172844505

# Check If File Already Uploaded

Service URL api/v1/map/mapfile
Request Type Get
Service Description Check if file exists on server before upload; if so return fileid without uploading. Can be skipped in practice.
Request Parameter Parameter Description Parameter Example
md5 File MD5 value fbe8dc085fbcdac502c640cf2dd8065c

Node.js implementation for file MD5 (other backends can adapt):

import SparkMD5 = require("spark-md5");
/**
     * Get file MD5 value
     * @param file
     * @return {Promise<any>}
     */
    function fileMd5(file: File): Promise<any> {
        return new Promise((resolve, reject) => {
            const blobSlice =
                // @ts-ignore
                File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
            const chunkSize = 2097152; // Read in chunks of 2MB
            const chunks = Math.ceil(file.size / chunkSize);
            let currentChunk = 0;
            const spark = new SparkMD5.ArrayBuffer();
            const fileReader = new FileReader();

            fileReader.onload = function(e) {
                // @ts-ignore
                spark.append(e.target.result); // Append array buffer
                currentChunk++;

                if (currentChunk < chunks) {
                    loadNext();
                } else {
                    var md5 = spark.end();
                    resolve(md5);
                }
            };

            fileReader.onerror = function() {
                reject("file reader error");
            };

            function loadNext() {
                var start = currentChunk * chunkSize;
                var end = start + chunkSize >= file.size ? file.size : start + chunkSize;
                fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
            }

            loadNext();
        });
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# Update Drawing

Service URL /api/v1/map/updatemap/{mapid}
Request Type Get or Post

Same parameters as Create or Open Drawing

# Raster Tile URL

Service URL api/v1/map/tile/{mapid}/{version}/{stylename}/{zoom}/{x}/{y}
Request Type Get
Service Description mapid: map id; version: version; stylename: style name; zoom: level; x,y: tile column/row
Request Parameter Parameter Description Parameter Example
tag fileid

# Vector Tile URL

Service URL api/v1/map/tile/{mapid}/{version}/{stylename}/{zoom}/{x}/{y}.mvt
Request Type Get
Service Description mapid: map id; version: version; stylename: style name; zoom: level; x,y: tile column/row
Request Parameter Parameter Description Parameter Example
tag fileid

# Execute Map Command

Service URL api/v1/map/cmd/${cmdname}/${mapid}/${version}
Request Type Get or Post
Service Description cmdname: command name; mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
Parameters vary by command name

# Get Map Metadata

Service URL api/v1/map/cmd/metadata/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
geom Whether geometry rendering

# Update Map Metadata

Service URL api/v1/map/cmd/updateMetadata/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
Metadata key Value for the metadata key

# Proactively Close Open Map

Service URL api/v1/map/cmd/closemap/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
(none) (none)

# Get Map List

Service URL api/v1/map/cmd/listmaps/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id (empty = get all); pass map ID array to get specified maps; use pagination e.g. {curPage: 1, pageCount: 10}; version: version (empty = latest, * = all versions)
Request Parameter Parameter Description Parameter Example
mapIds When mapid is empty, specify map ID array to query

# Query Entities

Service URL api/v1/map/cmd/queryFeatures/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
querytype Query type: "condition", "rect", "point", "expresion" condition
beginpos Record start position 0
bounds Bounds ""
condition Query condition layerindex = 0
fields Comma-separated field list to return, e.g. "name,objectid"
geom Whether geometry query true
includegeom Return geometry: when realgeom is false, if count>1 returns bounding rect per entity, if count=1 returns real GeoJSON; when realgeom is true returns GeoJSON per entity true
isContains Contain vs intersect: true=contain, false=intersect (default false). Used when bounds is set false
layername Style name (required). Use stylename from createMapStyle, e.g. api/v1/map/cmd/createMapStyle/yourMapid/v1?geom=true&token=xxx
maxReturnCount Max records to return 50000
realgeom Return real entity geometry GeoJSON. Used with includegeom true
expr Expression
x Point query x
y Point query y
pixelsize Point query pixel size
zoom Current zoom level 1
toMapCoordinate By default query returns Mercator; result is converted to CAD. Set true to return CAD coordinates directly.

Relevant SDK query source in JS:


/**
 * Query entity parameters
 */
export interface IQueryBaseFeatures {
    /** Current zoom level. */
    zoom?: number;
    /** Map ID (empty = current map). */
    mapid?: string;
    /** Map version (empty = current). */
    version?: string;
    /** Layer name (empty = current map layer). */
    layer?: string;
    /** Max records to return. */
    limit?: number;
    /** Comma-separated field list to return, e.g. "name,objectid" */
    fields?: string;
    /** Whether geometry query. */
    geom?: boolean;
    /** GeoJSON simplify tolerance in Mercator; 0 = no simplify. */
    simplifyTolerance?: boolean;
    /** Enable cache (for in-memory maps). */
    useCache?: boolean;
    /** By default returns Mercator; set true to return CAD coordinates. */
    toMapCoordinate?: boolean;
}

/**
 * Point query entity parameters
 */
export interface IPointQueryFeatures extends IQueryBaseFeatures {
    /** Query X. */
    x: number;
    /** Query Y. */
    y: number;
    /** Pixel size. */
    pixelsize?: number;
    /** Condition. */
    condition?: string;
    /** Max geometry bytes to return. */
    maxGeomBytesSize?: number;
    /** Geo length per pixel; if set, overrides zoom-based calculation. */
    pixelToGeoLength?: number;
}

/**
 * Rect query entity parameters
 */
export interface IRectQueryFeatures extends IQueryBaseFeatures {
    /** X1 (omit x1,y1,x2,y2 to query full map). */
    x1?: number;
    /** Y1. */
    y1?: number;
    /** X2. */
    x2?: number;
    /** Y2. */
    y2?: number;
    /** Condition. */
    condition?: string;
    /** Max geometry bytes to return. */
    maxGeomBytesSize?: number;
}

/**
 * Expression query entity parameters
 */
export interface IExprQueryFeatures extends IQueryBaseFeatures {
    /** Expression. */
    expr: string;
    /** Record start position. */
    beginpos?: number;
}

/**
 * Condition query entity parameters
 */
export interface IConditionQueryFeatures extends IQueryBaseFeatures {
    /** Condition. */
    condition: string;
    /** Bounds. */
    bounds?: [number,number,number,number];
    /** Record start position. */
    beginpos?: number;
    /** Include geometry; when realgeom false, multiple results get bbox only, single gets GeoJSON; when realgeom true each gets GeoJSON. */
    includegeom?: boolean;
    /** Return real entity GeoJSON; used with includegeom. */
    realgeom?: boolean;
    /** Contain (true) vs intersect (false) when bounds set; default false. */
    isContains?: boolean;
}
    /**
     * Point query entities
     * @param param Parameters
     * @param cb Callback for each point in result; null = default handling
     */
    async pointQueryFeature(param: IPointQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any> {
        const res = await this.execCommand(
            "queryFeatures",
            {
                querytype: "point",
                zoom: param.zoom ?? 1,
                pixelToGeoLength: param.pixelToGeoLength ?? undefined,
                layername: param?.layer ?? this._cur_map_param?.layer,
                x: param.x,
                y: param.y,
                pixelsize: param.pixelsize ?? 5,
                condition: param.condition ?? undefined,
                maxReturnCount: param.limit ?? undefined,
                maxGeomBytesSize: param.maxGeomBytesSize ?? undefined,
                fields: param.fields ?? "",
                geom: param.geom ?? undefined,
                simplifyTolerance: param.simplifyTolerance ?? undefined,
                useCache: param.useCache,
                toMapCoordinate: param.toMapCoordinate,
            },
            param.mapid,
            param.version
        );
        return this._processQueryResult(res, cb);
    }

    /**
     * Rect query entities
     * @param param Parameters
     * @param cb Callback for each point; null = default handling
     */
    async rectQueryFeature(param: IRectQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any> {
        const res = await this.execCommand(
            "queryFeatures",
            {
                querytype: "rect",
                zoom: param.zoom ?? 1,
                layername: param?.layer ?? this._cur_map_param?.layer,
                x1: param.x1,
                y1: param.y1,
                x2: param.x2,
                y2: param.y2,
                condition: param.condition ?? undefined,
                maxReturnCount: param.limit ?? undefined,
                maxGeomBytesSize: param.maxGeomBytesSize ?? undefined,
                fields: param.fields ?? "",
                geom: param.geom ?? undefined,
                simplifyTolerance: param.simplifyTolerance ?? undefined,
                useCache: param.useCache,
                toMapCoordinate: param.toMapCoordinate,
            },
            param.mapid,
            param.version
        );
        return this._processQueryResult(res, cb);
    }

    /**
     * Expression query entities
     * @param param Parameters
     * @param cb Callback for each point; null = default handling
     */
    async exprQueryFeature(param: IExprQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any> {
        const res = await this.execCommand(
            "queryFeatures",
            {
                querytype: "expresion",
                zoom: param.zoom ?? 1,
                layername: param?.layer ?? this._cur_map_param?.layer,
                expr: param.expr,
                beginpos: param.beginpos,
                maxReturnCount: param.limit ?? undefined,
                limit: param.limit ?? undefined,
                fields: param.fields ?? "",
                useCache: param.useCache ?? false,
                geom: param.geom ?? undefined,
                simplifyTolerance: param.simplifyTolerance ?? undefined,
                toMapCoordinate: param.toMapCoordinate,
            },
            param.mapid,
            param.version
        );
        return this._processQueryResult(res, cb);
    }

    /**
     * Condition query entities
     * @param param Parameters
     * @param cb Callback for each point; null = default handling
     */
    async conditionQueryFeature(param: IConditionQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any> {
        const res = await this.execCommand(
            "queryFeatures",
            {
                querytype: "condition",
                zoom: param.zoom ?? 1,
                layername: param?.layer ?? this._cur_map_param?.layer,
                condition: param.condition,
                beginpos: param.beginpos,
                maxReturnCount: param.limit ?? undefined,
                limit: param.limit ?? undefined,
                includegeom: param.includegeom ?? undefined,
                realgeom: param.realgeom ?? undefined,
                isContains: param.isContains ?? undefined,
                fields: param.fields ?? "",
                bounds: param.bounds ? JSON.stringify(param.bounds) : "",
                geom: param.geom ?? undefined,
                simplifyTolerance: param.simplifyTolerance ?? undefined,
                useCache: param.useCache,
                toMapCoordinate: param.toMapCoordinate,
            },
            param.mapid,
            param.version
        );
        return this._processQueryResult(res, cb);
    }

// _processQueryResult converts returned Mercator coordinates to CAD coordinates. For backend queries returning CAD coordinates directly, set toMapCoordinate to true.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

You can also inspect request parameters via the visual interface:

https://vjmap.com/app/visual/#/query?mapid=sys_zp&version=v1&mapopenway=GeomRender&theme=dark (opens new window) (Replace sys_zp with your mapid)

image-20230524160509120

When testing in Postman, set toMapCoordinate to true to return CAD coordinates directly.

image-20230524160843420

# Switch Layer

Service URL api/v1/map/cmd/switchlayer/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
visibleLayers Array of visible layer indices
darkMode Whether dark theme

# Get Style Layer Name

Service URL api/v1/map/cmd/createMapStyle/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
geom Whether geometry rendering
name Style name
layeron Layer indices to turn on, e.g. [0,1,3]
layeroff Layer indices to turn off, e.g. [2,4]. Use either layeron or layeroff
clipbounds Map clip bounds [x1,y1,x2,y2]. Single number = scale factor
backcolor Background color
lineweight Line weight [1,1,1,1,0]: levels 1–4 on, level 5 off; empty = same as original
expression Expression

# Get Data Bounds of Drawing

Service URL api/v1/map/cmd/getDataBounds/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
(none)

# Get Map Thumbnail

Service URL api/v1/map/cmd/thumbnail/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
width Width in pixels
height Height in pixels
darkTheme Dark theme; if true, image is inverted (black to white)

# WMS Tile URL

Service URL api/v1/map/cmd/wms/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
layers Layer name (empty = current map layer).
bbox Bounds, default {bbox-epsg-3857}. For CAD extent without conversion, use CAD bounds and leave srs, crs, mapbounds empty.
srs Current CRS, default EPSG:3857
crs CAD map CRS; empty = from metadata. Can be proj4 string
mapbounds Geographic bounds; when set, srs is ignored
width Tile width in pixels
height Tile height in pixels
transparent Background when opaque; default white. Must be rgb(r,g,b) or rgba(r,g,b,a), a=255 for opaque.
backgroundColor Background color when not transparent
fourParameter Four-parameter (x offset, y offset, scale, rotation in radians), optional
isInverseFourParamter Use inverse of four-parameter, default false
mvt Whether vector tiles
useImageRotate Consider rotation for CRS conversion. Default auto
imageProcessAlg Image processing for rotation: 1 or 2, default auto
webMapType Web base map type: WGS84 (e.g. Tianditu, OSM), GCJ02 (e.g. Amap, Tencent), BD09LL/Bd09MC (Baidu)

JS source:


/**
 * WMS service URL parameters
 */
export interface IWmsTileUrl {
    /** Map ID (empty = current); array = request multiple. */
    mapid?: string | string[];
    /** Map version (empty = current). */
    version?: string | string[];
    /** Layer name (empty = current map layer). */
    layers?: string | string[];
    /** Bounds, default {bbox-epsg-3857}. For CAD extent without conversion use CAD bounds and leave srs, crs, mapbounds empty. */
    bbox?: string;
    /** Current CRS, default EPSG:3857. */
    srs?: string;
    /** CAD map CRS; empty = from metadata. Can be proj4 string. */
    crs?: string | string[];
    /** Geographic bounds; when set, srs is ignored. */
    mapbounds?: string;
    /** Width. */
    width?: number;
    /** Height. */
    height?: number;
    /** Transparent. */
    transparent?: boolean;
    /** Background when opaque; default white. rgb(r,g,b) or rgba(r,g,b,a), a=255 for opaque. */
    backgroundColor?: string;
    /** Four-parameter (x, y offset, scale, rotation rad), optional. */
    fourParameter?: string | string[];
    /** Use inverse four-parameter, default false. */
    isInverseFourParamter?:  boolean | boolean[];
    /** Vector tiles. */
    mvt?: boolean;
    /** Consider rotation for CRS conversion; default auto. */
    useImageRotate?: boolean;
    /** Image processing for rotation: 1 or 2, default auto. */
    imageProcessAlg?: number;
    /** Web base map type: WGS84, GCJ02, BD09LL, BD09MC. */
    webMapType?: "WGS84" | "GCJ02" | "BD09LL" | "BD09MC"
}
    wmsTileUrl(param: IWmsTileUrl): string {
        const mapid = param.mapid ?? this._cur_map_param?.mapid;
        const version = param.version ?? ((param.mapid == this._cur_map_param?.mapid) ? this._cur_map_param?.version : "_") ?? "_";
        const layers = param.layers ?? this._cur_map_param?.layer;
        const bbox = param.bbox ?? "{bbox-epsg-3857}";
        const srs = param.srs ?? "EPSG:3857";// base map CRS
        let crs = param.crs ?? ""; // CAD map CRS
        if (crs.indexOf("+") >= 0) {
            // proj4 string
            // @ts-ignore
            crs = encodeURIComponent(crs);
        }
        const mapbounds = param.mapbounds ?? "";
        const width = param.width ?? 256;
        const height = param.height ?? 256;
        const transparent = param.transparent ?? true;
        const fourParameter = param.fourParameter ?? "";
        const isInverseFourParamter = param.isInverseFourParamter === true ? `&isInverseFourParamter=true` : "";
        const mvt = param.mvt === true ? ".mvt" : ""
        const useImageRotate = param.useImageRotate === true ? `&useImageRotate=true` : "";
        const imageProcessAlg = isNumber(param.imageProcessAlg) ? `&imageProcessAlg=${param.imageProcessAlg}` : "";
        const webMapType = param.webMapType ? `&webMapType=${param.webMapType}` : "";
        const backgroundColor = (param.backgroundColor && !transparent) ? `&backgroundColor=${param.backgroundColor}` : "";
        if (!Array.isArray(mapid)) {
            // Single map WMS request
            return  `${this._url("cmd")}/wms/${mapid}/${version}${mvt}` +
                `?mapbounds=${mapbounds}${bbox ? "&bbox=": ""}${bbox}&format=image/png&service=WMS&request=GetMap&srs=${srs}&transparent=${transparent}&width=${width}&height=${height}&layers=${layers}&crs=${crs}&fourParameter=${fourParameter}${isInverseFourParamter}${useImageRotate}${imageProcessAlg}${webMapType}${backgroundColor}&token=${this.accessToken}`
        } else {
            // Multiple maps WMS request
            //&layers=${layers}&crs=${crs}&fourParameter=${fourParameter}
            //${mapid}/${version}
            let mapidArr = mapid;
            let versionArr = Array.isArray(version) && version.length == mapidArr.length ?  version : mapidArr.map(m => version ?? "_")
            let layersArr = Array.isArray(layers) && layers.length == mapidArr.length ?  layers : mapidArr.map(m => layers ?? "")
            let crsArr = Array.isArray(crs) && crs.length == mapidArr.length ?  crs : mapidArr.map(m => crs ?? "")
            let fourParameterArr = Array.isArray(fourParameter) && fourParameter.length == mapidArr.length ?  fourParameter : mapidArr.map(m => fourParameter ?? "")
            let isInverseFourParamterArr = Array.isArray(isInverseFourParamter) && isInverseFourParamter.length == mapidArr.length ?  isInverseFourParamter : mapidArr.map(m => isInverseFourParamter ?? "")
            let param = `bbox=${bbox}&mapbounds=${mapbounds}&format=image/png&service=WMS&request=GetMap&srs=${srs}&transparent=${transparent}&width=${width}&height=${height}`
            let arrayParam = `mapid=${mapidArr.join("_,")}&version=${versionArr.join("_,")}&layers=${layersArr.join("_,")}&crs=${crsArr.join("_,")}&fourParameter=${fourParameterArr.join("_,")}&isInverseFourParamter=${isInverseFourParamterArr.join("_,")}`
            if (mapidArr.length == 1) {
               return `${this._url("cmd")}/wms/${mapidArr[0]}/${versionArr[0]}${mvt}` +
                    `?mapbounds=${mapbounds}${bbox ? "&bbox=": ""}${bbox}&format=image/png&service=WMS&request=GetMap&srs=${srs}&transparent=${transparent}&width=${width}&height=${height}&layers=${layersArr[0]}&crs=${crsArr[0]}&fourParameter=${fourParameterArr[0]}&isInverseFourParamter=${isInverseFourParamterArr[0]}${useImageRotate}${imageProcessAlg}${webMapType}${backgroundColor}&token=${this.accessToken}`
            } else {
                return `${this._svr_url_service}wms?${param}&${arrayParam}${useImageRotate}${imageProcessAlg}${webMapType}${backgroundColor}&token=${this.accessToken}`;
            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

# Delete Map

Service URL api/v1/map/cmd/deletemap/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version; use "*" to delete all versions
Request Parameter Parameter Description Parameter Example
retainVersionMaxCount When deleting all versions, keep this many latest (e.g. 10 versions, 3 = keep latest 3)

# Rename Map

Service URL api/v1/map/cmd/deletemap/${mapid}/_
Request Type Get or Post
Service Description mapid: map id
Request Parameter Parameter Description Parameter Example
newMapId New map id

# Clear Map Geometry and Tile Cache

Service URL api/v1/map/cmd/clearCacheTiles/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
(none)

# Clear Map Tile Cache

Service URL api/v1/map/cmd/clearCacheStyles/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
(none)

# Delete Map Style

Service URL api/v1/map/cmd/deletestyle/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
styleid Style id
onlycleardata Only clear data

# Delete Map Cache

Service URL api/v1/map/cmd/deletecache/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
key Cache key prefix

# Get System Run Status

Service URL api/v1/map/cmd/runstatus/${mapid}/${version}
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
detail Whether to return detailed data

# Compose New Map

Service URL api/v1/map/cmd/composeNewMap/_null/v1
Request Type Get or Post
Service Description
Request Parameter Parameter Description Parameter Example
mapid Map ID
version Map version
clipbounds Map clip bounds [x1,y1,x2,y2]; empty = no clip
selByCrossing Contain vs intersect (default false = contain, true = intersect)
fourParameter Four-parameter (x, y offset, scale, rotation rad), optional
isInverseFourParamter Use inverse four-parameter, default false
layers Layer names to show; empty = all
layerPrefix Layer name prefix for new map
layerSuffix Layer name suffix for new map
savefilename Output filename; empty = auto from params
purge Purge after compose to reduce DWG size
cadVersion Export CAD version; * = current

JS source:

/**
 * Compose new map parameters
 */
export interface IComposeNewMap {
    /** Map ID. */
    mapid: string;
    /** Map version (empty = current). */
    version?: string;
    /** Clip bounds [x1,y1,x2,y2]; empty = no clip. */
    clipbounds?: [number, number, number, number];
    /** Contain (false) vs intersect (true). */
    selByCrossing?: boolean;
    /** Four-parameter (x, y offset, scale, rotation rad), optional. */
    fourParameter?:  [number, number, number, number];
    /** Use inverse four-parameter, default false. */
    isInverseFourParamter?:  boolean;
    /** Layer names to show; empty = all. */
    layers?: string[];
    /** Layer name prefix for new map. */
    layerPrefix?: string;
    /** Layer name suffix for new map. */
    layerSuffix?: string;
    /** Output filename; empty = auto from params. */
    savefilename?: string;
    /** Purge after compose to reduce DWG size. */
    purge?: boolean
    /** Export CAD version; * = current. */
    cadVersion?: string | "*" | "cad2000" | "cad2004" | "cad2007" | "cad2010" | "cad2013"| "cad2018"
}

    /**
     * Compose new map
     * @param param Compose parameters
     * @return {Promise<any>}
     */
    async composeNewMap(param: IComposeNewMap | IComposeNewMap[]) {
        if (!Array.isArray(param)) {
            param = [param] // normalize to array
        }
        let cmdParam: Record<string, any> = {};
        if (param.length > 1) {
            cmdParam['count'] = param.length;
        }

        for(let i = 0; i < param.length; i++) {
            let paramKey = i === 0 ? "" : ((i + 1) + "")
            cmdParam['mapid' + paramKey] = param[i].mapid;
            cmdParam['version' + paramKey] = param[i].version;
            cmdParam['clipBounds' + paramKey] = Array.isArray(param[i].clipbounds) ? JSON.stringify(param[i].clipbounds) : undefined;
            cmdParam['selByCrossing' + paramKey] = param[i].selByCrossing;
            cmdParam['fourParameter' + paramKey] = Array.isArray(param[i].fourParameter) ? JSON.stringify(param[i].fourParameter) : undefined;
            cmdParam['isInverseFourParamter' + paramKey] = param[i].isInverseFourParamter === true ? true : undefined;
            cmdParam['layers' + paramKey] = Array.isArray(param[i].layers) ? JSON.stringify(param[i].layers) : undefined;
            cmdParam['layerPrefix' + paramKey] = param[i].layerPrefix;
            cmdParam['layerSuffix' + paramKey] = param[i].layerSuffix;
            cmdParam['savefilename' + paramKey] = param[i].savefilename;
            cmdParam['purge' + paramKey] = param[i].purge;
            if (param[i].cadVersion) {
                cmdParam['cadVersion' + paramKey] = param[i].cadVersion;
            }
        }
        return await this.execCommand("composeNewMap", cmdParam, "_null", "v1", false);
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# Projection PRJ WKT to Proj4 String

Service URL api/v1/map/cmd/prjWktToPrj4Str//
Request Type Post
Service Description Convert PRJ WKT to proj4 string.
Request Parameter Parameter Description Parameter Example
wkt PRJ file WKT string

# Export Layout to DWG

Service URL api/v1/map/cmd/exportLayout/_null/v1
Request Type Get or Post
Service Description mapid: map id; version: version
Request Parameter Parameter Description Parameter Example
mapid Map ID
version Map version (empty = current)
layoutIndex Layout index; use either layoutIndex or layoutName, layoutIndex takes precedence. Both empty = current DWG layout.
layoutName Layout name. Use either layoutIndex or layoutName. Both empty = current DWG layout.

# Object Match

Service URL api/v1/map/cmd/objectMatch/_null/v1
Request Type Get or Post
Service Description
Request Parameter Parameter Description Parameter Example
mapid Map ID
version Map version (empty = current)
layer Style layer name; empty = determined by selected entities
mapBounds Match extent; default full map
objectIds Entity objectId array, separated by ||
objectBounds Entity bounds
layeron Layers to turn on for match
size Image size for match, default 10000
method "matchTemplate" or "matchPattern"
maxCount Score threshold (0–1), default 0.6
minReduceArea Pyramid size (64–2048), default 256; for matchPattern
canOverlap Allow overlap (default false)
maxOverlap Overlap ratio (0–0.8), default 0.3
toleranceAngle Angle range (-180, 180) for rotation; for matchPattern, default 180
useToleranceRange Use angle range (default false); for matchPattern
tolerance1 Angle range 1 start; for matchPattern
tolerance2 Angle range 1 end; for matchPattern
tolerance3 Angle range 2 start; for matchPattern
tolerance4 Angle range 2 end; for matchPattern

# Get Created Entity Geometry Data

Service URL api/v1/map/cmd/createEntityGeoData/_null/v1
Request Type Get or Post
Service Description
Request Parameter Parameter Description Parameter Example
filedoc File document
mapBounds Drawing bounds; empty = full map
renderAccuracy Render accuracy, default 1. Increase if circles/arcs are not smooth (clears cache and may increase file size and hurt performance)
excludeAttribute Exclude attributes from result (default true)
useZip Use zip compression for result (default true)

# Get All Workspaces

Service URL api/v1/service/getWorkspace
Request Type Get
Service Description

# Workspace Switch

The request URLs above are for the default workspace.

To use a different workspace, change the path prefix:

Replace /api/v1/map/ with /api/v1/workspace/{workspaceName}/

Example: upload URL /api/v1/map/uploads for workspace w1 becomes /api/v1/workspace/w1/uploads

Frontend code to switch workspace:

/**
* Switch to workspace
* @param workspaceName Workspace name
* @return
*/
function  switchWorkspace(workspaceName) {
    workspaceName = workspaceName.trim()
    this._workspaceName = workspaceName;
    if (workspaceName != "") {
        // specified workspace
        this._svr_url_map = this.serverUrl + "workspace/" + workspaceName + "/";
    } else {
        // default workspace
        this._svr_url_map = this.serverUrl + "map/";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Full-Text Search API

# Add Single Document

Service URL /api/v1/service/fullsearch/add
Request Type Post
Request Parameter Parameter Description Parameter Example
document Document with fields: id, map_ver, content, type (1:single-line text, 2:multiline, 3:attribute, 4:block attribute, 5:layer, 6:block name, 7:linetype, 8:hatch, 9:custom), min_x, min_y, max_x, max_y, props (JSON), create_time, workspace, data

# Batch Add Documents

Service URL /api/v1/service/fullsearch/batchAdd
Request Type Post
Request Parameter Parameter Description Parameter Example
documents Document list; each has same fields as document above

# Update Document

Service URL /api/v1/service/fullsearch/update
Request Type Put
Request Parameter Parameter Description Parameter Example
document Document with fields: id, map_ver, content, type (1:single-line text, 2:multiline, 3:attribute, 4:block attribute, 5:layer, 6:block name, 7:linetype, 8:hatch, 9:custom), min_x, min_y, max_x, max_y, props (JSON), create_time, workspace, data

# Delete Document

Service URL /api/v1/service/fullsearch/delete
Request Type Delete
Request Parameter Parameter Description Parameter Example
id Document ID

# Delete Documents by Map Version

Service URL /api/v1/service/fullsearch/deleteByMapver
Request Type Delete
Request Parameter Parameter Description Parameter Example
map_ver Map version
workspace Workspace name

# Batch Delete Documents

Service URL /api/v1/service/fullsearch/batchDelete
Request Type Post
Request Parameter Parameter Description Parameter Example
ids Document ID array
query Query condition
map_ver Map version
workspace Workspace
type Document type
bounding_box Bounding box [minX, minY, maxX, maxY]
time_range Time range

# Delete Documents by ID Prefix

Service URL /api/v1/service/fullsearch/deleteByIDPrefix
Request Type Delete
Request Parameter Parameter Description Parameter Example
id_prefix ID prefix

# Search Documents

Service URL /api/v1/service/fullsearch/search
Request Type Get or Post
Request Parameter Parameter Description Parameter Example
query Search keyword
map_ver Map version (optional, comma-separated e.g. map1,map2_v2)
workspace Workspace (optional, comma-separated; use * for all)
type Document type (optional: single, multiple, range e.g. 1,2,5 or 1-3)
bounding_box Bounding box (optional, "minX,minY,maxX,maxY")
time_range Time range (optional, "start~end" or N days)
limit Results per page
offset Pagination offset
fields Return fields (comma-separated)
facet Aggregate MapVer (true/1 to enable)

# Get Document Count

Service URL /api/v1/service/fullsearch/count
Request Type Get

# Manually Trigger Data Sync

Service URL /api/v1/service/fullsearch/sync
Request Type Get

# Get Workspace Index Status

Service URL /api/v1/service/fullsearch/workspaceStatus
Request Type Get
Request Parameter Parameter Description Parameter Example
workspace Workspace name

# Get Search Suggestions

Service URL /api/v1/service/fullsearch/suggestions
Request Type Get
Request Parameter Parameter Description Parameter Example
prefix Search prefix
map_ver Map version
workspace Workspace
type Document type
limit Max suggestions

# Search Documents by ID Prefix

Service URL /api/v1/service/fullsearch/searchByIDPrefix
Request Type Get or Post
Request Parameter Parameter Description Parameter Example
id_prefix ID prefix
map_ver Map version (optional)
workspace Workspace (optional)
limit Page size
offset Offset
fields Return fields (comma-separated)

# Recognizer API

# Get Recognizer Config List

Service URL /api/v1/service/recognizer/list
Request Type Get
Service Description Get all saved recognizer configs
Request Parameter Parameter Description Parameter Example
(none)

# Delete Recognizer Config

Service URL /api/v1/service/recognizer/delete
Request Type Delete
Service Description Delete specified recognizer config file
Request Parameter Parameter Description Parameter Example
filename Config file name prefix config_20231201_001

# Add Recognizer Config

Service URL /api/v1/service/recognizer/add
Request Type Post
Service Description Save new recognizer config
Request Parameter Parameter Description Parameter Example
name Config name My recognizer config
sameColor Entities must have same color true
sameLayer Entities must be on same layer false
sameTextContent Text content must match false
thumbnail Thumbnail base64 (optional) data:image/png;base64,...
global Global match rules {...}
rules Recognizer rules array [...]

# Get Recognizer Config Detail

Service URL /api/v1/service/recognizer/detail
Request Type Get
Service Description Get recognizer config details
Request Parameter Parameter Description Parameter Example
filenames Config filenames, comma-separated config_20231201_001,config_20231201_002

# Run Object Recognition

Service URL /api/v1/map/cmd/objectDetection/_null/v1
Request Type Get or Post
Service Description Run smart object recognition on map; identify similar entities by config pattern
Request Parameter Parameter Description Parameter Example
mapid Map ID sys_zp
version Map version v1
layer Style layer name default
pattern Pattern config JSON {"name":"test","sameColor":true,"rules":[...]}
patternList Array of pattern configs (alternative to pattern) ["{"name":"config1",...}","{"name":"config2",...}"]
detailedLog Output detailed match info false
bounds Recognition bounds, GeoBounds string -1000,-1000,1000,1000

# Drawing Analysis API

# Extract Center Lines

Service URL /api/v1/map/cmd/extractCenterLines/_null/v1
Request Type Get or Post
Service Description Extract center lines from parallel segments; for pipelines, roads, etc.
Request Parameter Parameter Description Parameter Example
mapid Map ID sys_zp
version Map version v1
layer Style layer name default
geom Geometry rendering true
bounds Extract bounds, coords or polygon -1000,-1000,1000,1000
isContains Contain (true) vs intersect (false) false
minSpaceDistance Min distance array, comma-separated 2.5,5.0
maxSpaceDistance Max distance array, comma-separated 7.5,15.0
collinearTolerance Collinear tolerance 1.0
duplicateTolerance Duplicate point tolerance 0.2
maxGapDistance Max gap to connect segments 15
numDecimalDigits Decimal places 3
minDlMinRatio Min overlap ratio for double lines 0.01
paralleSlopeAngleTolerance Parallel slope angle tolerance (degrees) 1.5
mergeSlopeAngleTolerance Merge center line slope tolerance (degrees) 20
maxCenterMergeDistance Max distance to merge center segments 15
minCenterDistance Min center segment distance 5.1
bConnectGrapLine Connect lines within gap true
bMergeNode Merge endpoints true
bFilterShortLine Filter lines shorter than min distance true
bMergeLine Merge connected lines true
bSaveParalleLineJson Output parallel line coords false
bCenterGeoJson Return center line as GeoJSON false
bExtractLines Output extracted line coords false

# Map Entity Compare

Service URL /api/v1/map/cmd/mapCompare/_null/v1
Request Type Get or Post
Service Description Compare entities between two map versions; returns added, deleted, modified lists
Request Parameter Parameter Description Parameter Example
mapid1 First map ID sys_zp
version1 First map version v1
mapid2 Second map ID sys_zp
version2 Second map version v2

# Map Pixel Compare

Service URL api/v1/map/cmd/mapDiff/_null/v1
Request Type Get or Post
Service Description Compare two maps by pixel
Request Parameter Parameter Description Parameter Example
mapid1 Map 1 ID
version1 Map 1 version (empty = current)
layer1 Map 1 style layer
mapid2 Map 2 ID
version2 Map 2 version (empty = current)
layer2 Map 2 style layer
noCompareNew Do not compare new parts
noCompareDelete Do not compare deleted parts
size Compare size
cellsize Cell size
diffMinAlpha Min diff pixel alpha
diffMinAlpha Min diff transparency
diffMinColor Min diff color

# Map Similarity Analysis

Service URL /api/v1/map/cmd/imageSimilarity/_null/v1
Request Type Get or Post
Service Description Analyze similarity between map and others; returns map IDs sorted by similarity
Request Parameter Parameter Description Parameter Example
mapid Reference map ID sys_zp
version Reference map version v1