# Expression Query
When CAD drawings are opened directly in memory mode, there is no process of converting to a spatial database, so the frontend cannot perform custom queries on backend data via sql. Queries can only be performed through js scripts or through expressions. For expression syntax details, see the document Server-side Rendering Expression Syntax.
Tip
js scripts are easier to understand and get started with, but slightly slower in performance
Expressions are harder to understand and master, but perform better
We recommend using js scripts
# Built-in Variables
| Variable | Description | Type | Example |
|---|---|---|---|
| gInLayerIndex | Current entity layer index | (numeric) | 0 |
| gInObjectId | Current entity object ID | (string) | '283' e.g. gInObjectId=='283' |
| gInFeatureType | Current entity type | (string) | 'AcDbPolyline' e.g. gInFeatureType=='AcDbPolyline' |
| gInLayerName | Current entity layer name | (string) | 'Layer1' e.g. gInLayerName=='Layer1' |
| gInColor | Current entity color | (numeric) | 4278255615 |
| gInColorRed | Current entity color (red component) | (numeric) | 255 |
| gInColorGreen | Current entity color (green component) | (numeric) | 255 |
| gInColorBlue | Current entity color (blue component) | (numeric) | 0 |
| gInColorAlpha | Current entity color (alpha component) | (numeric) | 0 |
| println | Debug output function | ||
| gInExtendMinX | Current entity extent (bottom-right X) | (numeric) | 700.10 |
| gInExtendMinY | Current entity extent (bottom-right Y) | (numeric) | 10.01 |
| gInExtendMaxX | Current entity extent (top-left X) | (numeric) | 800.20 |
| gInExtendMaxY | Current entity extent (top-left Y) | (numeric) | 20.02 |
| gInAttrs1 | Current entity attribute 1 value | (string) s1 linetype | |
| gInAttrs2 | Current entity attribute 2 value | (string) s2 extended dictionary data | |
| gInAttrs3 | Current entity attribute 3 value | (string) s3 varies by entity type | |
| gInAttrs4 | Current entity attribute 4 value | (string) s4 string attribute data, varies by entity type | |
| gInAttrs5 | Current entity attribute 5 value | (string) s5 string attribute data, varies by entity type | |
| gInAttrn6 | Current entity attribute 6 value | (numeric) n1 color index | |
| gInAttrn7 | Current entity attribute 7 value | (numeric) n2 linetype scale | |
| gInAttrn8 | Current entity attribute 8 value | (numeric) n3 line width | |
| gInAttrn9 | Current entity attribute 9 value | (numeric) n4 transparency | |
| gInAttrn10 | Current entity attribute 10 value | (numeric) n5 numeric attribute data, varies by entity type | |
| gInAttrn11 | Current entity attribute 11 value | (numeric) n6 varies by entity type | |
| gInAttrn12 | Current entity attribute 12 value | (numeric) n7 varies by entity type | |
| gInAttrn13 | Current entity attribute 13 value | (numeric) n8 varies by entity type | |
| gInAttrn14 | Current entity attribute 14 value | (numeric) n9 varies by entity type | |
| gInAttrn15 | Current entity attribute 15 value | (numeric) n10 varies by entity type | |
| gInCoordX | Current entity X coordinate array | (numeric array) | [10,20...] gInCoordX[0]=10 |
| gInCoordY | Current entity Y coordinate array | (numeric array) | [10,20...] gInCoordY[0]=10 |
| gInCoordZ | Current entity Z coordinate array | (numeric array) | [10,20...] gInCoordZ[0]=10 |
| gInCoordCount | Current entity coordinate count | (numeric) | 2 |
| gOutColorRed | Output color (red component) (modify current entity color) | (numeric) | 255, e.g. gOutColorRed := 255; means all levels have red component 255; can also be array, e.g. gOutColorRed[0] := 122;gOutColorRed[5] := 200; means levels 1-4 have red 122, level 5+ has red 200 |
| gOutColorGreen | Output color (green component) (modify current entity color) | (numeric) | 255, same usage as above |
| gOutColorBlue | Output color (blue component) (modify current entity color) | (numeric) | 255, same usage as above |
| gOutColorAlpha | Output color (alpha component) (modify current entity color) | (numeric) | 255, same usage as above |
| gOutLineWidth | Output line width (modify current entity line width) | (numeric) | 3, same usage as above |
| gOutVisible | Output visibility (modify current entity visibility) | (numeric) | 1 or 0, same usage as above |
| gOutReturn | 0 do not add to selection set; 1 add to selection set |
# Supported CAD Entity Types
| Class Name | Description | Type Value |
|---|---|---|
| AcDbLine | Line | 1 |
| AcDbPolyline | Polyline | 2 |
| AcDb2dPolyline | 2D Polyline | 3 |
| AcDb3dPolyline | 3D Polyline | 4 |
| AcDbSpline | Spline | 5 |
| AcDbArc | Arc | 6 |
| AcDbCircle | Circle | 7 |
| AcDbEllipse | Ellipse | 8 |
| AcDbCurve | Curve | 9 |
| AcDbBlockReference | Block Reference | 10 |
| AcDbHatch | Hatch | 11 |
| AcDbMText | Multiline Text | 12 |
| AcDbText | Single-line Text | 13 |
| AcDbShape | Shape | 14 |
| AcDbRasterImage | Raster Image | 15 |
| AcDbWipeout | Wipeout | 16 |
| AcDb2LineAngularDimension | Angular Dimension [two lines] | 17 |
| AcDb3PointAngularDimension | Angular Dimension [three points] | 18 |
| AcDbAlignedDimension | Aligned Dimension | 19 |
| AcDbArcDimension | Arc Dimension | 20 |
| AcDbDiametricDimension | Diametric Dimension | 21 |
| AcDbOrdinateDimension | Ordinate Dimension | 22 |
| AcDbRadialDimension | Radial Dimension | 23 |
| AcDbRadialDimensionLarge | Radial Dimension Large | 24 |
| AcDbRotatedDimension | Rotated Dimension | 25 |
| AcDbAttributeDefinition | Attribute Definition | 26 |
| AcDbAttribute | Block Attribute | 27 |
| AcDbTable | Table | 28 |
| AcDbMLeader | MLeader | 29 |
| AcDbRegion | Region | 30 |
| AcDbPolyFaceMesh | Polyface Mesh | 31 |
| AcDbPolygonMesh | Polygon Mesh | 32 |
| AcDbSurface | Surface | 33 |
| AcDb3dSolid | 3D Solid | 34 |
| AcDbFace | 3D Face | 35 |
| AcDbSolid | Solid | 36 |
# Expression Examples
Query all lines in the drawing
js
return gInFeatureType=='AcDbLine'
Query all 3D polylines with layer name "Layer1" in the drawing
return (gInFeatureType=='AcDb3dPolyline' && gInLayerName=='Layer1')
Query red single-line text in the drawing
return (gInFeatureType=='AcDbText' && gInColorRed==255 && gInColorGreen==0 && gInColorBlue==0)
Query entity with objectid of 9BE in the drawing
return gInObjectId=='9BE'
Query all text in the drawing (single-line text, multiline text, attribute definition, block attribute)
return (gInFeatureType=='AcDbText' || gInFeatureType=='AcDbMText' || gInFeatureType=='AcDbAttributeDefinition' || gInFeatureType=='AcDbAttribute')
Query all block entities in the drawing
return gInFeatureType=='AcDbBlockReference'
Query lines with length 10 in the drawing
return (gInFeatureType=='AcDbLine' && gInAttrn11 == 10)
Query circles with radius 5 in the drawing
return (gInFeatureType=='AcDbCircle' && gInAttrn12 == 5)
Query all polylines in the drawing with layer "grid lines" and coordinate x greater than 10
return (gInFeatureType == 'AcDbPolyline' && gInLayerName == 'grid lines' && gInExtendMinX >= 10)
# Query Method
/**
* Expression query for entities
* @param param Parameters
* @param cb Callback for processing each point in the result. If null is returned, the default handler is used
*/
exprQueryFeature(param: IExprQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any>;
/**
* Expression query entity parameters
*/
export interface IExprQueryFeatures extends IQueryBaseFeatures {
/** Expression. */
expr: string;
/** Record start position. */
beginpos?: number;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
When writing expressions, you need to return based on condition evaluation. Format:
return true; // or return false;
For example, to query all block entities in the drawing, the expression is:
return gInFeatureType == 'AcDbBlockReference'
Query usage:
let query = await svc.exprQueryFeature({
// Expression syntax
// expr: `gOutReturn := if((gInFeatureType == 'AcDbPolyline' and gInLayerName == 'grid lines' and gInExtendMinX >= ${center.x} ), 1, 0);`,
// Now also supports js syntax
// expr: `if (gInFeatureType == 'AcDbPolyline' && gInLayerName == 'grid lines' && gInExtendMinX >= ${center.x} ) {
// return true;
// } else {
// return false;
// }`,
// Filter all block entities (expression syntax)
// expr: `gOutReturn := if((gInFeatureType == 'AcDbBlockReference'), 1, 0);`,
// Filter all block entities (js syntax)
expr: `return gInFeatureType == 'AcDbBlockReference'`,
fields: "objectid,blockname,envelop",
useCache: true,
limit: 1000000 // Large value, equivalent to finding all
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Combining Expression Query and SQL Query
View online demo: Multiple queries for maximum sub-entity area of block objects (opens new window)
// --Multiple queries for maximum sub-entity area of block objects--Query the entity with the largest area in blocks, first via expression query, then via condition query. Analyze results together
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
let res = await svc.openMap({
mapid: env.exampleMapId,
mapopenway: vjmap.MapOpenWay.GeomRender, // Open in geometry rendering mode
style: vjmap.openMapDarkStyle()
})
if (res.error) {
message.error(res.error)
}
let mapExtent = vjmap.GeoBounds.fromString(res.bounds);
let prj = new vjmap.GeoProjection(mapExtent);
let center = mapExtent.center();
let map = new vjmap.Map({
container: 'map', // container ID
style: svc.rasterStyle(),
center: prj.toLngLat(center),
zoom: 2,
renderWorldCopies: false
});
map.attach(svc, prj);
map.fitMapBounds();
map.addControl(new vjmap.NavigationControl());
map.addControl(new vjmap.MousePositionControl({showZoom: true}));
// let blockNames = ["M_F13", "_AXISO"]; // Block name list to find. Block names can be found in the cloud management platform by clicking a block entity and checking blockname in the right-side properties
const handleQuery= async () => {
let query = await svc.exprQueryFeature({
expr: `return gInFeatureType == 'AcDbBlockReference'`,
fields: "objectid,blockname,layername,positon,rotate,scaleX,scaleY,scaleZ", // Empty means all fields
geom: false, // Memory mode
useCache: true,
limit: 1000000 // Large value, equivalent to finding all
})
if (query.error) {
message.error(query.error)
return
}
// Filter results by block name
// let findBlockName = new Set(blockNames);
let objectIds = new Set(); // Block object objectid values
let blockEntities = [];
for(let i = 0; i < query.result.length; i++) {
let blockname = query.result[i].blockname;
// if (!findBlockName.has(blockname)) {
// If not in the target list
// continue
// }
blockEntities.push(query.result[i])
objectIds.add(query.result[i].objectid)
}
// Below, condition query for specific sub-entities contained in all blocks by objectid. This data cannot be obtained via memory query. Only after geometry processing decomposes blocks into individual sub-entities can condition query be used
// In condition query, sub-entities of the same block all have objectid prefixed with that block's objectid_
// Entity id
// Block objectid naming rule: block_id_referenced_block_def_id1_referenced_block_def_id2(may have multiple)_entity_id_#;
// Table naming rule: objectid naming rule: block_id_referenced_block_def_id1_referenced_block_def_id2(may have multiple)_entity_id_@;
// Group objectid naming rule: $entity_id_element_index_in_entity$group_id;
// Build sql condition, query all block objectid_ prefixed at once for efficiency
// For fuzzy search, % can be used as wildcard in like. % defines wildcards before/after the pattern. like 'k%' finds strings ending with 'k'
let condtionIds = Array.from(objectIds).map(id => `objectid like '${id}_%' `).join(" or ") // Concatenate all matching ids
let condQuery = await svc.conditionQueryFeature({
condition: condtionIds, // objectid matching the above condition
fields: "objectid,area",
geom: true,
limit: 100000 // Set large, equivalent to getting all. Default 100 if not specified
})
if (query.error) {
message.error(query.error)
return
}
let blockFeatures = []
for(let i = 0; i < condQuery.result.length; i++) {
let item = condQuery.result[i];
blockFeatures.push(item)
}
// Find related entities under all blocks, find the sub-entity with maximum area
let showDatas = []
for(let block of blockEntities) {
// All starting with block objectid_ are sub-entities of that block
let blockFeature = blockFeatures.filter(b => b.objectid.indexOf(block.objectid + "_") === 0)
let maxArea = Math.max(...blockFeature.filter(b => b.area).map(d => d.area))
showDatas.push({
...block,
area: maxArea
})
}
console.table(showDatas)
message.info(`Query result count: ${blockEntities.length} Press F12 to view console for details`);
};
handleQuery();
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