找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 833|回复: 3

[经典资料] 在线CAD(mxdraw库)如何自定义一个等腰三角形

[复制链接]

299

主题

20

回帖

3984

积分

中尉

积分
3984

活跃会员

发表于 2023-9-1 14:33:50 | 显示全部楼层 |阅读模式
前言
1.网页版  CAD  是指可以在  Web  浏览器中运行的计算机辅助设计软件,也被称为  Web  CAD,它可以通过网页浏览器进行交互和操作,使用户无需下载和安装  CAD  应用程序,而是在  Web  界面上直接浏览、修改、交互和保存CAD图纸。目前网页版  CAD  已经成为一种流行的设计工具,许多设计师和工程师都在使用它进行设计工作。但是由于网页版  CAD  的功能和性能限制,它相对于桌面版  CAD  仍然有一定的局限性,下面我们使用行业内代表产品梦想CAD云图(H5在线CAD),完成一个自定义等腰三角形的图形。
写一个等腰三角形的形状类
1.我们知道要构成三角形一定是需要三个点的, 所以我们可以通过mxdraw库提供的自定义形状类MxDbShape扩展出一个三角形。
1)首先我们在src/App.vue文件中找打<script setup lang="ts"></script>中的内容继续往下写,代码如下:
  1. import { MxDbShape } from "mxdraw"

  2. // ...其他内容



  3. export class MxDbTriangle extends MxDbShape {

  4.      // 这是必须的,这里相当于增加了一个传输值 points属性, 这个points就表示三个点的坐标位置

  5.      points: THREE.Vector3[] = []

  6.      protected _propertyDbKeys = [...this._propertyDbKeys, "points"]

  7.     //  我们直接重写getShapePoints 方法, 这样就可以直接把三个点渲染出来了

  8.     getShapePoints(): THREE.Vector3[] {

  9.         return this.points

  10.     }

  11. }
复制代码
以上就是实现了一个普通三角形类, 只需要往points中添加3个点,就会构成一个三角形, 你也可以用其他属性表示三角形的三个点比如point1point2 、point3;
2)但是这个三角形只是一个静态的三角形,你不能对三角形的三个点进行移动,也不能移动整个三角形
3)因此我们还可以再重写几个方法,让它支持再画布上移动三角形或者构成三角形的点,代码如下:
  1. import { MxDbShape } from "mxdraw"

  2. export class MxDbTriangle extends MxDbShape {



  3.   // ...

  4.   // 计算一下三角形的中间位置 这样我们我们就可以通过中点控制整个三角形的位置

  5.   getCenter() {

  6.         const _points = this.getShapePoints()

  7.         // 计算点的数量

  8.         const numPoints = _points.length;

  9.         // 计算所有点的向量之和

  10.         let sum = new THREE.Vector3();

  11.         for (let i = 0; i < numPoints; i++) {

  12.             sum.add(_points[i]);

  13.         }

  14.         const center = sum.divideScalar(numPoints);

  15.         return center

  16.   }

  17.   // 返回可以操作和移动的多个点坐标, 只有知道要操作的点在上面位置才能进行操作呀

  18.    getGripPoints() {

  19.         return [...this.points, this.getCenter()]

  20.     }

  21.     // 这里就开始移动点的位置了 offset就是鼠标点击操作点后的偏移量, 我们就可以通过add的方式改变点的位置了

  22.     // 那么如果是中点的话,我们就把三角形的三个点都进行偏移, 这样就实现移动整个三角形的功能了

  23.     moveGripPointsAt(index: number, offset: THREE.Vector3): boolean {

  24.         if (index === 3) {

  25.             this.points = [this.points[0].clone().add(offset), this.points[1].clone().add(offset), this.points[2].clone().add(offset)]

  26.         } else {

  27.             this.points[index] = this.points[index].clone().add(offset)

  28.         }

  29.         return true

  30.     }

  31. }
复制代码
2.有了三角形,那么我们再思考等腰三角形是什么样的呢? 以下只是其中一种实现方式,你也可以通过其他方式实现。
1)首先等腰三角形也是三角形, 所以我们用三个点来表示等腰三角形的三个点, 分别是底部开始点和结束点以及顶点。
2)我们需要先知道中点,去计算这个三角形的高度, 然后通过三个点的位置关系确认三角形的方向,最好得到三角形的实际顶点位置,代码如下:
  1. // 等腰三角形

  2. export class MxDbIsoscelesTriangle extends MxDbTriangle {

  3.     protected _propertyDbKeys = [...this._propertyDbKeys]

  4.     getShapePoints() {

  5.         const [baseStart, baseEnd, topPoint] = this.points

  6.         // 计算等腰三角形底边的中点

  7.         const midpoint = baseStart.clone().add(baseEnd).multiplyScalar(0.5);

  8.         // 计算高度和顶点位置

  9.         const height = topPoint.distanceTo(midpoint);

  10.         // 计算topPoint相对于baseStart和baseEnd的位置关系

  11.         const baseVector = new THREE.Vector3().subVectors(baseEnd, baseStart).normalize();

  12.         const perpendicularVector = new THREE.Vector3().crossVectors(baseVector, new THREE.Vector3(0, 0, 1)).normalize();

  13.         const direction = new THREE.Vector3().subVectors(topPoint, midpoint).dot(perpendicularVector);

  14.         const vertex = midpoint.clone().addScaledVector(perpendicularVector, direction >= 0 ? height : -height);

  15.         // 将三个点按照逆时针方向排列

  16.         const _points = [baseStart, baseEnd, vertex];

  17.         return _points;

  18.     }

  19.     getGripPoints() {

  20.         return [...this.getShapePoints(), this.getCenter()]

  21.     }

  22. }
