Тема: Как преобразовать WCS в DCS для Viewport'а с включенной перспективой

Помогите, пожалуйста, разобраться!

Есть ViewPort в Пространстве листа с включенной перспективой, мне нужно выполнить для этого вьюпорта  преобразование WCS->DCS (т.е. найти точку объекта, расположенного в пространстве модели, в координатах на листе, с учетом перспективы)

Я могу, например, получить ID вьюпорта с помощью функции acedGetCurViewportObjectId(), но я не знаю как преобразовать координаты WCS->DCS с учетом перспективы, у класса  AcDbViewport нет метода, подобного методу AcGiViewport::doPerspective(). А получить класс AcGiViewport из AcDbViewport по-моему нельзя, т.к. AcGiViewport  используется для отрисовки пользовательских объектов.

(Наверное, нужные данные хранятся в XDATA у вьюпорта, но как их использовать и вообще можно ли по ним вычислить координаты на листе?)

Заранее спасибо.

Re: Как преобразовать WCS в DCS для Viewport'а с включенной перспективой

Не мое, но может поможет:

void ms2ps( AcDbViewport*pVp, AcGeMatrix3d &resultMat) 
{
    AcGeVector3d viewDirection = pVp->viewDirection();
    AcGePoint2d centre2d = pVp->viewCenter();
    AcGePoint3d viewCenter = AcGePoint3d( centre2d.x, centre2d.y, 0);
    AcGePoint3d viewTarget = pVp->viewTarget (); 
    double twistAngle = -pVp->twistAngle(); 
    AcGePoint3d centerPoint = pVp->centerPoint(); 
    double viewHeight = pVp->viewHeight();
    double height = pVp->height();
    double width = pVp->width();
    double scaling = viewHeight / height;
    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)
    AcGeMatrix3d ps2Dcs; // paperspace to DCS
    // First initialise with a transformation to centerPoint
    ps2Dcs = AcGeMatrix3d::translation( AcGePoint3d::kOrigin - centerPoint);
    // then scale for the view
    ps2Dcs = ps2Dcs * AcGeMatrix3d::scaling( scaling, centerPoint); 
    // then adjust to the viewCenter
    dcs2wcs = AcGeMatrix3d::translation( viewCenter - AcGePoint3d::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( viewTarget - AcGePoint3d::kOrigin) * dcs2wcs;
    // Then the twist angle
    dcs2wcs = AcGeMatrix3d::rotation(twistAngle, zAxis, viewTarget ) *dcs2wcs;

    AcGeMatrix3d perspMat;
    if ( pVp->isPerspectiveOn() ) 
    {
        // we do special perspective handling
        double viewSize = viewHeight; 
        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 = eyeDistance - adjustedLensLength;
        double ed = eyeDistance;
        double ll = adjustedLensLength;
        double l = lensDistance;
        perspMat.entry[2][2] = (ll - l ) / ll;
        perspMat.entry[2][3] = l * ( ed - ll ) / ll;
        perspMat.entry[3][2] = -1.0 / ll;
        perspMat.entry[3][3] = ed / ll; 
    }
    resultMat = ps2Dcs.inverse() * perspMat * dcs2wcs.inverse();
}

Re: Как преобразовать WCS в DCS для Viewport'а с включенной перспективой

edan76,
Большое спасибо! Именно то, что нужно!