- UID
- 1
- 积分
- 15891
- 精华
- 贡献
-
- 威望
-
- 活跃度
-
- D豆
-
- 在线时间
- 小时
- 注册时间
- 2002-1-3
- 最后登录
- 1970-1-1
|
发表于 2017-2-28 17:59:30
|
显示全部楼层
下面文章是将关于矩阵的,你参考下
Question
How do I build a transformation matrix to be used to manipulate entities when I
have only a position, normal vector, scale and rotation?
Answer
You may use AcGeMatrix3d members to create your transformation matrix directly.
First, given the normal (Z Axis), you must construct the remaining axes (X and
Y). AutoCAD can construct one of them (X) for you using the perpVector() method
(perpVector() generates a perpendicular vector based upon the 'Arbitrary Axis
Algorithm'). The third axis (Y) can be created by calculating the cross-product
between the X and Z axes. Since you plan on rotating your entities, you may
need to know how this arbitrary axis is calculated. Here is a pseudocode breakdown.
(Vec is the argument passed to perpVector())
If abs(X and Y) of Vec(X,Y,Z) are both < .015625 (1/64), then
newVec.X=Vec.Z
newVec.Y=0.0
newVec.Z=-Vec.X
Otherwise
newVec.X=Vec.Y
newVec.Y=Vec.X
newVec.Z=0.0
(Note: either of these result axes are perpendicular to Vec.)
Once the X, Y, Z axes have been defined, you can use the setCoordSystem() method
of AcGeMatrix3d. setCoordSystem takes an origin PT, and the X,Y,Z vectors as
arguments to create a composite transformation matrix that, when applied, can
perform both rotation and translation on entities or geometry. Rotation and
scaling can be accomplished by creating matrices and applying them (multiplying)
to the coordinate system matrix you have just defined. Use the setToRotation()
and setToScaling() member functions of AcGeMatrix3d to create them, and once
created, you just multiply them with the coordinate system matrix. Remember
that matrix multiplication is not always commutative so care is needed in the
multiplication order.
Example: (no error checking...)
AcGeVector3d xAxis=normal.perpVector(); // Get a perpendicular vector
(Arbitrary Axis Algorithm) for the X Axis
AcGeVector3d yAxis=zAxis.crossProduct(xAxis); // get the Y Axis
AcGeMatrix3d rotMat,scaleMat,transMat,coordSysMat;
rotMat.setToRotation(rotation,normal); // Create a rotation matrix
scaleMat=scale.operator AcGeMatrix3d();// Create a scale matrix from your AcGeScale object
transMat.setToTranslation(asVec3d(asDblArray(position)));// Create a
translation matrix
coordSysMat.setCoordSystem(AcGePoint3d::kOrigin,
xAxis, yAxis, normal); // Create a coordinate system matrix based upon your axes
coordSysMat = scaleMat * mat; // Scale the matrix...note the multiplication order
coordSysMat = rotMat * coordSysMat; // Rotate the matrix, again note the multiplication order
coordSysMat = transMat * coordSysMat; // Translate the matrix, this has to be last.
I have shown the above method as a means for demonstrating some techniques for
matrix manipulation in AutoCAD. However, an alternate approach, since you know
the rotation angle, would be to rotate the vectors before you create the coordSys
matrix. This way, you reduce the number of matrix multiplications, thereby speeding
up your code.
Example:
AcGeMatrix3d coordSysMat;
AcGeVector3d xAxis=normal.perpVector(); // Get a perpendicular vector
(Arbitrary Axis Algorithm) for the X Axis
AcGeVector3d yAxis=zAxis.crossProduct(xAxis); // get the Y Axis
xAxis.rotateBy(rotation,normal);
yAxis.rotateBy(rotation,normal);
coordSysMat.setCoordSystem(position,xAxis,yAxis,normal); // create the
composite matrix.
// Notice the 'position' value can be used instead of 'kOrigin' since no further transformations are required.
And yet another alternate approach: If you need to scale the matrix you would
need to also add the transformation matrix, because it needs to be last:
AcGeMatrix3d scaleMat,transMat,coordSysMat;
AcGeVector3d xAxis=normal.perpVector(); // Get a perpendicular vector
(Arbitrary Axis Algorithm) for the X Axis
AcGeVector3d yAxis=zAxis.crossProduct(xAxis); // get the Y Axis
xAxis.rotateBy(rotation,normal);
yAxis.rotateBy(rotation,normal);
scaleMat=scale.operator AcGeMatrix3d(); // Create a scale matrix from your AcGeScale object
transMat.setToTranslation(asVec3d(asDblArray(position)));
coordSysMat.setCoordSystem(AcGePoint3d::kOrigin,xAxis,yAxis,normal);
coordSysMat=scaleMat * CoordSysMat;
mat = transMat * CoordSysMat;
You can use the transformBy() method of an entity along with this matrix to
map world coordinates (WCS) into the MCS (WCS within the block reference), or
invert() the matrix to map MCS coordinates into world coordinates.
|
|