The function acedXformSS() transforms a selection set by applying a transformation matrix (of type ads_matrix) to the entities in the set.
This provides an efficient alternative to invoking the ROTATE, SCALE, MIRROR, or MOVE commands with acedCommandS()/acedCommandC()/ (or acedCmd()/acedCmdC()) or to changing values in the database with acdbEntMod().
The selection set can be obtained in any of the usual ways. The matrix must do uniform scaling. That is, the elements in the scaling vector S X S Y S Z must all be equal; in matrix notation, M 00 M 11 M 22 .
If the scale vector is not uniform, acedXformSS() reports an error.
The following sample code gets a selection set by using a crossing box, and then applies the following matrix to it.
Applying this matrix scales the entities by one-half (which moves them toward the origin) and translates their location by (20.0,5.0).
int rc, i, j; ads_point pt1, pt2; ads_matrix matrix; ads_name ssname; // Initialize pt1 and pt2 here. rc = acedSSGet("C", pt1, pt2, NULL, ssname); if (rc == RTNORM) { // Initialize to identity. ident_init(matrix); // Initialize scale factors. matrix[0][0] = matrix[1][1] = matrix[2][2] = 0.5; // Initialize translation vector. matrix[0][T] = 20.0; matrix[1][T] = 5.0; rc = acedXformSS(ssname, matrix); }
When you invoke acedDragGen(), you must specify a similar function to let users interactively control the effect of the transformation. The function's declaration must have the following form:
int scnf(ads_point pt, ads_matrix mt)
It should return RTNORM if it modified the matrix, RTNONE if it did not, or RTERROR if it detects an error.
The acedDragGen() function calls the scnf function every time the user moves the cursor. The scnf() function sets the new value of the matrix mt. When scnf() returns with a status of RTNORM, acedDragGen() applies the new matrix to the selection set. If there is no need to modify the matrix (for example, if scnf() simply displays transient vectors with acedGrVecs()), scnf() should return RTNONE. In this case, acedDragGen() ignores mt and doesn't transform the selection set.
In the following example, the function sets the matrix to simply move (translate) the selection set without scaling or rotation.
int dragsample(usrpt, matrix) ads_point usrpt ads_matrix matrix; { ident_init(matrix); // Initialize to identity. // Initialize translation vector. matrix[0][T] = usrpt[X]; matrix[1][T] = usrpt[Y]; matrix[2][T] = usrpt[Z]; return RTNORM; // Matrix was modified. }
Conversely, the following version of dragsample() scales the selection set in the current XY plane but doesn't move it.
int dragsample(usrpt, matrix) ads_point usrpt ads_matrix matrix; { ident_init(matrix); // Initialize to identity. matrix[0][0] = userpt[X]; matrix[1][1] = userpt[Y]; return RTNORM; // Matrix was modified. }
A call to acedDragGen() that employs the transformation function looks like this:
int rc; ads_name ssname; ads_point return_pt; // Prompt the user for a general entity selection: if (acedSSGet(NULL, NULL, NULL, NULL, ssname) == RTNORM) rc = acedDragGen(ssname, // The new entities "Scale the selected objects by dragging", // Prompt 0, // Display normal cursor (crosshairs) dragsample, // Pointer to the transform function return_pt); // Set to the specified location
More complex transformations can rotate entities, combine transformations (as in the acedXformSS() example), and so forth.
Combining transformation matrices is known as matrix composition. The following function composes two transformation matrices by returning their product in resmat.
void xformcompose(ads_matrix xf1, ads_matrix xf2, ads_matrix resmat) { int i, j, k; ads_real sum; for (i=0; i<=3; i++) { for (j=0; j<=3; j++) { sum = 0.0; for (k=0; k<3; k++) { sum += xf1[i,k] * xf2[k,j]; } resmat[i,j] = sum; } } }