明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 291|回复: 1

(前端3D模型开发)在线三维CAD中绘制一个窗户模型

[复制链接]
发表于 2024-10-30 14:48:30 | 显示全部楼层 |阅读模式
本帖最后由 MxDraw 于 2024-10-30 14:54 编辑

前言
本文使用mxcad3d在网页中创建一个简单的三维窗户模型,mxcad3d提供了丰富的三维建模功能和便捷的API,使得创建各种三维模型变得简单方便,最终效果如下图

环境搭建和入门
首先学习mxcad的基本使用方法,可通过官方的入门教程来搭建一个最基本的项目模板,依次查看教程:

完整测试项目压缩包,下载解压后需要在项目目录下打开`cmd命令行`,然后在命令行中执行`npm install`来安装依赖,然后再按照本教程中的方式来运行项目查看效果


编写创建窗户模型的代码
1. 根据官方快速入门教程来创建一个名为`Test3dWindow`的项目,如下图:

2. 编写绘制窗户模型的代码
index.html中插入一个按钮"绘制窗户模型"index.html的完整代码如下
  1.    <!DOCTYPE html>
  2.    <html lang="en">
  3.    <head>
  4.        <meta charset="UTF-8">
  5.        <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6.        <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7.        <title>vite use mxcad</title>
  8.    </head>
  9.    <body>
  10.        <div style="height: 800px; overflow: hidden;"> <canvas id="myCanvas"></canvas></div>
  11.        <button>绘制窗户模型</button>
  12.        <script type="module" src="./src/index.ts"></script>
  13.    </body>
  14.    </html>
