---
title: Create Drawing Examples
source: https://vjmap.com/en/guide/createMap.html
---

# Create Drawing Examples

## Generate CAD Engineering Section Drawing from Frontend Data


### Effect

![datatodwg.gif](https://vjmap.com/blogimages/datatodwg.gif)

### What Features Does It Support?

- Supports creation of 27 CAD entity types, such as lines, text, hatches, etc.
- Supports modify, clone, and delete operations on entities in DWG drawings
- Supports creating CAD layers, linetypes, block definitions, and text styles
- Supports copying entities from external drawings into the current CAD drawing
- Supports creation and setting of block attribute text
- Created CAD geometry can be displayed directly in the frontend as GeoJSON, with selection and move support
- Created CAD geometry can be displayed in the frontend with click-to-show entity type and attributes
- Can export to DWG format

### Implementation Principle

![image-20230303202058333](https://vjmap.com/blogimages/image-20230303202058333.png)

(1) Use templates for constant elements such as legends. Copy these entities directly when creating the drawing. For title blocks, insert from external drawings; fields that need to be edited (e.g. drafter, date) can be created as block attribute text and set during creation. The section drawing template above comes from these two template drawings.

Section drawing template: ![image-20230303202523238](https://vjmap.com/blogimages/image-20230303202523238.png)

[View section drawing template online](https://vjmap.com/app/cloud/#/map/template_sect?version=v1&mapopenway=Memory&vector=false)

Title block template: (Unit and date are block attribute text; values can be set when inserting)

![image-20230303202615419](https://vjmap.com/blogimages/image-20230303202615419.png)

[View title block template online](https://vjmap.com/app/cloud/#/map/template_tk?version=v1&mapopenway=Memory&vector=false)

(2) Obtain the drawing data to create. The example uses simulated data.

(3) Create the relevant entities using the CAD entity creation methods provided by the VJMap [https://vjmap.com/](https://vjmap.com/) SDK.
  Supported entity types include DbLine (line), DbCurve (curve), Db2dPolyline (2D polyline), Db3dPolyline (3D polyline), DbPolyline (polyline), BlockReference (block reference), DbArc (arc), DbCircle (circle), DbEllipse (ellipse), DbHatch (hatch), Text (single-line text), DbMText (multiline text), RasterImage (raster image), DbShape (shape), Spline (spline), Wipeout (wipeout), Dimension (dimension), Db2LineAngularDimension (angular dimension [two lines]), Db3PointAngularDimension (angular dimension [three points]), DbAlignedDimension (aligned dimension), DbArcDimension (arc dimension), DbDiametricDimension (diametric dimension), DbOrdinateDimension (ordinate dimension), DbRadialDimension (radial dimension), DbRadialDimensionLarge (radial dimension with leader), DbRotatedDimension (rotated dimension), AcDbAttributeDefinition (attribute definition), AcDbAttribute (block attribute), DbLayer (layer), DbTextStyle (text style), DbDimStyle (dimension style), DbLinetypeStyle (linetype style), DbBlock (block definition), DbDocument (database document).

  Tips to reduce code:
  - Tip 1: Copy entities from the template and modify their properties. This reduces parameters and code.
  - Tip 2: For repeated objects, create blocks and define variable text as block attributes. Then create block references repeatedly and modify the attribute text.

(4) Build a JSON object from the created data and call the VJMap service to create the DWG drawing in the backend.

(5) Return the created DWG data to the frontend as GeoJSON or GIS tiles. For small drawings, GeoJSON works well. For large drawings, GeoJSON can be slow and affect rendering; use GIS raster or vector tiles instead.


### Online Demo

[https://vjmap.com/demo/#/demo/map/comprehensive/03datatodwgmap](https://vjmap.com/demo/#/demo/map/comprehensive/03datatodwgmap)


## Auto-Generate from Template Data

[Auto-generate and export DWG from a CAD template using data](https://vjmap.com/demo/#/demo/map/service/05ztpldatanewmap)

CAD template: [View CAD template online](https://vjmap.com/app/cloud/#/map/sys_drawtemplate?version=v1&mapopenway=Memory&vector=false)

![image-20240924210431612](https://vjmap.com/blogimages/image-202409242104659.png)


<mapFrameEx>
<pre>
// --Auto-generate from template data--Auto-generate and export DWG from a CAD template using data
// Template map ID and version
let templateId = "sys_drawtemplate";
let templateSecVersion = "v1";
let svc = new vjmap.Service(env.serviceUrl, env.accessToken);
// Note: objectids below can be obtained by:
// Opening the template in VJMap Cloud Platform in Memory mode, clicking the entity, and reading the object value in the attributes panel
// Or opening the template in Geometry Rendering mode, clicking the entity, and reading the object value in the attributes panel. For block entities (objectid with multiple _), use the string before the first _
let symbols = {
    "symbol1": "8F9",// symbol1 objectid
    "symbol2": "92A" ,// symbol2 objectid
}
let lineObjectId = "905"; // line objectid
let arrowObjectId = "909"; // arrow objectid
let textObjectId = "8FA"; // text objectid
// Mock data
const mockData = (num) => {
    num = num || 5;
    let lines = []
    for(let i = 0; i &lt;  num; i++) {
        let items = {
            points: [],
            textColor: vjmap.randomColor(),
            lineColor: vjmap.randomColor(),
            arrowColor: vjmap.randomColor()
        }
        for(let k = 0; k &lt;  3; k++) {
            items.points.push({
                symbol: (k % 2 == 0) ? "symbol1" : "symbol2", // Mock: even points use symbol1, odd use symbol2
                text: "CY" + vjmap.randInt(0, 1000), // Random text value
                position: [vjmap.randInt(-50, 50), vjmap.randInt(-50, 50)],
                symbolColor: vjmap.randomColor()
            })
        }
        lines.push(items);
    }
    return lines
}
// Create drawing
const createDoc = async (Data) => {
    // Get drawing data
    let drawData = Data;
    let doc = new vjmap.DbDocument();
    // Data source
    doc.from = `${templateId}/${templateSecVersion}`;
    // Clear all data from source (this template does not need clearing, used as-is)
    doc.isClearFromDb = true;
    let entitys = [];
    // All lines
    for(let ln = 0; ln &lt;  drawData.length; ln++) {
        let lineItem = drawData[ln];
        let textColor = lineItem.textColor; // Text color
        let lineColor = lineItem.lineColor; // Line color
        let arrowColor = lineItem.arrowColor; // Arrow color
        // All points on the line
        for(let pt = 0; pt &lt;  lineItem.points.length; pt++) {
            let point = lineItem.points[pt];
            entitys.push(new vjmap.DbBlockReference({
                cloneObjectId: symbols[point.symbol],
                position: point.position,
                color: vjmap.htmlColorToEntColor(point.symbolColor)
            }))
            entitys.push(new vjmap.DbText({
                cloneObjectId: textObjectId,
                position: [point.position[0], point.position[1]-0.5],
                horizontalMode: vjmap.DbTextHorzMode.kTextCenter, // kTextCenter
                verticalMode: vjmap.DbTextVertMode.kTextTop, // kTextVertMid,
                color: vjmap.htmlColorToEntColor(textColor)
            }))
            if (pt != 0) {
                // Create line between two points
                let startPt = lineItem.points[pt - 1].position;
                let endPt = lineItem.points[pt].position;
                entitys.push(new vjmap.Db2dPolyline({
                    cloneObjectId: lineObjectId,
                    points: [startPt, endPt],
                    color: vjmap.htmlColorToEntColor(lineColor)
                }))
                // Create arrow at midpoint
                let midPt = [(startPt[0] + endPt[0]) / 2.0, (startPt[1] + endPt[1]) / 2.0];
                entitys.push(new vjmap.DbBlockReference({
                    cloneObjectId: arrowObjectId,
                    position: midPt,
                    // Rotation
                    matrix: [
                        {
                            op: "rotate", // Rotate
                            angle: vjmap.geoPoint(startPt).angleTo(vjmap.geoPoint(endPt)), // Radians
                            origin: midPt // Rotation center
                        }
                    ],
                    color: vjmap.htmlColorToEntColor(arrowColor)
                }))
                let arrowTextPoint = [midPt[0], midPt[1] + 1];
                let arrowTextAngle = vjmap.geoPoint(startPt).angleTo(vjmap.geoPoint(endPt));
                if (arrowTextAngle > Math.PI / 2 && arrowTextAngle &lt;  Math.PI * 3 / 2 ) {
                    // Keep text upright
                    arrowTextAngle += Math.PI
                }
                // Text above arrow
                entitys.push(new vjmap.DbText({
                    cloneObjectId: textObjectId,
                    position: arrowTextPoint,
                    horizontalMode: vjmap.DbTextHorzMode.kTextCenter, // kTextCenter
                    verticalMode: vjmap.DbTextVertMode.kTextVertMid, // kTextVertMid,
                    color: vjmap.htmlColorToEntColor(arrowColor),
                    // Rotation
                    matrix: [
                        {
                            op: "rotate", // Rotate
                            angle: arrowTextAngle, // Radians
                            origin: arrowTextPoint // Rotation center
                        }
                    ],
                }))
            }
        }
    }
    doc.entitys = entitys;
    return doc;
}
// Set an initial bounds for the map (exact values do not matter). Final DWG export will compute real bounds from entity coordinates.
let mapBounds = '[-10000,-10000,10000,10000]'
let mapExtent = vjmap.GeoBounds.fromString(mapBounds);
mapExtent = mapExtent.square(); // Convert to square
svc.setCurrentMapParam({
    darkMode: true, // Set dark mode since no map opened yet
    bounds: mapExtent.toString()
})
// Create coordinate system
let prj = new vjmap.GeoProjection(mapExtent);
// Create map object
let map = new vjmap.Map({
    container: 'map', // container ID
    style: {
        version: svc.styleVersion(),
        glyphs: svc.glyphsUrl(),
        sources: {},
        layers: []
    },// Vector tile style
    center: [0,0], // Center
    zoom: 2,
    renderWorldCopies: false
});
// Attach service and projection to map
map.attach(svc, prj);
// Fit map to bounds
map.fitMapBounds();
await map.onLoad();
// Create geometry data
const createGeomData = async (map, doc) => {
    let svc = map.getService();
    let res = await svc.cmdCreateEntitiesGeomData({
        filedoc: JSON.stringify(doc)
    });
    if (res.error) {
        message.error(res.error);
        return {
            type: "FeatureCollection",
            features: []
        };
    }
    if (res.metadata && res.metadata.mapBounds) {
        // If metadata contains map bounds, update map extent
        map.updateMapExtent(res.metadata.mapBounds);
    }
    const features = [];
    if (res && res.result && res.result.length > 0) {
        for (let ent of res.result) {
            if (ent.geom && ent.geom.geometries) {
                let clr = map.entColorToHtmlColor(ent.color); // Entity color to HTML color
                let featureAttr = {};
                // Distinguish line and polygon colors for composite entities
                if (ent.isPolygon) {
                    featureAttr.color = clr; // Fill color, polygons only
                    featureAttr.noneOutline = true; // No polygon outline, polygons only
                } else {
                    featureAttr.color = clr; // Color
                    featureAttr.line_width = ent.lineWidth; // Line width
                }
                for(let g = 0; g &lt;  ent.geom.geometries.length; g++) {
                    if (ent.geom.geometries[g].type == "Point") {
                        // Convert to line with same start and end
                        ent.geom.geometries[g].type = "LineString";
                        ent.geom.geometries[g].coordinates = [
                            ent.geom.geometries[g].coordinates, // Start
                            ent.geom.geometries[g].coordinates // End
                        ]
                    }
                }
                let ft = {
                    id: vjmap.RandomID(10),
                    type: "Feature",
                    properties: {
                        objectid: ent.objectid,
                        opacity: ent.alpha / 255,
                        ...featureAttr,
                    }
                }
                if (ent.geom.geometries.length == 1) {
                    features.push({
                        ...ft,
                        geometry: ent.geom.geometries[0],
                    });
                } else {
                    features.push({
                        ...ft,
                        geometry: {
                            geometries: ent.geom.geometries,
                            type: "GeometryCollection"
                        },
                    });
                }
            }
        }
    }
    return {
        type: "FeatureCollection",
        features: features,
    };
};
// Clear previous map data
const clearMapData = () => {
    svc.setCurrentMapParam({
        darkMode: true, // Set dark mode since no map opened yet
        bounds: mapExtent.toString()
    })
    map.disableLayerClickHighlight();
    map.removeDrawLayer();
    let sources = map.getStyle().sources;
    for(let source in sources) {
        map.removeSourceEx(source);
    }
}
// Create map with data
const createDataMap = async (doc) => {
    clearMapData();
    let geojson = await createGeomData(map, doc);
    map.getDrawLayer().set(geojson);
}
// Create DWG map
const createDwgMap = async (doc) => {
    // Clear previous drawing first
    clearMapData();
    // js code
    let res = await svc.updateMap({
        // Get temporary map id (temporary maps auto-delete when expired)
        mapid: vjmap.getTempMapId(1), // Temp map auto-delete time in minutes when not viewed. Default 30
        filedoc: JSON.stringify(doc),
        mapopenway: vjmap.MapOpenWay.Memory,
        style: {
            backcolor: 0 // Set to 0xFFFFFF if div background is light
        }
    })
    if (res.error) {
        message.error(res.error)
    }
    await map.switchMap(res);
}
let curDoc;
const exportDwgOpen = async () => {
    if (!curDoc) return;
    const mapid = 'exportdwgmap';
    let res = await svc.updateMap({
        mapid: mapid,
        filedoc: JSON.stringify(curDoc),
        mapopenway: vjmap.MapOpenWay.Memory,
        style: {
            backcolor: 0 // Set to 0xFFFFFF if div background is light
        }
    })
    if (res.error) {
        message.error(res.error)
    } else{
        window.open(`https://vjmap.com/app/cloud/#/map/${res.mapid}?version=${res.version}&mapopenway=Memory&vector=false`)
    }
}
const creatDataMap = async () => {
    let Data = mockData(5);
    const doc = await createDoc(Data);
    await createDataMap(doc);
    map.fitMapBounds();
    curDoc = doc;
}
const creatDwgMap = async () => {
    let Data = mockData(15);
    const doc = await createDoc(Data);
    await createDwgMap(doc);
    map.fitMapBounds();
    // Highlight on click (elements highlight when clicked)
    map.enableLayerClickHighlight(svc, e => {
        if (!e) return;
        let msg = {
            content: `type: ${e.name}, id: ${e.objectid}, layer: ${e.layerindex}`,
            key: "layerclick",
            duration: 5
        }
        e && message.info(msg);
    })
    curDoc = doc;
}
// Generate random drawing
creatDataMap();
const mousePositionControl = new vjmap.MousePositionControl();
map.addControl(mousePositionControl, "bottom-left");
</pre>
</mapFrameEx>
<br/>
<br/>
