问题描述: 

开发过程中想对图纸ZOOM缩放图纸到合适的视角是比较常见的需求,开发者第一能想到的是发送ZOOM命令进行缩放,

但是实际开发过程中往往效果不理想,比如说发送命令不稳定还有不是瞬发等问题。


介绍几种缩放视口的封装函数:

示例代码:

  1. 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

  • No labels