⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gspreviewctrl.cpp

📁 ObjectARX 预览CAD图元类
💻 CPP
字号:
//
// (C) Copyright 2002 by Autodesk, Inc. 
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted, 
// provided that the above copyright notice appears in all copies and 
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting 
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC. 
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to 
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//

// GsPreviewCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "resource.h"
#include "GsPreviewCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGsPreviewCtrl

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()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGsPreviewCtrl message handlers

void CGsPreviewCtrl::OnPaint() 
{
	CPaintDC dc(this); 
	//update the gs view
	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(AcDbDatabase *pDb,HMODULE hRes, bool bCreateModel)
{
	//Load our special cursors
//	mhPanCursor = LoadCursor(hRes,MAKEINTRESOURCE(IDI_PAN));
//	mhCrossCursor = LoadCursor(hRes,MAKEINTRESOURCE(IDI_CROSS));
//	mhOrbitCursor = LoadCursor(hRes,MAKEINTRESOURCE(IDI_ORBIT));
//	::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
	//Instantiate view, a device and a model object
	CRect rect;
	if (!mpManager) 
	{
		// get the AcGsManager object for a specified AutoCAD MDI Client CView
		mpManager = acgsGetGsManager();
		RXASSERT(mpManager);
		// get the GS class factory
		mpFactory = mpManager->getGSClassFactory();
		RXASSERT(mpFactory);
		// create an AcGsDevice object. The window handle passed in to this 
		// function is the display surface onto which the graphics system draws
		//a device with standard autocad color palette
		mpDevice = mpManager->createAutoCADDevice(m_hWnd);
		RXASSERT(mpDevice);
		
		// get the size of the window that we are going to draw in
		GetClientRect( &rect);
		// make sure the gs device knows how big the window is
		mpDevice->onSize(rect.Width(), rect.Height());   
		// construct a simple view
		mpView = mpFactory->createView();
		RXASSERT(mpView);
		if (bCreateModel)
		{
			RXASSERT(mpModel==NULL);
			// create an AcGsModel object with the AcGsModel::kMain RenderType 
			// (which is a hint to the graphics system that the geometry in this 
			// model should be rasterized into its main frame buffer). This 
			// AcGsModel is created with get and release functions that will open and close AcDb objects.
			mpModel = mpManager->createAutoCADModel();
			RXASSERT(mpModel);
			mbModelCreated = true;
		}
		//another model without open/close for the orbit gadget
		mpGhostModel = mpFactory->createModel(AcGsModel::kDirect,0,0,0);
		mpView->add(&mOrbitGadget,mpGhostModel);
		mOrbitGadget.setGsView(mpView);
		mpDevice->add(mpView);
		
		// get the view port information - see parameter list
		ads_real height = 0.0, width = 0.0, viewTwist = 0.0;
		AcGePoint3d targetView;
		AcGeVector3d viewDir;
		GetActiveViewPortInfo (pDb,height, width, targetView, viewDir, viewTwist, true);
		
		//pDb->ucsxdir().crossProduct(pDb->ucsydir())
		  //pView->setView(position, target,
		mpView->setView(targetView + viewDir, targetView,
			AcGeVector3d(0.0, 1.0, 0.0),  // upvector
			1.0, 1.0);
			/*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());
	}
}

//应用 CGsPreviewCtrl
//初始化CAD图元预控件
//mPreviewCtrl - 预览控件,初始化后返回初始化值
//pDb          - 要预览的CAD图元的库
//space        - 要预览库中的空间 (模型空间/图纸空间,默认模型空间)
Acad::ErrorStatus InitDrawingControl (CGsPreviewCtrl &mPreviewCtrl,AcDbDatabase *pDb, const TCHAR *space)
{
  // have we got a valid drawing
  if (pDb == NULL)
    return Acad::eNullBlockName;

  // get the blocktable
  AcDbBlockTable *pTab = NULL;
  Acad::ErrorStatus es = pDb->getBlockTable (pTab, AcDb::kForRead);
  // if ok
  if (es == Acad::eOk)
  {
    // get the space required
    AcDbBlockTableRecord *pRec = NULL;
    es = pTab->getAt (space, pRec, AcDb::kForRead);
    // if ok
    if (es == Acad::eOk)
    {
      pTab->close();

      // initialize the preview control
      mPreviewCtrl.init(pDb,theArxDLL.ModuleResourceInstance(),true);

      // we are going to set the view to the current view of the drawing
      // The overall approach is to calculate the extents of the database in the coordinate system of the view
      // Calculate the extents in WCS
      //遍历块表,得到最大点与最小点
      double maxx,minx,maxy,miny,maxz,minz;
      AcDbBlockTableRecordIterator *pIterator;
      AcDbExtents extents;
      int num=0;

      maxx=minx=maxy=miny=maxz=minz=0;
      pRec->newIterator(pIterator);
      for(pIterator->start(); !pIterator->done(); pIterator->step())
      {
        AcDbEntity *pEnt;
        if(pIterator->getEntity(pEnt,AcDb::kForRead)==Acad::eOk)
        {
          num++;
          pEnt->getGeomExtents(extents);
          if(num==1)
          {
            maxx=extents.maxPoint().x;
            minx=extents.minPoint().x;
            maxy=extents.maxPoint().y;
            miny=extents.minPoint().y;
            maxz=extents.maxPoint().z;
            minz=extents.minPoint().z;
          }
          else
          {
            maxx=max(maxx,extents.maxPoint().x);
            minx=min(minx,extents.minPoint().x);
            maxy=max(maxy,extents.maxPoint().y);
            miny=min(miny,extents.minPoint().y);
            maxz=max(maxz,extents.maxPoint().z);
            minz=min(minz,extents.minPoint().z);
          }
          pEnt->close();
        }        
      }
      delete pIterator;

      AcGePoint3d extMax = AcGePoint3d(maxx+(maxx-minx)/10,maxy+(maxy-miny)/10,maxz+(maxz-minz)/10); //pDb->extmax();
      AcGePoint3d extMin = AcGePoint3d(minx-(maxx-minx)/10,miny-(maxy-miny)/10,minz-(maxz-minz)/10); //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 (pDb,height, width, targetView, viewDir, viewTwist, true);

      // we are only interested in the directions of the view, not the sizes, so we normalise. 
      viewDir = viewDir.normal();

      //**********************************************
      // Our view coordinate space consists of z direction 
      // get a perp vector off the z direction
      // Make sure its normalised
      AcGeVector3d viewXDir = viewDir.perpVector ().normal();
      // correct the x angle by applying the twist
      viewXDir = viewXDir.rotateBy (viewTwist, -viewDir);
      // 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
      AcGeVector3d viewYDir = viewDir.crossProduct (viewXDir);

      // find a nice point around which to transform the view. We'll use the same point as the center of the view.
      AcGePoint3d boxCenter = extMin + 0.5 * ( extMax - extMin );

      //**********************************************
      // 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 viewMat;
      viewMat = AcGeMatrix3d::alignCoordSys (boxCenter, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,  
        boxCenter, viewXDir, viewYDir, viewDir).inverse();

      AcDbExtents wcsExtents(extMin, extMax);
      // now we have the view Extents
      AcDbExtents viewExtents = wcsExtents;
      // transforms the extents in WCS->view space
      viewExtents.transformBy (viewMat);

      //**********************************************
      // get the extents of the AutoCAD view
      double xMax = fabs(viewExtents.maxPoint ().x - viewExtents.minPoint ().x);
      double yMax = fabs(viewExtents.maxPoint ().y - viewExtents.minPoint ().y);

      //**********************************************
      // setup the view
      AcGsView *pView = mPreviewCtrl.view();	
      AcGePoint3d eye = boxCenter + viewDir;

      // upvector				
      pView->setView(eye, boxCenter, viewYDir, xMax, yMax);

      pView->add(pRec, mPreviewCtrl.model()); 

      pRec->close();
    }
  }

  return es;
}

//
bool GetActiveViewPortInfo (AcDbDatabase *pDb,ads_real &height, ads_real &width, AcGePoint3d &target, AcGeVector3d &viewDir, ads_real &viewTwist, bool getViewCenter)
{
  // make sure the active view port is uptodate
  acedVports2VportTableRecords();
  
  // get the working db
  //AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase(); 
  // if not ok
  if (pDb == NULL)
    return false;
  
  // 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
      height = pViewPortRec->height ();
      // get the width
      width = pViewPortRec->width ();
      // if the user wants the center of the viewport used
      if (getViewCenter == true)
      {
        struct resbuf rb;
        memset (&rb, 0, sizeof (struct resbuf));
        // get the system var VIEWCTR
        acedGetVar (_T("VIEWCTR"), &rb);
        // set that as the target
        target = AcGePoint3d (rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
      }
      // we want the viewports camera target setting
      else
      {
        // get the target of the view
        target = pViewPortRec->target ();
      }		
      
      // get the view direction
      viewDir = pViewPortRec->viewDirection ();
      // get the view twist of the viewport
      viewTwist = pViewPortRec->viewTwist ();
    }
    // close after use
    pVTable->close ();
    pViewPortRec->close();			
  }	
  
  return (true);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -