Black Lives Matter. Please consider donating to Black Girls Code today.
https://www.blackgirlscode.com

View 3D/CAD data

I wonder if there are any modules/plugins/examples for Dash to view CAD files like OBJ, DXF or SKP? I am also interested in visualizing data on the Cad/3D files.
/Max

There isn’t a native CAD viewer in Dash yet, but here are some other options:

Just curious, what’s your particular use case for using Dash to do this?

1 Like

Thanks a lot. I am involved in a project where we want to visualize 3D Rhino grasshopper simulations (daylight, energy performance and thermal comfort) combined with CAD geometries to optimize buildings and whole areas. The plan is develop a platform for architects and engineers to exchange information and I think Dash would be very useful.

2 Likes

@maxt A mesh3d can be derived from an obj file, too: https://plot.ly/~empet/15040

Data from a DXF file can be extracted via the Python package dxfgrabber
https://dxfgrabber.readthedocs.io/en/latest/
and then use them to define plotly traces
representing the corresponding DXF drawings.

4 Likes

Amazing @empet!!

The interactivity is really neat, you can even zoom inside the car:

2 Likes

Hi Max!
Did you get the answer to your question here?
Small world : )
I thought your page on listing building energy optimization tools at


may be of ineterst to @alexcjohnson @jack

Updates of the notebooks illustrating how to extract data for a Mesh3d instance from files in ply, off, Wavefront obj or STL format:

1 Like

Hi @empet, thanks for the useful answer.

Regarding STL files, some exporters include color data in the attributes (see Wiki). Here some code example, based on yours that takes advantage of this feature. It is not optimized but just to show what is possible.

BR, Alex-

from stl import mesh
import numpy as np
import plotly.graph_objects as go

def get_stl_color(x):
    #two "attribute byte count" bytes at the end of every triangle to store a 15-bit RGB color
    #bits 0 to 4 are the intensity level for blue (0 to 31)
    #bits 5 to 9 are the intensity level for green (0 to 31)
    #bits 10 to 14 are the intensity level for red (0 to 31)
    sb = f'{x:015b}'[::-1]
    r = str(int(255/31*int(sb[:5],base=2)))
    g = str(int(255/31*int(sb[5:10],base=2)))
    b = str(int(255/31*int(sb[10:15],base=2)))
    color = f'rgb({r},{g},{b})'
    return color

def stl2mesh3d(stl_file):
    stl_mesh = mesh.Mesh.from_file(stl_file)
    # stl_mesh is read by nympy-stl from a stl file; it is  an array of faces/triangles (i.e. three 3d points) 
    # this function extracts the unique vertices and the lists I, J, K to define a Plotly mesh3d
    p, q, r = stl_mesh.vectors.shape #(p, 3, 3)
    # the array stl_mesh.vectors.reshape(p*q, r) can contain multiple copies of the same vertex;
    # extract unique vertices from all mesh triangles
    vertices, ixr = np.unique(stl_mesh.vectors.reshape(p*q, r), return_inverse=True, axis=0)
    I = np.take(ixr, [3*k for k in range(p)])
    J = np.take(ixr, [3*k+1 for k in range(p)])
    K = np.take(ixr, [3*k+2 for k in range(p)])
    facecolor = np.vectorize(get_stl_color)(stl_mesh.attr.flatten())
    x,y,z = vertices.T
    trace = go.Mesh3d(x=x, y=y, z=z, i=I, j=J, k=K, facecolor=facecolor)
    # optional parameters to make it look nicer
    trace.update(flatshading=True, lighting_facenormalsepsilon=0, lighting_ambient=0.7)
    return trace

Here an example of how it looks:
image

1 Like

Hey all, thanks for putting this material available.

I’m facing a challenge to get data from a DXF file and plot it using traces as @empet suggested. I’m using ezdxf to get the entities (CIRCLE, LINES, ARC, LWPOLYLINE, etc…) from the file as well as the points related to each one. Here is an example for the lines:


import ezdxf
import numpy as np
import plotly.graph_objects as go
import plotly.offline as pyo


doc = ezdxf.readfile("8770PZ-M-00003.dxf")

msp = doc.modelspace()

lines = msp.query('LINE')

len(lines)

data = []

for line in lines:
    x,y,z = np.linspace(line.dxf.start,line.dxf.end).T   

    data.append(
        go.Scatter3d(
        x=x,
        y=y,
        z=z,
        line=dict(
            color='darkblue',
            width=1
        )    
        ))


fig = go.Figure(data=data)

fig.update_layout()

pyo.plot(fig,filename='test.html')

The problem is rendering the image, in this case there are 10418 lines, which seem to be too many lines for plotting it. Am I missing something here? Should I just go over every entity and append to the data list as a specific trace to that entity?