H5网页三维CAD中创建一个装配体

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 本文介绍了如何使用mxcad3d创建小车装配体模型。通过官方教程搭建项目环境,使用API创建车轮、车轴、车身等部件,并通过实例引用与组合实现装配体的构建。最终通过按钮触发绘制小车模型,展示其三维效果。

前言

在网页CAD中有些相同的零件可以只建一个模型实例,其余用到的地方均为实例的引用,然后将引用组合起来形成装配体。mxcad3d提供了丰富的三维建模功能和便捷的API,接下来聊一下如何利用mxcad3d来创建小车装配体模型。
图片1.png

快速入门

首先我们需要学习mxcad的基本使用方法,可以通过官方的入门教程来搭建一个最基本的项目模板。
开发环境准备(对前端开发不熟悉的一定要看)安装Node.js和VS Code,然后创建最基本的mxcad开发项目API文档使用说明

本次教程最后完成的完整测试项目压缩包(https://gitee.com/mxcadx/mxcad_docs/tree/master/examples3D/Test3dAssemblyCar.7z) ,压缩包下载解压后需要在项目目录下打开cmd命令行,然后在命令行中执行npm install来安装依赖,然后再按照本教程中的方式来运行项目查看效果。

编写创建装配体小车的代码

1.按照上面前言中第2条中的方式,根据官方快速入门教程来创建一个名为Test3dAssemblyCar的项目,如下图:
图片2.png

2.编写绘制装配体小车的代码
在index.html中插入一个按钮"绘制装配体小车", index.html的完整代码如下:

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta http-equiv="X-UA-Compatible" content="IE=edge">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>vite use mxcad</title>  
</head>  
<body>  
    <div style="height: 800px; overflow: hidden;"> <canvas id="myCanvas"></canvas></div>  
    <button>绘制装配体小车</button>  
    <script type="module" src="./src/index.ts"></script>  
</body>  
</html>

在src/index.ts中编写绘制装配体小车的函数,src/index.ts的完整代码如下:

import {
    MdGe, Mx3dGeAxis, Mx3dGeColor, Mx3dGeCSYSR, Mx3dGeDir, Mx3dGeLocation, Mx3dGePoint, Mx3dGeTrsf, Mx3dGeVec, Mx3dMkCylinder, Mx3dMkFace, Mx3dMkPolygon, Mx3dMkPrism, MxCAD3DObject } from "mxcad"\
// 创建mxcad3d对象\
const mxcad3d = new MxCAD3DObject()\
// 初始化mxcad3d对象\
mxcad3d.create({
   \
    // canvas元素的css选择器字符串(示例中是id选择器),或canvas元素对象\
    canvas: "#myCanvas",\
    // 获取加载wasm相关文件(wasm/js/worker.js)路径位置\
    locateFile: (fileName)=> new URL(`/node_modules/mxcad/dist/wasm/3d/${
     fileName}`, import.meta.url).href,\
})\
// 初始化完成\
mxcad3d.on("init", ()=>{
   \
    console.log("初始化完成");\
});\
function drawAssemblyCar() {
   \
  // 轮子形状\
  const pt = new Mx3dGePoint(0, 0, 0);  // 中心点\
  const dir = new Mx3dGeDir(0, 0, 1); // 方向\
  const csysr = new Mx3dGeCSYSR(pt, dir); // 根据点和方向创建一个右手坐标系\
  const wheel = new Mx3dMkCylinder(csysr, 20, 10);  // 轮子(宽扁的圆柱体)\
  let wheelShape = wheel.Shape(); // 获取轮子拓扑形状\
  // 轴形状\
  const axle = new Mx3dMkCylinder(csysr, 5, 100); // 轴(细长的圆柱体)\
  const axleShape = axle.Shape(); // 获取轴拓扑形状\
  wheelShape = wheelShape.cut(axleShape); // 切割掉轮子的轴孔\
  // 车体形状\
  const bodyPts:Mx3dGePoint\[] = \[]\
  bodyPts.push(new Mx3dGePoint(0, 0, 0));\
  bodyPts.push(new Mx3dGePoint(0, 50, 0));\
  bodyPts.push(new Mx3dGePoint(160, 50, 0));\
  bodyPts.push(new Mx3dGePoint(160, 0, 0));\
  const bodyPoly = new Mx3dMkPolygon(); // 创建多段线(车体的截面轮廓)\
  bodyPts.forEach((pt) => {
   \
    bodyPoly.Add(pt);\
  });\
  bodyPoly.Close(); // 闭合多段线\
  const bodyWire = bodyPoly.Wire(); // 获取多段线(车体的截面轮廓)的拓扑Wire\
  const bodyMkFace = new Mx3dMkFace(bodyWire); // 用Wire生成面\
  const bodyFace = bodyMkFace.Face(); // 获取面\
  const bodyPrism = new Mx3dMkPrism(bodyFace, new Mx3dGeVec(0, 0, 100)); // 用面生成车体实体\
  let bodyShape = bodyPrism.Shape(); // 获取车体实体形状\
  bodyShape.TranslateBy2Points(new Mx3dGePoint(30, 0, 0), new Mx3dGePoint(0, 0, 0)); // 移动到合适位置,方便装配\
  const wheelForCut = new Mx3dMkCylinder(csysr, 25, 15); // 车体嵌入车轮的地方,用车体切掉,用于放入轮子\
  // 以下是切出四个放轮子的空间\
  const wheelForCutShape = wheelForCut.Shape();\
  bodyShape = bodyShape.cut(wheelForCutShape);\
  bodyShape = bodyShape.cut(wheelForCutShape.TranslatedByVec(new Mx3dGeVec(0, 0, 85)));\
  bodyShape = bodyShape.cut(wheelForCutShape.TranslatedByVec(new Mx3dGeVec(100, 0, 0)));\
  bodyShape = bodyShape.cut(wheelForCutShape.TranslatedByVec(new Mx3dGeVec(100, 0, 85)));\
  const axleForCut = new Mx3dMkCylinder(csysr, 6, 100); // 车体嵌入轴的地方,用车体切掉,用于放入轴\
  // 以下是切出两个放轴的空间\
  const axleForCutShape = axleForCut.Shape();\
  bodyShape = bodyShape.cut(axleForCutShape);\
  bodyShape = bodyShape.cut(axleForCutShape.TranslatedByVec(new Mx3dGeVec(100, 0, 0)));\
  // 获取文档\
  const doc = mxcad3d.getDocument();\
  // 车子装配体标签\
  const carLabel = doc.addShapeLabel();\
  // 轮子实例标签\
  const wheelLabel = doc.addShapeLabel();\
  // 车轴实例标签\
  const axleLabel = doc.addShapeLabel();\
  // 轮轴装配体实例标签\
  const wheelAxleLabel = doc.addShapeLabel();\
  // 车壳实例标签\
  const bodyLabel = doc.addShapeLabel();\
  // 轮子、轴、车体形状都添加到模型文档的标签中(同时为不同的形状设置不同的颜色)\
  wheelLabel.setShape(wheelShape);\
  wheelLabel.setColor(new Mx3dGeColor(MdGe.MxNameOfColor.Color\_NOC\_BLACK));\
  axleLabel.setShape(axleShape);\
  axleLabel.setColor(new Mx3dGeColor(MdGe.MxNameOfColor.Color\_NOC\_RED));\
  bodyLabel.setShape(bodyShape);\
  bodyLabel.setColor(new Mx3dGeColor(MdGe.MxNameOfColor.Color\_NOC\_BLUE2));\
  // 轮轴装配体(轮轴装配体需要两个轮子、一个轴)\
  wheelAxleLabel.addComponent(wheelLabel, new Mx3dGeLocation()); // 添加第一个轮子,没有位置(原位置,轮子模型创建的位置)\
  const wheel\_2\_trsf = new Mx3dGeTrsf();\
  wheel\_2\_trsf.SetTranslationPart(new Mx3dGeVec(0, 0, 90));\
  wheelAxleLabel.addComponent(wheelLabel, new Mx3dGeLocation(wheel\_2\_trsf)); // 添加第二个轮子,有位置(向Z轴正方向移动90之后的位置)\
  wheelAxleLabel.addComponent(axleLabel, new Mx3dGeLocation()); // 添加轴,没有位置(原位置,轴模型创建的位置)\
  // 车子装配体(车子装配体需要两个轮轴装配体、一个车体)\
  const wheelAxle\_1\_trsf = new Mx3dGeTrsf();\
  wheelAxle\_1\_trsf.SetRotation(new Mx3dGeAxis(new Mx3dGePoint(0, 0, 0), new Mx3dGeDir(1, 0, 0)), Math.PI / 2);\
  carLabel.addComponent(wheelAxleLabel, new Mx3dGeLocation(wheelAxle\_1\_trsf)); // 添加第一个轮轴装配体,有位置(绕X轴旋转90度之后的位置)\
  let wheelAxle\_2\_trsf = new Mx3dGeTrsf();\
  wheelAxle\_2\_trsf.SetTranslationPart(new Mx3dGeVec(100, 0, 0));\
  wheelAxle\_2\_trsf = wheelAxle\_2\_trsf.Multiplied(wheelAxle\_1\_trsf); // 矩阵相乘,得到第二个轮轴装配体的位置,相乘后的矩阵代表先绕X轴旋转90度,然后再向X轴正方形平移100\
  carLabel.addComponent(wheelAxleLabel, new Mx3dGeLocation(wheelAxle\_2\_trsf)); // 添加第二个轮轴装配体,有位置(绕X轴旋转90度,然后再向X轴正方形平移100之后的位置)\
  carLabel.addComponent(bodyLabel, new Mx3dGeLocation(wheelAxle\_1\_trsf)); // 添加车体,有位置(绕X轴旋转90度之后的位置)\
  // 更新新图显示模型,会将文档中的模型显示到当前视图中\
  mxcad3d.update();\
}\
// 给button添加点击事件,点击后调用drawAssemblyCar函数\
// 立即执行函数\
(function addEventToButton(){
   \
  const btn = document.querySelector("button");\
  if (btn) {
   \
    btn.addEventListener("click", () => {
   \
      drawAssemblyCar();\
    });\
  }\
})()

按照官方快速入门教程,新建终端,运行npx vite命令来运行项目,观察效果如下图:
图片3.png

相关文章
|
1天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1517 4
|
28天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
5天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
481 17
|
1天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
179 1
|
8天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
21天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
8天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
442 4
|
7天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
313 2
|
23天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
25天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2607 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析