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

568 lines
16 KiB
C++

// GsPreviewCtrl.cpp : implementation file
//
#include "stdafx.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
extern TARCH_IMPEXP double g_nWalkDistStep, g_nWalkAngleStep;
#define RXASSERT ASSERT
double GetLatitude(XPoint ptCam, XPoint ptTar) //-PI/2 ~ PI/2
{
double nDist=ptTar.Distance(ptCam);
if(nDist<_DIST_SNAP)
return 0.0;
if(ptTar.Distance2d(ptCam)<_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)<_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 (ADS >= 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 (ADS >= 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 (ADS >= 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 ADS<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 = IsKeyPressed(VK_SHIFT);
BOOL bCtrl = 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);
}