Click here to Skip to main content
15,901,001 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, What is the preferred method for zooming and panning on the graphics screen in a 2D C++ program?

I was reading my old linear algebra book and I was thinking a simple scaling and translation matrix could accomplish this. But how does a real CAD program like AutoCAD or Orcad accomplish such a task?

I realize scaling and translation matrices are intend for modifying points/vertices but are they also used for Zooming and panning? Can someone get me started on the correct approach to such a problem? I don't want to use a DX or OpenGL. I will just be drawing with WinAPI and the raw pixel and line drawing functions

Thanks in advance

This seems like a reasonable starting-point for further investigation. /free-cad/code/ci/master/tree/src/Gui/GLPainter.cpp

I realize you're not after an openGL implementation, but at the end of the day - it really only boils down to what performs the calculations - you or your gpu. There's nothing to stop you re-implementing their approach in such a manner that allows you to handle a different method of output- i.e software rather than hardware.

I'd just use matrices to transform from model-space to viewport-space, perform any simple culling where the entire line segment was off-screen, followed by letting the GDI subsystem handle clipping of partially not-visible lines. Given the added complexity required to implementing culling, I'd just skip this step for now and try throwing the whole lot at GDI (or GDI+).
Share this answer
The best way to do it is implementing some vector graphics. You can do it from scratch. In this case, your zoom won't show any pixellation, will be rendered from the model directly on screen. The idea is to handle the Windows message WM_PAINT where you render the graphics each time it is requested. Windows messages system has special provision to optimize pumping of this specific message. For example, if you invalidate some region before all messages are handler, only the last message is handler, and all invalidation are ORed together.

That said, the system does not store the graphics you output. This is the example of inversion of control, when you supply a handler which is called when the graphics is requested to be re-drawn, fully or partially. This mechanism is called invalidation. Therefore, you have to store some data in your code, and this data should be the data structure representing your vector graphics: collections of data objects representing lines, rectangles, ellipses, colors, and so on. You develop one universal method drawing all this data on some graphic context object.

Please see:[^],[^],
see also:[^].

When your model is changed in some part, use one of invalidation functions:[^],[^].

Now, what is that change? It could be logical change, such as adding, removing or transforming some of those objects of your model. Another class of changing is the "point of view": zoom level, pan parameters, I would even add rotations, and even more: set of layers to show or to hide. All these changes require appropriate invalidation, but "point of view" changes require full invalidation of all scene (window of your rendering control).

So, you have to have two levels of the model: "semantic", "logical" — graphics itself, and "point of view" data: current zoom level, angle, and so on. Change anything and then invalidate whatever you have to. That will lead to the call of your WM_PAINT handler, which is universal, renders all your graphics with all the parameters.

See also my past answer: MFC Drawed lines is disappeared[^].
(Please see it even if you are not planning to use MFC.)

Share this answer

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900