Skip to content
On this page

Mathematical Library

In CAD development, the correct use of mathematical libraries is crucial.

We learned from the Quick Start that when we open a drawing and want to manipulate the graphics in various ways, we need various calculations. MXCAD provides some classes to participate in calculations or represent certain data structures.

If you have never dealt with vectors or matrices before, please take the time to understand before continuing to read.

Mathematical system of Geometry Information

In cad, there are many different ways to describe the vertex, edge, line, face, volume and other information of a graph. If we use a different drawing system, each drawing system may have a unique way or a specific API to solve a specific problem or a certain kind of specific problem.

Because there are so many tools to choose from, it is difficult for us to find the most appropriate one.

And if we have only tools to solve specific problems and no unified methodology, then we will not be able to solve the root of the problem once and for all.

Therefore, in graphics, a set of simple mathematical system based on vector and matrix operation is established to describe the geometric information which is not related to each graphics system, and how to use this system to solve the problem of visual graphics presentation.

coordinate system and coordinate Mapping

First, let's take a look at some of the coordinate systems that mxcad might use:

  1. HTML uses the upper-left corner of the window coordinate system as the coordinate origin, x-axis to the right, y-axis down, and the coordinate values correspond to pixel values, which are generally called screen coordinates in CAD.

  2. Webgl coordinate system, mxcad depends on mxdraw, mxdraw internally uses a specific version of the modified three.js, so, generally speaking, we refer to the Three.js coordinate system.

  3. The drawing coordinate system is the drawing coordinate system in cad, and then mxcad and mxdraw generally become document coordinates based on the coordinates of its coordinate system.

  4. CAD coordinate system refers to the coordinate system of CAD drawings. In mxcad, the coordinates of McGePoint3d are CAD drawing coordinates.

The method of transformation between mxcad coordinate systems is listed in mxdraw coordinate conversion. We can directly use the API provided by mxdraw to transform the mxcad-related coordinates.

For example:

ts
Import { MxFun } from "mxdraw"
Import { McGePoint3d } from "mxcad"

Const pt = new McGePoint3d ()
// CAD drawing coordinates to document coordinates
MxFun.cadCoord2Doc (pt.x, pt.y, pt.z)

Although these four coordinate systems are different in origin position, axis direction and coordinate range, they are all Cartesian coordinate systems, so they all meet the characteristics of Cartesian coordinate systems: no matter how the direction of the origin and axis changes, using the same method to draw geometry, their shape and relative position remain the same.

Vector: McGeVector3d

: tip After the introduction of mxcad, the THREE variable is automatically mounted globally to represent three.js. If you find that McGeVector3d can call the toVector3 method to get THREE.Vector3, use the API provided by three.js for vector operation. To turn THREE.Vector3 into McGeVector3d, you only need to use THREE.Vector3 as a parameter of new McGeVector3d. :::

So how do you represent a point and a segment in a Cartesian coordinate system?

The previous example contains three axes x, y, z, so they form a three-dimensional space for drawing, but usually we only need to consider x and y. Therefore, we can use two-dimensional vectors to represent points and line segments on this plane. A two-dimensional vector is actually an array of two values, one is the x coordinate value, the other is the y coordinate value.

Suppose that there is now a vector v in this plane Cartesian coordinate system.

The vector v has two meanings: one is that it can represent a point located at (xPowery) in the coordinate system, and the other is that it can represent a line segment from the origin (0memy) to the coordinate (xmemy).

The same two vectors can also perform mathematical operations:

For example, now there are two vectors, v1 and v2, and if you add them together, the result is equivalent to moving the end point of the v1 vector (x1, y1) a distance in the direction of the v2 vector, which is equal to the length of the v2 vector.

In this way, we can get a new point (x1 + x2, y1 + y2), a new line segment [(0,0), (x1 + x2, y1 + y2)], and a broken line: [(0,0), (x1, y1), (x1 + x2, y1 + y2)].

描述向量数学运算

Second, a vector contains length and direction information. Its length can be expressed by the square root of the sum of x and y squares of vectors.

js
v.length = function () {return Math.hypot (this.x, this.y)}

Its direction can be expressed by the angle with the x-axis, that is:

js
v.dir = function () {return Math.atan2 (this.y, this.x);}

In the above code, the value of Math.atan2 ranges from-π to π, with negative numbers below the x-axis and positive numbers above the x-axis

Finally, according to the definition of length and direction, we can derive a set of relations:

js
v.x = v.length * Math.cos (v.dir)
v.y = v.length * Math.sin (v.dir)

This corollary implies an important fact: we can simply construct a drawing vector. That is, if we want to draw a line segment of length length along a certain direction, starting with a point (x0, y0), we only need to construct the following vector.

