Setting the View Center in an external DWG file with ObjectARX or RealDWG in C++

by Fenton Webb

In raw AutoCAD setting the View center is really easy, just set the VIEWCTR sysvar using acedSetVar(“VIEWCTR”). If you want to set the View center in a DWG file that is not loaded into the AutoCAD editor, it takes a little more work.

Here’s how you do it…

#include "dbents.h"

#include "dbobjptr2.h"  // include the smart pointer template

 

static void Wcs2Dcs(AcDbViewportTableRecord *pVp, AcGeMatrix3d &resultMat);

// set the viewctr outside of the AutoCAD Editor

// by Fenton Webb, DevTech, Autodesk 01/06/2012

void setViewCenter()

{

  // open some dwg file

  AcDbDatabase *dwg = new AcDbDatabase(false, true);

  if (dwg->readDwgFile(_T("c:\\temp\\fenton.dwg")) == Acad::eOk)

  {

    // read in the whole file, don’t cache

    dwg->closeInput();

 

    // start by getting the viewport table id

    AcDbObjectId id = dwg->viewportTableId();

    {

      AcDbSmartObjectPointer<AcDbViewportTable> pVt (id, AcDb::kForRead);

      // if ok

      if (pVt.openStatus() == Acad::eOk)

      {

        AcDbObjectId vpId;   

        // get the active viewport

        pVt->getAt(_T("*Active"), vpId);   

        // and open for write

        AcDbViewportTableRecordPointer pOldVTR(vpId, AcDb::kForWrite);   

        // if ok

        if (pOldVTR.openStatus() == Acad::eOk)

        {

          AcGeMatrix3d wcs2dcs;   

          AcGePoint3d newCenter(100,100,0);       

          Wcs2Dcs(pOldVTR.object(), wcs2dcs);   

          newCenter = wcs2dcs*newCenter;   

          // gives position of new pt in DCS wrt view center

          AcGePoint2d oldCenter = pOldVTR->centerPoint();   

 

          pOldVTR->setCenterPoint(

                        AcGePoint2d(newCenter[X]+oldCenter[X],

     &#16
0;                             
newCenter[Y]+oldCenter[Y]));                                   

          // just set the view direction to show that also…

          pOldVTR->setViewDirection(AcGeVector3d(-1,-1,1));   

        }

      }

    }

 

    // save the changes

    Acad::ErrorStatus es = dwg->saveAs(_T("c:\\temp\\fenton2.dwg"));

  }

}

 

/////////////////////////////////////////////////////////////////

void Wcs2Dcs(AcDbViewportTableRecord *pVp, AcGeMatrix3d &resultMat)

{   

  // first get all the data   

  AcGeVector3d viewDirection = pVp->viewDirection();   

  AcGePoint2d centre2d = pVp->centerPoint();   

  AcGePoint3d viewCenter = AcGePoint3d( centre2d.x, centre2d.y, 0);       

  AcGePoint3d viewTarget = pVp->target ();    

  double twistAngle = –pVp->viewTwist();&#160
;   

  double height = pVp->height();   

  double width = pVp->width();   

  double lensLength = pVp->lensLength();

 

  // prepare the transformation   

  AcGeVector3d xAxis, yAxis, zAxis;   

  zAxis = viewDirection.normal();   

  xAxis = AcGeVector3d::kZAxis.crossProduct( viewDirection );       

  if( !xAxis.isZeroLength() )

  {       

    xAxis.normalize();       

    yAxis = zAxis.crossProduct( xAxis );   

  }

  else if( zAxis.z < 0 )

  {       

    xAxis = –AcGeVector3d::kXAxis;       

    yAxis = AcGeVector3d::kYAxis;       

    zAxis = –AcGeVector3d::kZAxis;   

  }

  else

  {       

    xAxis = AcGeVector3d::kXAxis;       

    yAxis = AcGeVector3d::kYAxis;       

    zAxis = AcGeVector3d::kZAxis;   

  }       

 

  AcGeMatrix3d dcs2wcs;   

  // display coordinate system (DCS) to world coordinate system (WCS)      

  // then adjust to the viewCenter   

  dcs2wcs = AcGeMatrix3d::translation( viewCenterAcGePoint3d::kOrigin);       

  // Then transform for the view direction   

  AcGeMatrix3d matCoords;   

  matCoords.setCoordSystem( AcGePoint3d::kOrigin, xAxis, yAxis, zAxis);       

  dcs2wcs = matCoords * dcs2wcs;       

  // Then adjust for the viewTarget   

  dcs2wcs = AcGeMatrix3d::translation( viewTargetAcGePoint3d::kOrigin) * dcs2wcs;       

  // Then the twist angle   

  dcs2wcs = AcGeMatrix3d::rotation(twistAngle, zAxis, viewTarget ) * dcs2wcs;       

  AcGeMatrix3d perspMat;  

  if( pVp->perspectiveEnabled())

  {       

    // we do special perspective handling      

    double viewSize = height;          

    double aspectRatio = width / height;              

    double adjustFactor = 1.0 / 42.0;       

    double adjustedLensLength = viewSize * lensLength * sqrt ( 1.0 + aspectRatio * aspectRatio ) * adjustFactor;               

    double eyeDistance = viewDirection.length();       

    double lensDistance = eyeDistanceadjustedLensLength;                       

    double ed = eyeDistance;      

    double ll = adjustedLensLength;      

    double l = lensDistance;               

    perspMat.entry[2][2] = (lll ) / ll;      

    perspMat.entry[2][3] = l * ( edll ) / ll;      

    perspMat.entry[3][2] = -1.0 / ll;      

    perspMat.entry[3][3] = ed / ll;  

  }  

 

  resultMat = perspMat * dcs2wcs.inverse();

}

 


Comments

One response to “Setting the View Center in an external DWG file with ObjectARX or RealDWG in C++”

  1. nizar akel Avatar
    nizar akel

    hi all
    i need to open external dwg file and i need to do zoom extents then close it. all this should be done silintly while working on another dwg drawing
    thanks alot
    nizar

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading