Using pythonOCC's render function in Django

788 views Asked by At

I have a Django application and I'm using pythonOCC package in it. I have to display the 3D .stl, .stp, .igs files in my template. I have tried to use render() function which in x3dom_renderer.py file in the package.

Here is my view:

from OCC.Extend.DataExchange import read_step_file
from OCC.Display.WebGl import x3dom_renderer
from OCC.Core.BRep import BRep_Builder
from OCC.Core.TopoDS import TopoDS_Shape
from OCC.Core.BRepTools import breptools_Read

def index(request):
    shape = read_step_file('test.stp')
    my_renderer = x3dom_renderer.X3DomRenderer()
    my_renderer.DisplayShape(shape)
    my_renderer.render()
    return render(request, 'index.html')

When I call the render() function, the following outputs appear on my vscode console and since flask app created by pythonocc instead of django starts running in localhost, my index.html is never rendered.

The output when I call the render function:

 **  Model Complete Check List  **
Check:1 -- Entity (n0:id) 5:#14   Type:CURVE_STYLE
Parameter n0.2 (curve_font) not an Entity
Check:2 -- Entity (n0:id) 6:#15   Type:CURVE_STYLE
Parameter n0.2 (curve_font) not an Entity
Check:3 -- Entity (n0:id) 7:#16   Type:CURVE_STYLE
Parameter n0.2 (curve_font) not an Entity
Check:4 -- Entity (n0:id) 8:#17   Type:CURVE_STYLE
Parameter n0.2 (curve_font) not an Entity
Check:5 -- Entity (n0:id) 9:#18   Type:CURVE_STYLE
Parameter n0.2 (curve_font) not an Entity
Check:6 -- Entity (n0:id) 10:#19   Type:CURVE_STYLE
Parameter n0.2 (curve_font) not an Entity
## x3dom webgl renderer - render axes/planes : True - axes/plane zoom factor : 1
| meshing shapes... 100%
## Serving C:\Users\imgea\AppData\Local\Temp\tmppopa5opx
## using Flask
## Open your webbrowser at the URL: http://localhost:8080

As you see in this x3dom_renderer.py https://github.com/tpaviot/pythonocc-core/blob/master/src/Display/WebGl/x3dom_renderer.py, the html file is created in this python file and is shaped according to the image which I sent. How can I use this renderer in my Django template? Could you give any suggestions?

2

There are 2 answers

9
Lucas Moeskops On BEST ANSWER

The render function starts its own server so I think this one should not be called. It might be useful to extend the Renderer class, to add the functions to it that we miss. In this case an option to render to string, so we can use the output.

from OCC.Extend.DataExchange import read_step_file
from OCC.Display.WebGl import x3dom_renderer
from OCC.Core.BRep import BRep_Builder
from OCC.Core.TopoDS import TopoDS_Shape
from OCC.Core.BRepTools import breptools_Read
from django.http.response import HttpResponse


class CustomX3DomRenderer(x3dom_renderer.X3DomRenderer):
    def render_to_string(self):
        # N.B. Writing the html file to disk isn't really needed; you 
        # could also build the string directly without writing it
        # to disk
        self.generate_html_file(self._axes_plane, self._axes_plane_zoom_factor)
        return open(self._html_filename, 'r').read()


def index(request):
    shape = read_step_file('test.stp')
    my_renderer = CustomX3DomRenderer()
    my_renderer.DisplayShape(shape)
    return HttpResponse(my_renderer.render_to_string())
4
Lucas Moeskops On

The HTML consists of a few variables which you might not all need. Probably the <head> section you will create yourself. The JavaScript parts are useful to insert in your template. A relatively easy way to do this is to add a context processor, see this section of the Django documentation. Basically you define a function that gives extra variables to templates you are rendering.

In my_app/context_processors.py. Note that because we trust the HTML, we add mark_safe to it, to prevent templates escaping the HTML:

from Display.WebGl.three_js_renderer import BODY_PART1, BODY_PART2
from django.utils.safestring import mark_safe

def threejs_context(request):
  return {
    'threejs_body_part1':  mark_safe(BODY_PART1),
    'threejs_body_part2': mark_safe(BODY_PART2),
  }

In your project's settings.py:

TEMPLATES = [
  {
    ...
    'context_processors': [
      ...
      'my_app.context_processors.threejs_context',
    ],
    ...
  }
]

Now in your templates, you can use the defined variables to insert the HTML in your context:

{{ threejs_body_part1 }}
{{ threejs_body_part1 }}