矩形根据某点进行缩放并以该点为中心
/**
* 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坐标的转换矩阵。
![](https://img.haomeiwen.com/i5872479/93f502cd9a49e68c.png)
参考:
![](https://img.haomeiwen.com/i5872479/de7383476e95f17a.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倍后,获得新矩形绿色。
![](https://img.haomeiwen.com/i5872479/9886a25d6da407ac.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;
};
网友评论