问题描述:
开发过程中想对图纸ZOOM缩放图纸到合适的视角是比较常见的需求,开发者第一能想到的是发送ZOOM命令进行缩放,
但是实际开发过程中往往效果不理想,比如说发送命令不稳定还有不是瞬发等问题。
介绍几种缩放视口的封装函数:
示例代码:
- C++
const int BIT1 = 0x01;
const int BIT2 = 0x02;
const int BIT4 = 0x04;
const int BIT8 = 0x08;
const int BIT10 = 0x10;
void zoom(ads_point wmin, ads_point wmax)
{
AcDbViewTableRecord view;
struct resbuf rb;
struct resbuf wcs, dcs, ccs; // acedTrans coord system flags
ads_point vpDir;
ads_point wdcsmax, wdcsmin; // windows corners in device coords
AcGeVector3d viewDir;
AcGePoint2d cenPt; ads_real lenslength,
viewtwist,
frontz,
backz; ads_point target; int viewmode,
tilemode,
cvport;
wcs.restype = RTSHORT; // WORLD coord system flag
wcs.resval.rint = 0;
ccs.restype = RTSHORT; // CURRENT coord system flag
ccs.resval.rint = 1;
dcs.restype = RTSHORT; // DEVICE coord system flag
dcs.resval.rint = 2; // Get the 'VPOINT' direction vector
acedGetVar(L"VIEWDIR", &rb); //VIEWDIR is reported in UCS
acedTrans(rb.resval.rpoint, &ccs, &wcs, 0, vpDir);
viewDir.set(vpDir[X], vpDir[Y], vpDir[Z]); // convert upper right window corner to DCS
acedTrans(wmax, &ccs, &dcs, 0, wdcsmax); // convert lower left window corner to DCS
acedTrans(wmin, &ccs, &dcs, 0, wdcsmin);
//calculate and set view center point
cenPt.set(wdcsmin[X] + ((wdcsmax[X] - wdcsmin[X]) / 2.0),
wdcsmin[Y] + ((wdcsmax[Y] - wdcsmin[Y]) / 2.0)
);
double width = wdcsmax[X] - wdcsmin[X];
double height = wdcsmax[Y] - wdcsmin[Y];
// 计算居中点(默认中心)
double centerX = wdcsmin[X] + width / 2.0;
double centerY = wdcsmin[Y] + height / 2.0;
cenPt.set(centerX, centerY);
view.setCenterPoint(cenPt); // set view height and width and direction
view.setHeight(fabs(wdcsmax[Y] - wdcsmin[Y]) + 5);
view.setWidth(fabs(wdcsmax[X] - wdcsmin[X]) + 5);
view.setViewDirection(viewDir); // get and set other properties
acedGetVar(L"LENSLENGTH", &rb);
lenslength = rb.resval.rreal;
view.setLensLength(lenslength); acedGetVar(L"VIEWTWIST", &rb);
viewtwist = rb.resval.rreal;
view.setViewTwist(viewtwist); acedGetVar(L"FRONTZ", &rb);
frontz = rb.resval.rreal; acedGetVar(L"BACKZ", &rb);
backz = rb.resval.rreal; acedGetVar(L"VIEWMODE", &rb);
viewmode = rb.resval.rint; view.setPerspectiveEnabled((viewmode & BIT1) == BIT1);
view.setFrontClipEnabled((viewmode & BIT2) == BIT2);
view.setBackClipEnabled((viewmode & BIT4) == BIT4);
view.setFrontClipAtEye((viewmode & BIT10) != BIT10); acedGetVar(L"TILEMODE", &rb);
tilemode = rb.resval.rint;
acedGetVar(L"CVPORT", &rb);
cvport = rb.resval.rint; // Paperspace flag
bool paperspace =
((tilemode == 0) && (cvport == 1)) ? true : false;
view.setIsPaperspaceView(paperspace); if (false == paperspace)
{
view.setFrontClipDistance(frontz);
view.setBackClipDistance(backz);
}
else
{
view.setFrontClipDistance(0.0);
view.setBackClipDistance(0.0);
}
acedGetVar(L"TARGET", &rb);
acedTrans(rb.resval.rpoint, &ccs, &wcs, 0, target);
view.setTarget(AcGePoint3d(target[X], target[Y], target[Z])); // update view
acedSetCurrentView(&view, NULL);
}
//简单的调用方法
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
AcGePoint3d ptMin = pDb->extmin();
AcGePoint3d ptMax = pDb->extmax();
ads_point wmin1, wmax1;
ads_point_set(asDblArray(ptMin), wmin1);
ads_point_set(asDblArray(ptMax), wmax1);
zoom(wmin1, wmax1);
2.NET:
static void Zoom(Point3d pMin, Point3d pMax, Point3d pCenter, double dFactor)
{
//获取当前文档及数据库
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
int nCurVport = System.Convert.ToInt32(Application.GetSystemVariable("CVPORT"));
// 没提供点或只提供了一个中心点时,获取当前空间的范围
// 检查当前空间是否为模型空间
if (acCurDb.TileMode == true)
{
if (pMin.Equals(new Point3d()) == true &&
pMax.Equals(new Point3d()) == true)
{
pMin = acCurDb.Extmin;
pMax = acCurDb.Extmax;
}
}
else
{
// 检查当前空间是否为图纸空间
if (nCurVport == 1)
{
// 获取图纸空间范围
if (pMin.Equals(new Point3d()) == true &&
pMax.Equals(new Point3d()) == true)
{
pMin = acCurDb.Pextmin;
pMax = acCurDb.Pextmax;
}
}
else
{
// 获取模型空间范围
if (pMin.Equals(new Point3d()) == true &&
pMax.Equals(new Point3d()) == true)
{
pMin = acCurDb.Extmin;
pMax = acCurDb.Extmax;
}
}
}
// 启动事务
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// 获取当前视图
using (ViewTableRecord acView = acDoc.Editor.GetCurrentView())
{
Extents3d eExtents;
// 将 WCS 坐标变换为 DCS 坐标
Matrix3d matWCS2DCS;
matWCS2DCS = Matrix3d.PlaneToWorld(acView.ViewDirection);
matWCS2DCS = Matrix3d.Displacement(acView.Target - Point3d.Origin) * matWCS2DCS;
matWCS2DCS = Matrix3d.Rotation(-acView.ViewTwist, acView.ViewDirection, acView.Target) * matWCS2DCS;
//如果指定了中心点,就为中心模式和比例模式
//设置显示范围的最小点和最大点;
if (pCenter.DistanceTo(Point3d.Origin) != 0)
{
pMin = new Point3d(pCenter.X - (acView.Width / 2),
pCenter.Y - (acView.Height / 2), 0);
pMax = new Point3d((acView.Width / 2) + pCenter.X,
(acView.Height / 2) + pCenter.Y, 0);
}
// 用直线创建范围对象;
using (Line acLine = new Line(pMin, pMax))
{
eExtents = new Extents3d(acLine.Bounds.Value.MinPoint,
acLine.Bounds.Value.MaxPoint);
}
// 计算当前视图的宽高比
double dViewRatio;
dViewRatio = (acView.Width / acView.Height);
// 变换视图范围
matWCS2DCS = matWCS2DCS.Inverse();
eExtents.TransformBy(matWCS2DCS);
double dWidth;
double dHeight;
Point2d pNewCentPt;
//检查是否提供了中心点(中心模式和比例模式)
if (pCenter.DistanceTo(Point3d.Origin) != 0)
{
dWidth = acView.Width;
dHeight = acView.Height;
if (dFactor == 0)
{
pCenter = pCenter.TransformBy(matWCS2DCS);
}
pNewCentPt = new Point2d(pCenter.X, pCenter.Y);
}
else // 窗口、范围和界限模式下
{
// 计算当前视图的宽高新值;
dWidth = eExtents.MaxPoint.X - eExtents.MinPoint.X;
dHeight = eExtents.MaxPoint.Y - eExtents.MinPoint.Y;
// 获取视图中心点
pNewCentPt = new Point2d(((eExtents.MaxPoint.X + eExtents.MinPoint.X) * 0.5), ((eExtents.MaxPoint.Y + eExtents.MinPoint.Y) * 0.5));
}
// 检查宽度新值是否适于当前窗口
if (dWidth > (dHeight * dViewRatio)) dHeight = dWidth / dViewRatio;
// 调整视图大小;
if (dFactor != 0)
{
acView.Height = dHeight * dFactor;
acView.Width = dWidth * dFactor;
}
// 设置视图中心;
acView.CenterPoint = pNewCentPt;
// 更新当前视图;
acDoc.Editor.SetCurrentView(acView);
}
// 提交更改;
acTrans.Commit();
}
}
| 英文空间链接 |
|---|
★★中望CAD二开发中如何实现ZOOM效果?:https://confluence.zwcad.com/pages/viewpage.action?pageId=299763522