js
// Dir is the direction of a vector (angle with the x axis), and length is the length of the vector.
function createV1(dir, length) {
    return {
        x: length * Math.cos(dir),
        y: length * Math.sin(dir)
    }
}
var v0 = { x: 0, y: 0 }
var v1 = createV1(Math.PI / 5, 30)
// Then we add the vector (x0, y0) to this vector v1, and we get the end of the line.

The corresponding methods McGeVector3d.length and McGeVector3d.angleTo1 are also provided in mxcad to calculate the vector length and direction angle.

There are also two vectors added together McGeVector3d.add you can choose to use the API we provide to simplify the above operations.

There is a vector THREE.Vector3 in three.js and the corresponding McGeVector3d in mxcad represents a vector (vector) in 3D space.

In this class, four axes kXAxis, kYAxis, kZAxis and kNegateZAxis are fixed vectors, respectively.

THREE.Vector3 is completely equivalent to McGeVector3d, except that it is McGeVector3d that participates in operation with other data in mxcad.

Here is a brief explanation of some of the vector operations provided by mxcad:

ts
import { McGeVector3d } from "mxcad"
const vet = new McGeVector3d(1, 0, 0)
// Get THREE.Vector3
const tVet = vet.toVector3()
const newVet = new McGeVector3d(tVet)
// Rotation
tVet.rotateBy(Math.PI. McGeVector3d.kXAxis)
// negated
vet.negate()
// Vertical 90 degrees
vet.perpVector()
// Calculate the angle between two vectors
vet.angleTo1(newVet)
vet.angleTo1(newVet,  McGeVector3d.kZAxis)
// Normalization
vet.normalize()
// dot product
vet.dotProduct(newVet)
// crossed product
vet.crossProduct(newVet)
// Is it equal?
vet.isEqualTo(newVet)
// Multiply a vector by a value
vet.mult(10)

You can refer to Mathematics Library demonstration effect and click to get the length and angle of the vector and get a line through a vector according to the direction and distance to see if the corresponding method is used correctly. As in the code above, we use a lot of vector operations, maybe you don't understand what they mean, let's explain it briefly:

addition and subtraction of vectors

Their calculations are easier to calculate:

js
//  For example, vector v + vector v1:
(v.x + v1.x, v.y + v1.y)
// For example, vector v -vector v1:
(v.x - v1.x, v.y - v1.y)

So how do they understand that they get vectors by adding and subtracting?

向量相加 Each vector is connected from beginning to end in turn, and the result is that the starting point of the first vector points to the end vector a plus vector b of the last vector. After connecting an and b, the starting point of a points to the end of b, that is, a + b.

向量相减 Translate two vectors to the common starting point O, point from the end point B of the subtraction vector to the end point An of the subtracted vector A, subtract the starting point of the vector an and the vector b to the common starting point O in the lower left corner, and the vector pointing from point B to point An is a-b.

It may be more abstract to understand. It is easier to understand by clicking on the addition and subtraction of the vector in Mathematical Library demonstration effect to see the specific effect and source code.

Vector multiplication

There are two kinds of vector multiplication, one is point multiplication and the other is cross multiplication, which have different geometric and physical meanings.

