Skip to content

How to overlay a 2d dxf dwg to a 3d model

yanzexuan edited this page May 20, 2023 · 4 revisions

We can overlay a 3d dxf to a 3d model, and we can put as many modles/dxfs into one scene as long as there is enough memory for a web page.

If two models/dxfs have exactly the same coordinate system, and the same base point, etc. Simply load them, then their position/scale should be expected.

How to load two models into BimViewer

const model1 = {
    "id": "building1",
    "src": "./demo/models/gltf/building1.gltf"
};
const model2 = {
    "id": "building1_dxf",
    "src": "./demo/models/dxf/building1.dxf"
};
const viewer = new BimViewer({ containerId: "myCanvas" });
await viewer.loadModel(model1);
await viewer.loadModel(model2);

Run the sample page, we can see:

image

But we cannot see the dxf, why? let's continue...

Adjust matrix

A dxf is defined in xy plane, we usually need to apply a matrix in order to overlay it to a 3d model. Because threejs is a right-handed, y-up system. The sample dxf is a plan/floor view, so, we need to make dxf into xz plane. We can do it by a matrix. This is a unit matrix:

[1, 0, 0, 0,
 0, 1, 0, 0,
 0, 0, 1, 0,
 0, 0, 0, 1]

To switch y and z value, we use:

[1, 0, 0, 0,
 0, 0, -1, 0,
 0, 1, 0, 0,
 0, 0, 0, 1]

Further more, we need to convert the y value (for dxf data) to -z in threejs. That's why there is a "-1" in the matrix.

And, as we know the sample dxf is in Milimeter (well, you should know the unit of your file). And the gltf model is in Meter, so we need a scale value: 0.001. So, we get:

[0.001, 0, 0, 0,
 0, 0, -0.001, 0,
 0, 0.001, 0, 0,
 0, 0, 0, 1]

Now, let's try to load the dxf with a matrix:

const model2 = {
    "id": "building1_dxf",
    "src": "./demo/models/dxf/building1.dxf",
    "matrix": [
        [0.001, 0, 0, 0,
        0, 0, -0.001, 0,
        0, 0.001, 0, 0,
        0, 0, 0, 1]
    ],
};

Run example page, we probably still cannot find the dxf data in threejs scene although it is successfully loaded. Notice that the dxf data could be defined with a offset far from origin (0, 0), so we'll need to apply an offset to the matrix. We can open the dxf with a viewer (AutoCAD, etc.) Then check the lower left coner of the data, we can find the coordinate is (1831340, 456910). image

Since it is in Milimeter, it is (1831.340, 456.910) in meter. As y is changed to -z for threejs scene. So the offset should be x: -1831.340, z: 456.910. Then the new matrix is:

[0.001, 0, 0, 0,
 0, 0, -0.001, 0,
 0, 0.001, 0, 0,
 -1831.340, 0, 456.910, 1]

Run the example page again, then we can see this:

image

Let's try to change the elevation of the dxf data for a better view. Of couse, we can also dynamically change its elevation. I'd like to set the elevation to 17, that is about the height of the building.

[0.001, 0, 0, 0,
 0, 0, -0.001, 0,
 0, 0.001, 0, 0,
 -1831.340, 17, 456.910, 1]

Now, it look like:

image

The final sample code

const model1 = {
    "id": "building1",
    "src": "./demo/models/gltf/building1.gltf"
};
const model2 = {
    "id": "building1_dxf",
    "src": "./demo/models/dxf/building1.dxf",
    "matrix": [
        0.001, 0, 0, 0,
        0, 0, -0.001, 0,
        0, 0.001, 0, 0,
        -1831.340, 17, 456.910, 1
    ],
};
const viewer = new BimViewer({ containerId: "myCanvas" });
const fontFiles = ["three/fonts/hztxt.shx", "three/fonts/simplex.shx"];
await viewer.setFont(fontFiles);
const decoderPath = "demo/three/js/libs/draco/gltf/";
viewer.setDracoDecoderPath(decoderPath);
await viewer.loadModel(model1);
await viewer.loadModel(model2);

Overlaying an elevation view dxf with 3d model

It is even more complex to overlay an elevation view. We expect an elevation view to be xz or yz plane in z-up coordinate system. Since threejs is y-up, we need to convert it to xy or zy plane. Here is one more example, here is the final matrix and screenshot:

const model1 = {
    "name": "building2",
    "src": "./demo/models/gltf/building2.glb"
};
const model2 = {
    "id": "building2_elevation_view",
    "src": "./demo/models/dxf/building2_elevation_view.dxf",
    "matrix": [
        0, 0, 0.001, 0, // the dxf is in "mm", and gltf is in "meter", so need to set scale 0.001
        0, 0.001, 0, 0,
        0.001, 0, 0, 0, // swap x and z
        -177, 9921, -3538, 1 // also need to consider the base point
    ]
};

image