Image scaling geometry
This is very programming related but a somewhat non-programming question. I am performing image scaling in a web based application and I need to maintain my image relative to a fixed location even though it scales anchored by its top, left corner. Hope the graphic make this possible.
The idea is that C is a fixed location that I want to maintain as my scaling origin rather than B which which is the current css behavior. C may or may not be within the actual image. So as the image scale, B needs to move relative to C. Example: if the image was scaled 50%, then B would move 1/2 the distance to C. If the image grew to 200% of its size, then B would move twice the distance away from C.
Ultimately looking for a formula for x & y for B given the location of C and a scaling factor for the im开发者_如何学JAVAage. Not sure the size of the image needs to be part of this but I have it if needed.
Thanks for any help!
Things I know:
- I know the width and height of the image rectangle.
- I know the offset of B from A.
- I know the offset of C from A.
- I know the scale factor in percent of the image.
Effectively, you want to treat C as the origin, and just "move" B by the scaling amount. By treating it as a vector from C to B, and scaling it by the amount in question, you can do this fairly easily.
newBx = Cx - (Cx - Bx) * scale;
newBy = Cy - (Cy - By) * scale;
For example, with a scale of 0.5 (50%), this becomes:
newBx = 100 - (100 - 50) * 0.5
= 100 - 25
= 75 // 1/2 the distance to C
newBy = 100 - (100 - 25) * 0.5
= 100 - 37.5
= 62.5 // 1/2 the distance to C
With a scale of 2 (200%):
newBx = 100 - (100 - 50) * 2
= 100 - 100
= 0 // 2x the distance to C
newBy = 100 - (100 - 25) * 2
= 100 - 150
= -50 // 2x the distance to C
First you need to calculate the distance from B to C, then you just change that to scale, and that is where the new B is relative to C:
newB = C - (C - B) * scale
As you want the coordinates, it's the same function for x and y:
newBx = Cx - (Cx - Bx) * scale
newBy = Cy - (Cy - By) * scale
(The scale value used is not percentage but a size multiplier. An increase in size by 50% gives a scale of 1.5
.)
So you want point C
in the image which is currently at (C_x, C_y)
to remain at the same position after scaling the image by a factor of s
?
New position of C
, say, C_new = (s*C_x,s*C_y)
.
And you want to move the image so that C_new = C
.
Which means you'll have to shift B = (B_x,B_y)
by (s*C_x-C_x,s*C_y-C_y)
, or the new origin of the image, say B_new
is:
B_new = (B_x + s*C_x-C_x, B_y + s*C_y-C_y)
So now you can display the scaled image at B_new
--- and C
should remain fixed.
If I understand the problem:
X(b) = X(c) - Width*(1/3)
Y(b) = Y(c) - Height*(3/4)
The formula seems simple enough, but your sample image can't get any larger than 133x200 (scale = 133%) before it overruns Y=0 (which I assume is your northern limit).
If you want to stop it from moving past Y=0 or X=0, and push-out further to the south and east once it reaches either limit, one approach might be:
IIF(Height > 133, Y(b) = 0, Y(b) = Y(c) - Height*(3/4))
IIF(Width > 450, X(b) = 0, X(b) = X(c) - Width*(1/3))
I think scale should be converted to height and width, instead of using scale as a variable in these formulas, since your original image could be any size (assuming they're not always going to be 100x150 per your sample)
- dave
here's a C# snippet that is tested to work:
void Main()
{
Application.Run(new form1());
}
public class form1 : Form
{
static Point C = new Point(100,100);
static Point origLocB = new Point(50,25);
static Size origSizeB = new Size(150,100);
Panel Rec = new Panel()
{
Left = origLocB.X,
Top = origLocB.Y,
Width = origSizeB.Width,
Height = origSizeB.Height,
BorderStyle = BorderStyle.FixedSingle,
};
NumericUpDown nud = new NumericUpDown()
{
Value = 1M,
Increment = .01M,
DecimalPlaces = 2,
Dock = DockStyle.Bottom,
};
public form1()
{
nud.ValueChanged += NumericUpDown_ValueChanged;
Controls.Add(nud);
Controls.Add(Rec);
}
public void NumericUpDown_ValueChanged(object sender, EventArgs e)
{
Rec.Location = new Point(((int)((origLocB.X - C.X) * nud.Value + C.X)),
((int)((origLocB.Y - C.Y) * nud.Value + C.Y)));
Rec.Size = new Size((int)(origSizeB.Width*nud.Value),
(int)(origSizeB.Height*nud.Value));
}
}
it really just echo's @Reed's Answer
精彩评论