Fivestar - 1 year ago 120
C# Question

# Zooming in and out calculation

So I am attempting to create a little graph that I will allow the user to add random lines etc as a learning project. The most frustrating part is figuring out how to get the zooming in/out to work - I have my ZoomScale variable bound to the mouse wheel and it "works" but I would like to be able to label the axis depending on how much they are zoomed and calculate the distance measurement of it (meters, cm, etc, because I have a MM per Pixel variable as well so we should be able to calculate this) so it needs to be more of an exact science than just "it works"

``````double X1 = ((actualline[i].X1 + actualWidth - VisibleXMax - VisibleXMin) * ZoomScale); //Calculate modified coordinates based on
double X2 = ((actualline[i].X2 + actualWidth - VisibleXMax - VisibleXMin) * ZoomScale); //  window width, window height, Visible X/Y, and Zoom.
double Y1 = ((actualline[i].Y1 + actualHeight - VisibleYMax - VisibleYMin) * ZoomScale);
double Y2 = ((actualline[i].Y2 + actualHeight - VisibleYMax - VisibleYMin) * ZoomScale);
``````

Instead of trying to work with that let's try with a simple 1 dimensional equation and I can re write that for x and y.

So lets say we have a 5 unit wide line in the x direction

``````. . . . .
``````

Currently that fills up our entire screen (well the window actually). From 0 to 5 all the way across. Now the user scrolls in to zoom into the first 3 units. Now those 3 units should fill up the entire window since the user is zoomed into it. It SHOULD look like this across the window

``````. . .
``````

So originially the line was x1 = 0, x2 = 5. 0 to 5. And since our window is 5 units wide it fills up the window. Now the user wants to only see units x1 = 0 to x2 = 3. 0 to 3. But we want these units to stretch across the window, so with some sort of zoom calculation (like above) we want to turn 0,3 into 0,5 using the available variables. The variables being:

Window Width (5 units in this case)

Original X1 and X2 (0 and 5 in this case)

Visible X min and max (0 and 3 in this case)

And a zoom scale which is 1 and increments be 0.05 each time you scroll up.

Any suggestions?

Here is how I do mine. Follow the comments and let me know if you have any questions:

``````public void ZoomImage(int ScrollDelta)
{

OldUnitInPixels = UnitInPixels; // UnitInPixels is something similar to what you called mm/pixel - we need to keep the old one

if (ScrollDelta > 0) // this `if` means zoom in - the `else` means zoom out
{
if (ZoomLevel != 20) // to control my maximum zoom in (I want 20 zoom levels only)
{
ZoomLevel++; // increment zoom level

UnitInPixels += initialUnitInPixels; // I add certain value when I zoom in - for ex: initially it was 3 mm per pix, on zoom in it would be 4 mm  per pixel
dotSize++; // I want some points to increase in size a little bit
lineSize += 0.1; // I want some liness to increase in size a little bit

for (var i = 0; i < DisplayedCoords.Count; i++)
{
DisplayedCoords[i].X -= XCoordOffset; // remove value of what you called VisibleX from current x value - means go back to the very original coord - ex: actual value is (1,1) but I added (49, 49) for it so it looks (50,50) better on the screen. So I want to remove whatever I added which is (49,49)
DisplayedCoords[i].Y -= YCoordOffset; // remove value of what you called VisibleY from current Y value

DisplayedCoords[i].X /= OldUnitInPixels; // divide by old
DisplayedCoords[i].Y /= OldUnitInPixels;

DisplayedCoords[i].X *= UnitInPixels; // multiply by new
DisplayedCoords[i].Y *= UnitInPixels;

DisplayedCoords[i].X += XCoordOffset; // add back whatever we removed earlier. So it looks back again "better"
DisplayedCoords[i].Y += YCoordOffset;
}
DrawImage(); // draw
}
}
else
{
// else is super similar but instead of all the (++)s I do (--)s
}
}
``````

See it working: (zoom in/out from/on mouse position was not finished)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download