Base R中自定义旋转箭头图形变形问题求助
Fixing Rotation Distortion in Custom Arrow Function
Let's break down why your arrow distorts when rotated, and fix it step by step:
The Root Causes
- Incorrect Rotation Matrix: Your current rotation matrix uses the wrong sign combination for 2D coordinate rotation, which skews the shape instead of rotating it cleanly.
- Off-Center Vertex Coordinates: The original arrow's vertices aren't centered at the origin
(0,0), so rotating it pivots around an offset point—causing extra distortion and misalignment.
Corrected Function
Here's the revised version of your my_arrow function with fixes for both issues:
my_arrow <- function(x, y, rotate = 0, col = par("fg"), cex = 1) { # Original arrow vertex coordinates xbase <- c(1.2, 0.2, 0.2, -1.2, -1.2, 0.2, 0.2) ybase <- c(0, 1, 0.5, 0.5, -0.5, -0.5, -1) # Step 1: Center the shape on the origin (fixes pivot point issue) x_center <- mean(xbase) xbase_centered <- xbase - x_center # Step 2: Use the standard 2D counter-clockwise rotation matrix theta <- rotate * pi / 180 rotM <- matrix(c(cos(theta), -sin(theta), sin(theta), cos(theta)), nrow = 2) # Step 3: Apply transformations in the correct order: scale → rotate → translate transf <- function(x1, y1) { scaled <- cex * c(x1, y1) rotated <- rotM %*% scaled rotated + c(x, y) } ans <- t(mapply(transf, xbase_centered, ybase)) polygon(x = ans[,1], y = ans[,2], col = col) }
Key Fixes Explained
- Centering the Shape: We calculate the mean of the original
xbasecoordinates and subtract it to shift the arrow's center to the origin. This ensures rotations pivot around the arrow's actual center, not an offset point. - Correct Rotation Matrix: The standard 2D rotation matrix uses
-sin(theta)in the top-right andsin(theta)in the bottom-left position. This preserves the shape's proportions during rotation, no matter the angle. - Transformation Order: Scaling first, then rotation, then translation to
(x,y)prevents unintended skewing that can happen if you reorder these steps.
Test the Fixed Function
Run this code to verify the rotation works without distortion:
plot(1:2, type="p", col="white", xlim=c(-5,5), ylim=c(-10,10)) # Draw arrows at different rotations to check consistency my_arrow(0, 0, rotate = 0, col = "red") my_arrow(2, 2, rotate = 45, col = "blue") my_arrow(-2, -2, rotate = 90, col = "green")
You’ll now see arrows that maintain their custom shape regardless of rotation angle, and they’re properly positioned at your specified (x,y) coordinates.
内容的提问来源于stack exchange,提问作者Karsten W.
相关产品推荐
相关产品推荐

