找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 440|回复: 0

[在线文档] H5在线CAD实现一种绘制圆弧的方式

[复制链接]
发表于 2023-11-22 09:49:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
本帖最后由 ywl0224 于 2023-11-22 09:52 编辑

前言
在线CAD绘制圆弧本质上是在网页端编辑DWG图纸而DWG格式是无法直接在网页端编辑的,因此要先安装梦想CAD控件的后台转换程序,将图纸转换成mxweb格式,然后传送给前台进行编辑,其中转换方法和原理请查看快速入门的《编辑模式原理说明》章节,如下图:
编辑模式原理说明.png

注意:如果你对mxdraw不是很了解建议看看[官方文档mxdraw]


网页CAD绘制圆弧的方式有很多种,而mxdraw库的方式是通过继承Mx3PointArc类来实现两点绘制圆弧的功能,类似于多段线画圆弧,只需要确定两个点就可以画一个圆弧的效果,这两个点分别是圆弧的开始点和圆弧的结束点,下面讲一下具体实现方法。

使用Mx3PointArc

在此之前先了解以下内容:[Mx3PointArc]首先Mx3PointArc是通过给定的三个点来绘制圆弧的一个类。这三个点分别是起点(point1)、终点(point2)和第三个点(point3),其中第三个点是圆弧上的任意一点。
绘制圆弧的原理是通过计算得出圆的中心点(center)、半径(radius)以及起始角度(startAngle)和终止角度(endAngle)来确定圆弧的形状,具体的步骤如下:

1.首先通过三个点计算出圆的中心点(center)。这可以通过计算两条垂直平分线的交点来实现。假设已知点Apoint1)、点Bpoint2)和点Cpoint3),则可以计算出AB线段的中点和垂直于AB的斜率,再计算出BC线段的中点和垂直于BC的斜率,最后求出这两条垂直平分线的交点即为圆的中心点。

2.接下来,通过圆心和起点(point1)的距离来确定圆的半径(radius)。

3.然后,通过计算圆心到起点、圆心到终点和圆心到第三个点的角度,可以得到起始角度(startAngle)和终止角度(endAngle)。这可以通过三角函数来计算得出。

4.最后,根据圆弧的顺时针或逆时针方向进行调整。如果是顺时针方向,且起始角度小于终止角度,则将起始角度加上;如果是逆时针方向,且起始角度大于终止角度,则将终止角度加上

通过以上步骤,使用给定的三个点来计算出圆弧中心点(center)、半径(radius)、起始角度(startAngle)和终止角度(endAngle,从而通过THREE.EllipseCurve计算得出最终构成圆弧的(向量集合)points并通过mxdraw提供的自定义形状图形类[MxDbShape]渲染绘制出圆弧。


Mx3PointArc基础继承

要实现两点画圆弧,就要自动去计算point3的位置我们先继承Mx3PointArc, 重写一些简单的代码

import{ Mx3PointArc } from "mxdraw"
class MxDbArc extends Mx3PointArc {
  get startPoint() {
    return this.point1
  }
  set startPoint(v) {
    this.point1 = v
  }
  get endPoint() {
    return this.point2
  }
  set endPoint(v) {
    this.point2 = v
  }
  getTypeName(): string {
    return "MxDbArc"
  }
  getGripPoints(): THREE.Vector3[] {
    return [this.point1, this.point2, this.point3]
  }
}

上面的代码我们继承了Mx3PointArc 并重写了图形类的名称和显示的控制夹点数量并且新增了startPointendPoint 访问器,这样变量命名的意思更加明确。


计算point3(圆弧中点)

下面计算this.point3控制点, 在绘制完成后,这个控制点是一个弧线中点的位置所以我们在绘制时可以把this.point3当成弧线中点计算, 以下是具体代码:
import{ Mx3PointArc, McGiWorldDrawType,  McGiWorldDraw } from "mxdraw"
class MxDbArc extends Mx3PointArc {
  // ...
  worldDraw(pWorldDraw: McGiWorldDraw): void {
    // 这里比较特殊, 只有在动态拖动的绘制时去计算中点,才能达到我们想要的效果
    if(pWorldDraw.getType() === McGiWorldDrawType.kDynDragDraw) {
    //   计算中点 如果没有成功计算中点,我们也需要一个点来支撑下次的中点运算,
    //所以this.point3如果发现没有成功计算中点是需要一个默认值的
      this.point3 = this.getArcMidPoint()
      if(! this.point3 ) this.point3 = new THREE.Vector3(this.point1.x, this.point2.y)
    }
    super.worldDraw(pWorldDraw)
  }
  // 默认圆弧是不需要闭合的
  closed = false
  /** 获取圆弧线中点坐标 */
  getArcMidPoint() {
    const THREE = MxFun.getMxFunTHREE()
    let { startAngle, endAngle, center, radius, clockwise, autoClockwise } = this
    if(center.x ===0 && center.y ===0) return
    // 这里主要是更新计算必要的一些构成圆弧的参数 圆心、半径、角度、顺逆时针
    this.upDateCenter(this.point1, this.point2, this.point3)
    this.upDateRadius(this.point1)
    const [angle1, angle2, angle3] = this.compute3PointAngle()
    this.startAngle = THREE.MathUtils.degToRad(angle1)
    this.endAngle = THREE.MathUtils.degToRad(angle2)
    this.upDataClockwise(angle1, angle2, angle3)
    // 根据顺逆时针方向进行调整
    if (clockwise) {
      if (startAngle < endAngle) {
        startAngle += 2 * Math.PI;
      }
    } else {
      if (startAngle > endAngle) {
        endAngle += 2 * Math.PI;
      }
    }
    const midAngle = (startAngle + endAngle) / 2;
    const midX = center.x + radius * Math.cos(midAngle);
    const midY = center.y + radius * Math.sin(midAngle);
    return new THREE.Vector3(midX, midY, 0)
  }
}



实现绘制函数

现在实现以下绘制函数,其他就算得到圆弧开始点和结束点:

import{ MrxDbgUiPrPoint, MxFun } from "mxdraw"
const drawArc = async () => {
  const getPoint = new MrxDbgUiPrPoint()
  const arc = new MxDbArc()
  const p1 = await getPoint.go()
  if (!p1) return
  arc.startPoint = p1
  getPoint.setUserDraw((point, draw) => {
    arc.endPoint = point
    draw.drawCustomEntity(arc)
  })
  const p2 = await getPoint.go()
  if (!p2) return
  arc.endPoint = p2
  MxFun.getCurrentDraw().addMxEntity(arc)
}

最后在需要画圆弧的时候调用drawArc就可以通过指定开始点和结束点来确定一个圆弧了效果图如下:

第一次绘制过程中的截图:
点击圆弧中点拖动圆弧.png
绘制完成点击圆弧中点拖动的截图:
绘制圆弧.png
当然还有其他方式可以实现两点绘制圆弧, 目前这种方式是比较简单实用的一些使用mxdraw的技巧。

我们可以通过mxdraw提供的各种图形类去继承或者组合去实现更多好用且实用的图形和绘制能力。


Demo源码:




论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-10-18 13:00 , Processed in 0.387352 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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