坐标映射算法

2023-04-24  本文已影响0人  NullUser

矩形根据某点进行缩放并以该点为中心

    /**
     * Scale the rectangle around its center point.
     */
    void scale( double scaleFactor, const QgsPointXY *c = nullptr )
    {
      // scale from the center
      double centerX, centerY;
      if ( c )
      {
        centerX = c->x();
        centerY = c->y();
      }
      else
      {
        centerX = mXmin + width() / 2;
        centerY = mYmin + height() / 2;
      }
      scale( scaleFactor, centerX, centerY );
    }

    /**
     * Scale the rectangle around its center point.
     */
    void scale( double scaleFactor, double centerX, double centerY )
    {
      const double newWidth = width() * scaleFactor;
      const double newHeight = height() * scaleFactor;
      mXmin = centerX - newWidth / 2.0;
      mXmax = centerX + newWidth / 2.0;
      mYmin = centerY - newHeight / 2.0;
      mYmax = centerY + newHeight / 2.0;
    }

将矩形a完整放入矩形b,计算此时矩形a坐标映射到矩形b坐标的转换矩阵。

目前矩形b的minx和miny需要是0。
实现以下效果:A和B是任意矩形,将A通过等比例缩放后,完全放入B,计算此时从A坐标到B坐标的转换矩阵。

image.png

参考:


image.png
struct Rect 
{
    double minx;
    double maxx;
    double miny;
    double maxy;
};
/**
 * @brief 将矩形a完整放入矩形b,计算此时矩形a坐标映射到矩形b坐标的转换矩阵
 */
QMatrix calculateMatrix(Rect& a, Rect b)
{
    QMatrix matrix;


    double aWidth = a.maxx - a.minx;
    double aHeight = a.maxy - a.miny;
    //计算矩形a宽高比
    double aWHRatio = aWidth / aHeight;

    double bWidth = b.maxx - b.minx;
    double bHeight = b.maxy - b.miny;
    //计算矩形b宽高比
    double bWHRatio = bWidth / bHeight;

    //1.计算a到b的缩放,计算b/a
    double scale = 1;
    if (bWHRatio >= aWHRatio)
    {
        scale = bHeight / aHeight;
    }
    else
    {
        scale = bWidth / aWidth;
    }

    //2.计算偏移量,使a位于b的中心位置
    double aMidX = (a.maxx + a.minx) / 2;
    double bMidX = (b.maxx + b.minx) / 2;
    double xOffsetAfterScaled = (bMidX - aMidX * scale);

    double aMidY = (a.maxy + a.miny) / 2;
    double bMidY = (b.maxy + b.miny) / 2;
    double yOffsetAfterScaled = (bMidY - aMidY * scale);

    matrix.scale(scale, scale);
    matrix.translate(xOffsetAfterScaled / scale, yOffsetAfterScaled / scale);

    return matrix;
};

以矩形上某一点为锚点,缩放后,新矩形相对位置上仍为原坐标。

实现以下效果:将黄色矩形以其上某点(如:90,90)进行放大2倍后,获得新矩形绿色。


image.png
Rect scaleByPos(Rect rect, double scaleFactor, Point pos)
{
    Rect scaledRect;
    //假设窗口
    Rect window = rect;

    //窗口映射到矩形的转换矩阵
    QMatrix windowMatrix = calculateMatrix(window, rect);
    double originX, originY;
    windowMatrix.map(pos.x, pos.y, &originX, &originY);

    //原始中心点坐标
    double originCenterX, originCenterY;
    originCenterX = (rect.minx + rect.maxx) / 2;
    originCenterY = (rect.miny + rect.maxy) / 2;

    //计算缩放后的矩形宽高
    double newWidth = (rect.maxx - rect.minx) * scaleFactor;
    double newHeight = (rect.maxy - rect.miny) * scaleFactor;

    //计算以中心点进行缩放后的矩形
    Rect originCenterScaledRect = {
        originCenterX - newWidth / 2,
        originCenterX + newWidth / 2,
        originCenterY - newHeight / 2,
        originCenterY + newHeight / 2
    };

    //将新矩形放入窗口
    QMatrix tempMatrix = calculateMatrix(originCenterScaledRect, window);
    //获取窗口到新矩形的转换矩阵
    QMatrix matrix = tempMatrix.inverted();

    //计算锚点在新矩形中的坐标
    //即原始矩形坐标pos,放入新矩形originCenterScaledRect后的坐标
    double newX, newY;
    matrix.map(pos.x, pos.y, &newX, &newY);

    //计算偏移
    double centerX = originCenterX - (newX - originX);
    double centerY = originCenterY - (newY - originY);

    scaledRect = {
        centerX - newWidth / 2,
        centerX + newWidth / 2,
        centerY - newHeight / 2,
        centerY + newHeight / 2
    };

    return scaledRect;

};
上一篇 下一篇

猜你喜欢

热点阅读