【计算机图形学】3-2 二维几何变换基本代码
返回目录
基本理论参见:【计算机图形学】3-1 二维几何变换基本理论
注:这里不考虑插值的问题。
全部的代码都在https://github.com/CyberZHG/ZPIC上,欢迎各位前来围观和提出意见。
效果截图:
移动:
缩放:
旋转:
错切 :
改变旋转中心后的旋转:
transform_matrix.h
#ifndef TRANSFORM_MATRIX_H_INCLUDED
#define TRANSFORM_MATRIX_H_INCLUDED
#include
#include "define.h"
typedef struct Transform_Matrix_9d
{
double m[3][3];
}Transform_Matrix_9d;
void transform_matrix_init(Transform_Matrix_9d *matrix);
void transform_matrix_clear(Transform_Matrix_9d *matrix);
void transform_matrix_add(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2);
void transform_matrix_substract(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2);
void transform_matrix_multiply(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2);
void transform_matrix_copy(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2);
void transform_matrix_transformPoint(const Transform_Matrix_9d matrix, int32 *x, int32 *y);
void transform_matrix_move(Transform_Matrix_9d *matrix, double tx, double ty);
void transform_matrix_scale(Transform_Matrix_9d *matrix, double sx, double sy);
void transform_matrix_rotate(Transform_Matrix_9d *matrix, double angle);
void transform_matrix_shear(Transform_Matrix_9d *matrix, double b, double d);
#endif // TRANSFORM_MATRIX_H_INCLUDED
transform_matrix.c
#include "transform_matrix.h"
void transform_matrix_init(Transform_Matrix_9d *matrix)
{
int32 i, j;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
matrix->m[i][j] = 0.0;
}
matrix->m[i][i] = 1.0;
}
}
void transform_matrix_clear(Transform_Matrix_9d *matrix)
{
int32 i, j;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
matrix->m[i][j] = 0.0;
}
}
}
void transform_matrix_add(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2)
{
int32 i, j;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
m1->m[i][j] += m2.m[i][j];
}
}
}
void transform_matrix_substract(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2)
{
int32 i, j;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
m1->m[i][j] -= m2.m[i][j];
}
}
}
void transform_matrix_multiply(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2)
{
int32 i, j, k;
Transform_Matrix_9d temp;
transform_matrix_clear(&temp);
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
for(k=0;k<3;++k)
{
temp.m[i][j] += m1->m[i][k] * m2.m[k][j];
}
}
}
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
m1->m[i][j] = temp.m[i][j];
}
}
}
void transform_matrix_copy(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2)
{
int32 i, j;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
{
m1->m[i][j] = m2.m[i][j];
}
}
}
void transform_matrix_transformPoint(const Transform_Matrix_9d matrix, int32 *x, int32 *y)
{
int32 tx, ty;
tx = (int)(*x * matrix.m[0][0] + *y * matrix.m[1][0] + matrix.m[2][0]);
ty = (int)(*x * matrix.m[0][1] + *y * matrix.m[1][1] + matrix.m[2][1]);
*x = tx;
*y = ty;
}
void transform_matrix_move(Transform_Matrix_9d *matrix, double tx, double ty)
{
Transform_Matrix_9d moveMatrix;
transform_matrix_init(&moveMatrix);
moveMatrix.m[2][0] = tx;
moveMatrix.m[2][1] = ty;
transform_matrix_multiply(matrix, moveMatrix);
}
void transform_matrix_scale(Transform_Matrix_9d *matrix, double sx, double sy)
{
Transform_Matrix_9d scaleMatrix;
transform_matrix_init(&scaleMatrix);
scaleMatrix.m[0][0] = sx;
scaleMatrix.m[1][1] = sy;
transform_matrix_multiply(matrix, scaleMatrix);
}
void transform_matrix_rotate(Transform_Matrix_9d *matrix, double angle)
{
Transform_Matrix_9d rotateMatrix;
transform_matrix_init(&rotateMatrix);
rotateMatrix.m[0][0] = rotateMatrix.m[1][1] = cos(angle);
rotateMatrix.m[1][0] = - (rotateMatrix.m[0][1] = sin(angle));
transform_matrix_multiply(matrix, rotateMatrix);
}
void transform_matrix_shear(Transform_Matrix_9d *matrix, double b, double d)
{
Transform_Matrix_9d shearMatrix;
transform_matrix_init(&shearMatrix);
shearMatrix.m[0][1] = b;
shearMatrix.m[1][0] = d;
transform_matrix_multiply(matrix, shearMatrix);
}
transform_selection.h
#ifndef TRANSFORM_SELECTION_H_INCLUDED
#define TRANSFORM_SELECTION_H_INCLUDED
#include
#include
#include "define.h"
#include "gui.h"
#include "draw.h"
#include "transform_matrix.h"
typedef struct Transform_Selection_10i2f1m
{
int32 x[4], y[4];
float cx, cy;
draw_color **color;
int32 **px;
int32 **py;
Transform_Matrix_9d transMatrix;
}Transform_Selection_10i2f1m;
void transform_selection_display(void);
void transform_selection_mouseEvent(int32 state, int32 x, int32 y);
void transform_selection_keyboardEvent(int32 key, int32 state);
#endif // TRANSFORM_SELECTION_H_INCLUDED
transform_selection.c
#include "transform_selection.h"
static Transform_Selection_10i2f1m transform_default_selection;
int32 isMovingCenter;
int32 isSelecting;
int32 isSelected;
int32 isMoving;
int32 isResizing;
int32 isRotating;
int32 isShearing;
int32 isMouseDown;
int32 isFinshed;
int32 startX, startY;
int32 endX, endY;
int32 lastEdgeX, lastEdgeY;
Transform_Matrix_9d startMatrix;
int32 isShiftDown;
void transform_selection_display(void)
{
int32 i, j, w, h;
int32 x[4], y[4], mx, my;
float cx, cy;
int32 edgeL, edgeR, edgeB, edgeT;
draw_color **color;
int32 **px, **py;
int32 tx, ty;
Transform_Matrix_9d *matrix = &transform_default_selection.transMatrix;
draw_color penColor = draw_pen_getColor();
draw_color brushColor = draw_brush_getColor();
draw_pen_setColor(DRAW_COLOR_WHITE);
draw_brush_setColor(DRAW_COLOR_BLACK);
for(i=0;i<4;++i)
{
x[i] = transform_default_selection.x[i];
y[i] = transform_default_selection.y[i];
transform_matrix_transformPoint(*matrix, &x[i], &y[i]);
}
edgeL = min(min(x[0], x[1]), min(x[2], x[3]));
edgeR = max(max(x[0], x[1]), max(x[2], x[3]));
edgeB = min(min(y[0], y[1]), min(y[2], y[3]));
edgeT = max(max(y[0], y[1]), max(y[2], y[3]));
mx = (edgeL + edgeR) >> 1;
my = (edgeB + edgeT) >> 1;
cx = transform_default_selection.cx;
cy = transform_default_selection.cy;
w = abs(transform_default_selection.x[0] - transform_default_selection.x[2]) - 1;
h = abs(transform_default_selection.y[0] - transform_default_selection.y[2]) - 1;
color = transform_default_selection.color;
px = transform_default_selection.px;
py = transform_default_selection.py;
if(isSelecting)
{
if(isSelected)
{
for(i=0;i
{
for(j=0;j
{
gui_setPixel_2i1u(px[i][j], py[i][j], DRAW_COLOR_BLACK);
}
}
for(i=0;i
{
for(j=0;j
{
tx = px[i][j], ty = py[i][j];
transform_matrix_transformPoint(*matrix, &tx, &ty);
gui_setPixel_2i1u(tx, ty, color[i][j]);
}
}
if(isFinshed)
{
gui_saveCurrentImage();
isSelecting = 0;
isSelected = 0;
isMoving = 0;
isResizing = 0;
isRotating = 0;
isShearing = 0;
isFinshed = 0;
isMouseDown = 0;
w = abs(transform_default_selection.x[0] - transform_default_selection.x[2]) - 1;
h = abs(transform_default_selection.y[0] - transform_default_selection.y[2]) - 1;
for(i=0;i
{
free(transform_default_selection.color[i]);
free(transform_default_selection.px[i]);
free(transform_default_selection.py[i]);
}
free(transform_default_selection.color);
free(transform_default_selection.px);
free(transform_default_selection.py);
}
else
{
draw_line_4i(edgeL, edgeT, edgeR, edgeT);
draw_line_4i(edgeL, edgeB, edgeR, edgeB);
draw_line_4i(edgeL, edgeT, edgeL, edgeB);
draw_line_4i(edgeR, edgeT, edgeR, edgeB);
draw_dotted_line_4i(x[0], y[0], x[1], y[1]);
draw_dotted_line_4i(x[1], y[1], x[2], y[2]);
draw_dotted_line_4i(x[2], y[2], x[3], y[3]);
draw_dotted_line_4i(x[3], y[3], x[0], y[0]);
draw_rectangle_4i(edgeL - 3, edgeT - 3, edgeL + 3, edgeT + 3);
draw_rectangle_4i(edgeL - 3, edgeB - 3, edgeL + 3, edgeB + 3);
draw_rectangle_4i(edgeR - 3, edgeT - 3, edgeR + 3, edgeT + 3);
draw_rectangle_4i(edgeR - 3, edgeB - 3, edgeR + 3, edgeB + 3);
draw_rectangle_4i(edgeL - 3, my - 3, edgeL + 3, my + 3);
draw_rectangle_4i(mx - 3, edgeB - 3, mx + 3, edgeB + 3);
draw_rectangle_4i(edgeR - 3, my - 3, edgeR + 3, my + 3);
draw_rectangle_4i(mx - 3, edgeT - 3, mx + 3, edgeT + 3);
draw_circle_3i(cx, cy, 3);
if(isMoving)
{
gui_setMainWindowCursor(CURSOR_SIZEALL);
}
else if(isResizing)
{
switch(isResizing)
{
case POSITION_LEFT:
gui_setMainWindowCursor(CURSOR_SIZEWE);
break;
case POSITION_RIGHT:
gui_setMainWindowCursor(CURSOR_SIZEWE);
break;
case POSITION_TOP:
gui_setMainWindowCursor(CURSOR_SIZENS);
break;
case POSITION_BOTTOM:
gui_setMainWindowCursor(CURSOR_SIZENS);
break;
case POSITION_TOPLEFT:
gui_setMainWindowCursor(CURSOR_SIZENESW);
break;
case POSITION_TOPRIGHT:
gui_setMainWindowCursor(CURSOR_SIZENWSE);
break;
case POSITION_BOTTOMLEFT:
gui_setMainWindowCursor(CURSOR_SIZENWSE);
break;
case POSITION_BOTTOMRIGHT:
gui_setMainWindowCursor(CURSOR_SIZENESW);
break;
}
}
else if(isRotating)
{
gui_setMainWindowCursor(CURSOR_NO);
}
else if(isShearing)
{
switch(isShearing)
{
case POSITION_BOTTOM:
case POSITION_TOP:
gui_setMainWindowCursor(CURSOR_SIZEWE);
break;
case POSITION_LEFT:
case POSITION_RIGHT:
gui_setMainWindowCursor(CURSOR_SIZENS);
break;
}
}
}
}
else
{
gui_setMainWindowCursor(CURSOR_CROSS);
draw_dotted_line_4i(x[0], y[0], x[2], y[0]);
draw_dotted_line_4i(x[0], y[2], x[2], y[2]);
draw_dotted_line_4i(x[0], y[0], x[0], y[2]);
draw_dotted_line_4i(x[2], y[0], x[2], y[2]);
}
}
else
{
gui_setMainWindowCursor(CURSOR_CROSS);
}
draw_pen_setColor(penColor);
draw_brush_setColor(brushColor);
}
void transform_selection_mouseEvent(int32 state, int32 x, int32 y)
{
int32 i, j, w, h;
int32 rx[4], ry[4], mx, my, cx, cy;
int32 edgeL, edgeR, edgeB, edgeT;
double angle;
Transform_Matrix_9d *matrix = &transform_default_selection.transMatrix;
for(i=0;i<4;++i)
{
rx[i] = transform_default_selection.x[i];
ry[i] = transform_default_selection.y[i];
transform_matrix_transformPoint(*matrix, &rx[i], &ry[i]);
}
edgeL = min(min(rx[0], rx[1]), min(rx[2], rx[3]));
edgeR = max(max(rx[0], rx[1]), max(rx[2], rx[3]));
edgeB = min(min(ry[0], ry[1]), min(ry[2], ry[3]));
edgeT = max(max(ry[0], ry[1]), max(ry[2], ry[3]));
mx = (edgeL + edgeR) >> 1;
my = (edgeB + edgeT) >> 1;
cx = transform_default_selection.cx;
cy = transform_default_selection.cy;
switch(state)
{
case MOUSE_DOWN_LEFT:
isMouseDown = 1;
if(isSelected)
{
startX = x;
startY = y;
endX = x;
endY = y;
transform_matrix_copy(&startMatrix, *matrix);
if(isResizing)
{
switch(isResizing)
{
case POSITION_LEFT:
lastEdgeX = edgeR;
break;
case POSITION_RIGHT:
lastEdgeX = edgeL;
break;
case POSITION_BOTTOM:
lastEdgeY = edgeT;
break;
case POSITION_TOP:
lastEdgeY = edgeB;
break;
case POSITION_BOTTOMLEFT:
lastEdgeX = edgeR;
lastEdgeY = edgeT;
break;
case POSITION_BOTTOMRIGHT:
lastEdgeX = edgeL;
lastEdgeY = edgeT;
break;
case POSITION_TOPLEFT:
lastEdgeX = edgeR;
lastEdgeY = edgeB;
break;
case POSITION_TOPRIGHT:
lastEdgeX = edgeL;
lastEdgeY = edgeB;
break;
}
}
else if(isShearing)
{
switch(isShearing)
{
case POSITION_BOTTOM:
case POSITION_RIGHT:
lastEdgeX = edgeL;
lastEdgeY = edgeT;
break;
case POSITION_TOP:
case POSITION_LEFT:
lastEdgeX = edgeR;
lastEdgeY = edgeB;
break;
}
}
}
else
{
isSelecting = 1;
transform_default_selection.x[0] = x;
transform_default_selection.y[0] = y;
transform_default_selection.x[2] = x;
transform_default_selection.y[2] = y;
transform_matrix_init(&transform_default_selection.transMatrix);
}
break;
case MOUSE_UP_LEFT:
isMouseDown = 0;
if(isSelecting)
{
if(isSelected)
{
if(isMovingCenter || isMoving || isResizing || isRotating || isShearing)
{
return;
}
if(x < edgeL - 10 || x > edgeR + 10 || y < edgeB - 10 || y > edgeT + 10)
{
isFinshed = 1;
}
}
else
{
transform_default_selection.x[1] = x;
transform_default_selection.y[1] = ry[0];
transform_default_selection.x[3] = rx[0];
transform_default_selection.y[3] = y;
transform_default_selection.x[2] = x;
transform_default_selection.y[2] = y;
transform_default_selection.cx = (transform_default_selection.x[0] +
transform_default_selection.x[2]) >> 1;
transform_default_selection.cy = (transform_default_selection.y[0] +
transform_default_selection.y[2]) >> 1;
isSelected = 1;
w = abs(transform_default_selection.x[0] - transform_default_selection.x[2]) - 1;
h = abs(transform_default_selection.y[0] - transform_default_selection.y[2]) - 1;
transform_default_selection.color = (draw_color**)malloc(sizeof(draw_color*) * h);
transform_default_selection.px = (int32**)malloc(sizeof(int32*) * h);
transform_default_selection.py = (int32**)malloc(sizeof(int32*) * h);
for(i=0;i
{
transform_default_selection.color[i] = (draw_color*)malloc(sizeof(draw_color) * w);
transform_default_selection.px[i] = (int32*)malloc(sizeof(int32) * w);
transform_default_selection.py[i] = (int32*)malloc(sizeof(int32) * w);
for(j=0;j
{
transform_default_selection.color[i][j] = gui_getPixel(min(transform_default_selection.x[0], transform_default_selection.x[2]) + j + 1,
min(transform_default_selection.y[0], transform_default_selection.y[2]) + i + 1);
transform_default_selection.px[i][j] = min(transform_default_selection.x[0], transform_default_selection.x[2]) + j + 1;
transform_default_selection.py[i][j] = min(transform_default_selection.y[0], transform_default_selection.y[2]) + i + 1;
}
}
}
}
break;
case MOUSE_MOVE:
if(isSelecting)
{
if(isSelected)
{
if(isMouseDown)
{
if(isMovingCenter)
{
transform_default_selection.cx += x - endX;
transform_default_selection.cy += y - endY;
endX = x;
endY = y;
}
else if(isMoving)
{
transform_matrix_move(matrix, x - startX, y - startY);
transform_default_selection.cx += x - startX;
transform_default_selection.cy += y - startY;
startX = x;
startY = y;
}
else if(isResizing)
{
transform_matrix_copy(matrix, startMatrix);
switch(isResizing)
{
case POSITION_LEFT:
if(startX != lastEdgeX && endX != lastEdgeX)
{
transform_matrix_move(matrix, - lastEdgeX, 0);
if(x > lastEdgeX)
{
transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
else
{
transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
transform_matrix_move(matrix, lastEdgeX, 0);
}
transform_default_selection.cx += (x - endX) * 0.5;
endX = x;
break;
case POSITION_RIGHT:
if(startX != lastEdgeX && endX != lastEdgeX)
{
transform_matrix_move(matrix, - lastEdgeX, 0);
if(x < lastEdgeX)
{
transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
else
{
transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
transform_matrix_move(matrix, lastEdgeX, 0);
}
transform_default_selection.cx += (x - endX) * 0.5;
endX = x;
break;
case POSITION_BOTTOM:
if(startY != lastEdgeY && endY != lastEdgeY)
{
transform_matrix_move(matrix, 0, - lastEdgeY);
if(y > lastEdgeY)
{
transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
else
{
transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
transform_matrix_move(matrix, 0, lastEdgeY);
}
transform_default_selection.cy += (y - endY) * 0.5;
endY = y;
break;
case POSITION_TOP:
if(startY != lastEdgeY && endY != lastEdgeY)
{
transform_matrix_move(matrix, 0, - lastEdgeY);
if(y < lastEdgeY)
{
transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
else
{
transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
transform_matrix_move(matrix, 0, lastEdgeY);
}
transform_default_selection.cy += (y - endY) * 0.5;
endY = y;
break;
case POSITION_BOTTOMLEFT:
if(startX != lastEdgeX && endX != lastEdgeX)
{
transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY);
if(x > lastEdgeX)
{
transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
else
{
transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
if(y > lastEdgeY)
{
transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
else
{
transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
}
transform_default_selection.cx += (x - endX) * 0.5;
transform_default_selection.cy += (y - endY) * 0.5;
endX = x;
endY = y;
break;
case POSITION_BOTTOMRIGHT:
if(startX != lastEdgeX && endX != lastEdgeX)
{
transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY);
if(x < lastEdgeX)
{
transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
else
{
transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
if(y > lastEdgeY)
{
transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
else
{
transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
}
transform_default_selection.cx += (x - endX) * 0.5;
transform_default_selection.cy += (y - endY) * 0.5;
endX = x;
endY = y;
break;
case POSITION_TOPLEFT:
if(startX != lastEdgeX && endX != lastEdgeX)
{
transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY);
if(x > lastEdgeX)
{
transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
else
{
transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
if(y < lastEdgeY)
{
transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
else
{
transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
}
transform_default_selection.cx += (x - endX) * 0.5;
transform_default_selection.cy += (y - endY) * 0.5;
endX = x;
endY = y;
break;
case POSITION_TOPRIGHT:
if(startX != lastEdgeX && endX != lastEdgeX)
{
transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY);
if(x < lastEdgeX)
{
transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
else
{
transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0);
}
if(y < lastEdgeY)
{
transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
else
{
transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY));
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
}
transform_default_selection.cx += (x - endX) * 0.5;
transform_default_selection.cy += (y - endY) * 0.5;
endX = x;
endY = y;
break;
}
}
else if(isRotating)
{
transform_matrix_copy(matrix, startMatrix);
angle = atan2(y - cx, x - cy) - atan2(startY - cy, startX - cx);
transform_matrix_move(matrix, -cx, -cy);
transform_matrix_rotate(matrix, angle);
transform_matrix_move(matrix, cx, cy);
}
else if(isShearing)
{
switch(isShearing)
{
case POSITION_BOTTOM:
transform_matrix_copy(matrix, startMatrix);
transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY);
if(x > lastEdgeX)
{
transform_matrix_shear(matrix, 0.0, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0);
}
else
{
transform_matrix_shear(matrix, 0.0, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0);
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
transform_default_selection.cx += x - endX;
endX = x;
break;
case POSITION_RIGHT:
transform_matrix_copy(matrix, startMatrix);
transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY);
if(y < lastEdgeY)
{
transform_matrix_shear(matrix, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0);
}
else
{
transform_matrix_shear(matrix, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0);
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
transform_default_selection.cy += y - endY;
endY = y;
break;
case POSITION_TOP:
transform_matrix_copy(matrix, startMatrix);
transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY);
if(x < lastEdgeX)
{
transform_matrix_shear(matrix, 0.0, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0);
}
else
{
transform_matrix_shear(matrix, 0.0, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0);
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
transform_default_selection.cx += x - endX;
endX = x;
break;
case POSITION_LEFT:
transform_matrix_copy(matrix, startMatrix);
transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY);
if(y > lastEdgeY)
{
transform_matrix_shear(matrix, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0);
}
else
{
transform_matrix_shear(matrix, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0);
}
transform_matrix_move(matrix, lastEdgeX, lastEdgeY);
transform_default_selection.cy += y - endY;
endY = y;
break;
}
}
}
else
{
if(abs(x - cx) <= 4 && abs(y - cy) <= 4)
{
isMovingCenter = 1;
isMoving = 0;
isResizing = 0;
isRotating = 0;
isShearing = 0;
return;
}
if(abs(x - edgeL) <= 4 && abs(y - my) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_LEFT;
return;
}
if(abs(x - edgeR) <= 4 && abs(y - my) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_RIGHT;
return;
}
if(abs(x - mx) <= 4 && abs(y - edgeB) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_BOTTOM;
return;
}
if(abs(x - mx) <= 4 && abs(y - edgeT) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_TOP;
return;
}
if(abs(x - edgeL) <= 4 && abs(y - edgeT) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_TOPLEFT;
return;
}
if(abs(x - edgeL) <= 4 && abs(y - edgeB) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_BOTTOMLEFT;
return;
}
if(abs(x - edgeR) <= 4 && abs(y - edgeT) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_TOPRIGHT;
return;
}
if(abs(x - edgeR) <= 4 && abs(y - edgeB) <= 4)
{
isMovingCenter = 0;
isMoving = 0;
isRotating = 0;
isShearing = 0;
isResizing = POSITION_BOTTOMRIGHT;
return;
}
if(x > edgeL + 4 && x < edgeR - 4 && y > edgeB + 4 && y < edgeT - 4)
{
isMovingCenter = 0;
isResizing = 0;
isRotating = 0;
isShearing = 0;
isMoving = 1;
return;
}
if((x > edgeR + 4 && x <= edgeR + 8 && y < edgeB - 4 && y >= edgeB - 8))
{
isMovingCenter = 0;
isResizing = 0;
isRotating = 1;
isShearing = 0;
isMoving = 0;
return;
}
if(x >= edgeR - 4 && x < edgeR && y < edgeB - 4 && y >= edgeB - 8)
{
isMovingCenter = 0;
isResizing = 0;
isRotating = 0;
isShearing = POSITION_BOTTOM;
isMoving = 0;
return;
}
if(x > edgeR + 4 && x <= edgeR + 8 && y <= edgeB + 4 && y > edgeB)
{
isMovingCenter = 0;
isResizing = 0;
isRotating = 0;
isShearing = POSITION_RIGHT;
isMoving = 0;
return;
}
if(x > edgeL && x <= edgeL + 4 && y > edgeT + 4 && y <= edgeT + 8)
{
isMovingCenter = 0;
isResizing = 0;
isRotating = 0;
isShearing = POSITION_TOP;
isMoving = 0;
return;
}
if(x > edgeL - 8 && x <= edgeL - 4 && y >= edgeT - 4 && y < edgeT)
{
isMovingCenter = 0;
isResizing = 0;
isRotating = 0;
isShearing = POSITION_LEFT;
isMoving = 0;
return;
}
isMovingCenter = 0;
isMoving = 0;
isResizing = 0;
isRotating = 0;
isShearing = 0;
}
}
else
{
transform_default_selection.x[2] = x;
transform_default_selection.y[2] = y;
}
}
break;
case MOUSE_DOWN_RIGHT:
if(isSelecting)
{
isSelecting = 0;
}
break;
}
}
void transform_selection_keyboardEvent(int32 key, int32 state)
{
switch(state)
{
case KEY_STATE_DOWN:
switch(key)
{
case KEY_VALUE_SHIFT:
isShiftDown = 1;
}
break;
case KEY_STATE_UP:
switch(key)
{
case KEY_VALUE_SHIFT:
isShiftDown = 0;
}
break;
}
}