How to customize an isosceles triangle in online CAD (mxdraw library)
Published: 2024-03-08 08:37:56

## preamble
Web CAD refers to computer-aided design software that can be run in a Web browser, also known as WebCAD, which can be interacted and operated through a Web browser so that users do not need to download and install CAD applications, but rather browse, modify, interact with and save CAD drawings directly on the Web interface. Nowadays, web-based CAD has become a popular design tool and many designers and engineers are using it for their design work. However, due to the functionality and performance limitations of the web version of CAD , it still has certain limitations relative to the desktop version of CAD, the following we use the industry's representative product dream CAD cloud diagram (H5 online CAD), to complete a custom isosceles triangle graphics.

## Write an isosceles triangle shape class
1. We know that to form a triangle we must need three points, so we can extend a triangle with the custom shape class MxDbShape provided by the mxdraw library.
1) First of all, we are in the src/App.vue file to find hit <script setup lang="ts"></script> in the contents of continue to write down, the code is as follows:

```
import { MxDbShape } from "mxdraw"
// ... Other content
export class MxDbTriangle extends MxDbShape { 
     // This is necessary to add a transport value to the points attribute, which represents the coordinates of the three points.
     points: THREE.Vector3[] = []
     protected _propertyDbKeys = [. .this._propertyDbKeys, "points"]
    // We'll just override the getShapePoints method so that we can render the three points directly.
    getShapePoints(): THREE.Vector3[] {
        return this.points
    }
}
```
Above is the implementation of a common triangle class, just add three points to the points, will form a triangle, you can also use other properties to represent the three points of the triangle, such as point1, point2, point3;
2）But the triangle is just a static triangle, you can't move the three points of the triangle, nor can you move the whole triangle;
3）So we can also rewrite a couple of methods to support moving triangles or points that make up triangles on the canvas, as follows:

```
import { MxDbShape } from "mxdraw"
export class MxDbTriangle extends MxDbShape { 
  // ...
  // Calculate the center of the triangle so that we can control the entire triangle from the midpoint.
  getCenter() {
        const _points = this.getShapePoints()
        // Calculate the number of points
        const numPoints = _points.length;
        // Calculate the sum of the vectors with points
        let sum = new THREE.Vector3();
        for (let i = 0; i < numPoints; i++) {
            sum.add(_points[i]);
        }
        const center = sum.divideScalar(numPoints);
        return center
  }
  // Returns the coordinates of multiple points that can be manipulated and moved, only if you know where the point you want to manipulate is located above it.
   getGripPoints() {
        return [... .this.points, this.getCenter()]
    }
    // Here's where we start moving the position of the point. offset is the offset of the mouse click on the action point, so we can change the position of the point by adding it.
    // So if it's the midpoint, we'll offset all three points of the triangle, and that'll move the whole triangle.
    moveGripPointsAt(index: number, offset: THREE.Vector3): boolean {
        if (index === 3) {
            this.points = [this.points[0].clone().add(offset), this.points[1].clone().add(offset), this.points[2].clone().add(offset)]
        } else {
            this.points[index] = this.points[index].clone().add(offset)
        }
        return true
    } 
}
```
2. With triangles, so let's think about what an isosceles triangle looks like. The following is just one way of realizing this, and you can do it in other ways as well.
1) First of all, isosceles triangles are also triangles, so we represent the three points of an isosceles triangle by three points: the bottom start and end points, and the vertex.
2) We need to know the midpoint to calculate the height of the triangle, and then confirm the direction of the triangle through the relationship between the position of the three points, it is best to get the actual location of the vertices of the triangle, the code is as follows:

```
// Isosceles Triangle
export class MxDbIsoscelesTriangle extends MxDbTriangle {
    protected _propertyDbKeys = [... .this._propertyDbKeys]
    getShapePoints() {
        const [baseStart, baseEnd, topPoint] = this.points
        // Calculate the midpoint of the base of an isosceles triangle.
        const midpoint = baseStart.clone().add(baseEnd).multiplyScalar(0.5);
        // Calculate height and vertex position
        const height = topPoint.distanceTo(midpoint);
        // Calculate the position of topPoint with respect to baseStart and baseEnd.
        const baseVector = new THREE.Vector3().subVectors(baseEnd, baseStart).normalize();
        const perpendicularVector = new THREE.Vector3().crossVectors(baseVector, new THREE.Vector3(0, 0, 1)).normalize();
        const direction = new THREE.Vector3().subVectors(topPoint, midpoint).dot(perpendicularVector);
        const vertex = midpoint.clone().addScaledVector(perpendicularVector, direction >= 0 ? height : -height);
        // Arrange the three dots counterclockwise.
        const _points = [baseStart, baseEnd, vertex];
        return _points.
    }
    getGripPoints() {
        return [... .this.getShapePoints(), this.getCenter()]
    }
}
```
This is all there is to realizing an isosceles triangle.
3. So we want to draw this isosceles triangle on the canvas should be realized how?
1) First we need to click on a button that indicates to start drawing an isosceles triangle;
2) Then we need to listen to the click event on the canvas and record the click position to convert it to three.js coordinates;
3) Finally, add the coordinate values to the MxDbIsoscelesTriangle instance.
We need the position coordinates of three points, so we need to listen to three clicks. The above steps are a bit tedious, so the mxdraw library provides MrxDbgUiPrPoint to help us simplify the above steps, the code is as follows:

```
import { MrxDbgUiPrPoint } from "mxdraw"
const getPoint = new MrxDbgUiPrPoint()
async function drawTriangle() {
    // represents an isosceles triangle
    const triangle = new MxDbIsoscelesTriangle()
    // This is where you get the first mouse click and automatically convert it to three.js coordinates for you.
    const pt1 = await getPoint.go()
    triangle.points.push(pt1)
    // We may need a drawing process, which can be accomplished in this way
    getPoint.setUserDraw((currentPoint, draw) => {
        // Since this dynamic drawing now has only two known points, it can't form a triangle, so we'll draw a straight line to indicate that we're drawing the base of the triangle
        draw.drawLine(currentPoint, pt1)
    })
    // At this point, the pt2 coordinate is obtained by tapping on the screen as follows
    const pt2 = await getPoint.go()
    triangle.points.push(pt2)
   // Now that the triangle example has two more points, we can draw the triangle directly with the dynamic drawing process, and see in real time what the triangle looks like now.
     getPoint.setUserDraw((currentPoint, draw) => {
        // To set the best point of the triangle
        triangle.points[2] = currentPoint
        // and draw it.
        draw.drawCustomEntity(triangle)
    })
    // Finally, we'll tap the screen again to finalize the shape of the triangle.
    const pt3 = await getPoint.go()
    triangle.points[2] = pt3
  // Finally, add it to the control to render it, and the entire triangle is drawn.
    MxFun.getCurrentDraw().addMxEntity(triangle)
}
// Finally, you can start drawing isosceles triangles by triggering the drawTriangle function when you click the button.
```
4) Let's put this function in a button click event and go ahead and add new code in the <template></template> of App.vue:.

```
<button @click="drawTriangle">Draw Isosceles Triangle</button>
```
Now you can see whether the function of drawing isosceles triangles is realized, the effect is as follows:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00p856bm9udvls54d0ay.png)
Try moving the isosceles triangle by clicking on the center pinch point, the effect is shown below:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ls7lc1ff7rlxmn029n5q.png)

4. We finally concluded that first you need to first build an online CAD web page, where you can draw custom isosceles triangles, followed by the need for the Node environment, the Vite front-end engineering project, the use of mxdraw, the conversion of CAD drawings, the implementation of custom shapes, and custom shapes, we first defined the triangle, and according to the triangle definition of isosceles triangle class. In the rendering, we can see that the isosceles triangle has a stroke effect and a fill effect, these are the functions provided by the base class of the custom shape, and you only need to set the corresponding attributes to achieve the corresponding effect, the attributes and methods of the custom shape class are described in the following.
https://mxcad.github.io/mxdraw_api_docs/classes/MxDbShape.html
Finally there are no problems, and we can get to the root of the project by running the command.

```
npm run build
```
Packaged files with packaged online version of the front-end resources, in the dist directory is the specific packaged code.
DEMO source link: [https://github.com/mxcad/mxdraw-article/tree/master/mxdraw%E5%A6%82%E4%BD%95%E9%85%8D%E5%90%88three.js%E5%AE%9E%E7%8E%B0% E5%B8%A6%E7%BA%BF%E5%AE%BD%E7%9A%84%E7%BA%BF%E6%AE%B5/demo](https://github.com/mxcad/mxdraw-article/tree/master/mxdraw%E5%A6%82%E4%BD%95%E9%85%8D%E5%90%88three.js%E5%AE%9E%E7%8E%B0% E5%B8%A6%E7%BA%BF%E5%AE%BD%E7%9A%84%E7%BA%BF%E6%AE%B5/demo)