复制代码
src/index.ts中编写绘制窗户模型的函数,src/index.ts的完整代码如下
  1. import { MdGe, Mx3dGeAxis, Mx3dGeColor, Mx3dGeDir, Mx3dGeMaterial, Mx3dGeomPlane, Mx3dGePoint, Mx3dGeVec, Mx3dMkBox, Mx3dMkFace, Mx3dMkPolygon, Mx3dMkPrism, MxCAD3DObject } from "mxcad"
  2.    // 创建mxcad3d对象
  3.    const mxcad3d = new MxCAD3DObject()
  4.    // 初始化mxcad3d对象
  5.    mxcad3d.create({
  6.        // canvas元素的css选择器字符串(示例中是id选择器),或canvas元素对象
  7.        canvas: "#myCanvas",
  8.        // 获取加载wasm相关文件(wasm/js/worker.js)路径位置
  9.        locateFile: (fileName)=> new URL(`/node_modules/mxcad/dist/wasm/3d/${fileName}`, import.meta.url).href,
  10.    })
  11.    // 初始化完成
  12.    mxcad3d.on("init", ()=>{
  13.        console.log("初始化完成");
  14.        // 修改背景颜色
  15.        const color1 = new Mx3dGeColor(61/255, 139/255, 221/255, MdGe.MxTypeOfColor.Color_TOC_sRGB);
  16.        const color2 = new Mx3dGeColor(203/255, 223/255, 247/255, MdGe.MxTypeOfColor.Color_TOC_sRGB);
  17.        mxcad3d.setGradientBgColor(color1, color2, MdGe.MxGradientFillMethod.GFM_VER);
  18.        // 设置透视投影
  19.        mxcad3d.setProjectionType(MdGe.MxCameraProjection.CProjection_Perspective);
  20.        // 打开光照阴影
  21.        mxcad3d.enableDirLightSrc(true);
  22.    });
  23.    function drawWindow(){
  24.      // 窗户边框横截面轮廓点
  25.      const pts: Mx3dGePoint[] = [];
  26.      pts.push(new Mx3dGePoint(0, 0, 0));
  27.      pts.push(new Mx3dGePoint(1, 0, 0));
  28.      pts.push(new Mx3dGePoint(1, 0, 2));
  29.      pts.push(new Mx3dGePoint(4, 0, 2));
  30.      pts.push(new Mx3dGePoint(4, 0, 0));
  31.      pts.push(new Mx3dGePoint(5, 0, 0));
  32.      pts.push(new Mx3dGePoint(5, 0, 10));
  33.      pts.push(new Mx3dGePoint(3, 0, 10));
  34.      pts.push(new Mx3dGePoint(3, 0, 8));
  35.      pts.push(new Mx3dGePoint(2, 0, 8));
  36.      pts.push(new Mx3dGePoint(2, 0, 10));
  37.      pts.push(new Mx3dGePoint(0, 0, 10));
  38.      // 窗户边框横截面轮廓多段线
  39.      const polygon = new Mx3dMkPolygon();
  40.      pts.forEach((pt) => polygon.Add(pt));
  41.      polygon.Close();
  42.      // 窗户边框横截面轮廓线
  43.      const wire = polygon.Wire();
  44.      // 窗户边框横截面轮廓线生成窗框横截面
  45.      const makeface = new Mx3dMkFace(wire);
  46.      const face = makeface.Face();
  47.      const vec = new Mx3dGeVec(0, 100, 0);
  48.      // 横截面拉伸出窗框体形状
  49.      const frame = new Mx3dMkPrism(face, vec);
  50.      let frameShape = frame.Shape();
  51.      // 构造两个平面用于分割窗户边框(边框两端的斜45度角)
  52.      const pt = new Mx3dGePoint(0, 0, 0);
  53.      const dir = new Mx3dGeDir(0, -1, 1);
  54.      const plane = new Mx3dGeomPlane(pt, dir);
  55.      // 平面1
  56.      const planeFace = plane.Face(1e-5);
  57.      pt.setXYZ(0, 50, 0);
  58.      dir.SetXYZ(0, 0, 1);
  59.      const axis = new Mx3dGeAxis(pt, dir);;
  60.      // 平面2
  61.      const planeFace2 = planeFace.MirroredByAxis(axis);
  62.      // 分割窗户边框(分割成了两个斜45度的小三角形部分和中间的一个梯形部分)
  63.      const parts = frameShape.spliter([planeFace, planeFace2]);
  64.      // 筛选出中间那个梯形的部分(这里是通过质心的位置来判断的)
  65.      parts.forEach((shape)=>{
  66.        // 这里Centroid的参数添填的MdGe.MxQuantAspect.Quant_Volume这个枚举,是因为shape是实体,它的质心是体质心,所以这里填MdGe.MxQuantAspect.Quant_Volume
  67.        // 如果shape是面,它的质心是面质心,所以要填MdGe.MxQuantAspect.Quant_Area
  68.        // 如果shape是线,它的质心是线质心,所以要填MdGe.MxQuantAspect.Quant_Length
  69.        const centroid = shape.Centroid(MdGe.MxQuantAspect.Quant_Volume);
  70.        if (centroid.Y() > 45 && centroid.Y() < 55) {
  71.          frameShape = shape;
  72.        }
  73.      });
  74.      // 通过旋转得到另外三个边的边框
  75.      const frameShape2 = frameShape.Rotated(new Mx3dGeAxis([0, 50, 50], [1, 0, 0]), Math.PI / 2);
  76.      const frameShape3 = frameShape.Rotated(new Mx3dGeAxis([0, 50, 50], [1, 0, 0]), Math.PI);
  77.      const frameShape4 = frameShape2.Rotated(new Mx3dGeAxis([0, 50, 50], [1, 0, 0]), Math.PI);
  78.      // 合并四个边框,获得边框整体形状
  79.      frameShape = frameShape.fuse(frameShape2).fuse(frameShape3).fuse(frameShape4);
  80.      // 窗框颜色
  81.      const frameColor = new Mx3dGeColor(0.5, 0.5, 0.5, MdGe.MxTypeOfColor.Color_TOC_RGB);
  82.      // 窗框材质
  83.      const frameMaterial = new Mx3dGeMaterial(MdGe.MxNameOfMaterial.Material_NOM_ShinyPlastified);
  84.      // 玻璃
  85.      const glass = new Mx3dMkBox([2, 8, 8], [3, 92, 92]);
  86.      // 玻璃形状
  87.      const glassShape = glass.Shape();
  88.      // 玻璃颜色
  89.      const glassColor = new Mx3dGeColor(0, 0.9, 0.549, MdGe.MxTypeOfColor.Color_TOC_RGB);
  90.      // 玻璃材质,看起来是透明的
  91.      const glassMaterial = new Mx3dGeMaterial(MdGe.MxNameOfMaterial.Material_NOM_Glass);
  92.      // 获取模型文档
  93.      const doc = mxcad3d.getDocument();
  94.      // 新增一个形状标签用于保存边框形状
  95.      const frameLabel = doc.addShapeLabel();
  96.      frameLabel.setShape(frameShape);
  97.      frameLabel.setColor(frameColor)
  98.      frameLabel.setMaterial(frameMaterial);
  99.      // 新增一个形状标签用于保存玻璃形状
  100.      const glassLabel = doc.addShapeLabel();
  101.      glassLabel.setShape(glassShape);
  102.      glassLabel.setColor(glassColor)
  103.      glassLabel.setMaterial(glassMaterial);
  104.      // 更新视图显示
  105.      mxcad3d.update();
  106.    }
  107.    // 给button添加点击事件,点击后调用drawWindow函数,进行窗户模型的绘制
  108.    // 立即执行函数
  109.    (function addEventToButton(){
  110.      const btn = document.querySelector("button");
  111.      if (btn) {
  112.        btn.addEventListener("click", () => {
  113.          drawWindow();
  114.        });
  115.      }
  116.    })()
复制代码
3. 新建终端,运行`npx vite`命令来运行项目,效果如下图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 05:00 , Processed in 0.173926 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表