复制代码
以上就是实现一个等腰三角形的全部过程。
3.那么我们要在画布上画出这个等腰三角形应该如何实现呢?
1)首先我们需要点击一个按钮, 表示开始画等腰三角形
2)然后我们需要监听canvas上的点击事件, 并记录点击位置转换成three.js坐标
3)最后将坐标值添加到MxDbIsoscelesTriangle实例中。
我们需要三个点的位置坐标,所以需要监听三次点击。上述步骤比较繁琐, 为此mxdraw库提供了MrxDbgUiPrPoint 来帮助我们简化上述步骤,代码如下:
  1. import { MrxDbgUiPrPoint } from "mxdraw"



  2. const getPoint = new MrxDbgUiPrPoint()

  3. async function drawTriangle() {

  4.     // 表示一个等腰三角形

  5.     const triangle = new MxDbIsoscelesTriangle()

  6.     // 这里就是获取第一个鼠标点击的位置,并自动帮你转换成three.js坐标

  7.     const pt1 = await getPoint.go()

  8.     triangle.points.push(pt1)

  9.     // 我们可能需要一个绘制的过程, 通过这样的方式就可以实现

  10.     getPoint.setUserDraw((currentPoint, draw)=> {

  11.         // 因为现在这个动态绘制只有两个已知点,所以无法构成三角形,我们就画一个直线,表示我们正在画三角形的底边

  12.         draw.drawLine(currentPoint, pt1)

  13.     })

  14.     // 这时又在屏幕上点了以下得到了pt2这个坐标

  15.     const pt2 = await getPoint.go()

  16.     triangle.points.push(pt2)

  17.    // 这时triangle三角形示例已经又两个点了,我们可以直接动态绘制过程绘制出这个三角形了,可以实时看见现在画出的三角形的样子。

  18.      getPoint.setUserDraw((currentPoint, draw)=> {

  19.         // 去设置三角形的最好一个点

  20.         triangle.points[2] = currentPoint

  21.         // 并且把它绘制出来

  22.         draw.drawCustomEntity(triangle)

  23.     })

  24.     // 最后我们再次点击屏幕,确定下这个三角形的形状

  25.     const pt3 = await getPoint.go()

  26.     triangle.points[2] = pt3

  27.   // 最后将它添加渲染到控件中,就完成了整个三角形的绘制

  28.     MxFun.getCurrentDraw().addMxEntity(triangle)

  29. }

  30. // 最后将这个drawTriangle函数在点击按钮时触发就可以开始画等腰三角形了
复制代码
4)我们将这个函数放在一个按钮的点击事件中,在App.vue的<template></template>中继续新增代码:
  1. <button @click="drawTriangle">绘制等腰三角形</button>
复制代码
现在就可以看看画等腰三角形的功能是否实现了,效果如下图:
等腰三角形图片1.png
试试点击中间夹点移动等腰三角形,效果如下图:
等腰三角形图片2.png
4.我们最后总结一下,首先需要先搭建一个在线CAD的网页,在网页上可以绘制自定义的等腰三角形,其次需要Node环境、Vite前端工程化项目、使用mxdraw、对CAD图纸进行转换、实现自定义形状,而自定义形状,我们先定义了三角形,又根据三角形定义了等腰三角形的类。在效果图中,我们可以看见等腰三角形是有描边效果和填充效果,这些都是自定义形状的基类提供的功能,只需要设置对应的属性就可以实现对应的效果,自定义图形类的属性和方法说明请参考:
最后没有问题,我们可以通过在项目根目录运行命令:
  1. npm run build
复制代码
打包文件用打包线上的版本前端资源,在dist目录中是具体打包后的代码。
DEMO源码链接:


6

主题

2518

回帖

8286

积分

少校

积分
8286
发表于 2024-2-1 22:53:57 | 显示全部楼层
感谢大佬!

1

主题

2358

回帖

6591

积分

上尉

积分
6591
发表于 2024-3-1 10:11:12 | 显示全部楼层
感谢分享

1

主题

2358

回帖

6591

积分

上尉

积分
6591
发表于 2024-3-23 18:41:44 | 显示全部楼层
感谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

咨询QQ:1359218528|发帖须知!|Archiver|手机版|小黑屋|UG爱好者论坛 ( 京ICP备10217105号-2 )

GMT+8, 2024-12-26 01:50

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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