Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

578 lines
15 KiB
C++

// GsPreviewCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "globalFunc.h"
#include "resource.h"
#include "GsPreviewCtrl.h"
#include "acgsmanager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static double g_nWalkDistStep = 1000.0, g_nWalkAngleStep = 5.0 * PI / 180;;
#define RXASSERT ASSERT
double GetLatitude(XPoint ptCam, XPoint ptTar) //-PI/2 ~ PI/2
{
double nDist = ptTar.Distance(ptCam);
if (nDist < g_Option::instance()._DIST_SNAP)
return 0.0;
if (ptTar.Distance2d(ptCam) < g_Option::instance()._DIST_SNAP) {
return ((ptTar.z > ptCam.z) ? PI / 2 : -PI / 2);
}
return asin((ptTar.z - ptCam.z) / nDist);
}
double GetLongitude(XPoint ptCam, XPoint ptTar) // 0 ~ 2*PI
{
if (ptTar.Distance2d(ptCam) < g_Option::instance()._DIST_SNAP)
return 0.0;
return ads_angle(ptCam, ptTar);
}
/////////////////////////////////////////////////////////////////////////////
// CGsPreviewCtrl
IMPLEMENT_DYNAMIC(CGsPreviewCtrl, CStatic)
CGsPreviewCtrl::CGsPreviewCtrl(int nOrbitFlag) : CStatic(), mOrbitFlag(nOrbitFlag),
mpManager(NULL), mpFactory(NULL), mpDevice(NULL), mpView(NULL),
mpModel(NULL), mbModelCreated(false), mbPanning(false), mbOrbiting(false),
mDistStep(g_nWalkDistStep), mAngStep(g_nWalkAngleStep)
{
}
BOOL CGsPreviewCtrl::DestroyWindow()
{
clearAll();
return CStatic::DestroyWindow();
}
BEGIN_MESSAGE_MAP(CGsPreviewCtrl, CStatic)
//{{AFX_MSG_MAP(CGsPreviewCtrl)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONDOWN()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_NCHITTEST()
ON_WM_SETFOCUS()
ON_WM_LBUTTONUP()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGsPreviewCtrl message handlers
void CGsPreviewCtrl::OnPaint()
{
CPaintDC dc(this);
//update the gs view
if (mpView) {
mpView->invalidate();
mpView->update();
}
}
// Erase view and delete model
void CGsPreviewCtrl::erasePreview()
{
if (mpView)
mpView->eraseAll();
if (mpManager && mpModel) {
mpManager->destroyAutoCADModel(mpModel);
mpModel = NULL;
}
}
void CGsPreviewCtrl::setModel(AcGsModel* pModel)
{
erasePreview();
mpModel = pModel;
mbModelCreated = false;
}
void CGsPreviewCtrl::clearAll()
{
if (mpView) {
mpView->eraseAll();
}
if (mpDevice) {
bool b = mpDevice->erase(mpView);
RXASSERT(b);
}
if (mpFactory) {
if (mpView) {
mpFactory->deleteView(mpView);
mpView = NULL;
}
if (mpGhostModel) {
mpFactory->deleteModel(mpGhostModel);
mpGhostModel = NULL;
}
mpFactory = NULL;
}
if (mpManager) {
if (mpModel) {
if (mbModelCreated)
mpManager->destroyAutoCADModel(mpModel);
mpModel = NULL;
}
if (mpDevice) {
mpManager->destroyAutoCADDevice(mpDevice);
mpDevice = NULL;
}
mpManager = NULL;
}
}
void CGsPreviewCtrl::init(bool bCreateModel)
{
//Load our special cursors
{
CTemporaryResourceOverride vTemp;
CWinApp *pApp = AfxGetApp();
mhPanCursor = pApp->LoadCursor(IDI_PAN);
mhCrossCursor = pApp->LoadCursor(IDI_CROSS);
mhOrbitCursor = pApp->LoadCursor(IDI_ORBIT);
}
//Instantiate view, a device and a model object
CRect rect;
if (!mpManager) {
mpManager = acgsGetGsManager();
RXASSERT(mpManager);
#if (ARX >= 20)
AcGsKernelDescriptor desc;
desc.addRequirement(AcGsKernelDescriptor::k3DDrawing);
mpFactory = AcGsManager::acquireGraphicsKernel(desc);
if (!mpFactory) return;
#else
mpFactory = mpManager->getGSClassFactory();
#endif
RXASSERT(mpFactory);
//a device with standard autocad color palette
#if (ARX >= 20)
//mpDevice = mpFactory->createOffScreenDevice();
mpDevice = mpManager->createAutoCADDevice(*mpFactory, m_hWnd);
#else
mpDevice = mpManager->createAutoCADDevice(m_hWnd);
#endif
RXASSERT(mpDevice);
GetClientRect(&rect);
mpDevice->onSize(rect.Width(), rect.Height());
//a simple view
mpView = mpFactory->createView();
RXASSERT(mpView);
if (bCreateModel)
{
RXASSERT(mpModel == NULL);
//a model with open/close protocol
#if (ARX >= 20)
mpModel = mpManager->createAutoCADModel(*mpFactory);
#else
mpModel = mpManager->createAutoCADModel();
#endif
RXASSERT(mpModel);
mbModelCreated = true;
}
//another model without open/close for the orbit gadget
mpGhostModel = mpFactory->createModel(AcGsModel::kDirect, 0, 0, 0);
if (mOrbitFlag) {
/*
mpView->add(&mOrbitGadget,mpGhostModel);
mOrbitGadget.setGsView(mpView);
*/
}
mpDevice->add(mpView);
mpView->setView(AcGePoint3d(0.0, 0.0, 1.0),
AcGePoint3d(0.0, 0.0, 0.0),
AcGeVector3d(0.0, 1.0, 0.0),
1.0, 1.0);
}
}
void CGsPreviewCtrl::OnSize(UINT nType, int cx, int cy)
{
CRect rect;
if (mpDevice) {
GetClientRect(&rect);
mpDevice->onSize(rect.Width(), rect.Height());
}
}
BOOL CGsPreviewCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (!(mOrbitFlag & OBF_ZOOM))
return CStatic::OnMouseWheel(nFlags, zDelta, pt);
if (mpView) {
if (mpView->isPerspective()) {
AcGePoint3d ptTar = mpView->target();
AcGePoint3d ptCam = mpView->position();
AcGeVector3d vtView = ptTar - ptCam;
vtView.normalize();
double nScale = mDistStep;
if (zDelta < 0)
nScale = -nScale;
vtView *= nScale;
ptCam += vtView;
ptTar += vtView;
mpView->setView(ptCam, ptTar, AcGeVector3d(0, 0, 1), mpView->fieldWidth(),
mpView->fieldHeight(), AcGsView::kPerspective);
//mpView->setTarget(ptTar);
//mpView->setCamera(ptCam);
}
else {
if (zDelta < 0)
mpView->zoom(0.9);
else
mpView->zoom(1.1);
}
Invalidate();
}
return TRUE;
}
void CGsPreviewCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
SetFocus();
if (!(mOrbitFlag & OBF_ORBIT)) {
CStatic::OnLButtonDown(nFlags, point);
return;
}
//start orbit
mbOrbiting = true;
SetCapture();
//set up the proper cursor
//::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
::SetCursor(mhOrbitCursor);
//store the start point
mStartPt = point;
}
void CGsPreviewCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if (!(mOrbitFlag & OBF_ORBIT)) {
CStatic::OnLButtonUp(nFlags, point);
return;
}
//end orbit
mbOrbiting = false;
//::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor);
::SetCursor(mhCrossCursor);
ReleaseCapture();
}
void CGsPreviewCtrl::OnMButtonDown(UINT nFlags, CPoint point)
{
if (!(mOrbitFlag & OBF_PAN)) {
CStatic::OnMButtonDown(nFlags, point);
return;
}
//start pan
mbPanning = true;
SetCapture();
//set up the proper cursor
//::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
::SetCursor(mhPanCursor);
//store the start point
mStartPt = point;
}
void CGsPreviewCtrl::OnMButtonUp(UINT nFlags, CPoint point)
{
if (!(mOrbitFlag & OBF_PAN)) {
CStatic::OnMButtonUp(nFlags, point);
return;
}
//end pan
ReleaseCapture();
mbPanning = false;
//::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor);
::SetCursor(mhCrossCursor);
}
void CGsPreviewCtrl::Invalidate(BOOL bErase)
{
//if(g_nAcadVer<17.05)//2008以下
// CStatic::Invalidate(bErase);
//else
{
CWnd*pParent = GetParent();
if (pParent != NULL)//2008+vista发现刷新问题,暂用此方法解决
{
CRect rect;
GetWindowRect(rect);
pParent->ScreenToClient(rect);
pParent->InvalidateRect(rect, bErase);
}
else
CStatic::Invalidate(bErase);
}
}
void CGsPreviewCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if (mpView && mbPanning && (mOrbitFlag & OBF_PAN)) {
//transform the point from device coordinates to
//world coordinates
AcGeVector3d pan_vec(-(point.x - mStartPt.x), point.y - mStartPt.y, 0);
pan_vec.transformBy(mpView->viewingMatrix() * mpView->worldToDeviceMatrix().inverse());
mpView->dolly(pan_vec);
Invalidate();
mStartPt = point;
}
else if (mpView && mbOrbiting && (mOrbitFlag & OBF_ORBIT)) {
AcGeVector3d vtMov(mStartPt.x - point.x, point.y - mStartPt.y, 0.0);
//AcGeVector3d vtOff(point.x-m_ptLast.x, point.y-m_ptLast.y, 0.0);
//if(max(fabs(vtOff[0]), fabs(vtOff[1]))<10)
// return;
AcGePoint3d ptCam = mpView->position();
AcGePoint3d ptTar = mpView->target();
AcGeVector3d vtUp = mpView->upVector();
vtUp = AcGeVector3d(0, 0, 1);
CRect rect;
GetClientRect(rect);
//Modify bu xlc on 111222 Y向反向,解决预览图里拖动方向与实际方向相反的问题
//double nRotX = -vtMov.y/rect.Height()*PI/2;
//double nRotY = -vtMov.x/rect.Width()*PI/2;
double nRotX = vtMov.y / rect.Height() * PI / 2;
double nRotY = vtMov.x / rect.Width() * PI / 2;
AcGeVector3d vtZ = ptCam - ptTar;
AcGePlane plan(ptCam, vtZ);
AcGePoint3d ptUp = ptCam + vtUp * 10000.0;
AcGePoint3d ptUp1 = ptUp.orthoProject(plan);
if (ptCam.distanceTo(ptUp1) < 0.1)
return;
AcGeVector3d vtY = ptUp1 - ptCam;
//Modify bu xlc on 111222 Y向反向,解决预览图里拖动方向与实际方向相反的问题
vtY.negate();
AcGeVector3d vtX = vtY.crossProduct(vtZ);
vtX.normalize();
vtY.normalize();
vtZ.normalize();
AcGeVector3d vtView = ptTar - ptCam;
//if(fabs(vtMov.y)>fabs(vtMov.x)) {
//m_vtUp.rotateBy(nRotX, vtX);
vtView.rotateBy(nRotX, vtX);
//} else {
vtY.rotateBy(nRotX, vtX);
//m_vtUp.rotateBy(nRotY, vtY);
vtView.rotateBy(nRotY, vtY);
//}
ptTar = ptCam + vtView;
mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(),
mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel);
Invalidate();
//m_ptLast = point;
mStartPt = point;
/* 原来的代码
const double Half_Pi = 1.570796326795;
AcGsDCRect view_rect;
mpView->getViewport (view_rect);
int nViewportX = (view_rect.m_max.x - view_rect.m_min.x) + 1;
int nViewportY = (view_rect.m_max.y - view_rect.m_min.y) + 1;
int centerX = AS_INT(nViewportX / 2.0f + view_rect.m_min.x);
int centerY = AS_INT(nViewportY / 2.0f + view_rect.m_min.y);
const double radius = min (nViewportX, nViewportY) * 0.4f;
// compute two vectors from last and new cursor positions:
AcGeVector3d last_vector ((mStartPt.x - centerX) / radius,
-(mStartPt.y - centerY) / radius,
0.0);
if (last_vector.lengthSqrd () > 1.0) // outside the radius
last_vector.normalize ();
else
last_vector.z = sqrt (1.0 - last_vector.x * last_vector.x - last_vector.y * last_vector.y);
AcGeVector3d new_vector((point.x - centerX) / radius,
-(point.y - centerY) / radius,
0.0);
if (new_vector.lengthSqrd () > 1.0) // outside the radius
new_vector.normalize ();
else
new_vector.z = sqrt (1.0 - new_vector.x * new_vector.x - new_vector.y * new_vector.y);
// determine angles for proper sequence of camera manipulations:
AcGeVector3d rotation_vector (last_vector);
rotation_vector = rotation_vector.crossProduct (new_vector); // rotation_vector = last_vector x new_vector
AcGeVector3d work_vector (rotation_vector);
work_vector.z = 0.0f; // projection of rotation_vector onto xy plane
double roll_angle = atan2 (work_vector.x,
work_vector.y); // assuming that the camera's up vector is "up",
// this computes the angle between the up vector
// and the work vector, which is the roll required
// to make the up vector coincident with the rotation_vector
double length = rotation_vector.length ();
double orbit_y_angle = (length != 0.0) ? acos (rotation_vector.z / length) + Half_Pi : Half_Pi; // represents inverse cosine of the dot product of the
if (length > 1.0f) // rotation_vector and the up_vector divided by the
length = 1.0f; // magnitude of both vectors. We add pi/2 because we
// are making the up-vector parallel to the the rotation
double rotation_angle = asin (length); // vector ... up-vector is perpin. to the eye-vector.
// perform view manipulations
mpView->roll( roll_angle); // 1: roll camera to make up vector coincident with rotation vector
mpView->orbit( 0.0f, orbit_y_angle); // 2: orbit along y to make up vector parallel with rotation vector
mpView->orbit( rotation_angle, 0.0f); // 3: orbit along x by rotation angle
mpView->orbit( 0.0f, -orbit_y_angle); // 4: orbit along y by the negation of 2
mpView->roll(-roll_angle); // 5: roll camera by the negation of 1
Invalidate();
mStartPt = point;
*/
}
else {
CStatic::OnMouseMove(nFlags, point);
}
}
#if ARX<17
UINT CGsPreviewCtrl::OnNcHitTest(CPoint point)
#else
LRESULT CGsPreviewCtrl::OnNcHitTest(CPoint point)
#endif
{
return HTCLIENT;
}
void CGsPreviewCtrl::OnSetFocus(CWnd* pOldWnd)
{
if (mOrbitFlag && mhCrossCursor) {
//::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor);
::SetCursor(mhCrossCursor);
}
}
void CGsPreviewCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL bShift = GlobalFunc::IsKeyPressed(VK_SHIFT);
BOOL bCtrl = GlobalFunc::IsKeyPressed(VK_CONTROL);
XPoint ptCam = mpView->position();
XPoint ptTar = mpView->target();
XVector3D vtView = ptTar - ptCam;
vtView.Normalize();
XVector3D vtUp(0, 0, 1);
if (nChar == VK_LEFT || nChar == VK_RIGHT) {
double nFactor = 1.0;
if (nChar == VK_RIGHT)
nFactor = -1.0;
if (!bShift && !bCtrl) { //左右移
double nStepLen = mDistStep * nRepCnt;
double longitude = GetLongitude(ptCam, ptTar);
ads_matrix mat;
XPoint().GetMoveMatrix(XPoint(nStepLen * cos(longitude + PI / 2.0 * nFactor),
nStepLen * sin(longitude + PI / 2.0 * nFactor)), mat);
ptCam.TransformBy(mat);
ptTar.TransformBy(mat);
}
else if (bCtrl) { //左右转 PI/2
double val = GetLongitude(ptCam, ptTar) + PI / 2.0 * nFactor;
double nElev = ptTar.z;
ads_polar(ptCam, val, ptCam.Distance2d(ptTar), ptTar);
ptTar.z = nElev;
}
else if (bShift) { //左右转
double val = GetLongitude(ptCam, ptTar) + mAngStep * nRepCnt * nFactor;
double nElev = ptTar.z;
ads_polar(ptCam, val, ptCam.Distance2d(ptTar), ptTar);
ptTar.z = nElev;
}
}
else if (nChar == VK_UP || nChar == VK_DOWN) {
double nFactor = 1.0;
if (nChar == VK_DOWN)
nFactor = -1.0;
if (!bShift && !bCtrl) { //前进或后退
ads_matrix mat;
double nStepLen = mDistStep * nRepCnt * nFactor;
double longitude = GetLongitude(ptCam, ptTar);
XPoint().GetMoveMatrix(XPoint(nStepLen * cos(longitude), nStepLen * sin(longitude)), mat);
ptCam.TransformBy(mat);
ptTar.TransformBy(mat);
}
else if (bCtrl) { //上下移动
ptCam.z += mDistStep * nRepCnt * nFactor;
ptTar.z += mDistStep * nRepCnt * nFactor;
}
else if (bShift) { //上下转动
double val = GetLatitude(ptCam, ptTar) + mAngStep * nRepCnt * nFactor;
double nElevDiff = ptCam.Distance2d(ptTar) * tan(val);
ptTar.z = ptCam.z + nElevDiff;
}
}
else {
CStatic::OnKeyDown(nChar, nRepCnt, nFlags);
return;
}
mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(),
mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel);
Invalidate();
}
BOOL CGsPreviewCtrl::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN) {
int vk = pMsg->wParam;
if (vk == VK_LEFT || vk == VK_RIGHT || vk == VK_DOWN || vk == VK_UP) {
int nRepCnt = LOWORD(pMsg->lParam);
OnKeyDown(vk, nRepCnt, 0);
return TRUE;
}
}
return CStatic::PreTranslateMessage(pMsg);
}