Files
envi-code/SourceCode/Code2026/CoreCommand/GsPreviewCtrl.cpp
T
2026-09-28 15:28:50 +08:00

890 lines
23 KiB
C++

#include "stdafx.h"
#include "resource.h"
#include "GsPreviewCtrl.h"
#include "acgsmanager.h"
#include "EarThwormDef.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_VIEWDBLCLKSEL (WM_USER + 0x1200)
BOOL IsKeyPressed(int vk)
{
SHORT nState = ::GetKeyState(vk);
return ((nState & 256) != 0);
}
double g_nWalkDistStep = 1000.0, g_nWalkAngleStep = 5.0*PI / 180;;
#define RXASSERT ASSERT
double GetLatitude(AcGePoint3d ptCam, AcGePoint3d ptTar)
{
double nDist = ptTar.distanceTo(ptCam);
if (nDist < 1.e-6)
return 0.0;
if (ptTar.distanceTo(ptCam) < 1.e-5)
{
return ((ptTar.z > ptCam.z) ? PI / 2 : -PI / 2);
}
return asin((ptTar.z - ptCam.z) / nDist);
}
double GetLongitude(AcGePoint3d ptCam, AcGePoint3d ptTar) // 0 ~ 2*PI
{
if (ptTar.distanceTo(ptCam) < 1.e-6)
return 0.0;
return ads_angle(asDblArray(ptCam), asDblArray(ptTar));
}
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()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
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;
}
}
BOOL CGsPreviewCtrl::GetCurrentViewInfo(const AcDbExtents& exts, AcGePoint3d & ptPosition, AcGePoint3d & ptTarget,
AcGeVector3d& vecUpVector, double& dFieldWidth, double& dFieldHeight)
{
// get the view port information - see parameter list
double dHeight = 0.0, dWidth = 0.0, dViewTwist = 0.0;
AcGePoint3d ptTargetView;
AcGeVector3d vecViewDir;
GetActiveViewPortInfo(dHeight, dWidth, ptTargetView, vecViewDir, dViewTwist, TRUE);
// we are only interested in the directions of the view, not the sizes, so we normalise.
vecViewDir.normalize();
// Our view coordinate space consists of z direction
// get a perp vector off the z direction
// Make sure its normalised
AcGeVector3d vecViewXDir = vecViewDir.perpVector().normal();
// correct the x angle by applying the twist
vecViewXDir = vecViewXDir.rotateBy(dViewTwist, -vecViewDir);
// now we can work out y, this is of course perp to the x and z directions. No need to normalise this,
// as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length
vecUpVector = vecViewDir.crossProduct(vecViewXDir);
// Calculate the extents in WCS
AcGePoint3d ptExtMax = exts.maxPoint();
AcGePoint3d ptExtMin = exts.minPoint();
// find a nice point around which to transform the view. We'll use the same point as the center of the view.
ptTarget = ptExtMin + 0.5 * (ptExtMax - ptExtMin);
ptPosition = ptTarget + vecViewDir;
// create a transform from WCS to View space
// this represents the transformation from WCS to the view space. (Actually not quite since
// we are keeping the fixed point as the center of the box for convenience )
AcGeMatrix3d matView;
matView = AcGeMatrix3d::alignCoordSys(ptTarget, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
ptTarget, vecViewXDir, vecUpVector, vecViewDir).inverse();
AcDbExtents extWcsExtents(ptExtMin, ptExtMax);
// now we have the view Extents
AcDbExtents extViewExtents = extWcsExtents;
// transforms the extents in WCS->view space
extViewExtents.transformBy(matView);
// get the extents of the AutoCAD view
dFieldWidth = fabs(extViewExtents.maxPoint().x - extViewExtents.minPoint().x);
dFieldHeight = fabs(extViewExtents.maxPoint().y - extViewExtents.minPoint().y);
return TRUE;
}
void CGsPreviewCtrl::InitFromCurrentView2D(const AcDbExtents& exts,bool bRestTarget)
{
struct resbuf rb;
acedGetVar(_T("CVPORT"), &rb);
int iCurView = rb.resval.rint;
acedGetVar(_T("TILEMODE"), &rb);
int iTileMode = rb.resval.rint;
#ifndef ZWCAD
#if ARX < 20
AcGsView::RenderMode eShadeMode;
if (iTileMode == 0 && iCurView == 1)
eShadeMode = AcGsView::k2DOptimized;
else
eShadeMode = AcGsView::k2DOptimized;
mpView->setMode(eShadeMode);
#else
AcGiVisualStyle style;
if (iTileMode == 0 && iCurView == 1)
style.setType(AcGiVisualStyle::k2DWireframe);
else
style.setType(AcGiVisualStyle::k2DWireframe);
mpView->setVisualStyle(style);
#endif
#else
#if defined(R24)
AcGsView::RenderMode eShadeMode;
if (iTileMode == 0 && iCurView == 1)
eShadeMode = AcGsView::k2DOptimized;
else
eShadeMode = AcGsView::k2DOptimized;
mpView->setMode(eShadeMode);
#else
AcGiVisualStyle style;
if (iTileMode == 0 && iCurView == 1)
style.setType(AcGiVisualStyle::k2DWireframe);
else
style.setType(AcGiVisualStyle::k2DWireframe);
mpView->setVisualStyle(style);
#endif
#endif
AcGeVector3d vecUpVector;
AcGePoint3d ptPosition, ptTarget;
double dFieldWidth, dFieldHeight;
GetCurrentViewInfo(exts, ptPosition, ptTarget, vecUpVector, dFieldWidth, dFieldHeight);
if (!vecUpVector.isParallelTo(AcGeVector3d::kYAxis))
{
vecUpVector = AcGeVector3d::kYAxis;//???ÏÔʾY·½Ïò¿´
}
if (bRestTarget)
ptTarget.set(0,0,0);
ptPosition.set(0,0,0);
mpView->setView(ptPosition, ptTarget, vecUpVector, dFieldWidth, dFieldHeight);
mpView->zoomExtents(exts.minPoint(),exts.maxPoint());
mpView->zoom(1.1);
mpView->invalidate();
}
void CGsPreviewCtrl::InitFromCurrentView3D(const AcDbExtents& exts, bool bRestTarget)
{
struct resbuf rb;
acedGetVar(_T("CVPORT"), &rb);
int iCurView = rb.resval.rint;
acedGetVar(_T("TILEMODE"), &rb);
int iTileMode = rb.resval.rint;
#ifndef ZWCAD
#if ARX < 20
mpView->setMode(AcGsView::kGouraudShaded);
#else
mpView->setVisualStyle(AcGiVisualStyle::kGouraud);
#endif
#else
#if defined(R24)
mpView->setMode(AcGsView::kGouraudShaded);
#else
mpView->setVisualStyle(AcGiVisualStyle::kGouraud);
#endif
#endif
AcGePoint3d extMax(500, 500, 500);// = pDb->extmax();
AcGePoint3d extMin(-500, -500, -500);// = pDb->extmin();
//AcGePoint3d extMax = pDb->extmax();
//AcGePoint3d extMin = pDb->extmin();
// get the view port information - see parameter list
ads_real height = 0.0, width = 0.0, viewTwist = 0.0;
AcGePoint3d targetView;
AcGeVector3d viewDir;
GetActiveViewPortInfo(height, width, targetView, viewDir, viewTwist, true);
viewDir.set(-1, -1, 1);
viewDir = viewDir.normal();
AcGeVector3d viewXDir = viewDir.perpVector().normal();
viewXDir = viewXDir.rotateBy(viewTwist, -viewDir);
AcGeVector3d viewYDir = viewDir.crossProduct(viewXDir);
AcGePoint3d boxCenter = extMin + 0.5 * (extMax - extMin);
AcGeMatrix3d viewMat = AcGeMatrix3d::alignCoordSys(boxCenter, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
boxCenter, viewXDir, viewYDir, viewDir).inverse();
AcDbExtents wcsExtents(extMin, extMax);
AcDbExtents viewExtents = wcsExtents;
viewExtents.transformBy(viewMat);
double xMax = fabs(viewExtents.maxPoint().x - viewExtents.minPoint().x);
double yMax = fabs(viewExtents.maxPoint().y - viewExtents.minPoint().y);
AcGePoint3d eye = boxCenter + viewDir;
mpView->setView(eye, boxCenter, viewYDir, xMax, yMax);
//if (mpView != NULL)
//{
// mpView->invalidate();
// mpView->update();
//}
}
BOOL CGsPreviewCtrl::GetActiveViewPortInfo(double &dHeight, double &dWidth, AcGePoint3d &ptTarget,
AcGeVector3d &vecViewDir, double &dViewTwist, BOOL bGetViewCenter)
{
// get the working db
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
// if not ok
if (pDb == NULL)
return FALSE;
// lock document
//AcApDocument* pDoc = acDocManager->curDocument();
//acDocManager->lockDocument(pDoc);
// make sure the active view port is uptodate
//acedVports2VportTableRecords();
// unlock document
//acDocManager->unlockDocument(pDoc);
// open the view port records
AcDbViewportTable *pVTable = NULL;
Acad::ErrorStatus es = pDb->getViewportTable(pVTable, AcDb::kForRead);
// if we opened them ok
if (es == Acad::eOk)
{
AcDbViewportTableRecord *pViewPortRec = NULL;
es = pVTable->getAt(_T("*Active"), pViewPortRec, AcDb::kForRead);
if (es == Acad::eOk)
{
// get the height of the view
dHeight = pViewPortRec->height();
// get the width
dWidth = pViewPortRec->width();
// if the user wants the center of the viewport used
if (bGetViewCenter)
{
struct resbuf rb;
memset(&rb, 0, sizeof(struct resbuf));
// get the system var VIEWCTR
acedGetVar(_T("VIEWCTR"), &rb);
// set that as the target
ptTarget = AcGePoint3d(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
}
else
{
// we want the viewports camera target setting
// get the target of the view
ptTarget = pViewPortRec->target();
}
// get the view direction
vecViewDir = pViewPortRec->viewDirection();
// get the view twist of the viewport
dViewTwist = pViewPortRec->viewTwist();
}
// close after use
pVTable->close();
pViewPortRec->close();
}
return TRUE;
}
BOOL CGsPreviewCtrl::GetCurrentViewInfo(AcGePoint3d & ptPosition, AcGePoint3d & ptTarget,
AcGeVector3d& vecUpVector, double& dFieldWidth, double& dFieldHeight)
{
// get the view port information - see parameter list
double dHeight = 0.0, dWidth = 0.0, dViewTwist = 0.0;
AcGePoint3d ptTargetView;
AcGeVector3d vecViewDir;
GetActiveViewPortInfo(dHeight, dWidth, ptTargetView, vecViewDir, dViewTwist, TRUE);
// we are only interested in the directions of the view, not the sizes, so we normalise.
vecViewDir.normalize();
// Our view coordinate space consists of z direction
// get a perp vector off the z direction
// Make sure its normalised
AcGeVector3d vecViewXDir = vecViewDir.perpVector().normal();
// correct the x angle by applying the twist
vecViewXDir = vecViewXDir.rotateBy(dViewTwist, -vecViewDir);
// now we can work out y, this is of course perp to the x and z directions. No need to normalise this,
// as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length
vecUpVector = vecViewDir.crossProduct(vecViewXDir);
// the current editor drawing
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
// Calculate the extents in WCS
AcGePoint3d ptExtMax = pDb->extmax();
AcGePoint3d ptExtMin = pDb->extmin();
// find a nice point around which to transform the view. We'll use the same point as the center of the view.
ptTarget = ptExtMin + 0.5 * (ptExtMax - ptExtMin);
ptPosition = ptTarget + vecViewDir;
// create a transform from WCS to View space
// this represents the transformation from WCS to the view space. (Actually not quite since
// we are keeping the fixed point as the center of the box for convenience )
AcGeMatrix3d matView;
matView = AcGeMatrix3d::alignCoordSys(ptTarget, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
ptTarget, vecViewXDir, vecUpVector, vecViewDir).inverse();
AcDbExtents extWcsExtents(ptExtMin, ptExtMax);
// now we have the view Extents
AcDbExtents extViewExtents = extWcsExtents;
// transforms the extents in WCS->view space
extViewExtents.transformBy(matView);
// get the extents of the AutoCAD view
dFieldWidth = fabs(extViewExtents.maxPoint().x - extViewExtents.minPoint().x);
dFieldHeight = fabs(extViewExtents.maxPoint().y - extViewExtents.minPoint().y);
return TRUE;
}
void CGsPreviewCtrl::init(bool bCreateModel)
{
//Load our special cursors
{
CAcModuleResourceOverride vTemp;
CWinApp *pApp = AfxGetApp();
mhPanCursor = pApp->LoadCursor(IDI_PAN);
mhCrossCursor = pApp->LoadCursor(IDI_CROSS);
mhOrbitCursor = pApp->LoadCursor(IDI_ORBIT);
mhEditCursor = pApp->LoadCursor(IDC_CURSOREDIT);
}
//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, 0.0, 1.0),
1.0, 1.0);
}
}
BOOL CGsPreviewCtrl::Add(AcDbEntity* pEnt)
{
if (mpView != NULL)
{
mpView->add(pEnt, mpModel);
mpView->invalidate();
}
return TRUE;
}
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();//ÉÁµÄÀûº¦
RedrawWindow();
}
return TRUE;
}
void CGsPreviewCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
SetFocus();
if ((mOrbitFlag & OBF_COTE))
{
CRect rc;
GetClientRect(&rc);
CPoint pt = point;
AcGePoint3d ptGe1(pt.x, (rc.Height() - pt.y), 0.0);
ptGe1.transformBy(mpView->worldToDeviceMatrix().inverse());
GetParent()->SendMessage(WM_VIEW_LBUTTONDOWN, 0, (LPARAM)&ptGe1);
::SetCursor(mhEditCursor);
return;
}
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;
ClientToScreen(&point);
GetParent()->ScreenToClient(&point);
GetParent()->SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
}
void CGsPreviewCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if ((mOrbitFlag & OBF_COTE))
{
::SetCursor(mhEditCursor);
ReleaseCapture();
return;
}
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::OnLButtonDblClk(UINT nFlags, CPoint point)
{
ClientToScreen(&point);
GetParent()->ScreenToClient(&point);
GetParent()->SendMessage(WM_LBUTTONDBLCLK,nFlags,MAKELPARAM(point.x,point.y));
GetParent()->SendMessage(WM_VIEWDBLCLKSEL,0,0);
}
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(ARX<17)
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);
}
}
#endif
}
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();
RedrawWindow();
mStartPt = point;
}
else if (mpView && mbOrbiting && (mOrbitFlag&OBF_ORBIT))
{
AcGeVector3d vtMov(mStartPt.x - point.x, point.y - mStartPt.y, 0.0);
AcGePoint3d ptCam = mpView->position();
AcGePoint3d ptTar = mpView->target();
AcGeVector3d vtUp = mpView->upVector();
vtUp = AcGeVector3d(0, 0, 1);
CRect rect;
GetClientRect(rect);
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;
AcGeVector3d vtX = vtY.crossProduct(vtZ);
vtX.normalize();
vtY.normalize();
vtZ.normalize();
AcGeVector3d vtView = ptTar - ptCam;
vtView.rotateBy(nRotX, vtX);
vtY.rotateBy(nRotX, vtX);
vtView.rotateBy(nRotY, vtY);
ptTar = ptCam + vtView;
mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(),
mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel);
//Invalidate();
RedrawWindow();
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)
{
::SetCursor(mhCrossCursor);
}
}
void CGsPreviewCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL bShift = IsKeyPressed(VK_SHIFT);
BOOL bCtrl = IsKeyPressed(VK_CONTROL);
if (!mpView) return;
AcGePoint3d ptCam = mpView->position();
AcGePoint3d ptTar = mpView->target();
AcGeVector3d vtView = ptTar - ptCam;
vtView.normalize();
AcGeVector3d 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);
AcGeMatrix3d mat;
AcGePoint3d ptTmp(nStepLen*cos(longitude + PI / 2.0*nFactor),
nStepLen*sin(longitude + PI / 2.0*nFactor), 0.0);
mat.setToTranslation(ptTmp.asVector());
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(asDblArray(ptCam), val, ptCam.distanceTo(ptTar), asDblArray(ptTar));
ptTar.z = nElev;
}
else if (bShift) { //×óÓÒת
double val = GetLongitude(ptCam, ptTar) + mAngStep*nRepCnt*nFactor;
double nElev = ptTar.z;
ads_polar(asDblArray(ptCam), val, ptCam.distanceTo(ptTar), asDblArray(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) { //ǰ½ø»òºóÍË
AcGeMatrix3d mat;
double nStepLen = mDistStep*nRepCnt*nFactor;
double longitude = GetLongitude(ptCam, ptTar);
AcGePoint3d ptT(nStepLen*cos(longitude), nStepLen*sin(longitude), 0);
mat.setToTranslation(ptT.asVector());
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.distanceTo(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();
RedrawWindow();
}
BOOL CGsPreviewCtrl::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN) {
INT_PTR vk = pMsg->wParam;
if (vk == VK_LEFT || vk == VK_RIGHT || vk == VK_DOWN || vk == VK_UP) {
int nRepCnt = LOWORD(pMsg->lParam);
OnKeyDown((UINT)vk, nRepCnt, 0);
return TRUE;
}
}
return CStatic::PreTranslateMessage(pMsg);
}
BOOL CGsPreviewCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if ((mOrbitFlag & OBF_COTE))
{
SetCursor(mhEditCursor);
return FALSE;
}
return CStatic::OnSetCursor(pWnd, nHitTest, message);
}
void CGsPreviewCtrl::RefreshView()
{
if (mpView != NULL)
{
mpView->invalidate();
mpView->update();
}
}
void CGsPreviewCtrl::OnZoomExtents(AcDbDatabase* pDb)
{
AcDbExtents viewExtents(pDb->extmin(), pDb->extmax());
AcGeMatrix3d viewMatrix;
viewExtents.transformBy(viewMatrix);
//mpView->zoomExtents(viewExtents.minPoint(),viewExtents.maxPoint());
RefreshView();
}