基于SpringMVC对stl文件的3D可视化

先来看一下最终效果:


点击左上角的按钮,可以从后台获取stl文件,并且显示。


3DSTL_2.png

其中,按钮的代码为:,其调用的方法,笔者已经封装为read_file('test/testStl.do'),可以看出是调用了后端的controller得到相应的文件。

以下是实现过程:

  1. 收集实现代码

    首先,需要一个显示stl的前端实现。因为是前端代码,并且是显示比较主流的3D文件,所以肯定是已经有相应的实现,所以我们要做的就是找到相应的实现,然后在上面做相应的修改即可。笔者参考的是以下这个stl免费在线查看工具:free online STL viewer.因为这个工具已经标注了完全在本地运行,所以我们肯定能够通过这个网站的前端源码实现我们的需求。

  2. 下载源码

    新建文件夹stlShow,在上面的网页下ctrl+s保存代码到此文件夹。此时我们可以看到在其js文件夹下所有的js文件都是.下载结尾了,我们首先删除.下载后缀,然后打开Free online STL viewer.html,搜索.下载,并删除所有.下载后缀。

  3. 后端编写stl文件controller

    首先准备一个test.stl文件放在webapp下。

     @Controller
     public class TestDemonController {
         @RequestMapping(value = "/testStl.do")
         @ApiOperation(value = "以二进制流的形式传送STL")
         public void getTestSTL(HttpServletRequest request, HttpServletResponse response){
             FileInputStream fis = null;
             String stlPath = request.getSession().getServletContext().getRealPath("")+"test.stl";
             //这里的类型,是笔者在调试前端js代码的时候找到的,默认的类型里面没有这一类型,但是此类型是必须要写的
             response.setContentType("application/vnd.ms-pki.stl");
             out(request,response,fis,stlPath);
         }
     
         private void out(HttpServletRequest request, HttpServletResponse response,FileInputStream fis,String path){
             try {
                 OutputStream outputStream = response.getOutputStream();
                 File file = new File(path);
                 fis = new FileInputStream(file);
                 byte[] b = new byte[fis.available()];
                 fis.read(b);
                 outputStream.write(b);
                 outputStream.flush();
             } catch (IOException e) {
                 e.printStackTrace();
             }finally {
                 if(fis!=null){
                     try {
                         fis.close();
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
             }
         }
     }
    

    在浏览器中输入your-url/testStl.do,能够下载一个testStl.do文件,将其改名为testStl.stl,上传到最初的那个网站,可以看到效果,说明接口已经正常运行。

  4. 拷贝前端代码至你的项目中

    将前端代码拷贝到你的web项目中,并根据你拷贝的情况修改js引用路径。

  5. 修改前端代码read_internal.js

    替换read_internal.js文件中function read_file(f)方法为(具体解释请看注释):

     function read_file(stl_url)
     {
         waiting=true;
     
         var pbar=$id('file_pbar');
         var reader = new FileReader();
     
         reader.onerror = function(e)
         {
             var error_str="";
             switch(e.target.error.code)
             {
                 case e.target.error.NOT_FOUND_ERR:
                     error_str="File not found";
                     break;
     
                 case e.target.error.NOT_READABLE_ERR:
                     error_str="Can't read file - too large?";
                     break;
     
                 case e.target.error.ABORT_ERR:
                     error_str="Read operation aborted";
                     break;
     
                 case e.target.error.SECURITY_ERR:
                     error_str="File is locked";
                     break;
     
                 case e.target.error.ENCODING_ERR:
                     error_str="File too large";
     
                     break;
     
                 default:
                     error_str="Error reading file";
             }
             alert(error_str);
             switch_view('drag');
             return after_error();
         }
     
         reader.onload = function(e)
         {
             switch_view('proc');
             setTimeout(function(){after_file_load('3D圖片展示', e.target.result)}, 500);
         };
     
         reader.onprogress = function(e)
         {
             if (cancel_download)
             {
                 reader.abort();
                 return after_error();
             }
             else
                 pbar.value=e.loaded / e.total*100;
         };
     
         pbar.value=0;
     
         //使用一个回掉函数获取stl文件的二进制流为blob类型
         //使用Jquery的$.Ajax方法虽然能得到二进制数据,但是没有类型,甚至不是Array的类型,所以这里采用了这个方式
         switch_view('pbar');
         var stl;
         var xhr = new XMLHttpRequest();
         xhr.open('GET', stl_url, true);
         xhr.responseType = 'blob';
         xhr.onload = function(e) {
             if (this.status == 200) {
                 // get binary data as a response
                 stl = this.response;
                 reader.readAsArrayBuffer(stl);//调用原来的方法把stl文件传入
             }
         };
         xhr.send();
     }
    
  6. 修改parser.js文件

    parser.js文件是用来解析文件类型的,我们通过后端传入的文件因为没有文件名,所以这边会将我们传入的文件判断为不支持的类型,所以,这边我们用一个比较笨的方法,解决这个问题,之后如果需要解析objorvf文件,可以自行修改。这里,我们修改function parse_3d_file(filename, s)函数为:

     function parse_3d_file(filename, s)
     {
         //determine type of file
         //console.log(filename.split('.').pop().toLowerCase());
         switch (filename.split('.').pop().toLowerCase())
         {
             case "stl":
                 return parse_stl_bin(s);
                 break;
             case "obj":
                 return parse_obj(s);
                 break;
             case "vf":
                 return parse_vf(arrayBufferToString(s));
                 break;
             default:
                 return parse_stl_bin(s);//直接调用stl解析
                 break;
         }
     }
    
  7. 添加测试按钮

    Free online STL viewer.html中添加按钮。测试效果如文章开头所示。

  8. 删除掉Free online STL viewer.html中你不需要的代码

自此,stl 3D文件的自定义demon已经完成,作为一个后端开发人员,看到这6K多行的js代码,简直是头痛,特别是js基础不是很好,确实是个不小的挑战。个人感觉js代码相对于java这样的代码来说,大多时候更缺少比较严密的工程组织,不过据说现在的前端已经工程化了,希望以后看到更新的js代码时不会那么吃力:)。

转载请附原链接:https://www.jianshu.com/p/09f92404b959

你可能感兴趣的:(基于SpringMVC对stl文件的3D可视化)