📄 screctpoly.cpp
字号:
/*
* This file is part of the EMFexplorer projet.
* Copyright (C) 2004 Smith Charles.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* Extension: for commercial use, apply the Equity Public License, which
* adds to the normal terms of the GLPL a condition of donation to the author.
* If you are interested in support for this source code,
* contact Smith Charles <smith.charles@free.fr> for more information.
*/
#include "stdafx.h"
#include "SCRectPoly.h"
#include "SCGenInclude.h"
#include SC_INC_GENLIB(SCGenMath.h)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void SCRectPolygon::SCRotate(int iAngle, int xc, int yc)
{
// this is the angle of rotation for y growing down
double fAngle = -(iAngle/1800.0f)*SC_PI;
double cosAngle = cos(fAngle);
double sinAngle = sin(fAngle);
POINT *pPt = this->m_Points;
int itmpx;
for (int i=0; i<4; i++, pPt++)
{
itmpx = pPt->x;
pPt->x = static_cast<int>(0.5f + xc + (itmpx - xc)*cosAngle - (pPt->y - yc)*sinAngle);
pPt->y = static_cast<int>(0.5f + yc + (itmpx - xc)*sinAngle + (pPt->y - yc)*cosAngle);
}
}
#ifdef _DEBUG
void SCRectPolygon::SCTestDraw(HDC hdc)
{
// Save position
POINT PtPos;
MoveToEx(hdc, m_Points[cnr_LT].x, m_Points[cnr_LT].y, &PtPos);
// Draw top and right borders
HPEN hRedPen = CreatePen(PS_SOLID, 0, m_ColorTopAndRight);
HPEN hOldPen = (HPEN)SelectObject(hdc, hRedPen);
LineTo(hdc, m_Points[cnr_RT].x, m_Points[cnr_RT].y);
LineTo(hdc, m_Points[cnr_RB].x, m_Points[cnr_RB].y);
// Draw bottom and left borders
HPEN hBluePen = CreatePen(PS_SOLID, 0, m_ColorBottomAndLeft);
SelectObject(hdc, hBluePen);
LineTo(hdc, m_Points[cnr_LB].x, m_Points[cnr_LB].y);
LineTo(hdc, m_Points[cnr_LT].x, m_Points[cnr_LT].y);
// Restore position
MoveToEx(hdc, PtPos.x, PtPos.y, NULL);
SelectObject(hdc, hOldPen);
DeleteObject(hRedPen);
DeleteObject(hBluePen);
}
#endif
// The thechique used here is as follows:
// We want to reflect a point P(xP, yP) about any line given by two points
// A(xA, yA) and B(xB, yB).
// Let's call P'(xP', yP') the image of P,
// O(x, y) the intersection of PP' with AB
// W[u, v]=[xB - xA, yB - yA] a directing vector of AB
// we the following equations are true:
// 1) xP' + xP = 2x => since P' is a reflection of P
// 2) yP' + yP = 2y => ditto
// 3) (y - yA)u - (x - xA)v = 0 => equation of a line passing by A and B
// 4) (x - xP)u + (y - yP)v = 0 => OP and AB are othogonal
// Solving these equations yeilds:
//
// |xP'| | 2u^2 2u.v -2f.v | |xP'|
// | | | (----- - 1) (-------) (-------) | | |
// | | | d d d | | |
// | | | | | |
// |yP'| = | 2u.v 2v^2 2f.u | |yP |
// | | | (-------) (----- - 1) (-------) | | |
// | | | d d d | | |
// | | | | | |
// |1 | | 0 0 1 | |1 |
//
// Where: d = u^2 + v^2, and f = u.yA - v.xA;
// '^' stands for 'power of', and the dot '.' for multiplication.
// This function always reflects about the left border
// (going from LB to LT points, which become A and B respectively)
void SCRectPolygon::SCComputeReflectionLeft(XFORM& xform)
{
SCComputeReflection(xform, &m_Points[cnr_LB], &m_Points[cnr_LT]);
}
// This function always reflects about the top border
// (going from LT to RT points, which become A and B respectively)
void SCRectPolygon::SCComputeReflectionTop(XFORM& xform)
{
SCComputeReflection(xform, &m_Points[cnr_LT], &m_Points[cnr_RT]);
}
// This function always reflects about the right border
// (going from RB to RT points, which become A and B respectively)
void SCRectPolygon::SCComputeReflectionRight(XFORM& xform)
{
SCComputeReflection(xform, &m_Points[cnr_RB], &m_Points[cnr_RT]);
}
// This function always reflects about the bottom border
// (going from LB to RB points, which become A and B respectively)
void SCRectPolygon::SCComputeReflectionBottom(XFORM& xform)
{
SCComputeReflection(xform, &m_Points[cnr_LB], &m_Points[cnr_RB]);
}
// This function always reflects about a line parallel with the top border
// at a distance equal to iDeltaY
// Caution: use only on a non-rotated SCRectPolygon
void SCRectPolygon::SCComputeReflectionBase(XFORM& xform, int iDeltaY)
{
POINT PtA;
PtA.x = m_Points[cnr_LT].x;
PtA.y = m_Points[cnr_LT].y + iDeltaY;
POINT PtB;
PtA.x = m_Points[cnr_RT].x;
PtA.y = m_Points[cnr_RT].y + iDeltaY;
SCComputeReflection(xform, &PtA, &PtB);
}
// General reflection
void SCRectPolygon::SCComputeReflection(XFORM& xform, POINT* pPtA, POINT* pPtB)
{
ASSERT(pPtA);
ASSERT(pPtB);
int u = pPtB->x - pPtA->x;
int v = pPtB->y - pPtA->y;
int up2 = u*u;
int vp2 = v*v;
float d = (float)(up2 + vp2);
int f = u*pPtA->y - v*pPtA->x;
xform.eM11 = (FLOAT)(2.0*up2/d - 1);
xform.eM22 = (FLOAT)(2.0*vp2/d - 1);
xform.eM12 =
xform.eM21 = (FLOAT)(2.0*u*v/d);
xform.eDx = (FLOAT)(-2.0*f*v/d);
xform.eDy = (FLOAT)(2.0*f*u/d);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -