前言
前不久有朋友说能不能再网页上展示STL格式的模型文件,并且可以计算出STL模型的质量、面积和尺寸,因为他在某宝上买了一个简易APP,计算出来的结果误差太大;
为了帮助朋友解决问题,在他给了我一个STL模型后,我打开端详了下,觉得问题不大,开始搞~
什么是STL模型
STL(stereolithography)文件格式(光固化立体造型术的缩写),是一种为快速原型制造技术服务的三维图形文件格式,通常是在3D打印上使用。其他细节大家可自行查阅
模型展示
当然是使用Three.js来展示模型了,Three中通过STLLoader()加载器可以加载此格式模型:
let loader = new THREE.STLLoader();
// 材质
let material = new THREE.MeshPhongMaterial({ color: 0x0e2045, specular: 0x111111, shininess: 200 });
loader.load('stl文件地址', function (geometry) {
let mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, 0);
mesh.rotation.set(0, 0, 0);
mesh.scale.set(.02, .02, .02);
mesh.castShadow = true;
mesh.receiveShadow = true;
// code
scene.add(mesh);
render();
});
加载出来大概如图所示
测量质量、面积和尺寸
测量STL在使用纯前端是不行的了,需要结合Node服务来测量我们需要的。
node-stl
该插件我们可以用来解析 STL 文件并获取体积、质量、边界框和质心。我们通过搭建一个Express服务,集成该插件测试下效果看看
// density:密度
app.get('/express_backend', (req, res) => {
let stl = new NodeStl(__dirname + '/models/mb.stl', { density: 1.248 });
// console.log(stl.volume + '平方厘米');
// console.log(stl.weight + 'GM');
// console.log(stl.boundingBox,'(mm)');
// console.log(stl.area,'(m)');
// console.log(stl.centerOfMass,'(mm)');
});
计算结果如图所示
这样看来也不是很难嘛,于是乎我发给了朋友,结果他又说你这一次只能计算一个,我要计算其他的还要自己改代码,太麻烦了,请你吃顿饭给我加个上传呗,顺便把计算结果给我显示到浏览器界面上,这样我就可以想看啥就看啥了。
我在想咋又临时加需求了,还顺便,自己加不就行了,哎,看在饭的面子上就再花点时间整个上传。
集成上传、提交于一身
因为没有公网服务器,所以我给他说在局域网内使用吧,他说没问题!
上传的话需要涉及到文件操作,因此需要使用fs内置模块来读取前端提交的文件数据,先看看前端是如何提交的
<form id="form" action="/upload" method="post" onsubmit="return uploadAttachment()" target="postframe" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
前端提交的时候一定要注意,header头中的Content-Type一定要是multipart/form-data,这是小白在学习中经常遇到的问题,这点一定要注意!!!
通过Ajax将文件提交到/upload接口,该接口用来接收解析提交过来的文件数据
// 处理上传文件服务
app.post('/upload', (req, res) => {
const busboy = new Busboy({ headers: req.headers });
let fileName = null
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
const saveTo = path.join(__dirname, 'models', filename);
fileName = filename
file.pipe(fs.createWriteStream(saveTo));
});
busboy.on('finish', function () {
let stl = new NodeStl(__dirname + '/models/' + fileName, { density: 1.248 });
// 将结果返回
res.send({
code: 200,
data: {
volume: stl.volume.toFixed(3), // 尺寸
weight: stl.weight.toFixed(3), // 质量
area: stl.area.toFixed(3), // 面积
file_url: 'http://' + getIPAdress() + '/models/' + fileName, // 储存的文件地址
url: 'http://' + getIPAdress() + ':5000?stl=' + fileName, // 朋友需要复制查看的页面地址
}
});
});
return req.pipe(busboy);
});
至此上传和回显也就做完了,在回显的时候会存在跨域问题,这个通过cors插件好解决,具体代码自己可以看,这里不做过多赘述。
交工
至此上传、测量和回显也就做完了,发给朋友后他直呼过瘾,当然那顿饭肯定要年后了,至于要吃啥,我还要想一想,毕竟一个人吃不了太多~
源码获取
关注我的微信公众号,源码可以在公众号内回复STL测量获取
文章每周持续更新,文章类型涉及GIS开发、三维数字开发,可以微信搜索「 金刚小仓 」第一时间阅读和催更(比博客早一些子),同时会不定期分享GIS开发中所用到的一些实用小工具