affine.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 216 行
CPP
216 行
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : affine.cpp //
// Description: Affine transformation //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <math.h>
#include "Affine.h"
// Reset to identity transform
void KAffine::Reset()
{
m_xm.eM11 = 1;
m_xm.eM12 = 0;
m_xm.eM21 = 0;
m_xm.eM22 = 1;
m_xm.eDx = 0;
m_xm.eDy = 0;
}
// Copy transform if valid
BOOL KAffine::SetTransform(const XFORM & xm)
{
if ( xm.eM11 * xm.eM22 == xm.eM12 * xm.eM21 )
return FALSE;
m_xm = xm;
return TRUE;
}
// transform = transform * b
BOOL KAffine::Combine(const XFORM & b)
{
if ( b.eM11 * b.eM22 == b.eM12 * b.eM21 )
return FALSE;
XFORM a = m_xm;
// 11 12 11 12
// 21 22 21 22
m_xm.eM11 = a.eM11 * b.eM11 + a.eM12 * b.eM21;
m_xm.eM12 = a.eM11 * b.eM12 + a.eM12 * b.eM22;
m_xm.eM21 = a.eM21 * b.eM11 + a.eM22 * b.eM21;
m_xm.eM22 = a.eM21 * b.eM12 + a.eM22 * b.eM22;
m_xm.eDx = a.eDx * b.eM11 + a.eDy * b.eM21 + b.eDx;
m_xm.eDy = a.eDx * b.eM12 + a.eDy * b.eM22 + b.eDy;
return TRUE;
}
// transform = 1 / transform
// M = A * x + B
// Inv(M) = Inv(A) * x - Inv(A) * B
BOOL KAffine::Invert(void)
{
FLOAT det = m_xm.eM11 * m_xm.eM22 - m_xm.eM21 * m_xm.eM12;
if ( det==0 )
return FALSE;
XFORM old = m_xm;
m_xm.eM11 = old.eM22 / det;
m_xm.eM12 = - old.eM12 / det;
m_xm.eM21 = - old.eM21 / det;
m_xm.eM22 = old.eM11 / det;
m_xm.eDx = - ( m_xm.eM11 * old.eDx + m_xm.eM21 * old.eDy );
m_xm.eDy = - ( m_xm.eM12 * old.eDx + m_xm.eM22 * old.eDy );
return TRUE;
}
BOOL KAffine::Translate(FLOAT dx, FLOAT dy)
{
m_xm.eDx += dx;
m_xm.eDy += dy;
return TRUE;
}
BOOL KAffine::Scale(FLOAT sx, FLOAT sy)
{
if ( (sx==0) || (sy==0) )
return FALSE;
m_xm.eM11 *= sx;
m_xm.eM12 *= sx;
m_xm.eM21 *= sy;
m_xm.eM22 *= sy;
m_xm.eDx *= sx;
m_xm.eDy *= sy;
return TRUE;
}
BOOL KAffine::Rotate(FLOAT angle, FLOAT x0, FLOAT y0)
{
XFORM xm;
Translate(-x0, -y0); // make (x0,y0) the origin
double rad = angle * (3.14159265359 / 180);
xm.eM11 = (FLOAT) cos(rad);
xm.eM12 = (FLOAT) sin(rad);
xm.eM21 = - xm.eM12;
xm.eM22 = xm.eM11;
xm.eDx = 0;
xm.eDy = 0;
Combine(xm); // rotate
Translate(x0, y0); // move origin back
return TRUE;
}
// Find a transform which maps (0,0) (1,0) (0,1) to p, q, and r respectively
BOOL KAffine::MapTri(FLOAT px0, FLOAT py0, FLOAT qx0, FLOAT qy0, FLOAT rx0, FLOAT ry0)
{
// px0 = dx, qx0 = m11 + dx, rx0 = m21 + dx
// py0 = dy, qy0 = m12 + dy, ry0 = m22 + dy
m_xm.eM11 = qx0 - px0;
m_xm.eM12 = qy0 - py0;
m_xm.eM21 = rx0 - px0;
m_xm.eM22 = ry0 - py0;
m_xm.eDx = px0;
m_xm.eDy = py0;
return m_xm.eM11 * m_xm.eM22 != m_xm.eM12 * m_xm.eM21;
}
// Find a transform which maps p0, q0, and r0 to p1, p1 and r1 respectively
BOOL KAffine::MapTri(FLOAT px0, FLOAT py0, FLOAT qx0, FLOAT qy0, FLOAT rx0, FLOAT ry0,
FLOAT px1, FLOAT py1, FLOAT qx1, FLOAT qy1, FLOAT rx1, FLOAT ry1)
{
if ( ! MapTri(px0, py0, qx0, qy0, rx0, ry0) )
return FALSE;
Invert(); // transform p0, q0, and r0 back to (0,0),(1,0),(0,1)
KAffine map1;
if (! map1.MapTri(px1, py1, qx1, qy1, rx1, ry1) )
return FALSE;
return Combine(map1.m_xm); // then to p1,r1,q1
}
// get the combined world to device coordinate space mapping
BOOL KAffine::GetDPtoLP(HDC hDC)
{
if ( ! GetWorldTransform(hDC, & m_xm) )
return FALSE;
POINT origin;
GetWindowOrgEx(hDC, & origin);
Translate( - (FLOAT) origin.x, - (FLOAT) origin.y);
SIZE sizew, sizev;
GetWindowExtEx (hDC, & sizew);
GetViewportExtEx(hDC, & sizev);
Scale( (FLOAT) sizew.cx/sizev.cx, (FLOAT) sizew.cy/sizev.cy);
GetViewportOrgEx(hDC, & origin);
Translate( (FLOAT) origin.x, (FLOAT) origin.y);
return TRUE;
}
void minmax(int x0, int x1, int x2, int x3, int & minx, int & maxx)
{
if ( x0<x1 )
{
minx = x0; maxx = x1;
}
else
{
minx = x1; maxx = x0;
}
if ( x2<minx)
minx = x2;
else if ( x2>maxx)
maxx = x2;
if ( x3<minx)
minx = x3;
else if ( x3>maxx)
maxx = x3;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?