If you do not quite understand after reading, you can click on the vector multiplication in [Mathematical Library demonstration effect] (# Mathematical Library demonstration effect) to see its practical application, and it is easier to understand its concept by reading the source code.

Point multiplication

Suppose that there are two N-dimensional vectors an and b an a = [A1, a2,... bn], b = [b1, b2,... b2]. The dot product code of that vector is as follows:

js
a*b = a1*b1 + a2*b2 + ... + an*bn

In N-dimensional linear space, the geometric meaning of the dot product of an and b vectors is the projection component of a vector multiplied by b vector on a vector. Its physical meaning is equivalent to the work done by a force acting on an object to produce b displacement. The dot product formula is shown in the following figure:

向量点乘

Of course, there are two special cases of dot multiplication:

If the vectors an and b are parallel, then the angle between them is 0 °, then a ·b = | a | * | b | it is represented by JavaScript code:

js
a.x * b.x + a.y * b.y === a.length * b.length;

If the vectors of an and b are vertical, then the angle between them is 90 °, then a ·b = 0 is represented by JavaScript code:

js
a.x * b.x + a.y * b.y === 0;

Cross multiplication

There are two differences between cross multiplication and dot multiplication:

First of all, the result of vector cross multiplication is not a scalar, but a vector; secondly, the cross product of two vectors is perpendicular to the coordinate plane composed of two vectors.

In two-dimensional space, for example, the cross product of vectors an and b is equivalent to the product of the vertical projection of vector a (blue arrowhead segment) and vector b (red arrowhead segment). As shown in the following figure, the geometric meaning of two-dimensional vector cross product is the area of parallelogram composed of vectors an and b.

向量叉乘

How to calculate the cross product mathematically? Suppose that there are two three-dimensional vectors a (x1, y1, z1) and b (x2, y2, z2), then the cross product of an and b can be expressed as a determinant of the following graph:

叉乘行列式表示

Where I, j and k are the unit vectors of x, y and z axes, respectively. If we expand this determinant, we can get the following formula:

js
a * b = [y1 * z2 - y2 * z1, - (x1 * z2 - x2 * z1), x1 * y2 - x2 * y1]

The physical meaning of vector cross multiplication in two-dimensional space is the moment of an and b (torque you can understand as the tendency of an object to rotate around an axis under the action of a force.

3D Point: McGePoint3d

This is one of the most commonly used classes: McGePoint3d, representing a point in 3D space.

It consists of three double-precision values: x, y, and z.

typescript
import { McGePoint3d } from "mxcad";
const pt1 = new McGePoint3d(0, 0, 0);
// Or
const pt2 = new McGePoint3d({ x: 0, y: 0, z: 0 });

// Provides some utility methods
// Check if two points are equal
pt1.isEqualTo(pt2);
// Calculate the distance between two points
pt1.distanceTo(pt2);
// Set from a THREE.Vector3
pt1.setFromVector3(new THREE.Vector3());
// Get the corresponding THREE.Vector3
pt1.toVector3();

// Subtract two points to get a new vector
const vector = pt1.sub(pt2);
// Add a vector to get a new position
pt1.addvec(vector);
// Shortened form
pt1.av(vector);

// Subtract a vector to get a new position
pt1.subvec(vector);
// Shortened form
pt1.sv(vector);

We mentioned affine transformation earlier, so what is radiation transformation?

Affine transformation is simply "linear transformation + translation".

For example, setting the transform attribute of CSS on an element is to apply an affine transformation to the element.

The affine transformation of geometry has the following two properties:

  1. Before affine transformation, it is a straight line segment, but after affine transformation, it is still a straight line segment.
  2. Applying the same affine transformation to two straight line segments an and b, the length ratio of the line segments remains unchanged before and after the transformation.

Common forms of affine transformation include translation, rotation, scaling and their combinations.

The simplest thing is translation. In mxcad, you can directly understand that the McGePoint3d point adds a vector McGeVector3d through the addvec method, which is the distance of translating the vector in the direction represented by the vector.

Matrix: McGeMatrix3d

As we know how to translate a point above, we can also rotate and scale a point through a linear transformation.

So what is a linear transformation? we can also get how to rotate and scale through vector operations.

Just rotation and scaling, we choose to express it in the form of a matrix, and the transformation in the form of multiplying the matrix and the vector is called linear transformation.

In addition to the two properties of affine transformation, linear transformation has two additional properties:

  1. Linear transformation does not change the origin of coordinates (because if x 0 and y 0 are equal to zero, then x and y must be equal to 0).
  2. Linear transformations can be superimposed. The superposition result of multiple linear transformations is to multiply the matrices of linear transformations in turn, and then multiply them with the original vector.

Then according to the second property of linear transformation, we can sum up a general linear transformation formula, that is, an original vector P0 passes through M1, M2, … The final coordinate P is obtained after the linear transformation of Mn degree.

In mxcad, the McGeMatrix3d class represents the affine transformation of 3D space.

Usually, we need to represent all kinds of complex radiation transformations formed by the combination of translation, rotation, scaling, etc., by linear transformation.

We just need to convert the original n-dimensional coordinates into nasty 1-dimensional coordinates. This kind of 1-dimensional coordinate is called homogeneous coordinate, and the corresponding matrix is called homogeneous matrix.

Our McGeMatrix3d is also a homogeneous matrix, so we can perform various linear transformations directly through McGeMatrix3d, and finally apply this affine transformation through the vector's transformBy method.

The same matrix can also be applied to all geometric entities McDbEntity.transformBy in mxcad for affine transformation, because all geometry is based on points and lines.

We can regard the point or line as a vector, and the radiative transformation of the entity is equivalent to the radiative transformation of all the points that make up the entity.

McGeMatrix3d represents affine transformations in 3D space.

Matrix multiplication

The multiplication of the matrix actually corresponds to the property that the linear transformation described above can be superimposed.

We hope to form a complex affine transformation through a combination of matrices, that is, the final matrix obtained by multiplying matrices one by one, that is, the complex affine transformation formed by combination.

Two An and B matrices are multiplied. Take An as an example, A can choose left multiplication or right multiplication matrix B.

Left multiplication is B * A, right multiplication is A * B.

Here we can understand the difference between left multiplication and right multiplication through the following figure:

First, suppose the matrix A: 矩阵A

Set the column vector: 列向量

Remove the right multiplication matrix A by column vector 列向量去右乘矩阵A

It is equivalent to a linear combination of the column vectors in matrix A.

Left multiplication of matrix A by column vector 列向量左乘矩阵A

It is equivalent to the left linear combination of row vectors in matrix A.

According to the above concepts, the left multiplication and right multiplication in matrix multiplication are extended to the same idea:

Set up a matrix B: 矩阵B

Use matrix B to multiply matrix A: 矩阵B来左乘矩阵A

Therefore, every row of a new matrix obtained by matrix B left multiplication matrix An is a linear combination of row vectors of matrix A. similarly, every column of a new matrix obtained by matrix B right multiplication matrix An is a linear combination of column vectors of matrix A.

Here are some of the ways McGeMatrix3d offers:

typescript
import { McGeMatrix3d, McGePoint3d, McGeVector3d } from "mxcad";
// Identity matrix for multiplication
McGeMatrix3d.kIdentity;

const m = new McGeMatrix3d();
const m1 = new McGeMatrix3d();

// Set to identity matrix.
m.setToIdentity();

// Pre-multiply by a specified matrix.
const m3 = m.preMultBy(m1);

// Post-multiply by a specified matrix.
m3.postMultBy(m1);

// Set the matrix to the product of two matrices.
new McGeMatrix3d().setToProduct(m1, m2);

// Inverse matrix.
m1.invert();

// Check if the matrix is singular.
m1.isSingular();

// Transpose
m1.transposeIt();

// Check equality
m1.isEqualTo(m2);

// Determinant of the matrix.
m1.det();

// Set the matrix to a specified coordinate system. Parameters are origin, xyz axes
m1.setCoordSystem(new McGePoint3d(), new McGeVector3d(), new McGeVector3d(), new McGeVector3d());

// Translation
m1.setToTranslation(new McGeVector3d(0, 1, 0));

// Rotation: Parameters are angle, axis, rotation center
m1.setToRotation(Math.PI, McGeVector3d.kXAxis, new McGePoint3d());

// Scaling: Parameters are scaling factor, scaling center
m1.setToScaling(0.5, new McGePoint3d());

// Set as a mirror matrix
m1.setMirror(new McGePoint3d(), new McGePoint3d());

// Get scaling factors
m1.scale();

// Get the value of a specified element in the matrix. Parameters are row index, column index
m1.getData(0, 0);

How to use matrix in mxcad, you can view the rotation translation and scaling of points in [MathematicalLibrarydemonstrationeffect](#MathematicalLibrarydemonstration effect) | affine transformation of the entity | it is easier to understand and use by viewing the specific effect and source code.

MxCADResbuf

MxCADResbuf is a data structure used in CAD development to pass data, also known as a "result buffer".

It is commonly used for object property queries, custom object definitions and storage, XDATA (extended data) processing, and editing of drawing entities.

For example, in MxCADSelectionSet, it is used to represent object filters:

typescript
import { MxCADSelectionSet, MxCADResbuf } from "mxcad";
let ss = new MxCADSelectionSet();
let filter = new MxCADResbuf();
// Here, we add the query string "0". The second parameter is data type 8, indicating a null pointer (RTNUL), meaning that this resbuf structure does not contain any valid data. It is typically used as a terminator at the end of a linked list.
filter.AddString("0", 8);
// Select all entities on layer 0
ss.allSelect(filter);
ss.forEach((objId) => console.log(objId));

calcBulge: Calculate Arc Bulge

MxCADUtility is an instance provided by MxCADUtilityClass, offering many useful methods.

MxCADUtility.calcBulge calculates the bulge of an arc.

When adding points to a polyline entity, one parameter is the bulge value. Calculating the bulge can be complex, but MXCAD provides the calcBulge method for this purpose.

It requires three parameters: the start point of the arc, the mid-point of the arc, and the end point of the arc.

typescript
import { MxCADUtility, McGePoint3d, McDbPolyline } from "mxcad";
// Start point of the arc
const startPoint = new McGePoint3d(0, 0, 0);
// Mid-point of the arc
const midPoint = new McGePoint3d(0, 0, 0);
// End point of the arc
const endPoint = new McGePoint3d(0, 0, 0);
const bulge = MxCADUtility.calcBulge(startPoint, midPoint, endPoint).val;
const pl = new McDbPolyline();
pl.addVertexAt(startPoint, bulge);
pl.addVertexAt(endPoint);

This translation is kept as faithful as possible to the original Chinese article.

If you do not know any of the above three parameters, refer to the figure below to calculate the convexity yourself:

圆弧凸度计算公式

The convexity value is half the distance between the start point and the end point of the arc, and the distance from the midpoint of the segment to the center of the arc is connected by the start point of the arc to the end point.

Demonstration effect of math library

The demo is based on vue3 and is based on tsx. Please refer to vue official website Tsx instructions (code can be edited).